From 4271fc8652d7f46d2b4b682a0fe0fb8b67d2f3ca Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 6 Jul 2020 14:58:43 +0930 Subject: [PATCH] wallet: add explicit API for onchaind to register UTXOs. This is the only place outside the wallet code where we create a 'struct utxo', so it makes sense for us to move that logic inside the wallet. Signed-off-by: Rusty Russell --- lightningd/onchain_control.c | 38 +++++++++++----------- wallet/wallet.c | 63 ++++++++++++++++++++++++++++++++++++ wallet/wallet.h | 18 +++++++++++ 3 files changed, 101 insertions(+), 18 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index e4b767dca..83ac6468f 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -323,31 +323,33 @@ static void handle_irrevocably_resolved(struct channel *channel, const u8 *msg U */ static void onchain_add_utxo(struct channel *channel, const u8 *msg) { - struct utxo *u = tal(msg, struct utxo); struct chain_coin_mvt *mvt; u32 blockheight; - u->close_info = tal(u, struct unilateral_close_info); - - u->is_p2sh = true; - u->keyindex = 0; - u->status = output_state_available; - u->close_info->channel_id = channel->dbid; - u->close_info->peer_id = channel->peer->id; - u->spendheight = NULL; - u->scriptPubkey = NULL; + struct bitcoin_txid txid; + u32 outnum; + struct amount_sat amount; + struct pubkey *commitment_point; + u8 *scriptPubkey; if (!fromwire_onchain_add_utxo( - u, msg, &u->txid, &u->outnum, &u->close_info->commitment_point, - &u->amount, &blockheight, &u->scriptPubkey)) { - fatal("onchaind gave invalid add_utxo message: %s", tal_hex(msg, msg)); + tmpctx, msg, &txid, &outnum, &commitment_point, + &amount, &blockheight, &scriptPubkey)) { + log_broken(channel->log, + "onchaind gave invalid add_utxo message: %s", + tal_hex(msg, msg)); + return; } - u->blockheight = blockheight>0?&blockheight:NULL; - outpointfilter_add(channel->peer->ld->wallet->owned_outpoints, &u->txid, u->outnum); - wallet_add_utxo(channel->peer->ld->wallet, u, p2wpkh); + assert(blockheight); + outpointfilter_add(channel->peer->ld->wallet->owned_outpoints, + &txid, outnum); + wallet_add_onchaind_utxo(channel->peer->ld->wallet, + &txid, outnum, scriptPubkey, + blockheight, amount, channel, + commitment_point); - mvt = new_coin_deposit_sat(msg, "wallet", &u->txid, - u->outnum, blockheight, u->amount); + mvt = new_coin_deposit_sat(msg, "wallet", &txid, + outnum, blockheight, amount); notify_chain_mvt(channel->peer->ld, mvt); } diff --git a/wallet/wallet.c b/wallet/wallet.c index 1b25c5f59..326ebc1da 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -402,6 +402,69 @@ void wallet_confirm_utxos(struct wallet *w, const struct utxo **utxos) } } +bool wallet_add_onchaind_utxo(struct wallet *w, + const struct bitcoin_txid *txid, + u32 outnum, + const u8 *scriptpubkey, + u32 blockheight, + struct amount_sat amount, + const struct channel *channel, + /* NULL if option_static_remotekey */ + const struct pubkey *commitment_point) +{ + struct db_stmt *stmt; + + stmt = db_prepare_v2(w->db, SQL("SELECT * from outputs WHERE " + "prev_out_tx=? AND prev_out_index=?")); + db_bind_txid(stmt, 0, txid); + db_bind_int(stmt, 1, outnum); + db_query_prepared(stmt); + + /* If we get a result, that means a clash. */ + if (db_step(stmt)) { + tal_free(stmt); + return false; + } + tal_free(stmt); + + stmt = db_prepare_v2( + w->db, SQL("INSERT INTO outputs (" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", confirmation_height" + ", spend_height" + ", scriptpubkey" + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + db_bind_txid(stmt, 0, txid); + db_bind_int(stmt, 1, outnum); + db_bind_amount_sat(stmt, 2, &amount); + db_bind_int(stmt, 3, wallet_output_type_in_db(p2wpkh)); + db_bind_int(stmt, 4, output_state_available); + db_bind_int(stmt, 5, 0); + db_bind_u64(stmt, 6, channel->dbid); + db_bind_node_id(stmt, 7, &channel->peer->id); + if (commitment_point) + db_bind_pubkey(stmt, 8, commitment_point); + else + db_bind_null(stmt, 8); + + db_bind_int(stmt, 9, blockheight); + + /* spendheight */ + db_bind_null(stmt, 10); + db_bind_blob(stmt, 11, scriptpubkey, tal_bytelen(scriptpubkey)); + + db_exec_prepared_v2(take(stmt)); + return true; +} + static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, struct amount_sat sat, const u32 feerate_per_kw, diff --git a/wallet/wallet.h b/wallet/wallet.h index 8213184ee..3eef562a9 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -382,6 +382,24 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, struct utxo **wallet_get_unconfirmed_closeinfo_utxos(const tal_t *ctx, struct wallet *w); +/** + * wallet_add_onchaind_utxo - Add a UTXO with spending info from onchaind. + * + * Usually we add UTXOs by looking at transactions, but onchaind tells + * us about other UTXOs we can spend with some extra metadata. + * + * Returns false if we already have it in db (that's fine). + */ +bool wallet_add_onchaind_utxo(struct wallet *w, + const struct bitcoin_txid *txid, + u32 outnum, + const u8 *scriptpubkey, + u32 blockheight, + struct amount_sat amount, + const struct channel *chan, + /* NULL if option_static_remotekey */ + const struct pubkey *commitment_point); + /** wallet_utxo_get - Retrive a utxo. * * Returns a utxo, or NULL if not found.