9 Commits
dragonx ... dev

Author SHA1 Message Date
Duke
61513966c2 Remove googlemock and googletest deps 2026-03-03 18:47:26 -05:00
Duke
f15ac8ca8f Add randomx unit tests 2026-03-03 18:42:14 -05:00
Duke
71a8a627bd Add more netbase tests 2026-03-03 18:19:04 -05:00
Duke
2781ea64e0 Add netbase unit tests 2026-03-03 18:11:00 -05:00
Duke
25c62c52f5 remove ntz tests 2026-03-03 17:35:22 -05:00
Duke
c5a9aab2f9 Merge remote-tracking branch 'origin/dev' into dev 2026-03-03 17:33:57 -05:00
Duke
4a69d23e05 Add c++ unit tests with docs; split out ./rpctest and ./cpptest from ./test 2026-03-03 17:31:24 -05:00
duke
d6d495c447 AI/LLM usage policy
Inspired by the policy in https://github.com/ggml-org/llama.cpp/blob/master/CONTRIBUTING.md
2026-03-03 11:40:16 -05:00
duke
0867d8cf62 We do not have a code of conduct doc 2026-03-03 11:29:15 -05:00
47 changed files with 502 additions and 4347 deletions

8
.gitignore vendored
View File

@@ -167,11 +167,3 @@ REGTEST_7776
src/cc/librogue.so src/cc/librogue.so
src/cc/games/prices src/cc/games/prices
src/cc/games/tetris src/cc/games/tetris
release-linux/
release/
src/dragonxd
src/dragonx-cli
src/dragonx-tx
src/dragonxd.exe
src/dragonx-cli.exe
src/dragonx-tx.exe

145
build.sh
View File

