Browse Source

wallet: add path_secrets to payment table.

We need these to decode any returned errors.

We remove it from struct pay_command too, and load directly from db
when we need it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
559010f525
  1. 15
      lightningd/pay.c
  2. 4
      wallet/db.c
  3. 29
      wallet/wallet.c
  4. 10
      wallet/wallet.h

15
lightningd/pay.c

@ -28,9 +28,6 @@ struct pay_command {
/* Preimage if this succeeded. */
const struct preimage *rval;
struct command *cmd;
/* Remember all shared secrets, so we can unwrap an eventual failure */
struct secret *path_secrets;
};
static void json_pay_success(struct command *cmd, const struct preimage *rval)
@ -82,6 +79,8 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
struct pay_command *pc = hout->pay_command;
struct onionreply *reply;
enum onion_type failcode;
struct secret *path_secrets;
const tal_t *tmpctx = tal_tmpctx(ld);
wallet_payment_set_status(ld->wallet, &hout->payment_hash,
PAYMENT_FAILED, NULL);
@ -89,13 +88,15 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
/* This gives more details than a generic failure message */
if (localfail) {
json_pay_failed(pc, NULL, hout->failcode, localfail);
tal_free(tmpctx);
return;
}
/* Must be remote fail. */
assert(!hout->failcode);
reply = unwrap_onionreply(pc, pc->path_secrets,
tal_count(pc->path_secrets),
path_secrets = wallet_payment_get_secrets(tmpctx, ld->wallet,
&hout->payment_hash);
reply = unwrap_onionreply(pc, path_secrets, tal_count(path_secrets),
hout->failuremsg);
if (!reply) {
log_info(hout->key.peer->log,
@ -118,6 +119,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
/* check_for_routing_failure(i, sender, failure_code); */
json_pay_failed(pc, NULL, failcode, "reply from remote");
tal_free(tmpctx);
}
/* When JSON RPC goes away, cmd is freed: detach from any running paycommand */
@ -237,7 +239,6 @@ static bool send_payment(struct command *cmd,
if (pc) {
pc->ids = tal_free(pc->ids);
pc->path_secrets = tal_free(pc->path_secrets);
} else {
pc = tal(cmd->ld, struct pay_command);
list_add_tail(&cmd->ld->pay_commands, &pc->list);
@ -251,13 +252,13 @@ static bool send_payment(struct command *cmd,
payment->msatoshi = route[n_hops-1].amount;
payment->timestamp = time_now().ts.tv_sec;
payment->payment_preimage = NULL;
payment->path_secrets = tal_steal(payment, path_secrets);
}
pc->cmd = cmd;
pc->rhash = *rhash;
pc->rval = NULL;
pc->ids = tal_steal(pc, ids);
pc->msatoshi = route[n_hops-1].amount;
pc->path_secrets = tal_steal(pc, path_secrets);
pc->out = NULL;
log_info(cmd->ld->log, "Sending %u over %zu hops to deliver %"PRIu64,

4
wallet/db.c

@ -175,6 +175,8 @@ char *dbmigrations[] = {
"DROP TABLE temp_payments;",
/* We need to keep the preimage in case they ask to pay again. */
"ALTER TABLE payments ADD COLUMN payment_preimage BLOB;",
/* We need to keep the shared secrets to decode error returns. */
"ALTER TABLE payments ADD COLUMN path_secrets BLOB;",
NULL,
};
@ -533,6 +535,8 @@ struct secret *sqlite3_column_secrets(const tal_t *ctx,
/* Must fit exactly */
assert(n * sizeof(struct secret) == sqlite3_column_bytes(stmt, col));
if (n == 0)
return NULL;
secrets = tal_arr(ctx, struct secret, n);
return memcpy(secrets, sqlite3_column_blob(stmt, col), tal_len(secrets));
}

29
wallet/wallet.c

@ -1289,6 +1289,9 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx,
sqlite3_column_preimage(stmt, 6, payment->payment_preimage);
} else
payment->payment_preimage = NULL;
/* Can be NULL for old db! */
payment->path_secrets = sqlite3_column_secrets(payment, stmt, 7);
return payment;
}
@ -1301,7 +1304,8 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet,
stmt = db_prepare(wallet->db,
"SELECT id, status, destination,"
"msatoshi, payment_hash, timestamp, payment_preimage "
"msatoshi, payment_hash, timestamp, payment_preimage, "
"path_secrets "
"FROM payments "
"WHERE payment_hash = ?");
@ -1313,6 +1317,26 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet,
return payment;
}
struct secret *wallet_payment_get_secrets(const tal_t *ctx,
struct wallet *wallet,
const struct sha256 *payment_hash)
{
sqlite3_stmt *stmt;
struct secret *path_secrets = NULL;
stmt = db_prepare(wallet->db,
"SELECT path_secrets "
"FROM payments "
"WHERE payment_hash = ?");
sqlite3_bind_sha256(stmt, 1, payment_hash);
if (sqlite3_step(stmt) == SQLITE_ROW) {
path_secrets = sqlite3_column_secrets(ctx, stmt, 0);
}
sqlite3_finalize(stmt);
return path_secrets;
}
void wallet_payment_set_status(struct wallet *wallet,
const struct sha256 *payment_hash,
const enum wallet_payment_status newstatus,
@ -1349,7 +1373,8 @@ const struct wallet_payment **wallet_payment_list(const tal_t *ctx,
stmt = db_prepare(
wallet->db,
"SELECT id, status, destination, "
"msatoshi , payment_hash, timestamp, payment_preimage "
"msatoshi, payment_hash, timestamp, payment_preimage, "
"path_secrets "
"FROM payments;");
for (int i = 0; sqlite3_step(stmt) == SQLITE_ROW; i++) {

10
wallet/wallet.h

@ -90,6 +90,7 @@ struct wallet_payment {
u64 msatoshi;
/* Iff PAYMENT_COMPLETE */
struct preimage *payment_preimage;
struct secret *path_secrets;
};
/**
@ -556,6 +557,15 @@ void wallet_payment_set_status(struct wallet *wallet,
const enum wallet_payment_status newstatus,
const struct preimage *preimage);
/**
* wallet_payment_get_secrets - Get the secrets array for a given `payment_hash`
*
* Returns a tal_array: can return NULL for old dbs.
*/
struct secret *wallet_payment_get_secrets(const tal_t *ctx,
struct wallet *wallet,
const struct sha256 *payment_hash);
/**
* wallet_payment_list - Retrieve a list of payments
*/

Loading…
Cancel
Save