This commit isolates preimages of forwarded htlcs from invoice
preimages. The reason to do this is to prevent the incoming contest
resolver from settling exit hop htlcs for which the invoice isn't marked
as settled.
The former tryApplyPreimage function silently ignored invalid preimages.
This could mask potential bugs. This commit makes the logic stricter and
generates an error in case an unexpected mismatch occurs.
New behaviour of the chain notifier to always send the current block
immediately after registration takes away the need to make a separate
GetBestBlock call on ChainIO.
Now that the success resolver preimage field is always populated by the
incoming contest resolver, preimage lookups earlier in the
process (channel and channel arbitrator) can mostly be removed.
One of the first things the incoming contest resolver does is checking
if the preimage is available and if it is, convert itself into a success
resolver.
This behaviour makes it unnecessary to already determine earlier in the
process whether an incoming contest or a success resolver is needed.
By having all incoming htlcs go through the incoming contest resolver,
the number of execution paths is reduced and it becomes easier to
ascertain that the implemented logic is correct.
The only functional change in this commit is that a forwarded htlc for
which is the preimage is known, is no longer settled when the htlc is
already expired. Previously a success resolver would be instantiated
directly, skipping the expiry height check.
This created a risk that the success resolver would never finish,
because an expired htlc could already have been swept by the remote
party and there is no detection of this remote spend in the success
resolver currently.
With the new change, the general direction that an expired htlc
shouldn't be settled and instead given up on is implemented more
consistently.
This commit prepares for fixing edges cases related to hodl
invoice on-chain resolution.
In this commit, we modify the way we detect local force closes. Before
this commit, we would directly check the broadcast commitment's txid
against what we know to be our best local commitment. In the case of DLP
recovery from an SCB, it's possible that the user force closed, _then_
attempted to recover their channels. As a result, we need to check the
outputs directly in order to also handle this rare, but
possible recovery scenario.
The new detection method uses the outputs to detect if it's a local
commitment or not. Based on the state number, we'll re-derive the
expected scripts, and check to see if they're on the commitment. If not,
then we know it's a remote force close. A new test has been added to
exercise this new behavior, ensuring we catch local closes where we have
and don't have a direct output.
In this commit, we speed up the `TestChainWatcherDataLossProtect`
_considerably_ by enumerating relevant tests using table driven tests
rather than generating random tests via the `testing/quick` package.
Each of these test cases are also run in parallel bringing down the
execution time of this test from a few minutes, to a few seconds.
This commit adds logging of the reason to go to chain for a channel.
This can help users to find out the reason why a channels forced closed.
To get all go to chain reasons, an optimization to break early is
removed. This optimization was not significant, because the normal flow
already examined all htlcs. In the exceptional case where we need to go
to chain, it does not weigh up against logging all go to chain reasons.
This commits exposes the various parameters around going to chain and
accepting htlcs in a clear way.
In addition to this, it reverts those parameters to what they were
before the merge of commit d1076271456bdab1625ea6b52b93ca3e1bd9aed9.
In this commit, we modify the `closeObserver` to fast path the DLP
dispatch case if we detect that the channel has been restored. We do
this as otherwise, we may inadvertently enter one of the other cases
erroneously, causing us to now properly look up their dlp commitment
point.
In this commit, we modify the main `closeObserver` dispatch loop to only
look for the local force close if we didn't recover the channel. We do
this, as for a recovered channel, it isn't possible for us to force
close from a recovered channel.
The multiplier doesn't make sense because funds may be equally at risk
by failing to broadcast to chain regardless of whether the HTLC is a
redeem or a timeout.
In this commit, we simplify the existing `htlcTImeoutResolver` with some
newly refactored out methods from the `htlcTimeoutContestResolver`. The
resulting logic is easier to follow as it's more linear, and only deals
with spend notifications rather than both spend _and_ confirmation
notifications.
This commit modifies the invoice registry to handle invoices for which
the preimage is not known yet (hodl invoices). In that case, the
resolution channel passed in from links and resolvers is stored until we
either learn the preimage or want to cancel the htlc.
This commit detaches signaling the invoice registry that an htlc was
locked in from the actually settling of the htlc.
It is a preparation for hodl invoices.
Previously a function pointer was passed to chain arbitrator to avoid a
circular dependency. Now that the routetypes package exists, we can pass
the full invoice registry to chain arbitrator.
This is a preparation to be able to use other invoice registry methods
in contract resolvers.
In this commit, we address a lingering issue within some subsystems that
are responsible for broadcasting transactions. Previously,
ErrDoubleSpend indicated that a transaction was already included in the
mempool/chain. This error was then modified to actually be returned for
conflicting transactions, but its callers were not modified accordingly.
This would lead to conflicting transactions to be interpreted as valid,
when they shouldn't be.
In this commit, we fix an off-by-one error when handling force closes
from the remote party. Before this commit, if the remote party
broadcasts state 2, and we were on state 1, then we wouldn't act at all.
This is due to an extraneous +1 in the comparison, causing us to only
detect this DLP case if the remote party's state is two beyond what we
know atm. Before this commit, the test added in the prior commit failed.
In this commit, we add a new test case to exercise the way we handle the
DLP detection and dispatch within the chain watcher. Briefly, we use
the `testing/quick` package to ensure that the following invariant is
always held: "if we do N state updates, then state M is broadcast, iff M
> N, we'll execute the DLP protocol". We limit the number of iterations
to 10 for now, as the tests can take a bit of time to execute, since it
actually does proper state transitions.
In this commit, we abstract the call to `GetStateNumHint` within the
`closeObserver` method to a function closure in the primary config. This
allows us to feed in an arbitrary broadcast state number within unit
tests.
In this commit, we ensure that we mark the channel as borked before we
remove the link during the force close process. This ensures that if the
peer reconnects right after we remove the link, then it won't be loaded
into memory in `loadActiveChannels`. We'll now:
* mark the channel as borked
* remove the link
* read the channel state from disk
* force close
This ensures that the link (if it's active) is able to commit any
pending changes to disk before we read out the channel to force close.
In this commit, we modify the WitnessCache's
AddPreimage method to accept a variadic number
of preimages. This enables callers to batch
preimage writes in performance critical areas
of the codebase, e.g. the htlcswitch.
Additionally, we lift the computation of the
witnesses' keys outside of the db transaction.
This saves us from having to do hashing inside
and blocking other callers, and limits extraneous
blocking at the call site.
Now that the sweeper is available, it isn't necessary anymore for the
commit resolver to craft its own sweep tx. Instead it can offer its
input to the sweeper and wait for the outcome.
Previously the arbitrator wasn't advanced to the final stage after
the last contract resolved.
Also channel arbitrator now does not ignore a log error anymore
unresolved contracts cannot be retrieved.
This commit is a step to split the lnwallet package. It puts the Input
interface and implementations in a separate package along with all their
dependencies from lnwallet.
In this commit, we modify areas where we need to force close a channel
to use the new FetchChannel method instead of manually scanning. This
dramatically reduces the CPU usage when doing things like closing a
large number of channels within lnd.
In this commit, we extend the htlcSuccessResolver to settle the invoice,
if any, of the corresponding on-chain HTLC sweep. This ensures that the
invoice state is consistent as when claiming the HTLC "off-chain".
Previously, contract resolvers that needed to publish a second level tx,
did not have access to the original htlc amount.
This commit reconstructs this amount from data that is already persisted
in arbitrator log.
Co-authored-by: Joost Jager <joost.jager@gmail.com>