Browse Source

pay: remove struct pay_command.

It's all in wallet_payment, which is persistent.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
02e05ba6ff
  1. 5
      lightningd/htlc_end.c
  2. 4
      lightningd/htlc_end.h
  3. 1
      lightningd/lightningd.c
  4. 3
      lightningd/lightningd.h
  5. 96
      lightningd/pay.c
  6. 5
      lightningd/peer_htlcs.c
  7. 1
      lightningd/peer_htlcs.h
  8. 1
      wallet/wallet.c

5
lightningd/htlc_end.c

@ -129,9 +129,6 @@ struct htlc_out *htlc_out_check(const struct htlc_out *hout,
return corrupt(hout, abortstr, "Both failed and succeeded"); return corrupt(hout, abortstr, "Both failed and succeeded");
else if (hout->cmd && hout->in) else if (hout->cmd && hout->in)
return corrupt(hout, abortstr, "Both local and forwarded"); return corrupt(hout, abortstr, "Both local and forwarded");
else if (!hout->in && !hout->pay_command)
return corrupt(hout, abortstr,
"Neither hout->in nor paycommand");
return cast_const(struct htlc_out *, hout); return cast_const(struct htlc_out *, hout);
} }
@ -143,7 +140,6 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
struct htlc_in *in, struct htlc_in *in,
struct pay_command *pc,
struct wallet_payment *payment, struct wallet_payment *payment,
struct command *cmd) struct command *cmd)
{ {
@ -168,7 +164,6 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
hout->preimage = NULL; hout->preimage = NULL;
hout->in = in; hout->in = in;
hout->pay_command = pc;
return htlc_out_check(hout, "new_htlc_out"); return htlc_out_check(hout, "new_htlc_out");
} }

4
lightningd/htlc_end.h

@ -79,9 +79,6 @@ struct htlc_out {
/* Otherwise, this MAY be non-null if there's a pay command waiting */ /* Otherwise, this MAY be non-null if there's a pay command waiting */
struct command *cmd; struct command *cmd;
/* Otherwise, payment command which created it. */
struct pay_command *pay_command;
/* Temporary payment store, so we can save everything in one go */ /* Temporary payment store, so we can save everything in one go */
struct wallet_payment *payment; struct wallet_payment *payment;
}; };
@ -139,7 +136,6 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
struct htlc_in *in, struct htlc_in *in,
struct pay_command *pc,
struct wallet_payment *payment, struct wallet_payment *payment,
struct command *cmd); struct command *cmd);

1
lightningd/lightningd.c