@@ -1,152 +1,19 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Copyright (c) 2016-2024 The Hush developers # Copyright (c) 2016-2024 The Hush developers
# Copyright (c) 2024-2026 The DragonX developers
# Distributed under the GPLv3 software license, see the accompanying # Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html # file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
set -eu -o pipefail set -eu -o pipefail
VERSION="1.0.0" # run correct build script for detected OS
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RELEASE_DIR="$SCRIPT_DIR/release"
# Parse release flags
BUILD_LINUX_RELEASE=0
BUILD_WIN_RELEASE=0
BUILD_MAC_RELEASE=0
REMAINING_ARGS=()
for arg in "$@"; do
case "$arg" in
--linux-release)
BUILD_LINUX_RELEASE=1
;;
--win-release)
BUILD_WIN_RELEASE=1
;;
--mac-release)
BUILD_MAC_RELEASE=1
;;
--all-release)
BUILD_LINUX_RELEASE=1
BUILD_WIN_RELEASE=1
BUILD_MAC_RELEASE=1
;;
*)
REMAINING_ARGS+=("$arg")
;;
esac
done
# Clean artifacts that may conflict between platform builds
clean_for_platform() {
local platform="$1"
echo "Cleaning build artifacts for $platform build..."
# Use make clean if Makefile exists (safer than manual deletion)
if [ -f src/Makefile ]; then
make -C src clean 2>/dev/null || true
fi
# Remove final binaries
if [ -d src ]; then
rm -f src/dragonxd src/dragonx-cli src/dragonx-tx 2>/dev/null || true
rm -f src/dragonxd.exe src/dragonx-cli.exe src/dragonx-tx.exe 2>/dev/null || true
rm -f src/hushd src/hush-cli src/hush-tx 2>/dev/null || true
rm -f src/hushd.exe src/hush-cli.exe src/hush-tx.exe 2>/dev/null || true
fi
# Clean RandomX build for cross-platform compatibility
rm -rf src/RandomX/build 2>/dev/null || true
# Clean cryptoconditions
rm -rf src/cc/*.o src/cc/*.a 2>/dev/null || true
# Clean config cache (forces reconfigure for cross-platform)
rm -f config.status config.log 2>/dev/null || true
echo "Clean complete for $platform"
}
# Package release for a platform
package_release() {
local platform="$1"
local release_subdir="$RELEASE_DIR/dragonx-$VERSION-$platform"
echo "Packaging release for $platform..."
mkdir -p "$release_subdir"
# Copy bootstrap script
cp "$SCRIPT_DIR/util/bootstrap-dragonx.sh" "$release_subdir/"
# Copy common files
cp "$SCRIPT_DIR/contrib/asmap/asmap.dat" "$release_subdir/" 2>/dev/null || true
cp "$SCRIPT_DIR/sapling-output.params" "$release_subdir/" 2>/dev/null || true
cp "$SCRIPT_DIR/sapling-spend.params" "$release_subdir/" 2>/dev/null || true
case "$platform" in
linux-amd64)
cp "$SCRIPT_DIR/src/dragonxd" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-cli" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-tx" "$release_subdir/"
strip "$release_subdir/dragonxd" "$release_subdir/dragonx-cli" "$release_subdir/dragonx-tx"
;;
win64)
cp "$SCRIPT_DIR/src/dragonxd.exe" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-cli.exe" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-tx.exe" "$release_subdir/"
x86_64-w64-mingw32-strip "$release_subdir/"*.exe 2>/dev/null || strip "$release_subdir/"*.exe 2>/dev/null || true
;;
macos)
cp "$SCRIPT_DIR/src/dragonxd" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-cli" "$release_subdir/"
cp "$SCRIPT_DIR/src/dragonx-tx" "$release_subdir/"
strip "$release_subdir/dragonxd" "$release_subdir/dragonx-cli" "$release_subdir/dragonx-tx" 2>/dev/null || true
;;
esac
echo "Release packaged: $release_subdir"
ls -la "$release_subdir"
}
# Handle release builds
if [ $BUILD_LINUX_RELEASE -eq 1 ] || [ $BUILD_WIN_RELEASE -eq 1 ] || [ $BUILD_MAC_RELEASE -eq 1 ]; then
mkdir -p "$RELEASE_DIR"
if [ $BUILD_LINUX_RELEASE -eq 1 ]; then
echo "=== Building Linux release ==="
clean_for_platform linux
./util/build.sh --disable-tests "${REMAINING_ARGS[@]}"
package_release linux-amd64
fi
if [ $BUILD_WIN_RELEASE -eq 1 ]; then
echo "=== Building Windows release ==="
clean_for_platform windows
./util/build-win.sh --disable-tests "${REMAINING_ARGS[@]}"
package_release win64
fi
if [ $BUILD_MAC_RELEASE -eq 1 ]; then
echo "=== Building macOS release ==="
clean_for_platform macos
./util/build-mac.sh --disable-tests "${REMAINING_ARGS[@]}"
package_release macos
fi
echo ""
echo "=== Release builds complete ==="
ls -la "$RELEASE_DIR"/
exit 0
fi
# Standard build (auto-detect OS)
if [[ "$OSTYPE" == "linux-gnu"* ]]; then if [[ "$OSTYPE" == "linux-gnu"* ]]; then
./util/build.sh --disable-tests "${REMAINING_ARGS[@]}" ./util/build.sh $@
elif [[ "$OSTYPE" == "darwin"* ]]; then elif [[ "$OSTYPE" == "darwin"* ]]; then
./util/build-mac.sh --disable-tests "${REMAINING_ARGS[@]}" ./util/build-mac.sh $@
elif [[ "$OSTYPE" == "msys"* ]]; then elif [[ "$OSTYPE" == "msys"* ]]; then
./util/build-win.sh --disable-tests "${REMAINING_ARGS[@]}" ./util/build-win.sh $@
#elif [[ "$OSTYPE" == "freebsd"* ]]; then
# placeholder
else else
echo "Unable to detect your OS. What are you using?" echo "Unable to detect your OS. What are you using?"
fi fi

View File

@@ -1,23 +1,23 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60]) AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 1) define(_CLIENT_VERSION_MAJOR, 3)
dnl Must be kept in sync with src/clientversion.h , ugh! dnl Must be kept in sync with src/clientversion.h , ugh!
define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_MINOR, 10)
define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_REVISION, 5)
define(_CLIENT_VERSION_BUILD, 50) define(_CLIENT_VERSION_BUILD, 50)
define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))
define(_CLIENT_VERSION_IS_RELEASE, true) define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2026) define(_COPYRIGHT_YEAR, 2026)
AC_INIT([DragonX],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://git.dragonx.is/DragonX/dragonx],[dragonx]) AC_INIT([Hush],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://git.hush.is/hush/hush3],[hush])
AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4]) AC_CONFIG_MACRO_DIR([build-aux/m4])
BITCOIN_DAEMON_NAME=dragonxd BITCOIN_DAEMON_NAME=hushd
BITCOIN_CLI_NAME=dragonx-cli BITCOIN_CLI_NAME=hush-cli
BITCOIN_TX_NAME=dragonx-tx BITCOIN_TX_NAME=hush-tx
dnl Unless the user specified ARFLAGS, force it to be cr dnl Unless the user specified ARFLAGS, force it to be cr
AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to <cr> if not set]) AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to <cr> if not set])

7
cpptest Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
# Copyright 2026-now The Hush developers
# Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
# Run all tests by default
./src/hush-test $@

View File

@@ -1,33 +0,0 @@
# url=https://github.com/google/googlemock/archive/release-1.7.0.tar.gz
package=googlemock
$(package)_version=1.7.0
$(package)_dependencies=googletest
$(package)_download_path=https://github.com/google/$(package)/archive
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_download_file=release-$($(package)_version).tar.gz
$(package)_sha256_hash=3f20b6acb37e5a98e8c4518165711e3e35d47deb6cdb5a4dd4566563b5efd232
ifeq ($(build_os),darwin)
define $(package)_set_vars
$(package)_build_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" CXX="$($(package)_cxx)" CXXFLAGS="$($(package)_cxxflags)"
endef
endif
ifeq ($(build_os),darwin)
$(package)_install=ginstall
define $(package)_build_cmds
$(MAKE) -C make GTEST_DIR='$(host_prefix)' gmock-all.o
endef
else
$(package)_install=install
define $(package)_build_cmds
$(MAKE) -C make GTEST_DIR='$(host_prefix)' CXXFLAGS='-fPIC' gmock-all.o
endef
endif
define $(package)_stage_cmds
$($(package)_install) -D ./make/gmock-all.o $($(package)_staging_dir)$(host_prefix)/lib/libgmock.a && \
cp -a ./include $($(package)_staging_dir)$(host_prefix)/include
endef

View File

@@ -1,40 +0,0 @@
package=googletest
$(package)_version=1.8.0
$(package)_download_path=https://github.com/google/$(package)/archive
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_download_file=release-$($(package)_version).tar.gz
$(package)_sha256_hash=58a6f4277ca2bc8565222b3bbd58a177609e9c488e8a72649359ba51450db7d8
define $(package)_set_vars
$(package)_cxxflags+=-std=c++11
$(package)_cxxflags_linux=-fPIC
endef
ifeq ($(build_os),darwin)
define $(package)_set_vars
$(package)_build_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" CXX="$($(package)_cxx)" CXXFLAGS="$($(package)_cxxflags)"
endef
endif
ifeq ($(build_os),darwin)
$(package)_install=ginstall
define $(package)_build_cmds
$(MAKE) -C googlemock/make gmock.a && \
$(MAKE) -C googletest/make gtest.a
endef
else
$(package)_install=install
define $(package)_build_cmds
$(MAKE) -C googlemock/make CC="$($(package)_cc)" CXX="$($(package)_cxx)" AR="$($(package)_ar)" CXXFLAGS="$($(package)_cxxflags)" gmock.a && \
$(MAKE) -C googletest/make CC="$($(package)_cc)" CXX="$($(package)_cxx)" AR="$($(package)_ar)" CXXFLAGS="$($(package)_cxxflags)" gtest.a
endef
endif
define $(package)_stage_cmds
mkdir -p $($(package)_staging_dir)$(host_prefix)/lib && \
install ./googlemock/make/gmock.a $($(package)_staging_dir)$(host_prefix)/lib/libgmock.a && \
install ./googletest/make/gtest.a $($(package)_staging_dir)$(host_prefix)/lib/libgtest.a && \
cp -a ./googlemock/include $($(package)_staging_dir)$(host_prefix)/ && \
cp -a ./googletest/include $($(package)_staging_dir)$(host_prefix)/
endef

View File

@@ -39,8 +39,8 @@ native_packages := native_ccache
wallet_packages=bdb wallet_packages=bdb
ifeq ($(host_os),linux) ifeq ($(host_os),linux)
packages := boost wolfssl libevent $(zcash_packages) libcurl #googlemock googletest packages := boost wolfssl libevent $(zcash_packages) libcurl
else else
packages := boost wolfssl libevent $(zcash_packages) libcurl #googlemock googletest packages := boost wolfssl libevent $(zcash_packages) libcurl
endif endif

View File

@@ -1,10 +1,10 @@
# Hush Core (hushd) Software Contribution Guidelines # Hush Core (hushd) Software Contribution Guidelines
Thank you for reaching out and trying to make Hush an even better software application and cryptocoin platform. These contribution guidelines shall help you figuring out where you can be helpful and how to easily get started. Thank you for reaching out and trying to make Hush an even better software application and cryptocoin platform. These contribution guidelines shall help you figuring out where you can be helpful and how to easily get started.
## Table of Contents ## Table of Contents
0. [AI/LLM Usage Policty](#ai/llm-usage-policy)
0. [Types of contributions we're looking for](#types-of-contributions-were-looking-for) 0. [Types of contributions we're looking for](#types-of-contributions-were-looking-for)
0. [Ground rules & expectations](#ground-rules--expectations) 0. [Ground rules & expectations](#ground-rules--expectations)
0. [How to contribute](#how-to-contribute) 0. [How to contribute](#how-to-contribute)
@@ -13,6 +13,21 @@ Thank you for reaching out and trying to make Hush an even better software appli
0. [Contribution review process](#contribution-review-process) 0. [Contribution review process](#contribution-review-process)
0. [Community](#community) 0. [Community](#community)
## AI/LLM Usage Policy
> [!IMPORTANT]
> This project does **NOT** accept pull requests that are fully or predominantly AI-generated. AI tools may be utilized solely in an assistive capacity. The human submitting new code to the project must actually understand the code changes they are submitting.
Code that is initially generated by AI and subsequently edited will still be considered AI-generated. AI assistance is permissible only when the majority of the code is authored by a human contributor, with AI employed exclusively for corrections or to expand on verbose modifications that the contributor has already conceptualized (e.g., generating repeated lines with minor variations).
If AI is used to generate any portion of the code, contributors must adhere to the following requirements:
1. Explicitly disclose the manner in which AI was employed, including the exact model and quantization used and if it was done via local AI, such as with llama.cpp or a SaaS provider.
2. Perform a comprehensive manual review prior to submitting the pull request.
3. Be prepared to explain every line of code they submitted when asked about it by a maintainer.
4. It is strictly prohibited to use AI to write your posts for you (bug reports, feature requests, pull request descriptions, Github discussions, responding to humans, ...).
## Types of contributions we're looking for ## Types of contributions we're looking for
There are many ways you can directly contribute to Hush: There are many ways you can directly contribute to Hush:
@@ -31,7 +46,6 @@ Interested in making a contribution? Read on!
Before we get started, here are a few things we expect from you (and that you should expect from others): Before we get started, here are a few things we expect from you (and that you should expect from others):
* Be kind and thoughtful in your conversations around this project. We all come from different backgrounds and projects, which means we likely have different perspectives on "how free software and open source is done." Try to listen to others rather than convince them that your way is correct. * Be kind and thoughtful in your conversations around this project. We all come from different backgrounds and projects, which means we likely have different perspectives on "how free software and open source is done." Try to listen to others rather than convince them that your way is correct.
* Open Source Guides are released with a [Contributor Code of Conduct](./code_of_conduct.md). By participating in this project, you agree to abide by its terms.
* If you open a pull request, please ensure that your contribution does not increase test failures. If there are additional test failures, you will need to address them before we can merge your contribution. * If you open a pull request, please ensure that your contribution does not increase test failures. If there are additional test failures, you will need to address them before we can merge your contribution.
* When adding content, please consider if it is widely valuable. Please don't add references or links to things you or your employer have created as others will do so if they appreciate it. * When adding content, please consider if it is widely valuable. Please don't add references or links to things you or your employer have created as others will do so if they appreciate it.

View File

@@ -16,6 +16,48 @@ other programs and Operating System overhead. A good rule of thumb is:
Divide how many GBs of RAM you have by 2, subtract one. Use that many jobs. Divide how many GBs of RAM you have by 2, subtract one. Use that many jobs.
# Run all tests
To run both C++ and RPC tests:
./test
C++ test run much faster than the RPC tests.
## Run C++ Unit tests
To run the C++ unit tests
./src/hush-test
Example successful output:
Running 42 test cases...
*** No errors detected
Example failure output:
Running 42 test cases...
test-hush/main.cpp(16): error: in "test_sodium": check init_and_check_sodium() != 0 has failed [0 == 0]
*** 1 failure is detected in the test module "HushTestSuite"
# Run Python RPC tests
To run our QA/functional tests:
./rpctest
Example successful output:
# Running 2 tests..
PASS!
Example failure output:
FAIL! Number of failed tests: 1 . Details in test-1234567.txt
## Dealing with dependency changes ## Dealing with dependency changes

47
rpctest Executable file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env perl
# Copyright 2016-2026 The Hush developers
# Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
use strict;
use warnings;
use 5.010;
my $flags = $ENV{TEST_FLAGS} || '--tracerpc';
my $test_dir = './qa/rpc-tests';
$ENV{PYTHONPATH} = "./qa/rpc-tests/test_framework/";
#$ENV{PYTHON_DEBUG} = 1;
my @tests_to_run = qw{
lockzins.py
shieldcoinbase_donation.py
};
my $exit = 0;
my $failed_tests = 0;
my $time=time();
my $num_tests = @tests_to_run;
print "# Running $num_tests tests";
for my $test (@tests_to_run) {
# send both stderr+stdout to our output file
my $cmd = "$test_dir/$test $flags 1>test-$time.txt 2>&1";
system($cmd);
print ".";
if($?) {
say "$cmd FAILED!";
$exit = 1;
$failed_tests++;
}
}
print "\n";
if ($exit) {
say "FAIL! Number of failed tests: $failed_tests . Details in test-$time.txt";
} else {
say "PASS!";
}
exit($exit);

View File

@@ -94,11 +94,11 @@ noinst_PROGRAMS =
TESTS = TESTS =
#if BUILD_BITCOIND #if BUILD_BITCOIND
bin_PROGRAMS += dragonxd bin_PROGRAMS += hushd
#endif #endif
if BUILD_BITCOIN_UTILS if BUILD_BITCOIN_UTILS
bin_PROGRAMS += dragonx-cli dragonx-tx bin_PROGRAMS += hush-cli hush-tx
endif endif
if ENABLE_WALLET if ENABLE_WALLET
bin_PROGRAMS += wallet-utility bin_PROGRAMS += wallet-utility
@@ -453,16 +453,16 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
# #
# hushd binary # # hushd binary #
dragonxd_SOURCES = bitcoind.cpp hushd_SOURCES = bitcoind.cpp
dragonxd_CPPFLAGS = -fPIC $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) hushd_CPPFLAGS = -fPIC $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
dragonxd_CXXFLAGS = -fPIC $(AM_CXXFLAGS) $(PIE_FLAGS) hushd_CXXFLAGS = -fPIC $(AM_CXXFLAGS) $(PIE_FLAGS)
dragonxd_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) hushd_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_WINDOWS if TARGET_WINDOWS
dragonxd_SOURCES += bitcoind-res.rc hushd_SOURCES += bitcoind-res.rc
endif endif
dragonxd_LDADD = \ hushd_LDADD = \
$(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_COMMON) \
$(LIBUNIVALUE) \ $(LIBUNIVALUE) \
@@ -476,10 +476,10 @@ dragonxd_LDADD = \
$(LIBRANDOMX) $(LIBRANDOMX)
if ENABLE_WALLET if ENABLE_WALLET
dragonxd_LDADD += $(LIBBITCOIN_WALLET) hushd_LDADD += $(LIBBITCOIN_WALLET)
endif endif
dragonxd_LDADD += \ hushd_LDADD += \
$(BOOST_LIBS) \ $(BOOST_LIBS) \
$(BDB_LIBS) \ $(BDB_LIBS) \
$(SSL_LIBS) \ $(SSL_LIBS) \
@@ -490,27 +490,27 @@ dragonxd_LDADD += \
$(LIBZCASH_LIBS) $(LIBZCASH_LIBS)
if TARGET_DARWIN if TARGET_DARWIN
dragonxd_LDADD += libcc.dylib $(LIBSECP256K1) hushd_LDADD += libcc.dylib $(LIBSECP256K1)
endif endif
if TARGET_WINDOWS if TARGET_WINDOWS
dragonxd_LDADD += libcc.dll $(LIBSECP256K1) hushd_LDADD += libcc.dll $(LIBSECP256K1)
endif endif
if TARGET_LINUX if TARGET_LINUX
dragonxd_LDADD += libcc.so $(LIBSECP256K1) hushd_LDADD += libcc.so $(LIBSECP256K1)
endif endif
# [+] Decker: use static linking for libstdc++.6.dylib, libgomp.1.dylib, libgcc_s.1.dylib # [+] Decker: use static linking for libstdc++.6.dylib, libgomp.1.dylib, libgcc_s.1.dylib
if TARGET_DARWIN if TARGET_DARWIN
dragonxd_LDFLAGS += -static-libgcc hushd_LDFLAGS += -static-libgcc
endif endif
# hush-cli binary # # hush-cli binary #
dragonx_cli_SOURCES = bitcoin-cli.cpp hush_cli_SOURCES = bitcoin-cli.cpp
dragonx_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) hush_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS)
dragonx_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) hush_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
dragonx_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) hush_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_DARWIN if TARGET_DARWIN
dragonx_cli_LDFLAGS += -static-libgcc hush_cli_LDFLAGS += -static-libgcc
endif endif
# wallet-utility binary # # wallet-utility binary #
@@ -522,10 +522,10 @@ wallet_utility_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
endif endif
if TARGET_WINDOWS if TARGET_WINDOWS
dragonx_cli_SOURCES += bitcoin-cli-res.rc hush_cli_SOURCES += bitcoin-cli-res.rc
endif endif
dragonx_cli_LDADD = \ hush_cli_LDADD = \
$(LIBBITCOIN_CLI) \ $(LIBBITCOIN_CLI) \
$(LIBUNIVALUE) \ $(LIBUNIVALUE) \
$(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_UTIL) \
@@ -554,16 +554,16 @@ wallet_utility_LDADD = \
endif endif
# hush-tx binary # # hush-tx binary #
dragonx_tx_SOURCES = hush-tx.cpp hush_tx_SOURCES = hush-tx.cpp
dragonx_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) hush_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
dragonx_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) hush_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
dragonx_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) hush_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_WINDOWS if TARGET_WINDOWS
dragonx_tx_SOURCES += bitcoin-tx-res.rc hush_tx_SOURCES += bitcoin-tx-res.rc
endif endif
dragonx_tx_LDADD = \ hush_tx_LDADD = \
$(LIBUNIVALUE) \ $(LIBUNIVALUE) \
$(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_UTIL) \
@@ -574,7 +574,7 @@ dragonx_tx_LDADD = \
$(LIBZCASH_LIBS) \ $(LIBZCASH_LIBS) \
$(LIBRANDOMX) $(LIBRANDOMX)
dragonx_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) hush_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
# Zcash Protocol Primitives # Zcash Protocol Primitives
libzcash_a_SOURCES = \ libzcash_a_SOURCES = \
@@ -683,7 +683,7 @@ endif
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
if ENABLE_TESTS if ENABLE_TESTS
#include Makefile.test-hush.include include Makefile.test-hush.include
#include Makefile.test.include #include Makefile.test.include
#include Makefile.gtest.include #include Makefile.gtest.include
endif endif

View File

@@ -6,19 +6,14 @@ TESTS += hush-test
bin_PROGRAMS += hush-test bin_PROGRAMS += hush-test
# tool for generating our public parameters # tool for generating our public parameters
hush_test_SOURCES = test-hush/main.cpp hush_test_SOURCES = test-hush/main.cpp \
# devs can enable this shit, it just slows down default compiles test-hush/test_netbase_tests.cpp \
test-hush/randomx.cpp
# test-hush/testutils.cpp \ # test-hush/testutils.cpp \
# test-hush/test_cryptoconditions.cpp \ # test-hush/test_cryptoconditions.cpp \
# test-hush/test_coinimport.cpp \ # test-hush/test_coinimport.cpp \
# test-hush/test_eval_bet.cpp \ # test-hush/test_addrman.cpp
# test-hush/test_eval_notarization.cpp \
# test-hush/test_parse_notarization.cpp \
# test-hush/test_addrman.cpp \
# test-hush/test_netbase_tests.cpp
hush_test_CPPFLAGS = $(hushd_CPPFLAGS) hush_test_CPPFLAGS = $(hushd_CPPFLAGS)
hush_test_LDADD = $(hushd_LDADD)
hush_test_LDADD = -lgtest $(hushd_LDADD)
hush_test_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static hush_test_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static

View File

@@ -13,7 +13,7 @@
"ac_perc": "11111111", "ac_perc": "11111111",
"ac_eras": "3", "ac_eras": "3",
"ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac", "ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac",
"clientname": "DragonX", "clientname": "GoldenSandtrout",
"addnode": [ "addnode": [
"node1.hush.is", "node1.hush.is",
"node2.hush.is", "node2.hush.is",

View File

@@ -29,8 +29,8 @@
#include <event2/keyvalq_struct.h> #include <event2/keyvalq_struct.h>
#include "support/events.h" #include "support/events.h"
uint16_t ASSETCHAINS_RPCPORT = 21769; uint16_t ASSETCHAINS_RPCPORT = 18031;
uint16_t BITCOIND_RPCPORT = 21769; uint16_t BITCOIND_RPCPORT = 18031;
char SMART_CHAIN_SYMBOL[65]; char SMART_CHAIN_SYMBOL[65];
extern uint16_t ASSETCHAINS_RPCPORT; extern uint16_t ASSETCHAINS_RPCPORT;
@@ -47,7 +47,7 @@ std::string HelpMessageCli()
std::string strUsage; std::string strUsage;
strUsage += HelpMessageGroup(_("Options:")); strUsage += HelpMessageGroup(_("Options:"));
strUsage += HelpMessageOpt("-?", _("This help message")); strUsage += HelpMessageOpt("-?", _("This help message"));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "DRAGONX.conf")); strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "HUSH3.conf"));
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory (this path cannot use '~')")); strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory (this path cannot use '~')"));
strUsage += HelpMessageOpt("-testnet", _("Use the test network")); strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be " strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be "
@@ -87,19 +87,19 @@ static int AppInitRPC(int argc, char* argv[])
ParseParameters(argc, argv); ParseParameters(argc, argv);
std:string name; std:string name;
// default HAC is DRAGONX itself, which to the internals, is also a HAC // default HAC is HUSH3 itself, which to the internals, is also a HAC
name = GetArg("-ac_name","DRAGONX"); name = GetArg("-ac_name","HUSH3");
if ( !name.empty() ) if ( !name.empty() )
strncpy(SMART_CHAIN_SYMBOL,name.c_str(),sizeof(SMART_CHAIN_SYMBOL)-1); strncpy(SMART_CHAIN_SYMBOL,name.c_str(),sizeof(SMART_CHAIN_SYMBOL)-1);
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("DragonX RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); std::string strUsage = _("Hush RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo();
if (!mapArgs.count("-version")) { if (!mapArgs.count("-version")) {
strUsage += "\n" + _("Usage:") + "\n" + strUsage += "\n" + _("Usage:") + "\n" +
" dragonx-cli [options] <command> [params] " + _("Send command to DragonX") + "\n" + " hush-cli [options] <command> [params] " + _("Send command to Hush") + "\n" +
" dragonx-cli [options] help " + _("List commands") + "\n" + " hush-cli [options] help " + _("List commands") + "\n" +
" dragonx-cli [options] help <command> " + _("Get help for a command") + "\n"; " hush-cli [options] help <command> " + _("Get help for a command") + "\n";
strUsage += "\n" + HelpMessageCli(); strUsage += "\n" + HelpMessageCli();
} else { } else {

View File

@@ -117,14 +117,14 @@ bool AppInit(int argc, char* argv[])
// Process help and version before taking care about datadir // Process help and version before taking care about datadir
if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version"))
{ {
std::string strUsage = _("DragonX Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); std::string strUsage = _("Hush Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n" + PrivacyInfo();
if (mapArgs.count("-version")) if (mapArgs.count("-version"))
{ {
strUsage += LicenseInfo(); strUsage += LicenseInfo();
} else { } else {
strUsage += "\n" + _("Usage:") + "\n" + strUsage += "\n" + _("Usage:") + "\n" +
" dragonxd [options] " + _("Start DragonX Daemon") + "\n"; " hushd [options] " + _("Start a Hush Daemon") + "\n";
strUsage += "\n" + HelpMessage(HMM_BITCOIND); strUsage += "\n" + HelpMessage(HMM_BITCOIND);
} }
@@ -167,13 +167,13 @@ bool AppInit(int argc, char* argv[])
"\n" "\n"
"You can look at the example configuration file for suggestions of default\n" "You can look at the example configuration file for suggestions of default\n"
"options that you may want to change. It should be in one of these locations,\n" "options that you may want to change. It should be in one of these locations,\n"
"depending on how you installed DragonX\n") + "depending on how you installed Hush\n") +
_("- Source code: %s\n" _("- Source code: %s\n"
"- .deb package: %s\n")).c_str(), "- .deb package: %s\n")).c_str(),
GetConfigFile().string().c_str(), GetConfigFile().string().c_str(),
"contrib/debian/examples/DRAGONX.conf", "contrib/debian/examples/HUSH3.conf",
"/usr/share/doc/dragonx/examples/DRAGONX.conf", "/usr/share/doc/hush/examples/HUSH3.conf",
"https://git.dragonx.is/DragonX/dragonx/src/branch/main/contrib/debian/examples/DRAGONX.conf"); "https://git.hush.is/hush/hush3/src/branch/master/contrib/debian/examples/HUSH3.conf");
return false; return false;
} catch (const std::exception& e) { } catch (const std::exception& e) {
fprintf(stderr,"Error reading configuration file: %s\n", e.what()); fprintf(stderr,"Error reading configuration file: %s\n", e.what());
@@ -183,15 +183,15 @@ bool AppInit(int argc, char* argv[])
// Command-line RPC // Command-line RPC
bool fCommandLine = false; bool fCommandLine = false;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
// detect accidental use of RPC in dragonxd // detect accidental use of RPC in hushd
if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "dragonx:")) { if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "hush:")) {
fCommandLine = true; fCommandLine = true;
} }
} }
if (fCommandLine) if (fCommandLine)
{ {
fprintf(stderr, "Error: Ooops! There is no RPC client functionality in dragonxd. Use the dragonx-cli utility instead.\n"); fprintf(stderr, "Error: Ooops! There is no RPC client functionality in hushd. Use the hush-cli utility instead.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -199,7 +199,7 @@ bool AppInit(int argc, char* argv[])
fDaemon = GetBoolArg("-daemon", false); fDaemon = GetBoolArg("-daemon", false);
if (fDaemon) if (fDaemon)
{ {
fprintf(stdout, "DragonX %s server starting\n",SMART_CHAIN_SYMBOL); fprintf(stdout, "Hush %s server starting\n",SMART_CHAIN_SYMBOL);
// Daemonize // Daemonize
pid_t pid = fork(); pid_t pid = fork();

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ class CBaseMainParams : public CBaseChainParams
public: public:
CBaseMainParams() CBaseMainParams()
{ {
nRPCPort = 21769; nRPCPort = 18031;
} }
}; };
static CBaseMainParams mainParams; static CBaseMainParams mainParams;

View File

@@ -32,7 +32,7 @@
* for both bitcoind and bitcoin-core, to make it harder for attackers to * for both bitcoind and bitcoin-core, to make it harder for attackers to
* target servers or GUI users specifically. * target servers or GUI users specifically.
*/ */
const std::string CLIENT_NAME = GetArg("-clientname", "DragonX"); const std::string CLIENT_NAME = GetArg("-clientname", "GoldenSandtrout");
/** /**
* Client version number * Client version number

View File

@@ -28,9 +28,9 @@
// client versioning and copyright year // client versioning and copyright year
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
// Must be kept in sync with configure.ac , ugh! // Must be kept in sync with configure.ac , ugh!
#define CLIENT_VERSION_MAJOR 1 #define CLIENT_VERSION_MAJOR 3
#define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_MINOR 10
#define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_REVISION 5
#define CLIENT_VERSION_BUILD 50 #define CLIENT_VERSION_BUILD 50
//! Set to true for release, false for prerelease or test build //! Set to true for release, false for prerelease or test build
@@ -40,7 +40,7 @@
* Copyright year (2009-this) * Copyright year (2009-this)
* Todo: update this when changing our copyright comments in the source * Todo: update this when changing our copyright comments in the source
*/ */
#define COPYRIGHT_YEAR 2026 #define COPYRIGHT_YEAR 2024
#endif //HAVE_CONFIG_H #endif //HAVE_CONFIG_H

View File

@@ -403,7 +403,7 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *hushnotarized_hei
params[0] = 0; params[0] = 0;
*hushnotarized_heightp = 0; *hushnotarized_heightp = 0;
if ( strcmp(dest,"HUSH3") == 0 ) { if ( strcmp(dest,"HUSH3") == 0 ) {
port = DRAGONX_PORT; port = HUSH3_PORT;
userpass = HUSHUSERPASS; userpass = HUSHUSERPASS;
} else if ( strcmp(dest,"BTC") == 0 ) } else if ( strcmp(dest,"BTC") == 0 )
{ {
@@ -498,7 +498,7 @@ int32_t hush_verifynotarization(char *symbol,char *dest,int32_t height,int32_t N
{ {
if ( SMART_CHAIN_SYMBOL[0] != 0 ) if ( SMART_CHAIN_SYMBOL[0] != 0 )
{ {
jsonstr = hush_issuemethod(HUSHUSERPASS,(char *)"getrawtransaction",params,DRAGONX_PORT); jsonstr = hush_issuemethod(HUSHUSERPASS,(char *)"getrawtransaction",params,HUSH3_PORT);
//printf("userpass.(%s) got (%s)\n",HUSHUSERPASS,jsonstr); //printf("userpass.(%s) got (%s)\n",HUSHUSERPASS,jsonstr);
} }
}//else jsonstr = _dex_getrawtransaction(); }//else jsonstr = _dex_getrawtransaction();
@@ -1693,11 +1693,6 @@ int32_t hush_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
fprintf(stderr,"hush_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height); fprintf(stderr,"hush_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height);
return(-1); return(-1);
} }
if ( !CheckRandomXSolution(pblock, height) )
{
fprintf(stderr,"hush_checkPOW slowflag.%d ht.%d CheckRandomXSolution failed\n",slowflag,height);
return(-1);
}
hash = pblock->GetHash(); hash = pblock->GetHash();
bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow);
bhash = UintToArith256(hash); bhash = UintToArith256(hash);

View File

@@ -568,7 +568,6 @@ extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_FOUNDERS_REWARD;
extern int32_t ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER,ASSETCHAINS_BLOCKTIME; extern int32_t ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER,ASSETCHAINS_BLOCKTIME;
extern uint64_t ASSETCHAINS_TIMELOCKGTE; extern uint64_t ASSETCHAINS_TIMELOCKGTE;
extern uint32_t ASSETCHAINS_ALGO,ASSETCHAINS_EQUIHASH,ASSETCHAINS_RANDOMX, HUSH_INITDONE; extern uint32_t ASSETCHAINS_ALGO,ASSETCHAINS_EQUIHASH,ASSETCHAINS_RANDOMX, HUSH_INITDONE;
extern int32_t ASSETCHAINS_RANDOMX_VALIDATION;
extern int32_t HUSH_MININGTHREADS,HUSH_LONGESTCHAIN,ASSETCHAINS_SEED,IS_HUSH_NOTARY,USE_EXTERNAL_PUBKEY,HUSH_CHOSEN_ONE,HUSH_ON_DEMAND,HUSH_PASSPORT_INITDONE,ASSETCHAINS_STAKED,HUSH_NSPV; extern int32_t HUSH_MININGTHREADS,HUSH_LONGESTCHAIN,ASSETCHAINS_SEED,IS_HUSH_NOTARY,USE_EXTERNAL_PUBKEY,HUSH_CHOSEN_ONE,HUSH_ON_DEMAND,HUSH_PASSPORT_INITDONE,ASSETCHAINS_STAKED,HUSH_NSPV;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET; extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET;
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2]; extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2];

View File

@@ -93,7 +93,6 @@ uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff};
uint32_t ASSETCHAINS_NONCESHIFT[] = {32}; uint32_t ASSETCHAINS_NONCESHIFT[] = {32};
uint32_t ASSETCHAINS_HASHESPERROUND[] = {1}; uint32_t ASSETCHAINS_HASHESPERROUND[] = {1};
uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH; uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH;
int32_t ASSETCHAINS_RANDOMX_VALIDATION = -1; // activation height for RandomX validation (-1 = disabled)
// min diff returned from GetNextWorkRequired needs to be added here for each algo, so they can work with ac_staked. // min diff returned from GetNextWorkRequired needs to be added here for each algo, so they can work with ac_staked.
uint32_t ASSETCHAINS_MINDIFF[] = {537857807}; uint32_t ASSETCHAINS_MINDIFF[] = {537857807};
int32_t ASSETCHAINS_LWMAPOS = 0; // percentage of blocks should be PoS int32_t ASSETCHAINS_LWMAPOS = 0; // percentage of blocks should be PoS
@@ -102,7 +101,7 @@ int32_t ASSETCHAINS_OVERWINTER = -1;
int32_t ASSETCHAINS_STAKED; int32_t ASSETCHAINS_STAKED;
uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD;
uint32_t HUSH_INITDONE; uint32_t HUSH_INITDONE;
char HUSHUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t DRAGONX_PORT = 21769,BITCOIND_RPCPORT = 21769; char HUSHUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t HUSH3_PORT = 18031,BITCOIND_RPCPORT = 18031;
uint64_t PENDING_HUSH_TX; uint64_t PENDING_HUSH_TX;
extern int32_t HUSH_LOADINGBLOCKS; extern int32_t HUSH_LOADINGBLOCKS;
unsigned int MAX_BLOCK_SIGOPS = 20000; unsigned int MAX_BLOCK_SIGOPS = 20000;

View File

@@ -1413,20 +1413,20 @@ void hush_configfile(char *symbol,uint16_t rpcport)
#ifdef _WIN32 #ifdef _WIN32
while ( fname[strlen(fname)-1] != '\\' ) while ( fname[strlen(fname)-1] != '\\' )
fname[strlen(fname)-1] = 0; fname[strlen(fname)-1] = 0;
strcat(fname,"DRAGONX.conf"); strcat(fname,"HUSH3.conf");
#else #else
while ( fname[strlen(fname)-1] != '/' ) while ( fname[strlen(fname)-1] != '/' )
fname[strlen(fname)-1] = 0; fname[strlen(fname)-1] = 0;
#ifdef __APPLE__ #ifdef __APPLE__
strcat(fname,"DRAGONX.conf"); strcat(fname,"HUSH3.conf");
#else #else
strcat(fname,"DRAGONX.conf"); strcat(fname,"HUSH3.conf");
#endif #endif
#endif #endif
if ( (fp= fopen(fname,"rb")) != 0 ) if ( (fp= fopen(fname,"rb")) != 0 )
{ {
if ( (hushport= _hush_userpass(username,password,fp)) != 0 ) if ( (hushport= _hush_userpass(username,password,fp)) != 0 )
DRAGONX_PORT = hushport; HUSH3_PORT = hushport;
sprintf(HUSHUSERPASS,"%s:%s",username,password); sprintf(HUSHUSERPASS,"%s:%s",username,password);
fclose(fp); fclose(fp);
//printf("HUSH.(%s) -> userpass.(%s)\n",fname,HUSHUSERPASS); //printf("HUSH.(%s) -> userpass.(%s)\n",fname,HUSHUSERPASS);
@@ -1790,28 +1790,38 @@ void hush_args(char *argv0)
} }
name = GetArg("-ac_name","DRAGONX"); name = GetArg("-ac_name","HUSH3");
fprintf(stderr,".oO Starting %s Full Node (Extreme Privacy!) with genproc=%d notary=%d\n",name.c_str(),HUSH_MININGTHREADS, IS_HUSH_NOTARY); fprintf(stderr,".oO Starting %s Full Node (Extreme Privacy!) with genproc=%d notary=%d\n",name.c_str(),HUSH_MININGTHREADS, IS_HUSH_NOTARY);
vector<string> DRAGONX_nodes = {}; vector<string> HUSH_nodes = {};
// Only DRAGONX connects to these by default, other chains must opt-in via -connect/-addnode // Only HUSH3 uses these by default, other HACs must opt-in via -connect/-addnode
const bool isdragonx = strncmp(name.c_str(), "DRAGONX",7) == 0 ? true : false; const bool ishush3 = strncmp(name.c_str(), "HUSH3",5) == 0 ? true : false;
LogPrint("net", "%s: isdragonx=%d\n", __func__, isdragonx); LogPrint("net", "%s: ishush3=%d\n", __func__, ishush3);
if (isdragonx) { if (ishush3) {
DRAGONX_nodes = {"node1.dragonx.is","node2.dragonx.is","node3.dragonx.is", HUSH_nodes = {"node1.hush.is","node2.hush.is","node3.hush.is",
"node4.dragonx.is","node5.dragonx.is" "node4.hush.is","node5.hush.is","node6.hush.is",
"node7.hush.is","node8.hush.is",
"178.250.189.141",
"31.202.19.157",
"45.132.75.69",
"45.63.58.167",
"b2dln7mw7ydnuopls444tuixujhcw5kn5o22cna6gqfmw2fl6drb5nad.onion",
"dslbaa5gut5kapqtd44pbg65tpl5ydsamfy62hjbldhfsvk64qs57pyd.onion",
"vsqdumnh5khjbrzlxoeucbkiuaictdzyc3ezjpxpp2ph3gfwo2ptjmyd.onion",
"plrobkepqjxs2cmig273mxnqh3qhuhdaioyb2n5kafn264ramb7tqxid.onion"
}; };
} }
vector<string> more_nodes = mapMultiArgs["-addnode"]; vector<string> more_nodes = mapMultiArgs["-addnode"];
if (more_nodes.size() > 0) { if (more_nodes.size() > 0) {
fprintf(stderr,"%s: Adding %lu more nodes via custom -addnode arguments\n", __func__, more_nodes.size() ); fprintf(stderr,"%s: Adding %lu more nodes via custom -addnode arguments\n", __func__, more_nodes.size() );
} }
// Add default DRAGONX nodes after custom addnodes, if applicable // Add default HUSH nodes after custom addnodes, if applicable
if(DRAGONX_nodes.size() > 0) { if(HUSH_nodes.size() > 0) {
LogPrint("net", "%s: adding %d DRAGONX hostname-based nodes\n", __func__, DRAGONX_nodes.size() ); LogPrint("net", "%s: adding %d HUSH3 hostname-based nodes\n", __func__, HUSH_nodes.size() );
more_nodes.insert( more_nodes.end(), DRAGONX_nodes.begin(), DRAGONX_nodes.end() ); more_nodes.insert( more_nodes.end(), HUSH_nodes.begin(), HUSH_nodes.end() );
} }
mapMultiArgs["-addnode"] = more_nodes; mapMultiArgs["-addnode"] = more_nodes;
@@ -1820,15 +1830,10 @@ void hush_args(char *argv0)
WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10;
ASSETCHAINS_CC = GetArg("-ac_cc",0); ASSETCHAINS_CC = GetArg("-ac_cc",0);
HUSH_CCACTIVATE = GetArg("-ac_ccactivate",0); HUSH_CCACTIVATE = GetArg("-ac_ccactivate",0);
ASSETCHAINS_BLOCKTIME = GetArg("-ac_blocktime",60);
// Set defaults based on chain // We do not support ac_public=1 chains, Hush is a platform for privacy
int default_blocktime = isdragonx ? 36 : 60;
int default_private = isdragonx ? 1 : 0;
ASSETCHAINS_BLOCKTIME = GetArg("-ac_blocktime", default_blocktime);
// We do not support ac_public=1 chains, DragonX is a platform for privacy
ASSETCHAINS_PUBLIC = 0; ASSETCHAINS_PUBLIC = 0;
ASSETCHAINS_PRIVATE = GetArg("-ac_private", default_private); ASSETCHAINS_PRIVATE = GetArg("-ac_private",0);
HUSH_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0); HUSH_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0);
Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0);
@@ -1866,9 +1871,7 @@ void hush_args(char *argv0)
ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0); ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0);
if ( name.c_str()[0] != 0 ) if ( name.c_str()[0] != 0 )
{ {
// Default algo is randomx for DRAGONX, equihash for others std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0]));
std::string default_algo = isdragonx ? "randomx" : std::string(ASSETCHAINS_ALGORITHMS[0]);
std::string selectedAlgo = GetArg("-ac_algo", default_algo);
for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ )
{ {
@@ -1897,20 +1900,12 @@ void hush_args(char *argv0)
// Set our symbol from -ac_name value // Set our symbol from -ac_name value
strncpy(SMART_CHAIN_SYMBOL,name.c_str(),sizeof(SMART_CHAIN_SYMBOL)-1); strncpy(SMART_CHAIN_SYMBOL,name.c_str(),sizeof(SMART_CHAIN_SYMBOL)-1);
const bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
// Set RandomX validation activation height per chain
if (ASSETCHAINS_ALGO == ASSETCHAINS_RANDOMX) {
if (strncmp(SMART_CHAIN_SYMBOL, "DRAGONX", 7) == 0) {
ASSETCHAINS_RANDOMX_VALIDATION = 2838976; // TBD: set to coordinated upgrade height
} else if (strncmp(SMART_CHAIN_SYMBOL, "TUMIN", 5) == 0) {
ASSETCHAINS_RANDOMX_VALIDATION = 1200; // TBD: set to coordinated upgrade height
} else {
ASSETCHAINS_RANDOMX_VALIDATION = 1; // all other RandomX HACs: enforce from height 1
}
printf("ASSETCHAINS_RANDOMX_VALIDATION set to %d for %s\n", ASSETCHAINS_RANDOMX_VALIDATION, SMART_CHAIN_SYMBOL);
}
ASSETCHAINS_LASTERA = GetArg("-ac_eras", 1); ASSETCHAINS_LASTERA = GetArg("-ac_eras", 1);
if(ishush3) {
ASSETCHAINS_LASTERA = 3;
}
if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS ) if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS )
{ {
ASSETCHAINS_LASTERA = 1; ASSETCHAINS_LASTERA = 1;
@@ -1944,13 +1939,33 @@ void hush_args(char *argv0)
ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script","");
fprintf(stderr,"%s: Setting custom %s reward isdragonx=%d reward,halving,subsidy chain values...\n",__func__, SMART_CHAIN_SYMBOL, isdragonx); fprintf(stderr,"%s: Setting custom %s reward HUSH3=%d reward,halving,subsidy chain values...\n",__func__, SMART_CHAIN_SYMBOL, ishush3);
if(isdragonx) { if(ishush3) {
// DragonX chain parameters (previously set via wrapper script) // Migrated from hushd script
// -ac_name=DRAGONX -ac_algo=randomx -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=36 -ac_private=1 ASSETCHAINS_CC = 2;
ASSETCHAINS_BLOCKTIME = 150; // this will change to 75 at the correct block
ASSETCHAINS_COMMISSION = 11111111;
// 6250000 - (Sprout pool at block 500,000)
ASSETCHAINS_SUPPLY = 6178674;
ASSETCHAINS_FOUNDERS = 1;
ASSETCHAINS_SAPLING = 1; ASSETCHAINS_SAPLING = 1;
ASSETCHAINS_REWARD[0] = 300000000; // 3 DRAGONX per block // this corresponds to FR address RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn
ASSETCHAINS_HALVING[0] = 3500000; // halving every 3.5M blocks ASSETCHAINS_SCRIPTPUB = "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac";
// we do not want to change the magic of HUSH3 mainnet so we do not call devtax_scriptpub_for_height() here,
// instead we call it whenever ASSETCHAINS_SCRIPTPUB is used later on
// Over-ride HUSH3 values from CLI params. Changing our blocktime to 75s changes things
ASSETCHAINS_REWARD[0] = 0;
ASSETCHAINS_REWARD[1] = 1125000000;
ASSETCHAINS_REWARD[2] = 281250000; // 2.8125 HUSH goes to miners per block after 1st halving at Block 340K
ASSETCHAINS_REWARD[3] = 140625000; // 1.40625 HUSH after 2nd halving at Block 2020000
ASSETCHAINS_HALVING[0] = 129;
ASSETCHAINS_HALVING[1] = GetArg("-z2zheight",340000);
ASSETCHAINS_HALVING[2] = 2020000; // 2020000 = 340000 + 1680000 (1st halving block plus new halving interval)
ASSETCHAINS_HALVING[3] = 3700000; // ASSETCHAINS_HALVING[2] + 1680000;
ASSETCHAINS_ENDSUBSIDY[0] = 129;
ASSETCHAINS_ENDSUBSIDY[1] = GetArg("-z2zheight",340000);
ASSETCHAINS_ENDSUBSIDY[2] = 2*5422111; // TODO: Fix this, twice the previous end of rewards is an estimate
} }
Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0);
Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0);
@@ -2465,11 +2480,11 @@ void hush_args(char *argv0)
void hush_nameset(char *symbol,char *dest,char *source) void hush_nameset(char *symbol,char *dest,char *source)
{ {
if ( source[0] == 0 ) { if ( source[0] == 0 ) {
strcpy(symbol,(char *)"DRAGONX"); strcpy(symbol,(char *)"HUSH3");
strcpy(dest,(char *)"BTC"); strcpy(dest,(char *)"BTC");
} else { } else {
strcpy(symbol,source); strcpy(symbol,source);
strcpy(dest,(char *)"DRAGONX"); strcpy(dest,(char *)"HUSH3");
} }
} }

View File

@@ -377,8 +377,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288)); strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288));
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3)); strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
strUsage += HelpMessageOpt("-clientname=<SomeName>", _("Full node client name, default 'DragonX'")); strUsage += HelpMessageOpt("-clientname=<SomeName>", _("Full node client name, default 'GoldenSandtrout'"));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "DRAGONX.conf")); strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "HUSH3.conf"));
if (mode == HMM_BITCOIND) if (mode == HMM_BITCOIND)
{ {
#if !defined(WIN32) #if !defined(WIN32)
@@ -605,7 +605,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-stratumallowip=<ip>", _("Allow Stratum work requests from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); strUsage += HelpMessageOpt("-stratumallowip=<ip>", _("Allow Stratum work requests from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"));
// "ac" stands for "affects consensus" or Arrakis Chain // "ac" stands for "affects consensus" or Arrakis Chain
strUsage += HelpMessageGroup(_("DragonX Chain options:")); strUsage += HelpMessageGroup(_("Hush Arrakis Chain options:"));
strUsage += HelpMessageOpt("-ac_algo", _("Choose PoW mining algorithm, either 'equihash' or 'randomx'. default is Equihash (200,9)")); strUsage += HelpMessageOpt("-ac_algo", _("Choose PoW mining algorithm, either 'equihash' or 'randomx'. default is Equihash (200,9)"));
strUsage += HelpMessageOpt("-ac_blocktime", _("Block time in seconds, default is 60")); strUsage += HelpMessageOpt("-ac_blocktime", _("Block time in seconds, default is 60"));
strUsage += HelpMessageOpt("-ac_beam", _("BEAM integration")); strUsage += HelpMessageOpt("-ac_beam", _("BEAM integration"));
@@ -1619,7 +1619,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt)); return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt));
uacomments.push_back(SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)); uacomments.push_back(SanitizeString(cmt, SAFE_CHARS_UA_COMMENT));
} }
strSubVersion = FormatSubVersion(GetArg("-clientname","DragonX"), CLIENT_VERSION, uacomments); strSubVersion = FormatSubVersion(GetArg("-clientname","GoldenSandtrout"), CLIENT_VERSION, uacomments);
if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.", return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.",
strSubVersion.size(), MAX_SUBVERSION_LENGTH)); strSubVersion.size(), MAX_SUBVERSION_LENGTH));

