TxGraph:: apply_changeset ignores ChangeSet::first_seen

オープン 初心者向け
#2,270 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

@evanlinjin がすでに取り組んでいます。

2026年10月18日 から。

  • #2346 @NaitikVerma6776 による — マージされずにクローズ
  • #2392 @evanlinjin による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
78/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
rust
領域
backend

調査の方向性

TxGraph::apply_changeset と initial_changeset から始め、SQLite の再読み込みパスを確認する前に、issue に記載されたメモリ内のラウンドトリップを再現します。完了の条件は、changeset の適用後も first_seen の値が保持され、再読み込み後も未確認トランザクションの順序が変わらないことです。

索引モデルが issue の本文から書いたものです。

説明

bug

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)?

  • Electrum
  • Esplora
  • Bitcoin Core RPC
  • None / not backend-related (e.g. bdk_chain, bdk_core)
  • Other (please specify): ____

Is this blocking production use?

  • Yes
  • No

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

主要言語
Rust
スター
1.1k
フォーク
521
平均マージ
4日 1時間
マージ済み PR(30日)
21

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

bitcoindevkit/bdk のほかの issue

bitcoindevkit/bdk の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。