@ -57,7 +57,6 @@ static struct lightningd *new_lightningd(const tal_t *ctx,
ld->log = new_log(log_book, log_book, "lightningd(%u):", (int)getpid()); ld->log = new_log(log_book, log_book, "lightningd(%u):", (int)getpid());
ld->alias = NULL; ld->alias = NULL;
ld->rgb = NULL; ld->rgb = NULL;
list_head_init(&ld->pay_commands);
list_head_init(&ld->connects); list_head_init(&ld->connects);
ld->wireaddrs = tal_arr(ld, struct wireaddr, 0); ld->wireaddrs = tal_arr(ld, struct wireaddr, 0);
ld->portnum = DEFAULT_PORT; ld->portnum = DEFAULT_PORT;

3
lightningd/lightningd.h

@ -133,9 +133,6 @@ struct lightningd {
/* Maintained by invoices.c */ /* Maintained by invoices.c */
struct invoices *invoices; struct invoices *invoices;
/* Any outstanding "pay" commands. */
struct list_head pay_commands;
/* Transaction filter matching what we're interested in */ /* Transaction filter matching what we're interested in */
struct txfilter *owned_txfilter; struct txfilter *owned_txfilter;

96
lightningd/pay.c

@ -17,18 +17,6 @@
#include <lightningd/subd.h> #include <lightningd/subd.h>
#include <sodium/randombytes.h> #include <sodium/randombytes.h>
/* Outstanding "pay" commands. */
struct pay_command {
struct list_node list;
struct sha256 rhash;
u64 msatoshi;
const struct pubkey *ids;
/* Set if this is in progress. */
struct htlc_out *out;
/* Preimage if this succeeded. */
const struct preimage *rval;
};
static void json_pay_success(struct command *cmd, const struct preimage *rval) static void json_pay_success(struct command *cmd, const struct preimage *rval)
{ {
struct json_result *response; struct json_result *response;
@ -60,21 +48,17 @@ static void json_pay_failed(struct command *cmd,
void payment_succeeded(struct lightningd *ld, struct htlc_out *hout, void payment_succeeded(struct lightningd *ld, struct htlc_out *hout,
const struct preimage *rval) const struct preimage *rval)
{ {
assert(!hout->pay_command->rval);
wallet_payment_set_status(ld->wallet, &hout->payment_hash, wallet_payment_set_status(ld->wallet, &hout->payment_hash,
PAYMENT_COMPLETE, rval); PAYMENT_COMPLETE, rval);
hout->pay_command->rval = tal_dup(hout->pay_command,
struct preimage, rval);
/* Can be NULL if JSON RPC goes away. */ /* Can be NULL if JSON RPC goes away. */
if (hout->cmd) if (hout->cmd)
json_pay_success(hout->cmd, rval); json_pay_success(hout->cmd, rval);
hout->pay_command->out = NULL; hout->cmd = NULL;
} }
void payment_failed(struct lightningd *ld, const struct htlc_out *hout, void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
const char *localfail) const char *localfail)
{ {
struct pay_command *pc = hout->pay_command;
struct onionreply *reply; struct onionreply *reply;
enum onion_type failcode; enum onion_type failcode;
struct secret *path_secrets; struct secret *path_secrets;
@ -82,7 +66,6 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
wallet_payment_set_status(ld->wallet, &hout->payment_hash, wallet_payment_set_status(ld->wallet, &hout->payment_hash,
PAYMENT_FAILED, NULL); PAYMENT_FAILED, NULL);
pc->out = NULL;
/* This gives more details than a generic failure message */ /* This gives more details than a generic failure message */
if (localfail) { if (localfail) {
@ -95,7 +78,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
assert(!hout->failcode); assert(!hout->failcode);
path_secrets = wallet_payment_get_secrets(tmpctx, ld->wallet, path_secrets = wallet_payment_get_secrets(tmpctx, ld->wallet,
&hout->payment_hash); &hout->payment_hash);
reply = unwrap_onionreply(pc, path_secrets, tal_count(path_secrets), reply = unwrap_onionreply(tmpctx, path_secrets, tal_count(path_secrets),
hout->failuremsg); hout->failuremsg);
if (!reply) { if (!reply) {
log_info(hout->key.peer->log, log_info(hout->key.peer->log,
@ -128,29 +111,11 @@ static void remove_cmd_from_hout(struct command *cmd, struct htlc_out *hout)
hout->cmd = NULL; hout->cmd = NULL;
} }
static struct pay_command *find_pay_command(struct lightningd *ld,
const struct sha256 *rhash)
{
struct pay_command *pc;
list_for_each(&ld->pay_commands, pc, list) {
if (structeq(rhash, &pc->rhash))
return pc;
}
return NULL;
}
static void pay_command_destroyed(struct pay_command *pc)
{
list_del(&pc->list);
}
/* Returns true if it's still pending. */ /* Returns true if it's still pending. */
static bool send_payment(struct command *cmd, static bool send_payment(struct command *cmd,
const struct sha256 *rhash, const struct sha256 *rhash,
const struct route_hop *route) const struct route_hop *route)
{ {
struct pay_command *pc;
struct peer *peer; struct peer *peer;
const u8 *onion; const u8 *onion;
u8 sessionkey[32]; u8 sessionkey[32];
@ -164,6 +129,7 @@ static bool send_payment(struct command *cmd,
struct hop_data *hop_data = tal_arr(tmpctx, struct hop_data, n_hops); struct hop_data *hop_data = tal_arr(tmpctx, struct hop_data, n_hops);
struct pubkey *ids = tal_arr(tmpctx, struct pubkey, n_hops); struct pubkey *ids = tal_arr(tmpctx, struct pubkey, n_hops);
struct wallet_payment *payment = NULL; struct wallet_payment *payment = NULL;
struct htlc_out *hout;
/* Expiry for HTLCs is absolute. And add one to give some margin. */ /* Expiry for HTLCs is absolute. And add one to give some margin. */
base_expiry = get_block_height(cmd->ld->topology) + 1; base_expiry = get_block_height(cmd->ld->topology) + 1;
@ -187,37 +153,35 @@ static bool send_payment(struct command *cmd,
memset(&hop_data[i].channel_id, 0, sizeof(struct short_channel_id)); memset(&hop_data[i].channel_id, 0, sizeof(struct short_channel_id));
hop_data[i].amt_forward = route[i].amount; hop_data[i].amt_forward = route[i].amount;
pc = find_pay_command(cmd->ld, rhash); /* Now, do we already have a payment? */
if (pc) { payment = wallet_payment_by_hash(tmpctx, cmd->ld->wallet, rhash);
if (payment) {
log_debug(cmd->ld->log, "json_sendpay: found previous"); log_debug(cmd->ld->log, "json_sendpay: found previous");
if (pc->out) { if (payment->status == PAYMENT_PENDING) {
log_add(cmd->ld->log, "... still in progress"); log_add(cmd->ld->log, "... still in progress");
command_fail(cmd, "still in progress"); command_fail(cmd, "still in progress");
return false; return false;
} }
if (pc->rval) { if (payment->status == PAYMENT_COMPLETE) {
size_t old_nhops = tal_count(pc->ids);
log_add(cmd->ld->log, "... succeeded"); log_add(cmd->ld->log, "... succeeded");
/* Must match successful payment parameters. */ /* Must match successful payment parameters. */
if (pc->msatoshi != hop_data[n_hops-1].amt_forward) { if (payment->msatoshi != hop_data[n_hops-1].amt_forward) {
command_fail(cmd, command_fail(cmd,
"already succeeded with amount %" "already succeeded with amount %"
PRIu64, pc->msatoshi); PRIu64, payment->msatoshi);
return false; return false;
} }
if (!structeq(&pc->ids[old_nhops-1], &ids[n_hops-1])) { if (!structeq(&payment->destination, &ids[n_hops-1])) {
char *previd;
previd = pubkey_to_hexstr(cmd,
&pc->ids[old_nhops-1]);
command_fail(cmd, command_fail(cmd,
"already succeeded to %s", "already succeeded to %s",
previd); type_to_string(cmd, struct pubkey,
&payment->destination));
return false; return false;
} }
json_pay_success(cmd, pc->rval); json_pay_success(cmd, payment->payment_preimage);
return false; return false;
} }
/* FIXME: We can free failed ones... */ wallet_payment_delete(cmd->ld->wallet, rhash);
log_add(cmd->ld->log, "... retrying"); log_add(cmd->ld->log, "... retrying");
} }
@ -234,13 +198,7 @@ static bool send_payment(struct command *cmd,
sizeof(struct sha256), &path_secrets); sizeof(struct sha256), &path_secrets);
onion = serialize_onionpacket(cmd, packet); onion = serialize_onionpacket(cmd, packet);
if (pc) { /* We write this into db when HTLC is actually sent. */
pc->ids = tal_free(pc->ids);
} else {
pc = tal(cmd->ld, struct pay_command);
list_add_tail(&cmd->ld->pay_commands, &pc->list);
tal_add_destructor(pc, pay_command_destroyed);
payment = tal(tmpctx, struct wallet_payment); payment = tal(tmpctx, struct wallet_payment);
payment->id = 0; payment->id = 0;
payment->payment_hash = *rhash; payment->payment_hash = *rhash;
@ -250,25 +208,15 @@ static bool send_payment(struct command *cmd,
payment->timestamp = time_now().ts.tv_sec; payment->timestamp = time_now().ts.tv_sec;
payment->payment_preimage = NULL; payment->payment_preimage = NULL;
payment->path_secrets = tal_steal(payment, path_secrets); payment->path_secrets = tal_steal(payment, path_secrets);
}
pc->rhash = *rhash;
pc->rval = NULL;
pc->ids = tal_steal(pc, ids);
pc->msatoshi = route[n_hops-1].amount;
pc->out = NULL;
log_info(cmd->ld->log, "Sending %u over %zu hops to deliver %"PRIu64,
route[0].amount, n_hops, pc->msatoshi);
/* They're both children of ld, but on shutdown make sure we log_info(cmd->ld->log, "Sending %u over %zu hops to deliver %u",
* destroy the command before the pc, otherwise the route[0].amount, n_hops, route[n_hops-1].amount);
* remove_cmd_from_pc destructor causes a use-after-free */
tal_steal(pc, cmd);
/* Steals payment into hout */
failcode = send_htlc_out(peer, route[0].amount, failcode = send_htlc_out(peer, route[0].amount,
base_expiry + route[0].delay, base_expiry + route[0].delay,
rhash, onion, NULL, payment, pc, cmd, rhash, onion, NULL, payment, cmd,
&pc->out); &hout);
if (failcode) { if (failcode) {
command_fail(cmd, "first peer not ready: %s", command_fail(cmd, "first peer not ready: %s",
onion_type_name(failcode)); onion_type_name(failcode));
@ -276,7 +224,7 @@ static bool send_payment(struct command *cmd,
} }
/* If we fail, remove cmd ptr from htlc_out. */ /* If we fail, remove cmd ptr from htlc_out. */
tal_add_destructor2(cmd, remove_cmd_from_hout, pc->out); tal_add_destructor2(cmd, remove_cmd_from_hout, hout);
tal_free(tmpctx); tal_free(tmpctx);
return true; return true;

5
lightningd/peer_htlcs.c

@ -373,7 +373,6 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
struct htlc_in *in, struct htlc_in *in,
struct wallet_payment *payment, struct wallet_payment *payment,
struct pay_command *pc,
struct command *cmd, struct command *cmd,
struct htlc_out **houtp) struct htlc_out **houtp)
{ {
@ -395,7 +394,7 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv,
/* Make peer's daemon own it, catch if it dies. */ /* Make peer's daemon own it, catch if it dies. */
hout = new_htlc_out(out->owner, out, amount, cltv, hout = new_htlc_out(out->owner, out, amount, cltv,
payment_hash, onion_routing_packet, in, payment_hash, onion_routing_packet, in,
pc, payment, cmd); payment, cmd);
tal_add_destructor(hout, hout_subd_died); tal_add_destructor(hout, hout_subd_died);
msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash, msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash,
@ -487,7 +486,7 @@ static void forward_htlc(struct htlc_in *hin,
failcode = send_htlc_out(next, amt_to_forward, failcode = send_htlc_out(next, amt_to_forward,
outgoing_cltv_value, &hin->payment_hash, outgoing_cltv_value, &hin->payment_hash,
next_onion, hin, NULL, NULL, NULL, NULL); next_onion, hin, NULL, NULL, NULL);
if (!failcode) if (!failcode)
return; return;

1
lightningd/peer_htlcs.h

@ -40,7 +40,6 @@ enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
struct htlc_in *in, struct htlc_in *in,
struct wallet_payment *payment, struct wallet_payment *payment,
struct pay_command *pc,
struct command *cmd, struct command *cmd,
struct htlc_out **houtp); struct htlc_out **houtp);

1
wallet/wallet.c

@ -1056,7 +1056,6 @@ static bool wallet_stmt2htlc_out(const struct wallet_channel *channel,
* htlcs, will wire using origin_htlc_id */ * htlcs, will wire using origin_htlc_id */
out->in = NULL; out->in = NULL;
out->pay_command = NULL;
out->payment = NULL; out->payment = NULL;
return ok; return ok;

Loading…
Cancel
Save