View File

@@ -4993,8 +4993,6 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
{ {
if ( !CheckEquihashSolution(&blockhdr, Params()) ) if ( !CheckEquihashSolution(&blockhdr, Params()) )
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution");
if ( !CheckRandomXSolution(&blockhdr, height) )
return state.DoS(100, error("CheckBlockHeader(): RandomX solution invalid"),REJECT_INVALID, "invalid-randomx-solution");
} }
// Check proof of work matches claimed amount // Check proof of work matches claimed amount
/*hush_index2pubkey33(pubkey33,pindex,height); /*hush_index2pubkey33(pubkey33,pindex,height);
@@ -5140,26 +5138,6 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
} }
} }
// Check Proof-of-Work difficulty for smart chains (HACs)
// Without this check, an attacker can submit blocks with arbitrary nBits
// (e.g., powLimit / diff=1) and they will be accepted, allowing the chain
// to be flooded with minimum-difficulty blocks.
// Only enforce above daaForkHeight to avoid consensus mismatch with early
// chain blocks that were mined by a different binary version.
if (!ishush3 && SMART_CHAIN_SYMBOL[0] != 0 && nHeight > daaForkHeight) {
unsigned int nNextWork = GetNextWorkRequired(pindexPrev, &block, consensusParams);
if (fDebug) {
LogPrintf("%s: HAC nbits height=%d expected=%lu actual=%lu\n",
__func__, nHeight, (unsigned long)nNextWork, (unsigned long)block.nBits);
}
if (block.nBits != nNextWork) {
return state.DoS(100,
error("%s: Incorrect diffbits for %s at height %d: expected %lu got %lu",
__func__, SMART_CHAIN_SYMBOL, nHeight, (unsigned long)nNextWork, (unsigned long)block.nBits),
REJECT_INVALID, "bad-diffbits");
}
}
// Check timestamp against prev // Check timestamp against prev
if (ASSETCHAINS_ADAPTIVEPOW <= 0 || nHeight < 30) { if (ASSETCHAINS_ADAPTIVEPOW <= 0 || nHeight < 30) {
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast() ) if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast() )

View File

@@ -289,7 +289,7 @@ int printMiningStatus(bool mining)
lines++; lines++;
} else { } else {
std::cout << _("You are currently not mining.") << std::endl; std::cout << _("You are currently not mining.") << std::endl;
std::cout << _("To enable mining, add 'gen=1' to your DRAGONX.conf and restart.") << std::endl; std::cout << _("To enable mining, add 'gen=1' to your HUSH3.conf and restart.") << std::endl;
lines += 2; lines += 2;
} }
std::cout << std::endl; std::cout << std::endl;

View File

@@ -23,7 +23,6 @@
#include "pow/tromp/equi_miner.h" #include "pow/tromp/equi_miner.h"
#endif #endif
#include <atomic>
#include "amount.h" #include "amount.h"
#include "chainparams.h" #include "chainparams.h"
#include "consensus/consensus.h" #include "consensus/consensus.h"
@@ -52,7 +51,6 @@
#include "transaction_builder.h" #include "transaction_builder.h"
#include "sodium.h" #include "sodium.h"
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#ifdef ENABLE_MINING #ifdef ENABLE_MINING
#include <functional> #include <functional>
@@ -1013,213 +1011,8 @@ enum RandomXSolverCancelCheck
Reason2 Reason2
}; };
int GetRandomXInterval(); int GetRandomXInterval() { return GetArg("-ac_randomx_interval",1024); }
int GetRandomXBlockLag(); int GetRandomXBlockLag() { return GetArg("-ac_randomx_lag", 64); }
#ifdef _WIN32
#include <windows.h>
static void LogProcessMemory(const char* label) {
// Use K32GetProcessMemoryInfo from kernel32.dll (available on Win7+)
// to avoid linking psapi.lib
typedef struct {
DWORD cb;
DWORD PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivateUsage;
} PMC_EX;
typedef BOOL (WINAPI *PFN)(HANDLE, PMC_EX*, DWORD);
static PFN pfn = (PFN)GetProcAddress(GetModuleHandleA("kernel32.dll"), "K32GetProcessMemoryInfo");
if (pfn) {
PMC_EX pmc = {};
pmc.cb = sizeof(pmc);
if (pfn(GetCurrentProcess(), &pmc, sizeof(pmc))) {
LogPrintf("MemDiag [%s]: WorkingSet=%.1fMB, PrivateUsage=%.1fMB, PagefileUsage=%.1fMB\n",
label,
pmc.WorkingSetSize / (1024.0 * 1024.0),
pmc.PrivateUsage / (1024.0 * 1024.0),
pmc.PagefileUsage / (1024.0 * 1024.0));
}
}
}
#else
static void LogProcessMemory(const char* label) {
// Linux: read /proc/self/status
FILE *f = fopen("/proc/self/status", "r");
if (f) {
char line[256];
while (fgets(line, sizeof(line), f)) {
if (strncmp(line, "VmRSS:", 6) == 0 || strncmp(line, "VmSize:", 7) == 0) {
// Remove newline
line[strlen(line)-1] = '\0';
LogPrintf("MemDiag [%s]: %s\n", label, line);
}
}
fclose(f);
}
}
#endif
// Shared RandomX dataset manager — all miner threads share a single ~2GB dataset
// instead of each allocating their own. The dataset is read-only after initialization
// and RandomX explicitly supports multiple VMs sharing one dataset.
struct RandomXDatasetManager {
randomx_flags flags;
randomx_cache *cache;
randomx_dataset *dataset;
unsigned long datasetItemCount;
std::string currentKey;
std::mutex mtx; // protects Init/Shutdown/CreateVM
boost::shared_mutex datasetMtx; // readers-writer lock: shared for hashing, exclusive for rebuild
bool initialized;
RandomXDatasetManager() : flags(randomx_get_flags()), cache(nullptr), dataset(nullptr),
datasetItemCount(0), initialized(false) {}
bool Init() {
std::lock_guard<std::mutex> lock(mtx);
if (initialized) return true;
flags |= RANDOMX_FLAG_FULL_MEM;
LogPrintf("RandomXDatasetManager: flags=0x%x (JIT=%d, HARD_AES=%d, FULL_MEM=%d, LARGE_PAGES=%d)\n",
(int)flags,
!!(flags & RANDOMX_FLAG_JIT), !!(flags & RANDOMX_FLAG_HARD_AES),
!!(flags & RANDOMX_FLAG_FULL_MEM), !!(flags & RANDOMX_FLAG_LARGE_PAGES));
LogProcessMemory("before cache alloc");
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_SECURE);
if (cache == nullptr) {
LogPrintf("RandomXDatasetManager: cache alloc failed with large pages, trying without...\n");
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_SECURE);
if (cache == nullptr) {
LogPrintf("RandomXDatasetManager: cache alloc failed with secure, trying basic...\n");
cache = randomx_alloc_cache(flags);
if (cache == nullptr) {
LogPrintf("RandomXDatasetManager: cannot allocate cache!\n");
return false;
}
}
}
LogProcessMemory("after cache alloc");
// Try to allocate dataset with large pages first for better performance
dataset = randomx_alloc_dataset(flags | RANDOMX_FLAG_LARGE_PAGES);
if (dataset == nullptr) {
LogPrintf("RandomXDatasetManager: dataset alloc failed with large pages, trying without...\n");
dataset = randomx_alloc_dataset(flags);
if (dataset == nullptr) {
LogPrintf("RandomXDatasetManager: cannot allocate dataset!\n");
randomx_release_cache(cache);
cache = nullptr;
return false;
}
}
datasetItemCount = randomx_dataset_item_count();
initialized = true;
LogProcessMemory("after dataset alloc");
// Log the actual memory addresses to help diagnose sharing issues
uint8_t *datasetMemory = (uint8_t*)randomx_get_dataset_memory(dataset);
size_t datasetSize = datasetItemCount * RANDOMX_DATASET_ITEM_SIZE;
LogPrintf("RandomXDatasetManager: allocated shared dataset:\n");
LogPrintf(" - Dataset struct at: %p\n", (void*)dataset);
LogPrintf(" - Dataset memory at: %p (size: %.2f GB)\n", (void*)datasetMemory, datasetSize / (1024.0 * 1024.0 * 1024.0));
LogPrintf(" - Items: %lu, Item size: %d bytes\n", datasetItemCount, RANDOMX_DATASET_ITEM_SIZE);
LogPrintf(" - Expected total process memory: ~%.2f GB + ~2MB per mining thread\n", datasetSize / (1024.0 * 1024.0 * 1024.0));
return true;
}
// Initialize cache with a key and rebuild the dataset.
// Thread-safe: acquires exclusive lock so all hashing threads must finish first.
void UpdateKey(const void *key, size_t keySize) {
std::string newKey((const char*)key, keySize);
// Fast check with shared lock — skip if key hasn't changed
{
boost::shared_lock<boost::shared_mutex> readLock(datasetMtx);
if (newKey == currentKey) return; // already up to date
}
// Acquire exclusive lock — blocks until all hashing threads release their shared locks
boost::unique_lock<boost::shared_mutex> writeLock(datasetMtx);
// Double-check after acquiring exclusive lock (another thread may have rebuilt first)
if (newKey == currentKey) return;
LogPrintf("RandomXDatasetManager: updating key (size=%lu)\n", keySize);
randomx_init_cache(cache, key, keySize);
currentKey = newKey;
// Rebuild dataset using all available CPU threads
const int initThreadCount = std::thread::hardware_concurrency();
if (initThreadCount > 1) {
std::vector<std::thread> threads;
uint32_t startItem = 0;
const auto perThread = datasetItemCount / initThreadCount;
const auto remainder = datasetItemCount % initThreadCount;
for (int i = 0; i < initThreadCount; ++i) {
const auto count = perThread + (i == initThreadCount - 1 ? remainder : 0);
threads.push_back(std::thread(&randomx_init_dataset, dataset, cache, startItem, count));
startItem += count;
}
for (unsigned i = 0; i < threads.size(); ++i) {
threads[i].join();
}
} else {
randomx_init_dataset(dataset, cache, 0, datasetItemCount);
}
LogPrintf("RandomXDatasetManager: dataset rebuilt\n");
LogProcessMemory("after dataset init");
}
// Creates a per-thread VM using the shared dataset.
// Caller must hold a shared lock on datasetMtx.
// The VM itself is small (~2MB scratchpad + ~84KB JIT code) — the ~2GB dataset is shared via pointer.
// VMs should be created ONCE per thread and reused across blocks to avoid
// heap fragmentation on Windows (repeated 2MB alloc/free causes address-space bloat).
randomx_vm *CreateVM() {
static std::atomic<int> vmCount{0};
LogProcessMemory("before CreateVM");
randomx_vm *vm = randomx_create_vm(flags, nullptr, dataset);
if (vm != nullptr) {
int id = ++vmCount;
uint8_t *datasetMemory = (uint8_t*)randomx_get_dataset_memory(dataset);
LogPrintf("RandomXDatasetManager: VM #%d created — VM at %p, shared dataset at %p\n",
id, (void*)vm, (void*)datasetMemory);
LogPrintf(" Per-thread overhead: ~2MB scratchpad + ~84KB JIT (dataset NOT copied)\n");
LogProcessMemory("after CreateVM");
}
return vm;
}
void Shutdown() {
std::lock_guard<std::mutex> lock(mtx);
if (dataset != nullptr) {
randomx_release_dataset(dataset);
dataset = nullptr;
}
if (cache != nullptr) {
randomx_release_cache(cache);
cache = nullptr;
}
initialized = false;
currentKey.clear();
LogPrintf("RandomXDatasetManager: shutdown complete\n");
}
~RandomXDatasetManager() {
Shutdown();
}
};
// Global shared dataset manager, created by GenerateBitcoins before spawning miner threads
static RandomXDatasetManager *g_rxDatasetManager = nullptr;
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
void static RandomXMiner(CWallet *pwallet) void static RandomXMiner(CWallet *pwallet)
@@ -1257,12 +1050,33 @@ void static RandomXMiner()
); );
miningTimer.start(); miningTimer.start();
// Use the shared dataset manager — no per-thread dataset allocation randomx_flags flags = randomx_get_flags();
if (g_rxDatasetManager == nullptr || !g_rxDatasetManager->initialized) { flags |= RANDOMX_FLAG_FULL_MEM;
LogPrintf("HushRandomXMiner: shared dataset manager not initialized, aborting!\n"); randomx_cache *randomxCache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_SECURE );
if (randomxCache == NULL) {
LogPrintf("RandomX cache is null, trying without large pages...\n");
randomxCache = randomx_alloc_cache(flags | RANDOMX_FLAG_SECURE);
if (randomxCache == NULL) {
LogPrintf("RandomX cache is null, trying without secure...\n");
}
randomxCache = randomx_alloc_cache(flags);
if (randomxCache == NULL) {
LogPrintf("RandomX cache is null, cannot mine!\n");
}
}
rxdebug("%s: created randomx flags + cache\n");
randomx_dataset *randomxDataset = randomx_alloc_dataset(flags);
rxdebug("%s: created dataset\n");
if( randomxDataset == nullptr) {
LogPrintf("%s: allocating randomx dataset failed!\n", __func__);
return; return;
} }
auto datasetItemCount = randomx_dataset_item_count();
rxdebug("%s: dataset items=%lu\n", datasetItemCount);
char randomxHash[RANDOMX_HASH_SIZE]; char randomxHash[RANDOMX_HASH_SIZE];
rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE);
char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific
@@ -1333,37 +1147,48 @@ void static RandomXMiner()
// fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag); // fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag);
rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height); rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height);
// Update the shared dataset key — only one thread will actually rebuild, // Use the initial key at the start of the chain, until the first key block
// others will see the key is already current and skip.
if( (Mining_height) < randomxInterval + randomxBlockLag) { if( (Mining_height) < randomxInterval + randomxBlockLag) {
g_rxDatasetManager->UpdateKey(randomxKey, strlen(randomxKey)); randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey);
rxdebug("%s: updated shared dataset with initial key\n"); rxdebug("%s: initialized cache with initial key\n");
} else { } else {
rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval); rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval);
// At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing
const int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval; const int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval;
uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash(); uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash();
g_rxDatasetManager->UpdateKey(&randomxBlockKey, sizeof randomxBlockKey);
rxdebug("%s: updated shared dataset with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str()); randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey);
rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str());
} }
// Create a per-thread VM once and reuse across blocks. const int initThreadCount = std::thread::hardware_concurrency();
// The VM just stores a pointer to the shared dataset — the pointer if(initThreadCount > 1) {
// remains valid across key changes since UpdateKey rebuilds the dataset rxdebug("%s: initializing dataset with %d threads\n", initThreadCount);
// contents in-place without reallocating. Reusing the VM avoids std::vector<std::thread> threads;
// repeated 2MB scratchpad + 84KB JIT alloc/free churn that causes uint32_t startItem = 0;
// Windows heap fragmentation and apparent memory growth per thread. const auto perThread = datasetItemCount / initThreadCount;
if (myVM == nullptr) { const auto remainder = datasetItemCount % initThreadCount;
// First iteration: acquire shared lock briefly to create VM for (int i = 0; i < initThreadCount; ++i) {
boost::shared_lock<boost::shared_mutex> initLock(g_rxDatasetManager->datasetMtx); const auto count = perThread + (i == initThreadCount - 1 ? remainder : 0);
myVM = g_rxDatasetManager->CreateVM(); threads.push_back(std::thread(&randomx_init_dataset, randomxDataset, randomxCache, startItem, count));
if (myVM == nullptr) { startItem += count;
}
for (unsigned i = 0; i < threads.size(); ++i) {
threads[i].join();
}
threads.clear();
} else {
rxdebug("%s: initializing dataset with 1 thread\n");
randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount);
}
rxdebug("%s: dataset initialized\n");
myVM = randomx_create_vm(flags, nullptr, randomxDataset);
if(myVM == NULL) {
LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n");
return; return;
} }
}
// Acquire shared lock to prevent dataset rebuild while we're hashing
boost::shared_lock<boost::shared_mutex> datasetLock(g_rxDatasetManager->datasetMtx);
//fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start); //fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0); CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0);
@@ -1443,17 +1268,16 @@ void static RandomXMiner()
arith_uint256 hashTarget; arith_uint256 hashTarget;
hashTarget = HASHTarget; hashTarget = HASHTarget;
CRandomXInput rxInput(pblocktemplate->block);
CDataStream randomxInput(SER_NETWORK, PROTOCOL_VERSION); CDataStream randomxInput(SER_NETWORK, PROTOCOL_VERSION);
// Serialize block header without nSolution but with nNonce for deterministic RandomX input // Use the current block as randomx input
randomxInput << rxInput; randomxInput << pblocktemplate->block;
// std::cerr << "RandomXMiner: randomxInput=" << HexStr(randomxInput) << "\n"; // std::cerr << "RandomXMiner: randomxInput=" << HexStr(randomxInput) << "\n";
// fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput); // fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput);
rxdebug("%s: randomxKey=%s randomxInput=%s\n", randomxKey, HexStr(randomxInput).c_str()); rxdebug("%s: randomxKey=%s randomxInput=%s\n", randomxKey, HexStr(randomxInput).c_str());
rxdebug("%s: calculating randomx hash\n"); rxdebug("%s: calculating randomx hash\n");
randomx_calculate_hash(myVM, &randomxInput[0], randomxInput.size(), randomxHash); randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash);
rxdebug("%s: calculated randomx hash\n"); rxdebug("%s: calculated randomx hash\n");
rxdebug("%s: randomxHash="); rxdebug("%s: randomxHash=");
@@ -1500,28 +1324,14 @@ void static RandomXMiner()
CValidationState state; CValidationState state;
//{ LOCK(cs_main); //{ LOCK(cs_main);
// Skip RandomX re-validation during TestBlockValidity — we already if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false))
// computed the correct hash, and re-verifying allocates ~256MB which
// can trigger the OOM killer on memory-constrained systems.
SetSkipRandomXValidation(true);
bool fValid = TestBlockValidity(state,B, chainActive.LastTip(), true, false);
SetSkipRandomXValidation(false);
if ( !fValid )
{ {
h = UintToArith256(B.GetHash()); h = UintToArith256(B.GetHash());
fprintf(stderr,"RandomXMiner: TestBlockValidity FAILED at ht.%d nNonce=%s hash=", fprintf(stderr,"RandomXMiner: Invalid randomx block mined, try again ");
Mining_height, pblock->nNonce.ToString().c_str());
for (z=31; z>=0; z--) for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&h)[z]); fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
fprintf(stderr," nSolution.size=%lu\n", B.nSolution.size());
// Dump nSolution hex for comparison with validator
fprintf(stderr,"RandomXMiner: nSolution=");
for (unsigned i = 0; i < B.nSolution.size(); i++)
fprintf(stderr,"%02x", B.nSolution[i]);
fprintf(stderr,"\n");
LogPrintf("RandomXMiner: TestBlockValidity FAILED at ht.%d, gotinvalid=1, state=%s\n",
Mining_height, state.GetRejectReason());
gotinvalid = 1; gotinvalid = 1;
fprintf(stderr,"\n");
return(false); return(false);
} }
//} //}
@@ -1589,24 +1399,21 @@ void static RandomXMiner()
pblock->nBits = savebits; pblock->nBits = savebits;
} }
// Release shared lock so UpdateKey can acquire exclusive lock for dataset rebuild rxdebug("%s: going to destroy rx VM\n");
// VM is kept alive — its dataset pointer remains valid across rebuilds randomx_destroy_vm(myVM);
datasetLock.unlock(); rxdebug("%s: destroyed VM\n");
} }
} catch (const boost::thread_interrupted&) { } catch (const boost::thread_interrupted&) {
miningTimer.stop(); miningTimer.stop();
c.disconnect(); c.disconnect();
if (myVM != nullptr) {
randomx_destroy_vm(myVM); randomx_destroy_vm(myVM);
myVM = nullptr;
LogPrintf("%s: destroyed vm via thread interrupt\n", __func__); LogPrintf("%s: destroyed vm via thread interrupt\n", __func__);
} else { randomx_release_dataset(randomxDataset);
LogPrintf("%s: WARNING myVM already null in thread interrupt handler, skipping destroy (would double-free)\n", __func__); rxdebug("%s: released dataset via thread interrupt\n");
fprintf(stderr, "%s: WARNING myVM already null in thread interrupt, would have double-freed!\n", __func__); randomx_release_cache(randomxCache);
} rxdebug("%s: released cache via thread interrupt\n");
// Dataset and cache are owned by g_rxDatasetManager — do NOT release here
LogPrintf("HushRandomXMiner terminated\n"); LogPrintf("HushRandomXMiner terminated\n");
throw; throw;
@@ -1615,21 +1422,20 @@ void static RandomXMiner()
c.disconnect(); c.disconnect();
fprintf(stderr,"RandomXMiner: runtime error: %s\n", e.what()); fprintf(stderr,"RandomXMiner: runtime error: %s\n", e.what());
if (myVM != nullptr) {
randomx_destroy_vm(myVM); randomx_destroy_vm(myVM);
myVM = nullptr;
LogPrintf("%s: destroyed vm because of error\n", __func__); LogPrintf("%s: destroyed vm because of error\n", __func__);
} randomx_release_dataset(randomxDataset);
// Dataset and cache are owned by g_rxDatasetManager — do NOT release here rxdebug("%s: released dataset because of error\n");
randomx_release_cache(randomxCache);
rxdebug("%s: released cache because of error\n");
return; return;
} }
// Only destroy per-thread VM, dataset/cache are shared randomx_release_dataset(randomxDataset);
if (myVM != nullptr) { rxdebug("%s: released dataset in normal exit\n");
randomx_destroy_vm(myVM); randomx_release_cache(randomxCache);
myVM = nullptr; rxdebug("%s: released cache in normal exit\n");
}
miningTimer.stop(); miningTimer.stop();
c.disconnect(); c.disconnect();
} }
@@ -2073,18 +1879,8 @@ void static BitcoinMiner()
if (minerThreads != NULL) if (minerThreads != NULL)
{ {
minerThreads->interrupt_all(); minerThreads->interrupt_all();
// Wait for all miner threads to fully terminate before destroying shared resources
minerThreads->join_all();
delete minerThreads; delete minerThreads;
minerThreads = NULL; minerThreads = NULL;
// Shutdown shared RandomX dataset manager after all threads are done
if (g_rxDatasetManager != nullptr) {
g_rxDatasetManager->Shutdown();
delete g_rxDatasetManager;
g_rxDatasetManager = nullptr;
LogPrintf("%s: destroyed shared RandomX dataset manager\n", __func__);
}
} }
if(fDebug) if(fDebug)
@@ -2099,21 +1895,6 @@ void static BitcoinMiner()
minerThreads = new boost::thread_group(); minerThreads = new boost::thread_group();
// Initialize shared RandomX dataset manager before spawning miner threads
if (ASSETCHAINS_ALGO == ASSETCHAINS_RANDOMX) {
g_rxDatasetManager = new RandomXDatasetManager();
if (!g_rxDatasetManager->Init()) {
LogPrintf("%s: FATAL - Failed to initialize shared RandomX dataset manager\n", __func__);
fprintf(stderr, "%s: FATAL - Failed to initialize shared RandomX dataset manager\n", __func__);
delete g_rxDatasetManager;
g_rxDatasetManager = nullptr;
delete minerThreads;
minerThreads = NULL;
return;
}
LogPrintf("%s: shared RandomX dataset manager initialized\n", __func__);
}
for (int i = 0; i < nThreads; i++) { for (int i = 0; i < nThreads; i++) {
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH ) { if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH ) {

View File

@@ -28,7 +28,6 @@
#include <tuple> #include <tuple>
constexpr uint64_t CNetAddr::V1_SERIALIZATION_SIZE; constexpr uint64_t CNetAddr::V1_SERIALIZATION_SIZE;
constexpr uint64_t CNetAddr::MAX_ADDRV2_SIZE;
/** check whether a given address is in a network we can probably connect to */ /** check whether a given address is in a network we can probably connect to */
bool CNetAddr::IsReachableNetwork() { bool CNetAddr::IsReachableNetwork() {

View File

@@ -28,8 +28,6 @@
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"
#include "sodium.h" #include "sodium.h"
#include "RandomX/src/randomx.h"
#include <mutex>
#ifdef ENABLE_RUST #ifdef ENABLE_RUST
#include "librustzcash.h" #include "librustzcash.h"
@@ -339,7 +337,6 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
memset(zflags,0,sizeof(zflags)); memset(zflags,0,sizeof(zflags));
if ( pindexLast != 0 ) if ( pindexLast != 0 )
height = (int32_t)pindexLast->GetHeight() + 1; height = (int32_t)pindexLast->GetHeight() + 1;
if ( ASSETCHAINS_ADAPTIVEPOW > 0 && pindexFirst != 0 && pblock != 0 && height >= (int32_t)(sizeof(ct)/sizeof(*ct)) ) if ( ASSETCHAINS_ADAPTIVEPOW > 0 && pindexFirst != 0 && pblock != 0 && height >= (int32_t)(sizeof(ct)/sizeof(*ct)) )
{ {
tipdiff = (pblock->nTime - pindexFirst->nTime); tipdiff = (pblock->nTime - pindexFirst->nTime);
@@ -686,140 +683,6 @@ bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& param
return true; return true;
} }
int GetRandomXInterval() { return GetArg("-ac_randomx_interval", 1024); }
int GetRandomXBlockLag() { return GetArg("-ac_randomx_lag", 64); }
// Cached RandomX validation state — reused across calls, protected by mutex
static std::mutex cs_randomx_validator;
static randomx_cache *s_rxCache = nullptr;
static randomx_vm *s_rxVM = nullptr;
static std::string s_rxCurrentKey; // tracks current key to avoid re-init
// Thread-local flag: skip CheckRandomXSolution when the miner is validating its own block
// The miner already computed the correct RandomX hash — re-verifying with a separate
// cache+VM would allocate ~256MB extra memory and can trigger the OOM killer.
thread_local bool fSkipRandomXValidation = false;
void SetSkipRandomXValidation(bool skip) { fSkipRandomXValidation = skip; }
CBlockIndex *hush_chainactive(int32_t height);
bool CheckRandomXSolution(const CBlockHeader *pblock, int32_t height)
{
// Only applies to RandomX chains
if (ASSETCHAINS_ALGO != ASSETCHAINS_RANDOMX)
return true;
// Disabled if activation height is negative
if (ASSETCHAINS_RANDOMX_VALIDATION < 0)
return true;
// Not yet at activation height
if (height < ASSETCHAINS_RANDOMX_VALIDATION)
return true;
// Do not affect initial block loading
extern int32_t HUSH_LOADINGBLOCKS;
if (HUSH_LOADINGBLOCKS != 0)
return true;
// Skip when miner is validating its own block via TestBlockValidity
if (fSkipRandomXValidation)
return true;
// nSolution must be exactly RANDOMX_HASH_SIZE (32) bytes
if (pblock->nSolution.size() != RANDOMX_HASH_SIZE) {
return error("CheckRandomXSolution(): nSolution size %u != expected %d at height %d",
pblock->nSolution.size(), RANDOMX_HASH_SIZE, height);
}
static int randomxInterval = GetRandomXInterval();
static int randomxBlockLag = GetRandomXBlockLag();
// Determine the correct RandomX key for this height
char initialKey[82];
snprintf(initialKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT);
std::string rxKey;
if (height < randomxInterval + randomxBlockLag) {
// Use initial key derived from chain params
rxKey = std::string(initialKey, strlen(initialKey));
} else {
// Use block hash at the key height
int keyHeight = ((height - randomxBlockLag) / randomxInterval) * randomxInterval;
CBlockIndex *pKeyIndex = hush_chainactive(keyHeight);
if (pKeyIndex == nullptr) {
return error("CheckRandomXSolution(): cannot get block index at key height %d for block %d", keyHeight, height);
}
uint256 blockKey = pKeyIndex->GetBlockHash();
rxKey = std::string((const char*)&blockKey, sizeof(blockKey));
}
// Serialize the block header without nSolution (but with nNonce) as RandomX input
CRandomXInput rxInput(*pblock);
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << rxInput;
char computedHash[RANDOMX_HASH_SIZE];
{
std::lock_guard<std::mutex> lock(cs_randomx_validator);
// Initialize cache + VM if needed, or re-init if key changed
if (s_rxCache == nullptr) {
randomx_flags flags = randomx_get_flags();
s_rxCache = randomx_alloc_cache(flags);
if (s_rxCache == nullptr) {
return error("CheckRandomXSolution(): failed to allocate RandomX cache");
}
randomx_init_cache(s_rxCache, rxKey.data(), rxKey.size());
s_rxCurrentKey = rxKey;
s_rxVM = randomx_create_vm(flags, s_rxCache, nullptr);
if (s_rxVM == nullptr) {
randomx_release_cache(s_rxCache);
s_rxCache = nullptr;
return error("CheckRandomXSolution(): failed to create RandomX VM");
}
} else if (s_rxCurrentKey != rxKey) {
randomx_init_cache(s_rxCache, rxKey.data(), rxKey.size());
s_rxCurrentKey = rxKey;
randomx_vm_set_cache(s_rxVM, s_rxCache);
}
randomx_calculate_hash(s_rxVM, &ss[0], ss.size(), computedHash);
}
// Compare computed hash against nSolution
if (memcmp(computedHash, pblock->nSolution.data(), RANDOMX_HASH_SIZE) != 0) {
// Debug: dump both hashes for diagnosis
std::string computedHex, solutionHex;
for (int i = 0; i < RANDOMX_HASH_SIZE; i++) {
char buf[4];
snprintf(buf, sizeof(buf), "%02x", (uint8_t)computedHash[i]);
computedHex += buf;
snprintf(buf, sizeof(buf), "%02x", pblock->nSolution[i]);
solutionHex += buf;
}
fprintf(stderr, "CheckRandomXSolution(): HASH MISMATCH at height %d\n", height);
fprintf(stderr, " computed : %s\n", computedHex.c_str());
fprintf(stderr, " nSolution: %s\n", solutionHex.c_str());
fprintf(stderr, " rxKey size=%lu, input size=%lu, nNonce=%s\n",
rxKey.size(), ss.size(), pblock->nNonce.ToString().c_str());
fprintf(stderr, " nSolution.size()=%lu, RANDOMX_HASH_SIZE=%d\n",
pblock->nSolution.size(), RANDOMX_HASH_SIZE);
// Also log to debug.log
LogPrintf("CheckRandomXSolution(): HASH MISMATCH at height %d\n", height);
LogPrintf(" computed : %s\n", computedHex);
LogPrintf(" nSolution: %s\n", solutionHex);
LogPrintf(" rxKey size=%lu, input size=%lu, nNonce=%s\n",
rxKey.size(), ss.size(), pblock->nNonce.ToString());
return false;
}
LogPrint("randomx", "CheckRandomXSolution(): valid at height %d\n", height);
return true;
}
int32_t hush_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); int32_t hush_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
int32_t hush_currentheight(); int32_t hush_currentheight();
void hush_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); void hush_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height);
@@ -863,19 +726,9 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t
// Check proof of work matches claimed amount // Check proof of work matches claimed amount
if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget ) if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget )
{ {
// During initial block loading/sync, skip PoW validation for blocks if ( HUSH_LOADINGBLOCKS != 0 )
// before RandomX validation height. After activation, always validate
// to prevent injection of blocks with fake PoW.
if ( HUSH_LOADINGBLOCKS != 0 ) {
if (ASSETCHAINS_ALGO == ASSETCHAINS_RANDOMX && ASSETCHAINS_RANDOMX_VALIDATION > 0 && height >= ASSETCHAINS_RANDOMX_VALIDATION) {
// Fall through to reject the block — do NOT skip validation after activation
} else {
return true; return true;
}
}
if ( SMART_CHAIN_SYMBOL[0] != 0 || height > 792000 )
{
if ( Params().NetworkIDString() != "regtest" ) if ( Params().NetworkIDString() != "regtest" )
{ {
for (i=31; i>=0; i--) for (i=31; i>=0; i--)
@@ -893,7 +746,6 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t
} }
return false; return false;
} }
}
/*for (i=31; i>=0; i--) /*for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," hash vs "); fprintf(stderr," hash vs ");

View File

@@ -38,18 +38,6 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
/** Check whether the Equihash solution in a block header is valid */ /** Check whether the Equihash solution in a block header is valid */
bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams&); bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams&);
/** Check whether a block header contains a valid RandomX solution */
bool CheckRandomXSolution(const CBlockHeader *pblock, int32_t height);
/** Set thread-local flag to skip RandomX validation (used by miner during TestBlockValidity) */
void SetSkipRandomXValidation(bool skip);
/** Return the RandomX key rotation interval in blocks */
int GetRandomXInterval();
/** Return the RandomX key change lag in blocks */
int GetRandomXBlockLag();
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t height, const Consensus::Params& params); bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t height, const Consensus::Params& params);
CChainPower GetBlockProof(const CBlockIndex& block); CChainPower GetBlockProof(const CBlockIndex& block);

