mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 09:54:16 +01:00
waitsendpay: add partid arg.
We need to be able to wait for a unique payment, now payment_hash is not always unique. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
63fffd41c8
commit
b670b51fa2
@ -37,6 +37,7 @@ struct sendpay_command {
|
|||||||
struct list_node list;
|
struct list_node list;
|
||||||
|
|
||||||
struct sha256 payment_hash;
|
struct sha256 payment_hash;
|
||||||
|
u64 partid;
|
||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,11 +51,13 @@ static void destroy_sendpay_command(struct sendpay_command *pc)
|
|||||||
static void
|
static void
|
||||||
add_sendpay_waiter(struct lightningd *ld,
|
add_sendpay_waiter(struct lightningd *ld,
|
||||||
struct command *cmd,
|
struct command *cmd,
|
||||||
const struct sha256 *payment_hash)
|
const struct sha256 *payment_hash,
|
||||||
|
u64 partid)
|
||||||
{
|
{
|
||||||
struct sendpay_command *pc = tal(cmd, struct sendpay_command);
|
struct sendpay_command *pc = tal(cmd, struct sendpay_command);
|
||||||
|
|
||||||
pc->payment_hash = *payment_hash;
|
pc->payment_hash = *payment_hash;
|
||||||
|
pc->partid = partid;
|
||||||
pc->cmd = cmd;
|
pc->cmd = cmd;
|
||||||
list_add(&ld->sendpay_commands, &pc->list);
|
list_add(&ld->sendpay_commands, &pc->list);
|
||||||
tal_add_destructor(pc, destroy_sendpay_command);
|
tal_add_destructor(pc, destroy_sendpay_command);
|
||||||
@ -65,11 +68,13 @@ add_sendpay_waiter(struct lightningd *ld,
|
|||||||
static void
|
static void
|
||||||
add_waitsendpay_waiter(struct lightningd *ld,
|
add_waitsendpay_waiter(struct lightningd *ld,
|
||||||
struct command *cmd,
|
struct command *cmd,
|
||||||
const struct sha256 *payment_hash)
|
const struct sha256 *payment_hash,
|
||||||
|
u64 partid)
|
||||||
{
|
{
|
||||||
struct sendpay_command *pc = tal(cmd, struct sendpay_command);
|
struct sendpay_command *pc = tal(cmd, struct sendpay_command);
|
||||||
|
|
||||||
pc->payment_hash = *payment_hash;
|
pc->payment_hash = *payment_hash;
|
||||||
|
pc->partid = partid;
|
||||||
pc->cmd = cmd;
|
pc->cmd = cmd;
|
||||||
list_add(&ld->waitsendpay_commands, &pc->list);
|
list_add(&ld->waitsendpay_commands, &pc->list);
|
||||||
tal_add_destructor(pc, destroy_sendpay_command);
|
tal_add_destructor(pc, destroy_sendpay_command);
|
||||||
@ -252,6 +257,8 @@ static void tell_waiters_failed(struct lightningd *ld,
|
|||||||
list_for_each_safe(&ld->waitsendpay_commands, pc, next, list) {
|
list_for_each_safe(&ld->waitsendpay_commands, pc, next, list) {
|
||||||
if (!sha256_eq(payment_hash, &pc->payment_hash))
|
if (!sha256_eq(payment_hash, &pc->payment_hash))
|
||||||
continue;
|
continue;
|
||||||
|
if (payment->partid != pc->partid)
|
||||||
|
continue;
|
||||||
|
|
||||||
sendpay_fail(pc->cmd, payment,
|
sendpay_fail(pc->cmd, payment,
|
||||||
pay_errcode, onionreply, fail, details);
|
pay_errcode, onionreply, fail, details);
|
||||||
@ -269,6 +276,8 @@ static void tell_waiters_success(struct lightningd *ld,
|
|||||||
list_for_each_safe(&ld->waitsendpay_commands, pc, next, list) {
|
list_for_each_safe(&ld->waitsendpay_commands, pc, next, list) {
|
||||||
if (!sha256_eq(payment_hash, &pc->payment_hash))
|
if (!sha256_eq(payment_hash, &pc->payment_hash))
|
||||||
continue;
|
continue;
|
||||||
|
if (payment->partid != pc->partid)
|
||||||
|
continue;
|
||||||
|
|
||||||
sendpay_success(pc->cmd, payment);
|
sendpay_success(pc->cmd, payment);
|
||||||
}
|
}
|
||||||
@ -623,9 +632,12 @@ static struct command_result *wait_payment(struct lightningd *ld,
|
|||||||
payment_hash));
|
payment_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_debug(cmd->ld->log, "Payment part %"PRIu64"/%"PRIu64" status %u",
|
||||||
|
partid, payment->partid, payment->status);
|
||||||
|
|
||||||
switch (payment->status) {
|
switch (payment->status) {
|
||||||
case PAYMENT_PENDING:
|
case PAYMENT_PENDING:
|
||||||
add_waitsendpay_waiter(ld, cmd, payment_hash);
|
add_waitsendpay_waiter(ld, cmd, payment_hash, partid);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case PAYMENT_COMPLETE:
|
case PAYMENT_COMPLETE:
|
||||||
@ -913,7 +925,7 @@ send_payment_core(struct lightningd *ld,
|
|||||||
/* We write this into db when HTLC is actually sent. */
|
/* We write this into db when HTLC is actually sent. */
|
||||||
wallet_payment_setup(ld->wallet, payment);
|
wallet_payment_setup(ld->wallet, payment);
|
||||||
|
|
||||||
add_sendpay_waiter(ld, cmd, rhash);
|
add_sendpay_waiter(ld, cmd, rhash, partid);
|
||||||
return command_still_pending(cmd);
|
return command_still_pending(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1344,14 +1356,16 @@ static struct command_result *json_waitsendpay(struct command *cmd,
|
|||||||
struct sha256 *rhash;
|
struct sha256 *rhash;
|
||||||
unsigned int *timeout;
|
unsigned int *timeout;
|
||||||
struct command_result *res;
|
struct command_result *res;
|
||||||
|
u64 *partid;
|
||||||
|
|
||||||
if (!param(cmd, buffer, params,
|
if (!param(cmd, buffer, params,
|
||||||
p_req("payment_hash", param_sha256, &rhash),
|
p_req("payment_hash", param_sha256, &rhash),
|
||||||
p_opt("timeout", param_number, &timeout),
|
p_opt("timeout", param_number, &timeout),
|
||||||
|
p_opt_def("partid", param_u64, &partid, 0),
|
||||||
NULL))
|
NULL))
|
||||||
return command_param_failed();
|
return command_param_failed();
|
||||||
|
|
||||||
res = wait_payment(cmd->ld, cmd, rhash, /* FIXME: Set partid! */0);
|
res = wait_payment(cmd->ld, cmd, rhash, *partid);
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
@ -2569,11 +2569,11 @@ def test_sendonion_rpc(node_factory):
|
|||||||
assert(e.error['data']['raw_message'] == "400f00000000000003e80000006c")
|
assert(e.error['data']['raw_message'] == "400f00000000000003e80000006c")
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
@unittest.skipIf(not DEVELOPER, "needs dev-disconnect, dev-no-htlc-timeout")
|
||||||
@unittest.skipIf(not EXPERIMENTAL_FEATURES, "needs partid support")
|
@unittest.skipIf(not EXPERIMENTAL_FEATURES, "needs partid support")
|
||||||
def test_partial_payment(node_factory, bitcoind, executor):
|
def test_partial_payment(node_factory, bitcoind, executor):
|
||||||
# We want to test two payments at the same time, before we send commit
|
# We want to test two payments at the same time, before we send commit
|
||||||
l1, l2, l3, l4 = node_factory.get_nodes(4, [{}] + [{'disconnect': ['=WIRE_UPDATE_ADD_HTLC-nocommit']}] * 2 + [{}])
|
l1, l2, l3, l4 = node_factory.get_nodes(4, [{}] + [{'disconnect': ['=WIRE_UPDATE_ADD_HTLC-nocommit'], 'dev-no-htlc-timeout': None}] * 2 + [{}])
|
||||||
|
|
||||||
# Two routes to l4: one via l2, and one via l3.
|
# Two routes to l4: one via l2, and one via l3.
|
||||||
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
|
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
|
||||||
@ -2621,8 +2621,17 @@ def test_partial_payment(node_factory, bitcoind, executor):
|
|||||||
l1.rpc.call('sendpay', [r124, inv['payment_hash'], None, 1000, inv['bolt11'], paysecret, 1])
|
l1.rpc.call('sendpay', [r124, inv['payment_hash'], None, 1000, inv['bolt11'], paysecret, 1])
|
||||||
l1.rpc.call('sendpay', [r134, inv['payment_hash'], None, 1000, inv['bolt11'], paysecret, 2])
|
l1.rpc.call('sendpay', [r134, inv['payment_hash'], None, 1000, inv['bolt11'], paysecret, 2])
|
||||||
|
|
||||||
|
# Make sure they've done the suppress-commitment thing before we unsuppress
|
||||||
|
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 fail because receiver doesn't do MPP.
|
||||||
l2.rpc.dev_reenable_commit(l4.info['id'])
|
l2.rpc.dev_reenable_commit(l4.info['id'])
|
||||||
l3.rpc.dev_reenable_commit(l4.info['id'])
|
l3.rpc.dev_reenable_commit(l4.info['id'])
|
||||||
|
|
||||||
# FIXME: waitsendpay needs a 'partid' field.
|
# 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})
|
||||||
|
Loading…
Reference in New Issue
Block a user