From a150b09665e82e4a332435f2b2e8b89ddff6d236 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 18 Feb 2020 10:30:58 +1030 Subject: [PATCH] wallet: Add new htlc column "localfailmsg" for outgoing htlcs. We're going to change our internal structure next, so this is preparation. We populate existing errors with temporary node failures, for simplicity. Signed-off-by: Rusty Russell --- devtools/sql-rewrite.py | 2 ++ lightningd/peer_htlcs.c | 11 +++++++---- wallet/db.c | 4 ++++ wallet/test/run-wallet.c | 14 ++++++++++---- wallet/wallet.c | 17 ++++++++++++++--- wallet/wallet.h | 6 ++++-- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/devtools/sql-rewrite.py b/devtools/sql-rewrite.py index 35aebf4c5..f49a23871 100755 --- a/devtools/sql-rewrite.py +++ b/devtools/sql-rewrite.py @@ -41,6 +41,8 @@ class Sqlite3Rewriter(Rewriter): r'BIGSERIAL': 'INTEGER', r'CURRENT_TIMESTAMP\(\)': "strftime('%s', 'now')", r'INSERT INTO[ \t]+(.*)[ \t]+ON CONFLICT.*DO NOTHING;': 'INSERT OR IGNORE INTO \\1;', + # Rewrite "decode('abcd', 'hex')" to become "x'abcd'" + r'decode\((.*),\s*[\'\"]hex[\'\"]\)': 'x\\1', } return self.rewrite_types(query, typemapping) diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index ee1b68575..2595fde63 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -76,7 +76,7 @@ static bool htlc_in_update_state(struct channel *channel, wallet_htlc_update(channel->peer->ld->wallet, hin->dbid, newstate, hin->preimage, - hin->failcode, hin->failonion); + hin->failcode, hin->failonion, NULL); hin->hstate = newstate; return true; @@ -91,7 +91,8 @@ static bool htlc_out_update_state(struct channel *channel, return false; wallet_htlc_update(channel->peer->ld->wallet, hout->dbid, newstate, - hout->preimage, hout->failcode, hout->failonion); + hout->preimage, hout->failcode, hout->failonion, + NULL); hout->hstate = newstate; return true; @@ -1100,7 +1101,8 @@ static void fulfill_our_htlc_out(struct channel *channel, struct htlc_out *hout, htlc_out_check(hout, __func__); wallet_htlc_update(ld->wallet, hout->dbid, hout->hstate, - hout->preimage, hout->failcode, hout->failonion); + hout->preimage, hout->failcode, hout->failonion, + NULL); /* Update channel stats */ wallet_channel_stats_incr_out_fulfilled(ld->wallet, channel->dbid, @@ -1281,7 +1283,8 @@ void onchain_failed_our_htlc(const struct channel *channel, hout->hstate = RCVD_REMOVE_HTLC; htlc_out_check(hout, __func__); wallet_htlc_update(ld->wallet, hout->dbid, hout->hstate, - hout->preimage, hout->failcode, hout->failonion); + hout->preimage, hout->failcode, hout->failonion, + NULL); if (hout->am_origin) { assert(why != NULL); diff --git a/wallet/db.c b/wallet/db.c index 610ebb717..3e06ce436 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -592,6 +592,10 @@ static struct migration dbmigrations[] = { NULL}, /* FIXME: Remove now-unused local_feerate_per_kw and remote_feerate_per_kw from channels */ {SQL("INSERT INTO vars (name, intval) VALUES ('data_version', 0);"), NULL}, + /* For outgoing HTLCs, we now keep a localmsg instead of a failcode. + * Turn anything in transition into a WIRE_TEMPORARY_NODE_FAILURE. */ + {SQL("ALTER TABLE channel_htlcs ADD localfailmsg BLOB;"), NULL}, + {SQL("UPDATE channel_htlcs SET localfailmsg=decode('2002', 'hex') WHERE malformed_onion != 0 AND direction = 1;"), NULL}, }; /* Leak tracking. */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 9578c6d38..c814b8d1f 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1316,15 +1316,18 @@ static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx) wallet_err = tal_free(wallet_err); /* Update */ - CHECK_MSG(transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, RCVD_ADD_HTLC, NULL, 0, NULL)), + CHECK_MSG(transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, RCVD_ADD_HTLC, NULL, 0, NULL, NULL)), "Update HTLC with null payment_key failed"); CHECK_MSG( - transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, &payment_key, 0, NULL)), + transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, &payment_key, 0, NULL, NULL)), "Update HTLC with payment_key failed"); onionreply = new_onionreply(tmpctx, tal_arrz(tmpctx, u8, 100)); CHECK_MSG( - transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, NULL, 0, onionreply)), - "Update HTLC with failreason failed"); + transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, NULL, 0, onionreply, NULL)), + "Update HTLC with failonion failed"); + CHECK_MSG( + transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, NULL, 0x2002, NULL, NULL)), + "Update HTLC with failcode failed"); CHECK_MSG(transaction_wrap(w->db, wallet_htlc_save_out(w, chan, &out)), tal_fmt(ctx, "Save htlc_out failed: %s", wallet_err)); @@ -1334,6 +1337,9 @@ static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx) "Saving two HTLCs with the same data must not succeed."); CHECK(wallet_err); wallet_err = tal_free(wallet_err); + CHECK_MSG( + transaction_wrap(w->db, wallet_htlc_update(w, out.dbid, SENT_ADD_ACK_REVOCATION, NULL, 0, NULL, tal_arrz(tmpctx, u8, 100))), + "Update outgoing HTLC with failmsg failed"); /* Attempt to load them from the DB again */ htlc_in_map_init(htlcs_in); diff --git a/wallet/wallet.c b/wallet/wallet.c index 8a918ec61..52efa640e 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1755,11 +1755,13 @@ void wallet_htlc_save_out(struct wallet *wallet, tal_free(stmt); } +/* input htlcs use failcode & failonion, output htlcs use failmsg & failonion */ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, const enum htlc_state new_state, const struct preimage *payment_key, enum onion_type failcode, - const struct onionreply *failonion) + const struct onionreply *failonion, + const u8 *failmsg) { struct db_stmt *stmt; @@ -1768,11 +1770,12 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, assert(htlc_dbid); stmt = db_prepare_v2( wallet->db, SQL("UPDATE channel_htlcs SET hstate=?, payment_key=?, " - "malformed_onion=?, failuremsg=? WHERE id=?")); + "malformed_onion=?, failuremsg=?, localfailmsg=?" + " WHERE id=?")); /* FIXME: htlc_state_in_db */ db_bind_int(stmt, 0, new_state); - db_bind_u64(stmt, 4, htlc_dbid); + db_bind_u64(stmt, 5, htlc_dbid); if (payment_key) db_bind_preimage(stmt, 1, payment_key); @@ -1780,11 +1783,17 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, db_bind_null(stmt, 1); db_bind_int(stmt, 2, failcode); + if (failonion) db_bind_onionreply(stmt, 3, failonion); else db_bind_null(stmt, 3); + if (failmsg) + db_bind_blob(stmt, 4, failmsg, tal_bytelen(failmsg)); + else + db_bind_null(stmt, 4); + db_exec_prepared_v2(take(stmt)); } @@ -1872,6 +1881,7 @@ static bool wallet_stmt2htlc_out(struct wallet *wallet, out->failonion = NULL; else out->failonion = db_column_onionreply(out, stmt, 8); + out->failcode = db_column_int_or_default(stmt, 9, 0); out->in = NULL; @@ -2002,6 +2012,7 @@ bool wallet_htlcs_load_out_for_channel(struct wallet *wallet, ", shared_secret" ", received_time" ", partid" + ", localfailmsg" " FROM channel_htlcs" " WHERE direction = ?" " AND channel_id = ?" diff --git a/wallet/wallet.h b/wallet/wallet.h index f2b2afc56..c8c0a065c 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -582,7 +582,8 @@ void wallet_htlc_save_out(struct wallet *wallet, * @payment_key: the `payment_key` which hashes to the `payment_hash`, * or NULL if unknown. * @failcode: the current failure code, or 0. - * @failonion: the current failure message (from peer), or NULL. + * @failonion: the current failure onion message (from peer), or NULL. + * @failmsg: the current local failure message, or NULL. * * Used to update the state of an HTLC, either a `struct htlc_in` or a * `struct htlc_out` and optionally set the `payment_key` should the @@ -592,7 +593,8 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, const enum htlc_state new_state, const struct preimage *payment_key, enum onion_type failcode, - const struct onionreply *failonion); + const struct onionreply *failonion, + const u8 *failmsg); /** * wallet_htlcs_load_in_for_channel - Load incoming HTLCs associated with chan from DB.