View File

@@ -237,33 +237,6 @@ public:
} }
}; };
/**
* Custom serializer for CBlockHeader that includes nNonce but omits nSolution,
* for use as deterministic input to RandomX hashing.
*/
class CRandomXInput : private CBlockHeader
{
public:
CRandomXInput(const CBlockHeader &header)
{
CBlockHeader::SetNull();
*((CBlockHeader*)this) = header;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(hashFinalSaplingRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
}
};
/** Describes a place in the block chain to another node such that if the /** Describes a place in the block chain to another node such that if the
* other node doesn't have the same branch, it can find a recent common trunk. * other node doesn't have the same branch, it can find a recent common trunk.

View File

@@ -169,7 +169,7 @@ UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk)
throw runtime_error( throw runtime_error(
"getgenerate\n" "getgenerate\n"
"\nReturn if the server is set to mine coins or not. The default is false.\n" "\nReturn if the server is set to mine coins or not. The default is false.\n"
"It is set with the command line argument -gen (or DRAGONX.conf setting gen).\n" "It is set with the command line argument -gen (or HUSH3.conf setting gen).\n"
"It can also be set with the setgenerate call.\n" "It can also be set with the setgenerate call.\n"
"\nResult\n" "\nResult\n"
"{\n" "{\n"

View File

@@ -133,7 +133,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
" \"pingtime\": n, (numeric) ping time\n" " \"pingtime\": n, (numeric) ping time\n"
" \"pingwait\": n, (numeric) ping wait\n" " \"pingwait\": n, (numeric) ping wait\n"
" \"version\": v, (numeric) The peer version, such as 170002\n" " \"version\": v, (numeric) The peer version, such as 170002\n"
" \"subver\": \"/DragonX:x.y.z[-v]/\", (string) The string version\n" " \"subver\": \"/GoldenSandtrout:x.y.z[-v]/\", (string) The string version\n"
" \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n" " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
" \"startingheight\": n, (numeric) The starting height (block) of the peer\n" " \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
" \"banscore\": n, (numeric) The ban score\n" " \"banscore\": n, (numeric) The ban score\n"
@@ -505,7 +505,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
"\nResult:\n" "\nResult:\n"
"{\n" "{\n"
" \"version\": xxxxx, (numeric) the server version\n" " \"version\": xxxxx, (numeric) the server version\n"
" \"subversion\": \"/DragonX:x.y.z[-v]/\", (string) the server subversion string\n" " \"subversion\": \"/GoldenSandtrout:x.y.z[-v]/\", (string) the server subversion string\n"
" \"protocolversion\": xxxxx, (numeric) the protocol version\n" " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
" \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
" \"timeoffset\": xxxxx, (numeric) the time offset (deprecated, always 0)\n" " \"timeoffset\": xxxxx, (numeric) the time offset (deprecated, always 0)\n"

View File

@@ -14,7 +14,7 @@
"ac_perc": "11111111", "ac_perc": "11111111",
"ac_eras": "3", "ac_eras": "3",
"ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac", "ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac",
"clientname": "DragonX", "clientname": "GoldenSandtrout",
"addnode": [ "addnode": [
"1.1.1.1" "1.1.1.1"
] ]

View File

@@ -1,29 +1,37 @@
// Copyright (c) 2016-2024 The Hush developers // Copyright (c) 2016-now The Hush developers
// Distributed under the GPLv3 software license, see the accompanying // Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html // file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include "key.h" #include "key.h"
#include "base58.h" #include "base58.h"
#include "chainparams.h" #include "chainparams.h"
#include "gtest/gtest.h"
#include "crypto/common.h" #include "crypto/common.h"
//#include "testutils.h" #define BOOST_TEST_MODULE HushTestSuite
#include <boost/test/included/unit_test.hpp>
std::string notaryPubkey = "0205a8ad0c1dbc515f149af377981aab58b836af008d4d7ab21bd76faf80550b47";
std::string notarySecret = "UxFWWxsf1d7w7K5TvAWSkeX4H95XQKwdwGv49DXwWUTzPTTjHBbU";
int main(int argc, char **argv) { // Test that libsodium has been initialized correctly
/* BOOST_AUTO_TEST_CASE(test_sodium) {
assert(init_and_check_sodium() != -1); BOOST_CHECK_NE( init_and_check_sodium(), -1 );
ECC_Start(); }
ECCVerifyHandle handle; // Inits secp256k1 verify context
SelectParams(CBaseChainParams::REGTEST); BOOST_AUTO_TEST_CASE(test_ecc) {
ECC_Start();
CBitcoinSecret vchSecret; BOOST_CHECK("created secp256k1 context");
// this returns false due to network prefix mismatch but works anyway
vchSecret.SetString(notarySecret); ECCVerifyHandle handle; // Inits secp256k1 verify context
CKey notaryKey = vchSecret.GetKey(); // this value is currently private
*/ //BOOST_CHECK_EQUAL( ECCVerifyHandle::refcount, 1 );
testing::InitGoogleTest(&argc, argv); ECC_Stop();
return RUN_ALL_TESTS(); BOOST_CHECK("destroyed secp256k1 context");
}
BOOST_AUTO_TEST_CASE(test_nets) {
SelectParams(CBaseChainParams::REGTEST);
BOOST_CHECK("regtest");
SelectParams(CBaseChainParams::MAIN);
BOOST_CHECK("mainnet");
SelectParams(CBaseChainParams::TESTNET);
BOOST_CHECK("testnet");
} }

