HomePhabricator

coins/refactor: enforce GetCoin() returns only unspent coins

Description

coins/refactor: enforce GetCoin() returns only unspent coins

Summary:

txdb: assert CCoinsViewDB::GetCoin only returns unspent coins

The chainstate UTXO database only stores unspent outputs; spent entries are removed.

Assert after reading a Coin so corruption or misuse cannot propagate a spent coin through the GetCoin() interface.

test: do not return spent coins from CCoinsViewTest::GetCoin

Production GetCoin() implementations only return unspent coins.

Update the CCoinsView test backend to match that contract, so tests stop exercising cache states that cannot occur with CCoinsViewCache or CCoinsViewDB.

fuzz: keep coinscache_sim backend free of spent coins

CoinsViewBottom roughly simulates a memory-backed CCoinsViewDB, which never stores spent coins.

Stop returning spent coins from GetCoin(), erase spent entries in BatchWrite(), and tighten comparisons to expect std::nullopt when the simulator has no coin.

coins: assume GetCoin only returns unspent coins

CCoinsViewCache::FetchCoin() had special handling for a spent Coin returned by the parent view.
Production parents (CCoinsViewCache and CCoinsViewDB) do not return spent coins, so this path is unreachable.

Replace it with an Assume(!coin.IsSpent()), drop outdated documentation about spent+FRESH cache entries, and simplify SanityCheck() to assert the remaining possible state invariants.
This is safe because it does not change behavior for valid backends and will fail fast if the GetCoin() contract is violated.

Co-authored-by: Lőrinc <pap.lorinc@gmail.com>

This is a backport of core#34207
https://github.com/bitcoin/bitcoin/pull/34207/changes/2ee7f9b259059d59e127852ea898b58183604b46

Test Plan: ninja all check check-functional-extended

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D20104

Details

Provenance
Lőrinc <pap.lorinc@gmail.com>Authored on Jan 3 2026, 19:26
PiRKCommitted on Jun 12 2026, 10:56
PiRKPushed on Jun 12 2026, 10:56
Reviewer
Restricted Project
Differential Revision
D20104: coins/refactor: enforce GetCoin() returns only unspent coins
Parents
rABC0bea55c27c0a: Fix inflight bytes accounting for paused peers
Branches
Unknown
Tags
Unknown