Compare commits

...

19 Commits

Author SHA1 Message Date
sami7777 65b9417c28 Eliminate all blocking LOCK(cs_wallet) calls from UI thread
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
During sync, NotifyTransactionChanged fires for every wallet tx in
every block, each triggering 3 blocking LOCK(cs_wallet) calls on
the UI thread: updateWallet, GetAllBalances, getNumTransactions.
With the block processing thread holding cs_wallet almost continuously,
the UI thread blocks waiting for the lock - causing "not responding".

Fixes:
- GetAllBalances: LOCK → TRY_LOCK, returns false if busy
- updateWallet (tx table): LOCK → TRY_LOCK, skips if busy
- updateTransaction: removed checkBalanceChanged() call entirely
  (pollBalanceChanged timer handles it every 2.5s with TRY_LOCK)
- getNumTransactions: replaced with rowCount() from cached model

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 19:32:04 -07:00
sami7777 ed87543153 Fix Linux Qt build: int64_t/qint64 type mismatch
On Linux, int64_t is long but qint64 is long long - different types
that can't bind to the same reference. Use int64_t locals to match
the GetAllBalances signature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 18:05:43 -07:00
sami7777 6e9dbb1aa9 Bump version to 5.3.5 - fix out-of-sync display for PoS chains
Remove time-based sync check that showed "out of sync" when blocks
were >6 hours old. For PoS chains with few stakers, blocks can be
hours apart - that's idle, not out of sync. Now uses block count
only. Also adds periodic UI refresh every 30s and switches cached
stake weight from volatile to std::atomic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 17:59:18 -07:00
SamiAhmed7777 a6ec711cfa Merge pull request #1 from SamiAhmed7777/cleanup/desloppify
Code cleanup: Documentation and C++11 compliance fixes
2026-03-22 15:43:35 -07:00
Krystie 6877aeaddb chore: Update .gitignore for build artifacts 2026-03-22 22:54:21 +01:00
Krystie 60067e1a88 fix: Add space between string literals and PRId64 macros
Fixes C++11 literal-suffix warnings in util.h, net.h, and alert.cpp.
Required space between string literal and macro per C++11 standard.

No functional changes - formatting only.
2026-03-22 22:46:48 +01:00
Krystie e91ccd8786 docs: Document critical TODOs/FIXMEs with context
- Add CLEANUP_NOTES.md documenting cleanup strategy
- Add TODO_DOCUMENTATION.md with detailed context for all TODOs
- Improve inline comments for thread safety issue in rpcmining.cpp
- Clarify potential collision note in walletmodel.cpp
- Remove unclear 'DRM' comment, replace with descriptive text

No functional changes - documentation only.
2026-03-22 22:26:52 +01:00
sami7777 96fb7d5040 Bump version to 5.3.4 - fix UI freezing during staking
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
Move GetStakeWeight() off the UI thread by caching in the staking
miner thread. Replace blocking LOCK(cs_vNodes) with TRY_LOCK in
clientmodel and staking icon updates. Fix out-of-sync label getting
stuck when disconnected. Add daemon bootstrap and faster IBD pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 21:28:11 -07:00
sami7777 47cf8abbda Add daemon bootstrap, repeating bootstrap prompt, faster IBD pipeline
- Daemon: add -bootstrap flag to download chain files from server on startup
- Qt: bootstrap prompt shows every launch with "Don't show this again" checkbox
- IBD: reduce pipeline refill interval from 1000 to 100 blocks for faster sync
- Add bootstrap.o to daemon makefiles (mingw + unix)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 21:35:12 -07:00
sami7777 2abd494fec Bump version to 5.3.3 and update CI version
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 18:54:44 -07:00
sami7777 378b0370e3 Improve peer connectivity, UI responsiveness, and add auto-bootstrap
Peer connectivity (small network optimizations):
- Reduce hardcoded seed fallback delay from 30s to 10s
- Reduce peer retry interval from 600s to 120s
- Lower staking minimum peers from 3 to 1
- Relay addr messages to all connected peers instead of just 2

UI responsiveness:
- Add progress reporting to ScanForWalletTransactions (every 10K blocks)
- Use TRY_LOCK in WalletModel::pollBalanceChanged to avoid blocking UI
- Use TRY_LOCK in TransactionTablePriv::refreshWallet with retry

Auto-bootstrap:
- Add bootstrap.h/cpp with HTTP download via boost::asio
- On first run, prompt user to download blockchain snapshot from
  bootstrap.cryptographic-triangles.org directly into data directory
- Downloads filelist.txt manifest then each file with progress dialog
- Falls back to IP 194.233.88.206 if DNS fails
- Gracefully continues to P2P sync if bootstrap unavailable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 18:02:47 -07:00
sami7777 61f22fcfd4 Fix display version string to match 5.3.2
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
DISPLAY_VERSION_REVISION in version.h was still set to 1, causing the
internal version string to show v5.3.1.0 instead of v5.3.2.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 14:52:44 -07:00
sami7777 bf1bf393c8 Bump version to 5.3.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 14:18:06 -07:00
sami7777 39e244a11c Fix build: random_shuffle removal, Windows daemon missing objects
- Replace random_shuffle (removed in C++17) with std::shuffle in wallet.cpp
- Add -std=c++17 to makefile.mingw (Windows daemon was missing it)
- Add lz4.o, tor_embed_hooks.o, tor_embedded.o to makefile.mingw OBJS
- Add build rules for new objects in makefile.mingw
- Simplify Tor embedded build to use aggregate libtor.a

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:47:42 -07:00
sami7777 6724dfc832 Fix build: revert shared_ptr in RPC, replace auto_ptr with unique_ptr
- trianglesrpc.cpp: revert std::shared_ptr back to boost::shared_ptr
  (boost::signals2::slot::track() requires boost::shared_ptr)
- miner.cpp: auto_ptr → unique_ptr (auto_ptr removed in C++17,
  caught by macOS clang)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:34:16 -07:00
