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.