Describe the bug
TxGraph::apply_changeset loops over txs, txouts, anchors, last_seen and last_evicted but not first_seen. Meanwhile initial_changeset() does write first_seen out, so persist and apply don't match up.
the value doesn't just come back as None apply_changeset still replays last_seen via insert_seen_at, which calls update_first_seen internally, and on an empty graph that entry is vacant so it just takes the last_seen value So after a reload every tx ends up with first_seen == last_seen.
SQLite isn't the problem the changeset that comes back off disk has the right values. They get thrown away when it's applied to the graph.
first_seen is the primary sort key for unconfirmed txs in ChainPosition::Ord Once it equals last_seen the ordering can change across a restart, without anything else changing.
To Reproduce
Two unconfirmed txs where first_seen and last_seen disagree on order, through a real sqlite file (write, close, reopen, apply):
before: A = (100, 500) B = (200, 300) order = [A, B]
changeset off disk: first_seen = {A: 100, B: 200} <- fine
last_seen = {A: 500, B: 300}
after apply_changeset: A = (500, 500) B = (300, 300) order = [B, A]
Also reproduces with no database at all:
let mut reloaded = TxGraph::<BlockId>::default();
reloaded.apply_changeset(graph.initial_changeset());
// first_seen is now last_seen
Expected behavior
initial_changeset() to apply_changeset() should round-trip, and unconfirmed ordering shouldn't change just because you restarted.
Build environment
- BDK tag/commit:
337e9d68, bdk_chain 0.23.2 (apply_changeset is the same on master)
- OS+version: Windows 11
- Rust/Cargo version: 1.97.1
- Rust/Cargo target: x86_64-pc-windows-msvc
Which backend(s) are relevant (if any)?
Is this blocking production use?
Additional context
first_seen was added in #1947/#1950 and persisted in #1965/#1966, so it's computed and stored on purpose it just never gets read back. #1966's test checks the reloaded changeset has first_seen but never applies it to a graph, which is why this slipped through
Describe the bug
TxGraph::apply_changesetloops overtxs,txouts,anchors,last_seenandlast_evictedbut notfirst_seen. Meanwhileinitial_changeset()does writefirst_seenout, so persist and apply don't match up.the value doesn't just come back as
Noneapply_changesetstill replayslast_seenviainsert_seen_at, which callsupdate_first_seeninternally, and on an empty graph that entry is vacant so it just takes thelast_seenvalue So after a reload every tx ends up withfirst_seen == last_seen.SQLite isn't the problem the changeset that comes back off disk has the right values. They get thrown away when it's applied to the graph.
first_seenis the primary sort key for unconfirmed txs inChainPosition::OrdOnce it equalslast_seenthe ordering can change across a restart, without anything else changing.To Reproduce
Two unconfirmed txs where
first_seenandlast_seendisagree on order, through a real sqlite file (write, close, reopen, apply):Also reproduces with no database at all:
Expected behavior
initial_changeset()toapply_changeset()should round-trip, and unconfirmed ordering shouldn't change just because you restarted.Build environment
337e9d68,bdk_chain0.23.2 (apply_changesetis the same onmaster)Which backend(s) are relevant (if any)?
bdk_chain,bdk_core)____Is this blocking production use?
Additional context
first_seenwas added in #1947/#1950 and persisted in #1965/#1966, so it's computed and stored on purpose it just never gets read back. #1966's test checks the reloaded changeset hasfirst_seenbut never applies it to a graph, which is why this slipped through