mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-10 01:24:30 +01:00
invoice: hack in merkle of invoice as "payment_secret" (EXPERIMENTAL_FEATURES)
This lets actually pay the invoice that fetchinvoice returns. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
2baa410e2b
commit
19af1d10e6
@@ -135,6 +135,31 @@ static void invoice_secret(const struct preimage *payment_preimage,
|
||||
memcpy(payment_secret->data, secret.u.u8, sizeof(secret.u.u8));
|
||||
}
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
/* FIXME: This is a hack. The real secret should be a signature of some
|
||||
* onion key, using the payer_id */
|
||||
static void invoice_secret_bolt12(struct lightningd *ld,
|
||||
const char *invstring,
|
||||
struct secret *payment_secret)
|
||||
{
|
||||
char *fail;
|
||||
struct tlv_invoice *inv;
|
||||
struct sha256 merkle;
|
||||
|
||||
inv = invoice_decode(tmpctx, invstring, strlen(invstring),
|
||||
NULL, NULL, &fail);
|
||||
if (!inv) {
|
||||
log_broken(ld->log, "Unable to decode our invoice %s",
|
||||
invstring);
|
||||
return;
|
||||
}
|
||||
|
||||
merkle_tlv(inv->fields, &merkle);
|
||||
BUILD_ASSERT(sizeof(*payment_secret) == sizeof(merkle));
|
||||
memcpy(payment_secret, &merkle, sizeof(merkle));
|
||||
}
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
|
||||
struct invoice_payment_hook_payload {
|
||||
struct lightningd *ld;
|
||||
/* Set to NULL if it is deleted while waiting for plugin */
|
||||
@@ -348,6 +373,11 @@ invoice_check_payment(const tal_t *ctx,
|
||||
if (payment_secret) {
|
||||
struct secret expected;
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
if (details->invstring && strstarts(details->invstring, "lni1"))
|
||||
invoice_secret_bolt12(ld, details->invstring, &expected);
|
||||
else
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
invoice_secret(&details->r, &expected);
|
||||
if (!secret_eq_consttime(payment_secret, &expected)) {
|
||||
log_debug(ld->log, "Attept to pay %s with wrong secret",
|
||||
|
||||
@@ -760,6 +760,13 @@ struct tlv_invoice *invoice_decode_nosig(const tal_t *ctx UNNEEDED,
|
||||
/* Generated stub for invoice_encode */
|
||||
char *invoice_encode(const tal_t *ctx UNNEEDED, const struct tlv_invoice *bolt12_tlv UNNEEDED)
|
||||
{ fprintf(stderr, "invoice_encode called!\n"); abort(); }
|
||||
/* Generated stub for invoice_decode */
|
||||
struct tlv_invoice *invoice_decode(const tal_t *ctx UNNEEDED,
|
||||
const char *b12 UNNEEDED, size_t b12len UNNEEDED,
|
||||
const struct feature_set *our_features UNNEEDED,
|
||||
const struct chainparams *must_be_chain UNNEEDED,
|
||||
char **fail UNNEEDED)
|
||||
{ fprintf(stderr, "invoice_decode called!\n"); abort(); }
|
||||
#endif
|
||||
|
||||
static void add_candidate(struct routehint_candidate **candidates, int n,
|
||||
|
||||
@@ -3856,6 +3856,8 @@ def test_fetchinvoice(node_factory, bitcoind):
|
||||
inv1 = l1.rpc.call('fetchinvoice', {'offer': offer})
|
||||
inv2 = l1.rpc.call('fetchinvoice', {'offer': offer})
|
||||
assert inv1 != inv2
|
||||
l1.rpc.pay(inv1['invoice'])
|
||||
l1.rpc.pay(inv2['invoice'])
|
||||
|
||||
# Single-use invoice can be fetched multiple times, only paid once.
|
||||
offer = l3.rpc.call('offer', {'amount': '1msat',
|
||||
@@ -3866,3 +3868,34 @@ def test_fetchinvoice(node_factory, bitcoind):
|
||||
inv1 = l1.rpc.call('fetchinvoice', {'offer': offer})
|
||||
inv2 = l1.rpc.call('fetchinvoice', {'offer': offer})
|
||||
assert inv1 != inv2
|
||||
|
||||
l1.rpc.pay(inv1['invoice'])
|
||||
|
||||
# FIXME: We don't report failure yet.
|
||||
# # We can't pay the other one now.
|
||||
# with pytest.raises(RpcError, match='???'):
|
||||
# l1.rpc.pay(inv2['invoice'])
|
||||
#
|
||||
# # We can't reuse the offer, either.
|
||||
# with pytest.raises(RpcError, match='???'):
|
||||
# l1.rpc.call('fetchinvoice', {'offer': offer})
|
||||
|
||||
# Recurring offer.
|
||||
offer = l2.rpc.call('offer', {'amount': '1msat',
|
||||
'description': 'recurring test',
|
||||
'recurrence': '1minutes'})['bolt12']
|
||||
print(offer)
|
||||
|
||||
ret = l1.rpc.call('fetchinvoice', {'offer': offer,
|
||||
'recurrence_counter': 0,
|
||||
'recurrence_label': 'test recurrence'})
|
||||
print(ret)
|
||||
|
||||
l1.rpc.pay(ret['invoice'], label='test recurrence')
|
||||
|
||||
ret = l1.rpc.call('fetchinvoice', {'offer': offer,
|
||||
'recurrence_counter': 1,
|
||||
'recurrence_label': 'test recurrence'})
|
||||
print(ret)
|
||||
|
||||
l1.rpc.pay(ret['invoice'], label='test recurrence')
|
||||
|
||||
Reference in New Issue
Block a user