mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
pay: Save nodes and channels used on route to payment.
This commit is contained in:
parent
b255d82ae2
commit
299b280f78
@ -131,6 +131,7 @@ static bool send_payment(struct command *cmd,
|
||||
struct pubkey *ids = tal_arr(tmpctx, struct pubkey, n_hops);
|
||||
struct wallet_payment *payment = NULL;
|
||||
struct htlc_out *hout;
|
||||
struct short_channel_id *channels;
|
||||
|
||||
/* Expiry for HTLCs is absolute. And add one to give some margin. */
|
||||
base_expiry = get_block_height(cmd->ld->topology) + 1;
|
||||
@ -213,6 +214,11 @@ static bool send_payment(struct command *cmd,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy channels used along the route. */
|
||||
channels = tal_arr(tmpctx, struct short_channel_id, n_hops);
|
||||
for (i = 0; i < n_hops; ++i)
|
||||
channels[i] = route[i].channel_id;
|
||||
|
||||
/* If hout fails, payment should be freed too. */
|
||||
payment = tal(hout, struct wallet_payment);
|
||||
payment->id = 0;
|
||||
@ -223,6 +229,8 @@ static bool send_payment(struct command *cmd,
|
||||
payment->timestamp = time_now().ts.tv_sec;
|
||||
payment->payment_preimage = NULL;
|
||||
payment->path_secrets = tal_steal(payment, path_secrets);
|
||||
payment->route_nodes = tal_steal(payment, ids);
|
||||
payment->route_channels = tal_steal(payment, channels);
|
||||
|
||||
/* We write this into db when HTLC is actually sent. */
|
||||
wallet_payment_setup(cmd->ld->wallet, payment);
|
||||
|
102
wallet/db.c
102
wallet/db.c
@ -183,6 +183,12 @@ char *dbmigrations[] = {
|
||||
"UPDATE invoices"
|
||||
" SET paid_timestamp = strftime('%s', 'now')"
|
||||
" WHERE state = 1;",
|
||||
/* We need to keep the route node pubkeys and short channel ids to
|
||||
* correctly mark routing failures. We separate short channel ids
|
||||
* because we cannot safely save them as blobs due to byteorder
|
||||
* concerns. */
|
||||
"ALTER TABLE payments ADD COLUMN route_nodes BLOB;",
|
||||
"ALTER TABLE payments ADD COLUMN route_channels TEXT;",
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -454,6 +460,56 @@ bool sqlite3_column_short_channel_id(sqlite3_stmt *stmt, int col,
|
||||
size_t sourcelen = sqlite3_column_bytes(stmt, col);
|
||||
return short_channel_id_from_str(source, sourcelen, dest);
|
||||
}
|
||||
bool sqlite3_bind_short_channel_id_array(sqlite3_stmt *stmt, int col,
|
||||
const struct short_channel_id *id)
|
||||
{
|
||||
u8 *ser;
|
||||
size_t num;
|
||||
size_t i;
|
||||
|
||||
/* Handle nulls early. */
|
||||
if (!id) {
|
||||
sqlite3_bind_null(stmt, col);
|
||||
return true;
|
||||
}
|
||||
|
||||
ser = tal_arr(NULL, u8, 0);
|
||||
num = tal_count(id);
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
towire_short_channel_id(&ser, &id[i]);
|
||||
|
||||
sqlite3_bind_blob(stmt, col, ser, tal_len(ser), SQLITE_TRANSIENT);
|
||||
|
||||
tal_free(ser);
|
||||
return true;
|
||||
}
|
||||
struct short_channel_id *
|
||||
sqlite3_column_short_channel_id_array(const tal_t *ctx,
|
||||
sqlite3_stmt *stmt, int col)
|
||||
{
|
||||
const u8 *ser;
|
||||
size_t len;
|
||||
struct short_channel_id *ret;
|
||||
size_t n;
|
||||
|
||||
/* Handle nulls early. */
|
||||
if (sqlite3_column_type(stmt, col) == SQLITE_NULL)
|
||||
return NULL;
|
||||
|
||||
ser = sqlite3_column_blob(stmt, col);
|
||||
len = sqlite3_column_bytes(stmt, col);
|
||||
ret = tal_arr(ctx, struct short_channel_id, 0);
|
||||
n = 0;
|
||||
|
||||
while (len != 0) {
|
||||
tal_resize(&ret, n + 1);
|
||||
fromwire_short_channel_id(&ser, &len, &ret[n]);
|
||||
++n;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool sqlite3_bind_tx(sqlite3_stmt *stmt, int col, const struct bitcoin_tx *tx)
|
||||
{
|
||||
@ -503,6 +559,52 @@ bool sqlite3_bind_pubkey(sqlite3_stmt *stmt, int col, const struct pubkey *pk)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sqlite3_bind_pubkey_array(sqlite3_stmt *stmt, int col,
|
||||
const struct pubkey *pks)
|
||||
{
|
||||
size_t n;
|
||||
size_t i;
|
||||
u8 *ders;
|
||||
|
||||
if (!pks) {
|
||||
sqlite3_bind_null(stmt, col);
|
||||
return true;
|
||||
}
|
||||
|
||||
n = tal_count(pks);
|
||||
ders = tal_arr(NULL, u8, n * PUBKEY_DER_LEN);
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
pubkey_to_der(&ders[i * PUBKEY_DER_LEN], &pks[i]);
|
||||
sqlite3_bind_blob(stmt, col, ders, tal_len(ders), SQLITE_TRANSIENT);
|
||||
|
||||
tal_free(ders);
|
||||
return true;
|
||||
}
|
||||
struct pubkey *sqlite3_column_pubkey_array(const tal_t *ctx,
|
||||
sqlite3_stmt *stmt, int col)
|
||||
{
|
||||
size_t i;
|
||||
size_t n;
|
||||
struct pubkey *ret;
|
||||
const u8 *ders;
|
||||
|
||||
if (sqlite3_column_type(stmt, col) == SQLITE_NULL)
|
||||
return NULL;
|
||||
|
||||
n = sqlite3_column_bytes(stmt, col) / PUBKEY_DER_LEN;
|
||||
assert(n * PUBKEY_DER_LEN == sqlite3_column_bytes(stmt, col));
|
||||
ret = tal_arr(ctx, struct pubkey, n);
|
||||
ders = sqlite3_column_blob(stmt, col);
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!pubkey_from_der(&ders[i * PUBKEY_DER_LEN], PUBKEY_DER_LEN, &ret[i]))
|
||||
return tal_free(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool sqlite3_column_preimage(sqlite3_stmt *stmt, int col, struct preimage *dest)
|
||||
{
|
||||
assert(sqlite3_column_bytes(stmt, col) == sizeof(struct preimage));
|
||||
|
10
wallet/db.h
10
wallet/db.h
@ -117,6 +117,11 @@ bool sqlite3_bind_short_channel_id(sqlite3_stmt *stmt, int col,
|
||||
const struct short_channel_id *id);
|
||||
bool sqlite3_column_short_channel_id(sqlite3_stmt *stmt, int col,
|
||||
struct short_channel_id *dest);
|
||||
bool sqlite3_bind_short_channel_id_array(sqlite3_stmt *stmt, int col,
|
||||
const struct short_channel_id *id);
|
||||
struct short_channel_id *
|
||||
sqlite3_column_short_channel_id_array(const tal_t *ctx,
|
||||
sqlite3_stmt *stmt, int col);
|
||||
bool sqlite3_bind_tx(sqlite3_stmt *stmt, int col, const struct bitcoin_tx *tx);
|
||||
struct bitcoin_tx *sqlite3_column_tx(const tal_t *ctx, sqlite3_stmt *stmt,
|
||||
int col);
|
||||
@ -126,6 +131,11 @@ bool sqlite3_column_signature(sqlite3_stmt *stmt, int col, secp256k1_ecdsa_signa
|
||||
bool sqlite3_column_pubkey(sqlite3_stmt *stmt, int col, struct pubkey *dest);
|
||||
bool sqlite3_bind_pubkey(sqlite3_stmt *stmt, int col, const struct pubkey *pk);
|
||||
|
||||
bool sqlite3_bind_pubkey_array(sqlite3_stmt *stmt, int col,
|
||||
const struct pubkey *pks);
|
||||
struct pubkey *sqlite3_column_pubkey_array(const tal_t *ctx,
|
||||
sqlite3_stmt *stmt, int col);
|
||||
|
||||
bool sqlite3_column_preimage(sqlite3_stmt *stmt, int col, struct preimage *dest);
|
||||
bool sqlite3_bind_preimage(sqlite3_stmt *stmt, int col, const struct preimage *p);
|
||||
|
||||
|
@ -1295,8 +1295,10 @@ void wallet_payment_store(struct wallet *wallet,
|
||||
" destination,"
|
||||
" msatoshi,"
|
||||
" timestamp,"
|
||||
" path_secrets"
|
||||
") VALUES (?, ?, ?, ?, ?, ?);");
|
||||
" path_secrets,"
|
||||
" route_nodes,"
|
||||
" route_channels"
|
||||
") VALUES (?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
|
||||
sqlite3_bind_int(stmt, 1, payment->status);
|
||||
sqlite3_bind_sha256(stmt, 2, &payment->payment_hash);
|
||||
@ -1306,6 +1308,9 @@ void wallet_payment_store(struct wallet *wallet,
|
||||
sqlite3_bind_blob(stmt, 6, payment->path_secrets,
|
||||
tal_len(payment->path_secrets),
|
||||
SQLITE_TRANSIENT);
|
||||
sqlite3_bind_pubkey_array(stmt, 7, payment->route_nodes);
|
||||
sqlite3_bind_short_channel_id_array(stmt, 8,
|
||||
payment->route_channels);
|
||||
|
||||
db_exec_prepared(wallet->db, stmt);
|
||||
|
||||
@ -1353,6 +1358,11 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx,
|
||||
|
||||
/* Can be NULL for old db! */
|
||||
payment->path_secrets = sqlite3_column_secrets(payment, stmt, 7);
|
||||
|
||||
payment->route_nodes = sqlite3_column_pubkey_array(payment, stmt, 8);
|
||||
payment->route_channels
|
||||
= sqlite3_column_short_channel_id_array(payment, stmt, 9);
|
||||
|
||||
return payment;
|
||||
}
|
||||
|
||||
@ -1371,7 +1381,7 @@ 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, "
|
||||
"path_secrets "
|
||||
"path_secrets, route_nodes, route_channels "
|
||||
"FROM payments "
|
||||
"WHERE payment_hash = ?");
|
||||
|
||||
@ -1463,7 +1473,7 @@ wallet_payment_list(const tal_t *ctx,
|
||||
wallet->db,
|
||||
"SELECT id, status, destination, "
|
||||
"msatoshi, payment_hash, timestamp, payment_preimage, "
|
||||
"path_secrets "
|
||||
"path_secrets, route_nodes, route_channels "
|
||||
"FROM payments;");
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,10 @@ struct wallet_payment {
|
||||
u64 msatoshi;
|
||||
/* If and only if PAYMENT_COMPLETE */
|
||||
struct preimage *payment_preimage;
|
||||
/* Needed for recovering from routing failures. */
|
||||
struct secret *path_secrets;
|
||||
struct pubkey *route_nodes;
|
||||
struct short_channel_id *route_channels;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user