mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 10:46:58 +01:00
utxo: Add blockheight and spendheight to outputs to track state
Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
7f00230657
commit
227dc36146
7 changed files with 64 additions and 13 deletions
|
@ -26,6 +26,12 @@ struct utxo {
|
|||
/* Optional unilateral close information, NULL if this is just
|
||||
* a HD key */
|
||||
struct unilateral_close_info *close_info;
|
||||
|
||||
/* NULL if we haven't seen it in a block, otherwise the block it's in */
|
||||
const int *blockheight;
|
||||
|
||||
/* NULL if not spent yet, otherwise, the block the spending transaction is in */
|
||||
const int *spendheight;
|
||||
};
|
||||
|
||||
void towire_utxo(u8 **pptr, const struct utxo *utxo);
|
||||
|
|
|
@ -77,7 +77,7 @@ static void filter_block_txs(struct chain_topology *topo, struct block *b)
|
|||
satoshi_owned = 0;
|
||||
if (txfilter_match(topo->bitcoind->ld->owned_txfilter, tx)) {
|
||||
wallet_extract_owned_outputs(topo->bitcoind->ld->wallet,
|
||||
tx, &satoshi_owned);
|
||||
tx, b, &satoshi_owned);
|
||||
}
|
||||
|
||||
/* We did spends first, in case that tells us to watch tx. */
|
||||
|
@ -350,17 +350,17 @@ static void updates_complete(struct chain_topology *topo)
|
|||
|
||||
static void add_tip(struct chain_topology *topo, struct block *b)
|
||||
{
|
||||
/* Only keep the transactions we care about. */
|
||||
filter_block_txs(topo, b);
|
||||
|
||||
block_map_add(&topo->block_map, b);
|
||||
|
||||
/* Attach to tip; b is now the tip. */
|
||||
assert(b->height == topo->tip->height + 1);
|
||||
b->prev = topo->tip;
|
||||
topo->tip->next = b;
|
||||
topo->tip = b;
|
||||
wallet_block_add(topo->wallet, b);
|
||||
|
||||
/* Only keep the transactions we care about. */
|
||||
filter_block_txs(topo, b);
|
||||
|
||||
block_map_add(&topo->block_map, b);
|
||||
}
|
||||
|
||||
static struct block *new_block(struct chain_topology *topo,
|
||||
|
|
|
@ -226,6 +226,8 @@ static void onchain_add_utxo(struct channel *channel, const u8 *msg)
|
|||
u->status = output_state_available;
|
||||
u->close_info->channel_id = channel->dbid;
|
||||
u->close_info->peer_id = channel->peer->id;
|
||||
u->blockheight = NULL;
|
||||
u->spendheight = NULL;
|
||||
|
||||
if (!fromwire_onchain_add_utxo(msg, &u->txid, &u->outnum,
|
||||
&u->close_info->commitment_point,
|
||||
|
@ -457,4 +459,3 @@ enum watch_result funding_spent(struct channel *channel,
|
|||
/* We keep watching until peer finally deleted, for reorgs. */
|
||||
return KEEP_WATCHING;
|
||||
}
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
|
|||
tal_hex(msg, resp));
|
||||
|
||||
/* Extract the change output and add it to the DB */
|
||||
wallet_extract_owned_outputs(ld->wallet, fundingtx, &change_satoshi);
|
||||
wallet_extract_owned_outputs(ld->wallet, fundingtx, NULL, &change_satoshi);
|
||||
|
||||
/* Send it out and watch for confirms. */
|
||||
broadcast_tx(ld->topology, channel, fundingtx, funding_broadcast_failed);
|
||||
|
|
|
@ -35,7 +35,18 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
|||
{
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
stmt = db_prepare(w->db, "INSERT INTO outputs (prev_out_tx, prev_out_index, value, type, status, keyindex, channel_id, peer_id, commitment_point) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
stmt = db_prepare(w->db, "INSERT INTO outputs ("
|
||||
"prev_out_tx, "
|
||||
"prev_out_index, "
|
||||
"value, "
|
||||
"type, "
|
||||
"status, "
|
||||
"keyindex, "
|
||||
"channel_id, "
|
||||
"peer_id, "
|
||||
"commitment_point, "
|
||||
"confirmation_height, "
|
||||
"spend_height) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
sqlite3_bind_blob(stmt, 1, &utxo->txid, sizeof(utxo->txid), SQLITE_TRANSIENT);
|
||||
sqlite3_bind_int(stmt, 2, utxo->outnum);
|
||||
sqlite3_bind_int64(stmt, 3, utxo->amount);
|
||||
|
@ -51,6 +62,19 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
|||
sqlite3_bind_null(stmt, 8);
|
||||
sqlite3_bind_null(stmt, 9);
|
||||
}
|
||||
|
||||
if (utxo->blockheight) {
|
||||
sqlite3_bind_int(stmt, 10, *utxo->blockheight);
|
||||
} else
|
||||
sqlite3_bind_null(stmt, 10);
|
||||
|
||||
if (utxo->spendheight)
|
||||
sqlite3_bind_int(stmt, 11, *utxo->spendheight);
|
||||
else
|
||||
sqlite3_bind_null(stmt, 11);
|
||||
|
||||
/* May fail if we already know about the tx, e.g., because
|
||||
* it's change or some internal tx. */
|
||||
return db_exec_prepared_mayfail(w->db, stmt);
|
||||
}
|
||||
|
||||
|
@ -61,6 +85,7 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
|||
*/
|
||||
static bool wallet_stmt2output(sqlite3_stmt *stmt, struct utxo *utxo)
|
||||
{
|
||||
int *blockheight, *spendheight;
|
||||
sqlite3_column_sha256_double(stmt, 0, &utxo->txid.shad);
|
||||
utxo->outnum = sqlite3_column_int(stmt, 1);
|
||||
utxo->amount = sqlite3_column_int64(stmt, 2);
|
||||
|
@ -76,6 +101,21 @@ static bool wallet_stmt2output(sqlite3_stmt *stmt, struct utxo *utxo)
|
|||
utxo->close_info = NULL;
|
||||
}
|
||||
|
||||
utxo->blockheight = NULL;
|
||||
utxo->spendheight = NULL;
|
||||
|
||||
if (sqlite3_column_type(stmt, 9) != SQLITE_NULL) {
|
||||
blockheight = tal(utxo, int);
|
||||
*blockheight = sqlite3_column_int(stmt, 9);
|
||||
utxo->blockheight = blockheight;
|
||||
}
|
||||
|
||||
if (sqlite3_column_type(stmt, 10) != SQLITE_NULL) {
|
||||
spendheight = tal(utxo, int);
|
||||
*spendheight = sqlite3_column_int(stmt, 10);
|
||||
utxo->spendheight = spendheight;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -110,7 +150,7 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum ou
|
|||
|
||||
sqlite3_stmt *stmt = db_prepare(
|
||||
w->db, "SELECT prev_out_tx, prev_out_index, value, type, status, keyindex, "
|
||||
"channel_id, peer_id, commitment_point "
|
||||
"channel_id, peer_id, commitment_point, confirmation_height, spend_height "
|
||||
"FROM outputs WHERE status=?1 OR ?1=255");
|
||||
sqlite3_bind_int(stmt, 1, state);
|
||||
|
||||
|
@ -942,7 +982,7 @@ void wallet_peer_delete(struct wallet *w, u64 peer_dbid)
|
|||
}
|
||||
|
||||
int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx,
|
||||
u64 *total_satoshi)
|
||||
const struct block *block, u64 *total_satoshi)
|
||||
{
|
||||
int num_utxos = 0;
|
||||
for (size_t output = 0; output < tal_count(tx->output); output++) {
|
||||
|
@ -962,6 +1002,10 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx,
|
|||
bitcoin_txid(tx, &utxo->txid);
|
||||
utxo->outnum = output;
|
||||
utxo->close_info = NULL;
|
||||
|
||||
utxo->blockheight = block?&block->height:NULL;
|
||||
utxo->spendheight = NULL;
|
||||
|
||||
log_debug(w->log, "Owning output %zu %"PRIu64" (%s) txid %s",
|
||||
output, tx->output[output].amount,
|
||||
is_p2sh ? "P2SH" : "SEGWIT",
|
||||
|
|
|
@ -279,7 +279,7 @@ u32 wallet_first_blocknum(struct wallet *w, u32 first_possible);
|
|||
* wallet_extract_owned_outputs - given a tx, extract all of our outputs
|
||||
*/
|
||||
int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx,
|
||||
u64 *total_satoshi);
|
||||
const struct block *block, u64 *total_satoshi);
|
||||
|
||||
/**
|
||||
* wallet_htlc_save_in - store an htlc_in in the database
|
||||
|
|
|
@ -58,7 +58,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
|
|||
* generated the hex tx, so this should always work */
|
||||
tx = bitcoin_tx_from_hex(withdraw, withdraw->hextx, strlen(withdraw->hextx));
|
||||
assert(tx != NULL);
|
||||
wallet_extract_owned_outputs(ld->wallet, tx, &change_satoshi);
|
||||
wallet_extract_owned_outputs(ld->wallet, tx, NULL, &change_satoshi);
|
||||
|
||||
/* Note normally, change_satoshi == withdraw->changesatoshi, but
|
||||
* not if we're actually making a payment to ourselves! */
|
||||
|
|
Loading…
Add table
Reference in a new issue