ido: garbage collect tracker entries of mempool txs that never confirm
Stamp mempool tracker entries with the negative of the highest known block height instead of a fixed -1 sentinel, and trim on abs(height) so entries whose tx is invalidated before confirming (e.g. by a double spend) age out after TRACKER_MAX_BLOCK_DEPTH like confirmed ones. The height is still replaced with the real one once the tx confirms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7f46b1b4b7
commit
b1df63c6c4
2 changed files with 21 additions and 8 deletions
|
|
@ -903,8 +903,11 @@ async fn txchain_trim_tracker(
|
|||
pool: &SqlitePool,
|
||||
current_block_height: i64,
|
||||
) -> Result<()> {
|
||||
// A negative height marks a mempool entry stamped with the negative of the
|
||||
// highest known block height when it was indexed (see index_mempool), so
|
||||
// abs(height) is the entry's reference height in both cases.
|
||||
sqlx::query(
|
||||
"DELETE FROM ido_txchain_tracker_map AS t0 WHERE t0.height < ? AND t0.height >= 0 AND NOT EXISTS (SELECT 1 FROM ido t1 WHERE t1.txchain_head = t0.txchain_id)",
|
||||
"DELETE FROM ido_txchain_tracker_map AS t0 WHERE abs(t0.height) < ? AND NOT EXISTS (SELECT 1 FROM ido t1 WHERE t1.txchain_head = t0.txchain_id)",
|
||||
)
|
||||
.bind(current_block_height - TRACKER_MAX_BLOCK_DEPTH)
|
||||
.execute(pool)
|
||||
|
|
@ -2288,17 +2291,20 @@ pub async fn index_block(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Sentinel block height for txs indexed from the mempool. txchain_trim_tracker
|
||||
// never trims tracker entries with a negative height; the height is replaced
|
||||
// with the real one once the tx confirms in a block.
|
||||
const MEMPOOL_BLOCK_HEIGHT: i64 = -1;
|
||||
|
||||
pub async fn index_mempool(
|
||||
network: Option<Network>,
|
||||
pool: &SqlitePool,
|
||||
sorted_txs: &[Transaction],
|
||||
highest_known_block_height: u64,
|
||||
) -> Result<()> {
|
||||
index_txs(network, pool, sorted_txs, MEMPOOL_BLOCK_HEIGHT)
|
||||
// Txs indexed from the mempool are stamped with the negative of the
|
||||
// highest known block height, so txchain_trim_tracker can garbage collect
|
||||
// entries that never confirm (e.g. invalidated by a double spend) once
|
||||
// they pass TRACKER_MAX_BLOCK_DEPTH. The height is replaced with the real
|
||||
// (positive) one once the tx confirms in a block. max(1) avoids storing 0,
|
||||
// which would be indistinguishable from a confirmed height.
|
||||
let mempool_height = -(highest_known_block_height.max(1) as i64);
|
||||
index_txs(network, pool, sorted_txs, mempool_height)
|
||||
.await
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,13 @@ pub async fn update_mempool(
|
|||
// ido updates
|
||||
let ido_electrum = electrum.clone();
|
||||
|
||||
// highest known block height; mempool tracker entries are stamped with its
|
||||
// negative so ido's txchain_trim_tracker can age them out (see index_mempool)
|
||||
let tip_electrum = electrum.clone();
|
||||
let (_, tip_height) =
|
||||
tokio::task::spawn_blocking(move || electrum_get_tip(&tip_electrum.lock().unwrap()))
|
||||
.await??;
|
||||
|
||||
// filter txs already in an ido txchain
|
||||
let mut ido_to_add = Vec::new();
|
||||
for txid in ido_txs {
|
||||
|
|
@ -219,7 +226,7 @@ pub async fn update_mempool(
|
|||
|
||||
// an ido txchain can have several unconfirmed txs in flight; index parents first
|
||||
let txs_to_add = ttor_sorted_kahn(txs_to_add);
|
||||
db::ido::index_mempool(network, &db.ido_w, &txs_to_add).await?;
|
||||
db::ido::index_mempool(network, &db.ido_w, &txs_to_add, tip_height).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue