Jeffrey Czyz [Fri, 16 Dec 2022 19:35:50 +0000 (13:35 -0600)]
Use explicit WithoutLength for BOLT 12 features
Most BOLT 12 features are used as the value of a TLV record and thus
don't use an explicit length. One exception is the features inside the
blinded payinfo subtype since the TLV record contains a list of them.
However, these features are also used in the BOLT 4 encrypted_data_tlv
TLV stream as a single record, where the length is implicit.
Implement Readable and Writeable for Features wrapped in WithoutLength
such that either serialization can be used where required.
Jeffrey Czyz [Tue, 29 Nov 2022 23:30:56 +0000 (18:30 -0500)]
Builder for creating refunds
Add a builder for creating refunds given a payer_id and other required
fields. Other settings are optional and duplicative settings will
override previous settings. Building produces a semantically valid
`invoice_request` message representing the refund, which then may be
communicated out of band (e.g., via QR code).
Define an interface for BOLT 12 refunds (i.e., an `invoice_request`
message without an `offer_node_id`). A refund is more generally an
"offer for money". While it is encoded using the same TLV streams as an
`invoice_request` message, it has different semantics.
Jeffrey Czyz [Mon, 28 Nov 2022 16:20:07 +0000 (11:20 -0500)]
Add BOLT 12 merkle root test for `invoice_request`
A BOLT 12 test vector uses an `invoice_request` message that has a
currency, which aren't supported, so using OfferBuilder::build_unchecked
is required to avoid a panic.
Jeffrey Czyz [Wed, 31 Aug 2022 15:19:44 +0000 (10:19 -0500)]
Builder for creating invoice requests
Add a builder for creating invoice requests for an offer given a
payer_id. Other settings may be optional depending on the offer and
duplicative settings will override previous settings. Building produces
a semantically valid `invoice_request` message for the offer, which then
can be signed for the payer_id.
Jeffrey Czyz [Tue, 23 Aug 2022 22:31:46 +0000 (17:31 -0500)]
Invoice request raw byte encoding and decoding
When reading an offer, an `invoice_request` message is sent over the
wire. Implement Writeable for encoding the message and TryFrom for
decoding it by defining in terms of TLV streams. These streams represent
content for the payer metadata (0), reflected `offer` (1-79),
`invoice_request` (80-159), and signature (240).
Jeffrey Czyz [Tue, 9 Aug 2022 22:37:02 +0000 (17:37 -0500)]
Merkle root hash computation
Offers uses a merkle root hash construction for signature calculation
and verification. Add a submodule implementing this so that it can be
used when parsing and signing invoice_request and invoice messages.
Define an interface for BOLT 12 `invoice_request` messages. The
underlying format consists of the original bytes and the parsed
contents.
The bytes are later needed when constructing an `invoice` message. This
is because it must mirror all the `offer` and `invoice_request` TLV
records, including unknown ones, which aren't represented in the
contents.
The contents will be used in `invoice` messages to avoid duplication.
Some fields while required in a typical user-pays-merchant flow may not
be necessary in the merchant-pays-user flow (e.g., refund, ATM).
BOLT 12 messages are limited to a range of TLV record types. Refactor
decode_tlv_stream into a decode_tlv_stream_range macro for limiting
which types are parsed. Requires a SeekReadable trait for rewinding when
a type outside of the range is seen. This allows for composing TLV
streams of different ranges.
Updates offer parsing accordingly and adds a test demonstrating failure
if a type outside of the range is included.
Jeffrey Czyz [Thu, 11 Aug 2022 21:51:06 +0000 (16:51 -0500)]
Offer parsing from bech32 strings
Add common bech32 parsing for BOLT 12 messages. The encoding is similar
to bech32 only without a checksum and with support for continuing
messages across multiple parts.
Messages implementing Bech32Encode are parsed into a TLV stream, which
is converted to the desired message content while performing semantic
checks. Checking after conversion allows for more elaborate checks of
data composed of multiple TLV records and for more meaningful error
messages.
The parsed bytes are also saved to allow creating messages with mirrored
data, even if TLV records are unknown.
Elias Rohrer [Wed, 16 Nov 2022 09:54:25 +0000 (10:54 +0100)]
Mention `user_channel_id` rand. version req.
As it was previously omitted, we clarify here starting from which version users can expect the `user_channel_id` to be randomized for inbound channels.
Matt Corallo [Tue, 15 Nov 2022 00:46:22 +0000 (00:46 +0000)]
Accept feerate increases even if they aren't high enough for us
LND nodes have very broken fee estimators, causing them to suggest
feerates that don't even meet a current mempool minimum feerate
when fees go up over the course of hours. This can cause us to
reject their feerate estimates as they're not high enough, even
though their new feerate is higher than what we had already (which
is the feerate we'll use to broadcast a closing transaction). This
implies we force-close the channel and broadcast something with a
feerate lower than our counterparty was offering.
Here we simply accept such feerates as they are better than what we
had. We really should also close the channel, but only after we
get their signature on the new feerate. That should happen by
checking channel feerates every time we see a new block so is
orthogonal to this code.
Ultimately the fix is anchor outputs plus package-based relay in
Bitcoin Core, however we're still quite some ways from that, so
worth needlessly closing channels for now.
Matt Corallo [Tue, 15 Nov 2022 00:29:10 +0000 (00:29 +0000)]
Await `Future::poll` `Complete`d before unsetting notify-required
When we mark a future as complete, if the user is using the
`std::future::Future` impl to get notified, we shouldn't just
assume we have completed the `Future` when we call the `Waker`. A
`Future` may have been `drop`'d at that point (or may not be
`poll`'d again) even though we wake the `Waker`.
Because we now have a `callbacks_made` flag, we can fix this rather
trivially, simply not setting the flag until the `Future` is
`poll`'d `Complete`.
Matt Corallo [Tue, 15 Nov 2022 00:24:25 +0000 (00:24 +0000)]
Wipe `Notifier` `FutureState` when returning from a waiter.
When we return from one of the wait functions in `Notifier`, we
should also ensure that the next `Future` doesn't start in the
`complete` state, as we have already notified the user, as far as
we're concerned.
This is technically a regression from the previous commit, but as
it is a logically separate change it is in its own commit.
Matt Corallo [Mon, 14 Nov 2022 23:49:27 +0000 (23:49 +0000)]
Unset the needs-notify bit in a Notifier when a Future is fetched
If a `Notifier` gets `notify()`ed and the a `Future` is fetched,
even though the `Future` is marked completed from the start and
the user may pass callbacks which are called, we'll never wipe the
needs-notify bit in the `Notifier`.
The solution is to keep track of the `FutureState` in the returned
`Future` even though its `complete` from the start, adding a new
flag in the `FutureState` which indicates callbacks have been made
and checking that flag when waiting or returning a second `Future`.
Elias Rohrer [Mon, 24 Oct 2022 08:30:11 +0000 (10:30 +0200)]
Make `user_channel_id` a `u128`
We increase the `user_channel_id` type from `u64` to `u128`. In order to
maintain backwards compatibility, we have to de-/serialize it as two
separate `u64`s in `Event` as well as in the `Channel` itself.
Elias Rohrer [Fri, 21 Oct 2022 09:05:18 +0000 (11:05 +0200)]
Randomize `user_channel_id` for inbound channels
Previously, all inbound channels defaulted to a `user_channel_id` of 0,
which didn't allow for them being discerned on that basis. Here, we
simply randomize the identifier to fix this and enable the use of
`user_channel_id` as a true identifier for channels (assuming an equally
reasonable value is chosen for outbound channels and given upon
`create_channel()`).
After the first persistence-required `Future` wakeup, we'll always
complete additional futures instantly as we don't clear the
"need wake" bit. Instead, we need to just assume that if a future
was generated (and not immediately drop'd) that its sufficient to
notify the user.
Wilmer Paulino [Tue, 8 Nov 2022 02:09:16 +0000 (18:09 -0800)]
Use BaseEventHandler to expose async event handling on InvoicePayer
We introduce a new sealed trait BaseEventHandler that has a blanket
implementation for any T. Since the trait cannot be implemented outside
of the crate, this allow us to expose specific implementations of
InvoicePayer that allow for synchronous and asynchronous event handling.
Matt Corallo [Wed, 2 Nov 2022 23:25:34 +0000 (23:25 +0000)]
Add a separate PaymentSendFailure for idempotency violation
When a user attempts to send a payment but it fails due to
idempotency key violation, they need to know that this was the
reason as they need to handle the error programmatically
differently from other errors.
Here we simply add a new `PaymentSendFailure` enum variant for
`DuplicatePayment` to allow for that.
It was pointed out that its quite confusing that
`AllFailedRetrySafe` does not allow you to call `retry_payment`,
though the documentation on it does specify this. Instead, we
simply rename it to `AllFailedResendSafe` to indicate that the
action that is safe to take is *resending*, not *retrying*.
Elias Rohrer [Tue, 8 Nov 2022 20:45:28 +0000 (21:45 +0100)]
Track block hash, return via `get_relevant_txids`
Previously, `Confirm::get_relevant_txids()` only returned a list of
transactions that have to be monitored for reorganization out of the
chain. This interface however required double bookkeeping: while we
internally keep track of the best block, height, etc, it would also
require the user to keep track which transaction was previously
confirmed in which block and to take actions based on any change, e.g,
to reconfirm them when the block would be reorged-out and the
transactions had been reconfirmed in another block.
Here, we track the confirmation block hash internally and return it via
`Confirm::get_relevant_txids()` to the user, which alleviates the
requirement for double bookkeeping: the user can now simply check
whether the given transaction is still confirmed and in the given block,
and take action if not.
We also split `update_claims_view`: Previously it was one, now it's two
methods: `update_claims_view_from_matched_txn` and
`update_claims_view_from_requests`.
Refactor HTLCForwardInfo::AddHTLC for intercept forwards
In upcoming commit(s), we'll want to store intercepted HTLC forwards in
ChannelManager before the user signals that they should be forwarded. It
wouldn't make sense to store a HTLCForwardInfo as-is because the FailHTLC
variant doesn't make sense, so we refactor out the ::AddHTLC contents into its
own struct for storage.
Co-authored-by: John Cantrell <johncantrell97@gmail.com> Co-authored-by: Valentine Wallace <vwallace@protonmail.com>
Jeffrey Czyz [Tue, 9 Aug 2022 22:40:26 +0000 (17:40 -0500)]
Builder for creating offers
Add a builder for creating offers given a required description and
node_id. Other settings are optional and duplicative settings will
override previous settings for non-Vec fields.
Jeffrey Czyz [Fri, 24 Jun 2022 21:27:42 +0000 (16:27 -0500)]
Serialization macro for TLV streams
BOLT 12's offer message is encoded as a TLV stream (i.e., a sequence of
TLV records). impl_writeable_tlv_based can't be used because it writes
the overall length of the struct, whereas TLV streams only include the
length of each TLV record. Add a `tlv_stream` macro for defining structs
used in encoding.
TLV records containing a single variable-length type should not encode
the types length in the value since it is redundant. Add a wrapper type
that can be used within a TLV stream to support the correct behavior
during serialization and de-serialization.
Jeffrey Czyz [Fri, 7 Oct 2022 04:12:48 +0000 (23:12 -0500)]
Add WithoutLength wrapper
When serializing variable-length types as part of a TLV stream, the
length does not need to be serialized as it is already encoded in TLV
records. Add a WithoutLength wrapper for this encoding. Replace
VecReadWrapper and VecWriteWrapper with this single type to avoid
redundant encoders.
Jeffrey Czyz [Tue, 9 Aug 2022 22:24:10 +0000 (17:24 -0500)]
Offer message interface and data format
Define an interface for BOLT 12 `offer` messages. The underlying format
consists of the original bytes and the parsed contents.
The bytes are later needed when constructing an `invoice_request`
message. This is because it must mirror all the `offer` TLV records,
including unknown ones, which aren't represented in the contents.
The contents will be used in `invoice_request` messages to avoid
duplication. Some fields while required in a typical user-pays-merchant
flow may not be necessary in the merchant-pays-user flow (i.e., refund).
Jeffrey Czyz [Thu, 6 Oct 2022 18:44:35 +0000 (13:44 -0500)]
Add PrintableString utility
Strings defined by third parties may contain control characters. Provide
a wrapper such that these are replaced when displayed. Useful in node
aliases and offer fields.
Jeffrey Czyz [Fri, 24 Jun 2022 21:40:49 +0000 (16:40 -0500)]
Offer features for BOLT 12
The offer message in BOLT 12 contains a features TLV record. Add a
corresponding OfferFeatures type where the length is not included in the
serialization as it would be redundant with the record length.
Otherwise, define the features to be the same as InvoiceFeatures.
Make `process_pending_htlc_forwards` more readable
Refactor `process_pending_htlc_forwards` to ensure that both branches
that fails `pending_forwards` are placed next to eachother for improved
readability.
Consider `channel_id`s in `short_to_chan_info` as unguaranteed
As the `short_to_chan_info` map has been removed from the
`channel_state`, there is no longer any consistency guarantees between
the `by_id` and `short_to_chan_info` maps. This commit ensures that we
don't force unwrap channels where the channel_id has been queried from
the `short_to_chan_info` map.
As the `short_to_chan_info` has been moved out of the `channel_state` to
a standalone lock, several macros no longer need the `channel_state`
passed into the macro.