Skip to content

rpc: dumptxoutset rollback without invalidating blocks (backport of bitcoin/bitcoin#33477) - #443

Open
chrisguida wants to merge 3 commits into
bitcoinknots:29.x-knotsfrom
chrisguida:dumptxoutset-rollback-copy
Open

chrisguida wants to merge 3 commits into
bitcoinknots:29.x-knotsfrom
chrisguida:dumptxoutset-rollback-copy

Conversation

@chrisguida

@chrisguida chrisguida commented Oct 7, 2026 •

Copy link
Copy Markdown

Backport of bitcoin#33477 (fjahr, merged 2026-04-19) to 29.x-knots.

dumptxoutset with rollback currently invalidates blocks down to the target height,
suspends network activity, writes the snapshot and reconsiders the blocks. While it runs
the node is in a state that does not reflect reality, it cannot serve peers or follow the
chain, and a fork at the target height makes it fail. Reviewing an assumeutxo chainparams
entry means running exactly this on a synced node, which discourages people from doing it.

With this change the RPC copies the UTXO set into a temporary database, disconnects blocks
on that copy down to the target height, computes the snapshot from the copy and deletes
it. The node keeps running normally. A temporary prune lock keeps the needed block data on
pruned nodes. The new in_memory=true option keeps the temporary database in RAM (more
than 10 GB on mainnet) and is faster.

Deep rollbacks are slower than before (upstream measured 9m16s vs 3m17s for ~1500 blocks
on disk) but the time no longer depends on the state of the main chain, and the node stays
online.

Adapted to Knots' human-readable dumptxoutset format: the rolled-back dump takes the
same format, show_header and separator arguments as the tip dump. The functional
tests that checked the network-activity handling are dropped (there is nothing to suspend
any more); the upstream fork test and the in-memory case are added, and the sqlite tool
test exercises the rollback path.

Commits:

  • rpc: Don't invalidate blocks in dumptxoutset (49d5e83 + fc73601)
  • test: Add dumptxoutset fork test (ab9463e)
  • test: Extend named pipe sqlite tool test to use rollback (d0fd718)

Motivation: makes verifying the assumeutxo snapshot in #444 a background
operation on any synced node.

Testing done

  • Built on Ubuntu 26.04 (g++ 15.2, cmake 4.2.3, boost 1.90) on 2026-10-07.
  • test/functional/rpc_dumptxoutset.py and tool_utxo_to_sqlite.py pass (python 3.14).
  • Mainnet, on a pruned assumeutxo node (Knots 29.4.2 + this PR + chainparams: add assumeutxo snapshot at height 976000 #444, snapshot loaded at
    976000, tip 976069, 16 cores, NVMe): dumptxoutset rollback=976001 while the node kept
    its 10 peers and followed the chain. On disk: 784 s (copying 167M coins into the temporary
    database is most of it; the copy was 9.1 GB and was removed afterwards). With
    in_memory=true: 473 s. Both runs returned the same txoutset_hash
    (ed7dfbf6388813105dbc7c39bb44ee5503252868c39db8f0d93607dbc342fb98) and nchaintx
    (1417215824). Rolling back to the snapshot base height itself (976000) is refused on such
    a node with "necessary block data is already pruned", because the base block has no undo
    data until background validation reaches it; that check is unchanged from the current code.

fjahr and others added 3 commits October 7, 2026 12:44
Backport of bitcoin#33477 (commits 49d5e83 and fc73601).

dumptxoutset with rollback no longer invalidates blocks and suspends
network activity. It copies the UTXO set into a temporary database,
disconnects blocks on that copy down to the target height, computes the
snapshot from the copy and deletes it. The node keeps following the
chain and serving peers while a historical snapshot (or its hash, to
verify an assumeutxo chainparams entry) is produced, and a fork at the
target height cannot make it fail. A temporary prune lock keeps the
needed block data while a pruned node rolls back.

The new in_memory option keeps the temporary database in RAM
(more than 10 GB on mainnet), which is faster.

Adapted to Knots' human-readable dumptxoutset output: the rolled-back
dump takes the same format arguments as the tip dump.

Rolling back on the copy is slower than the invalidateblock approach
for deep rollbacks (upstream measured 9m16s vs 3m17s for ~1500 blocks)
but performance no longer depends on the state of the main chain.
Backport of bitcoin#33477 commit ab9463e, with the in-memory
case from fc73601.
@chrisguida

Copy link
Copy Markdown
Author

An assembler-ready copy is at chrisguida/dumptxoutset-rollback-copy-29+knots (same three commits rebased onto the compat_rpc_dumptxoutset_hr merge, the oldest point on 29.x where they apply); this branch stays as is for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants