Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2abd494fec | |||
| 378b0370e3 | |||
| 61f22fcfd4 | |||
| bf1bf393c8 | |||
| 39e244a11c | |||
| 6724dfc832 | |||
| 9dadba6b09 |
@@ -9,7 +9,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
VERSION: "5.2.0"
|
||||
VERSION: "5.3.3"
|
||||
|
||||
jobs:
|
||||
build-windows-qt:
|
||||
|
||||
+21
-26
@@ -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
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// 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 <fstream>
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace Bootstrap
|
||||
@@ -0,0 +1,39 @@
|
||||
// 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);
|
||||
|
||||
} // namespace Bootstrap
|
||||
|
||||
#endif // TRIANGLES_BOOTSTRAP_H
|
||||
+1
-1
@@ -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 1
|
||||
#define CLIENT_VERSION_REVISION 3
|
||||
#define CLIENT_VERSION_BUILD 0
|
||||
|
||||
// Converts the parameter X to a string after macro replacement on X has been performed.
|
||||
|
||||
+2
-1
@@ -3392,7 +3392,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);
|
||||
}
|
||||
|
||||
+26
-2
@@ -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)
|
||||
@@ -135,8 +135,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 +211,27 @@ 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/net_bootstrap.o: net_bootstrap.cpp
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
|
||||
+12
-4
@@ -170,24 +170,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 +244,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); \
|
||||
|
||||
+12
-12
@@ -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,7 +551,7 @@ void StakeMiner(CWallet *pwallet)
|
||||
if (fTryToSync)
|
||||
{
|
||||
fTryToSync = false;
|
||||
if (vNodes.size() < 3 || nBestHeight < GetNumBlocksOfPeers())
|
||||
if (vNodes.size() < 1 || nBestHeight < GetNumBlocksOfPeers())
|
||||
{
|
||||
MilliSleep(60000);
|
||||
continue;
|
||||
@@ -562,7 +562,7 @@ void StakeMiner(CWallet *pwallet)
|
||||
// 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
@@ -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,5 +1,6 @@
|
||||
#include "introdialog.h"
|
||||
#include "util.h"
|
||||
#include "bootstrap.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QVBoxLayout>
|
||||
@@ -9,6 +10,8 @@
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QProgressDialog>
|
||||
#include <QApplication>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -201,5 +204,81 @@ bool IntroDialog::pickDataDirectory()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Offer bootstrap download once (tracks via QSettings so it only asks once)
|
||||
fs::path dataDirPath(dataDir.toStdString());
|
||||
if (!settings.value("bootstrapOffered", false).toBool())
|
||||
{
|
||||
settings.setValue("bootstrapOffered", true);
|
||||
|
||||
int ret = QMessageBox::question(0, "Triangles",
|
||||
"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.",
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
|
||||
if (ret == QMessageBox::Yes)
|
||||
{
|
||||
std::string host = Bootstrap::DEFAULT_HOST;
|
||||
std::string strError;
|
||||
std::vector<std::string> files;
|
||||
|
||||
// Fetch file list (try domain first, then fallback to IP)
|
||||
if (!Bootstrap::FetchFileList(host, files, strError)) {
|
||||
host = Bootstrap::FALLBACK_HOST;
|
||||
if (!Bootstrap::FetchFileList(host, files, strError)) {
|
||||
QMessageBox::warning(0, "Triangles",
|
||||
QString("Could not reach bootstrap server:\n%1\n\n"
|
||||
"The wallet will sync from the network instead.")
|
||||
.arg(QString::fromStdString(strError)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Show progress dialog
|
||||
QProgressDialog progress("Downloading blockchain data...", "Cancel",
|
||||
0, (int)files.size(), 0);
|
||||
progress.setWindowTitle("Triangles - Bootstrap");
|
||||
progress.setWindowModality(Qt::ApplicationModal);
|
||||
progress.setMinimumDuration(0);
|
||||
progress.setValue(0);
|
||||
|
||||
bool failed = false;
|
||||
for (int i = 0; i < (int)files.size(); i++) {
|
||||
if (progress.wasCanceled())
|
||||
break;
|
||||
|
||||
QString filename = QString::fromStdString(files[i]);
|
||||
progress.setLabelText(
|
||||
QString("Downloading %1 (%2 of %3)...")
|
||||
.arg(filename).arg(i + 1).arg((int)files.size()));
|
||||
progress.setValue(i);
|
||||
QApplication::processEvents();
|
||||
|
||||
// Create subdirectories if needed (e.g. txleveldb/)
|
||||
fs::path destPath = dataDirPath / files[i];
|
||||
fs::create_directories(destPath.parent_path());
|
||||
|
||||
// Download this file
|
||||
std::string urlPath = std::string(Bootstrap::BASE_PATH) + files[i];
|
||||
if (!Bootstrap::DownloadFile(host, urlPath, destPath,
|
||||
[](int64_t, int64_t) {
|
||||
QApplication::processEvents();
|
||||
}, strError))
|
||||
{
|
||||
QMessageBox::warning(0, "Triangles",
|
||||
QString("Download failed for %1:\n%2\n\n"
|
||||
"The wallet will sync remaining data from the network.")
|
||||
.arg(filename).arg(QString::fromStdString(strError)));
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!failed)
|
||||
progress.setValue((int)files.size());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -78,6 +78,12 @@ void WalletModel::pollBalanceChanged()
|
||||
{
|
||||
if(nBestHeight != cachedNumBlocks)
|
||||
{
|
||||
// Don't block the UI thread waiting for cs_wallet - skip this
|
||||
// update cycle if the lock is held by the block processing thread
|
||||
TRY_LOCK(wallet->cs_wallet, lockWallet);
|
||||
if(!lockWallet)
|
||||
return;
|
||||
|
||||
// Balance and number of transactions might have changed
|
||||
cachedNumBlocks = nBestHeight;
|
||||
checkBalanceChanged();
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <tuple>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
#include "script.h"
|
||||
#include "keystore.h"
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ Notes:
|
||||
#include "txdb.h"
|
||||
|
||||
|
||||
#include "lz4/lz4.c"
|
||||
#include "lz4/lz4.h"
|
||||
|
||||
#include "xxhash/xxhash.h"
|
||||
#include "xxhash/xxhash.c"
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
|
||||
@@ -739,7 +740,7 @@ void ThreadRPCServer(void* parg)
|
||||
|
||||
// Forward declaration required for RPCListen
|
||||
template <typename Protocol, typename SocketAcceptorService>
|
||||
static void RPCAcceptHandler(std::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
|
||||
static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
|
||||
ssl::context& context,
|
||||
bool fUseSSL,
|
||||
AcceptedConnection* conn,
|
||||
@@ -749,7 +750,7 @@ static void RPCAcceptHandler(std::shared_ptr< basic_socket_acceptor<Protocol, So
|
||||
* Sets up I/O resources to accept and handle a new connection.
|
||||
*/
|
||||
template <typename Protocol, typename SocketAcceptorService>
|
||||
static void RPCListen(std::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
|
||||
static void RPCListen(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
|
||||
ssl::context& context,
|
||||
const bool fUseSSL)
|
||||
{
|
||||
@@ -771,7 +772,7 @@ static void RPCListen(std::shared_ptr< basic_socket_acceptor<Protocol, SocketAcc
|
||||
* Accept and handle incoming connection.
|
||||
*/
|
||||
template <typename Protocol, typename SocketAcceptorService>
|
||||
static void RPCAcceptHandler(std::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
|
||||
static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketAcceptorService> > acceptor,
|
||||
ssl::context& context,
|
||||
const bool fUseSSL,
|
||||
AcceptedConnection* conn,
|
||||
@@ -874,7 +875,7 @@ void ThreadRPCServer2(void* parg)
|
||||
asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any();
|
||||
ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", GetDefaultRPCPort()));
|
||||
boost::system::error_code v6_only_error;
|
||||
std::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(io_service));
|
||||
boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(io_service));
|
||||
|
||||
boost::signals2::signal<void ()> StopRequests;
|
||||
|
||||
|
||||
+1
-1
@@ -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 1
|
||||
#define DISPLAY_VERSION_REVISION 3
|
||||
#define DISPLAY_VERSION_BUILD 0
|
||||
|
||||
#endif
|
||||
|
||||
+12
-1
@@ -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))) {
|
||||
@@ -1477,7 +1488,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)
|
||||
{
|
||||
|
||||
+11
-5
@@ -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_)
|
||||
|
||||
Reference in New Issue
Block a user