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. */ /* Preimage if this succeeded. */
const struct preimage *rval; const struct preimage *rval;
struct command *cmd; 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) 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 pay_command *pc = hout->pay_command;
struct onionreply *reply; struct onionreply *reply;
enum onion_type failcode; enum onion_type failcode;
struct secret *path_secrets;
const tal_t *tmpctx = tal_tmpctx(ld);
wallet_payment_set_status(ld->wallet, &hout->payment_hash, wallet_payment_set_status(ld->wallet, &hout->payment_hash,
PAYMENT_FAILED, NULL); 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 */ /* This gives more details than a generic failure message */
if (localfail) { if (localfail) {
json_pay_failed(pc, NULL, hout->failcode, localfail); json_pay_failed(pc, NULL, hout->failcode, localfail);
tal_free(tmpctx);
return; return;
} }
/* Must be remote fail. */ /* Must be remote fail. */
assert(!hout->failcode); assert(!hout->failcode);
reply = unwrap_onionreply(pc, pc->path_secrets, path_secrets = wallet_payment_get_secrets(tmpctx, ld->wallet,
tal_count(pc->path_secrets), &hout->payment_hash);
reply = unwrap_onionreply(pc, 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,
@ -118,6 +119,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
/* check_for_routing_failure(i, sender, failure_code); */ /* check_for_routing_failure(i, sender, failure_code); */
json_pay_failed(pc, NULL, failcode, "reply from remote"); 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 */ /* 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) { if (pc) {
pc->ids = tal_free(pc->ids); pc->ids = tal_free(pc->ids);
pc->path_secrets = tal_free(pc->path_secrets);
} else { } else {
pc = tal(cmd->ld, struct pay_command); pc = tal(cmd->ld, struct pay_command);
list_add_tail(&cmd->ld->pay_commands, &pc->list); 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->msatoshi = route[n_hops-1].amount;
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);
} }
pc->cmd = cmd; pc->cmd = cmd;
pc->rhash = *rhash; pc->rhash = *rhash;
pc->rval = NULL; pc->rval = NULL;
pc->ids = tal_steal(pc, ids); pc->ids = tal_steal(pc, ids);
pc->msatoshi = route[n_hops-1].amount; pc->msatoshi = route[n_hops-1].amount;
pc->path_secrets = tal_steal(pc, path_secrets);
pc->out = NULL; pc->out = NULL;
log_info(cmd->ld->log, "Sending %u over %zu hops to deliver %"PRIu64, 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;", "DROP TABLE temp_payments;",
/* We need to keep the preimage in case they ask to pay again. */ /* We need to keep the preimage in case they ask to pay again. */
"ALTER TABLE payments ADD COLUMN payment_preimage BLOB;", "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, NULL,
}; };
@ -533,6 +535,8 @@ struct secret *sqlite3_column_secrets(const tal_t *ctx,
/* Must fit exactly */ /* Must fit exactly */
assert(n * sizeof(struct secret) == sqlite3_column_bytes(stmt, col)); assert(n * sizeof(struct secret) == sqlite3_column_bytes(stmt, col));
if (n == 0)
return NULL;
secrets = tal_arr(ctx, struct secret, n); secrets = tal_arr(ctx, struct secret, n);
return memcpy(secrets, sqlite3_column_blob(stmt, col), tal_len(secrets)); 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); sqlite3_column_preimage(stmt, 6, payment->payment_preimage);
} else } else
payment->payment_preimage = NULL; payment->payment_preimage = NULL;
/* Can be NULL for old db! */
payment->path_secrets = sqlite3_column_secrets(payment, stmt, 7);
return payment; return payment;
} }
@ -1301,7 +1304,8 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet,
stmt = db_prepare(wallet->db, stmt = db_prepare(wallet->db,
"SELECT id, status, destination," "SELECT id, status, destination,"
"msatoshi, payment_hash, timestamp, payment_preimage " "msatoshi, payment_hash, timestamp, payment_preimage, "
"path_secrets "
"FROM payments " "FROM payments "
"WHERE payment_hash = ?"); "WHERE payment_hash = ?");
@ -1313,6 +1317,26 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet,
return payment; 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, void wallet_payment_set_status(struct wallet *wallet,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const enum wallet_payment_status newstatus, const enum wallet_payment_status newstatus,
@ -1349,7 +1373,8 @@ const struct wallet_payment **wallet_payment_list(const tal_t *ctx,
stmt = db_prepare( stmt = db_prepare(
wallet->db, wallet->db,
"SELECT id, status, destination, " "SELECT id, status, destination, "
"msatoshi , payment_hash, timestamp, payment_preimage " "msatoshi, payment_hash, timestamp, payment_preimage, "
"path_secrets "
"FROM payments;"); "FROM payments;");
for (int i = 0; sqlite3_step(stmt) == SQLITE_ROW; i++) { for (int i = 0; sqlite3_step(stmt) == SQLITE_ROW; i++) {

10
wallet/wallet.h

@ -90,6 +90,7 @@ struct wallet_payment {
u64 msatoshi; u64 msatoshi;
/* Iff PAYMENT_COMPLETE */ /* Iff PAYMENT_COMPLETE */
struct preimage *payment_preimage; 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 enum wallet_payment_status newstatus,
const struct preimage *preimage); 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 * wallet_payment_list - Retrieve a list of payments
*/ */

Loading…
Cancel
Save