44
src/test-hush/randomx.cpp Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (c) 2016-now The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include "addrman.h"
#include <string>
#include "netbase.h"
#include <boost/test/unit_test.hpp>
#include "RandomX/src/randomx.h"
BOOST_AUTO_TEST_SUITE(randomx)
BOOST_AUTO_TEST_CASE(test_basic) {
randomx_flags flags = randomx_get_flags();
randomx_cache *randomxCache = randomx_alloc_cache(flags);
BOOST_CHECK_MESSAGE(randomxCache != NULL, "randomxCache is not null");
randomx_dataset *randomxDataset = randomx_alloc_dataset(flags);
BOOST_CHECK_MESSAGE(randomxDataset != NULL, "randomxDataset is not null");
auto datasetItemCount = randomx_dataset_item_count();
BOOST_CHECK_MESSAGE( datasetItemCount > 0, "datasetItemCount is positive");
// unknown location(0): fatal error: in "randomx/test_basic": memory access violation at address: 0x7f6983ce2000: invalid permissions
/* TODO
randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount);
char randomxHash[RANDOMX_HASH_SIZE];
randomx_vm *myVM = nullptr;
myVM = randomx_create_vm(flags, nullptr, randomxDataset);
BOOST_CHECK_MESSAGE(myVM != NULL, "randomx_vm is not null");
CDataStream randomxInput(SER_NETWORK, PROTOCOL_VERSION);
randomxInput << "stuff and things";
randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash);
*/
}
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -1,197 +0,0 @@
// Copyright (c) 2016-2024 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <gtest/gtest.h>
#include "cc/betprotocol.h"
#include "cc/eval.h"
#include "base58.h"
#include "core_io.h"
#include "key.h"
#include "main.h"
#include "script/cc.h"
#include "primitives/transaction.h"
#include "script/interpreter.h"
#include "script/serverchecker.h"
#include "testutils.h"
extern int32_t hush_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
namespace TestEvalNotarization {
class EvalMock : public Eval
{
public:
uint32_t nNotaries;
uint8_t notaries[64][33];
std::map<uint256, CTransaction> txs;
std::map<uint256, CBlockIndex> blocks;
int32_t GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const
{
memcpy(pubkeys, notaries, sizeof(notaries));
return nNotaries;
}
bool GetTxUnconfirmed(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) const
{
auto r = txs.find(hash);
if (r != txs.end()) {
txOut = r->second;
if (blocks.count(hash) > 0)
hashBlock = hash;
return true;
}
return false;
}
bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const
{
auto r = blocks.find(hash);
if (r == blocks.end()) return false;
blockIdx = r->second;
return true;
}
};
//static auto noop = [&](CMutableTransaction &mtx){};
static auto noop = [](CMutableTransaction &mtx){};
template<typename Modifier>
void SetupEval(EvalMock &eval, CMutableTransaction &notary, Modifier modify)
{
eval.nNotaries = hush_notaries(eval.notaries, 780060, 1522946781);
// make fake notary inputs
notary.vin.resize(11);
for (int i=0; i<notary.vin.size(); i++) {
CMutableTransaction txIn;
txIn.vout.resize(1);
txIn.vout[0].scriptPubKey << VCH(eval.notaries[i*2], 33) << OP_CHECKSIG;
notary.vin[i].prevout = COutPoint(txIn.GetHash(), 0);
eval.txs[txIn.GetHash()] = CTransaction(txIn);
}
modify(notary);
eval.txs[notary.GetHash()] = CTransaction(notary);
eval.blocks[notary.GetHash()].SetHeight(780060);
eval.blocks[notary.GetHash()].nTime = 1522946781;
}
// inputs have been dropped
static auto rawNotaryTx = "01000000000290460100000000002321020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac0000000000000000506a4c4dae8e0f3e6e5de498a072f5967f3c418c4faba5d56ac8ce17f472d029ef3000008f2e0100424f545300050ba773f0bc31da5839fc7cb9bd7b87f3b765ca608e5cf66785a466659b28880500000000000000";
CTransaction notaryTx;
static bool init = DecodeHexTx(notaryTx, rawNotaryTx);
static uint256 proofTxHash = uint256S("37f76551a16093fbb0a92ee635bbd45b3460da8fd00cf7d5a6b20d93e727fe4c");
static auto vMomProof = ParseHex("0303faecbdd4b3da128c2cd2701bb143820a967069375b2ec5b612f39bbfe78a8611978871c193457ab1e21b9520f4139f113b8d75892eb93ee247c18bccfd067efed7eacbfcdc8946cf22de45ad536ec0719034fb9bc825048fe6ab61fee5bd6e9aae0bb279738d46673c53d68eb2a72da6dbff215ee41a4d405a74ff7cd355805b"); // $ fiat/bots txMoMproof $proofTxHash
/*
TEST(TestEvalNotarization, testGetNotarization)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
SetupEval(eval, notary, noop);
NotarizationData data;
ASSERT_TRUE(eval.GetNotarizationData(notary.GetHash(), data));
EXPECT_EQ(data.height, 77455);
EXPECT_EQ(data.blockHash.GetHex(), "000030ef29d072f417cec86ad5a5ab4f8c413c7f96f572a098e45d6e3e0f8eae");
EXPECT_STREQ(data.symbol, "BOTS");
EXPECT_EQ(data.MoMDepth, 5);
EXPECT_EQ(data.MoM.GetHex(), "88289b6566a48567f65c8e60ca65b7f3877bbdb97cfc3958da31bcf073a70b05");
MoMProof proof;
E_UNMARSHAL(vMomProof, ss >> proof);
EXPECT_EQ(data.MoM, proof.branch.Exec(proofTxHash));
}
TEST(TestEvalNotarization, testInvalidNotaryPubkey)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
SetupEval(eval, notary, noop);
memset(eval.notaries[10], 0, 33);
NotarizationData data;
ASSERT_FALSE(eval.GetNotarizationData(notary.GetHash(), data));
}
*/
TEST(TestEvalNotarization, testInvalidNotarizationBadOpReturn)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
notary.vout[1].scriptPubKey = CScript() << OP_RETURN << 0;
SetupEval(eval, notary, noop);
NotarizationData data(0);
ASSERT_FALSE(eval.GetNotarizationData(notary.GetHash(), data));
}
TEST(TestEvalNotarization, testInvalidNotarizationTxNotEnoughSigs)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
SetupEval(eval, notary, [](CMutableTransaction &tx) {
tx.vin.resize(10);
});
NotarizationData data(0);
ASSERT_FALSE(eval.GetNotarizationData(notary.GetHash(), data));
}
TEST(TestEvalNotarization, testInvalidNotarizationTxDoesntExist)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
SetupEval(eval, notary, noop);
NotarizationData data(0);
ASSERT_FALSE(eval.GetNotarizationData(uint256(), data));
}
TEST(TestEvalNotarization, testInvalidNotarizationDupeNotary)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
SetupEval(eval, notary, [](CMutableTransaction &tx) {
tx.vin[1] = tx.vin[3];
});
NotarizationData data(0);
ASSERT_FALSE(eval.GetNotarizationData(notary.GetHash(), data));
}
TEST(TestEvalNotarization, testInvalidNotarizationInputNotCheckSig)
{
EvalMock eval;
CMutableTransaction notary(notaryTx);
SetupEval(eval, notary, [&](CMutableTransaction &tx) {
int i = 1;
CMutableTransaction txIn;
txIn.vout.resize(1);
txIn.vout[0].scriptPubKey << VCH(eval.notaries[i*2], 33) << OP_RETURN;
notary.vin[i].prevout = COutPoint(txIn.GetHash(), 0);
eval.txs[txIn.GetHash()] = CTransaction(txIn);
});
NotarizationData data(0);
ASSERT_FALSE(eval.GetNotarizationData(notary.GetHash(), data));
}
} /* namespace TestEvalNotarization */

