This was not a good change

This commit is contained in:
jakobsn 2026-08-25 14:33:34 +02:00
parent 635f4f3afc
commit 3949436801

View file

@ -184,15 +184,7 @@ pub async fn insert_pool_history_entry(
tx_pos = excluded.tx_pos,
mtp_timestamp = COALESCE(excluded.mtp_timestamp, pool_history_entry.mtp_timestamp),
first_seen_timestamp = COALESCE(excluded.first_seen_timestamp, pool_history_entry.first_seen_timestamp),
-- Deliberately NOT excluded.sequence. This row is re-inserted when a
-- mempool transaction confirms, and taking the new value would move
-- it ahead of rows recorded in between -- reordering a pool's
-- history and breaking any cursor paging over it. The original value
-- is the order the state was first observed; note this is only a
-- spend order because update_pool_history re-queues a child until
-- its parent is stored. Block position would not give us that --
-- CTOR sorts a block by txid, not topologically.
sequence = pool_history_entry.sequence",
sequence = excluded.sequence",
)
.bind(cauldron.new_utxo_hash.expect("utxo hash on new pool history entry").to_blob())
.bind(pool.to_blob())
@ -1209,57 +1201,6 @@ mod tests {
(utxo0_bytes, expected)
}
#[tokio::test]
async fn confirming_a_mempool_entry_keeps_its_place_in_history() {
// A pool's history is a chain of spends, and `sequence` is the order the
// states were observed. Re-inserting a row when its transaction
// confirms used to take the new sequence, moving it ahead of everything
// recorded in between — which reorders the chart and lets a cursor
// return the same row twice.
let pool = test_pool().await;
setup_test_db(&pool).await;
let (utxo, _) = insert_traded_pool(&pool, 120, 1_000, 2_000).await;
let pool_id = PoolID::from_byte_array(utxo);
let before = db_pool_history(&pool, &pool_id, 0, 100, None)
.await
.unwrap();
let seqs_before: Vec<i64> = before.iter().map(|e| e.cursor.sequence).collect();
// Re-insert the first entry, as the confirm path does.
let first_utxo = OutPointHash::from_byte_array(utxo);
let contract = ParsedContract {
pkh: PubkeyHash::all_zeros(),
is_withdrawn: false,
spent_utxo_hash: OutPointHash::all_zeros(),
new_utxo_hash: Some(first_utxo),
new_utxo_txid: Some(Txid::from_byte_array([120u8; 32])),
new_utxo_n: Some(0),
token_id: Some(TokenID::from_byte_array([120u8; 32])),
sats: Some(1_000_000),
token_amount: Some(1_000_000),
};
let mut conn = pool.acquire().await.unwrap();
insert_pool_history_entry(&mut conn, &first_utxo, &contract, Some(2_500), None, 0, 0)
.await
.unwrap();
let after = db_pool_history(&pool, &pool_id, 0, 100, None)
.await
.unwrap();
let seqs_after: Vec<i64> = after.iter().map(|e| e.cursor.sequence).collect();
assert_eq!(
seqs_before, seqs_after,
"confirming must not renumber history"
);
assert_eq!(
before.iter().map(|e| e.txid.clone()).collect::<Vec<_>>(),
after.iter().map(|e| e.txid.clone()).collect::<Vec<_>>(),
"order must be unchanged"
);
}
#[tokio::test]
async fn paging_covers_every_row_exactly_once() {
// The property that matters: follow `next_cursor` to the end and you see