#36280 validation: throw when a compressed script can't be decompressed

full analysis

https://github.com/bitcoin/bitcoin/pull/36280 · furszy · +61/-4 in 3 files, 2 commits · labels: Validation

Goal

  • Fail explicitly on corrupted compressed scripts instead of silently treating them as empty scripts
  • Prevents corrupt UTXO database or undo data from quietly yielding anyone-can-spend outputs

This pull request modifies `ScriptCompression::Unser` to throw `std::ios_base::failure` when `DecompressScript` fails, rather than ignoring the failure and leaving the output script empty. It also adds unit tests covering off-curve and invalid-pubkey P2PK decompression failure modes, plus an assertion round-trip in the script fuzz harness.

Problem: When deserializing compressed scripts from the UTXO database or undo data, decompression failures are currently ignored. If a compressed record is corrupted or improperly formed, it silently yields an empty script (anyone-can-spend) instead of signaling deserialization failure to the caller.

Category: Validation (#18 of 48)

P3 · bug fix

  • P3 because it fixes error handling for corrupted UTXO and undo data
  • Requires database corruption to trigger in practice, limiting real-world impact
  • Prevents severe misinterpretation of corrupt records as anyone-can-spend coins

Hardens UTXO deserialization error handling against corrupted or non-decodable data. As noted by furszy, the bug requires data corruption to trigger today, but ignoring failure produces an empty anyone-can-spend script instead of raising an error.

Membership: Touches `src/compressor.h`, which handles UTXO script compression for the coins database and undo storage, carrying the Validation label.

Factors: security/stability 1, bug 1, performance 0, user value 0, leverage 0

Reviewability: Ready

  • Ready for review with passing CI, unit tests, and fuzz coverage

The patch is small, passes CI, and includes unit and fuzz tests with no pending requests.

Author status: active

Agreement: Positive

  • Positive early sentiment with no objections raised
  • Concept approval without stated reasons (sedited)

Positive with early Approach ACK from sedited

Reviewer sedited provided an Approach ACK, with no objections raised.

  • sedited left an Approach ACK on 2026-09-16

Review verdicts (DrahtBot): 0

Files

55 lines under test/bench/ci.

  • src/test/compress_tests.cpp +46/-0
  • src/compressor.h +7/-3
  • src/test/fuzz/script.cpp +8/-1

Card

PR 36280 fixes error handling in ScriptCompression::Unser so that decompression failures throw std::ios_base::failure instead of silently leaving the script empty. Currently, a corrupted compressed record can deserialize into an empty script, which consensus evaluates as anyone-can-spend. While only reachable via corruption today, the change ensures clean deserialization failure and adds explicit test coverage for uncompressed off-curve pubkey scripts. Review is ready and has an initial Approach ACK.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T16:24, confidence high, input hash 0cb9d8e680a22b3d