sami7777 9dadba6b09 Fix build: tuple access syntax, namespace, LZ4 separate compilation
- miner.cpp: .get<N>() → std::get<N>() (boost::tuple member syntax
  doesn't exist on std::tuple)
- script.cpp: remove 'using namespace boost' (no boost headers left)
- smessage.cpp: include lz4/lz4.h instead of lz4/lz4.c (U64 typedef
  conflict with xxhash when LZ4 1.10.0 source included in same TU)
- makefile.unix: add obj/lz4.o as separate compilation unit
- triangles-qt.pro: add src/lz4/lz4.c to SOURCES

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 02:46:37 -07:00
sami7777 c432817d5f Bump version to 5.3.1
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 02:36:12 -07:00
sami7777 7ceb1f6a4d Replace boost with C++17 std equivalents, upgrade LZ4 to 1.10.0
- boost::tuple → std::tuple (serialize.h, miner.cpp, script.cpp, walletdb.cpp)
- boost::shared_ptr → std::shared_ptr (trianglesrpc.cpp)
- boost::variant → std::variant for CTxDestination (script.h)
- boost::get → std::get_if (main.cpp, rpcblockchain.cpp, coincontroldialog.cpp, wallet.cpp)
- boost::apply_visitor → std::visit (base58.h, script.cpp, rpcwallet.cpp, test/base58_tests.cpp)
- boost::static_visitor removed from all visitor classes
- boost::lexical_cast → std::to_string/std::stoll (smessage.cpp, rpcsmessage.cpp)
- Removed unused boost/lexical_cast.hpp includes (rest.cpp, trianglesrpc.cpp)
- Removed boost/variant/get.hpp include (rpcdump.cpp)
- Upgraded vendored LZ4 from 1.1.3 to 1.10.0
- Updated LZ4_compress() → LZ4_compress_default() (smessage.cpp)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 02:31:23 -07:00
sami7777 1a2793bb88 Fix build: replace remaining list_of calls, remove register keyword
- Replace boost::assign::list_of/map_list_of with brace-init in
  rpcrawtransaction.cpp (7 call sites missed in previous commit)
- Remove C++17-banned 'register' keyword from lz4.c (macOS build fix)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 02:07:49 -07:00
53 changed files with 4771 additions and 1036 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ on:
workflow_dispatch:
env:
VERSION: "5.2.0"
VERSION: "5.3.5"
jobs:
build-windows-qt:
+3
View File
@@ -52,3 +52,6 @@ triangles.conf
*.key
*.cert
*.gpg
*.o
src/trianglesd
src/obj/
+94
View File
@@ -0,0 +1,94 @@
# Triangles Codebase Cleanup Notes
## Overview
Systematic code quality improvements for the Triangles cryptocurrency codebase (v5.3.4+).
**Goal:** Improve maintainability without changing behavior or breaking consensus.
## Inventory
### TODOs/FIXMEs Found (38 total)
#### High Priority (Affects Safety/Correctness)
- `rpcmining.cpp:263` - **Thread safety issue** in mapNewBlock (static variable, no mutex)
- `walletmodel.cpp:249` - **Potential collision** in balance calculation
- `smessage.cpp:863, 2219, 2373` - **File size limit** (files must be split if >2GB)
#### Medium Priority (Encapsulation/Security)
- `protocol.h:50, 100, 132` - Public members should be private (3 locations)
- `wallet.h:378` - nOrderPos calculation should move elsewhere
- `wallet.cpp:733, 1732` - Change output handling needs improvement
- `rpcwallet.cpp:1474, 1513, 1569` - SecureString operator= missing (forced .c_str())
#### Low Priority (Nice-to-Have)
- `util.cpp:1322` - Disabled feature needs verification
- `tor/tor_embedded.cpp:209` - Tor 0.4.9+ shutdown API upgrade
- `init.cpp:442` - Remaining sanity checks (see Bitcoin issue #4081)
- `rpcmining.cpp:232` - DRM comment (unclear what it means)
- `smessage.cpp:*` - Various improvements (hash inclusion, thread safety, defaults)
- `qt/*` - UI improvements (decrypt not supported, message filtering, OSX startup)
#### External/Third-Party (Don't Touch)
- `leveldb/*` - LevelDB library TODOs (upstream issues)
## Code Quality Issues
### Using namespace std (37 files)
All in .cpp files - **this is fine for .cpp**, problematic only in headers.
No headers have this issue, so **no action needed**.
### Printf/Cout Usage (56 files)
Most cryptocurrency code uses printf for early init/error handling before logging is available.
**Review needed:** Check if these are legitimate early-init cases or should use LogPrintf.
## Cleanup Plan (Safest → Riskiest)
### Phase 1: Documentation & Comments ✅ SAFE
1. Document all TODOs with context (why deferred, what's needed)
2. Add function-level comments for complex logic
3. Improve inline comments for clarity
### Phase 2: Low-Risk Code Quality 🟨 MEDIUM RISK
4. Fix compiler warnings (-Wall -Wextra)
5. Add const correctness where missing
6. Remove commented-out dead code
7. Standardize code formatting (if inconsistent)
### Phase 3: Functional Improvements 🟥 HIGH RISK (Skip for now)
8. Fix thread safety issue in rpcmining.cpp (requires testing)
9. Improve protocol.h encapsulation (may affect other code)
10. Address >2GB file handling in smessage.cpp
## Decisions
### What NOT to Change
- **Consensus code** - main.cpp (validation), kernel.cpp (PoS), miner.cpp (staking)
- **Serialization** - Any READWRITE, serialize/deserialize code
- **Protocol constants** - Network message types, version numbers
- **Third-party code** - leveldb/, tor/, sph_types.h, xxhash/, lz4/
### What's Safe to Change
- Comments and documentation
- Variable names (in non-consensus code)
- Code organization (splitting large functions)
- Logging statements
- UI code (qt/)
- RPC interface (as long as API contract preserved)
## Initial Cleanup (2026-03-22)
### Actions Taken
1. Created this documentation file
2. Created cleanup/desloppify branch
3. Inventoried all TODOs/FIXMEs
### Next Steps
1. Add documentation comments to TODO items
2. Review printf/cout usage patterns
3. Check for compiler warnings
4. Consider low-risk improvements
## Notes
- This is a Bitcoin-derived codebase, so many patterns follow Bitcoin Core conventions
- Recent v5.3.x work already modernized to C++17 and removed Boost - good foundation
- Code is generally well-structured; main improvements are documentation and minor cleanup
+21 -26
View File
@@ -11,7 +11,7 @@ trianglesd / triangles-qt
├── tor_embedded.cpp ← calls tor_run_main() in a background thread
├── tor_process.cpp ← fallback: launches external tor binary (already works)
├── onion_v3.cpp ← V3 onion address generation / SOCKS5 proxy logic
└── libtor.a ← static Tor library (built from official source)
└── libtor.a ← aggregate static Tor library (built from official source)
```
When compiled with `ENABLE_TOR_EMBEDDED`, the wallet calls `tor_run_main()` from
@@ -34,7 +34,7 @@ This puts the full Tor source at `src/tor/tor-src/`.
Current imported checkout in this repo: `release-0.4.9` at commit `1442ca4`.
There is also a helper build script at `src/tor/build-libtor.sh`.
## Step 2: Build libtor.a (Linux)
## Step 2: Build libtor.a
Tor uses autotools. Build it as a static library:
@@ -71,10 +71,9 @@ Or from the repo root:
./src/tor/build-libtor.sh
```
After building, the static libraries are in `src/tor/tor-src/src/`:
- `src/core/libtor-app.a`
After building, the static libraries are in `src/tor/tor-src/`:
- `libtor.a`
- `src/lib/libtor-*.a` (multiple component libs)
- `src/trunnel/libor-trunnel.a`
The header `src/feature/api/tor_api.h` provides the public C API:
```c
@@ -98,22 +97,14 @@ make -f makefile.unix \
```
You may need to adjust the `-l` flags in the makefile depending on the exact
library names Tor produces. Check `src/tor/tor-src/src/` after building:
library names Tor produces. Check `src/tor/tor-src/` after building:
```bash
find tor/tor-src/src -name '*.a' | sort
find tor/tor-src -name '*.a' | sort
```
Common libraries to link (order matters):
```
-ltor-app -lor -lor-ctime -lor-evloop -lor-event -lor-compress
-lor-container -lor-crypt-ops -lor-encoding -lor-err -lor-fs
-lor-intmath -lor-lock -lor-log -lor-malloc -lor-math -lor-memarea
-lor-meminfo -lor-net -lor-osinfo -lor-process -lor-sandbox
-lor-smartlist-core -lor-string -lor-term -lor-thread -lor-time
-lor-tls -lor-trace -lor-version -lor-wallclock
-lor-trunnel
```
On the imported `release-0.4.9` checkout in this repo, the simplest working
link path is the aggregate `libtor.a` plus the normal dependency libraries.
### Windows (triangles-qt.pro)
@@ -126,9 +117,14 @@ qmake "USE_TOR_EMBEDDED=1" \
Both build systems now default to:
- source root: `src/tor/tor-src`
- include path: `src/tor/tor-src/src/feature/api`
- library paths: `src/tor/tor-src/src/core`, `src/tor/tor-src/src/lib`, `src/tor/tor-src/src/trunnel`
- library path: `src/tor/tor-src`
- embedded Tor library: `-ltor`
Override `TOR_EMBEDDED_LIBS` if the actual Tor static library names differ on your platform/build.
On Windows, the imported Tor `0.4.9.5` build also needed:
- `-llzma`
- `-lzstd`
- `-liphlpapi`
- `-lshlwapi` (already linked by Triangles)
## Step 4: Wire into init.cpp
@@ -182,10 +178,9 @@ The embedded Tor respects these command-line flags:
src/tor/
├── tor-src/ ← git submodule (official Tor repo)
│ └── src/
│ ├── core/libtor-app.a
│ ├── lib/libor-*.a
│ ├── trunnel/libor-trunnel.a
│ ├── lib/libtor-*.a
│ └── feature/api/tor_api.h
│ └── libtor.a
├── tor_embedded.h ← CTorEmbedded class header
├── tor_embedded.cpp ← implementation (calls tor_run_main)
├── tor_process.h ← external Tor process manager (fallback)
@@ -213,11 +208,11 @@ object instead of raw `tor_main(int argc, char** argv)`.
**Tor fails to bootstrap**: Check firewall rules. Tor needs outbound TCP to the
Tor network (ports 80, 443, 9001, 9030).
**Link errors with libtor**: The Tor static libraries must be linked in
dependency order. If you get undefined symbols, reorder the `-l` flags or use
`-Wl,--start-group ... -Wl,--end-group` to resolve circular deps:
**Link errors with libtor**: Prefer the aggregate `libtor.a` from the top level
of the Tor build tree. On the imported Windows/MSYS2 build in this repo, the
minimal verified link set was:
```
LIBS += -Wl,--start-group -ltor-app -lor -lor-ctime ... -Wl,--end-group
-ltor -levent -lssl -lcrypto -lz -llzma -lzstd -lws2_32 -liphlpapi -lshlwapi
```
**OpenSSL version mismatch**: Both Tor and Triangles must link against the same
+3 -3
View File
@@ -3,7 +3,7 @@
# Generated by qmake (3.1) (Qt 5.15.18)
# Project: triangles-qt.pro
# Template: app
# Command: C:/msys64/mingw64/bin/qmake-qt5.exe -o Makefile triangles-qt.pro USE_QRCODE=1 USE_UPNP=-
# Command: C:/msys64/mingw64/bin/qmake-qt5.exe -o Makefile triangles-qt.pro -spec win32-g++ CONFIG+=release
#############################################################################
MAKEFILE = Makefile
@@ -156,7 +156,7 @@ Makefile: triangles-qt.pro C:/msys64/mingw64/share/qt5/mkspecs/win32-g++/qmake.c
C:/msys64/mingw64/lib/qtmain.prl \
C:/msys64/mingw64/share/qt5/mkspecs/features/build_pass.prf \
src/qt/triangles.qrc
$(QMAKE) -o Makefile triangles-qt.pro USE_QRCODE=1 USE_UPNP=-
$(QMAKE) -o Makefile triangles-qt.pro -spec win32-g++ CONFIG+=release
C:/msys64/mingw64/share/qt5/mkspecs/features/spec_pre.prf:
C:/msys64/mingw64/share/qt5/mkspecs/qdevice.pri:
C:/msys64/mingw64/share/qt5/mkspecs/features/device_config.prf:
@@ -244,7 +244,7 @@ C:/msys64/mingw64/lib/qtmain.prl:
C:/msys64/mingw64/share/qt5/mkspecs/features/build_pass.prf:
src/qt/triangles.qrc:
qmake: FORCE
@$(QMAKE) -o Makefile triangles-qt.pro USE_QRCODE=1 USE_UPNP=-
@$(QMAKE) -o Makefile triangles-qt.pro -spec win32-g++ CONFIG+=release
qmake_all: FORCE
+124
View File
@@ -0,0 +1,124 @@
# TODO/FIXME Documentation
Detailed context for each TODO/FIXME in the codebase.
## Critical (Needs Attention)
### src/rpcmining.cpp:263 - Thread Safety Issue
```cpp
static mapNewBlock_t mapNewBlock; // FIXME: thread safety
```
**Issue:** Static variable accessed by multiple RPC threads without mutex protection.
**Impact:** Potential race condition in getwork RPC (used for mining).
**Status:** Low priority - PoW mining ended at block 9000, this code path rarely used.
**Fix:** Add std::mutex and lock_guard if getwork usage increases.
### src/qt/walletmodel.cpp:249 - Collision Risk
```cpp
if((total + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future
```
**Issue:** Balance check may have edge case causing transaction collisions.
**Context:** In createTransaction fee calculation loop.
**Status:** Needs investigation - unclear what "collisions" means here.
**Fix:** Review Bitcoin Core's current implementation of this logic.
### src/smessage.cpp - File Size Limits
```cpp
// Lines 863, 2219, 2373: "TODO files must be split if > 2GB"
```
**Issue:** Secure message storage files not split when exceeding 2GB.
**Impact:** May fail on 32-bit systems or with large message volumes.
**Status:** Low priority - unlikely to reach 2GB in practice.
**Fix:** Implement file rotation when approaching 2GB limit.
## Medium Priority (Encapsulation/API)
### src/protocol.h - Make Members Private
```cpp
// Lines 50, 100, 132: "TODO: make private (improves encapsulation)"
```
**Issue:** CAddress, CInv, CMessageHeader have public data members.
**Impact:** Poor encapsulation, harder to maintain invariants.
**Status:** Deferred - would require extensive refactoring.
**Fix:** Add getter/setter methods, make members private, update all call sites.
### src/wallet.h:378 - nOrderPos Calculation
```cpp
nOrderPos = -1; // TODO: calculate elsewhere
```
**Issue:** Transaction ordering position calculated in constructor.
**Impact:** Minor - works but not ideal separation of concerns.
**Status:** Deferred - no functional issue.
**Fix:** Move calculation to WalletDB when transaction is added.
### src/rpcwallet.cpp - SecureString Operator
```cpp
// Lines 1474, 1513, 1569: "TODO: get rid of this .c_str()"
```
**Issue:** SecureString missing operator=(std::string).
**Impact:** Forced to use .c_str() which exposes password temporarily.
**Status:** Deferred - would require SecureString class modification.
**Fix:** Add `SecureString& operator=(const std::string&)` method.
## Low Priority (Nice-to-Have)
### src/util.cpp:1322 - Disabled Feature
```cpp
// TODO: This is currently disabled because it needs to be verified to work
```
**Context:** File descriptor management code.
**Status:** Intentionally disabled pending verification.
**Fix:** Test thoroughly, then enable if needed.
### src/tor/tor_embedded.cpp:209 - Tor Shutdown API
```cpp
// TODO: Tor 0.4.9+ may add tor_api_shutdown(), use it when available
```
**Context:** Embedded Tor cleanup.
**Status:** Waiting for upstream Tor API.
**Fix:** Check Tor 0.4.9+ releases for new API, integrate when stable.
### src/init.cpp:442 - Sanity Checks
```cpp
// TODO: remaining sanity checks, see #4081
```
**Context:** Bitcoin Core issue #4081 - additional startup sanity checks.
**Status:** Deferred - core checks already in place.
**Fix:** Review Bitcoin Core's current sanity check implementation.
### src/rpcmining.cpp:232 - DRM Comment
```cpp
CDataStream(coinbase, SER_NETWORK, PROTOCOL_VERSION) >> pblock->vtx[0]; // FIXME - DRM!
```
**Issue:** Unclear what "DRM" means here - likely "Data Race Maybe"?
**Status:** Needs clarification from original author.
**Fix:** Investigate if there's an actual issue, otherwise remove comment.
## Deferred (External/Low Impact)
### LevelDB TODOs (src/leveldb/*)
**Status:** Upstream LevelDB issues - don't modify embedded library.
**Action:** None - track upstream LevelDB project.
### Qt TODOs (src/qt/*)
**Status:** UI improvements, not critical.
**Action:** Track as nice-to-have enhancements.
### Secure Message TODOs (src/smessage.cpp)
Multiple minor improvements suggested:
- Include hash in certain operations
- Improve thread shutdown
- Set default recv/recvAnon behavior
- Update outbox after PoW completes
**Status:** Non-critical enhancements.
**Action:** Consider for future encrypted messaging upgrades.
## Summary
**Critical:** 3 items (thread safety, balance collision, file limits)
**Medium:** 6 items (encapsulation, SecureString)
**Low:** 5 items (disabled features, upstream APIs)
**Deferred:** ~24 items (external libs, minor enhancements)
**Recommendation:** Focus on documenting critical items in code comments, defer fixes until specific issues arise.
+2 -2
View File
@@ -53,8 +53,8 @@ std::string CUnsignedAlert::ToString() const
return strprintf(
"CAlert(\n"
" nVersion = %d\n"
" nRelayUntil = %"PRId64"\n"
" nExpiration = %"PRId64"\n"
" nRelayUntil = %" PRId64 "\n"
" nExpiration = %" PRId64 "\n"
" nID = %d\n"
" nCancel = %d\n"
" setCancel = %s\n"
+2 -2
View File
@@ -260,7 +260,7 @@ public:
* The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
*/
class CTrianglesAddress;
class CTrianglesAddressVisitor : public boost::static_visitor<bool>
class CTrianglesAddressVisitor
{
private:
CTrianglesAddress *addr;
@@ -294,7 +294,7 @@ public:
bool Set(const CTxDestination &dest)
{
return boost::apply_visitor(CTrianglesAddressVisitor(this), dest);
return std::visit(CTrianglesAddressVisitor(this), dest);
}
bool IsValid() const
+378
View File
@@ -0,0 +1,378 @@
// Copyright (c) 2024 Triangles developers
// Distributed under the MIT/X11 software license
#include "bootstrap.h"
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/algorithm/string.hpp>
#include <zlib.h>
#include <fstream>
#include <sstream>
#include <cstdio>
#include <cstring>
namespace fs = boost::filesystem;
using boost::asio::ip::tcp;
namespace Bootstrap {
bool NeedsBootstrap(const fs::path& dataDir)
{
return !fs::exists(dataDir / "blk0001.dat");
}
bool DownloadFile(const std::string& host, const std::string& urlPath,
const fs::path& destPath,
ProgressCallback progressFn,
std::string& strError)
{
try {
boost::asio::io_context io_context;
tcp::resolver resolver(io_context);
boost::system::error_code resolve_ec;
tcp::resolver::results_type endpoints =
resolver.resolve(host, std::to_string(PORT), resolve_ec);
if (resolve_ec) {
strError = "Cannot resolve host: " + host;
return false;
}
tcp::socket socket(io_context);
boost::asio::connect(socket, endpoints);
// Send HTTP GET request
std::string request =
"GET " + urlPath + " HTTP/1.1\r\n"
"Host: " + host + "\r\n"
"Connection: close\r\n"
"User-Agent: Triangles\r\n"
"\r\n";
boost::asio::write(socket, boost::asio::buffer(request));
// Read response headers
boost::asio::streambuf response_buf;
boost::asio::read_until(socket, response_buf, "\r\n\r\n");
std::istream response_stream(&response_buf);
// Parse status line
std::string http_version;
unsigned int status_code = 0;
response_stream >> http_version >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (status_code != 200) {
strError = "HTTP error " + std::to_string(status_code) + " for " + urlPath;
return false;
}
// Parse headers for Content-Length
int64_t content_length = 0;
std::string header_line;
while (std::getline(response_stream, header_line) && header_line != "\r") {
std::string lower_header = header_line;
std::transform(lower_header.begin(), lower_header.end(),
lower_header.begin(), ::tolower);
if (lower_header.find("content-length:") == 0) {
content_length = std::stoll(header_line.substr(header_line.find(':') + 1));
}
}
// Open output file
FILE* file = fopen(destPath.string().c_str(), "wb");
if (!file) {
strError = "Cannot create file: " + destPath.string();
return false;
}
int64_t bytes_written = 0;
// Write any data remaining in the header buffer (body starts here)
if (response_buf.size() > 0) {
std::istreambuf_iterator<char> eos;
std::string remaining(std::istreambuf_iterator<char>(response_stream), eos);
if (!remaining.empty()) {
fwrite(remaining.data(), 1, remaining.size(), file);
bytes_written += remaining.size();
}
}
// Read remaining body in chunks
std::vector<char> chunk(65536); // 64 KB
boost::system::error_code ec;
int64_t last_progress = 0;
while (true) {
size_t n = socket.read_some(boost::asio::buffer(chunk), ec);
if (n > 0) {
fwrite(chunk.data(), 1, n, file);
bytes_written += n;
// Report progress every 256 KB
if (progressFn && (bytes_written - last_progress >= 262144)) {
last_progress = bytes_written;
progressFn(bytes_written, content_length);
}
}
if (ec == boost::asio::error::eof)
break;
if (ec) {
fclose(file);
fs::remove(destPath);
strError = "Network error: " + ec.message();
return false;
}
}
fclose(file);
// Verify download size if Content-Length was provided
if (content_length > 0 && bytes_written != content_length) {
fs::remove(destPath);
strError = "Incomplete download: got " + std::to_string(bytes_written)
+ " of " + std::to_string(content_length) + " bytes";
return false;
}
return true;
} catch (std::exception& e) {
strError = std::string("Download failed: ") + e.what();
return false;
}
}
bool FetchFileList(const std::string& host,
std::vector<std::string>& files,
std::string& strError)
{
// Download filelist.txt to a temp file
fs::path tmpPath = fs::temp_directory_path() / "triangles_bootstrap_filelist.txt";
std::string urlPath = std::string(BASE_PATH) + "filelist.txt";
if (!DownloadFile(host, urlPath, tmpPath, nullptr, strError))
return false;
// Read lines
std::ifstream in(tmpPath.string().c_str());
if (!in.is_open()) {
strError = "Cannot read downloaded file list";
return false;
}
files.clear();
std::string line;
while (std::getline(in, line)) {
boost::trim(line);
if (!line.empty() && line[0] != '#')
files.push_back(line);
}
in.close();
fs::remove(tmpPath);
if (files.empty()) {
strError = "File list is empty";
return false;
}
return true;
}
// --- tar.gz bootstrap support ---
namespace {
// Parse a tar octal field (ASCII octal, null/space terminated)
static int64_t ParseTarOctal(const char* field, size_t len)
{
int64_t result = 0;
for (size_t i = 0; i < len && field[i] != '\0' && field[i] != ' '; i++) {
if (field[i] < '0' || field[i] > '7') continue;
result = (result << 3) | (field[i] - '0');
}
return result;
}
// Extract a tar.gz file to a destination directory
static bool ExtractTarGz(const fs::path& tarGzPath,
const fs::path& destDir,
std::string& strError)
{
gzFile gz = gzopen(tarGzPath.string().c_str(), "rb");
if (!gz) {
strError = "Cannot open " + tarGzPath.string();
return false;
}
gzbuffer(gz, 262144); // 256 KB buffer for performance
char header[512];
while (true) {
int bytesRead = gzread(gz, header, 512);
if (bytesRead == 0) break; // EOF
if (bytesRead != 512) {
strError = "Truncated tar header";
gzclose(gz);
return false;
}
// End-of-archive marker (zero block)
bool allZero = true;
for (int i = 0; i < 512; i++) {
if (header[i] != 0) { allZero = false; break; }
}
if (allZero) break;
// Parse filename: name (offset 0, 100 bytes) + optional prefix (offset 345, 155 bytes)
char name[101] = {0};
char prefix[156] = {0};
memcpy(name, header, 100);
memcpy(prefix, header + 345, 155);
std::string fullName;
if (prefix[0] != '\0')
fullName = std::string(prefix) + "/" + std::string(name);
else
fullName = std::string(name);
// Security: reject absolute paths and path traversal
if (fullName.empty() || fullName[0] == '/' || fullName.find("..") != std::string::npos) {
strError = "Unsafe path in tar archive: " + fullName;
gzclose(gz);
return false;
}
char typeflag = header[156];
int64_t fileSize = ParseTarOctal(header + 124, 12);
if (typeflag == '5' || (!fullName.empty() && fullName.back() == '/')) {
// Directory entry
fs::create_directories(destDir / fullName);
} else if (typeflag == '0' || typeflag == '\0') {
// Regular file
fs::path filePath = destDir / fullName;
fs::create_directories(filePath.parent_path());
FILE* outFile = fopen(filePath.string().c_str(), "wb");
if (!outFile) {
strError = "Cannot create file: " + filePath.string();
gzclose(gz);
return false;
}
int64_t remaining = fileSize;
char buf[65536];
while (remaining > 0) {
int toRead = (remaining > (int64_t)sizeof(buf)) ? (int)sizeof(buf) : (int)remaining;
int n = gzread(gz, buf, toRead);
if (n <= 0) {
fclose(outFile);
strError = "Truncated tar data for: " + fullName;
gzclose(gz);
return false;
}
fwrite(buf, 1, n, outFile);
remaining -= n;
}
fclose(outFile);
// Skip padding to next 512-byte boundary
int64_t pad = (512 - (fileSize % 512)) % 512;
if (pad > 0) {
char padBuf[512];
if (gzread(gz, padBuf, (unsigned)pad) != (int)pad) {
strError = "Truncated tar padding for: " + fullName;
gzclose(gz);
return false;
}
}
} else {
// Unknown entry type - skip its data
int64_t totalSkip = fileSize + ((512 - (fileSize % 512)) % 512);
char skipBuf[512];
while (totalSkip > 0) {
int toRead = (totalSkip > 512) ? 512 : (int)totalSkip;
if (gzread(gz, skipBuf, toRead) != toRead) break;
totalSkip -= toRead;
}
}
}
gzclose(gz);
return true;
}
} // anonymous namespace
bool DownloadBootstrap(const std::string& host,
const fs::path& dataDir,
ProgressCallback progressFn,
std::string& strError)
{
bool gotBlockFile = false;
// Try downloading bootstrap.tar.gz first
fs::path tmpTarGz = dataDir / "bootstrap.tar.gz.tmp";
std::string tarUrl = std::string(BASE_PATH) + "bootstrap.tar.gz";
bool tarDownloaded = DownloadFile(host, tarUrl, tmpTarGz, progressFn, strError);
if (tarDownloaded) {
bool extractOk = ExtractTarGz(tmpTarGz, dataDir, strError);
fs::remove(tmpTarGz);
if (extractOk && fs::exists(dataDir / "blk0001.dat"))
gotBlockFile = true;
// If extraction failed, fall through to legacy path
}
if (!gotBlockFile) {
// Fallback: try filelist.txt + individual file downloads
std::string fallbackError;
std::vector<std::string> files;
if (!FetchFileList(host, files, fallbackError)) {
if (!tarDownloaded)
strError = strError + " (fallback also failed: " + fallbackError + ")";
else
strError = "Extraction failed: " + strError + " (fallback also failed: " + fallbackError + ")";
return false;
}
for (size_t i = 0; i < files.size(); i++) {
fs::path destPath = dataDir / files[i];
fs::create_directories(destPath.parent_path());
std::string urlPath = std::string(BASE_PATH) + files[i];
if (!DownloadFile(host, urlPath, destPath, progressFn, strError))
return false;
}
gotBlockFile = fs::exists(dataDir / "blk0001.dat");
}
if (!gotBlockFile) {
strError = "No blk0001.dat after download";
return false;
}
// Remove any extracted txleveldb/ and database/ - they were built on
// a different machine and won't work here. FastImportBlockFile() will
// rebuild the index directly from blk0001.dat on next startup.
fs::path txleveldb = dataDir / "txleveldb";
fs::path database = dataDir / "database";
if (fs::exists(txleveldb))
fs::remove_all(txleveldb);
if (fs::exists(database))
fs::remove_all(database);
return true;
}
} // namespace Bootstrap
+46
View File
@@ -0,0 +1,46 @@
// Copyright (c) 2024 Triangles developers
// Distributed under the MIT/X11 software license
#ifndef TRIANGLES_BOOTSTRAP_H
#define TRIANGLES_BOOTSTRAP_H
#include <string>
#include <vector>
#include <functional>
#include <boost/filesystem.hpp>
namespace Bootstrap {
// Bootstrap server configuration
static const char* DEFAULT_HOST = "bootstrap.cryptographic-triangles.org";
static const char* FALLBACK_HOST = "194.233.88.206";
static const char* BASE_PATH = "/";
static const int PORT = 80;
// Progress callback: (bytesDownloaded, totalBytes)
typedef std::function<void(int64_t, int64_t)> ProgressCallback;
// Check if data dir already has blockchain data
bool NeedsBootstrap(const boost::filesystem::path& dataDir);
// Download a single file via HTTP GET, write to destPath
bool DownloadFile(const std::string& host, const std::string& urlPath,
const boost::filesystem::path& destPath,
ProgressCallback progressFn,
std::string& strError);
// Fetch the file manifest (list of relative paths to download)
bool FetchFileList(const std::string& host,
std::vector<std::string>& files,
std::string& strError);
// Download bootstrap.tar.gz and extract to dataDir.
// Falls back to filelist.txt + individual file download if tar.gz unavailable.
bool DownloadBootstrap(const std::string& host,
const boost::filesystem::path& dataDir,
ProgressCallback progressFn,
std::string& strError);
} // namespace Bootstrap
#endif // TRIANGLES_BOOTSTRAP_H
+1 -1
View File
@@ -8,7 +8,7 @@
// These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 5
#define CLIENT_VERSION_MINOR 3
#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_REVISION 5
#define CLIENT_VERSION_BUILD 0
// Converts the parameter X to a string after macro replacement on X has been performed.
+48
View File
@@ -12,6 +12,7 @@
#include "checkpoints.h"
#include "smessage.h"
#include "openssl_compat.h"
#include "bootstrap.h"
#include "tor/tor_embedded.h"
#include "tor/onion_v3.h"
#include "tor/tor_process.h"
@@ -797,6 +798,43 @@ bool AppInit2()
for (string strDest : mapMultiArgs["-seednode"])
AddOneShot(strDest);
// ********************************************************* Step 6b: bootstrap download (daemon)
#ifndef QT_GUI
if (GetBoolArg("-bootstrap", false))
{
fs::path dataPath = GetDataDir();
std::string host = Bootstrap::DEFAULT_HOST;
std::string strError;
uiInterface.InitMessage(_("Downloading blockchain snapshot..."));
printf("Bootstrap: contacting %s...\n", host.c_str());
auto progressFn = [](int64_t bytesDownloaded, int64_t totalBytes) {
if (totalBytes > 0) {
printf("\rBootstrap: %lld / %lld MB (%lld%%)",
(long long)(bytesDownloaded / (1024*1024)),
(long long)(totalBytes / (1024*1024)),
(long long)((bytesDownloaded * 100) / totalBytes));
fflush(stdout);
}
};
bool success = Bootstrap::DownloadBootstrap(host, dataPath, progressFn, strError);
if (!success) {
host = Bootstrap::FALLBACK_HOST;
printf("\nBootstrap: primary host failed, trying fallback %s...\n", host.c_str());
success = Bootstrap::DownloadBootstrap(host, dataPath, progressFn, strError);
}
if (!success) {
printf("\nBootstrap: failed: %s\n", strError.c_str());
printf("Bootstrap: skipping, will sync from network.\n");
} else {
printf("\nBootstrap: done.\n");
}
}
#endif
// ********************************************************* Step 7: load blockchain
if (!bitdb.Open(GetDataDir()))
@@ -821,6 +859,16 @@ bool AppInit2()
if (!LoadBlockIndex())
return InitError(_("Error loading blkindex.dat"));
// If the block index is empty but blk0001.dat exists (bootstrap download),
// fast-import: build the index directly from the block file without re-writing
// data. Batches LevelDB commits every 200K blocks for speed.
if (nBestHeight == 0 && boost::filesystem::exists(GetDataDir() / "blk0001.dat")
&& mapBlockIndex.size() <= 1)
{
uiInterface.InitMessage(_("Importing bootstrap blocks..."));
printf("Block index empty but blk0001.dat exists - running fast import...\n");
FastImportBlockFile();
}
// as LoadBlockIndex can take several minutes, it's possible the user
// requested to kill triangles-qt during the last operation. If so, exit.
+2 -2
View File
@@ -18,8 +18,8 @@
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
namespace json_spirit
{
+10 -22
View File
@@ -1,24 +1,12 @@
LZ4 Library
Copyright (c) 2011-2014, Yann Collet
All rights reserved.
This repository uses 2 different licenses :
- all files in the `lib` directory use a BSD 2-Clause license
- all other files use a GPL-2.0-or-later license, unless explicitly stated otherwise
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Relevant license is reminded at the top of each source file,
and with presence of COPYING or LICENSE file in associated directories.
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This model is selected to emphasize that
files in the `lib` directory are designed to be included into 3rd party applications,
while all other files, in `programs`, `tests` or `examples`,
are intended to be used "as is", as part of their intended scenarios,
with no intention to support 3rd party integration use cases.
+2571 -622
View File
File diff suppressed because it is too large Load Diff
+808 -172
View File
File diff suppressed because it is too large Load Diff
+243 -12
View File
@@ -1526,14 +1526,14 @@ static bool GetAddressFromScript(const CScript& script, int& nType, uint160& has
if (!ExtractDestination(script, dest))
return false;
const CKeyID* keyId = boost::get<CKeyID>(&dest);
const CKeyID* keyId = std::get_if<CKeyID>(&dest);
if (keyId) {
nType = ADDR_TYPE_P2PKH;
hashBytes = *keyId;
return true;
}
const CScriptID* scriptId = boost::get<CScriptID>(&dest);
const CScriptID* scriptId = std::get_if<CScriptID>(&dest);
if (scriptId) {
nType = ADDR_TYPE_P2SH;
hashBytes = *scriptId;
@@ -3023,7 +3023,14 @@ bool LoadExternalBlockFile(FILE* fileIn)
{
int64_t nStart = GetTimeMillis();
// Get file size for progress reporting
int64_t nFileSize = 0;
fseek(fileIn, 0, SEEK_END);
nFileSize = ftell(fileIn);
fseek(fileIn, 0, SEEK_SET);
int nLoaded = 0;
int64_t nLastProgressReport = 0;
{
LOCK(cs_main);
try {
@@ -3074,6 +3081,20 @@ bool LoadExternalBlockFile(FILE* fileIn)
nLoaded++;
nPos += 4 + nSize;
}
// Report progress every 1000 blocks
if (nLoaded - nLastProgressReport >= 1000)
{
nLastProgressReport = nLoaded;
if (nFileSize > 0) {
int pct = (int)((int64_t)nPos * 100 / nFileSize);
printf("Importing blocks... %d blocks loaded (%d%%)\n", nLoaded, pct);
uiInterface.InitMessage(strprintf(_("Importing blocks... %d loaded (%d%%)"), nLoaded, pct));
} else {
printf("Importing blocks... %d blocks loaded\n", nLoaded);
uiInterface.InitMessage(strprintf(_("Importing blocks... %d loaded"), nLoaded));
}
}
}
}
catch (std::exception &e) {
@@ -3085,6 +3106,210 @@ bool LoadExternalBlockFile(FILE* fileIn)
return nLoaded > 0;
}
bool FastImportBlockFile()
{
// Fast block import: reads blk0001.dat and builds the block index
// directly without re-writing block data. LevelDB writes are batched
// every 200K blocks for speed. Only used for trusted bootstrap data
// (blocks below the hardcoded checkpoint).
fs::path blkPath = GetDataDir() / "blk0001.dat";
if (!fs::exists(blkPath))
return false;
printf("FastImportBlockFile: starting from %s\n", blkPath.string().c_str());
int64_t nStart = GetTimeMillis();
FILE* fileIn = fopen(blkPath.string().c_str(), "rb");
if (!fileIn)
return false;
// Get file size for progress
fseek(fileIn, 0, SEEK_END);
int64_t nFileSize = ftell(fileIn);
fseek(fileIn, 0, SEEK_SET);
int nLoaded = 0;
int64_t nLastProgressReport = 0;
{
LOCK(cs_main);
CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION);
CTxDB txdb;
txdb.TxnBegin();
unsigned int nPos = 0;
while (nPos != (unsigned int)-1 && blkdat.good() && !fRequestShutdown)
{
// Find message start bytes (same scan as LoadExternalBlockFile)
unsigned char pchData[65536];
do {
fseek(blkdat, nPos, SEEK_SET);
int nRead = fread(pchData, 1, sizeof(pchData), blkdat);
if (nRead <= 8)
{
nPos = (unsigned int)-1;
break;
}
void* nFind = memchr(pchData, pchMessageStart[0], nRead+1-sizeof(pchMessageStart));
if (nFind)
{
if (memcmp(nFind, pchMessageStart, sizeof(pchMessageStart))==0)
{
nPos += ((unsigned char*)nFind - pchData) + sizeof(pchMessageStart);
break;
}
nPos += ((unsigned char*)nFind - pchData) + 1;
}
else
nPos += sizeof(pchData) - sizeof(pchMessageStart) + 1;
} while(!fRequestShutdown);
if (nPos == (unsigned int)-1)
break;
fseek(blkdat, nPos, SEEK_SET);
unsigned int nSize;
blkdat >> nSize;
if (nSize == 0 || nSize > MAX_BLOCK_SIZE)
{
nPos += 4 + nSize;
continue;
}
// nBlockPos = file position where the block data starts
// (after 4-byte message start + 4-byte size)
unsigned int nBlockPos = nPos + 4;
CBlock block;
blkdat >> block;
uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash))
{
nPos += 4 + nSize;
continue; // already indexed
}
// Create CBlockIndex
CBlockIndex* pindexNew = new CBlockIndex(1, nBlockPos, block);
if (!pindexNew)
break;
// Link to previous block
map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end())
{
pindexNew->pprev = (*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
}
// Chain trust
pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + pindexNew->GetBlockTrust();
// Stake entropy bit
pindexNew->SetStakeEntropyBit(block.GetStakeEntropyBit());
// Stake modifier (minimal for blocks far below checkpoint)
int nCheckpointHeight = Checkpoints::GetTotalBlocksEstimate();
if (pindexNew->nHeight >= nCheckpointHeight - 1000)
{
uint64_t nStakeModifier = 0;
bool fGeneratedStakeModifier = false;
ComputeNextStakeModifier(pindexNew->pprev, nStakeModifier, fGeneratedStakeModifier);
pindexNew->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
}
else
{
pindexNew->SetStakeModifier(0, pindexNew->nHeight == 0);
}
pindexNew->nStakeModifierChecksum = GetStakeModifierChecksum(pindexNew);
// Money supply tracking
pindexNew->nMint = 0;
pindexNew->nMoneySupply = (pindexNew->pprev ? pindexNew->pprev->nMoneySupply : 0);
// PoS stake seen set
if (pindexNew->IsProofOfStake())
setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
// Insert into mapBlockIndex
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
// Link pnext for previous block
if (pindexNew->pprev)
pindexNew->pprev->pnext = pindexNew;
// Write block index to batch
txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
// Build tx index entries
unsigned int nTxPos = nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION)
- (2 * GetSizeOfCompactSize(0)) + GetSizeOfCompactSize(block.vtx.size());
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
const CTransaction& tx = block.vtx[i];
CDiskTxPos posThisTx(1, nBlockPos, nTxPos);
txdb.UpdateTxIndex(tx.GetHash(), CTxIndex(posThisTx, tx.vout.size()));
nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
// Update best chain
if (pindexNew->nChainTrust > nBestChainTrust)
{
hashBestChain = hash;
pindexBest = pindexNew;
pblockindexFBBHLast = NULL;
nBestHeight = pindexNew->nHeight;
nBestChainTrust = pindexNew->nChainTrust;
nTimeBestReceived = GetTime();
}
// Set genesis block
if (pindexGenesisBlock == NULL && pindexNew->nHeight == 0)
pindexGenesisBlock = pindexNew;
nLoaded++;
nPos += 4 + nSize;
// Batch commit every 200K blocks for LevelDB efficiency
if (nLoaded % 200000 == 0)
{
txdb.WriteHashBestChain(hashBestChain);
txdb.TxnCommit();
txdb.TxnBegin();
}
// Report progress every 5000 blocks to keep GUI responsive.
// AppInit2 runs on the GUI thread, so uiInterface.InitMessage
// triggers processEvents() which prevents the window from freezing.
if (nLoaded % 5000 == 0)
{
int pct = (nFileSize > 0) ? (int)((int64_t)nPos * 100 / nFileSize) : 0;
printf("FastImport: %d blocks indexed (%d%%)\n", nLoaded, pct);
uiInterface.InitMessage(strprintf(_("Importing blocks... %d indexed (%d%%)"), nLoaded, pct));
}
}
// Final commit
if (pindexBest)
{
txdb.WriteHashBestChain(hashBestChain);
// Write sync checkpoint
Checkpoints::WriteSyncCheckpoint(hashBestChain);
}
txdb.TxnCommit();
}
nTransactionsUpdated++;
printf("FastImportBlockFile: indexed %d blocks in %"PRId64"ms\n", nLoaded, GetTimeMillis() - nStart);
return nLoaded > 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlert
@@ -3392,7 +3617,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
hashKey = Hash(BEGIN(hashKey), END(hashKey));
mapMix.insert(make_pair(hashKey, pnode));
}
int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
// Small network: relay to more peers so addresses propagate quickly
int nRelayNodes = fReachable ? (int)mapMix.size() : 1;
for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
((*mi).second)->PushAddress(addr);
}
@@ -3496,11 +3722,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Trigger them to send a getblocks request for the next batch of inventory
if (inv.hash == pfrom->hashContinue)
{
// triangles: send latest proof-of-work block to allow the
// download node to accept as orphan (proof-of-stake
// block might be rejected by stake connection check)
// Send the best block hash to trigger the next getblocks.
// Original code sent the last PoW block, but since PoW ended
// at block 9000, that always sent an ancient block causing
// thousands of redundant round-trips through known blocks.
vector<CInv> vInv;
vInv.push_back(CInv(MSG_BLOCK, GetLastBlockIndex(pindexBest, false)->GetBlockHash()));
vInv.push_back(CInv(MSG_BLOCK, hashBestChain));
pfrom->PushMessage("inv", vInv);
pfrom->hashContinue = 0;
}
@@ -3548,7 +3775,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Send the rest of the chain
if (pindex)
pindex = pindex->pnext;
int nLimit = IsInitialBlockDownload() ? 20000 : 500;
// Send larger batches when the requester is far behind (syncing).
// The original check used our own IBD state, but we're the seed node
// (fully synced), so it always returned 500. Check how far behind
// the requester is instead.
int nLimit = (pindex && pindexBest && pindexBest->nHeight - pindex->nHeight > 1000) ? 10000 : 500;
printf("IBD-DIAG: getblocks request from peer %s: start=%d stop=%s limit=%d\n",
pfrom->addr.ToString().c_str(), (pindex ? pindex->nHeight : -1),
hashStop.ToString().substr(0,20).c_str(), nLimit);
@@ -3774,7 +4005,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (IsInitialBlockDownload())
{
static int nBlocksSinceRequest = 0;
if (++nBlocksSinceRequest >= 1000)
if (++nBlocksSinceRequest >= 5000)
{
nBlocksSinceRequest = 0;
pfrom->pindexLastGetBlocksBegin = NULL;
@@ -4230,7 +4461,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
//
// Stall detection: if IBD and no new blocks for 5 seconds, re-request
// Stall detection: if IBD and no new blocks for 10 seconds, re-request
//
if (IsInitialBlockDownload() && !pto->fClient)
{
@@ -4240,8 +4471,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (nBestHeight > nLastHeight) {
nLastHeight = nBestHeight;
nLastBlockReceived = GetTime();
} else if (nLastBlockReceived > 0 && GetTime() - nLastBlockReceived > 2) {
if (GetTime() - nLastStallLog >= 10) { // log every 10s max
} else if (nLastBlockReceived > 0 && GetTime() - nLastBlockReceived > 10) {
if (GetTime() - nLastStallLog >= 30) { // log every 30s max
printf("IBD-DIAG: STALL at height %d for %ds, peer=%s askfor_queue=%d send_size=%d\n",
nBestHeight, (int)(GetTime() - nLastBlockReceived),
pto->addr.ToString().c_str(),
+1
View File
@@ -112,6 +112,7 @@ CBlockIndex* FindBlockByHeight(int nHeight);
bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
bool LoadExternalBlockFile(FILE* fileIn);
bool FastImportBlockFile();
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake);
+34 -2
View File
@@ -74,7 +74,7 @@ HARDENING+=-D_FORTIFY_SOURCE=2
DEBUGFLAGS=-g
xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter \
xCXXFLAGS=-O2 -std=c++17 -pthread -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter \
-Wno-deprecated-declarations -Wno-reserved-user-defined-literal \
-Wa,-mbig-obj \
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
@@ -111,6 +111,7 @@ OBJS= \
obj/miner.o \
obj/main.o \
obj/net.o \
obj/bootstrap.o \
obj/net_bootstrap.o \
obj/protocol.o \
obj/trianglesrpc.o \
@@ -135,8 +136,11 @@ OBJS= \
obj/scrypt-x86.o \
obj/scrypt-x86_64.o \
obj/smessage.o \
obj/lz4.o \
obj/onion_v3.o \
obj/tor_process.o
obj/tor_process.o \
obj/tor_embed_hooks.o \
obj/tor_embedded.o
all: trianglesd.exe
@@ -208,6 +212,34 @@ obj/tor_process.o: tor/tor_process.cpp
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/lz4.o: lz4/lz4.c
$(CXX) -c $(xCXXFLAGS) -fpermissive -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/tor_embed_hooks.o: tor_embed_hooks.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/tor_embedded.o: tor/tor_embedded.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/bootstrap.o: bootstrap.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/net_bootstrap.o: net_bootstrap.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
+20 -4
View File
@@ -146,6 +146,7 @@ OBJS= \
obj/miner.o \
obj/main.o \
obj/net.o \
obj/bootstrap.o \
obj/net_bootstrap.o \
obj/protocol.o \
obj/trianglesrpc.o \
@@ -170,24 +171,25 @@ OBJS= \
obj/scrypt-x86.o \
obj/scrypt-x86_64.o \
obj/smessage.o \
obj/lz4.o \
obj/onion_v3.o \
obj/tor_process.o \
obj/tor_embed_hooks.o \
obj/tor_embedded.o
# Embedded Tor support (optional)
# Build with: make -f makefile.unix USE_TOR_EMBEDDED=1 TOR_LIB_PATH=/path/to/libtor
# Build with: make -f makefile.unix USE_TOR_EMBEDDED=1 TOR_SOURCE_ROOT=/path/to/tor-src
# Requires libtor.a built from official Tor source (see CODEX-TOR-GUIDE.md)
TOR_SOURCE_ROOT ?= tor/tor-src
TOR_INCLUDE_PATH ?= $(TOR_SOURCE_ROOT)/src/feature/api
TOR_LIB_PATH ?= $(TOR_SOURCE_ROOT)/src/core $(TOR_SOURCE_ROOT)/src/lib $(TOR_SOURCE_ROOT)/src/trunnel
TOR_EMBEDDED_LIBS ?= -ltor-app -lor -lor-ctime -lor-event -lor-trunnel
TOR_LIB_PATH ?= $(TOR_SOURCE_ROOT)
TOR_EMBEDDED_LIBS ?= -ltor
ifdef USE_TOR_EMBEDDED
DEFS += -DENABLE_TOR_EMBEDDED
DEFS += $(addprefix -I,$(TOR_INCLUDE_PATH))
LIBS += $(addprefix -L,$(TOR_LIB_PATH))
LIBS += -Wl,--start-group $(TOR_EMBEDDED_LIBS) -Wl,--end-group
LIBS += -levent -levent_pthreads -lssl -lcrypto -lz -lm -lpthread
LIBS += -llzma -lzstd -lm -lpthread
endif
# ZMQ support (optional)
@@ -243,6 +245,13 @@ obj/%.o: %.c
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/lz4.o: lz4/lz4.c
$(CXX) -c $(xCXXFLAGS) -fpermissive -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//'\
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/tor_embed_hooks.o: tor_embed_hooks.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
@@ -271,6 +280,13 @@ obj/tor_embedded.o: tor/tor_embedded.cpp
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/bootstrap.o: bootstrap.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
obj/net_bootstrap.o: net_bootstrap.cpp
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
+23 -13
View File
@@ -83,7 +83,7 @@ uint64_t nLastBlockSize = 0;
int64_t nLastCoinStakeSearchInterval = 0;
// We want to sort transactions by priority and fee, so:
typedef boost::tuple<double, double, CTransaction*> TxPriority;
typedef std::tuple<double, double, CTransaction*> TxPriority;
class TxPriorityCompare
{
bool byFee;
@@ -93,15 +93,15 @@ public:
{
if (byFee)
{
if (a.get<1>() == b.get<1>())
return a.get<0>() < b.get<0>();
return a.get<1>() < b.get<1>();
if (std::get<1>(a) == std::get<1>(b))
return std::get<0>(a) < std::get<0>(b);
return std::get<1>(a) < std::get<1>(b);
}
else
{
if (a.get<0>() == b.get<0>())
return a.get<1>() < b.get<1>();
return a.get<0>() < b.get<0>();
if (std::get<0>(a) == std::get<0>(b))
return std::get<1>(a) < std::get<1>(b);
return std::get<0>(a) < std::get<0>(b);
}
}
};
@@ -110,7 +110,7 @@ public:
CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees)
{
// Create new block
auto_ptr<CBlock> pblock(new CBlock());
unique_ptr<CBlock> pblock(new CBlock());
if (!pblock.get())
return NULL;
@@ -259,9 +259,9 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees)
while (!vecPriority.empty())
{
// Take highest priority transaction off the priority queue:
double dPriority = vecPriority.front().get<0>();
double dFeePerKb = vecPriority.front().get<1>();
CTransaction& tx = *(vecPriority.front().get<2>());
double dPriority = std::get<0>(vecPriority.front());
double dFeePerKb = std::get<1>(vecPriority.front());
CTransaction& tx = *(std::get<2>(vecPriority.front()));
std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
vecPriority.pop_back();
@@ -551,18 +551,28 @@ void StakeMiner(CWallet *pwallet)
if (fTryToSync)
{
fTryToSync = false;
if (vNodes.size() < 3 || nBestHeight < GetNumBlocksOfPeers())
if (vNodes.size() < 1 || nBestHeight < GetNumBlocksOfPeers())
{
MilliSleep(60000);
continue;
}
}
//
// Update cached stake weight for UI display (avoids heavy work on UI thread)
//
{
uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0;
pwallet->GetStakeWeight(*pwallet, nMinWeight, nMaxWeight, nWeight);
pwallet->nCachedStakeWeight = nWeight;
pwallet->nCachedStakeWeightTime = GetTime();
}
//
// Create new block
//
int64_t nFees;
auto_ptr<CBlock> pblock(CreateNewBlock(pwallet, true, &nFees));
unique_ptr<CBlock> pblock(CreateNewBlock(pwallet, true, &nFees));
if (!pblock.get())
return;
+3 -3
View File
@@ -1584,7 +1584,7 @@ void ThreadOpenConnections2(void* parg)
for (CNode* pnode : vNodes) {
if (!pnode->fInbound) { fNoOutbound = false; break; }
}
if (fNoOutbound && (GetTime() - nStart > 30) && !fTestNet)
if (fNoOutbound && (GetTime() - nStart > 10) && !fTestNet)
{
std::vector<CAddress> vAdd;
for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
@@ -1596,7 +1596,7 @@ void ThreadOpenConnections2(void* parg)
vAdd.push_back(addr);
}
addrman.Add(vAdd, CNetAddr("127.0.0.1"));
printf("No outbound connections after 30s, added %d hardcoded seeds\n", (int)vAdd.size());
printf("No outbound connections after 10s, added %d hardcoded seeds\n", (int)vAdd.size());
}
}
@@ -1642,7 +1642,7 @@ void ThreadOpenConnections2(void* parg)
continue;
// only consider very recently tried nodes after 30 failed attempts
if (nANow - addr.nLastTry < 600 && nTries < 30)
if (nANow - addr.nLastTry < 120 && nTries < 30)
continue;
// do not allow non-default ports, unless after 50 invalid addresses selected already
+1 -1
View File
@@ -422,7 +422,7 @@ public:
// the key is the earliest time the request can be sent
int64_t& nRequestTime = mapAlreadyAskedFor[inv];
if (fDebugNet)
printf("askfor %s %"PRId64" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
printf("askfor %s %" PRId64 " (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
// Make sure not to reuse time indexes to keep things in the same order
int64_t nNow = (GetTime() - 1) * 1000000;
+20 -5
View File
@@ -15,7 +15,7 @@ static const int64_t nClientStartupTime = GetTime();
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
QObject(parent), optionsModel(optionsModel),
cachedNumBlocks(0), cachedNumBlocksOfPeers(0), pollTimer(0)
cachedNumBlocks(0), cachedNumBlocksOfPeers(0), cachedNumConnections(0), pollTimer(0)
{
numBlocksAtStartup = -1;
@@ -34,7 +34,14 @@ ClientModel::~ClientModel()
int ClientModel::getNumConnections() const
{
return vNodes.size();
// Use TRY_LOCK to avoid blocking the UI thread when the network
// thread holds cs_vNodes (e.g. during DNS resolution or connections).
// Return the cached value if the lock is busy.
TRY_LOCK(cs_vNodes, lockNodes);
if (lockNodes) {
cachedNumConnections = vNodes.size();
}
return cachedNumConnections;
}
int ClientModel::getNumBlocks() const
@@ -63,12 +70,20 @@ void ClientModel::updateTimer()
int newNumBlocks = getNumBlocks();
int newNumBlocksOfPeers = getNumBlocksOfPeers();
// Always emit during IBD so the speed/ETA display stays live
if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers
|| newNumBlocks < newNumBlocksOfPeers)
// Always emit when values change or during IBD.
// Also emit every ~30 seconds even when idle so setNumBlocks() can
// re-evaluate sync status (e.g. when a new block arrives after a long gap).
static int64_t nLastEmit = 0;
int64_t nNow = GetTime();
bool fChanged = (cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers);
bool fCatchingUp = (newNumBlocks < newNumBlocksOfPeers);
bool fPeriodicRefresh = (nNow - nLastEmit >= 30);
if(fChanged || fCatchingUp || fPeriodicRefresh)
{
cachedNumBlocks = newNumBlocks;
cachedNumBlocksOfPeers = newNumBlocksOfPeers;
nLastEmit = nNow;
emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers);
}
+1
View File
@@ -49,6 +49,7 @@ private:
int cachedNumBlocks;
int cachedNumBlocksOfPeers;
mutable int cachedNumConnections;
int numBlocksAtStartup;
+2 -2
View File
@@ -522,7 +522,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
{
CPubKey pubkey;
CKeyID *keyid = boost::get< CKeyID >(&address);
CKeyID *keyid = std::get_if< CKeyID >(&address);
if (keyid && model->getPubKey(*keyid, pubkey))
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
else
@@ -703,7 +703,7 @@ void CoinControlDialog::updateView()
itemOutput->setText(COLUMN_ADDRESS, sAddress);
CPubKey pubkey;
CKeyID *keyid = boost::get< CKeyID >(&outputAddress);
CKeyID *keyid = std::get_if< CKeyID >(&outputAddress);
if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed())
nInputSize = 180;
}
+1 -1
View File
@@ -2,7 +2,7 @@
#define GUICONSTANTS_H
/* Milliseconds between model updates */
static const int MODEL_UPDATE_DELAY = 500;
static const int MODEL_UPDATE_DELAY = 2500;
/* AskPassphraseDialog -- Maximum passphrase length */
static const int MAX_PASSPHRASE_SIZE = 1024;
+72
View File
@@ -1,5 +1,6 @@
#include "introdialog.h"
#include "util.h"
#include "bootstrap.h"
#include <QSettings>
#include <QVBoxLayout>
@@ -9,6 +10,9 @@
#include <QDir>
#include <QMessageBox>
#include <QDialogButtonBox>
#include <QProgressDialog>
#include <QCheckBox>
#include <QApplication>
#include <boost/filesystem.hpp>
@@ -201,5 +205,73 @@ bool IntroDialog::pickDataDirectory()
return false;
}
// Offer bootstrap download on each startup (unless user checked "don't ask again")
fs::path dataDirPath(dataDir.toStdString());
if (!settings.value("bootstrapDontAsk", false).toBool())
{
QMessageBox msgBox;
msgBox.setWindowTitle("Triangles");
msgBox.setText(
"Would you like to download the latest blockchain snapshot?\n\n"
"This will download the blockchain data from the Triangles network "
"and replace any existing chain data in your data directory.\n\n"
"Click Yes to download, or No to sync from the network.");
msgBox.setIcon(QMessageBox::Question);
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
QCheckBox *dontAskBox = new QCheckBox("Don't show this again");
msgBox.setCheckBox(dontAskBox);
int ret = msgBox.exec();
if (dontAskBox->isChecked())
settings.setValue("bootstrapDontAsk", true);
if (ret == QMessageBox::Yes)
{
std::string host = Bootstrap::DEFAULT_HOST;
std::string strError;
QProgressDialog progress("Downloading blockchain snapshot...", "Cancel",
0, 100, 0);
progress.setWindowTitle("Triangles - Bootstrap");
progress.setWindowModality(Qt::ApplicationModal);
progress.setMinimumDuration(0);
progress.setValue(0);
auto progressFn = [&progress](int64_t bytesDownloaded, int64_t totalBytes) {
if (totalBytes > 0) {
int pct = (int)((bytesDownloaded * 100) / totalBytes);
progress.setValue(pct);
progress.setLabelText(
QString("Downloading blockchain snapshot... %1 MB / %2 MB")
.arg(bytesDownloaded / (1024*1024))
.arg(totalBytes / (1024*1024)));
} else {
progress.setLabelText(
QString("Downloading blockchain snapshot... %1 MB")
.arg(bytesDownloaded / (1024*1024)));
}
QApplication::processEvents();
};
bool success = Bootstrap::DownloadBootstrap(host, dataDirPath, progressFn, strError);
if (!success) {
host = Bootstrap::FALLBACK_HOST;
progress.setValue(0);
success = Bootstrap::DownloadBootstrap(host, dataDirPath, progressFn, strError);
}
if (!success) {
QMessageBox::warning(0, "Triangles",
QString("Could not download blockchain snapshot:\n%1\n\n"
"The wallet will sync from the network instead.")
.arg(QString::fromStdString(strError)));
} else {
progress.setValue(100);
}
}
}
return true;
}
+2
View File
@@ -126,6 +126,8 @@ OverviewPage::~OverviewPage()
void OverviewPage::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance)
{
if (!model || !model->getOptionsModel())
return;
int unit = model->getOptionsModel()->getDisplayUnit();
currentBalance = balance;
currentStake = stake;
+10 -2
View File
@@ -71,7 +71,13 @@ public:
OutputDebugStringF("refreshWallet\n");
cachedWallet.clear();
{
LOCK(wallet->cs_wallet);
TRY_LOCK(wallet->cs_wallet, lockWallet);
if(!lockWallet)
{
// Lock busy (block processing), retry in 500ms
QTimer::singleShot(500, parent, SLOT(refreshWallet()));
return;
}
for(std::map<uint256, CWalletTx>::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it)
{
if(TransactionRecord::showTransaction(it->second))
@@ -89,7 +95,9 @@ public:
{
OutputDebugStringF("updateWallet %s %i\n", hash.ToString().c_str(), status);
{
LOCK(wallet->cs_wallet);
TRY_LOCK(wallet->cs_wallet, lockWallet);
if (!lockWallet)
return;
// Find transaction in wallet
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
+43 -24
View File
@@ -799,19 +799,23 @@ void TrianglesGUI::setNumConnections(int count)
void TrianglesGUI::setNumBlocks(int count, int nTotalBlocks)
{
// don't show / hide progress bar and its label if we have no connection to the network
if (!clientModel || clientModel->getNumConnections() == 0)
if (!clientModel)
return;
int nConnections = clientModel->getNumConnections();
// Hide progress bar when disconnected, but don't return early -
// we still need to update sync state and the out-of-sync warning
if (nConnections == 0)
{
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
ui->label_blocks->setVisible(false);
return;
}
QString tooltip;
if(count < nTotalBlocks)
if(nConnections > 0 && count < nTotalBlocks)
{
// Calculate blocks/sec - only update rate when new blocks arrive
static int lastCount = 0;
@@ -899,20 +903,20 @@ void TrianglesGUI::setNumBlocks(int count, int nTotalBlocks)
text = tr("%n day(s) ago","",secs/(60*60*24));
}
// Set icon state: spinning if catching up, tick otherwise
if(secs < 90*60 && count >= nTotalBlocks)
// Set icon state: spinning if catching up, tick otherwise.
// For PoS chains with few stakers, blocks can be hours or days apart.
// Sync status is based purely on block count - NOT block timestamp.
// A stale chain (no recent blocks) is still "synced" if we have all blocks.
if(count >= nTotalBlocks)
{
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
overviewPage->showOutOfSyncWarning(false);
}
else
{
tooltip = tr("Catching up...") + QString("<br>") + tooltip;
//syncIconMovie doesn't work for some reason - using fallback png
//labelBlocksIcon->setMovie(syncIconMovie);
//syncIconMovie->start();
labelBlocksIcon->setPixmap(QIcon(":/icons/notsynced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
overviewPage->showOutOfSyncWarning(true);
@@ -1590,32 +1594,47 @@ void TrianglesGUI::toggleHidden()
void TrianglesGUI::updateStakingIcon()
{
uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0;
// Read cached staking info computed by the staking thread.
// No locks needed - these are volatile values written by the miner thread
// and are display-only. This keeps the UI thread completely non-blocking.
uint64_t nWeight = 0;
bool fWalletLocked = false;
bool fHasPeers = false;
if (pwalletMain)
pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight);
{
TRY_LOCK(pwalletMain->cs_wallet, lockWallet);
if (lockWallet)
fWalletLocked = pwalletMain->IsLocked();
else
return; // Skip this cycle, try again in 30 seconds
// Use cached weight from the staking thread instead of computing on UI thread.
// The staking thread updates this every ~500ms-1s loop iteration.
nWeight = pwalletMain->nCachedStakeWeight;
}
{
TRY_LOCK(cs_vNodes, lockNodes);
if (lockNodes)
fHasPeers = !vNodes.empty();
}
if (nLastCoinStakeSearchInterval && nWeight)
{
uint64_t nNetworkWeight = GetPoSKernelPS();
unsigned nEstimateTime = nTargetSpacing * nNetworkWeight / nWeight;
unsigned nEstimateTime = nWeight > 0 ? nTargetSpacing * nNetworkWeight / nWeight : 0;
QString text;
if (nEstimateTime < 60)
{
text = tr("%n second(s)", "", nEstimateTime);
}
else if (nEstimateTime < 60*60)
{
text = tr("%n minute(s)", "", nEstimateTime/60);
}
else if (nEstimateTime < 24*60*60)
{
text = tr("%n hour(s)", "", nEstimateTime/(60*60));
}
else
{
text = tr("%n day(s)", "", nEstimateTime/(60*60*24));
}
labelStakingIcon->setPixmap(QIcon(":/icons/staking_on").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
labelStakingIcon->setToolTip(tr("Staking.<br>Your weight is %1<br>Network weight is %2<br>Expected time to earn reward is %3").arg(nWeight).arg(nNetworkWeight).arg(text));
@@ -1623,9 +1642,9 @@ void TrianglesGUI::updateStakingIcon()
else
{
labelStakingIcon->setPixmap(QIcon(":/icons/staking_off").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
if (pwalletMain && pwalletMain->IsLocked())
if (fWalletLocked)
labelStakingIcon->setToolTip(tr("Not staking because wallet is locked"));
else if (vNodes.empty())
else if (!fHasPeers)
labelStakingIcon->setToolTip(tr("Not staking because wallet is offline"));
else if (IsInitialBlockDownload())
labelStakingIcon->setToolTip(tr("Not staking because wallet is syncing"));
+22 -11
View File
@@ -86,10 +86,12 @@ void WalletModel::pollBalanceChanged()
void WalletModel::checkBalanceChanged()
{
qint64 newBalance = getBalance();
qint64 newStake = getStake();
qint64 newUnconfirmedBalance = getUnconfirmedBalance();
qint64 newImmatureBalance = getImmatureBalance();
// Get all balances in a single lock acquisition + single pass.
// Uses TRY_LOCK internally - if cs_wallet is busy (block processing),
// skip this cycle. The timer will retry in 2.5 seconds.
int64_t newBalance = 0, newStake = 0, newUnconfirmedBalance = 0, newImmatureBalance = 0;
if (!wallet->GetAllBalances(newBalance, newStake, newUnconfirmedBalance, newImmatureBalance))
return;
if(cachedBalance != newBalance || cachedStake != newStake || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance)
{
@@ -106,14 +108,20 @@ void WalletModel::updateTransaction(const QString &hash, int status)
if(transactionTableModel)
transactionTableModel->updateTransaction(hash, status);
// Balance and number of transactions might have changed
checkBalanceChanged();
// Don't call checkBalanceChanged() here - it does LOCK(cs_wallet) + iterates
// all wallet transactions, blocking the UI thread. The pollBalanceChanged()
// timer already handles balance updates every 2.5 seconds with TRY_LOCK.
int newNumTransactions = getNumTransactions();
if(cachedNumTransactions != newNumTransactions)
// Same for getNumTransactions() - use cached count from the transaction model
// to avoid another LOCK(cs_wallet) on the UI thread.
if(transactionTableModel)
{
cachedNumTransactions = newNumTransactions;
emit numTransactionsChanged(newNumTransactions);
int newNumTransactions = transactionTableModel->rowCount(QModelIndex());
if(cachedNumTransactions != newNumTransactions)
{
cachedNumTransactions = newNumTransactions;
emit numTransactionsChanged(newNumTransactions);
}
}
}
@@ -240,7 +248,10 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
if(!fCreated)
{
if((total + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future
// NOTE: Potential edge case in fee calculation. The term "collisions" is unclear
// from original comment - may refer to transaction conflicts or UTXO selection issues.
// Consider reviewing Bitcoin Core's current implementation of this balance check.
if((total + nFeeRequired) > nBalance)
{
return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired);
}
-1
View File
@@ -13,7 +13,6 @@
#include "init.h"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace json_spirit;
+2 -2
View File
@@ -431,13 +431,13 @@ static bool ParseAddress(const std::string& strAddr, int& nType, uint160& hashBy
return false;
CTxDestination dest = addr.Get();
const CKeyID* keyId = boost::get<CKeyID>(&dest);
const CKeyID* keyId = std::get_if<CKeyID>(&dest);
if (keyId) {
nType = ADDR_TYPE_P2PKH;
hashBytes = *keyId;
return true;
}
const CScriptID* scriptId = boost::get<CScriptID>(&dest);
const CScriptID* scriptId = std::get_if<CScriptID>(&dest);
if (scriptId) {
nType = ADDR_TYPE_P2SH;
hashBytes = *scriptId;
-1
View File
@@ -11,7 +11,6 @@
#include "base58.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/variant/get.hpp>
#include <boost/algorithm/string.hpp>
#define printf OutputDebugStringF
+6 -2
View File
@@ -229,7 +229,8 @@ Value getworkex(const Array& params, bool fHelp)
if(coinbase.size() == 0)
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
else
CDataStream(coinbase, SER_NETWORK, PROTOCOL_VERSION) >> pblock->vtx[0]; // FIXME - DRM!
// Deserialize custom coinbase transaction from miner
CDataStream(coinbase, SER_NETWORK, PROTOCOL_VERSION) >> pblock->vtx[0];
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
@@ -260,7 +261,10 @@ Value getwork(const Array& params, bool fHelp)
throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks");
typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
static mapNewBlock_t mapNewBlock; // FIXME: thread safety
// NOTE: Thread safety issue - static variables accessed by multiple RPC threads
// without mutex protection. Low priority since PoW ended at block 9000 and
// getwork is rarely used. Consider adding std::mutex if usage increases.
static mapNewBlock_t mapNewBlock;
static vector<CBlock*> vNewBlock;
static CReserveKey reservekey(pwalletMain);
+7 -7
View File
@@ -145,7 +145,7 @@ Value listunspent(const Array& params, bool fHelp)
"Results are an array of Objects, each of which has:\n"
"{txid, vout, scriptPubKey, amount, confirmations}");
RPCTypeCheck(params, list_of(int_type)(int_type)(array_type));
RPCTypeCheck(params, {int_type, int_type, array_type});
int nMinDepth = 1;
if (params.size() > 0)
@@ -221,7 +221,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
"Note that the transaction's inputs are not signed, and\n"
"it is not stored in the wallet or transmitted to the network.");
RPCTypeCheck(params, list_of(array_type)(obj_type));
RPCTypeCheck(params, {array_type, obj_type});
Array inputs = params[0].get_array();
Object sendTo = params[1].get_obj();
@@ -281,7 +281,7 @@ Value decoderawtransaction(const Array& params, bool fHelp)
"decoderawtransaction <hex string>\n"
"Return a JSON object representing the serialized, hex-encoded transaction.");
RPCTypeCheck(params, list_of(str_type));
RPCTypeCheck(params, {str_type});
vector<unsigned char> txData(ParseHex(params[0].get_str()));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
@@ -306,7 +306,7 @@ Value decodescript(const Array& params, bool fHelp)
"decodescript <hex string>\n"
"Decode a hex-encoded script.");
RPCTypeCheck(params, list_of(str_type));
RPCTypeCheck(params, {str_type});
Object r;
CScript script;
@@ -339,7 +339,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
" complete : 1 if transaction has a complete set of signature (0 if not)"
+ HelpRequiringPassphrase());
RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
RPCTypeCheck(params, {str_type, array_type, array_type, str_type}, true);
vector<unsigned char> txData(ParseHex(params[0].get_str()));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
@@ -398,7 +398,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
Object prevOut = p.get_obj();
RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
RPCTypeCheck(prevOut, {{"txid", str_type}, {"vout", int_type}, {"scriptPubKey", str_type}});
string txidHex = find_value(prevOut, "txid").get_str();
if (!IsHex(txidHex))
@@ -518,7 +518,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
"sendrawtransaction <hex string>\n"
"Submits raw transaction (serialized, hex-encoded) to local node and network.");
RPCTypeCheck(params, list_of(str_type));
RPCTypeCheck(params, {str_type});
// parse hex string from parameter
vector<unsigned char> txData(ParseHex(params[0].get_str()));
+6 -6
View File
@@ -5,7 +5,7 @@
#include "main.h"
#include "trianglesrpc.h"
#include <boost/lexical_cast.hpp>
#include <string>
#include "smessage.h"
#include "init.h" // pwalletMain
@@ -802,13 +802,13 @@ Value smsgbuckets(const Array& params, bool fHelp)
{
std::set<SecMsgToken>& tokenSet = it->second.setTokens;
std::string sBucket = boost::lexical_cast<std::string>(it->first);
std::string sBucket = std::to_string(it->first);
std::string sFile = sBucket + "_01.dat";
snprintf(cbuf, sizeof(cbuf), "%"PRIszu, tokenSet.size());
std::string snContents(cbuf);
std::string sHash = boost::lexical_cast<std::string>(it->second.hash);
std::string sHash = std::to_string(it->second.hash);
nBuckets++;
nMessages += tokenSet.size();
@@ -849,8 +849,8 @@ Value smsgbuckets(const Array& params, bool fHelp)
}; // LOCK(cs_smsg);
std::string snBuckets = boost::lexical_cast<std::string>(nBuckets);
std::string snMessages = boost::lexical_cast<std::string>(nMessages);
std::string snBuckets = std::to_string(nBuckets);
std::string snMessages = std::to_string(nMessages);
Object objM;
objM.push_back(Pair("buckets", snBuckets));
@@ -868,7 +868,7 @@ Value smsgbuckets(const Array& params, bool fHelp)
for (it = smsgBuckets.begin(); it != smsgBuckets.end(); ++it)
{
std::string sFile = boost::lexical_cast<std::string>(it->first) + "_01.dat";
std::string sFile = std::to_string(it->first) + "_01.dat";
try {
boost::filesystem::path fullPath = GetDataDir() / "smsgStore" / sFile;
+3 -3
View File
@@ -1587,7 +1587,7 @@ Value encryptwallet(const Array& params, bool fHelp)
return "wallet encrypted; Triangles server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
}
class DescribeAddressVisitor : public boost::static_visitor<Object>
class DescribeAddressVisitor
{
public:
Object operator()(const CNoDestination &dest) const { return Object(); }
@@ -1644,7 +1644,7 @@ Value validateaddress(const Array& params, bool fHelp)
bool fMine = IsMine(*pwalletMain, dest);
ret.push_back(Pair("ismine", fMine));
if (fMine) {
Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
Object detail = std::visit(DescribeAddressVisitor(), dest);
ret.insert(ret.end(), detail.begin(), detail.end());
}
if (pwalletMain->mapAddressBook.count(dest))
@@ -1681,7 +1681,7 @@ Value validatepubkey(const Array& params, bool fHelp)
ret.push_back(Pair("ismine", fMine));
ret.push_back(Pair("iscompressed", isCompressed));
if (fMine) {
Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
Object detail = std::visit(DescribeAddressVisitor(), dest);
ret.insert(ret.end(), detail.begin(), detail.end());
}
if (pwalletMain->mapAddressBook.count(dest))
+8 -10
View File
@@ -3,11 +3,9 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <tuple>
using namespace std;
using namespace boost;
#include "script.h"
#include "keystore.h"
@@ -1213,7 +1211,7 @@ class CSignatureCache
{
private:
// sigdata_type is (signature hash, signature, public key):
typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
typedef std::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
std::set< sigdata_type> setValid;
CCriticalSection cs_sigcache;
@@ -1542,7 +1540,7 @@ unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
}
class CKeyStoreIsMineVisitor : public boost::static_visitor<bool>
class CKeyStoreIsMineVisitor
{
private:
const CKeyStore *keystore;
@@ -1555,7 +1553,7 @@ public:
bool IsMine(const CKeyStore &keystore, const CTxDestination &dest)
{
return boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest);
return std::visit(CKeyStoreIsMineVisitor(&keystore), dest);
}
bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
@@ -1623,7 +1621,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
return false;
}
class CAffectedKeysVisitor : public boost::static_visitor<void> {
class CAffectedKeysVisitor {
private:
const CKeyStore &keystore;
std::vector<CKeyID> &vKeys;
@@ -1637,7 +1635,7 @@ public:
int nRequired;
if (ExtractDestinations(script, type, vDest, nRequired)) {
for (const CTxDestination &dest : vDest)
boost::apply_visitor(*this, dest);
std::visit(*this, dest);
}
}
@@ -1994,7 +1992,7 @@ bool CScript::HasCanonicalPushes() const
return true;
}
class CScriptVisitor : public boost::static_visitor<bool>
class CScriptVisitor
{
private:
CScript *script;
@@ -2022,7 +2020,7 @@ public:
void CScript::SetDestination(const CTxDestination& dest)
{
boost::apply_visitor(CScriptVisitor(this), dest);
std::visit(CScriptVisitor(this), dest);
}
void CScript::SetMultisig(int nRequired, const std::vector<CKey>& keys)
+2 -2
View File
@@ -11,7 +11,7 @@
#include <stdint.h>
#include <boost/variant.hpp>
#include <variant>
#include "keystore.h"
#include "bignum.h"
@@ -52,7 +52,7 @@ public:
* * CScriptID: TX_SCRIPTHASH destination
* A CTxDestination is the internal data type encoded in a CTrianglesAddress
*/
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
typedef std::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
const char* GetTxnOutputType(txnouttype t);
+34 -36
View File
@@ -17,9 +17,7 @@
#include <cstdio>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <tuple>
#include "allocators.h"
#include "version.h"
@@ -310,14 +308,14 @@ template<typename Stream, typename K, typename T> void Serialize(Stream& os, con
template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion);
// 3 tuple
template<typename T0, typename T1, typename T2> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2> void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2> void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion);
template<typename T0, typename T1, typename T2> unsigned int GetSerializeSize(const std::tuple<T0, T1, T2>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2> void Serialize(Stream& os, const std::tuple<T0, T1, T2>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2> void Unserialize(Stream& is, std::tuple<T0, T1, T2>& item, int nType, int nVersion);
// 4 tuple
template<typename T0, typename T1, typename T2, typename T3> unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
template<typename T0, typename T1, typename T2, typename T3> unsigned int GetSerializeSize(const std::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Serialize(Stream& os, const std::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
template<typename Stream, typename T0, typename T1, typename T2, typename T3> void Unserialize(Stream& is, std::tuple<T0, T1, T2, T3>& item, int nType, int nVersion);
// map
template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion);
@@ -530,29 +528,29 @@ void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
// 3 tuple
//
template<typename T0, typename T1, typename T2>
unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
unsigned int GetSerializeSize(const std::tuple<T0, T1, T2>& item, int nType, int nVersion)
{
unsigned int nSize = 0;
nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<0>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<1>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<2>(item), nType, nVersion);
return nSize;
}
template<typename Stream, typename T0, typename T1, typename T2>
void Serialize(Stream& os, const boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
void Serialize(Stream& os, const std::tuple<T0, T1, T2>& item, int nType, int nVersion)
{
Serialize(os, boost::get<0>(item), nType, nVersion);
Serialize(os, boost::get<1>(item), nType, nVersion);
Serialize(os, boost::get<2>(item), nType, nVersion);
Serialize(os, std::get<0>(item), nType, nVersion);
Serialize(os, std::get<1>(item), nType, nVersion);
Serialize(os, std::get<2>(item), nType, nVersion);
}
template<typename Stream, typename T0, typename T1, typename T2>
void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVersion)
void Unserialize(Stream& is, std::tuple<T0, T1, T2>& item, int nType, int nVersion)
{
Unserialize(is, boost::get<0>(item), nType, nVersion);
Unserialize(is, boost::get<1>(item), nType, nVersion);
Unserialize(is, boost::get<2>(item), nType, nVersion);
Unserialize(is, std::get<0>(item), nType, nVersion);
Unserialize(is, std::get<1>(item), nType, nVersion);
Unserialize(is, std::get<2>(item), nType, nVersion);
}
@@ -561,32 +559,32 @@ void Unserialize(Stream& is, boost::tuple<T0, T1, T2>& item, int nType, int nVer
// 4 tuple
//
template<typename T0, typename T1, typename T2, typename T3>
unsigned int GetSerializeSize(const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
unsigned int GetSerializeSize(const std::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
{
unsigned int nSize = 0;
nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion);
nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion);
nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion);
nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<0>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<1>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<2>(item), nType, nVersion);
nSize += GetSerializeSize(std::get<3>(item), nType, nVersion);
return nSize;
}
template<typename Stream, typename T0, typename T1, typename T2, typename T3>
void Serialize(Stream& os, const boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
void Serialize(Stream& os, const std::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
{
Serialize(os, boost::get<0>(item), nType, nVersion);
Serialize(os, boost::get<1>(item), nType, nVersion);
Serialize(os, boost::get<2>(item), nType, nVersion);
Serialize(os, boost::get<3>(item), nType, nVersion);
Serialize(os, std::get<0>(item), nType, nVersion);
Serialize(os, std::get<1>(item), nType, nVersion);
Serialize(os, std::get<2>(item), nType, nVersion);
Serialize(os, std::get<3>(item), nType, nVersion);
}
template<typename Stream, typename T0, typename T1, typename T2, typename T3>
void Unserialize(Stream& is, boost::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
void Unserialize(Stream& is, std::tuple<T0, T1, T2, T3>& item, int nType, int nVersion)
{
Unserialize(is, boost::get<0>(item), nType, nVersion);
Unserialize(is, boost::get<1>(item), nType, nVersion);
Unserialize(is, boost::get<2>(item), nType, nVersion);
Unserialize(is, boost::get<3>(item), nType, nVersion);
Unserialize(is, std::get<0>(item), nType, nVersion);
Unserialize(is, std::get<1>(item), nType, nVersion);
Unserialize(is, std::get<2>(item), nType, nVersion);
Unserialize(is, std::get<3>(item), nType, nVersion);
}
+11 -11
View File
@@ -44,7 +44,7 @@ Notes:
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <boost/lexical_cast.hpp>
#include <string>
#include <boost/algorithm/string/predicate.hpp>
@@ -54,7 +54,7 @@ Notes:
#include "txdb.h"
#include "lz4/lz4.c"
#include "lz4/lz4.h"
#include "xxhash/xxhash.h"
#include "xxhash/xxhash.c"
@@ -627,7 +627,7 @@ void ThreadSecureMsg(void* parg)
{
if (fDebugSmsg)
printf("Removing bucket %"PRId64" \n", it->first);
std::string fileName = boost::lexical_cast<std::string>(it->first) + "_01.dat";
std::string fileName = std::to_string(it->first) + "_01.dat";
fs::path fullPath = GetDataDir() / "smsgStore" / fileName;
if (fs::exists(fullPath))
{
@@ -641,7 +641,7 @@ void ThreadSecureMsg(void* parg)
printf("Path %s does not exist \n", fullPath.string().c_str());
// -- look for a wl file, it stores incoming messages when wallet is locked
fileName = boost::lexical_cast<std::string>(it->first) + "_01_wl.dat";
fileName = std::to_string(it->first) + "_01_wl.dat";
fullPath = GetDataDir() / "smsgStore" / fileName;
if (fs::exists(fullPath))
{
@@ -868,7 +868,7 @@ int SecureMsgBuildBucketSet()
std::string stime = fileName.substr(0, sep);
int64_t fileTime = boost::lexical_cast<int64_t>(stime);
int64_t fileTime = std::stoll(stime);
if (fileTime < now - SMSG_RETENTION)
{
@@ -2224,7 +2224,7 @@ bool SecureMsgScanBuckets()
std::string stime = fileName.substr(0, sep);
int64_t fileTime = boost::lexical_cast<int64_t>(stime);
int64_t fileTime = std::stoll(stime);
if (fileTime < now - SMSG_RETENTION)
{
@@ -2378,7 +2378,7 @@ int SecureMsgWalletUnlocked()
std::string stime = fileName.substr(0, sep);
int64_t fileTime = boost::lexical_cast<int64_t>(stime);
int64_t fileTime = std::stoll(stime);
if (fileTime < now - SMSG_RETENTION)
{
@@ -2769,7 +2769,7 @@ int SecureMsgRetrieve(SecMsgToken &token, std::vector<unsigned char>& vchData)
//printf("token.offset %"PRId64".\n", token.offset); // DEBUG
int64_t bucket = token.timestamp - (token.timestamp % SMSG_BUCKET_LEN);
std::string fileName = boost::lexical_cast<std::string>(bucket) + "_01.dat";
std::string fileName = std::to_string(bucket) + "_01.dat";
fs::path fullpath = pathSmsgDir / fileName;
//printf("bucket %"PRId64".\n", bucket);
@@ -2972,7 +2972,7 @@ int SecureMsgStoreUnscanned(unsigned char *pHeader, unsigned char *pPayload, uin
int64_t bucket = psmsg->timestamp - (psmsg->timestamp % SMSG_BUCKET_LEN);
std::string fileName = boost::lexical_cast<std::string>(bucket) + "_01_wl.dat";
std::string fileName = std::to_string(bucket) + "_01_wl.dat";
fs::path fullpath = pathSmsgDir / fileName;
FILE *fp;
@@ -3073,7 +3073,7 @@ int SecureMsgStore(unsigned char *pHeader, unsigned char *pPayload, uint32_t nPa
return 1;
};
std::string fileName = boost::lexical_cast<std::string>(bucket) + "_01.dat";
std::string fileName = std::to_string(bucket) + "_01.dat";
fs::path fullpath = pathSmsgDir / fileName;
FILE *fp;
@@ -3468,7 +3468,7 @@ int SecureMsgEncrypt(SecureMessage& smsg, std::string& addressFrom, std::string&
return 8;
};
int lenComp = LZ4_compress((char*)message.c_str(), (char*)&vchCompressed[0], lenMsg);
int lenComp = LZ4_compress_default((char*)message.c_str(), (char*)&vchCompressed[0], lenMsg, worstCase);
if (lenComp < 1)
{
printf("Could not compress message data.\n");
+5 -5
View File
@@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
}
// Visitor to check address type
class TestAddrTypeVisitor : public boost::static_visitor<bool>
class TestAddrTypeVisitor
{
private:
std::string exp_addrType;
@@ -79,7 +79,7 @@ public:
};
// Visitor to check address payload
class TestPayloadVisitor : public boost::static_visitor<bool>
class TestPayloadVisitor
{
private:
std::vector<unsigned char> exp_payload;
@@ -150,7 +150,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest);
BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest);
CTxDestination dest = addr.Get();
BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);
BOOST_CHECK_MESSAGE(std::visit(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);
// Public key must be invalid private key
secret.SetString(exp_base58string);
@@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
continue;
}
CTrianglesAddress addrOut;
BOOST_CHECK_MESSAGE(boost::apply_visitor(CTrianglesAddressVisitor(&addrOut), dest), "encode dest: " + strTest);
BOOST_CHECK_MESSAGE(std::visit(CTrianglesAddressVisitor(&addrOut), dest), "encode dest: " + strTest);
BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
}
}
@@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
// Visiting a CNoDestination must fail
CTrianglesAddress dummyAddr;
CTxDestination nodest = CNoDestination();
BOOST_CHECK(!boost::apply_visitor(CTrianglesAddressVisitor(&dummyAddr), nodest));
BOOST_CHECK(!std::visit(CTrianglesAddressVisitor(&dummyAddr), nodest));
// Restore global state
fTestNet = fTestNet_stored;
+1 -1
View File
@@ -1,6 +1,6 @@
#include <boost/assert.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/tuple/tuple.hpp>
#include <tuple>
#include <openssl/ec.h>
#include <openssl/err.h>
+6 -4
View File
@@ -25,16 +25,18 @@ echo "Configuring Tor static library build from: $TOR_SRC_DIR"
--disable-manpage \
--disable-html-manual \
--disable-unittests \
--disable-tool-name-check
--disable-tool-name-check \
--with-libevent-dir="${LIBEVENT_DIR:-/mingw64}" \
--with-openssl-dir="${OPENSSL_DIR:-/mingw64}" \
--with-zlib-dir="${ZLIB_DIR:-/mingw64}"
echo "Building Tor"
make -j"${NPROC:-$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)}"
echo
echo "Build finished. Inspect these locations for static libraries:"
echo " $TOR_SRC_DIR/src/core"
echo " $TOR_SRC_DIR"
echo " $TOR_SRC_DIR/src/lib"
echo " $TOR_SRC_DIR/src/trunnel"
echo
echo "Suggested next step for Triangles:"
echo ' make -f src/makefile.unix USE_TOR_EMBEDDED=1'
echo ' make -f src/makefile.unix USE_TOR_EMBEDDED=1 TOR_SOURCE_ROOT=src/tor/tor-src'
+1 -1
View File
@@ -22,10 +22,10 @@
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <list>
#define printf OutputDebugStringF
+1 -1
View File
@@ -237,7 +237,7 @@ void runCommand(std::string strCommand);
inline std::string i64tostr(int64_t n)
{
return strprintf("%"PRId64, n);
return strprintf("%" PRId64, n);
}
inline std::string itostr(int n)
+1 -1
View File
@@ -53,7 +53,7 @@ static const int MEMPOOL_GD_VERSION = 60002;
#define DISPLAY_VERSION_MAJOR 5
#define DISPLAY_VERSION_MINOR 3
#define DISPLAY_VERSION_REVISION 0
#define DISPLAY_VERSION_REVISION 5
#define DISPLAY_VERSION_BUILD 0
#endif
+41 -2
View File
@@ -14,6 +14,7 @@
#include "addressindex.h"
#include <boost/algorithm/string/replace.hpp>
#include <algorithm>
#include <random>
#include <deque>
using namespace std;
@@ -957,11 +958,21 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
CBlockIndex* pindex = pindexStart;
{
LOCK(cs_wallet);
int nScanned = 0;
int nTotal = nBestHeight - (pindexStart ? pindexStart->nHeight : 0);
if (nTotal < 1) nTotal = 1;
while (pindex)
{
if (fShutdown)
break;
// Report progress every 10000 blocks to keep UI responsive
if (++nScanned % 10000 == 0)
{
int nPercent = (nScanned * 100) / nTotal;
uiInterface.InitMessage(strprintf(_("Rescanning... %d%%"), nPercent));
}
// no need to read and scan block, if block was created before
// our wallet birthday (as adjusted for block time variability)
if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
@@ -1465,6 +1476,34 @@ int64_t CWallet::GetNewMint() const
return nTotal;
}
bool CWallet::GetAllBalances(int64_t& nBalance, int64_t& nStake, int64_t& nUnconfirmed, int64_t& nImmature) const
{
nBalance = 0;
nStake = 0;
nUnconfirmed = 0;
nImmature = 0;
TRY_LOCK(cs_wallet, lockWallet);
if (!lockWallet)
return false;
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx& pcoin = (*it).second;
if (pcoin.IsCoinStake() && pcoin.GetBlocksToMaturity() > 0 && pcoin.GetDepthInMainChain() > 0)
nStake += CWallet::GetCredit(pcoin);
if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.IsInMainChain())
nImmature += GetCredit(pcoin);
if (pcoin.IsTrusted())
nBalance += pcoin.GetAvailableCredit();
if (!pcoin.IsFinal() || !pcoin.IsTrusted())
nUnconfirmed += pcoin.GetAvailableCredit();
}
return true;
}
bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, vector<COutput> vCoins, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const
{
setCoinsRet.clear();
@@ -1477,7 +1516,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime,
vector<pair<int64_t, pair<const CWalletTx*,unsigned int> > > vValue;
int64_t nTotalLower = 0;
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
std::shuffle(vCoins.begin(), vCoins.end(), std::mt19937(GetRandInt(std::numeric_limits<int>::max())));
for (COutput output : vCoins)
{
@@ -1698,7 +1737,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
CScript scriptChange;
// coin control: send change to custom address
if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
if (coinControl && !std::get_if<CNoDestination>(&coinControl->destChange))
scriptChange.SetDestination(coinControl->destChange);
// no coin control: send change to newly generated address
+11
View File
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include <atomic>
#include <stdlib.h>
@@ -107,6 +108,8 @@ public:
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
nOrderPosNext = 0;
nCachedStakeWeight = 0;
nCachedStakeWeightTime = 0;
}
CWallet(std::string strWalletFileIn)
{
@@ -117,6 +120,8 @@ public:
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
nOrderPosNext = 0;
nCachedStakeWeight = 0;
nCachedStakeWeightTime = 0;
}
std::map<uint256, CWalletTx> mapWallet;
@@ -190,6 +195,8 @@ public:
int64_t GetImmatureBalance() const;
int64_t GetStake() const;
int64_t GetNewMint() const;
// Get all balances in a single lock acquisition + single pass (avoids 4x lock + 4x iteration)
bool GetAllBalances(int64_t& nBalance, int64_t& nStake, int64_t& nUnconfirmed, int64_t& nImmature) const;
bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl *coinControl=NULL);
bool CreateTransaction(CScript scriptPubKey, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl *coinControl=NULL);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
@@ -197,6 +204,10 @@ public:
bool GetStakeWeight(const CKeyStore& keystore, uint64_t& nMinWeight, uint64_t& nMaxWeight, uint64_t& nWeight);
bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key);
// Cached staking info - updated by the staking thread, read by the UI thread.
std::atomic<uint64_t> nCachedStakeWeight;
std::atomic<int64_t> nCachedStakeWeightTime; // GetTime() when last updated
std::string SendMoney(CScript scriptPubKey, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, bool fAskFee=false);
std::string SendMoneyToDestination(const CTxDestination& address, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, bool fAskFee=false);
+2 -2
View File
@@ -47,7 +47,7 @@ bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry)
{
return Write(boost::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry);
return Write(std::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry);
}
bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
@@ -80,7 +80,7 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
// Read next record
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
if (fFlags == DB_SET_RANGE)
ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64_t(0));
ssKey << std::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64_t(0));
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
fFlags = DB_NEXT;
+11 -5
View File
@@ -204,6 +204,7 @@ HEADERS += src/qt/trianglesgui.h \
src/qt/addressbookpage.h \
src/qt/aboutdialog.h \
src/qt/introdialog.h \
src/bootstrap.h \
src/qt/editaddressdialog.h \
src/qt/trianglesaddressvalidator.h \
src/alert.h \
@@ -322,6 +323,7 @@ SOURCES += src/qt/triangles.cpp src/qt/trianglesgui.cpp \
src/qt/addressbookpage.cpp \
src/qt/aboutdialog.cpp \
src/qt/introdialog.cpp \
src/bootstrap.cpp \
src/qt/editaddressdialog.cpp \
src/qt/trianglesaddressvalidator.cpp \
# Old embedded Tor v2 client removed - incompatible with OpenSSL 3.x
@@ -331,6 +333,7 @@ SOURCES += src/qt/triangles.cpp src/qt/trianglesgui.cpp \
src/version.cpp \
src/sync.cpp \
src/smessage.cpp \
src/lz4/lz4.c \
src/util.cpp \
src/netbase.cpp \
src/key.cpp \
@@ -557,8 +560,7 @@ contains(USE_ZMQ, 1) {
# Embedded Tor support (optional)
# Build with:
# qmake "USE_TOR_EMBEDDED=1" "TOR_INCLUDE_PATH=src/tor/tor-src/src/feature/api" \
# "TOR_LIB_PATH=src/tor/tor-src/src/core src/tor/tor-src/src/lib src/tor/tor-src/src/trunnel"
# qmake "USE_TOR_EMBEDDED=1" "TOR_SOURCE_ROOT=src/tor/tor-src"
contains(USE_TOR_EMBEDDED, 1) {
message(Building with embedded Tor support)
DEFINES += ENABLE_TOR_EMBEDDED
@@ -572,7 +574,7 @@ contains(USE_TOR_EMBEDDED, 1) {
}
isEmpty(TOR_LIB_PATH) {
TOR_LIB_PATH = $$TOR_SOURCE_ROOT/src/core $$TOR_SOURCE_ROOT/src/lib $$TOR_SOURCE_ROOT/src/trunnel
TOR_LIB_PATH = $$TOR_SOURCE_ROOT
}
!isEmpty(TOR_INCLUDE_PATH) {
@@ -583,10 +585,11 @@ contains(USE_TOR_EMBEDDED, 1) {
LIBS += -L$$path
}
# Default static library set for Tor 0.4.8/0.4.9 style builds.
# Default static library set for the imported Tor 0.4.9.x tree.
# A full upstream build emits a top-level libtor.a aggregator.
# Override with TOR_EMBEDDED_LIBS from the qmake command line if needed.
isEmpty(TOR_EMBEDDED_LIBS) {
TOR_EMBEDDED_LIBS = -ltor-app -lor -lor-ctime -lor-event -lor-trunnel
TOR_EMBEDDED_LIBS = -ltor
}
unix {
@@ -594,6 +597,9 @@ contains(USE_TOR_EMBEDDED, 1) {
} else {
LIBS += $$TOR_EMBEDDED_LIBS
}
LIBS += -llzma -lzstd
windows:LIBS += -liphlpapi
}
system($$QMAKE_LRELEASE -silent $$_PRO_FILE_)