View File

@@ -1,81 +1,85 @@
// Copyright (c) 2016-2024 The Hush developers // Copyright (c) 2016-2024 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying // Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html // file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <gtest/gtest.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include "addrman.h" #include "addrman.h"
#include <string> #include <string>
#include "netbase.h" #include "netbase.h"
//#include <boost/test/included/unit_test.hpp>
#include <boost/test/unit_test.hpp>
#define GTEST_COUT_NOCOLOR std::cerr << "[ ] [ INFO ] " BOOST_AUTO_TEST_SUITE(netbase)
namespace testing
{
namespace internal
{
enum GTestColor {
COLOR_DEFAULT,
COLOR_RED,
COLOR_GREEN,
COLOR_YELLOW
};
extern void ColoredPrintf(GTestColor color, const char* fmt, ...);
}
}
#define PRINTF(...) do { testing::internal::ColoredPrintf(testing::internal::COLOR_GREEN, "[ ] "); testing::internal::ColoredPrintf(testing::internal::COLOR_YELLOW, __VA_ARGS__); } while(0)
// C++ stream interface
class TestCout : public std::stringstream
{
public:
~TestCout()
{
PRINTF("%s",str().c_str());
}
};
#define GTEST_COUT_COLOR TestCout()
using namespace std;
static CNetAddr ResolveIP(const std::string& ip) static CNetAddr ResolveIP(const std::string& ip)
{ {
vector<CNetAddr> vIPs;
CNetAddr addr; CNetAddr addr;
if (LookupHost(ip.c_str(), vIPs)) { bool fAllowLookup = true;
addr = vIPs[0]; if (LookupHost(ip.c_str(), addr, fAllowLookup)) {
} else } else {
{
// it was BOOST_CHECK_MESSAGE, but we can't use ASSERT outside a test
GTEST_COUT_COLOR << strprintf("failed to resolve: %s", ip) << std::endl;
} }
return addr; return addr;
} }
namespace TestNetBaseTests { BOOST_AUTO_TEST_CASE(test_resolve) {
TEST(TestAddrmanTests, netbase_getgroup) {
std::vector<bool> asmap; // use /16 std::vector<bool> asmap; // use /16
ASSERT_TRUE(ResolveIP("127.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // Local -> !Routable() BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // Local -> !Routable()
ASSERT_TRUE(ResolveIP("257.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // !Valid -> !Routable() BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // !Valid -> !Routable()
ASSERT_TRUE(ResolveIP("10.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // RFC1918 -> !Routable() BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // RFC1918 -> !Routable()
ASSERT_TRUE(ResolveIP("169.254.1.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // RFC3927 -> !Routable() BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup(asmap) == std::vector<unsigned char>({0})); // RFC3927 -> !Routable()
ASSERT_TRUE(ResolveIP("1.2.3.4").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // IPv4 BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // IPv4
// std::vector<unsigned char> vch = ResolveIP("4.3.2.1").GetGroup(asmap); // std::vector<unsigned char> vch = ResolveIP("4.3.2.1").GetGroup(asmap);
// GTEST_COUT_COLOR << boost::to_string((int)vch[0]) << boost::to_string((int)vch[1]) << boost::to_string((int)vch[2]) << std::endl;
ASSERT_TRUE(ResolveIP("::FFFF:0:102:304").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6145 BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6145
ASSERT_TRUE(ResolveIP("64:FF9B::102:304").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052 BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052
ASSERT_TRUE(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964 BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964
ASSERT_TRUE(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380 BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380
ASSERT_TRUE(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_ONION, 239})); // Tor BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_ONION, 239})); // Tor
ASSERT_TRUE(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net
ASSERT_TRUE(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6 BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup(asmap) == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6
}
} }
#define TEST_ONION "hushv3h6mbxd2pptj42reko3jcexcgnz5zvp3mqcu6myto3jhhn4yzyd.onion"
BOOST_AUTO_TEST_CASE(netbase_networks)
{
BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
BOOST_CHECK(ResolveIP("10.0.0.42").GetNetwork() == NET_UNROUTABLE);
BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE);
BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4);
BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6);
BOOST_CHECK(ResolveIP(TEST_ONION).GetNetwork() == NET_ONION);
}
BOOST_AUTO_TEST_CASE(netbase_properties)
{
BOOST_CHECK(ResolveIP("127.0.0.1").IsIPv4());
BOOST_CHECK(ResolveIP("::FFFF:192.168.1.1").IsIPv4());
BOOST_CHECK(ResolveIP("::1").IsIPv6());
BOOST_CHECK(ResolveIP("10.0.0.1").IsRFC1918());
BOOST_CHECK(ResolveIP("192.168.1.1").IsRFC1918());
BOOST_CHECK(ResolveIP("172.31.255.255").IsRFC1918());
BOOST_CHECK(ResolveIP("198.18.0.0").IsRFC2544());
BOOST_CHECK(ResolveIP("198.19.255.255").IsRFC2544());
BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849());
BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927());
BOOST_CHECK(ResolveIP("2002::1").IsRFC3964());
BOOST_CHECK(ResolveIP("FC00::").IsRFC4193());
BOOST_CHECK(ResolveIP("2001::2").IsRFC4380());
BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843());
BOOST_CHECK(ResolveIP("2001:20::").IsRFC7343());
BOOST_CHECK(ResolveIP("FE80::").IsRFC4862());
BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052());
BOOST_CHECK(ResolveIP(TEST_ONION).IsTor());
BOOST_CHECK(ResolveIP("127.0.0.1").IsLocal());
BOOST_CHECK(ResolveIP("::1").IsLocal());
BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
}
BOOST_AUTO_TEST_SUITE_END()

View File

@@ -1,54 +0,0 @@
// Copyright (c) 2016-2024 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <gtest/gtest.h>
#include "cc/eval.h"
#include "core_io.h"
#include "key.h"
#include "testutils.h"
namespace TestParseNotarization {
class TestParseNotarization : public ::testing::Test, public Eval {};
TEST(TestParseNotarization, test_ee2fa)
{
// ee2fa47820a31a979f9f21cb3fedbc484bf9a8957cb6c9acd0af28ced29bdfe1
std::vector<uint8_t> opret = ParseHex("c349ff90f3bce62c1b7b49d1da0423b1a3d9b733130cce825b95b9e047c729066e020d00743a06fdb95ad5775d032b30bbb3680dac2091a0f800cf54c79fd3461ce9b31d4b4d4400");
NotarizationData nd;
ASSERT_TRUE(E_UNMARSHAL(opret, ss >> nd));
}
TEST(TestParseNotarization, test__)
{
// 576e910a1f704207bcbcf724124ff9adc5237f45cb6919589cd0aa152caec424
std::vector<uint8_t> opret = ParseHex("b3ed7fbbfbc027caeeeec81e65489ec5d9cd47cda675a5cbb75b4a845e67cf0ef6330300b5a6bd8385feb833f3be961c9d8a46fcecd36dcdfa42ad81a20a892433722f0b4b4d44004125a06024eae24c11f36ea110acd707b041d5355b6e1b42de5e2614357999c6aa02000d26ad0300000000404b4c000000000005130300500d000061f22ba7d19fe29ac3baebd839af8b7127d1f90755534400");
NotarizationData nd;
// We can't parse this one
ASSERT_FALSE(E_UNMARSHAL(opret, ss >> nd));
}
TEST(TestParseNotarization, test__a)
{
// be55101e6c5a93fb3611a44bd66217ad8714d204275ea4e691cfff9d65dff85c TXSCL
std::vector<uint8_t> opret = ParseHex("fb9ea2818eec8b07f8811bab49d64379db074db478997f8114666f239bd79803cc460000d0fac4e715b7e2b917a5d79f85ece0c423d27bd3648fd39ac1dc7db8e1bd4b16545853434c00a69eab9f23d7fb63c4624973e7a9079d6ada2f327040936356d7af5e849f6d670a0003001caf7b7b9e1c9bc59d0c7a619c9683ab1dd0794b6f3ea184a19f8fda031150e700000000");
NotarizationData nd(1);
bool res = E_UNMARSHAL(opret, ss >> nd);
ASSERT_TRUE(res);
}
TEST(TestParseNotarization, test__b)
{
// 03085dafed656aaebfda25bf43ffe9d1fb72565bb1fc8b2a12a631659f28f877 TXSCL
std::vector<uint8_t> opret = ParseHex("48c71a10aa060eab1a43f52acefac3b81fb2a2ce310186b06141884c0501d403c246000052e6d49afd82d9ab3d97c996dd9b6a78a554ffa1625e8dadf0494bd1f8442e3e545853434c007cc5c07e3b67520fd14e23cd5b49f2aa022f411500fd3326ff91e6dc0544a1c90c0003008b69117bb1376ac8df960f785d8c208c599d3a36248c98728256bb6d4737e59600000000");
NotarizationData nd(1);
bool res = E_UNMARSHAL(opret, ss >> nd);
ASSERT_TRUE(res);
}
// for l in `g 'parse notarization' ~/.hush/HUSH3/debug.log | pyline 'l.split()[8]'`; do hoek decodeTx '{"hex":"'`src/hush-cli getrawtransaction "$l"`'"}' | jq '.outputs[1].script.op_return' | pyline 'import base64; print base64.b64decode(l).encode("hex")'; done
}

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# Copyright (c) 2016-2024 The Hush developers # Copyright (c) 2016-2024 The Hush developers
# Copyright 2014 BitPay, Inc. # Copyright 2014 BitPay, Inc.
# Distributed under the GPLv3 software license, see the accompanying # Distributed under the GPLv3 software license, see the accompanying

View File

@@ -710,7 +710,7 @@ boost::filesystem::path GetConfigFile()
if ( SMART_CHAIN_SYMBOL[0] != 0 ) { if ( SMART_CHAIN_SYMBOL[0] != 0 ) {
sprintf(confname,"%s.conf",SMART_CHAIN_SYMBOL); sprintf(confname,"%s.conf",SMART_CHAIN_SYMBOL);
} else { } else {
strcpy(confname,"DRAGONX.conf"); strcpy(confname,"HUSH3.conf");
} }
boost::filesystem::path pathConfigFile(GetArg("-conf",confname)); boost::filesystem::path pathConfigFile(GetArg("-conf",confname));
if (!pathConfigFile.is_complete()) if (!pathConfigFile.is_complete())
@@ -731,7 +731,7 @@ void ReadConfigFile(map<string, string>& mapSettingsRet,
for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
{ {
// Don't overwrite existing settings so command line settings override DRAGONX.conf // Don't overwrite existing settings so command line settings override HUSH3.conf
string strKey = string("-") + it->string_key; string strKey = string("-") + it->string_key;
if (mapSettingsRet.count(strKey) == 0) if (mapSettingsRet.count(strKey) == 0)
{ {
@@ -1029,16 +1029,14 @@ void SetThreadPriority(int nPriority)
std::string PrivacyInfo() std::string PrivacyInfo()
{ {
return "\n" + return "\n" +
FormatParagraph(strprintf(_("In order to ensure you are adequately protecting your privacy when using DragonX, please see <%s>."), FormatParagraph(strprintf(_("In order to ensure you are adequately protecting your privacy when using Hush, please see <%s>."),
"https://dragonx.is/security/")) + "\n"; "https://hush.is/security/")) + "\n";
} }
std::string LicenseInfo() std::string LicenseInfo()
{ {
return "\n" + return "\n" +
FormatParagraph(strprintf(_("Copyright (C) 2024-%i The DragonX Developers"), COPYRIGHT_YEAR)) + "\n" + FormatParagraph(strprintf(_("Copyright (C) 2016-%i Duke Leto and The Hush Developers"), COPYRIGHT_YEAR)) + "\n" +
"\n" +
FormatParagraph(strprintf(_("Copyright (C) 2016-2024 Duke Leto and The Hush Developers"))) + "\n" +
"\n" + "\n" +
FormatParagraph(strprintf(_("Copyright (C) 2016-2020 jl777 and SuperNET developers"))) + "\n" + FormatParagraph(strprintf(_("Copyright (C) 2016-2020 jl777 and SuperNET developers"))) + "\n" +
"\n" + "\n" +

View File

@@ -21,8 +21,7 @@
#define HUSH_VERSION_H #define HUSH_VERSION_H
// network protocol versioning // network protocol versioning
// DragonX 1.0.0 - bumped to separate from old HUSH/DragonX nodes with RandomX bug static const int PROTOCOL_VERSION = 1987429;
static const int PROTOCOL_VERSION = 2000000;
//! initial proto version, to be increased after version/verack negotiation //! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209; static const int INIT_PROTO_VERSION = 209;
//! In this version, 'getheaders' was introduced. //! In this version, 'getheaders' was introduced.
@@ -31,9 +30,8 @@ static const int GETHEADERS_VERSION = 31800;
//! disconnect from peers older than this proto version (HUSH mainnet) //! disconnect from peers older than this proto version (HUSH mainnet)
static const int MIN_HUSH_PEER_PROTO_VERSION = 1987426; static const int MIN_HUSH_PEER_PROTO_VERSION = 1987426;
//! disconnect from peers older than this proto version (DragonX/HACs) //! disconnect from peers older than this proto version (HACs)
//! Set to 2000000 to reject nodes without RandomX validation fix static const int MIN_PEER_PROTO_VERSION = 1987420;
static const int MIN_PEER_PROTO_VERSION = 2000000;
//! nTime field added to CAddress, starting with this version; //! nTime field added to CAddress, starting with this version;
//! if possible, avoid requesting addresses nodes older than this //! if possible, avoid requesting addresses nodes older than this

View File

@@ -13,7 +13,7 @@
char SMART_CHAIN_SYMBOL[HUSH_SMART_CHAIN_MAXLEN]; char SMART_CHAIN_SYMBOL[HUSH_SMART_CHAIN_MAXLEN];
int64_t MAX_MONEY = 200000000 * 100000000LL; int64_t MAX_MONEY = 200000000 * 100000000LL;
uint64_t ASSETCHAINS_SUPPLY; uint64_t ASSETCHAINS_SUPPLY;
uint16_t BITCOIND_RPCPORT = 21769; uint16_t BITCOIND_RPCPORT = 18031;
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC; uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC;
uint32_t ASSETCHAINS_MAGIC = 2387029918; uint32_t ASSETCHAINS_MAGIC = 2387029918;

47
test
View File

@@ -1,47 +1,8 @@
#!/usr/bin/env perl #!/bin/bash
# Copyright 2016-2026 The Hush developers # Copyright 2026-now The Hush developers
# Distributed under the GPLv3 software license, see the accompanying # Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html # file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
use strict; # Run c++ tests first, they are faster
use warnings; ./cpptest && ./rpctest
use 5.010;
my $flags = $ENV{TEST_FLAGS} || '--tracerpc';
my $test_dir = './qa/rpc-tests';
$ENV{PYTHONPATH} = "./qa/rpc-tests/test_framework/";
#$ENV{PYTHON_DEBUG} = 1;
my @tests_to_run = qw{
lockzins.py
shieldcoinbase_donation.py
};
my $exit = 0;
my $failed_tests = 0;
my $time=time();
my $num_tests = @tests_to_run;
print "# Running $num_tests tests";
for my $test (@tests_to_run) {
# send both stderr+stdout to our output file
my $cmd = "$test_dir/$test $flags 1>test-$time.txt 2>&1";
system($cmd);
print ".";
if($?) {
say "$cmd FAILED!";
$exit = 1;
$failed_tests++;
}
}
print "\n";
if ($exit) {
say "FAIL! Number of failed tests: $failed_tests . Details in test-$time.txt";
} else {
say "PASS!";
}
exit($exit);

View File

@@ -1,227 +0,0 @@
#!/usr/bin/env bash
# Copyright 2024 The Hush Developers
# Copyright 2024 The DragonX Developers
# Released under the GPLv3
#
# Download and apply a DRAGONX blockchain bootstrap.
# Safely preserves wallet.dat and configuration files.
set -euo pipefail
BOOTSTRAP_BASE_URL="https://bootstrap.dragonx.is"
BOOTSTRAP_FILE="DRAGONX.zip"
CHAIN_NAME="DRAGONX"
# Determine data directory
if [[ "$OSTYPE" == "darwin"* ]]; then
DATADIR="$HOME/Library/Application Support/Hush/$CHAIN_NAME"
else
DATADIR="$HOME/.hush/$CHAIN_NAME"
fi
CLI="dragonx-cli"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
info() { echo -e "${GREEN}[INFO]${NC} $*" >&2; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*" >&2; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
# Find dragonx-cli in PATH or relative to this script
find_cli() {
if command -v "$CLI" &>/dev/null; then
CLI=$(command -v "$CLI")
elif [[ -x "$(dirname "$0")/../../src/$CLI" ]]; then
CLI="$(dirname "$0")/../../src/$CLI"
else
CLI=""
fi
}
# Stop the daemon if running
stop_daemon() {
find_cli
if [[ -n "$CLI" ]]; then
if "$CLI" getinfo &>/dev/null 2>&1; then
info "Stopping DragonX daemon..."
"$CLI" stop 2>/dev/null || true
# Wait for daemon to exit
local tries=0
while "$CLI" getinfo &>/dev/null 2>&1; do
sleep 2
tries=$((tries + 1))
if [[ $tries -ge 60 ]]; then
error "Daemon did not stop after 120 seconds. Please stop it manually and retry."
fi
done
info "Daemon stopped."
else
info "Daemon is not running."
fi
else
warn "dragonx-cli not found. Please make sure the daemon is stopped before continuing."
read -rp "Is the DragonX daemon stopped? (y/N): " answer
if [[ "${answer,,}" != "y" ]]; then
error "Please stop the daemon first and run this script again."
fi
fi
}
# Files/dirs to preserve (never delete these)
PRESERVE_LIST=(
"wallet.dat"
"DRAGONX.conf"
"peers.dat"
)
# Remove blockchain data while preserving wallet and config
clean_chain_data() {
if [[ ! -d "$DATADIR" ]]; then
info "Data directory does not exist yet, creating it."
mkdir -p "$DATADIR"
return
fi
info "Cleaning blockchain data from $DATADIR ..."
# Move preserved files to a temp location
local tmpdir
tmpdir=$(mktemp -d)
for f in "${PRESERVE_LIST[@]}"; do
if [[ -e "$DATADIR/$f" ]]; then
cp -a "$DATADIR/$f" "$tmpdir/"
fi
done
# Remove blockchain directories
local dirs_to_remove=("blocks" "chainstate" "notarizations" "komodo" "db.log" "debug.log" "fee_estimates.dat" "banlist.dat")
for d in "${dirs_to_remove[@]}"; do
if [[ -e "$DATADIR/$d" ]]; then
rm -rf "$DATADIR/$d"
fi
done
# Restore preserved files
for f in "${PRESERVE_LIST[@]}"; do
if [[ -e "$tmpdir/$f" ]]; then
cp -a "$tmpdir/$f" "$DATADIR/"
fi
done
rm -rf "$tmpdir"
info "Blockchain data cleaned."
}
# Download a file via wget or curl
download_file() {
local url="$1"
local outfile="$2"
if command -v wget &>/dev/null; then
wget --progress=bar:force -O "$outfile" "$url" || error "Download failed: $url"
elif command -v curl &>/dev/null; then
curl -L --progress-bar -o "$outfile" "$url" || error "Download failed: $url"
else
error "Neither wget nor curl found. Please install one and retry."
fi
}
# Download the bootstrap and verify checksums
download_bootstrap() {
local outfile="$DATADIR/$BOOTSTRAP_FILE"
local md5file="$DATADIR/${BOOTSTRAP_FILE}.md5"
local sha256file="$DATADIR/${BOOTSTRAP_FILE}.sha256"
info "Downloading bootstrap from $BOOTSTRAP_BASE_URL ..."
info "This may take a while depending on your connection speed."
download_file "$BOOTSTRAP_BASE_URL/$BOOTSTRAP_FILE" "$outfile"
info "Bootstrap download complete."
info "Downloading checksums..."
download_file "$BOOTSTRAP_BASE_URL/${BOOTSTRAP_FILE}.md5" "$md5file"
download_file "$BOOTSTRAP_BASE_URL/${BOOTSTRAP_FILE}.sha256" "$sha256file"
# Verify checksums
info "Verifying checksums..."
cd "$DATADIR"
if command -v md5sum &>/dev/null; then
if md5sum -c "$md5file" >&2; then
info "MD5 checksum verified."
else
error "MD5 checksum verification failed! The download may be corrupted."
fi
else
warn "md5sum not found, skipping MD5 verification."
fi
if command -v sha256sum &>/dev/null; then
if sha256sum -c "$sha256file" >&2; then
info "SHA256 checksum verified."
else
error "SHA256 checksum verification failed! The download may be corrupted."
fi
else
warn "sha256sum not found, skipping SHA256 verification."
fi
# Clean up checksum files
rm -f "$md5file" "$sha256file"
echo "$outfile"
}
# Extract the bootstrap
extract_bootstrap() {
local archive="$1"
info "Extracting bootstrap..."
cd "$DATADIR"
# Extract zip, but never overwrite wallet.dat or config
unzip -o "$archive" -x 'wallet.dat' '*.conf' || error "Extraction failed. Please install unzip and retry."
info "Bootstrap extracted successfully."
# Clean up the downloaded archive
rm -f "$archive"
info "Removed downloaded archive to save disk space."
}
main() {
echo "============================================"
echo " DragonX Bootstrap Installer"
echo "============================================"
echo ""
info "Data directory: $DATADIR"
echo ""
# Step 1: Stop daemon
stop_daemon
# Step 2: Clean old chain data
clean_chain_data
# Step 3: Download bootstrap
local archive
archive=$(download_bootstrap)
# Step 4: Extract bootstrap
extract_bootstrap "$archive"
echo ""
info "Bootstrap installation complete!"
info "You can now start DragonX with: dragonxd"
echo ""
}
main "$@"

View File

@@ -40,4 +40,4 @@ cd $WD
sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure
cd src/ cd src/
CC="${CC} -g " CXX="${CXX} -g " make V=1 dragonxd.exe dragonx-cli.exe dragonx-tx.exe CC="${CC} -g " CXX="${CXX} -g " make V=1 hushd.exe hush-cli.exe hush-tx.exe

View File

@@ -1,15 +1,14 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Copyright (c) 2016-2024 The Hush developers # Copyright (c) 2016-2024 The Hush developers
# Copyright (c) 2024-2026 The DragonX developers
# Released under the GPLv3 # Released under the GPLv3
set -e set -e
set -x set -x
#hardcode and uncomment if dragonxd is not running on this machine #hardcode and uncomment if hushd is not running on this machine
#VERSION=1.0.0 #VERSION=3.6.3
VERSION=$(./src/dragonxd --version|grep version|cut -d' ' -f4|cut -d- -f1|sed 's/v//g') VERSION=$(./src/hushd --version|grep version|cut -d' ' -f4|cut -d- -f1|sed 's/v//g')
DIR="dragonx-$VERSION-linux-amd64" DIR="hush-$VERSION-linux-amd64"
FILE="$DIR.tar" FILE="$DIR.tar"
TIME=$(perl -e 'print time') TIME=$(perl -e 'print time')
@@ -24,13 +23,12 @@ mkdir $BUILD
echo "Created new build dir $BUILD" echo "Created new build dir $BUILD"
cp contrib/asmap/asmap.dat $BUILD cp contrib/asmap/asmap.dat $BUILD
cp sapling*.params $BUILD cp sapling*.params $BUILD
cp util/bootstrap-dragonx.sh $BUILD
cd src cd src
cp dragonxd dragonx-cli dragonx-tx ../$BUILD cp hushd hush-cli hush-tx hush-arrakis-chain ../$BUILD
cd ../$BUILD cd ../$BUILD
strip dragonxd dragonx-cli dragonx-tx strip hushd hush-cli hush-tx
cd .. cd ..
tar -f $FILE -c dragonx-$VERSION-linux-amd64/* tar -f $FILE -c hush-$VERSION-linux-amd64/*
gzip -9 $FILE gzip -9 $FILE
sha256sum *.gz sha256sum *.gz
du -sh *.gz du -sh *.gz