Replace a constant three retry attempts for BOLT 12 invoice payments
with a retry strategy specified when creating a pending outbound
payment. This is configured by users in a later commit when constructing
an InvoiceRequest or a Refund.
An upcoming commit requires serializing Retry, so use a type with a
fixed byte length. Otherwise, using eight bytes to serialize a usize
would fail to read on 32-bit machines.
Add a send_payment_for_bolt12_invoice method to OutboundPayments for
initiating payment of a BOLT 12 invoice. This will be called from an
OffersMessageHandler, after which any retries are handled using the
Retryable logic.
Consolidate the creation and insertion of onion_session_privs to the
PendingOutboundPayment::Retryable arm. In an upcoming commit, this
method will be reused for an initial BOLT 12 invoice payment. However,
onion_session_privs are created using a different helper.
When a BOLT 12 invoice has been received, a payment attempt is made and
any errors result in abandoning the PendingOutboundPayment. This results
in generating at PaymentFailed event, which has a PaymentHash. Thus,
when receiving an invoice, transition from AwaitingInvoice to a new
InvoiceReceived state, the latter of which contains a PaymentHash such
the abandon_payment helper can still be used.
When a BOLT 12 invoice has been requested, in order to guarantee
invoice payment idempotency the future payment needs to be tracked. Add
an AwaitingInvoice variant to PendingOutboundPayment such that only
requested invoices are paid only once. Timeout after a few timer ticks
if a request has not been received.
When an invoice is requested but either receives an error or never
receives a response, surface an event to indicate to the user that the
corresponding future payment has failed.
When receiving a BOLT 12 invoice originating from either an invoice
request or a refund, the invoice should only be paid once. To accomplish
this, require that the invoice includes an encrypted payment id in the
payer metadata. This allows ChannelManager to track a payment when
requesting but prior to receiving the invoice. Thus, it can determine if
the invoice has already been paid.
Metadata such as the PaymentId should be encrypted when included in an
InvoiceRequest or a Refund, as it is user data and is exposed to the
payment recipient. Add an encryption key to ExpandedKey for this purpose
instead of reusing offers_base_key.
Releasing write locks in between monitor updates
requires storing a set of cloned keys to iterate
over. For efficiency purposes, that set of keys
is an actual set, as opposed to array, which means
that the iteration order may not be consistent.
The test was relying on an event array index to
access the revocation transaction. We change that
to accessing a hash map keyed by the txid, fixing
the test.
- Split Score from LockableScore to ScoreLookUp to handle read
operations and ScoreUpdate to handle write operations
- Change all struct that implemented Score to implement ScoreLookUp
and/or ScoreUpdate
- Change Mutex's to RwLocks to allow multiple data readers
- Change LockableScore to Deref in ScorerAccountingForInFlightHtlcs
as we only need to read
- Add ScoreLookUp and ScoreUpdate docs
- Remove reference(&'a) and Sized from Score in ScorerAccountingForInFlightHtlcs
as Score implements Deref
- Split MultiThreadedScoreLock into MultiThreadedScoreLockWrite and MultiThreadedScoreLockRead.
After splitting LockableScore, we split MultiThreadedScoreLock following
the same way, splitting a single score into two srtucts, one for read and
other for write.
MultiThreadedScoreLock is used in c_bindings.
Because a `UtxoLookup` implementation is likely to need a reference
to the `PeerManager` which contains a reference to the
`P2PGossipSync`, it is likely to be impossible to get a mutable
reference to the `P2PGossipSync` by the time we want to add a
`UtxoLookup` without a ton of boilerplate and trait wrapping.
Instead, we simply place the `UtxoLookup` in a `RwLock`, allowing
us to modify it without a mutable self reference.
The lifetime bounds updates in tests required in this commit are
entirely unclear to me, but do allow tests to continue building, so
somehow make rustc happier.
Here we implement `WatchtowerPersister`, which provides a test-only
sample implementation of `Persist` similar to how we might imagine a
user to build watchtower-like functionality in the persistence pipeline.
We test that the `WatchtowerPersister` is able to successfully build and
sign a valid justice transaction that sweeps a counterparty's funds if
they broadcast an old commitment.
For watchtowers to be able to build justice transactions for our
counterparty's revoked commitments, they need to be able to find the
revokeable output for them to sweep. Here we cache `to_self_delay` in
`CommitmentTransaction` to allow for finding this output on the struct
directly. We also add a simple helper method to aid in building the
initial spending transaction.
This also adds a unit test for both of these helpers, and
refactors a bit of a previous `CommitmentTransaction` unit test to make
adding these easier.
Upon creating a channel monitor, it is provided with the initial
counterparty commitment transaction info directly before the very first
time it is persisted. Because of this, the very first counterparty
commitment is not seen as an update in the persistence pipeline, and so
our previous changes to the monitor and updates cannot be used to
reconstruct this commitment.
To be able to expose the counterparty's transaction for the very first
commitment, we add a thin wrapper around
`provide_latest_counterparty_commitment_tx`, that stores the necessary
data needed to reconstruct the initial commitment transaction in the
monitor.
Currently, when we receive an HTLC claim from a peer, we first hash
the preimage they gave us before removing the HTLC, then
immediately pass the preimage to the inbound channel and hash the
preimage again before removing the HTLC and sending our peer an
`update_fulfill_htlc`. This second hash is actually only asserted
on, never used in any meaningful way as we have the htlc data
present in the same code.
Here we simply drop this second hash and move it into a
`debug_assert`.
If a user has issues with a payment, the most obvious thing they'll
do is check logs for the payment hash. Thus, we should ensure our
logs that show a payment's lifecycle include the payment hash and
are emitted (a) as soon as LDK learns of the payment, (b) once the
payment goes out to the peer (which is already reasonably covered
in the commitment transaction building logs) and (c) when the
payment ultimately is fulfilled or fails.
Here we improve our logs for both (a) and (c).
This adds the feerate and local and remote output values to this channel
monitor update step so that a monitor can reconstruct the counterparty's
commitment transaction from an update. These commitment transactions
will be exposed to users in the following commits to support third-party
watchtowers in the persistence pipeline.
With only the HTLC outputs currently available in the monitor update, we
can tell how much of the channel balance is in-flight and towards which
side, however it doesn't tell us the amount that resides on either side.
Because of dust, we can't reliably derive the remote value from the
local value and visa versa. Thus, it seems these are the minimum fields
that need to be added.