From 2cbe5b65c7efc4cb8efe046b6cb25cc434e0efbb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 18 Jan 2018 06:59:49 +1030 Subject: [PATCH] wallet: add preimage to db. We should be saving this, as it's our proof of payment. Also, we return it if they try to pay again. Signed-off-by: Rusty Russell --- lightningd/pay.c | 11 +++++++++-- wallet/db.c | 2 ++ wallet/test/run-wallet.c | 9 ++++++++- wallet/wallet.c | 22 +++++++++++++++++++--- wallet/wallet.h | 5 ++++- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lightningd/pay.c b/lightningd/pay.c index 09a95a7b8..84f598445 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -68,7 +68,8 @@ void payment_succeeded(struct lightningd *ld, struct htlc_out *hout, const struct preimage *rval) { assert(!hout->pay_command->rval); - wallet_payment_set_status(ld->wallet, &hout->payment_hash, PAYMENT_COMPLETE); + wallet_payment_set_status(ld->wallet, &hout->payment_hash, + PAYMENT_COMPLETE, rval); hout->pay_command->rval = tal_dup(hout->pay_command, struct preimage, rval); json_pay_success(hout->pay_command->cmd, rval); @@ -82,7 +83,8 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, struct onionreply *reply; enum onion_type failcode; - wallet_payment_set_status(ld->wallet, &hout->payment_hash, PAYMENT_FAILED); + wallet_payment_set_status(ld->wallet, &hout->payment_hash, + PAYMENT_FAILED, NULL); /* This gives more details than a generic failure message */ if (localfail) { @@ -248,6 +250,7 @@ static bool send_payment(struct command *cmd, payment->status = PAYMENT_PENDING; payment->msatoshi = route[n_hops-1].amount; payment->timestamp = time_now().ts.tv_sec; + payment->payment_preimage = NULL; } pc->cmd = cmd; pc->rhash = *rhash; @@ -514,6 +517,10 @@ static void json_listpayments(struct command *cmd, const char *buffer, json_add_string(response, "status", "failed"); break; } + if (t->payment_preimage) + json_add_hex(response, "payment_preimage", + t->payment_preimage, + sizeof(*t->payment_preimage)); json_object_end(response); } diff --git a/wallet/db.c b/wallet/db.c index b45d97a8a..20edf1af8 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -173,6 +173,8 @@ char *dbmigrations[] = { ");", "INSERT INTO payments SELECT id, timestamp, status, payment_hash, destination, msatoshi FROM temp_payments WHERE direction=1;", "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;", NULL, }; diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index f24867b0c..a53b0578f 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -15,6 +15,7 @@ static void db_log_(struct log *log, enum log_level level, const char *fmt, ...) #include #include +#include #include #include #include @@ -557,6 +558,7 @@ static bool test_payment_crud(const tal_t *ctx) t.id = 0; t.msatoshi = 100; t.status = PAYMENT_PENDING; + t.payment_preimage = NULL; memset(&t.payment_hash, 1, sizeof(t.payment_hash)); db_begin_transaction(w->db); @@ -568,15 +570,20 @@ static bool test_payment_crud(const tal_t *ctx) CHECK(t2->status == t.status); CHECK(pubkey_cmp(&t2->destination, &t.destination) == 0); CHECK(t2->msatoshi == t.msatoshi); + CHECK(!t2->payment_preimage); t.status = PAYMENT_COMPLETE; - wallet_payment_set_status(w, &t.payment_hash, t.status); + t.payment_preimage = tal(w, struct preimage); + memset(t.payment_preimage, 2, sizeof(*t.payment_preimage)); + wallet_payment_set_status(w, &t.payment_hash, t.status, + t.payment_preimage); t2 = wallet_payment_by_hash(ctx, w, &t.payment_hash); CHECK(t2 != NULL); CHECK(t2->id == t.id); CHECK(t2->status == t.status); CHECK(pubkey_cmp(&t2->destination, &t.destination) == 0); CHECK(t2->msatoshi == t.msatoshi); + CHECK(structeq(t.payment_preimage, t2->payment_preimage)); db_commit_transaction(w->db); return true; diff --git a/wallet/wallet.c b/wallet/wallet.c index be404887c..b8f3b377c 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1284,6 +1284,11 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx, sqlite3_column_sha256(stmt, 4, &payment->payment_hash); payment->timestamp = sqlite3_column_int(stmt, 5); + if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { + payment->payment_preimage = tal(payment, struct preimage); + sqlite3_column_preimage(stmt, 6, payment->payment_preimage); + } else + payment->payment_preimage = NULL; return payment; } @@ -1296,7 +1301,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 " + "msatoshi, payment_hash, timestamp, payment_preimage " "FROM payments " "WHERE payment_hash = ?"); @@ -1310,7 +1315,8 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, void wallet_payment_set_status(struct wallet *wallet, const struct sha256 *payment_hash, - const enum wallet_payment_status newstatus) + const enum wallet_payment_status newstatus, + const struct preimage *preimage) { sqlite3_stmt *stmt; @@ -1321,6 +1327,16 @@ void wallet_payment_set_status(struct wallet *wallet, sqlite3_bind_int(stmt, 1, newstatus); sqlite3_bind_sha256(stmt, 2, payment_hash); db_exec_prepared(wallet->db, stmt); + + if (preimage) { + stmt = db_prepare(wallet->db, + "UPDATE payments SET payment_preimage=? " + "WHERE payment_hash=?"); + + sqlite3_bind_preimage(stmt, 1, preimage); + sqlite3_bind_sha256(stmt, 2, payment_hash); + db_exec_prepared(wallet->db, stmt); + } } const struct wallet_payment **wallet_payment_list(const tal_t *ctx, @@ -1333,7 +1349,7 @@ const struct wallet_payment **wallet_payment_list(const tal_t *ctx, stmt = db_prepare( wallet->db, "SELECT id, status, destination, " - "msatoshi , payment_hash, timestamp " + "msatoshi , payment_hash, timestamp, payment_preimage " "FROM payments;"); for (int i = 0; sqlite3_step(stmt) == SQLITE_ROW; i++) { diff --git a/wallet/wallet.h b/wallet/wallet.h index f05beca9d..24d370e5e 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -88,6 +88,8 @@ struct wallet_payment { enum wallet_payment_status status; struct pubkey destination; u64 msatoshi; + /* Iff PAYMENT_COMPLETE */ + struct preimage *payment_preimage; }; /** @@ -551,7 +553,8 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, */ void wallet_payment_set_status(struct wallet *wallet, const struct sha256 *payment_hash, - const enum wallet_payment_status newstatus); + const enum wallet_payment_status newstatus, + const struct preimage *preimage); /** * wallet_payment_list - Retrieve a list of payments