mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
lightningd: sew in htlc set.
The invoice_try_pay code now takes a set, rather than a single htlc, but it's basically the same thing. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
c2b357b916
commit
8e3234e67a
@ -178,8 +178,7 @@ void htlc_set_add(struct lightningd *ld,
|
||||
}
|
||||
|
||||
if (amount_msat_eq(set->so_far, total_msat)) {
|
||||
/* FIXME: hand to invoice_try_pay! */
|
||||
tal_free(set);
|
||||
invoice_try_pay(ld, set, details);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ static void invoice_secret(const struct preimage *payment_preimage,
|
||||
struct invoice_payment_hook_payload {
|
||||
struct lightningd *ld;
|
||||
/* Set to NULL if it is deleted while waiting for plugin */
|
||||
struct htlc_in *hin;
|
||||
struct htlc_set *set;
|
||||
/* What invoice it's trying to pay. */
|
||||
const struct json_escape *label;
|
||||
/* Amount it's offering. */
|
||||
@ -146,12 +146,13 @@ invoice_payment_serialize(struct invoice_payment_hook_payload *payload,
|
||||
json_object_end(stream); /* .payment */
|
||||
}
|
||||
|
||||
/* Peer dies? Remove hin ptr from payload so we know to ignore plugin return */
|
||||
static void invoice_payload_remove_hin(struct htlc_in *hin,
|
||||
/* Set times out or HTLC deleted? Remove set ptr from payload so we
|
||||
* know to ignore plugin return */
|
||||
static void invoice_payload_remove_set(struct htlc_set *set,
|
||||
struct invoice_payment_hook_payload *payload)
|
||||
{
|
||||
assert(payload->hin == hin);
|
||||
payload->hin = NULL;
|
||||
assert(payload->set == set);
|
||||
payload->set = NULL;
|
||||
}
|
||||
|
||||
static bool hook_gives_failcode(const char *buffer,
|
||||
@ -195,12 +196,12 @@ invoice_payment_hook_cb(struct invoice_payment_hook_payload *payload,
|
||||
* called even if the hook is not registered. */
|
||||
notify_invoice_payment(ld, payload->msat, payload->preimage, payload->label);
|
||||
|
||||
tal_del_destructor2(payload->hin, invoice_payload_remove_hin, payload);
|
||||
tal_del_destructor2(payload->set, invoice_payload_remove_set, payload);
|
||||
/* We want to free this, whatever happens. */
|
||||
tal_steal(tmpctx, payload);
|
||||
|
||||
/* If peer dies or something, this can happen. */
|
||||
if (!payload->hin) {
|
||||
if (!payload->set) {
|
||||
log_debug(ld->log, "invoice '%s' paying htlc_in has gone!",
|
||||
payload->label->s);
|
||||
return;
|
||||
@ -210,21 +211,22 @@ invoice_payment_hook_cb(struct invoice_payment_hook_payload *payload,
|
||||
* we can also fail */
|
||||
if (!wallet_invoice_find_by_label(ld->wallet, &invoice, payload->label)) {
|
||||
failcode = WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS;
|
||||
fail_htlc(payload->hin, failcode);
|
||||
htlc_set_fail(payload->set, failcode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Did we have a hook result? */
|
||||
if (hook_gives_failcode(buffer, toks, &failcode)) {
|
||||
fail_htlc(payload->hin, failcode);
|
||||
htlc_set_fail(payload->set, failcode);
|
||||
return;
|
||||
}
|
||||
|
||||
log_info(ld->log, "Resolved invoice '%s' with amount %s",
|
||||
payload->label->s,
|
||||
type_to_string(tmpctx, struct amount_msat, &payload->msat));
|
||||
log_info(ld->log, "Resolved invoice '%s' with amount %s in %zu htlcs",
|
||||
payload->label->s,
|
||||
type_to_string(tmpctx, struct amount_msat, &payload->msat),
|
||||
tal_count(payload->set->htlcs));
|
||||
wallet_invoice_resolve(ld->wallet, invoice, payload->msat);
|
||||
fulfill_htlc(payload->hin, &payload->preimage);
|
||||
htlc_set_fulfill(payload->set, &payload->preimage);
|
||||
}
|
||||
|
||||
REGISTER_PLUGIN_HOOK(invoice_payment,
|
||||
@ -303,29 +305,18 @@ invoice_check_payment(const tal_t *ctx,
|
||||
}
|
||||
|
||||
void invoice_try_pay(struct lightningd *ld,
|
||||
struct htlc_in *hin,
|
||||
const struct sha256 *payment_hash,
|
||||
const struct amount_msat msat,
|
||||
const struct secret *payment_secret)
|
||||
struct htlc_set *set,
|
||||
const struct invoice_details *details)
|
||||
{
|
||||
const struct invoice_details *details;
|
||||
struct invoice_payment_hook_payload *payload;
|
||||
|
||||
details = invoice_check_payment(tmpctx, ld, payment_hash, msat,
|
||||
payment_secret);
|
||||
|
||||
if (!details) {
|
||||
fail_htlc(hin, WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS);
|
||||
return;
|
||||
}
|
||||
|
||||
payload = tal(ld, struct invoice_payment_hook_payload);
|
||||
payload->ld = ld;
|
||||
payload->label = tal_steal(payload, details->label);
|
||||
payload->msat = msat;
|
||||
payload->msat = set->so_far;
|
||||
payload->preimage = details->r;
|
||||
payload->hin = hin;
|
||||
tal_add_destructor2(hin, invoice_payload_remove_hin, payload);
|
||||
payload->set = set;
|
||||
tal_add_destructor2(set, invoice_payload_remove_set, payload);
|
||||
|
||||
plugin_hook_call_invoice_payment(ld, payload, payload);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <wire/gen_onion_wire.h>
|
||||
|
||||
struct amount_msat;
|
||||
struct htlc_in;
|
||||
struct htlc_set;
|
||||
struct lightningd;
|
||||
struct sha256;
|
||||
|
||||
@ -27,19 +27,15 @@ invoice_check_payment(const tal_t *ctx,
|
||||
const struct secret *payment_secret);
|
||||
|
||||
/**
|
||||
* invoice_try_pay - process payment for this payment_hash, amount msat.
|
||||
* invoice_try_pay - process payment for these incoming payments.
|
||||
* @ld: lightningd
|
||||
* @hin: the input HTLC which is offering to pay.
|
||||
* @payment_hash: hash of preimage they want.
|
||||
* @msat: amount they offer to pay.
|
||||
* @payment_secret: they payment secret they sent, if any.
|
||||
* @set: the htlc_set used to pay this.
|
||||
* @details: returned from successful invoice_check_payment.
|
||||
*
|
||||
* Either calls fulfill_htlc() or fail_htlcs().
|
||||
* Either calls fulfill_htlc_set() or fail_htlc_set().
|
||||
*/
|
||||
void invoice_try_pay(struct lightningd *ld,
|
||||
struct htlc_in *hin,
|
||||
const struct sha256 *payment_hash,
|
||||
const struct amount_msat msat,
|
||||
const struct secret *payment_secret);
|
||||
struct htlc_set *set,
|
||||
const struct invoice_details *details);
|
||||
|
||||
#endif /* LIGHTNING_LIGHTNINGD_INVOICE_H */
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <gossipd/gen_gossip_wire.h>
|
||||
#include <lightningd/chaintopology.h>
|
||||
#include <lightningd/htlc_end.h>
|
||||
#include <lightningd/htlc_set.h>
|
||||
#include <lightningd/json.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
#include <lightningd/lightningd.h>
|
||||
@ -299,18 +300,6 @@ static void handle_localpay(struct htlc_in *hin,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* BOLT-9441a66faad63edc8cd89860b22fbf24a86f0dcd #4:
|
||||
* - if it does not support `basic_mpp`:
|
||||
* - MUST fail the HTLC if `total_msat` is not exactly equal to
|
||||
* `amt_to_forward`.
|
||||
*/
|
||||
if (!amount_msat_eq(amt_to_forward, total_msat)) {
|
||||
/* FIXME: Ideally, we use WIRE_INVALID_ONION_PAYLOAD and
|
||||
* point at the total_msat field */
|
||||
failcode = WIRE_FINAL_INCORRECT_HTLC_AMOUNT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* BOLT #4:
|
||||
*
|
||||
* 1. type: 18 (`final_incorrect_cltv_expiry`)
|
||||
@ -341,7 +330,7 @@ static void handle_localpay(struct htlc_in *hin,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
invoice_try_pay(ld, hin, &hin->payment_hash, amt_to_forward, payment_secret);
|
||||
htlc_set_add(ld, hin, total_msat, payment_secret);
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
@ -87,9 +87,6 @@ char *encode_scriptpubkey_to_addr(const tal_t *ctx UNNEEDED,
|
||||
const struct chainparams *chainparams UNNEEDED,
|
||||
const u8 *scriptPubkey UNNEEDED)
|
||||
{ fprintf(stderr, "encode_scriptpubkey_to_addr called!\n"); abort(); }
|
||||
/* Generated stub for fail_htlc */
|
||||
void fail_htlc(struct htlc_in *hin UNNEEDED, enum onion_type failcode UNNEEDED)
|
||||
{ fprintf(stderr, "fail_htlc called!\n"); abort(); }
|
||||
/* Generated stub for fatal */
|
||||
void fatal(const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "fatal called!\n"); abort(); }
|
||||
@ -120,9 +117,6 @@ bool fromwire_hsm_sign_invoice_reply(const void *p UNNEEDED, secp256k1_ecdsa_rec
|
||||
/* Generated stub for fromwire_onchain_dev_memleak_reply */
|
||||
bool fromwire_onchain_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_onchain_dev_memleak_reply called!\n"); abort(); }
|
||||
/* Generated stub for fulfill_htlc */
|
||||
void fulfill_htlc(struct htlc_in *hin UNNEEDED, const struct preimage *preimage UNNEEDED)
|
||||
{ fprintf(stderr, "fulfill_htlc called!\n"); abort(); }
|
||||
/* Generated stub for get_block_height */
|
||||
u32 get_block_height(const struct chain_topology *topo UNNEEDED)
|
||||
{ fprintf(stderr, "get_block_height called!\n"); abort(); }
|
||||
@ -136,6 +130,12 @@ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED,
|
||||
struct amount_sat dust_limit UNNEEDED,
|
||||
enum side side UNNEEDED)
|
||||
{ fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); }
|
||||
/* Generated stub for htlc_set_fail */
|
||||
void htlc_set_fail(struct htlc_set *set UNNEEDED, enum onion_type failcode UNNEEDED)
|
||||
{ fprintf(stderr, "htlc_set_fail called!\n"); abort(); }
|
||||
/* Generated stub for htlc_set_fulfill */
|
||||
void htlc_set_fulfill(struct htlc_set *set UNNEEDED, const struct preimage *preimage UNNEEDED)
|
||||
{ fprintf(stderr, "htlc_set_fulfill called!\n"); abort(); }
|
||||
/* Generated stub for json_add_address */
|
||||
void json_add_address(struct json_stream *response UNNEEDED, const char *fieldname UNNEEDED,
|
||||
const struct wireaddr *addr UNNEEDED)
|
||||
|
@ -2625,16 +2625,15 @@ def test_partial_payment(node_factory, bitcoind, executor):
|
||||
l2.daemon.wait_for_log(r'dev_disconnect')
|
||||
l3.daemon.wait_for_log(r'dev_disconnect')
|
||||
|
||||
# Now continue, payments will fail because receiver doesn't do MPP.
|
||||
# Now continue, payments will succeed due to MPP.
|
||||
l2.rpc.dev_reenable_commit(l4.info['id'])
|
||||
l3.rpc.dev_reenable_commit(l4.info['id'])
|
||||
|
||||
# See FIXME in peer_htlcs: WIRE_INVALID_ONION_PAYLOAD would be better.
|
||||
with pytest.raises(RpcError, match=r'WIRE_FINAL_INCORRECT_HTLC_AMOUNT'):
|
||||
l1.rpc.call('waitsendpay', [inv['payment_hash'], None, 1])
|
||||
with pytest.raises(RpcError, match=r'WIRE_FINAL_INCORRECT_HTLC_AMOUNT'):
|
||||
l1.rpc.call('waitsendpay', {'payment_hash': inv['payment_hash'],
|
||||
'partid': 2})
|
||||
res = l1.rpc.call('waitsendpay', [inv['payment_hash'], None, 1])
|
||||
assert res['partid'] == 1
|
||||
res = l1.rpc.call('waitsendpay', {'payment_hash': inv['payment_hash'],
|
||||
'partid': 2})
|
||||
assert res['partid'] == 2
|
||||
|
||||
for i in range(2):
|
||||
line = l4.daemon.wait_for_log('print_htlc_onion.py: Got onion')
|
||||
|
@ -130,6 +130,12 @@ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED,
|
||||
struct amount_sat dust_limit UNNEEDED,
|
||||
enum side side UNNEEDED)
|
||||
{ fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); }
|
||||
/* Generated stub for htlc_set_add */
|
||||
void htlc_set_add(struct lightningd *ld UNNEEDED,
|
||||
struct htlc_in *hin UNNEEDED,
|
||||
struct amount_msat total_msat UNNEEDED,
|
||||
const struct secret *payment_secret UNNEEDED)
|
||||
{ fprintf(stderr, "htlc_set_add called!\n"); abort(); }
|
||||
/* Generated stub for invoices_create */
|
||||
bool invoices_create(struct invoices *invoices UNNEEDED,
|
||||
struct invoice *pinvoice UNNEEDED,
|
||||
@ -203,13 +209,6 @@ void invoices_waitone(const tal_t *ctx UNNEEDED,
|
||||
void (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED,
|
||||
void *cbarg UNNEEDED)
|
||||
{ fprintf(stderr, "invoices_waitone called!\n"); abort(); }
|
||||
/* Generated stub for invoice_try_pay */
|
||||
void invoice_try_pay(struct lightningd *ld UNNEEDED,
|
||||
struct htlc_in *hin UNNEEDED,
|
||||
const struct sha256 *payment_hash UNNEEDED,
|
||||
const struct amount_msat msat UNNEEDED,
|
||||
const struct secret *payment_secret UNNEEDED)
|
||||
{ fprintf(stderr, "invoice_try_pay called!\n"); abort(); }
|
||||
/* Generated stub for json_add_address */
|
||||
void json_add_address(struct json_stream *response UNNEEDED, const char *fieldname UNNEEDED,
|
||||
const struct wireaddr *addr UNNEEDED)
|
||||
|
Loading…
Reference in New Issue
Block a user