#include "bitcoin/pullpush.h" #include "commit_tx.h" #include "db.h" #include "feechange.h" #include "gen_version.h" #include "htlc.h" #include "invoice.h" #include "lightningd.h" #include "log.h" #include "names.h" #include "netaddr.h" #include "pay.h" #include "peer_internal.h" #include "routing.h" #include "secrets.h" #include "utils.h" #include "wallet.h" #include #include #include #include #include #include #include #include #include #include #define DB_FILE "lightning.sqlite3" /* They don't use stdint types. */ #define PRIuSQLITE64 "llu" struct db { bool in_transaction; const char *err; sqlite3 *sql; }; static void close_db(struct db *db) { sqlite3_close(db->sql); } /* We want a string, not an 'unsigned char *' thanks! */ static const char *sqlite3_column_str(sqlite3_stmt *stmt, int iCol) { return cast_signed(const char *, sqlite3_column_text(stmt, iCol)); } #define SQL_U64(var) stringify(var)" BIGINT" /* Actually, an s64 */ #define SQL_U32(var) stringify(var)" INT" #define SQL_BOOL(var) stringify(var)" BOOLEAN" #define SQL_BLOB(var) stringify(var)" BLOB" #define SQL_PUBKEY(var) stringify(var)" CHAR(33)" #define SQL_PRIVKEY(var) stringify(var)" CHAR(32)" #define SQL_SIGNATURE(var) stringify(var)" CHAR(64)" #define SQL_TXID(var) stringify(var)" CHAR(32)" #define SQL_RHASH(var) stringify(var)" CHAR(32)" #define SQL_SHA256(var) stringify(var)" CHAR(32)" #define SQL_R(var) stringify(var)" CHAR(32)" /* STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE == 45*/ #define SQL_STATENAME(var) stringify(var)" VARCHAR(45)" #define SQL_INVLABEL(var) stringify(var)" VARCHAR("stringify(INVOICE_MAX_LABEL_LEN)")" /* 8 + 4 + (8 + 32) * (64 + 1) */ #define SHACHAIN_SIZE 2612 #define SQL_SHACHAIN(var) stringify(var)" CHAR("stringify(SHACHAIN_SIZE)")" /* FIXME: Should be fixed size. */ #define SQL_ROUTING(var) stringify(var)" BLOB" #define SQL_FAIL(var) stringify(var)" BLOB" #define TABLE(tablename, ...) \ "CREATE TABLE " #tablename " (" CPPMAGIC_JOIN(", ", __VA_ARGS__) ");" static const char *sql_bool(bool b) { /* SQL2003 says TRUE and FALSE are binary literal keywords. * sqlite3 barfs. */ return (b) ? "1" : "0"; } static bool PRINTF_FMT(3,4) db_exec(const char *caller, struct lightningd_state *dstate, const char *fmt, ...) { va_list ap; char *cmd, *errmsg; int err; if (dstate->db->in_transaction && dstate->db->err) return false; va_start(ap, fmt); cmd = tal_vfmt(dstate->db, fmt, ap); va_end(ap); err = sqlite3_exec(dstate->db->sql, cmd, NULL, NULL, &errmsg); if (err != SQLITE_OK) { tal_free(dstate->db->err); dstate->db->err = tal_fmt(dstate->db, "%s:%s:%s:%s", caller, sqlite3_errstr(err), cmd, errmsg); sqlite3_free(errmsg); tal_free(cmd); log_broken(dstate->base_log, "%s", dstate->db->err); return false; } tal_free(cmd); return true; } static char *sql_hex_or_null(const tal_t *ctx, const void *buf, size_t len) { char *r; if (!buf) return "NULL"; r = tal_arr(ctx, char, 3 + hex_str_size(len)); r[0] = 'x'; r[1] = '\''; hex_encode(buf, len, r+2, hex_str_size(len)); r[2+hex_str_size(len)-1] = '\''; r[2+hex_str_size(len)] = '\0'; return r; } static void from_sql_blob(sqlite3_stmt *stmt, int idx, void *p, size_t n) { if (sqlite3_column_bytes(stmt, idx) != n) fatal("db:wrong bytes %i not %zu", sqlite3_column_bytes(stmt, idx), n); memcpy(p, sqlite3_column_blob(stmt, idx), n); } static u8 *tal_sql_blob(const tal_t *ctx, sqlite3_stmt *stmt, int idx) { u8 *p; if (sqlite3_column_type(stmt, idx) == SQLITE_NULL) return NULL; p = tal_arr(ctx, u8, sqlite3_column_bytes(stmt, idx)); from_sql_blob(stmt, idx, p, tal_count(p)); return p; } static void pubkey_from_sql(sqlite3_stmt *stmt, int idx, struct pubkey *pk) { if (!pubkey_from_der(sqlite3_column_blob(stmt, idx), sqlite3_column_bytes(stmt, idx), pk)) fatal("db:bad pubkey length %i", sqlite3_column_bytes(stmt, idx)); } static void sha256_from_sql(sqlite3_stmt *stmt, int idx, struct sha256 *sha) { from_sql_blob(stmt, idx, sha, sizeof(*sha)); } static void sig_from_sql(sqlite3_stmt *stmt, int idx, secp256k1_ecdsa_signature *sig) { u8 compact[64]; from_sql_blob(stmt, idx, compact, sizeof(compact)); if (secp256k1_ecdsa_signature_parse_compact(secp256k1_ctx, sig, compact) != 1) fatal("db:bad signature blob"); } static char *sig_to_sql(const tal_t *ctx, const secp256k1_ecdsa_signature *sig) { u8 compact[64]; if (!sig) return sql_hex_or_null(ctx, NULL, 0); secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, compact, sig); return sql_hex_or_null(ctx, compact, sizeof(compact)); } static void db_load_wallet(struct lightningd_state *dstate) { int err; sqlite3_stmt *stmt; err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM wallet;", -1, &stmt, NULL); if (err != SQLITE_OK) fatal("db_load_wallet:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct privkey privkey; if (err != SQLITE_ROW) fatal("db_load_wallet:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); if (sqlite3_column_count(stmt) != 1) fatal("db_load_wallet:step gave %i cols, not 1", sqlite3_column_count(stmt)); from_sql_blob(stmt, 0, &privkey, sizeof(privkey)); if (!restore_wallet_address(dstate, &privkey)) fatal("db_load_wallet:bad privkey"); } err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("db_load_wallet:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); } void db_add_wallet_privkey(struct lightningd_state *dstate, const struct privkey *privkey) { char *ctx = tal_tmpctx(dstate); log_debug(dstate->base_log, "%s", __func__); if (!db_exec(__func__, dstate, "INSERT INTO wallet VALUES (x'%s');", tal_hexstr(ctx, privkey, sizeof(*privkey)))) fatal("db_add_wallet_privkey failed"); tal_free(ctx); } static void load_peer_secrets(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); const char *select; bool secrets_set = false; select = tal_fmt(ctx, "SELECT * FROM peer_secrets WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_secrets:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { if (err != SQLITE_ROW) fatal("load_peer_secrets:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (secrets_set) fatal("load_peer_secrets: two secrets for '%s'", select); peer_set_secrets_from_db(peer, sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1), sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2), sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3)); secrets_set = true; } if (!secrets_set) fatal("load_peer_secrets: no secrets for '%s'", select); tal_free(ctx); } static void load_peer_anchor(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); const char *select; bool anchor_set = false; select = tal_fmt(ctx, "SELECT * FROM anchors WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_anchor:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { if (err != SQLITE_ROW) fatal("load_peer_anchor:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (anchor_set) fatal("load_peer_anchor: two anchors for '%s'", select); from_sql_blob(stmt, 1, &peer->anchor.txid, sizeof(peer->anchor.txid)); peer->anchor.index = sqlite3_column_int64(stmt, 2); peer->anchor.satoshis = sqlite3_column_int64(stmt, 3); peer->anchor.ours = sqlite3_column_int(stmt, 6); peer_watch_anchor(peer, sqlite3_column_int(stmt, 4)); peer->anchor.min_depth = sqlite3_column_int(stmt, 5); anchor_set = true; } if (!anchor_set) fatal("load_peer_anchor: no anchor for '%s'", select); tal_free(ctx); } static void load_peer_anchor_input(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); const char *select; bool anchor_input_set = false; select = tal_fmt(ctx, "SELECT * FROM anchor_inputs WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_anchor_input:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { if (err != SQLITE_ROW) fatal("load_peer_anchor_input:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (anchor_input_set) fatal("load_peer_anchor_input: two inputs for '%s'", select); peer->anchor.input = tal(peer, struct anchor_input); from_sql_blob(stmt, 1, &peer->anchor.input->txid, sizeof(peer->anchor.input->txid)); peer->anchor.input->index = sqlite3_column_int(stmt, 2); peer->anchor.input->in_amount = sqlite3_column_int64(stmt, 3); peer->anchor.input->out_amount = sqlite3_column_int64(stmt, 4); pubkey_from_sql(stmt, 5, &peer->anchor.input->walletkey); anchor_input_set = true; } if (!anchor_input_set) fatal("load_peer_anchor_input: no inputs for '%s'", select); tal_free(ctx); } static void load_peer_visible_state(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); const char *select; bool visible_set = false; select = tal_fmt(ctx, "SELECT * FROM their_visible_state WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_visible_state:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { if (err != SQLITE_ROW) fatal("load_peer_visible_state:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (sqlite3_column_count(stmt) != 8) fatal("load_peer_visible_state:step gave %i cols, not 8", sqlite3_column_count(stmt)); if (visible_set) fatal("load_peer_visible_state: two states for %s", select); visible_set = true; peer->remote.offer_anchor = sqlite3_column_int(stmt, 1); pubkey_from_sql(stmt, 2, &peer->remote.commitkey); pubkey_from_sql(stmt, 3, &peer->remote.finalkey); peer->remote.locktime.locktime = sqlite3_column_int(stmt, 4); peer->remote.mindepth = sqlite3_column_int(stmt, 5); peer->remote.commit_fee_rate = sqlite3_column_int64(stmt, 6); sha256_from_sql(stmt, 7, &peer->remote.next_revocation_hash); log_debug(peer->log, "%s:next_revocation_hash=%s", __func__, tal_hexstr(ctx, &peer->remote.next_revocation_hash, sizeof(peer->remote.next_revocation_hash))); /* Now we can fill in anchor witnessscript. */ peer->anchor.witnessscript = bitcoin_redeem_2of2(peer, &peer->local.commitkey, &peer->remote.commitkey); } if (!visible_set) fatal("load_peer_visible_state: no result '%s'", select); err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("load_peer_visible_state:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); tal_free(ctx); } static void load_peer_commit_info(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); const char *select; select = tal_fmt(ctx, "SELECT * FROM commit_info WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_commit_info:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct commit_info **cip, *ci; if (err != SQLITE_ROW) fatal("load_peer_commit_info:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); /* peer "SQL_PUBKEY", side TEXT, commit_num INT, revocation_hash "SQL_SHA256", sig "SQL_SIGNATURE", xmit_order INT, prev_revocation_hash "SQL_SHA256", */ if (sqlite3_column_count(stmt) != 7) fatal("load_peer_commit_info:step gave %i cols, not 7", sqlite3_column_count(stmt)); if (streq(sqlite3_column_str(stmt, 1), "LOCAL")) cip = &peer->local.commit; else { if (!streq(sqlite3_column_str(stmt, 1), "REMOTE")) fatal("load_peer_commit_info:bad side %s", sqlite3_column_str(stmt, 1)); cip = &peer->remote.commit; /* This is a hack where we temporarily store their * previous revocation hash before we get their * revocation. */ if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { peer->their_prev_revocation_hash = tal(peer, struct sha256); sha256_from_sql(stmt, 6, peer->their_prev_revocation_hash); } } /* Do we already have this one? */ if (*cip) fatal("load_peer_commit_info:duplicate side %s", sqlite3_column_str(stmt, 1)); *cip = ci = new_commit_info(peer, sqlite3_column_int64(stmt, 2)); sha256_from_sql(stmt, 3, &ci->revocation_hash); ci->order = sqlite3_column_int64(stmt, 4); if (sqlite3_column_type(stmt, 5) == SQLITE_NULL) ci->sig = NULL; else { ci->sig = tal(ci, secp256k1_ecdsa_signature); sig_from_sql(stmt, 5, ci->sig); } /* Set once we have updated HTLCs. */ ci->cstate = NULL; ci->tx = NULL; } err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("load_peer_commit_info:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); tal_free(ctx); if (!peer->local.commit) fatal("load_peer_commit_info:no local commit info found"); if (!peer->remote.commit) fatal("load_peer_commit_info:no remote commit info found"); } /* Because their HTLCs are not ordered wrt to ours, we can go negative * and do normally-impossible things in intermediate states. So we * mangle cstate balances manually. */ static void apply_htlc(struct channel_state *cstate, const struct htlc *htlc, enum side side) { const char *sidestr = side_to_str(side); if (!htlc_has(htlc, HTLC_FLAG(side,HTLC_F_WAS_COMMITTED))) return; log_debug(htlc->peer->log, " %s committed", sidestr); force_add_htlc(cstate, htlc); if (!htlc_has(htlc, HTLC_FLAG(side, HTLC_F_COMMITTED))) { log_debug(htlc->peer->log, " %s %s", sidestr, htlc->r ? "resolved" : "failed"); if (htlc->r) force_fulfill_htlc(cstate, htlc); else force_fail_htlc(cstate, htlc); } } /* As we load the HTLCs, we apply them to get the final channel_state. * We also get the last used htlc id. * This is slow, but sure. */ static void load_peer_htlcs(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); const char *select; bool to_them_only, to_us_only; select = tal_fmt(ctx, "SELECT * FROM htlcs WHERE peer = x'%s' ORDER BY id;", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_htlcs:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); peer->local.commit->cstate = initial_cstate(peer->local.commit, peer->anchor.satoshis, peer->local.commit_fee_rate, peer->local.offer_anchor ? LOCAL : REMOTE); peer->remote.commit->cstate = initial_cstate(peer->remote.commit, peer->anchor.satoshis, peer->remote.commit_fee_rate, peer->local.offer_anchor ? LOCAL : REMOTE); /* We rebuild cstate by running *every* HTLC through. */ while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct htlc *htlc; struct sha256 rhash; enum htlc_state hstate; if (err != SQLITE_ROW) fatal("load_peer_htlcs:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (sqlite3_column_count(stmt) != 11) fatal("load_peer_htlcs:step gave %i cols, not 11", sqlite3_column_count(stmt)); sha256_from_sql(stmt, 5, &rhash); hstate = htlc_state_from_name(sqlite3_column_str(stmt, 2)); if (hstate == HTLC_STATE_INVALID) fatal("load_peer_htlcs:invalid state %s", sqlite3_column_str(stmt, 2)); htlc = peer_new_htlc(peer, sqlite3_column_int64(stmt, 1), sqlite3_column_int64(stmt, 3), &rhash, sqlite3_column_int64(stmt, 4), sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7), NULL, hstate); if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { htlc->r = tal(htlc, struct preimage); from_sql_blob(stmt, 6, htlc->r, sizeof(*htlc->r)); } if (sqlite3_column_type(stmt, 10) != SQLITE_NULL) { htlc->fail = tal_sql_blob(htlc, stmt, 10); } if (htlc->r && htlc->fail) fatal("%s HTLC %"PRIu64" has failed and fulfilled?", htlc_owner(htlc) == LOCAL ? "local" : "remote", htlc->id); log_debug(peer->log, "Loaded %s HTLC %"PRIu64" (%s)", htlc_owner(htlc) == LOCAL ? "local" : "remote", htlc->id, htlc_state_name(htlc->state)); if (htlc_owner(htlc) == LOCAL && htlc->id >= peer->htlc_id_counter) peer->htlc_id_counter = htlc->id + 1; /* Update cstate with this HTLC. */ apply_htlc(peer->local.commit->cstate, htlc, LOCAL); apply_htlc(peer->remote.commit->cstate, htlc, REMOTE); } err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("load_peer_htlcs:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); /* Now set any in-progress fee changes. */ select = tal_fmt(ctx, "SELECT * FROM feechanges WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_htlcs:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { enum feechange_state feechange_state; if (err != SQLITE_ROW) fatal("load_peer_htlcs:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (sqlite3_column_count(stmt) != 3) fatal("load_peer_htlcs:step gave %i cols, not 3", sqlite3_column_count(stmt)); feechange_state = feechange_state_from_name(sqlite3_column_str(stmt, 1)); if (feechange_state == FEECHANGE_STATE_INVALID) fatal("load_peer_htlcs:invalid feechange state %s", sqlite3_column_str(stmt, 1)); if (peer->feechanges[feechange_state]) fatal("load_peer_htlcs: second feechange in state %s", sqlite3_column_str(stmt, 1)); peer->feechanges[feechange_state] = new_feechange(peer, sqlite3_column_int64(stmt, 2), feechange_state); } err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("load_peer_htlcs:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (!balance_after_force(peer->local.commit->cstate) || !balance_after_force(peer->remote.commit->cstate)) fatal("load_peer_htlcs:channel didn't balance"); /* Update commit->tx and commit->map */ peer->local.commit->tx = create_commit_tx(peer->local.commit, peer, &peer->local.commit->revocation_hash, peer->local.commit->cstate, LOCAL, &to_them_only); bitcoin_txid(peer->local.commit->tx, &peer->local.commit->txid); peer->remote.commit->tx = create_commit_tx(peer->remote.commit, peer, &peer->remote.commit->revocation_hash, peer->remote.commit->cstate, REMOTE, &to_us_only); bitcoin_txid(peer->remote.commit->tx, &peer->remote.commit->txid); peer->remote.staging_cstate = copy_cstate(peer, peer->remote.commit->cstate); peer->local.staging_cstate = copy_cstate(peer, peer->local.commit->cstate); log_debug(peer->log, "Local staging: pay %u/%u fee %u/%u htlcs %u/%u", peer->local.staging_cstate->side[LOCAL].pay_msat, peer->local.staging_cstate->side[REMOTE].pay_msat, peer->local.staging_cstate->side[LOCAL].fee_msat, peer->local.staging_cstate->side[REMOTE].fee_msat, peer->local.staging_cstate->side[LOCAL].num_htlcs, peer->local.staging_cstate->side[REMOTE].num_htlcs); log_debug(peer->log, "Remote staging: pay %u/%u fee %u/%u htlcs %u/%u", peer->remote.staging_cstate->side[LOCAL].pay_msat, peer->remote.staging_cstate->side[REMOTE].pay_msat, peer->remote.staging_cstate->side[LOCAL].fee_msat, peer->remote.staging_cstate->side[REMOTE].fee_msat, peer->remote.staging_cstate->side[LOCAL].num_htlcs, peer->remote.staging_cstate->side[REMOTE].num_htlcs); tal_free(ctx); } /* FIXME: A real database person would do this in a single clause along * with loading the htlcs in the first place! */ static void connect_htlc_src(struct lightningd_state *dstate) { sqlite3 *sql = dstate->db->sql; int err; sqlite3_stmt *stmt; char *ctx = tal_tmpctx(dstate); const char *select; select = tal_fmt(ctx, "SELECT peer,id,state,src_peer,src_id FROM htlcs WHERE src_peer IS NOT NULL AND state <> 'RCVD_REMOVE_ACK_REVOCATION' AND state <> 'SENT_REMOVE_ACK_REVOCATION';"); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("connect_htlc_src:%s gave %s:%s", select, sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct pubkey id; struct peer *peer; struct htlc *htlc; enum htlc_state s; if (err != SQLITE_ROW) fatal("connect_htlc_src:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); pubkey_from_sql(stmt, 0, &id); peer = find_peer(dstate, &id); if (!peer) continue; s = htlc_state_from_name(sqlite3_column_str(stmt, 2)); if (s == HTLC_STATE_INVALID) fatal("connect_htlc_src:unknown state %s", sqlite3_column_str(stmt, 2)); htlc = htlc_get(&peer->htlcs, sqlite3_column_int64(stmt, 1), htlc_state_owner(s)); if (!htlc) fatal("connect_htlc_src:unknown htlc %"PRIuSQLITE64" state %s", sqlite3_column_int64(stmt, 1), sqlite3_column_str(stmt, 2)); pubkey_from_sql(stmt, 4, &id); peer = find_peer(dstate, &id); if (!peer) fatal("connect_htlc_src:unknown src peer %s", tal_hexstr(dstate, &id, sizeof(id))); /* Source must be a HTLC they offered. */ htlc->src = htlc_get(&peer->htlcs, sqlite3_column_int64(stmt, 4), REMOTE); if (!htlc->src) fatal("connect_htlc_src:unknown src htlc"); } err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("load_peer_htlcs:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); tal_free(ctx); } static const char *linearize_shachain(const tal_t *ctx, const struct shachain *shachain) { size_t i; u8 *p = tal_arr(ctx, u8, 0); const char *str; push_le64(shachain->min_index, push, &p); push_le32(shachain->num_valid, push, &p); for (i = 0; i < shachain->num_valid; i++) { push_le64(shachain->known[i].index, push, &p); push(&shachain->known[i].hash, sizeof(shachain->known[i].hash), &p); } for (i = shachain->num_valid; i < ARRAY_SIZE(shachain->known); i++) { static u8 zeroes[sizeof(shachain->known[0].hash)]; push_le64(0, push, &p); push(zeroes, sizeof(zeroes), &p); } assert(tal_count(p) == SHACHAIN_SIZE); str = tal_hex(ctx, p); tal_free(p); return str; } static bool delinearize_shachain(struct shachain *shachain, const void *data, size_t len) { size_t i; const u8 *p = data; shachain->min_index = pull_le64(&p, &len); shachain->num_valid = pull_le32(&p, &len); for (i = 0; i < ARRAY_SIZE(shachain->known); i++) { shachain->known[i].index = pull_le64(&p, &len); pull(&p, &len, &shachain->known[i].hash, sizeof(shachain->known[i].hash)); } return p && len == 0; } static void load_peer_shachain(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); bool shachain_found = false; const char *select; select = tal_fmt(ctx, "SELECT * FROM shachain WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_shachain:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { const char *hexstr; if (err != SQLITE_ROW) fatal("load_peer_shachain:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); /* shachain (peer "SQL_PUBKEY", shachain BINARY(%zu) */ if (sqlite3_column_count(stmt) != 2) fatal("load_peer_shachain:step gave %i cols, not 2", sqlite3_column_count(stmt)); if (shachain_found) fatal("load_peer_shachain:multiple shachains?"); hexstr = tal_hexstr(ctx, sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1)); if (!delinearize_shachain(&peer->their_preimages, sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1))) fatal("load_peer_shachain:invalid shachain %s", hexstr); shachain_found = true; } if (!shachain_found) fatal("load_peer_shachain:no shachain"); tal_free(ctx); } /* We may not have one, and that's OK. */ static void load_peer_closing(struct peer *peer) { int err; sqlite3_stmt *stmt; sqlite3 *sql = peer->dstate->db->sql; char *ctx = tal_tmpctx(peer); bool closing_found = false; const char *select; select = tal_fmt(ctx, "SELECT * FROM closing WHERE peer = x'%s';", pubkey_to_hexstr(ctx, peer->id)); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_closing:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { if (err != SQLITE_ROW) fatal("load_peer_closing:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); if (sqlite3_column_count(stmt) != 9) fatal("load_peer_closing:step gave %i cols, not 9", sqlite3_column_count(stmt)); if (closing_found) fatal("load_peer_closing:multiple closing?"); peer->closing.our_fee = sqlite3_column_int64(stmt, 1); peer->closing.their_fee = sqlite3_column_int64(stmt, 2); if (sqlite3_column_type(stmt, 3) == SQLITE_NULL) peer->closing.their_sig = NULL; else { peer->closing.their_sig = tal(peer, secp256k1_ecdsa_signature); sig_from_sql(stmt, 3, peer->closing.their_sig); } peer->closing.our_script = tal_sql_blob(peer, stmt, 4); peer->closing.their_script = tal_sql_blob(peer, stmt, 5); peer->closing.shutdown_order = sqlite3_column_int64(stmt, 6); peer->closing.closing_order = sqlite3_column_int64(stmt, 7); peer->closing.sigs_in = sqlite3_column_int64(stmt, 8); closing_found = true; } tal_free(ctx); } /* FIXME: much of this is redundant. */ static void restore_peer_local_visible_state(struct peer *peer) { assert(peer->local.offer_anchor == !peer->remote.offer_anchor); /* peer->local.commitkey and peer->local.finalkey set by * peer_set_secrets_from_db(). */ memcheck(&peer->local.commitkey, sizeof(peer->local.commitkey)); memcheck(&peer->local.finalkey, sizeof(peer->local.finalkey)); /* These set in new_peer */ memcheck(&peer->local.locktime, sizeof(peer->local.locktime)); memcheck(&peer->local.mindepth, sizeof(peer->local.mindepth)); /* This set in db_load_peers */ memcheck(&peer->local.commit_fee_rate, sizeof(peer->local.commit_fee_rate)); peer_get_revocation_hash(peer, peer->local.commit->commit_num + 1, &peer->local.next_revocation_hash); if (state_is_normal(peer->state)) peer->nc = add_connection(peer->dstate->rstate, &peer->dstate->id, peer->id, peer->dstate->config.fee_base, peer->dstate->config.fee_per_satoshi, peer->dstate->config.min_htlc_expiry, peer->dstate->config.min_htlc_expiry); peer->their_commitsigs = peer->local.commit->commit_num + 1; /* If they created anchor, they didn't send a sig for first commit */ if (!peer->anchor.ours) peer->their_commitsigs--; if (peer->local.commit->order + 1 > peer->order_counter) peer->order_counter = peer->local.commit->order + 1; if (peer->remote.commit->order + 1 > peer->order_counter) peer->order_counter = peer->remote.commit->order + 1; if (peer->closing.closing_order + 1 > peer->order_counter) peer->order_counter = peer->closing.closing_order + 1; if (peer->closing.shutdown_order + 1 > peer->order_counter) peer->order_counter = peer->closing.shutdown_order + 1; } static void db_load_peers(struct lightningd_state *dstate) { int err; sqlite3_stmt *stmt; struct peer *peer; err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM peers;", -1, &stmt, NULL); if (err != SQLITE_OK) fatal("db_load_peers:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { enum state state; struct log *l; struct pubkey id; const char *idstr; if (err != SQLITE_ROW) fatal("db_load_peers:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); if (sqlite3_column_count(stmt) != 4) fatal("db_load_peers:step gave %i cols, not 4", sqlite3_column_count(stmt)); state = name_to_state(sqlite3_column_str(stmt, 1)); if (state == STATE_MAX) fatal("db_load_peers:unknown state %s", sqlite3_column_str(stmt, 1)); pubkey_from_sql(stmt, 0, &id); idstr = pubkey_to_hexstr(dstate, &id); l = new_log(dstate, dstate->log_book, "%s:", idstr); tal_free(idstr); peer = new_peer(dstate, l, state, sqlite3_column_int(stmt, 2)); peer->htlc_id_counter = 0; peer->id = tal_dup(peer, struct pubkey, &id); peer->local.commit_fee_rate = sqlite3_column_int64(stmt, 3); peer->order_counter = 1; log_debug(peer->log, "%s:%s", __func__, state_name(peer->state)); } err = sqlite3_finalize(stmt); if (err != SQLITE_OK) fatal("db_load_peers:finalize gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); list_for_each(&dstate->peers, peer, list) { load_peer_secrets(peer); load_peer_closing(peer); peer->anchor.min_depth = 0; if (peer->state >= STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE && !state_is_error(peer->state)) { load_peer_anchor(peer); load_peer_visible_state(peer); load_peer_shachain(peer); load_peer_commit_info(peer); load_peer_htlcs(peer); restore_peer_local_visible_state(peer); } if (peer->local.offer_anchor) load_peer_anchor_input(peer); } connect_htlc_src(dstate); } static const char *pubkeys_to_hex(const tal_t *ctx, const struct pubkey *ids) { u8 *ders = tal_arr(ctx, u8, PUBKEY_DER_LEN * tal_count(ids)); size_t i; for (i = 0; i < tal_count(ids); i++) pubkey_to_der(ders + i * PUBKEY_DER_LEN, &ids[i]); return tal_hex(ctx, ders); } static struct pubkey *pubkeys_from_arr(const tal_t *ctx, const void *blob, size_t len) { struct pubkey *ids; size_t i; if (len % PUBKEY_DER_LEN) fatal("ids array bad length %zu", len); ids = tal_arr(ctx, struct pubkey, len / PUBKEY_DER_LEN); for (i = 0; i < tal_count(ids); i++) { if (!pubkey_from_der(blob, PUBKEY_DER_LEN, &ids[i])) fatal("ids array invalid %zu", i); blob = (const u8 *)blob + PUBKEY_DER_LEN; } return ids; } static void db_load_pay(struct lightningd_state *dstate) { int err; sqlite3_stmt *stmt; char *ctx = tal_tmpctx(dstate); err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM pay;", -1, &stmt, NULL); if (err != SQLITE_OK) fatal("db_load_pay:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct sha256 rhash; struct htlc *htlc; struct pubkey *peer_id; u64 htlc_id, msatoshi; struct pubkey *ids; struct preimage *r; void *fail; if (err != SQLITE_ROW) fatal("db_load_pay:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); if (sqlite3_column_count(stmt) != 7) fatal("db_load_pay:step gave %i cols, not 7", sqlite3_column_count(stmt)); sha256_from_sql(stmt, 0, &rhash); msatoshi = sqlite3_column_int64(stmt, 1); ids = pubkeys_from_arr(ctx, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2)); if (sqlite3_column_type(stmt, 3) == SQLITE_NULL) peer_id = NULL; else { peer_id = tal(ctx, struct pubkey); pubkey_from_sql(stmt, 3, peer_id); } htlc_id = sqlite3_column_int64(stmt, 4); if (sqlite3_column_type(stmt, 5) == SQLITE_NULL) r = NULL; else { r = tal(ctx, struct preimage); from_sql_blob(stmt, 5, r, sizeof(*r)); } fail = tal_sql_blob(ctx, stmt, 6); /* Exactly one of these must be set. */ if (!fail + !peer_id + !r != 2) fatal("db_load_pay: not exactly one set:" " fail=%p peer_id=%p r=%p", fail, peer_id, r); if (peer_id) { struct peer *peer = find_peer(dstate, peer_id); if (!peer) fatal("db_load_pay: unknown peer"); htlc = htlc_get(&peer->htlcs, htlc_id, LOCAL); if (!htlc) fatal("db_load_pay: unknown htlc"); } else htlc = NULL; if (!pay_add(dstate, &rhash, msatoshi, ids, htlc, fail, r)) fatal("db_load_pay: could not add pay"); } tal_free(ctx); } static void db_load_invoice(struct lightningd_state *dstate) { int err; sqlite3_stmt *stmt; char *ctx = tal_tmpctx(dstate); err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM invoice;", -1, &stmt, NULL); if (err != SQLITE_OK) fatal("db_load_invoice:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct preimage r; u64 msatoshi, paid_num; const char *label; if (err != SQLITE_ROW) fatal("db_load_invoice:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); if (sqlite3_column_count(stmt) != 4) fatal("db_load_invoice:step gave %i cols, not 4", sqlite3_column_count(stmt)); from_sql_blob(stmt, 0, &r, sizeof(r)); msatoshi = sqlite3_column_int64(stmt, 1); label = (const char *)sqlite3_column_text(stmt, 2); paid_num = sqlite3_column_int64(stmt, 3); invoice_add(dstate->invoices, &r, msatoshi, label, paid_num); } tal_free(ctx); } static void db_load_addresses(struct lightningd_state *dstate) { int err; sqlite3_stmt *stmt; sqlite3 *sql = dstate->db->sql; char *ctx = tal_tmpctx(dstate); const char *select; select = tal_fmt(ctx, "SELECT * FROM peer_address;"); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("load_peer_addresses:prepare gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { struct peer_address *addr; if (err != SQLITE_ROW) fatal("load_peer_addresses:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); addr = tal(dstate, struct peer_address); pubkey_from_sql(stmt, 0, &addr->id); if (!netaddr_from_blob(sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1), &addr->addr)) fatal("load_peer_addresses: unparsable addresses for '%s'", select); list_add_tail(&dstate->addresses, &addr->list); log_debug(dstate->base_log, "load_peer_addresses:%s", pubkey_to_hexstr(ctx, &addr->id)); } tal_free(ctx); } static void db_check_version(struct lightningd_state *dstate) { int err; sqlite3_stmt *stmt; sqlite3 *sql = dstate->db->sql; char *ctx = tal_tmpctx(dstate); const char *select; select = tal_fmt(ctx, "SELECT * FROM version;"); err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); if (err != SQLITE_OK) fatal("DATABASE NEEDS UPDATE. Can't access VERSION: %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { const char *ver; if (err != SQLITE_ROW) fatal("db_check_version:step gave %s:%s", sqlite3_errstr(err), sqlite3_errmsg(sql)); ver = sqlite3_column_str(stmt, 0); if (!streq(ver, VERSION)) { if (dstate->config.db_version_ignore) log_unusual(dstate->base_log, "DATABASE NEEDS UPDATE." " Version %s does not match %s", ver, VERSION); else fatal("DATABASE NEEDS UPDATE." " Version %s does not match %s", ver, VERSION); } } tal_free(ctx); } static void db_load(struct lightningd_state *dstate) { db_check_version(dstate); db_load_wallet(dstate); db_load_addresses(dstate); db_load_peers(dstate); db_load_pay(dstate); db_load_invoice(dstate); } void db_init(struct lightningd_state *dstate) { int err; bool created = false; if (SQLITE_VERSION_NUMBER != sqlite3_libversion_number()) fatal("SQLITE version mistmatch: compiled %u, now %u", SQLITE_VERSION_NUMBER, sqlite3_libversion_number()); dstate->db = tal(dstate, struct db); err = sqlite3_open_v2(DB_FILE, &dstate->db->sql, SQLITE_OPEN_READWRITE, NULL); if (err != SQLITE_OK) { log_unusual(dstate->base_log, "Error opening %s (%s), trying to create", DB_FILE, sqlite3_errstr(err)); err = sqlite3_open_v2(DB_FILE, &dstate->db->sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if (err != SQLITE_OK) fatal("failed creating %s: %s", DB_FILE, sqlite3_errstr(err)); created = true; } tal_add_destructor(dstate->db, close_db); dstate->db->in_transaction = false; dstate->db->err = NULL; if (!created) { db_load(dstate); return; } /* Set up tables. */ dstate->db->in_transaction = true; db_exec(__func__, dstate, "BEGIN IMMEDIATE;"); db_exec(__func__, dstate, TABLE(wallet, SQL_PRIVKEY(privkey)) TABLE(pay, SQL_RHASH(rhash), SQL_U64(msatoshi), SQL_BLOB(ids), SQL_PUBKEY(htlc_peer), SQL_U64(htlc_id), SQL_R(r), SQL_FAIL(fail), "PRIMARY KEY(rhash)") TABLE(invoice, SQL_R(r), SQL_U64(msatoshi), SQL_INVLABEL(label), SQL_U64(paid_num), "PRIMARY KEY(label)") TABLE(anchor_inputs, SQL_PUBKEY(peer), SQL_TXID(txid), SQL_U32(idx), SQL_U64(in_amount), SQL_U64(out_amount), SQL_PUBKEY(walletkey)) TABLE(anchors, SQL_PUBKEY(peer), SQL_TXID(txid), SQL_U32(idx), SQL_U64(amount), SQL_U32(ok_depth), SQL_U32(min_depth), SQL_BOOL(ours)) /* FIXME: state in key is overkill: just need side */ TABLE(htlcs, SQL_PUBKEY(peer), SQL_U64(id), SQL_STATENAME(state), SQL_U64(msatoshi), SQL_U32(expiry), SQL_RHASH(rhash), SQL_R(r), SQL_ROUTING(routing), SQL_PUBKEY(src_peer), SQL_U64(src_id), SQL_BLOB(fail), "PRIMARY KEY(peer, id, state)") TABLE(feechanges, SQL_PUBKEY(peer), SQL_STATENAME(state), SQL_U32(fee_rate), "PRIMARY KEY(peer,state)") TABLE(commit_info, SQL_PUBKEY(peer), SQL_U32(side), SQL_U64(commit_num), SQL_SHA256(revocation_hash), SQL_U64(xmit_order), SQL_SIGNATURE(sig), SQL_SHA256(prev_revocation_hash), "PRIMARY KEY(peer, side)") TABLE(shachain, SQL_PUBKEY(peer), SQL_SHACHAIN(shachain), "PRIMARY KEY(peer)") TABLE(their_visible_state, SQL_PUBKEY(peer), SQL_BOOL(offered_anchor), SQL_PUBKEY(commitkey), SQL_PUBKEY(finalkey), SQL_U32(locktime), SQL_U32(mindepth), SQL_U32(commit_fee_rate), SQL_SHA256(next_revocation_hash), "PRIMARY KEY(peer)") TABLE(their_commitments, SQL_PUBKEY(peer), SQL_SHA256(txid), SQL_U64(commit_num), "PRIMARY KEY(peer, txid)") TABLE(peer_secrets, SQL_PUBKEY(peer), SQL_PRIVKEY(commitkey), SQL_PRIVKEY(finalkey), SQL_SHA256(revocation_seed), "PRIMARY KEY(peer)") TABLE(peer_address, SQL_PUBKEY(peer), SQL_BLOB(addr), "PRIMARY KEY(peer)") TABLE(closing, SQL_PUBKEY(peer), SQL_U64(our_fee), SQL_U64(their_fee), SQL_SIGNATURE(their_sig), SQL_BLOB(our_script), SQL_BLOB(their_script), SQL_U64(shutdown_order), SQL_U64(closing_order), SQL_U64(sigs_in), "PRIMARY KEY(peer)") TABLE(peers, SQL_PUBKEY(peer), SQL_STATENAME(state), SQL_BOOL(offered_anchor), SQL_U32(our_feerate), "PRIMARY KEY(peer)") TABLE(version, "version VARCHAR(100)")); db_exec(__func__, dstate, "INSERT INTO version VALUES ('"VERSION"');"); db_exec(__func__, dstate, "COMMIT;"); dstate->db->in_transaction = false; if (dstate->db->err) { unlink(DB_FILE); fatal("%s", dstate->db->err); } } void db_set_anchor(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid; assert(peer->dstate->db->in_transaction); peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); db_exec(__func__, peer->dstate, "INSERT INTO anchors VALUES (x'%s', x'%s', %u, %"PRIu64", %i, %u, %s);", peerid, tal_hexstr(ctx, &peer->anchor.txid, sizeof(peer->anchor.txid)), peer->anchor.index, peer->anchor.satoshis, peer->anchor.ok_depth, peer->anchor.min_depth, sql_bool(peer->anchor.ours)); db_exec(__func__, peer->dstate, "INSERT INTO commit_info VALUES(x'%s', '%s', 0, x'%s', %"PRIi64", %s, NULL);", peerid, side_to_str(LOCAL), tal_hexstr(ctx, &peer->local.commit->revocation_hash, sizeof(peer->local.commit->revocation_hash)), peer->local.commit->order, sig_to_sql(ctx, peer->local.commit->sig)); db_exec(__func__, peer->dstate, "INSERT INTO commit_info VALUES(x'%s', '%s', 0, x'%s', %"PRIi64", %s, NULL);", peerid, side_to_str(REMOTE), tal_hexstr(ctx, &peer->remote.commit->revocation_hash, sizeof(peer->remote.commit->revocation_hash)), peer->remote.commit->order, sig_to_sql(ctx, peer->remote.commit->sig)); db_exec(__func__, peer->dstate, "INSERT INTO shachain VALUES (x'%s', x'%s');", peerid, linearize_shachain(ctx, &peer->their_preimages)); tal_free(ctx); } void db_set_visible_state(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "INSERT INTO their_visible_state VALUES (x'%s', %s, x'%s', x'%s', %u, %u, %"PRIu64", x'%s');", peerid, sql_bool(peer->remote.offer_anchor), pubkey_to_hexstr(ctx, &peer->remote.commitkey), pubkey_to_hexstr(ctx, &peer->remote.finalkey), peer->remote.locktime.locktime, peer->remote.mindepth, peer->remote.commit_fee_rate, tal_hexstr(ctx, &peer->remote.next_revocation_hash, sizeof(peer->remote.next_revocation_hash))); tal_free(ctx); } void db_update_next_revocation_hash(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s):%s", __func__, peerid, tal_hexstr(ctx, &peer->remote.next_revocation_hash, sizeof(peer->remote.next_revocation_hash))); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE their_visible_state SET next_revocation_hash=x'%s' WHERE peer=x'%s';", tal_hexstr(ctx, &peer->remote.next_revocation_hash, sizeof(peer->remote.next_revocation_hash)), peerid); tal_free(ctx); } void db_create_peer(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "INSERT INTO peers VALUES (x'%s', '%s', %s, %"PRIi64");", peerid, state_name(peer->state), sql_bool(peer->local.offer_anchor), peer->local.commit_fee_rate); db_exec(__func__, peer->dstate, "INSERT INTO peer_secrets VALUES (x'%s', %s);", peerid, peer_secrets_for_db(ctx, peer)); if (peer->local.offer_anchor) db_exec(__func__, peer->dstate, "INSERT INTO anchor_inputs VALUES" " (x'%s', x'%s', %u, %"PRIi64", %"PRIi64", x'%s');", peerid, tal_hexstr(ctx, &peer->anchor.input->txid, sizeof(peer->anchor.input->txid)), peer->anchor.input->index, peer->anchor.input->in_amount, peer->anchor.input->out_amount, pubkey_to_hexstr(ctx, &peer->anchor.input->walletkey)); tal_free(ctx); } void db_start_transaction(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(!peer->dstate->db->in_transaction); peer->dstate->db->in_transaction = true; peer->dstate->db->err = tal_free(peer->dstate->db->err); db_exec(__func__, peer->dstate, "BEGIN IMMEDIATE;"); tal_free(ctx); } void db_abort_transaction(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); peer->dstate->db->in_transaction = false; db_exec(__func__, peer->dstate, "ROLLBACK;"); tal_free(ctx); } const char *db_commit_transaction(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); if (!db_exec(__func__, peer->dstate, "COMMIT;")) db_abort_transaction(peer); else peer->dstate->db->in_transaction = false; tal_free(ctx); return peer->dstate->db->err; } void db_new_htlc(struct peer *peer, const struct htlc *htlc) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); if (htlc->src) { db_exec(__func__, peer->dstate, "INSERT INTO htlcs VALUES" " (x'%s', %"PRIu64", '%s', %"PRIu64", %u, x'%s', NULL, x'%s', x'%s', %"PRIu64", NULL);", pubkey_to_hexstr(ctx, peer->id), htlc->id, htlc_state_name(htlc->state), htlc->msatoshi, abs_locktime_to_blocks(&htlc->expiry), tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash)), tal_hex(ctx, htlc->routing), peerid, htlc->src->id); } else { db_exec(__func__, peer->dstate, "INSERT INTO htlcs VALUES" " (x'%s', %"PRIu64", '%s', %"PRIu64", %u, x'%s', NULL, x'%s', NULL, NULL, NULL);", peerid, htlc->id, htlc_state_name(htlc->state), htlc->msatoshi, abs_locktime_to_blocks(&htlc->expiry), tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash)), tal_hex(ctx, htlc->routing)); } tal_free(ctx); } void db_new_feechange(struct peer *peer, const struct feechange *feechange) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "INSERT INTO feechanges VALUES" " (x'%s', '%s', %"PRIu64");", peerid, feechange_state_name(feechange->state), feechange->fee_rate); tal_free(ctx); } void db_update_htlc_state(struct peer *peer, const struct htlc *htlc, enum htlc_state oldstate) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s): %"PRIu64" %s->%s", __func__, peerid, htlc->id, htlc_state_name(oldstate), htlc_state_name(htlc->state)); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE htlcs SET state='%s' WHERE peer=x'%s' AND id=%"PRIu64" AND state='%s';", htlc_state_name(htlc->state), peerid, htlc->id, htlc_state_name(oldstate)); tal_free(ctx); } void db_update_feechange_state(struct peer *peer, const struct feechange *f, enum feechange_state oldstate) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s): %s->%s", __func__, peerid, feechange_state_name(oldstate), feechange_state_name(f->state)); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE feechanges SET state='%s' WHERE peer=x'%s' AND state='%s';", feechange_state_name(f->state), peerid, feechange_state_name(oldstate)); tal_free(ctx); } void db_remove_feechange(struct peer *peer, const struct feechange *feechange, enum feechange_state oldstate) { const char *ctx = tal(peer, char); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "DELETE FROM feechanges WHERE peer=x'%s' AND state='%s';", peerid, feechange_state_name(oldstate)); tal_free(ctx); } void db_update_state(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE peers SET state='%s' WHERE peer=x'%s';", state_name(peer->state), peerid); tal_free(ctx); } void db_htlc_fulfilled(struct peer *peer, const struct htlc *htlc) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE htlcs SET r=x'%s' WHERE peer=x'%s' AND id=%"PRIu64" AND state='%s';", tal_hexstr(ctx, htlc->r, sizeof(*htlc->r)), peerid, htlc->id, htlc_state_name(htlc->state)); tal_free(ctx); } void db_htlc_failed(struct peer *peer, const struct htlc *htlc) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE htlcs SET fail=x'%s' WHERE peer=x'%s' AND id=%"PRIu64" AND state='%s';", tal_hexstr(ctx, htlc->fail, sizeof(*htlc->fail)), peerid, htlc->id, htlc_state_name(htlc->state)); tal_free(ctx); } void db_new_commit_info(struct peer *peer, enum side side, const struct sha256 *prev_rhash) { struct commit_info *ci; const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); if (side == LOCAL) { ci = peer->local.commit; } else { ci = peer->remote.commit; } db_exec(__func__, peer->dstate, "UPDATE commit_info SET commit_num=%"PRIu64", revocation_hash=x'%s', sig=%s, xmit_order=%"PRIi64", prev_revocation_hash=%s WHERE peer=x'%s' AND side='%s';", ci->commit_num, tal_hexstr(ctx, &ci->revocation_hash, sizeof(ci->revocation_hash)), sig_to_sql(ctx, ci->sig), ci->order, sql_hex_or_null(ctx, prev_rhash, sizeof(*prev_rhash)), peerid, side_to_str(side)); tal_free(ctx); } /* FIXME: Is this strictly necessary? */ void db_remove_their_prev_revocation_hash(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE commit_info SET prev_revocation_hash=NULL WHERE peer=x'%s' AND side='REMOTE' and prev_revocation_hash IS NOT NULL;", peerid); tal_free(ctx); } void db_save_shachain(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE shachain SET shachain=x'%s' WHERE peer=x'%s';", linearize_shachain(ctx, &peer->their_preimages), peerid); tal_free(ctx); } void db_add_commit_map(struct peer *peer, const struct sha256_double *txid, u64 commit_num) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s),commit_num=%"PRIu64, __func__, peerid, commit_num); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "INSERT INTO their_commitments VALUES (x'%s', x'%s', %"PRIu64");", peerid, tal_hexstr(ctx, txid, sizeof(*txid)), commit_num); tal_free(ctx); } /* FIXME: Clean out old ones! */ bool db_add_peer_address(struct lightningd_state *dstate, const struct peer_address *addr) { const tal_t *ctx = tal_tmpctx(dstate); bool ok; log_debug(dstate->base_log, "%s", __func__); assert(!dstate->db->in_transaction); ok = db_exec(__func__, dstate, "INSERT OR REPLACE INTO peer_address VALUES (x'%s', x'%s');", pubkey_to_hexstr(ctx, &addr->id), netaddr_to_hex(ctx, &addr->addr)); tal_free(ctx); return ok; } void db_forget_peer(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); size_t i; const char *const tables[] = { "anchors", "htlcs", "commit_info", "shachain", "their_visible_state", "their_commitments", "peer_secrets", "closing", "peers" }; log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->state == STATE_CLOSED); db_start_transaction(peer); for (i = 0; i < ARRAY_SIZE(tables); i++) { db_exec(__func__, peer->dstate, "DELETE from %s WHERE peer=x'%s';", tables[i], peerid); } if (db_commit_transaction(peer) != NULL) fatal("%s:db_commi_transaction failed", __func__); tal_free(ctx); } void db_begin_shutdown(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "INSERT INTO closing VALUES (x'%s', 0, 0, NULL, NULL, NULL, 0, 0, 0);", peerid); tal_free(ctx); } void db_set_our_closing_script(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE closing SET our_script=x'%s',shutdown_order=%"PRIu64" WHERE peer=x'%s';", tal_hex(ctx, peer->closing.our_script), peer->closing.shutdown_order, peerid); tal_free(ctx); } void db_set_their_closing_script(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(peer->dstate->db->in_transaction); db_exec(__func__, peer->dstate, "UPDATE closing SET their_script=x'%s' WHERE peer=x'%s';", tal_hex(ctx, peer->closing.their_script), peerid); tal_free(ctx); } /* For first time, we are in transaction to make it atomic with peer->state * update. Later calls are not. */ /* FIXME: make caller wrap in transaction. */ void db_update_our_closing(struct peer *peer) { const char *ctx = tal_tmpctx(peer); const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); db_exec(__func__, peer->dstate, "UPDATE closing SET our_fee=%"PRIu64", closing_order=%"PRIi64" WHERE peer=x'%s';", peer->closing.our_fee, peer->closing.closing_order, peerid); tal_free(ctx); } bool db_update_their_closing(struct peer *peer) { const char *ctx = tal_tmpctx(peer); bool ok; const char *peerid = pubkey_to_hexstr(ctx, peer->id); log_debug(peer->log, "%s(%s)", __func__, peerid); assert(!peer->dstate->db->in_transaction); ok = db_exec(__func__, peer->dstate, "UPDATE closing SET their_fee=%"PRIu64", their_sig=%s, sigs_in=%u WHERE peer=x'%s';", peer->closing.their_fee, sig_to_sql(ctx, peer->closing.their_sig), peer->closing.sigs_in, peerid); tal_free(ctx); return ok; } bool db_new_pay_command(struct lightningd_state *dstate, const struct sha256 *rhash, const struct pubkey *ids, u64 msatoshi, const struct htlc *htlc) { const tal_t *ctx = tal_tmpctx(dstate); bool ok; log_debug(dstate->base_log, "%s", __func__); log_add_struct(dstate->base_log, "(%s)", struct sha256, rhash); assert(!dstate->db->in_transaction); ok = db_exec(__func__, dstate, "INSERT INTO pay VALUES (x'%s', %"PRIu64", x'%s', x'%s', %"PRIu64", NULL, NULL);", tal_hexstr(ctx, rhash, sizeof(*rhash)), msatoshi, pubkeys_to_hex(ctx, ids), pubkey_to_hexstr(ctx, htlc->peer->id), htlc->id); tal_free(ctx); return ok; } bool db_replace_pay_command(struct lightningd_state *dstate, const struct sha256 *rhash, const struct pubkey *ids, u64 msatoshi, const struct htlc *htlc) { const tal_t *ctx = tal_tmpctx(dstate); bool ok; log_debug(dstate->base_log, "%s", __func__); log_add_struct(dstate->base_log, "(%s)", struct sha256, rhash); assert(!dstate->db->in_transaction); ok = db_exec(__func__, dstate, "UPDATE pay SET msatoshi=%"PRIu64", ids=x'%s', htlc_peer=x'%s', htlc_id=%"PRIu64", r=NULL, fail=NULL WHERE rhash=x'%s';", msatoshi, pubkeys_to_hex(ctx, ids), pubkey_to_hexstr(ctx, htlc->peer->id), htlc->id, tal_hexstr(ctx, rhash, sizeof(*rhash))); tal_free(ctx); return ok; } void db_complete_pay_command(struct lightningd_state *dstate, const struct htlc *htlc) { const tal_t *ctx = tal_tmpctx(dstate); log_debug(dstate->base_log, "%s", __func__); log_add_struct(dstate->base_log, "(%s)", struct sha256, &htlc->rhash); assert(dstate->db->in_transaction); if (htlc->r) db_exec(__func__, dstate, "UPDATE pay SET r=x'%s', htlc_peer=NULL WHERE rhash=x'%s';", tal_hexstr(ctx, htlc->r, sizeof(*htlc->r)), tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash))); else db_exec(__func__, dstate, "UPDATE pay SET fail=x'%s', htlc_peer=NULL WHERE rhash=x'%s';", tal_hex(ctx, htlc->fail), tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash))); tal_free(ctx); } bool db_new_invoice(struct lightningd_state *dstate, u64 msatoshi, const char *label, const struct preimage *r) { const tal_t *ctx = tal_tmpctx(dstate); bool ok; log_debug(dstate->base_log, "%s", __func__); assert(!dstate->db->in_transaction); /* Insert label as hex; suspect injection attacks. */ ok = db_exec(__func__, dstate, "INSERT INTO invoice VALUES (x'%s', %"PRIu64", x'%s', %s);", tal_hexstr(ctx, r, sizeof(*r)), msatoshi, tal_hexstr(ctx, label, strlen(label)), sql_bool(false)); tal_free(ctx); return ok; } void db_resolve_invoice(struct lightningd_state *dstate, const char *label, u64 paid_num) { const tal_t *ctx = tal_tmpctx(dstate); log_debug(dstate->base_log, "%s", __func__); assert(dstate->db->in_transaction); db_exec(__func__, dstate, "UPDATE invoice SET paid_num=%"PRIu64" WHERE label=x'%s';", paid_num, tal_hexstr(ctx, label, strlen(label))); tal_free(ctx); } bool db_remove_invoice(struct lightningd_state *dstate, const char *label) { const tal_t *ctx = tal_tmpctx(dstate); bool ok; log_debug(dstate->base_log, "%s", __func__); assert(!dstate->db->in_transaction); ok = db_exec(__func__, dstate, "DELETE FROM invoice WHERE label=x'%s';", tal_hexstr(ctx, label, strlen(label))); tal_free(ctx); return ok; }