* Add triangles-cli: JSON-RPC client (port bitcoin-cli pattern)
Triangles never had a CLI client (bitcoin-cli analog). This adds
triangles-cli as a third build target alongside trianglesd and
triangles-qt.
- src/triangles-cli.cpp: self-contained JSON-RPC 1.0 client.
Reads triangles.conf for credentials, supports -rpcuser/-rpcpassword
/-rpcconnect/-rpcport/-testnet/-datadir/-conf flags. Implements
-getinfo (synthesized summary from getnetworkinfo/getblockchaininfo
/getwalletinfo) and raw method dispatch. JSON via json_spirit compat
shim (json_compat.h), HTTP via boost::asio, base64 auth inline.
No util.cpp / wallet.cpp / net.cpp / triangles_common link dep —
keeps the binary small (~600 KB Linux, ~1.5 MB Windows).
- CMake: new option(BUILD_CLI ON) + add_executable(triangles-cli)
in src/CMakeLists.txt. Status line added.
- CI: BUILD_CLI=ON added to build-windows-daemon and build-linux-daemon
jobs. triangles-cli.exe bundled into windows-daemon artifact
alongside trianglesd.exe. triangles-cli added to linux-daemon .deb
package (with launcher in /usr/bin).
- Default ON; set BUILD_CLI=OFF to skip.
Closes the open 'triangles-cli.exe missing from Windows build'
follow-up (the binary wasn't missing — it never existed).
Patterned after Bitcoin Core bitcoin-cli and Dash Core dash-cli.
* Fix macOS build: drop Boost::system/find_package component, use std::filesystem
Homebrew's boost formula doesn't ship the boost_system CMake config file,
so find_package(Boost REQUIRED COMPONENTS system) failed on macOS.
- Replace boost::filesystem with std::filesystem (C++17, no Boost dep)
- Drop 'filesystem' from find_package — only headers needed (asio + system)
- Link libboost_system explicitly per-platform by library name, resolved
via the platform's default search path (Homebrew toolchain on macOS,
system libs on Linux, MSYS2 on Windows)
CI will rerun automatically on PR push.
* Fix macOS build: add Boost::boost target for headers, link boost_system
The previous fix dropped the find_package component but also killed the
boost include path. Now use the modern Boost::boost header-only target
(available in Boost 1.83+) which sets up include directories without
requiring a per-component config file.
Link libboost_system explicitly by name on all platforms — the linker
finds it via the platform's default search path:
- Linux: /usr/lib (libboost_system.so)
- macOS Homebrew: /opt/homebrew/lib (libboost_system.dylib)
- Windows MSYS2: mingw64/bin (libboost_system-mt-X-XX.dll)
* Drop Boost entirely from triangles-cli: use raw sockets for HTTP
Third time's the charm. After two CI failures chasing boost::asio / libboost_system
linking issues across platforms (Homebrew missing config on macOS, MSYS2 versioned
names on Windows, CMake targets that don't quite work everywhere), rip the whole
Boost dependency out of the CLI and use raw POSIX/Winsock sockets.
- triangles-cli.cpp: replaced boost::asio with raw socket() / connect() / send()
/ recv() / getaddrinfo(). Cross-platform: #ifdef _WIN32 for Winsock + WSAStartup
/ WSACleanup, else POSIX. ~100 lines of clean portable socket code.
- src/CMakeLists.txt: dropped find_package(Boost) entirely. Only links
json_compat (header-only) + ws2_32 on Windows. No boost libs to find.
Should be the last fix needed for this PR.
* Fix Windows packaging step: simplify bash { } | sort -u | while pattern
The previous step used a bash group command piped through sort -u and a
while loop. Under MSYS2 bash + 'set -e -o pipefail' (GitHub Actions
default), this triggered a non-zero exit even when the loop body
succeeded, causing the Windows daemon job to fail at the packaging step
(the actual link of both trianglesd.exe and triangles-cli.exe succeeded).
Replaced the { } | sort -u | while pattern with a temp-file-based dedup:
- ldd both binaries, append to /tmp/cli-dlls.txt (or cli-libs.txt on Linux)
- sort -u the temp file
- pipe the result into the while loop (simpler pipeline, no group)
Also applied the same simplification to the Linux .deb packaging for
consistency, even though the Linux build was passing.
* Simplify DLL packaging: plain for loop, no pipe-into-while
The previous attempts used 'ldd | sort -u | while read; do ... done' patterns
that exit 1 under MSYS2 bash + 'set -e -o pipefail' even when the script
ran successfully. Replaced with a plain 'for bin in ...; do ldd > list.txt;
while read; do cp; done < list.txt; done' pattern that has no pipelines
other than the standard redirection, and uses IFS= read -r for safe line
iteration.
Also moved temp files from /tmp to the working directory (./dll-list.txt)
to avoid any MSYS2 /tmp path-translation edge cases.
* diagnostic: add tracing to Windows packaging step
* Add package-windows-daemon.sh + package-linux-daemon.sh scripts
Move the Windows daemon packaging step and the Linux .deb build into
committed shell scripts under scripts/ci/. This bypasses GitHub Actions'
inline-run-block quirks (silent exit 1 under msys2 + set -e -o pipefail
with multi-line scripts) and makes the packaging logic debuggable locally.
* Switch to script-file packaging for Windows + Linux daemon jobs
Replace inline multi-line run: blocks with invocations of the
scripts/ci/package-*.sh scripts. This sidesteps the GitHub Actions
msys2 + 'set -e -o pipefail' issue that caused silent exit 1 on the
Windows daemon packaging step. The scripts are also debuggable locally.
---------
Co-authored-by: Krystie <krystie@sami>
Internal refactor milestone for the C++20 modernization series.
No protocol or on-disk format change (version.h untouched).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add libsecp256k1 v0.7.1 as src/secp256k1 submodule and introduce
crypto_ecdsa / crypto_ecdh wrappers as drop-in replacements for the
OpenSSL ECDSA_verify / ECDSA_sign / ECDH_compute_key call sites used
by key.cpp and smessage.cpp. Wrappers preserve on-chain compatibility
(lax DER parsing, 65-byte recoverable compact sigs, SEC1 priv-key
DER round-trip, raw-X ECDH output for smsg KDF).
CMake wires the submodule and new sources into the build. Mid-refactor;
landing as a checkpoint before stacking sync-pipeline work on top.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two CI failures from the prior push:
1. MSYS2 mingw64's RocksDB headers (8.x+) use `using enum` and defaulted
operator== on user-defined types — both C++20-only. Bumped
CMAKE_CXX_STANDARD from 17 to 20 across the project. GCC 11.4 (Ubuntu),
GCC 14.x (MSYS2), and Apple Clang 16 all support what we need.
2. Ubuntu 22.04's librocksdb-dev ships neither a CMake config package nor
a rocksdb.pc file, so both find_package(RocksDB CONFIG) and
pkg_check_modules(rocksdb) fail. Added a manual find_path/find_library
fallback that creates a RocksDB::rocksdb IMPORTED target from the
raw header dir + .so, with a clear FATAL_ERROR if all three probes miss.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The secure-messaging store (smsgDB) used the LevelDB API directly. Mass-
mapped to the equivalent RocksDB types: leveldb::DB/Status/WriteBatch/
Iterator/Slice/ReadOptions/WriteOptions/WriteBatch::Handler -> rocksdb::*.
The RocksDB API surface for our usage is binary-compatible — pure namespace
substitution, no semantic changes. Consumers in rpcsmessage.cpp and
qt/messagemodel.cpp updated to match.
RocksDB now becomes a hard build dependency (was optional behind
BUILD_ROCKSDB). The chain-DB rocksdb backend is consequently always
available; -chaindb=leveldb remains the default until the Phase-4
LevelDB retirement. Removed the BUILD_ROCKSDB cmake option, the
#ifdef BUILD_ROCKSDB guards in txdb*, and the runtime error path
that triggered when the flag was off.
CI updated: librocksdb-dev (Ubuntu), mingw-w64-x86_64-rocksdb (MSYS2),
and rocksdb (Homebrew) added to all build jobs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Adds CRocksTxDB, the second concrete backend for CTxDBBase. Mirrors
CTxDB (LevelDB) one-for-one with rocksdb:: substitutions: same key
serialization (inherited from CTxDBBase), same active-batch semantics,
same LoadBlockIndex flow including the dbformat v3 chain-trust upgrade.
Build flag BUILD_ROCKSDB defaults OFF, so the existing LevelDB build is
untouched — RocksDB headers are only included when the flag is on, and
the entire .cpp file is wrapped in #ifdef BUILD_ROCKSDB.
Build system:
* Top-level option(BUILD_ROCKSDB ... OFF)
* find_package(RocksDB CONFIG) with pkg-config fallback
* Conditional list(APPEND CORE_SOURCES txdb-rocksdb.cpp)
* Conditional target_link_libraries(... RocksDB::rocksdb)
Data layout: RocksDB lives under <datadir>/rocksdb/, separate from
<datadir>/txleveldb/, so both backends can coexist for migration and
parity testing.
Acknowledged debt: LoadBlockIndex is duplicated between CTxDB and
CRocksTxDB. Will be extracted into CTxDBBase once the iterator and
batch abstractions are proven across both backends (M1.4 or later).
Validated: default-OFF build still compiles cleanly. The BUILD_ROCKSDB=ON
path is NOT compile-validated yet — RocksDB isn't installed on this dev
machine. The code is straight namespace substitution from the working
LevelDB backend; whoever first enables the flag should report any
header/API drift between rocksdb releases.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
M1.2 (mechanical):
Convert every CTxDB& parameter and reference across main.{h,cpp},
wallet.{h,cpp}, and smessage.cpp to CTxDBBase&. Local instantiations
like `CTxDB txdb("r");` are deliberately left as concrete LevelDB —
they'll move behind a factory in M1.4 once the parity harness exists.
CTxDB IS-A CTxDBBase, so all existing call sites continue to compile:
a CTxDB instance binds to a CTxDBBase& parameter automatically.
Forward declaration `class CTxDB;` in main.h replaced with
`class CTxDBBase;`.
Parallel work (snapshotnet + version bump to 5.9.4 + checkpoints/init
/protocol/version edits) included so origin/master matches the local
working tree in one push.
NOT YET COMPILE-TESTED: pushed at the user's explicit request before
the build verification step. If CI fails, expected breakage is in
files that include main.h transitively but not txdb-base.h — fix is
to add `#include "txdb-base.h"` (or rely on the existing txdb.h which
pulls it in).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pairs net.h heartbeat-throttle field with the IBD header-sync fix
in 2a484e4, and ships a full RPC reference doc.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nodes syncing from zero would accept blocks normally up to ~6000 then
stall permanently with askfor_queue=0 and no new blocks. Root cause: a
broken feedback loop between the header planner and block downloader.
Blocks consume entries from mapHeaderSync (MAX 15000) while getheaders
refills only 2000 at a time; when the cache drains, hashBestHeaderSync
falls to 0 and every refill site is guarded on it being non-zero, so
the pipeline deadlocks with no recovery path.
Recovery paths added:
- ProcessBlock: when the cache is empty during IBD after accepting a
block, broadcast getheaders to all full-node peers. This restarts
the planner at the exact point it dies.
- Stall detection: send getheaders alongside the existing getblocks.
getblocks alone cannot refill the header cache.
- SendMessages: belt-and-suspenders, re-request headers every 30s
while hashBestHeaderSync == 0 in IBD, independent of stall state.
Also fix a secondary issue: GetHeaderSyncDownloadPath walks back from
the tip and breaks on the first TTL-evicted entry. The accumulated
partial tail has a parent that is neither in mapBlockIndex nor
mapHeaderSync, so requesting those blocks would produce orphans.
Discard the partial path on a gap; the recovery paths above will
re-request the missing range.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follow-up to #5. Addresses three risks with the apply=true path:
- MoneyRange sanity gate: refuse to persist a recalculated supply that is
negative or above MAX_MONEY (2,222,222 TRI). A walk that produces an
out-of-range figure indicates a bug (orphan contamination, missing
prevout), not real chain state. Prevents corrupting nMoneySupply with
junk values.
- Atomic apply: wrap every per-block WriteBlockIndex in a single
TxnBegin/TxnCommit so a mid-walk failure leaves on-disk state
untouched instead of half-rewritten.
- Single chain walk: cache (valueOut - valueIn) per block during the
dry-run pass and reuse the cached deltas during apply. Previous code
walked the full chain twice, roughly doubling apply runtime on a
2.2M-block chain.
Help text now warns that the RPC holds cs_main for the full walk and
blocks new blocks, wallet ops, and other RPC for the duration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Auto-detect and use ccache as compiler launcher when available
- Add ENABLE_UNITY_BUILD option for jumbo builds (batch size 8)
- Precompile heavy STL/Boost/OpenSSL headers for C++ targets
- Exclude hash9 crypto from unity builds (colliding static symbols)
- Fix RAND_screen() compile error on OpenSSL 3.x (removed API)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- BIP 31 ping/pong with 2-min heartbeat, RTT tracking, 3-miss disconnect
- Reduce max outbound from 16 to 8, add -maxoutbound flag
- Emergency reconnection: 15s re-seed when 0 peers, 30s when 1 peer
- Inactivity timeout reduced from 90min to 10min (dead peer detection)
- Header sync TTL extended from 5min to 15min for Tor latency
- Reserve 2 inbound slots for known seed nodes at capacity
- Enhanced address gossip: hourly rebroadcast, getaddr from all peers
- New getnetworkstability RPC with isolation risk assessment
- getpeerinfo now includes pingtime, blocksdelivered, avglatency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add checkpoints through block 2,209,000 to lock canonical chain
- Ban peers on incompatible forks (no common blocks after 3 getblocks)
- Auto-checkpoint: finalize blocks at MAX_REORG_DEPTH to prevent deep reorgs
- Require 10% trust delta for side-chain reorgs (first-seen advantage)
- Add gencheckpoints RPC command for easy future checkpoint generation
- Add wallet onion address to hardcoded seed list
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Reduce equal-trust reorg cooldown from 10min to 2min for faster convergence
- Tighten future block drift from 3min to 90sec to shrink competing-block window
- Require 2+ peers before staking (was 1) to prevent isolated fork creation
- Push full blocks directly to peers instead of inv-only (saves 1-2s Tor roundtrip)
- Add periodic 45-second chain-tip sync to detect and resolve silent forks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Version System:
- Unified version display as v5.8.2 (removed trailing .0)
- Single source of truth in clientversion.h
- Fixed version.cpp to use CLIENT_VERSION_* macros
Staking Improvements:
- Enhanced getstakinginfo with detailed diagnostics
- Shows specific reasons when staking is disabled
- Added wallet lock status, mature coins check, peer count
Performance & Sync:
- Added checkpoint at block 2,200,000 (hash: 0a8d0442...)
- 14 total checkpoints for faster sync
- Enhanced recalculatesupply RPC with safety validation
- Prevents changes > 1M TRI, fixes money supply tracking
Anti-Fork Protection:
- Enhanced reorganize logging with fork details
- Shows old/new tips, fork point, disconnect/connect counts
- Works with existing anti-oscillation and chain re-eval fixes
Recovery Tools (Krystie):
- -reindex flag for full block index rebuild
- recalculatesupply RPC to fix money supply from UTXOs
- SumUtxoValues() helper for UTXO set analysis
All changes are non-consensus and wallet-safe.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Krystie <krystie@cryptographic-triangles.org>
Guard pindexBest and pprev dereferences that segfault during IBD
block serving when chain state is incomplete:
- kernel.cpp: CheckStakeKernelHash null pindexBest during PoS validation
- main.cpp: InvalidChainFound null pprev/pindexBest on rejected blocks
- main.cpp: SetBestChain null pprev in trust calculation
- main.cpp: ProcessBlock orphan handler null pindexBest
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix moneysupply calculation in FastImportBlockFile and ConnectBlock assumevalid path
- Route bootstrap downloads through Tor SOCKS proxy (no more clearnet leaks)
- Remove hardcoded clearnet fallback IP from bootstrap
- Fix snprintf missing argument in walletmodel.cpp narration key (UB/crash)
- Fix potential null deref from db_strerror() in rpcwallet.cpp
- Filter non-.onion addresses from HTTPS seed list parser
- Add periodic re-seeding when node has 0 outbound peers
- Make clientversion.h single source of truth for version display string
- Remove redundant DISPLAY_VERSION macros from version.h
- Update README: max supply 2,222,222, CMake build instructions, Tor-only config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace FutureDrift(GetAdjustedTime()) with GetTime() + 15min in CheckBlock
and header-sync validation. GetAdjustedTime() incorporates peer-reported
time offsets that vary between Tor nodes, causing the same block to be
accepted by some nodes and rejected by others — the primary cause of
persistent chain forks. AcceptBlock still enforces tight 3-min drift rules
deterministically against the previous block timestamp.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes for the fork-oscillation problem where same-version nodes
keep disagreeing on the chain tip:
1. Prune setStakeSeen on reorg — disconnected PoS blocks' stake entries
were never removed, blocking acceptance of valid competing blocks
and preventing chain convergence after reorganizations.
2. Remove global nBestHeight from PastDrift/FutureDrift — the no-argument
overloads used the mutable global nBestHeight to decide between 3-min
and 10-min timestamp drift at the V5.4 fork boundary (block 2186941).
Nodes at different heights applied different validation rules to the
same block, causing a permanent consensus split. Now always uses
post-fork 3-min rules since all nodes are well past the fork.
3. Anti-oscillation for equal-trust reorgs — the hash-based tiebreaker
now only fires for shallow forks (parent in main chain). Deep forks
with equal trust no longer trigger reorgs, preventing the Tor-latency-
induced ping-pong where nodes flip between competing chains.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ubuntu 22.04 ships Boost 1.74; the previous 1.75 minimum rejected it.
Also remove boost_system from required components since it has been
header-only since Boost 1.69 and modern installs (macOS Homebrew 1.90)
don't ship a separate cmake config for it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove legacy build files (Makefile, makefile.unix/mingw/osx,
triangles-qt.pro) and replace with CMake build system. Includes
find modules for all dependencies, LevelDB bundled build, and
updated CI workflow for CMake + Ninja on all platforms.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>