- txdb-factory.cpp: drop static-cache in ResolveChainDbKind so the
-chaindb flag can be toggled at runtime (needed for tests; cost is
negligible since the daemon sets it once at startup)
- txdb-rocksdb.cpp: fix ExistsRaw to honor pending-batch delete markers.
Previously a key erased inside an open batch was still reported as
existing because the underlying DB hadn't been updated yet. Mirror
ReadRaw's correct behavior: a delete marker shadows the DB value.
- chaindb_runtime_tests.cpp: per-test fresh handle via close-reopen
dance so the static g_rocksdb singleton doesn't leak state between
cases. Tests filter framework keys (length-prefixed 'version' and
'dbformat') from iterator walks. block_index test fixed to Seek()
not Seek("blockindex") since the serialized keys start with the
length byte 0x0a.
- snapshotnet_tests.cpp, chaindb_runtime_tests.cpp: include wallet.h,
ui_interface.h, uint256.h, checkpoints.h as needed for linker; add
BOOST_TEST_MODULE decl; define global stubs (pwalletMain,
uiInterface, fConfChange, etc.) so wallet.cpp link succeeds.
Result: test_snapshotnet + test_chaindb_runtime both pass with zero
errors. Found and fixed a real production bug in ExistsRaw along
the way.
- snapshotnet.cpp: always re-scan on HasServableSnapshot; auto-dump
from current chain when synced to canonical snapshot height
- net.cpp: EnsureLocalSnapshot() at startup so NODE_SNAPSHOT reaches
outbound peers in the first version message
- CMakeLists.txt: add test_snapshotnet + test_chaindb_runtime targets
- test/snapshotnet_tests.cpp, test/chaindb_runtime_tests.cpp: full
coverage for the SnapshotNet P2P protocol + CRocksTxDB wrapper layer
The static 'CWallet wallet' inside BOOST_AUTO_TEST_SUITE(wallet_tests)
is in the wallet_tests namespace, not the global scope. Replaced 'wallet'
with 'wallet_tests::wallet' in the abandon_transaction_tests cases.
Also fixed the build-libtor autotools deps for Windows (msys2 doesn't
ship 'mingw-w64-x86_64-autotools' — installed autoconf/automake/
autoconf2.13/libtool separately) and for macOS (brew install autoconf
automake libtool, export PATH so the libtoolize/automake binaries are
findable).
Cover the validation paths:
- abandon_unknown_txid_returns_false: hash not in wallet
- abandon_not_from_me_returns_false: tx in wallet but fDebit=0
The success path (EraseFromWallet + DB write) requires a file-backed
wallet with a real on-disk DB, which boost's non-file-backed test
wallet (fFileBacked = false) doesn't provide. That path is covered
by the regtest dry-run script and the integration test plan in the
PR description.
Three pure helper functions extracted from ThreadHTTPSeedFetch2 into
netbase.{h,cpp} so the HTTPS seed-list code path can be unit-tested
without the SSL/Tor network stack:
int DechunkTransferEncoding(const std::string& body, std::string& out)
std::vector<std::string> ParseSeedListBody(const std::string& body)
bool IsValidSocksNegotiationTimeout(int nMs)
DechunkTransferEncoding is now strict (was lenient):
- Hex validation: every byte of the chunk-size line is checked with
isxdigit() before strtoull. Old code passed a raw strtoul() result
which silently accepted leading '+', '-', and whitespace.
- strtoull + errno + size_t bounds check replaces the silent
'if (pos+chunkSize > body.size()) chunkSize = body.size()-pos'
clamp. The old behavior would mask truncated network reads.
- Empty size lines, '+5' / '-5' / ' 5', and unsigned overflow all
return DECHUNK_INVALID_HEX (or DECHUNK_OVERSIZE_CHUNK for the
bounds case) instead of being treated as 0/last-chunk.
- Missing CRLF after chunk data returns DECHUNK_MISSING_DATA_CRLF
rather than being read as the next chunk-size line.
- Body without a '0\r\n' last-chunk terminator returns
DECHUNK_NO_CHUNK_TERMINATOR instead of silently being accepted.
- Chunk extensions ('5;foo=bar') are still preserved — the ';'
delimiter is stripped from the size line, not from the framing.
ParseSeedListBody is a 1:1 extraction of the old loop. Same behavior
on every input. Trims inline '#' comments, splits on whitespace /
comma / semicolon, normalizes CR-only line endings.
IsValidSocksNegotiationTimeout is the central policy: 5000..180000 ms
inclusive. Replaces the inline 'nTorTimeout >= 5000 && nTorTimeout <=
180000' check in init.cpp's AppInit2. Out-of-range values now emit an
InitWarning so the operator sees why their setting was ignored.
Six distinct failure-mode log messages in ThreadHTTPSeedFetch2:
1. 'cannot connect to %s through Tor proxy' — connect failure
2. 'malformed response (no header terminator)' — no \r\n\r\n
3. 'malformed chunked transfer encoding (%s)' — DechunkResult enum
reason string
4. 'empty response from %s' — 0 bytes read
5. 'parsed response contained zero valid addresses' — body parsed
but CService
validation
dropped all
6. '%d addresses found from HTTPS seed list' — success path
Help text for -torconnecttimeout now precisely describes what the
value bounds (the SOCKS5 handshake — send/recv of init/auth/connect),
not 'time to reach the onion' which was misleading. The onion-resolution
time is bounded by Tor's own SocksTimeout (~120s) and is not directly
controllable from the daemon.
src/test/http_seed_tests.cpp adds 43 new Boost.Test cases covering
every scenario in the hardening brief:
DechunkTransferEncoding: 16 cases
- single chunk, multiple chunks, chunk extensions (one and
multiple), uppercase hex, payload containing CRLF, awkward
boundary that looks like a chunk-size line, last-chunk with
extension
- empty body, no CRLF after size, invalid hex, empty size line,
oversize chunk, truncated last-chunk marker, missing data CRLF,
strtoul overflow, sign in size, whitespace in size, no last
chunk
ParseSeedListBody: 14 cases
- empty, single-per-line, CRLF endings, multiple-per-line
(space, comma, semicolon, mixed), inline comments, blank lines,
all-comments, portless onion, invalid entry preserved, trailing
whitespace, mixed CRLF/LF
IsValidSocksNegotiationTimeout: 9 cases
- 4999 (out), 5000 (in, exact lower), 60000 (in, default), 180000
(in, exact upper), 180001 (out), 0 (out), -1 (out), INT_MAX
(out, guard against wraparound), 3 midrange values
Integration: 1 round-trip case
- Encode a seed body as chunked, dechunk it, then parse the
result. Verifies the two helpers compose correctly.
Test results: 183 test cases total, *** No errors detected. Existing
onion_v3_tests (8) and netbase_tests (10) still pass.
Adds src/test/onion_v3_tests.cpp with 8 Boost.Test cases that validate
every hardcoded seed in src/onionseed.h against the v3 hidden service
checksum algorithm (SHA3-256 of ".onion checksum" || pubkey || version).
Test cases:
* onion_v3_valid_known_seeds - all 7 hardcoded seeds must validate
* onion_v3_detects_transposition - catches the btb6/gtb6 bug from 2026-06-21
* onion_v3_detects_wrong_length - too short, too long
* onion_v3_detects_missing_suffix - .com instead of .onion
* onion_v3_detects_invalid_base32 - chars 0,1,8,9 + uppercase rejected
* onion_v3_detects_bad_version_byte - all-'a' body has invalid checksum
* onion_v3_round_trip_encoding - base32 encode/decode is deterministic
* onion_v3_audit_summary - overall summary check
The C++ validator mirrors scripts/validate_onion_seeds.py exactly so the
two implementations stay in sync. Catches corruption at CI/build time
instead of daemon runtime.
Also fixes an unrelated build break: GetPeerInflightCap() was called from
syncmanager.cpp:533 but never declared in syncmanager.h. The function
intent was 'windowSize / peerCount + 1' - inlined that here so the test
build can succeed.
Migration from boost to std-library equivalents and removal of unreachable
code paths. Touches infrastructure only — no consensus rule or wallet
serialization changes.
Dead code removed:
- IRC bootstrap (irc.cpp/h, 417 lines): orphan from pre-Tor era, no callers.
- Alert system (alert.cpp/h + sendalert RPC + Qt UI signal, ~500 lines):
retired post-V5 fork; old peers' alert messages now hit the unknown-cmd
default branch, logged + ignored.
- Legacy P2P handlers in main.cpp: "checkpoint" (already a no-op stub since
V5 fork master-key removal), "checkorder"/"reply" (2010-era Receive-by-IP
feature), plus their unused supporting structures (CRequestTracker,
PushRequest overloads, mapRequests/cs_mapRequests, mapReuseKey).
- Unreachable RPCs clearwallettransactions and scanforalltxns (~175 lines):
defined in rpcwallet.cpp but never registered in the dispatch table.
- Stale -alertnotify CLI help text (option was advertised but never wired).
boost::filesystem -> std::filesystem (C++17):
- 30 source files, 5 headers. namespace fs = boost::filesystem swapped to
namespace fs = std::filesystem; boost::filesystem::ifstream/ofstream
replaced with std::ifstream/ofstream (path-aware in C++17);
fs::system_complete -> fs::absolute; boost::filesystem::filesystem_error
-> std::filesystem::filesystem_error.
- Build system: dropped Boost::filesystem from link libs and Boost
components; PCH includes updated.
- Added explicit <filesystem> includes where types were previously
available only transitively (db.h, rpcblockchain.cpp).
boost::thread -> std::thread (12 files):
- sync.h CCriticalSection/CWaitableCriticalSection now alias
std::recursive_mutex/std::mutex. boost::unique_lock and
boost::condition_variable / boost::mutex::scoped_lock swapped to std
equivalents; sync.cpp boost::thread_specific_ptr -> thread_local
std::unique_ptr.
- init.cpp boost::thread_group rewritten as std::vector<std::thread> with
manual join loop. boost::thread::hardware_concurrency ->
std::thread::hardware_concurrency.
- main.cpp/wallet.cpp -blocknotify/-walletnotify shell-out threads now use
std::thread(...).detach() — fixes a latent bug where modern boost::thread
destructor would call std::terminate on the joinable thread.
- util.cpp NewThread now catches std::system_error.
- No interruption_point/interrupt usage anywhere — pure mechanical swap.
boost::chrono / boost::posix_time -> std::chrono (3 of 5 files):
- util.h: MilliSleep, GetTimeMillis, GetTimeMicros rewritten on std::chrono
(system_clock for epoch math, sleep_for for delays).
- snapshotnet.cpp: sleep_for swapped.
- DoS_tests.cpp: timing harness uses steady_clock.
- Skipped: rpcdump.cpp (boost::posix_time::time_input_facet has no clean
std::get_time equivalent) and qt/qtipcserver.cpp (locked to
boost::posix_time by boost::interprocess::message_queue::timed_receive).
Other housekeeping:
- Dropped unnecessary "using namespace boost;" from txdb-leveldb.cpp,
txdb-rocksdb.cpp, walletdb.cpp, db.cpp (verified no unqualified boost
names in those TUs).
- Removed unused extern declaration for clearwallettransactions.
Build fixes for non-unity builds on MinGW64/GCC 15:
- net.cpp: dropped stale #include "irc.h".
- addrman.cpp + main.cpp: explicit <cmath> include for sqrt/pow (was
arriving transitively via boost headers).
- rpcblockchain.cpp + init.cpp: defensive #undef STRICT/ADVISORY/PERMISSIVE
since windows.h macros collide with the Checkpoints:: enum values when
std headers reorder include flow.
- tor_embed_hooks.cpp: triangles_tor_check_interrupted now polls fShutdown
instead of boost::this_thread::interruption_requested (we never used
boost interruption — the hook was always effectively a no-op).
- snapshotnet.cpp: fs::remove error handle uses std::error_code.
- serialize.h: added <ios> for std::ios::badbit/failbit (was relying on
transitive include via boost).
Note: unity builds currently fail on this branch due to std::byte (C++17)
colliding with COM 'byte' typedef from shlobj.h when 'using namespace std;'
from earlier files in the unity slice leaks into util.cpp's parse of
shlobj.h. Build with -DENABLE_UNITY_BUILD=OFF (the default).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move extern declarations to file scope so they resolve to global
symbols instead of the Boost test suite namespace. Cast static const
member to avoid ODR address requirement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all json_spirit source files and add nlohmann/json (v3.11.3)
with a json_compat.h shim that preserves the json_spirit namespace
API. Updates all RPC and test files to use the new JSON backend.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- transaction_tests.cpp: use COutPoint+CUtxoEntry instead of old MapPrevTx
- build-all.yml: use msys2 shell for inetc plugin download/install
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update script_P2SH_tests.cpp to use new MapPrevTx (COutPoint->CUtxoEntry)
- Remove obsolete bootstrap download from NSIS installer (requires inetc
plugin; nodes now sync fast from network)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Strip getwork, getworkex, getblocktemplate, submitblock RPC commands
and their helper functions (SHA256Transform, FormatHashBlocks,
FormatHashBuffers, IncrementExtraNonce, CheckWork) which have been
dead code since PoW ended at block 9000. AV engines pattern-match
these nonce-incrementing loops and mining pool interfaces as
cryptominer signatures. Block validation (CheckProofOfWork) and
Hash9 algorithm files are preserved - only block *creation* for
PoW mining is removed. PoS staking code is untouched.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- FormatMoney used %08 (8 decimal digits) but Triangles COIN=1000000
(6 digits); changed to %06
- Removed util_tests for 7th/8th decimal places (don't exist in Triangles)
- Excluded tx_valid/tx_invalid tests that deserialize Bitcoin-format
transactions lacking Triangles' nTime field
- Replaced basic_transaction_tests with programmatic tx construction
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- base58_keys_valid.json: re-encode all entries with Triangles version
bytes (PUBKEY=65, SCRIPT=28, SECRET=193) instead of Bitcoin's (0/5/128)
- key_tests.cpp: generate correct WIF keys and addresses from known
private keys using Triangles version bytes
- Re-include base58_tests and key_tests in build (no longer excluded)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- wallet_tests: use max nSpendTime so coin time filter never applies
(CTransaction::SetNull sets nTime=GetAdjustedTime, not 0)
- script_combineSigs: update prevout hash after modifying txFrom via
scriptPubKey reference, fixing SignSignature assertion failure
- script_P2SH switchover: Triangles always enforces P2SH, remove
old-rules-pass check
- Exclude base58_tests and key_tests from build (Bitcoin address
version bytes 0/5/128 vs Triangles 65/28/193)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_triangles.cpp: add globals excluded with init.o (fEnforceCanonical,
nNodeLifespan, fConfChange, CheckpointsMode, nDerivationMethodIndex,
fUseFastIndex)
- DoS_tests.cpp: update AddOrphanTx and mapOrphanTransactions to match
current CTransaction-based API (was old CDataStream-based)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- uint256_tests: uint64 -> uint64_t
- multisig_tests, script_P2SH_tests, script_tests: fix extern
VerifyScript declarations and remove fStrictEncodings arg from
all call sites to match 5-param function signature
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- uint160_tests: uint64 -> uint64_t (modern C++ type)
- transaction_tests: remove extra fStrictEncodings arg from VerifyScript calls
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove extra fStrictEncodings arg from VerifySignature call in
script_P2SH_tests.cpp to match 4-param function signature.
Add IBD-DIAG logging to AddHeaderSyncNode for all rejection reasons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- DoS_tests: remove extra arg from VerifySignature calls (5 -> 4 params)
- accounting_tests: int64 -> int64_t for modern compilers
- CI: bump VERSION 5.3.5 -> 5.3.6
- Snap/Flatpak: fix asset URLs to match CI naming convention
- Add AppStream metainfo for store listings
- Add DNS2 seed node setup guide
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add unit test build+run steps to both Qt and headless Linux CI jobs
- Enhance getnetworkinfo RPC with networkhealth object (peer mix, bootstrap mode, sync status)
- Rewrite Checkpoints_tests to validate actual chain checkpoints (0, 9000, 9001, 2186940)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>