Now that we use the `rust-bitcoin` `WitnessProgram` to check our
addresses, we can just rely on it, rather than checking the program
length and version.
We change the Bolt12Invoice struct to carry a tagged hash. Because
message_digest is then only used in one place, we can inline it in
the TaggedHash constructor.
Additional BOLT 12 tests specific to Offer were added, which will live
in the offer module. Thus, it makes sense to move the bech32 tests to
the parse module.
Define the BOLT 12 message flow in ChannelManager's
OffersMessageHandler implementation.
- An invoice_request message results in responding with an invoice
message if it can be verified that the request is for a valid offer.
- An invoice is paid if it can be verified to have originated from a
sent invoice_request or a refund.
- An invoice_error is sent in some failure cases.
- Initial messages enqueued for sending are released to OnionMessenger
Building an invoice will fail if the underlying offer or refund has
already expired. The check was skipped in no-std since there is no
system clock. However, the invoice creation time can be used instead.
This prevents responding to an invoice request if the offer has already
expired.
Add a utility to ChannelManager for sending an InvoiceRequest for an
Offer such that derived keys are used for the payer id. This allows for
stateless verification of any Invoice messages before it is paid.
Also tracks future payments using the given PaymentId such that the
corresponding Invoice is paid only once.
Add utility functions to ChannelManager for creating OfferBuilder,
and RefundBuilder such that derived keys are used for the signing
pubkey and payer id, respectively. This allows for stateless
verification of any InvoiceRequest and Invoice messages.
Later, blinded paths can be included in the returned builders.
Also tracks future payments using the given PaymentId such that the
corresponding Invoice is paid only once.
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.
InvoiceRequest::verify_and_respond_using_derived_keys takes a payment
hash. To avoid generating one for invoice requests that ultimately
cannot be verified, split the method into one for verifying and another
for responding.
BOLT 12 messages need to be signed in the following scenarios:
- constructing an InvoiceRequest after scanning an Offer,
- constructing an Invoice after scanning a Refund, and
- constructing an Invoice when handling an InvoiceRequest.
Extend the NodeSigner trait to support signing BOLT 12 invoices such
that it can be used in the latter contexts. The method could be used
in an OffersMessageHandler.
Bolt12Invoice can either be for an Offer (via an InvoiceRequest) or a
Refund. It wraps those types, so expose their methods on both
Bolt12Invoice and UnsignedBolt12Invoice.
Since Refund does not have all the Offer/InvoiceRequest methods, use an
Option return type such that None can returned for refund-based
invoices.
For methods that are duplicated between Offer/InvoiceRequest and
Bolt12Invoice, prefer the (non-Option, if applicable) method from
Bolt12Invoice (e.g., amount_msats, signing_pubkey).
Various messages wrap InvoiceRequestContents, which shouldn't be exposed
as it is an implementation detail. Define a macro for InvoiceRequest
accessor methods so that these messages can also define them.
InvoiceRequest wraps OfferContents, which shouldn't be exposed as it is
an implementation detail. Define a macro for Offer accessor methods so
that InvoiceRequest and UnsignedInvoiceRequest can also define them.
InvoiceBuilder is parameterized by a SigningPubkeyStrategy, either
ExplicitSigningPubkey and DerivedSigningPubkey. It also holds an
Option<KeyPair>, which may be None and Some for those strategies,
respectively. This leads to methods for InvoiceBuilder parameterized by
DerivedSigningPubkey needing to blindly unwrap the Option<KeyPair>.
Instead, have DerivedSigningPubkey wrap KeyPair.
The function used to sign BOLT 12 messages only takes a message digest.
This doesn't allow signers to independently verify the message before
signing nor does it allow them to derive the necessary signing keys, if
needed.
Introduce a TaggedHash wrapper for a message digest, which each unsigned
BOLT 12 message type constructs upon initialization. Change the signing
function to take AsRef<TaggedHash>, which each unsigned type implements.
This allows the signing function to take any unsigned message and obtain
its tagged hash.
We missed one method that now cannot be bindings exported - the
`payment_paths` method, as it returns a slice of objects, which
cannot be supported in bindings.
If an InvoiceRequest or an Invoice delivered via an onion message cannot
be handled, the recipient should reply with an InvoiceError if a reply
path was given. Define the message and conversion from SemanticError.