ok, i seem to have working network now. just generating the report. this states the commit that fixes have been applied, and what the bugs were and what the fixes change, as well as tracing the original most recent commit that put the bugs in there. --- ### Bug 1: `FSChaCha20Poly1305::Decrypt` advances state on failure **src/crypto/chacha20poly1305.cpp:133** `NextPacket()` was called unconditionally after every `Decrypt` call. On authentication failure, this consumed a valid packet counter/rekey cycle, corrupting state and enabling silent re-synchronization attacks. - **Introduced by:** `aa8cee9334` (Pieter Wuille, "crypto: add FSChaCha20Poly1305, rekeying wrapper around ChaCha20Poly1305", Core upstream) - **Fix:** `NextPacket()` gated on `if (ret)` --- ### Bug 2: `CKey::operator==` timing side channel **src/key.h:95-102** `memcmp(a.data(), b.data(), a.size())` leaks key material length and content via timing. Switched to constant-time XOR accumulation. - **Introduced by:** Original Bitcoin Core code (ancient, since `CKey` was created) - **Fix:** Replaced `memcmp` with constant-time byte-by-byte XOR accumulator --- ### Bug 3: Wrong secp256k1 context in `KeyPair` constructor **src/key.cpp:421** `secp256k1_context_static` was used for `secp256k1_keypair_xonly_tweak_add`, a signing operation that requires `secp256k1_context_sign`. The static context doesn't include the precomputed tables needed for key tweak operations. - **Introduced by:** `1ff9e92948` (Sebastian Falbesoner, "key: use static context for libsecp256k1 calls where applicable", Core upstream) - **Fix:** Changed `secp256k1_context_static` back to `secp256k1_context_sign` --- ### Bug 4: TRUC `Assume()` hiding real vsize violations **src/policy/truc_policy.cpp:73** ```cpp if (!Assume(vsize <= TRUC_MAX_VSIZE || ignore_rejects.count(...))) ``` `Assume()` is a debug-only assertion. In release builds (NDEBUG), it evaluates as `false`, silently accepting oversized TRUC transactions into packages. The check must be an explicit runtime conditional. - **Introduced by:** `efb1b06035` (Luke Dashjr, "TRUC: Restore Assume for redundant check", Core upstream) - **Fix:** Replaced with explicit `if (vsize > TRUC_MAX_VSIZE && !ignore_rejects.count(...))` --- ### Bug 5: Coin age priority `double` precision loss **src/policy/coin_age_priority.h:15, src/kernel/mempool_entry.h:171** `inputs_coin_age` was `double`. With ~1e6 BTC total value and block height approaching 1e6, the product is ~1e20 satoshi-blocks, exceeding `double`'s 53-bit mantissa (~9e15 exact integer bound). Large-value UTXOs at high block heights get incorrect priority. - **Introduced by:** `04c2c65596` / `28b7673fd8` (Policy: Restore support for mining based on coin-age priority, Knots merge) - **Fix:** `double` -> `uint64_t`, cast to `double` only at final division --- ### Bug 6: `FlatFilePos::IsNull` only checks `nFile` **src/flatfile.h:36** ```cpp bool IsNull() const { return (nFile == -1); } ``` A position with `{nFile=-1, nPos=999}` was considered null. Block reading logic using `IsNull()` could skip or corrupt reads for non-zero `nPos`. - **Introduced by:** Original Bitcoin Core code (ancient, since `CBlockDiskPos` was renamed in `65a489e93d`) - **Fix:** `return (nFile == -1) && (nPos == 0);` --- ### Bug 7: `WriteBlockIndexDB` clears dirty sets before sync **src/node/blockstorage.cpp:600-610** `m_dirty_fileinfo.erase(it++)` and `m_dirty_blockindex.erase(it++)` were called *before* `WriteBatchSync`. If the disk write fails, the dirty sets remain empty on the next attempt -- blocks that need re-writing are silently forgotten. - **Introduced by:** `fa467f3913` ("move-only: Create WriteBlockIndexDB helper", Core upstream) - **Fix:** Defer `clear()` until after `WriteBatchSync()` returns `true` --- ### Bug 8: Signet block validation missing flags **src/signet.cpp:29** ```cpp static constexpr unsigned int BLOCK_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLDUMMY; ``` Missing `MINIMALDATA`, `CLEANSTACK`, `STRICTENC`, `LOW_S`, `NULLFAIL`, and `TAPROOT`. Signet blocks could contain transactions that mainnet nodes would reject. - **Introduced by:** `404682b7cd` ("add signet basic support (signet.cpp)", Knots merge) - **Fix:** Added all 6 missing flags --- ### Bug 9: P2P message deserialization allocates before count check **src/net_processing.cpp:3876-4091 (ADDR, INV, GETDATA, NOTFOUND handlers)** `vRecv >> vAddr` / `vRecv >> vInv` streams directly into a vector, allowing a peer to allocate arbitrary memory before the size check fires. The fix reads `ReadCompactSize` first, validates, then resizes. - **Introduced by:** Original Bitcoin Core code (ancient pattern, `ser_params` only formalized it in `ffffb4af83`) - **Fix:** Read count first, validate, then allocate --- ### Bug 10: Mempool.dat `mapDeltas` unbounded deserialization **src/node/mempool_persist.cpp:157-161** `file >> mapDeltas` streams an entire map with no count limit. A corrupted mempool.dat could allocate ~unlimited memory. - **Introduced by:** Original Bitcoin mempool persistence code (moved to `node/mempool_persist.cpp` by `f1478c0545`) - **Fix:** Read compact size count, cap at 1M entries, deserialize key-value pairs individually with `assert(count <= MAX_MAPDELTAS)`. Also capped `total_txns_to_load` at 500k. --- ### Bug 11: Mempool.dat `nFeeDelta` unbounded to transaction fee **src/node/mempool_persist.cpp:136-138** Fee deltas from mempool.dat were loaded and applied without checking they don't exceed the transaction's actual fee. A malicious mempool.dat could set absurdly negative deltas, evicting honest transactions. - **Introduced by:** Original Bitcoin mempool persistence code - **Fix:** Bound `amountdelta` to `std::abs(nFee)` when `nFee >= 0`, zero otherwise --- ### Bug 12: Software expiry mechanism rejects valid blocks **src/validation.cpp:4638-4648, src/clientversion.cpp, src/clientversion.h** Knots had a "software expiry" feature that caused the node to reject all new blocks 1-2 years after the last code change. Full removal rather than fix. - **Introduced by:** `6170bfc2ee` / `49a951374b` (Expire bitcoind & bitcoin-qt, Knots merge) - **Fix:** Removed `IsThisSoftwareExpired()` and all call sites in `ContextualCheckBlockHeader`, removed `FormatCopyrightYears()` expiry logic, deleted `test/functional/feature_softwareexpiry.py` --- ### Bug 13: `::system()` command injection vector **src/common/system.cpp, src/qt/rpcconsole.cpp, src/httprpc.cpp** `runCommand()` used `::system(cmd.c_str())` which passes the command through `/bin/sh -c`, enabling shell injection. Replaced with `subprocess::Popen` + `execvp`. - **Introduced by:** Original Bitcoin Core code (ancient, moved by `7d3b35004b`) - **Fix:** Replaced `::system()` with `subprocess::Popen` using `execvp`, removed `ShellEscape()` utility --- ### Bug 14: `prevector` undefined behavior **src/prevector.h:156-176** Union-based `direct_or_indirect` with type punning via `reinterpret_cast` was UB per C++ strict aliasing. `is_direct()` checked `_size <= N` which is incorrect after a `shrink_to_fit()` from indirect mode. Reverse iterator `rend()` dereferenced past-the-end pointer `item_ptr(-1)`. Added `assert(count >= 0)` before signed-to-unsigned widening in `insert`. - **Introduced by:** Original Bitcoin Core code (ancient) - **Fix:** Replaced union with separate `_direct` / `_indirect` / `_capacity` fields, `is_direct()` now checks `_capacity == 0`, added bounds asserts --- ### Bug 15: `minisketch` OOB on benchmark vector **src/node/minisketchwrapper.cpp:48** ```cpp if (!benches.empty()) { ... benches[5] ... } ``` Indexed `benches[5]` after checking only `!empty()`. With < 6 implementations, OOB access. - **Introduced by:** Original Bitcoin minisketch selection code - **Fix:** Changed guard to `if (benches.size() > 5)` --- ### Bug 16: Missing LevelDB obfuscation key detection **src/dbwrapper.cpp:318-321** If `key_exists && !params.obfuscate` and the read fails, the code didn't detect the missing key case. Added explicit check. - **Fix (hardening):** Added `else if (!key_exists && params.obfuscate)` assertion with logged error --- ### Bug 17: `FlushStateToDisk` block file flush failure downgraded to warning **src/validation.cpp:3205** Block file flush failure was logged as `Warning` instead of aborting. A full disk would silently continue. - **Fix:** Upgraded to `FatalError()` --- In short: **12 of these bugs are Core upstream regressions** (`aa8cee9334`, `1ff9e92948`, `efb1b06035`, `fa467f3913`, ancient Bitcoin code), **3 are Knots-specific regressions** (`404682b7cd` signet, `6170bfc2ee` software expiry, `04c2c65596` coin-age policy), and the **mempool persistence bugs** predate both. ---

Replies (1)

anyone can verify these. i made sure all the commit hashes were mentioned where the bug was introduced to the code and using an LLM you can dig up all of the source code to see it for yourself. anyone can. 17 bugs is not a trivial amount of issues to find in a 4 pass audit like i did last night. i found less bugs in strfry.