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,
|
pool: &SqlitePool,
|
||||||
current_block_height: i64,
|
current_block_height: i64,
|
||||||
) -> Result<()> {
|
) -> 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(
|
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)
|
.bind(current_block_height - TRACKER_MAX_BLOCK_DEPTH)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
|
|
@ -2288,17 +2291,20 @@ pub async fn index_block(
|
||||||
Ok(())
|
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(
|
pub async fn index_mempool(
|
||||||
network: Option<Network>,
|
network: Option<Network>,
|
||||||
pool: &SqlitePool,
|
pool: &SqlitePool,
|
||||||
sorted_txs: &[Transaction],
|
sorted_txs: &[Transaction],
|
||||||
|
highest_known_block_height: u64,
|
||||||
) -> Result<()> {
|
) -> 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
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,13 @@ pub async fn update_mempool(
|
||||||
// ido updates
|
// ido updates
|
||||||
let ido_electrum = electrum.clone();
|
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
|
// filter txs already in an ido txchain
|
||||||
let mut ido_to_add = Vec::new();
|
let mut ido_to_add = Vec::new();
|
||||||
for txid in ido_txs {
|
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
|
// an ido txchain can have several unconfirmed txs in flight; index parents first
|
||||||
let txs_to_add = ttor_sorted_kahn(txs_to_add);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue