Compare commits
10 Commits
f5c8e02f24
...
a2647b106f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2647b106f | ||
|
|
ab6a3a05d7 | ||
|
|
f565b2920d | ||
|
|
0083cd26bb | ||
|
|
a918136a7c | ||
|
|
3d4e25e429 | ||
|
|
896fa9c107 | ||
|
|
10a1b27de1 | ||
|
|
3cf6c37bf6 | ||
|
|
b25bd2838c |
271
.gitignore
vendored
271
.gitignore
vendored
@@ -1,13 +1,43 @@
|
|||||||
|
# ==========================
|
||||||
|
# Editor & IDE files
|
||||||
|
# ==========================
|
||||||
|
.*.sw?
|
||||||
|
*.*~*
|
||||||
|
*~
|
||||||
|
*.bak
|
||||||
|
*.rej
|
||||||
|
*.orig
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# Compiled objects & libraries
|
||||||
|
# ==========================
|
||||||
|
*.o
|
||||||
|
*.o-*
|
||||||
|
*.a
|
||||||
|
*.lo
|
||||||
|
*.la
|
||||||
|
*.so
|
||||||
|
*.dll
|
||||||
|
*.pyc
|
||||||
|
*.pb.cc
|
||||||
|
*.pb.h
|
||||||
|
*.json.h
|
||||||
|
*.raw.h
|
||||||
|
*.dSYM
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# Archives & packages
|
||||||
|
# ==========================
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.deb
|
*.deb
|
||||||
src/bitcoin
|
*.zip
|
||||||
src/test/test_bitcoin
|
*.dmg
|
||||||
src/core
|
|
||||||
|
|
||||||
*zcashTest.pk
|
# ==========================
|
||||||
*zcashTest.vk
|
# Autotools / configure
|
||||||
|
# ==========================
|
||||||
# autoreconf
|
|
||||||
#Makefile.in
|
#Makefile.in
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
autom4te.cache/
|
autom4te.cache/
|
||||||
@@ -28,58 +58,74 @@ config.log
|
|||||||
config.status
|
config.status
|
||||||
configure
|
configure
|
||||||
libtool
|
libtool
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
src/Makefile.in
|
||||||
|
doc/man/Makefile.in
|
||||||
src/config/bitcoin-config.h
|
src/config/bitcoin-config.h
|
||||||
src/config/bitcoin-config.h.in
|
src/config/bitcoin-config.h.in
|
||||||
src/config/stamp-h1
|
src/config/stamp-h1
|
||||||
|
libzcashconsensus.pc
|
||||||
|
|
||||||
cache/
|
# ==========================
|
||||||
venv-mnf/
|
# Build outputs & artifacts
|
||||||
src/univalue/gen
|
# ==========================
|
||||||
|
src/.build_target
|
||||||
.deps
|
.deps
|
||||||
.dirstamp
|
.dirstamp
|
||||||
.idea
|
|
||||||
.libs
|
.libs
|
||||||
.*.sw?
|
|
||||||
*.*~*
|
|
||||||
*.bak
|
|
||||||
*.rej
|
|
||||||
*.orig
|
|
||||||
*.pyc
|
|
||||||
*.o
|
|
||||||
*.o-*
|
|
||||||
.zcash
|
|
||||||
*.a
|
|
||||||
*.pb.cc
|
|
||||||
*.pb.h
|
|
||||||
.vscode
|
|
||||||
|
|
||||||
|
# Hush binaries
|
||||||
|
src/hush-cli
|
||||||
|
src/hushd
|
||||||
|
src/hush-tx
|
||||||
|
src/hush-test
|
||||||
|
src/hush-cli.exe
|
||||||
|
src/hushd.exe
|
||||||
|
src/hush-tx.exe
|
||||||
|
src/wallet-utility
|
||||||
|
src/wallet-utility.exe
|
||||||
|
|
||||||
|
# Legacy bitcoin binaries
|
||||||
|
src/bitcoin
|
||||||
|
src/test/test_bitcoin
|
||||||
|
src/core
|
||||||
|
|
||||||
|
# Shared libraries
|
||||||
|
src/libcc.so
|
||||||
|
src/libcc.dll
|
||||||
|
src/cc/customcc.so
|
||||||
|
src/cc/customcc.dll
|
||||||
|
src/cc/librogue.so
|
||||||
|
|
||||||
|
# RandomX build dirs
|
||||||
|
src/RandomX/build-linux/
|
||||||
|
src/RandomX/build-win64/
|
||||||
|
|
||||||
|
# Release directories
|
||||||
|
release/
|
||||||
|
release-win64/
|
||||||
|
release-linux/
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# Depends build system
|
||||||
|
# ==========================
|
||||||
|
depends/built/
|
||||||
|
depends/work/
|
||||||
|
depends/x86_64-*/
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# Zcash / Sapling test keys
|
||||||
|
# ==========================
|
||||||
|
*zcashTest.pk
|
||||||
|
*zcashTest.vk
|
||||||
|
.zcash
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# Test & coverage
|
||||||
|
# ==========================
|
||||||
*.log
|
*.log
|
||||||
*.trs
|
*.trs
|
||||||
*.dmg
|
|
||||||
|
|
||||||
*.json.h
|
|
||||||
*.raw.h
|
|
||||||
|
|
||||||
#libtool object files
|
|
||||||
*.lo
|
|
||||||
*.la
|
|
||||||
|
|
||||||
# Compilation
|
|
||||||
Makefile
|
|
||||||
|
|
||||||
# Unit-tests
|
|
||||||
Makefile.test
|
|
||||||
src/test/buildenv.py
|
|
||||||
|
|
||||||
# Resources cpp
|
|
||||||
qrc_*.cpp
|
|
||||||
|
|
||||||
# Mac specific
|
|
||||||
.DS_Store
|
|
||||||
build
|
|
||||||
|
|
||||||
#lcov
|
|
||||||
*.gcno
|
*.gcno
|
||||||
*.gcda
|
*.gcda
|
||||||
/*.info
|
/*.info
|
||||||
@@ -87,8 +133,8 @@ test_bitcoin.coverage/
|
|||||||
zcash-gtest.coverage/
|
zcash-gtest.coverage/
|
||||||
total.coverage/
|
total.coverage/
|
||||||
coverage_percent.txt
|
coverage_percent.txt
|
||||||
|
Makefile.test
|
||||||
#build tests
|
src/test/buildenv.py
|
||||||
linux-coverage-build
|
linux-coverage-build
|
||||||
linux-build
|
linux-build
|
||||||
win32-build
|
win32-build
|
||||||
@@ -97,84 +143,61 @@ qa/pull-tester/tests-config.sh
|
|||||||
qa/pull-tester/cache/*
|
qa/pull-tester/cache/*
|
||||||
qa/pull-tester/test.*/*
|
qa/pull-tester/test.*/*
|
||||||
|
|
||||||
!src/leveldb*/Makefile
|
# ==========================
|
||||||
|
# Generated / misc source
|
||||||
|
# ==========================
|
||||||
|
qrc_*.cpp
|
||||||
|
src/univalue/gen
|
||||||
|
src/cryptoconditions/compile
|
||||||
|
src/fiat/-usd
|
||||||
/doc/doxygen/
|
/doc/doxygen/
|
||||||
|
|
||||||
libzcashconsensus.pc
|
# ==========================
|
||||||
|
# CC / games (legacy)
|
||||||
|
# ==========================
|
||||||
|
src/cc/rogue/rogue
|
||||||
|
src/cc/rogue/rogue.so
|
||||||
|
src/cc/rogue/test.zip
|
||||||
|
src/cc/rogue/config.h
|
||||||
|
src/cc/rogue/confdefs.h
|
||||||
|
src/cc/rogue/x64
|
||||||
|
src/cc/dapps/a.out
|
||||||
|
src/cc/games/prices
|
||||||
|
src/cc/games/tetris
|
||||||
|
src/ROGUE.conf
|
||||||
|
src/rogue.scr
|
||||||
|
src/rogue.*.*
|
||||||
|
|
||||||
src/fiat/-usd
|
# ==========================
|
||||||
|
# Misc runtime / temp files
|
||||||
|
# ==========================
|
||||||
|
src/checkfile
|
||||||
|
src/foo.zip
|
||||||
|
src/log
|
||||||
|
src/HUSH3_7776
|
||||||
|
REGTEST_7776
|
||||||
|
src/rpcmisc~.cpp
|
||||||
|
cache/
|
||||||
|
venv-mnf/
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# Debian packaging
|
||||||
|
# ==========================
|
||||||
contrib/debian/files
|
contrib/debian/files
|
||||||
contrib/debian/substvars
|
contrib/debian/substvars
|
||||||
|
|
||||||
src/rpcmisc~.cpp
|
# ==========================
|
||||||
src/wallet-utility
|
# Platform specific
|
||||||
|
# ==========================
|
||||||
|
.DS_Store
|
||||||
|
build
|
||||||
|
|
||||||
src/hush-cli
|
# ==========================
|
||||||
src/hushd
|
# Bundled repos (use separately)
|
||||||
src/hush-tx
|
# ==========================
|
||||||
src/hush-test
|
repos/
|
||||||
src/hush-cli.exe
|
|
||||||
src/hushd.exe
|
|
||||||
src/hush-tx.exe
|
|
||||||
|
|
||||||
#output during builds, symbol tables?
|
# ==========================
|
||||||
*.dSYM
|
# Leveldb Makefile exception
|
||||||
|
# ==========================
|
||||||
|
!src/leveldb*/Makefile
|
||||||
src/cryptoconditions/compile
|
|
||||||
|
|
||||||
src/cc/rogue/rogue
|
|
||||||
|
|
||||||
src/cc/rogue/rogue.so
|
|
||||||
|
|
||||||
src/cc/rogue/test.zip
|
|
||||||
src/cc/dapps/a.out
|
|
||||||
src/checkfile
|
|
||||||
|
|
||||||
src/foo.zip
|
|
||||||
|
|
||||||
src/log
|
|
||||||
|
|
||||||
src/rogue.530623577502174316.0
|
|
||||||
|
|
||||||
src/rogue.530623577502174316.pack
|
|
||||||
|
|
||||||
src/rogue.530623577502174316.player
|
|
||||||
|
|
||||||
|
|
||||||
src/cc/rogue/config.h
|
|
||||||
|
|
||||||
src/ROGUE.conf
|
|
||||||
|
|
||||||
src/rogue.scr
|
|
||||||
|
|
||||||
src/cc/rogue/confdefs.h
|
|
||||||
src/cc/rogue/x64
|
|
||||||
|
|
||||||
src/cc/dapps/a.out
|
|
||||||
src/Makefile.in
|
|
||||||
doc/man/Makefile.in
|
|
||||||
Makefile.in
|
|
||||||
src/libcc.so
|
|
||||||
src/libcc.dll
|
|
||||||
src/cc/customcc.so
|
|
||||||
src/cc/customcc.dll
|
|
||||||
src/HUSH3_7776
|
|
||||||
REGTEST_7776
|
|
||||||
src/cc/librogue.so
|
|
||||||
src/cc/games/prices
|
|
||||||
src/cc/games/tetris
|
|
||||||
|
|
||||||
# Build artifacts
|
|
||||||
*~
|
|
||||||
*.zip
|
|
||||||
release-win64/
|
|
||||||
release-linux/
|
|
||||||
src/RandomX/build-linux/
|
|
||||||
src/RandomX/build-win64/
|
|
||||||
src/wallet-utility.exe
|
|
||||||
src/.build_target
|
|
||||||
|
|
||||||
# other
|
|
||||||
repos/
|
|
||||||
@@ -11,38 +11,43 @@ make clean 2>/dev/null || true
|
|||||||
rm -rf depends/built depends/x86_64-unknown-linux-gnu depends/work
|
rm -rf depends/built depends/x86_64-unknown-linux-gnu depends/work
|
||||||
make -C depends clean 2>/dev/null || true
|
make -C depends clean 2>/dev/null || true
|
||||||
|
|
||||||
|
# Limit parallelism to avoid OOM kills inside Docker.
|
||||||
|
# Each C++ compilation can use 1-2 GB RAM; cap at ~half of nproc.
|
||||||
|
JOBS=$(( $(nproc) / 2 ))
|
||||||
|
[ "$JOBS" -lt 1 ] && JOBS=1
|
||||||
|
|
||||||
# Build RandomX for Linux (clean, since host build is different arch/libc)
|
# Build RandomX for Linux (clean, since host build is different arch/libc)
|
||||||
cd src/RandomX
|
cd src/RandomX
|
||||||
rm -rf build-linux
|
rm -rf build-linux
|
||||||
mkdir -p build-linux && cd build-linux
|
mkdir -p build-linux && cd build-linux
|
||||||
cmake -DARCH=native ..
|
cmake -DARCH=native ..
|
||||||
make -j$(nproc)
|
make -j"$JOBS"
|
||||||
cd /hush3
|
cd /hush3
|
||||||
|
|
||||||
# Run the normal build
|
# Run the normal build
|
||||||
./util/build.sh --disable-tests -j$(nproc)
|
./util/build.sh --disable-tests -j"$JOBS"
|
||||||
|
|
||||||
# Package release
|
# Package release
|
||||||
echo "Creating Linux release package..."
|
echo "Creating Linux release package..."
|
||||||
VERSION=$(grep -oP 'define\(_CLIENT_VERSION.*?,\s*\K[0-9]+' configure.ac | head -3 | tr '\n' '.' | sed 's/\.$//')
|
VERSION=$(grep -oP 'define\(_CLIENT_VERSION.*?,\s*\K[0-9]+' configure.ac | head -3 | tr '\n' '.' | sed 's/\.$//')
|
||||||
VERSION=${VERSION:-3.10.5}
|
VERSION=${VERSION:-3.10.5}
|
||||||
RELEASE_DIR="release-linux"
|
RELEASE_DIR="release/${VERSION}-linux-amd64"
|
||||||
mkdir -p "$RELEASE_DIR"
|
mkdir -p "$RELEASE_DIR"
|
||||||
|
|
||||||
strip -s src/hushd src/hush-cli src/hush-tx
|
strip -s src/hushd src/hush-cli src/hush-tx
|
||||||
cp src/hushd src/hush-cli src/hush-tx "$RELEASE_DIR/"
|
cp src/hushd src/hush-cli src/hush-tx "$RELEASE_DIR/"
|
||||||
cp asmap.dat sapling-spend.params sapling-output.params "$RELEASE_DIR/" 2>/dev/null || true
|
cp asmap.dat sapling-spend.params sapling-output.params "$RELEASE_DIR/" 2>/dev/null || true
|
||||||
cp src/hush-arrakis-chain src/dragonxd src/dragonx-cli "$RELEASE_DIR/"
|
cp contrib/scripts/hush-arrakis-chain contrib/scripts/dragonxd contrib/scripts/dragonx-cli "$RELEASE_DIR/"
|
||||||
cp contrib/bootstrap/bootstrap-dragonx.sh "$RELEASE_DIR/"
|
cp contrib/bootstrap/bootstrap-dragonx.sh "$RELEASE_DIR/"
|
||||||
|
|
||||||
# Create ZIP inside release dir (matches --win-release layout)
|
# Create ZIP inside release dir (matches --win-release layout)
|
||||||
rm -f "$RELEASE_DIR/hush-${VERSION}-linux64.zip"
|
rm -f "$RELEASE_DIR/${VERSION}-linux-amd64.zip"
|
||||||
cd "$RELEASE_DIR"
|
cd "$RELEASE_DIR"
|
||||||
zip -9 "hush-${VERSION}-linux64.zip" *
|
zip -9 "${VERSION}-linux-amd64.zip" *
|
||||||
cd ..
|
cd ../..
|
||||||
|
|
||||||
echo "Release package created: $RELEASE_DIR/hush-${VERSION}-linux64.zip"
|
echo "Release package created: $RELEASE_DIR/${VERSION}-linux-amd64.zip"
|
||||||
ls -lh "$RELEASE_DIR/hush-${VERSION}-linux64.zip"
|
ls -lh "$RELEASE_DIR/${VERSION}-linux-amd64.zip"
|
||||||
|
|
||||||
# Fix ownership of all files created by root so host user can access them
|
# Fix ownership of all files created by root so host user can access them
|
||||||
if [ -n "${HOST_UID:-}" ] && [ -n "${HOST_GID:-}" ]; then
|
if [ -n "${HOST_UID:-}" ] && [ -n "${HOST_GID:-}" ]; then
|
||||||
|
|||||||
24
build.sh
24
build.sh
@@ -26,6 +26,26 @@ check_and_clean_target() {
|
|||||||
if [[ -d src/leveldb ]]; then
|
if [[ -d src/leveldb ]]; then
|
||||||
make -C src/leveldb clean 2>/dev/null || true
|
make -C src/leveldb clean 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
# Clean depends when switching between Docker and native builds,
|
||||||
|
# since Docker builds bake container paths into .la files
|
||||||
|
local TRIPLET
|
||||||
|
TRIPLET=$(./depends/config.guess 2>/dev/null || true)
|
||||||
|
if [[ -n "$TRIPLET" && -d "depends/$TRIPLET" ]]; then
|
||||||
|
echo "Cleaning depends/$TRIPLET to avoid path contamination..."
|
||||||
|
# Use sudo if files are root-owned (from Docker builds)
|
||||||
|
if [[ "$(stat -c '%u' "depends/$TRIPLET" 2>/dev/null)" == "0" ]]; then
|
||||||
|
sudo rm -rf "depends/$TRIPLET" "depends/built/$TRIPLET"
|
||||||
|
else
|
||||||
|
rm -rf "depends/$TRIPLET" "depends/built/$TRIPLET"
|
||||||
|
fi
|
||||||
|
elif [[ -n "$TRIPLET" && -d "depends/built/$TRIPLET" ]]; then
|
||||||
|
echo "Cleaning depends/built/$TRIPLET to avoid path contamination..."
|
||||||
|
if [[ "$(stat -c '%u' "depends/built/$TRIPLET" 2>/dev/null)" == "0" ]]; then
|
||||||
|
sudo rm -rf "depends/built/$TRIPLET"
|
||||||
|
else
|
||||||
|
rm -rf "depends/built/$TRIPLET"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
echo "Clean complete."
|
echo "Clean complete."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -48,7 +68,9 @@ if [[ "${1:-}" == "--linux-release" ]]; then
|
|||||||
echo "Building Linux release inside Ubuntu 20.04 Docker container..."
|
echo "Building Linux release inside Ubuntu 20.04 Docker container..."
|
||||||
sudo docker build -t hush-builder -f Dockerfile.build .
|
sudo docker build -t hush-builder -f Dockerfile.build .
|
||||||
sudo docker run --rm -e HOST_UID=$(id -u) -e HOST_GID=$(id -g) -v "$SCRIPT_DIR:/hush3" hush-builder "$@"
|
sudo docker run --rm -e HOST_UID=$(id -u) -e HOST_GID=$(id -g) -v "$SCRIPT_DIR:/hush3" hush-builder "$@"
|
||||||
echo "Docker build complete. Release is in release-linux/"
|
VERSION=$(grep -oP 'define\(_CLIENT_VERSION.*?,\s*\K[0-9]+' configure.ac | head -3 | tr '\n' '.' | sed 's/\.$//')
|
||||||
|
VERSION=${VERSION:-3.10.5}
|
||||||
|
echo "Docker build complete. Release is in release/${VERSION}-linux-amd64/"
|
||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Estimate when a Hush block will happen.
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
./contrib/block_time.pl 123456 # Print out datetime of when block height 123456 happens
|
./contrib/scripts/block_time.pl 123456 # Print out datetime of when block height 123456 happens
|
||||||
|
|
||||||
## gen-zaddrs.pl
|
## gen-zaddrs.pl
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ Generate zaddrs in bulk, by default 50 at a time. Prints out a zaddr one per lin
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
./contrib/gen-zaddrs.pl # generate 50 zaddrs
|
./contrib/scripts/gen-zaddrs.pl # generate 50 zaddrs
|
||||||
./contrib/gen-zaddrs.pl 500 # generate 500 zaddrs
|
./contrib/scripts/gen-zaddrs.pl 500 # generate 500 zaddrs
|
||||||
|
|
||||||
|
|
||||||
## Wallet Tools
|
## Wallet Tools
|
||||||
|
|||||||
19
contrib/scripts/assetchains_stop
Executable file
19
contrib/scripts/assetchains_stop
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright (c) 2016-2024 The Hush developers
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
|
hush_cli='./hush-cli'
|
||||||
|
|
||||||
|
"$SCRIPTDIR/listassetchains" | while read chain; do
|
||||||
|
$hush_cli --ac_name=$chain stop
|
||||||
|
done
|
||||||
|
|
||||||
15
contrib/scripts/dragonx-cli
Executable file
15
contrib/scripts/dragonx-cli
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2016-2024 The Hush Developers
|
||||||
|
# Copyright 2022 The DragonX Developers
|
||||||
|
# Released under the GPLv3
|
||||||
|
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
|
./hush-cli -ac_name=DRAGONX "$@"
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
# Copyright 2022 The DragonX Developers
|
# Copyright 2022 The DragonX Developers
|
||||||
# Released under the GPLv3
|
# Released under the GPLv3
|
||||||
|
|
||||||
# set working directory to the location of this script
|
# Resolve binary directory
|
||||||
# readlink -f does not always exist
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR"
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
else
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
SEEDNODE=176.126.87.241
|
SEEDNODE=176.126.87.241
|
||||||
|
|
||||||
17
contrib/scripts/hush-arrakis-chain
Executable file
17
contrib/scripts/hush-arrakis-chain
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright (c) 2016-2024 The Hush developers
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
|
DEFAULTS=""
|
||||||
|
|
||||||
|
# People can just use hushd going forward, but this script makes it
|
||||||
|
# more clear what is going on
|
||||||
|
HUSH="./hushd"
|
||||||
|
$HUSH $DEFAULTS "$@"
|
||||||
@@ -5,8 +5,12 @@ import json
|
|||||||
def format_param(param, value):
|
def format_param(param, value):
|
||||||
return '-' + param + '=' + value
|
return '-' + param + '=' + value
|
||||||
|
|
||||||
script_dir = os.path.dirname(__file__)
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
with open(script_dir + '/assetchains.json') as file:
|
# Look for assetchains.json in same dir first, then in src/
|
||||||
|
json_path = os.path.join(script_dir, 'assetchains.json')
|
||||||
|
if not os.path.exists(json_path):
|
||||||
|
json_path = os.path.join(script_dir, '..', '..', 'src', 'assetchains.json')
|
||||||
|
with open(json_path) as file:
|
||||||
assetchains = json.load(file)
|
assetchains = json.load(file)
|
||||||
|
|
||||||
for chain in assetchains:
|
for chain in assetchains:
|
||||||
14
contrib/scripts/listassetchains
Executable file
14
contrib/scripts/listassetchains
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# Look for assetchains.json in same dir first, then in src/
|
||||||
|
json_path = os.path.join(script_dir, 'assetchains.json')
|
||||||
|
if not os.path.exists(json_path):
|
||||||
|
json_path = os.path.join(script_dir, '..', '..', 'src', 'assetchains.json')
|
||||||
|
with open(json_path) as file:
|
||||||
|
assetchains = json.load(file)
|
||||||
|
|
||||||
|
for chain in assetchains:
|
||||||
|
print(chain['ac_name'])
|
||||||
@@ -10,7 +10,7 @@ use warnings;
|
|||||||
use strict;
|
use strict;
|
||||||
|
|
||||||
# call this script like this to generate checkpoints for a HAC such as DragonX:
|
# call this script like this to generate checkpoints for a HAC such as DragonX:
|
||||||
# CLI=./src/dragonx-cli ./contrib/sdl_checkpoints.pl ...
|
# CLI=./src/dragonx-cli ./contrib/scripts/sdl_checkpoints.pl ...
|
||||||
|
|
||||||
my $hush = $ENV{CLI} || "./src/hush-cli";
|
my $hush = $ENV{CLI} || "./src/hush-cli";
|
||||||
my $gethash = "$hush getblockhash";
|
my $gethash = "$hush getblockhash";
|
||||||
@@ -2,15 +2,24 @@
|
|||||||
# Copyright (c) 2018-2024 The Hush developers
|
# Copyright (c) 2018-2024 The Hush developers
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
# You can now add delay line to pubkey.txt file
|
# You can now add delay line to pubkey.txt file
|
||||||
source pubkey.txt
|
source pubkey.txt
|
||||||
overide_args="$@"
|
override_args="$@"
|
||||||
seed_ip=$(SEEDNODE)
|
seed_ip=$(SEEDNODE)
|
||||||
hsc='./hush-arrakis-chain'
|
hsc='./hush-arrakis-chain'
|
||||||
|
|
||||||
if [ -z "$delay" ]; then delay=20; fi
|
if [ -z "$delay" ]; then delay=20; fi
|
||||||
|
|
||||||
./listassetchainparams | while read args; do
|
"$SCRIPTDIR/listassetchainparams" | while read args; do
|
||||||
gen=""
|
gen=""
|
||||||
if [ $[RANDOM % 10] == 1 ]; then
|
if [ $[RANDOM % 10] == 1 ]; then
|
||||||
gen=" -gen -genproclimit=1"
|
gen=" -gen -genproclimit=1"
|
||||||
15
contrib/scripts/testdragonx-cli
Executable file
15
contrib/scripts/testdragonx-cli
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2016-2024 The Hush Developers
|
||||||
|
# Copyright 2022 The DragonX Developers
|
||||||
|
# Released under the GPLv3
|
||||||
|
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
|
./hush-cli -ac_name=TESTDRAGONX $@
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
# Copyright 2022 The DragonX Developers
|
# Copyright 2022 The DragonX Developers
|
||||||
# Released under the GPLv3
|
# Released under the GPLv3
|
||||||
|
|
||||||
# set working directory to the location of this script
|
# Resolve binary directory
|
||||||
# readlink -f does not always exist
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR"
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
else
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
BLOCKTIME=18
|
BLOCKTIME=18
|
||||||
SUPPLY=0
|
SUPPLY=0
|
||||||
15
contrib/scripts/testequihash-cli
Executable file
15
contrib/scripts/testequihash-cli
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2016-2024 The Hush Developers
|
||||||
|
# Copyright 2022 The DragonX Developers
|
||||||
|
# Released under the GPLv3
|
||||||
|
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
|
./hush-cli -ac_name=TESTEQUIHASH $@
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
# Copyright 2022 The DragonX Developers
|
# Copyright 2022 The DragonX Developers
|
||||||
# Released under the GPLv3
|
# Released under the GPLv3
|
||||||
|
|
||||||
# set working directory to the location of this script
|
# Resolve binary directory
|
||||||
# readlink -f does not always exist
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR"
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
else
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
BLOCKTIME=18
|
BLOCKTIME=18
|
||||||
SUPPLY=0
|
SUPPLY=0
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Copyright (c) 2016-2024 The Hush developers
|
# Copyright (c) 2016-2024 The Hush developers
|
||||||
|
|
||||||
# set working directory to the location of this script
|
# Resolve binary directory
|
||||||
# readlink -f does not always exist
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR"
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
else
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
NAME=TUSH
|
NAME=TUSH
|
||||||
|
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
# 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 working directory to the location of this script
|
# Resolve binary directory
|
||||||
# readlink -f does not always exist
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR"
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
else
|
||||||
cd $DIR
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
# ./hushd -ac_name=TUSH -ac_private=1 -gen=1 -testnode=1
|
# ./hushd -ac_name=TUSH -ac_private=1 -gen=1 -testnode=1
|
||||||
./hushd -ac_name=TUSH -ac_private=1 -ac_supply=55555
|
./hushd -ac_name=TUSH -ac_private=1 -ac_supply=55555
|
||||||
18
contrib/scripts/zush
Executable file
18
contrib/scripts/zush
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright (c) 2016-2024 The Hush developers
|
||||||
|
|
||||||
|
# Resolve binary directory
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -f "$SCRIPTDIR/hush-cli" ] || [ -f "$SCRIPTDIR/hushd" ]; then
|
||||||
|
BINDIR="$SCRIPTDIR"
|
||||||
|
else
|
||||||
|
BINDIR="$SCRIPTDIR/../../src"
|
||||||
|
fi
|
||||||
|
cd "$BINDIR"
|
||||||
|
|
||||||
|
NAME=ZUSH
|
||||||
|
|
||||||
|
CLI=${HUSHCLI:-./hush-cli}
|
||||||
|
if [ -f $CLI ]; then
|
||||||
|
$CLI -ac_name=$NAME "$@"
|
||||||
|
fi
|
||||||
@@ -19,7 +19,7 @@ with `t1` and now they begin with `R`.
|
|||||||
To see what an old HUSH v2 address looks like on the new chain, this online tool
|
To see what an old HUSH v2 address looks like on the new chain, this online tool
|
||||||
can be used: https://dexstats.info/addressconverter.php
|
can be used: https://dexstats.info/addressconverter.php
|
||||||
|
|
||||||
or this command line tool: https://git.hush.is/hush/hush3/src/master/contrib/convert_address.py
|
or this command line tool: https://git.hush.is/hush/hush3/src/master/contrib/scripts/convert_address.py
|
||||||
|
|
||||||
|
|
||||||
### Using an old wallet.dat
|
### Using an old wallet.dat
|
||||||
|
|||||||
137
doc/codebase-cleanup.md
Normal file
137
doc/codebase-cleanup.md
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# Codebase Cleanup & Organization Options
|
||||||
|
|
||||||
|
## 1. Remove Build Artifacts from the Working Tree
|
||||||
|
|
||||||
|
The `depends/` directory alone is **1.8 GB**, with 479M in `depends/sources/`, 302M in `depends/built/`. The `release/` dir is 395M, and `repos/` is 164M. While `release/` and `repos/` are already in `.gitignore`, the `depends/built/` and `depends/work/` outputs are not explicitly ignored.
|
||||||
|
|
||||||
|
**Actions:**
|
||||||
|
- [x] Add `depends/built/`, `depends/work/`, `depends/x86_64-w64-mingw32/` to `.gitignore`
|
||||||
|
- [ ] Run `git clean -fdx` on build output directories periodically
|
||||||
|
- [ ] The `.o` and `.a` files in `src/` (e.g., 22M `libbitcoin_server.a`) are build outputs cluttering the source tree
|
||||||
|
|
||||||
|
## 2. Move Large Binary Params Out of Git History
|
||||||
|
|
||||||
|
`sapling-spend.params` (46M) and `sapling-output.params` (3.5M) are committed directly. These are cryptographic proving keys from the Zcash Sapling trusted setup ceremony and **cannot be regenerated**. The node shuts down without them.
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
- [ ] Use **Git LFS** to track them instead
|
||||||
|
- [ ] Download them at build/install time via a script (like Zcash's `fetch-params.sh`)
|
||||||
|
- [x] Keep as-is (current deliberate design choice — guarantees out-of-box operation)
|
||||||
|
|
||||||
|
## 3. Clean Up Tracked Editor/Autoconf Backup Files
|
||||||
|
|
||||||
|
`src/univalue/configure~` is a tracked backup file. The root `configure~` also exists. These should be removed from tracking and the `.gitignore` pattern `*~` should catch them going forward.
|
||||||
|
|
||||||
|
- [x] Remove `src/univalue/configure~` from git tracking
|
||||||
|
|
||||||
|
## 4. Split Monolithic Source Files
|
||||||
|
|
||||||
|
Several files are extremely large and would benefit from decomposition:
|
||||||
|
|
||||||
|
| File | Lines | Suggestion |
|
||||||
|
|------|-------|------------|
|
||||||
|
| `src/main.cpp` | 8,217 | Split validation, block processing, mempool logic into separate files |
|
||||||
|
| `src/wallet/rpcwallet.cpp` | 6,392 | Group RPC methods by category (send, receive, list, z-operations) |
|
||||||
|
| `src/chainparams.cpp` | 5,420 | Extract checkpoint data and chain-specific params to separate files |
|
||||||
|
| `src/wallet/wallet.cpp` | 5,059 | Split wallet transaction logic from key management |
|
||||||
|
|
||||||
|
- [x] Split `src/main.cpp`
|
||||||
|
- 8,217 → 2,821 lines in `main.cpp`
|
||||||
|
- Created `tx_validation.cpp` (1,012 lines) — transaction validation (IsStandardTx, CheckTransaction, ContextualCheckInputs, etc.)
|
||||||
|
- Created `mempool_accept.cpp` (524 lines) — mempool acceptance and orphan management (AcceptToMemoryPool, AddOrphanTx, etc.)
|
||||||
|
- Created `block_processing.cpp` (4,064 lines) — block processing, chain management, and disk I/O (ConnectBlock, DisconnectBlock, ActivateBestChain, CheckBlock, LoadBlockIndex, etc.)
|
||||||
|
- Created `main_internal.h` (83 lines) — shared internal state (block index candidates, file info, dirty sets, etc.)
|
||||||
|
- [x] Split `src/wallet/rpcwallet.cpp`
|
||||||
|
- 6,392 → 4,099 lines in `rpcwallet.cpp`
|
||||||
|
- Created `wallet/rpcwallet_zindex.cpp` (1,193 lines) — z-index query RPCs (`getalldata`, `z_getinfo`, `z_getstats`, etc.)
|
||||||
|
- Created `wallet/rpcwallet_zops.cpp` (1,194 lines) — shielded async operation RPCs (`z_sendmany`, `z_shieldcoinbase`, `z_mergetoaddress`, etc.)
|
||||||
|
- Created `wallet/rpcwallet_internal.h` (45 lines) — shared declarations and `THROW_IF_SYNCING` macro
|
||||||
|
- [x] Split `src/chainparams.cpp`
|
||||||
|
- 5,420 → 593 lines in `chainparams.cpp`
|
||||||
|
- Created `chainparams_checkpoints_hush3.h` (1,986 lines) — HUSH3 checkpoint data
|
||||||
|
- Created `chainparams_checkpoints_dragonx.h` (2,853 lines) — DRAGONX checkpoint data
|
||||||
|
- [x] Split `src/wallet/wallet.cpp`
|
||||||
|
- 5,059 → 4,143 lines in `wallet.cpp`
|
||||||
|
- Created `wallet_keys.cpp` (975 lines) — key management, encryption, HD seed, keypool
|
||||||
|
|
||||||
|
## 5. Move Implementation Out of Header Files
|
||||||
|
|
||||||
|
There are **13,652 lines** of implementation code in `hush_*.h` headers:
|
||||||
|
|
||||||
|
| Header | Lines |
|
||||||
|
|--------|-------|
|
||||||
|
| `src/hush_utils.h` | 2,549 |
|
||||||
|
| `src/hush_gateway.h` | 2,531 |
|
||||||
|
| `src/hush_bitcoind.h` | 1,867 |
|
||||||
|
| `src/hush_curve25519.h` | 1,017 |
|
||||||
|
| `src/hush_nSPV_superlite.h` | 977 |
|
||||||
|
| `src/hush_nSPV_fullnode.h` | 914 |
|
||||||
|
| `src/hush_defs.h` | 656 |
|
||||||
|
| `src/hush_nSPV.h` | 603 |
|
||||||
|
| `src/hush_nSPV_wallet.h` | 505 |
|
||||||
|
| `src/hush_notary.h` | 469 |
|
||||||
|
| `src/hush_globals.h` | 360 |
|
||||||
|
| `src/hush_ccdata.h` | 272 |
|
||||||
|
| `src/hush_kv.h` | 204 |
|
||||||
|
| `src/hush_nSPV_defs.h` | 193 |
|
||||||
|
|
||||||
|
- [x] Move implementations from `hush_*.h` headers to `.cpp` files
|
||||||
|
- Created `src/hush_impl.cpp` — compiles all hush_*.h implementation via `HUSH_PRIVATE_IMPLEMENTATION` guard
|
||||||
|
- Created `src/hush_nSPV_impl.cpp` — compiles all hush_nSPV_*.h implementation
|
||||||
|
- Modified `src/hush.h` with `#ifdef HUSH_PRIVATE_IMPLEMENTATION` to separate implementation from declarations
|
||||||
|
- `main.cpp` now includes declarations only (no longer a unity build for hush code)
|
||||||
|
|
||||||
|
## 6. Deduplicate Vendored Code
|
||||||
|
|
||||||
|
`cJSON` has been consolidated:
|
||||||
|
|
||||||
|
- `src/cJSON.c` + `src/cJSON.h` — canonical implementation, compiled as a standalone C translation unit
|
||||||
|
- `src/hush_cJSON.cpp` + `src/hush_cJSON.h` — helper/wrapper functions, compiled as a standalone C++ translation unit
|
||||||
|
- `src/cc/includes/cJSON.h` — thin redirect to the canonical headers above
|
||||||
|
- `src/cc/dapps/cJSON.c` — deleted (old 2009 fork); dapp includes updated to use canonical copy
|
||||||
|
|
||||||
|
- [x] Consolidate to a single copy and have other modules link against it
|
||||||
|
|
||||||
|
## 7. Relocate Shell Scripts Out of `src/`
|
||||||
|
|
||||||
|
There are **15+ shell scripts and .bat files** tracked inside `src/`:
|
||||||
|
|
||||||
|
- `dragonx-cli`, `dragonxd`, `tush-cli`, `tushd`, `zush`
|
||||||
|
- `smartchains`, `purge`, `listassetchains`, `listassetchainparams`
|
||||||
|
- `testdragonx-cli`, `testdragonxd`, `testequihash-cli`, `testequihashd`
|
||||||
|
- `assetchains_stop`, `hush-arrakis-chain`
|
||||||
|
- `.bat` variants: `dragonx-cli.bat`, `dragonxd.bat`, `hush-arrakis-chain.bat`
|
||||||
|
|
||||||
|
- [x] Move shell scripts to `contrib/scripts/` directory
|
||||||
|
|
||||||
|
## 8. ~~Organize the `repos/` Directory~~ (N/A — `repos/` is gitignored)
|
||||||
|
|
||||||
|
## 9. Improve `.gitignore` Coverage
|
||||||
|
|
||||||
|
The current `.gitignore` has redundant and scattered entries (e.g., `src/cc/dapps/a.out` listed twice, many game-related paths for a rogue game that appears obsolete).
|
||||||
|
|
||||||
|
- [x] Group entries by category (build outputs, editor files, platform-specific)
|
||||||
|
- [x] Remove stale entries for files/features that no longer exist
|
||||||
|
- [x] Add `depends/built/`, `depends/work/`, `depends/x86_64-*/`
|
||||||
|
|
||||||
|
## 10. Consolidate Documentation
|
||||||
|
|
||||||
|
Docs are split across `doc/`, `contrib/README.md`, and the root.
|
||||||
|
|
||||||
|
- [ ] Create a `doc/architecture.md` describing the module structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Priority
|
||||||
|
|
||||||
|
**Highest-impact, lowest-risk changes** (don't touch compiled code):
|
||||||
|
|
||||||
|
1. Items **1, 3, 9** — `.gitignore` cleanup and removing tracked backup files
|
||||||
|
2. Item **7** — relocate scripts out of `src/`
|
||||||
|
|
||||||
|
**Higher-impact, higher-risk changes** (affect build system and code):
|
||||||
|
|
||||||
|
4. Item **5** — move implementation out of headers
|
||||||
|
5. Item **4** — split monolithic source files
|
||||||
|
6. Item **6** — deduplicate cJSON
|
||||||
|
7. Item **2** — ~~Move shell scripts to `contrib/scripts/` directory~~ Done — moved 15 loose scripts from `contrib/` root into `contrib/scripts/`
|
||||||
@@ -96,7 +96,7 @@ For this repo, it's likely this is the command you need:
|
|||||||
gdb src/hushd core
|
gdb src/hushd core
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: Even if you are debugging a coredump on a HAC, such as DragonX, the file `src/dragonxd`
|
NOTE: Even if you are debugging a coredump on a HAC, such as DragonX, the file `contrib/scripts/dragonxd`
|
||||||
is just a shell script that calls `src/hushd` and you always want to give an actual executable
|
is just a shell script that calls `src/hushd` and you always want to give an actual executable
|
||||||
file as the first argument to `gdb`, not a bash script.
|
file as the first argument to `gdb`, not a bash script.
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ The following command can be used to launch an HSC on a single computer. Each op
|
|||||||
HSC CLI arguments that start with `-ac_` means they *Affect Consensus*.
|
HSC CLI arguments that start with `-ac_` means they *Affect Consensus*.
|
||||||
|
|
||||||
```
|
```
|
||||||
./src/hush-arrakis-chain -ac_halving=100 -ac_algo=randomx -ac_name=RANDOMX -ac_private=1 -ac_blocktime=15 -ac_reward=500000000 -ac_supply=55555 -gen=1 -genproclimit=1 -testnode=1
|
./contrib/scripts/hush-arrakis-chain -ac_halving=100 -ac_algo=randomx -ac_name=RANDOMX -ac_private=1 -ac_blocktime=15 -ac_reward=500000000 -ac_supply=55555 -gen=1 -genproclimit=1 -testnode=1
|
||||||
```
|
```
|
||||||
|
|
||||||
* `hush-arrakis-chain` is the script used to launch or connect to HSCs
|
* `hush-arrakis-chain` is the script used to launch or connect to HSCs
|
||||||
* It lives in the `./src` directory, next to `hushd` and `hush-cli`
|
* It lives in the `./contrib/scripts` directory
|
||||||
* It is called `hush-arrakis-chain.bat` on Windows
|
* It is called `hush-arrakis-chain.bat` on Windows
|
||||||
* `-ac_halving=100` means "the block reward halves every 100 blocks"
|
* `-ac_halving=100` means "the block reward halves every 100 blocks"
|
||||||
* `-ac_algo=randomx` means "use RandomX for Proof-Of-Work
|
* `-ac_algo=randomx` means "use RandomX for Proof-Of-Work
|
||||||
@@ -41,12 +41,12 @@ HSC CLI arguments that start with `-ac_` means they *Affect Consensus*.
|
|||||||
* One node would use
|
* One node would use
|
||||||
```
|
```
|
||||||
# first node
|
# first node
|
||||||
./src/hush-arrakis-chain -ac_halving=100 -ac_algo=randomx -ac_name=RANDOMX -ac_private=1 -ac_blocktime=15 -ac_reward=500000000 -ac_supply=55555
|
./contrib/scripts/hush-arrakis-chain -ac_halving=100 -ac_algo=randomx -ac_name=RANDOMX -ac_private=1 -ac_blocktime=15 -ac_reward=500000000 -ac_supply=55555
|
||||||
```
|
```
|
||||||
* And the second node would use:
|
* And the second node would use:
|
||||||
```
|
```
|
||||||
# mining node. NOTE: This node will mine the genesis block and pre-mine, if any
|
# mining node. NOTE: This node will mine the genesis block and pre-mine, if any
|
||||||
./src/hush-arrakis-chain -ac_halving=100 -ac_algo=randomx -ac_name=RANDOMX -ac_private=1 -ac_blocktime=15 -ac_reward=500000000 -ac_supply=55555 -gen=1 -genproclimit=1
|
./contrib/scripts/hush-arrakis-chain -ac_halving=100 -ac_algo=randomx -ac_name=RANDOMX -ac_private=1 -ac_blocktime=15 -ac_reward=500000000 -ac_supply=55555 -gen=1 -genproclimit=1
|
||||||
```
|
```
|
||||||
|
|
||||||
# Advanced Options
|
# Advanced Options
|
||||||
|
|||||||
@@ -231,8 +231,8 @@ since it contains various bugfixes and improvements that will benefit busy walle
|
|||||||
* sendmany RPC will now reject transactions that send to taddrs immediately, instead of them being rejected in mempool
|
* sendmany RPC will now reject transactions that send to taddrs immediately, instead of them being rejected in mempool
|
||||||
* Preliminary support for FreeBSD has been added to the Hush build system
|
* Preliminary support for FreeBSD has been added to the Hush build system
|
||||||
* New contrib scripts:
|
* New contrib scripts:
|
||||||
* `contrib/gen-zaddrs.pl` - Generate zaddrs in bulk, defaults to 50
|
* `contrib/scripts/gen-zaddrs.pl` - Generate zaddrs in bulk, defaults to 50
|
||||||
* `contrib/sdl_checkpoints.pl` - Generate SDL checkpoints using `getblockmerkletree`
|
* `contrib/scripts/sdl_checkpoints.pl` - Generate SDL checkpoints using `getblockmerkletree`
|
||||||
* ZeroMQ support has been removed from Hush
|
* ZeroMQ support has been removed from Hush
|
||||||
|
|
||||||
# Hush 3.9.1 "Luciferous Locust"
|
# Hush 3.9.1 "Luciferous Locust"
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ BITCOIN_CORE_H = \
|
|||||||
wallet/crypter.h \
|
wallet/crypter.h \
|
||||||
wallet/db.h \
|
wallet/db.h \
|
||||||
wallet/rpcwallet.h \
|
wallet/rpcwallet.h \
|
||||||
|
wallet/rpcwallet_internal.h \
|
||||||
wallet/rpchushwallet.h \
|
wallet/rpchushwallet.h \
|
||||||
wallet/wallet.h \
|
wallet/wallet.h \
|
||||||
wallet/wallet_ismine.h \
|
wallet/wallet_ismine.h \
|
||||||
@@ -277,7 +278,14 @@ libbitcoin_server_a_SOURCES = \
|
|||||||
i2p.cpp \
|
i2p.cpp \
|
||||||
init.cpp \
|
init.cpp \
|
||||||
dbwrapper.cpp \
|
dbwrapper.cpp \
|
||||||
|
cJSON.c \
|
||||||
|
hush_cJSON.cpp \
|
||||||
|
hush_impl.cpp \
|
||||||
|
hush_nSPV_impl.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
|
tx_validation.cpp \
|
||||||
|
mempool_accept.cpp \
|
||||||
|
block_processing.cpp \
|
||||||
merkleblock.cpp \
|
merkleblock.cpp \
|
||||||
metrics.h \
|
metrics.h \
|
||||||
miner.cpp \
|
miner.cpp \
|
||||||
@@ -322,8 +330,11 @@ libbitcoin_wallet_a_SOURCES = \
|
|||||||
wallet/rpcdump.cpp \
|
wallet/rpcdump.cpp \
|
||||||
cc/CCtx.cpp \
|
cc/CCtx.cpp \
|
||||||
wallet/rpcwallet.cpp \
|
wallet/rpcwallet.cpp \
|
||||||
|
wallet/rpcwallet_zindex.cpp \
|
||||||
|
wallet/rpcwallet_zops.cpp \
|
||||||
wallet/rpchushwallet.cpp \
|
wallet/rpchushwallet.cpp \
|
||||||
wallet/wallet.cpp \
|
wallet/wallet.cpp \
|
||||||
|
wallet/wallet_keys.cpp \
|
||||||
wallet/wallet_ismine.cpp \
|
wallet/wallet_ismine.cpp \
|
||||||
wallet/walletdb.cpp \
|
wallet/walletdb.cpp \
|
||||||
zcash/zip32.cpp \
|
zcash/zip32.cpp \
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2016-2024 The Hush developers
|
|
||||||
set -eo pipefail
|
|
||||||
hush_cli='./hush-cli'
|
|
||||||
|
|
||||||
./listassetchains | while read chain; do
|
|
||||||
$hush_cli --ac_name=$chain stop
|
|
||||||
done
|
|
||||||
|
|
||||||
4064
src/block_processing.cpp
Normal file
4064
src/block_processing.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -50,6 +50,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC visibility pop
|
#pragma GCC visibility pop
|
||||||
|
|||||||
1201
src/cc/dapps/cJSON.c
1201
src/cc/dapps/cJSON.c
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include "cJSON.c"
|
#include "../../cJSON.c"
|
||||||
|
|
||||||
bits256 zeroid;
|
bits256 zeroid;
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ int32_t safecopy(char *dest,char *src,long len)
|
|||||||
//#ifdef STANDALONE
|
//#ifdef STANDALONE
|
||||||
//#include "../hush3/src/hush_cJSON.c"
|
//#include "../hush3/src/hush_cJSON.c"
|
||||||
//#else
|
//#else
|
||||||
#include "../hush_cJSON.c"
|
#include "../../hush_cJSON.cpp"
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
int32_t games_replay(uint64_t seed,int32_t sleeptime);
|
int32_t games_replay(uint64_t seed,int32_t sleeptime);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include "cJSON.c"
|
#include "../../cJSON.c"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NOTE: HUSH nor any Hush Arrakis Chain has any sprout outputs. This code is kept for historical and educational purposes.
|
NOTE: HUSH nor any Hush Arrakis Chain has any sprout outputs. This code is kept for historical and educational purposes.
|
||||||
|
|||||||
@@ -1,255 +1,19 @@
|
|||||||
// 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
|
||||||
/*
|
//
|
||||||
Copyright (c) 2009 Dave Gamble
|
// This header now redirects to the canonical cJSON at src/cJSON.h + src/hush_cJSON.h.
|
||||||
|
// The old duplicate (2009 Dave Gamble fork) has been removed as part of cJSON deduplication.
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
//
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
||||||
* *
|
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef cJSON__ccih
|
#ifndef cJSON__ccih
|
||||||
#define cJSON__ccih
|
#define cJSON__ccih
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "../../cJSON.h"
|
||||||
#include <stdlib.h>
|
#include "../../hush_cJSON.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#include "../crypto777/OS_portable.h"
|
|
||||||
|
|
||||||
|
#ifndef SATOSHIDEN
|
||||||
#define SATOSHIDEN ((uint64_t)100000000L)
|
#define SATOSHIDEN ((uint64_t)100000000L)
|
||||||
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
||||||
#define MAX_JSON_FIELD 4096 // on the big side
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* cJSON Types: */
|
|
||||||
#define cJSON_False 0
|
|
||||||
#define cJSON_True 1
|
|
||||||
#define cJSON_NULL 2
|
|
||||||
#define cJSON_Number 3
|
|
||||||
#define cJSON_String 4
|
|
||||||
#define cJSON_Array 5
|
|
||||||
#define cJSON_Object 6
|
|
||||||
|
|
||||||
#define is_cJSON_Null(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_NULL)
|
|
||||||
#define is_cJSON_Array(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_Array)
|
|
||||||
#define is_cJSON_String(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_String)
|
|
||||||
#define is_cJSON_Number(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_Number)
|
|
||||||
#define is_cJSON_Object(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_Object)
|
|
||||||
#define is_cJSON_True(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_True)
|
|
||||||
#define is_cJSON_False(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_False)
|
|
||||||
|
|
||||||
#define cJSON_IsReference 256
|
|
||||||
|
|
||||||
/* The cJSON structure: */
|
|
||||||
typedef struct cJSON {
|
|
||||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
|
||||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
|
||||||
|
|
||||||
int32_t type; /* The type of the item, as above. */
|
|
||||||
|
|
||||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
|
||||||
int64_t valueint; /* The item's number, if type==cJSON_Number */
|
|
||||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
|
||||||
|
|
||||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
|
||||||
uint32_t cjsonid;
|
|
||||||
} cJSON;
|
|
||||||
|
|
||||||
typedef struct cJSON_Hooks {
|
|
||||||
void *(*malloc_fn)(size_t sz);
|
|
||||||
void (*free_fn)(void *ptr);
|
|
||||||
} cJSON_Hooks;
|
|
||||||
|
|
||||||
/* Supply malloc, realloc and free functions to cJSON */
|
|
||||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
|
||||||
|
|
||||||
|
|
||||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
|
||||||
extern cJSON *cJSON_Parse(const char *value);
|
|
||||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
|
||||||
extern char *cJSON_Print(cJSON *item);
|
|
||||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
|
||||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
|
||||||
/* Delete a cJSON entity and all subentities. */
|
|
||||||
extern void cJSON_Delete(cJSON *c);
|
|
||||||
|
|
||||||
/* Returns the number of items in an array (or object). */
|
|
||||||
extern int cJSON_GetArraySize(cJSON *array);
|
|
||||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
|
||||||
extern cJSON *cJSON_GetArrayItem(cJSON *array,int32_t item);
|
|
||||||
/* Get item "string" from object. Case insensitive. */
|
|
||||||
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
|
|
||||||
|
|
||||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
|
||||||
extern const char *cJSON_GetErrorPtr(void);
|
|
||||||
|
|
||||||
/* These calls create a cJSON item of the appropriate type. */
|
|
||||||
extern cJSON *cJSON_CreateNull(void);
|
|
||||||
extern cJSON *cJSON_CreateTrue(void);
|
|
||||||
extern cJSON *cJSON_CreateFalse(void);
|
|
||||||
extern cJSON *cJSON_CreateBool(int32_t b);
|
|
||||||
extern cJSON *cJSON_CreateNumber(double num);
|
|
||||||
extern cJSON *cJSON_CreateString(const char *string);
|
|
||||||
extern cJSON *cJSON_CreateArray(void);
|
|
||||||
extern cJSON *cJSON_CreateObject(void);
|
|
||||||
|
|
||||||
/* These utilities create an Array of count items. */
|
|
||||||
extern cJSON *cJSON_CreateIntArray(int64_t *numbers,int32_t count);
|
|
||||||
extern cJSON *cJSON_CreateFloatArray(float *numbers,int32_t count);
|
|
||||||
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int32_t count);
|
|
||||||
extern cJSON *cJSON_CreateStringArray(char **strings,int32_t count);
|
|
||||||
|
|
||||||
/* Append item to the specified array/object. */
|
|
||||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
|
||||||
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
|
|
||||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
|
||||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
|
||||||
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
|
|
||||||
|
|
||||||
/* Remove/Detatch items from Arrays/Objects. */
|
|
||||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int32_t which);
|
|
||||||
extern void cJSON_DeleteItemFromArray(cJSON *array,int32_t which);
|
|
||||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
|
||||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
|
||||||
|
|
||||||
/* Update array items. */
|
|
||||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int32_t which,cJSON *newitem);
|
|
||||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
|
||||||
|
|
||||||
/* Duplicate a cJSON item */
|
|
||||||
extern cJSON *cJSON_Duplicate(cJSON *item,int32_t recurse);
|
|
||||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
|
||||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
|
||||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
|
||||||
|
|
||||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
|
||||||
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int32_t require_null_terminated);
|
|
||||||
|
|
||||||
extern void cJSON_Minify(char *json);
|
|
||||||
|
|
||||||
/* Macros for creating things quickly. */
|
|
||||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
|
||||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
|
||||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
|
||||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
|
||||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
|
||||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
|
||||||
|
|
||||||
struct destbuf { char buf[MAX_JSON_FIELD]; };
|
|
||||||
|
|
||||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
|
||||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
|
||||||
#define jfieldstr get_cJSON_fieldname
|
|
||||||
|
|
||||||
char *cJSON_str(cJSON *json);
|
|
||||||
char *jstr(cJSON *json,char *field);
|
|
||||||
char *jprint(cJSON *json,int32_t freeflag);
|
|
||||||
int32_t jint(cJSON *json,char *field);
|
|
||||||
uint32_t juint(cJSON *json,char *field);
|
|
||||||
char *jstri(cJSON *json,int32_t i);
|
|
||||||
int32_t jinti(cJSON *json,int32_t i);
|
|
||||||
uint32_t juinti(cJSON *json,int32_t i);
|
|
||||||
uint64_t j64bitsi(cJSON *json,int32_t i);
|
|
||||||
double jdoublei(cJSON *json,int32_t i);
|
|
||||||
double jdouble(cJSON *json,char *field);
|
|
||||||
cJSON *jobj(cJSON *json,char *field);
|
|
||||||
cJSON *jarray(int32_t *nump,cJSON *json,char *field);
|
|
||||||
cJSON *jitem(cJSON *array,int32_t i);
|
|
||||||
uint64_t j64bits(cJSON *json,char *field);
|
|
||||||
void jadd(cJSON *json,char *field,cJSON *item);
|
|
||||||
void jaddstr(cJSON *json,char *field,char *str);
|
|
||||||
void jaddnum(cJSON *json,char *field,double num);
|
|
||||||
void jadd64bits(cJSON *json,char *field,uint64_t nxt64bits);
|
|
||||||
void jaddi(cJSON *json,cJSON *item);
|
|
||||||
void jaddistr(cJSON *json,char *str);
|
|
||||||
void jaddinum(cJSON *json,double num);
|
|
||||||
void jaddi64bits(cJSON *json,uint64_t nxt64bits);
|
|
||||||
void jdelete(cJSON *object,char *string);
|
|
||||||
cJSON *jduplicate(cJSON *json);
|
|
||||||
int32_t jnum(cJSON *obj,char *field);
|
|
||||||
|
|
||||||
bits256 jbits256(cJSON *json,char *field);
|
|
||||||
bits256 jbits256i(cJSON *json,int32_t i);
|
|
||||||
void jaddbits256(cJSON *json,char *field,bits256 hash);
|
|
||||||
void jaddibits256(cJSON *json,bits256 hash);
|
|
||||||
void copy_cJSON(struct destbuf *dest,cJSON *obj);
|
|
||||||
void copy_cJSON2(char *dest,int32_t maxlen,cJSON *obj);
|
|
||||||
cJSON *gen_list_json(char **list);
|
|
||||||
int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field);
|
|
||||||
|
|
||||||
void free_json(cJSON *json);
|
|
||||||
int64_t _conv_cJSON_float(cJSON *json);
|
|
||||||
int64_t conv_cJSON_float(cJSON *json,char *field);
|
|
||||||
int64_t get_cJSON_int(cJSON *json,char *field);
|
|
||||||
void add_satoshis_json(cJSON *json,char *field,uint64_t satoshis);
|
|
||||||
uint64_t get_satoshi_obj(cJSON *json,char *field);
|
|
||||||
|
|
||||||
int32_t get_API_int(cJSON *obj,int32_t val);
|
|
||||||
uint32_t get_API_uint(cJSON *obj,uint32_t val);
|
|
||||||
uint64_t get_API_nxt64bits(cJSON *obj);
|
|
||||||
double get_API_float(cJSON *obj);
|
|
||||||
char *get_cJSON_fieldname(cJSON *obj);
|
|
||||||
void ensure_jsonitem(cJSON *json,char *field,char *value);
|
|
||||||
int32_t in_jsonarray(cJSON *array,char *value);
|
|
||||||
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout);
|
|
||||||
uint64_t calc_nxt64bits(const char *str);
|
|
||||||
int32_t expand_nxt64bits(char *str,uint64_t nxt64bits);
|
|
||||||
char *nxt64str(uint64_t nxt64bits);
|
|
||||||
char *nxt64str2(uint64_t nxt64bits);
|
|
||||||
cJSON *addrs_jsonarray(uint64_t *addrs,int32_t num);
|
|
||||||
int32_t myatoi(char *str,int32_t range);
|
|
||||||
void cJSON_register(cJSON *item);
|
|
||||||
void cJSON_unregister(cJSON *item);
|
|
||||||
|
|
||||||
char *stringifyM(char *str);
|
|
||||||
#define replace_backslashquotes unstringify
|
|
||||||
char *unstringify(char *str);
|
|
||||||
#define jtrue cJSON_CreateTrue
|
|
||||||
#define jfalse cJSON_CreateFalse
|
|
||||||
|
|
||||||
#define jfieldname get_cJSON_fieldname
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
3597
src/chainparams.cpp
3597
src/chainparams.cpp
File diff suppressed because it is too large
Load Diff
2853
src/chainparams_checkpoints_dragonx.h
Normal file
2853
src/chainparams_checkpoints_dragonx.h
Normal file
File diff suppressed because it is too large
Load Diff
1986
src/chainparams_checkpoints_hush3.h
Normal file
1986
src/chainparams_checkpoints_hush3.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright 2016-2024 The Hush Developers
|
|
||||||
# Copyright 2022 The DragonX Developers
|
|
||||||
# Released under the GPLv3
|
|
||||||
|
|
||||||
# set working directory to the location of this script
|
|
||||||
# readlink -f does not always exist
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
|
|
||||||
./hush-cli -ac_name=DRAGONX "$@"
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2016-2024 The Hush developers
|
|
||||||
# set working directory to the location of this script
|
|
||||||
# readlink -f does not always exist
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
|
|
||||||
DEFAULTS=""
|
|
||||||
|
|
||||||
# People can just use hushd going forward, but this script makes it
|
|
||||||
# more clear what is going on
|
|
||||||
HUSH="./hushd"
|
|
||||||
$HUSH $DEFAULTS "$@"
|
|
||||||
169
src/hush.h
169
src/hush.h
@@ -27,6 +27,12 @@
|
|||||||
#define HUSH_SMART_CHAINS_WAITNOTARIZE
|
#define HUSH_SMART_CHAINS_WAITNOTARIZE
|
||||||
#define HUSH_PAXMAX (10000 * COIN)
|
#define HUSH_PAXMAX (10000 * COIN)
|
||||||
extern int32_t NOTARIZED_HEIGHT;
|
extern int32_t NOTARIZED_HEIGHT;
|
||||||
|
|
||||||
|
#ifdef HUSH_PRIVATE_IMPLEMENTATION
|
||||||
|
// ===================================================================
|
||||||
|
// Full implementation mode — only compiled via hush_impl.cpp
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID;
|
uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID;
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -45,7 +51,7 @@ bool check_pprevnotarizedht();
|
|||||||
#include "hush_globals.h"
|
#include "hush_globals.h"
|
||||||
#include "hush_utils.h"
|
#include "hush_utils.h"
|
||||||
#include "hush_curve25519.h"
|
#include "hush_curve25519.h"
|
||||||
#include "hush_cJSON.c"
|
#include "hush_cJSON.h"
|
||||||
#include "hush_bitcoind.h"
|
#include "hush_bitcoind.h"
|
||||||
#include "hush_pax.h"
|
#include "hush_pax.h"
|
||||||
#include "hush_notary.h"
|
#include "hush_notary.h"
|
||||||
@@ -56,6 +62,9 @@ int32_t hush_parsestatefile(struct hush_state *sp,FILE *fp,char *symbol,char *de
|
|||||||
#include "hush_events.h"
|
#include "hush_events.h"
|
||||||
#include "hush_ccdata.h"
|
#include "hush_ccdata.h"
|
||||||
|
|
||||||
|
// Need NSPV struct definitions for hush_currentheight() below
|
||||||
|
#include "hush_nSPV_defs.h"
|
||||||
|
|
||||||
void hush_currentheight_set(int32_t height)
|
void hush_currentheight_set(int32_t height)
|
||||||
{
|
{
|
||||||
char symbol[HUSH_SMART_CHAIN_MAXLEN],dest[HUSH_SMART_CHAIN_MAXLEN]; struct hush_state *sp;
|
char symbol[HUSH_SMART_CHAIN_MAXLEN],dest[HUSH_SMART_CHAIN_MAXLEN]; struct hush_state *sp;
|
||||||
@@ -980,4 +989,162 @@ int32_t hush_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
// ===================================================================
|
||||||
|
// Declarations-only mode — for files that call hush functions
|
||||||
|
// This provides type info and function declarations without pulling
|
||||||
|
// in 14,000+ lines of implementation code.
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
extern uint256 NOTARIZED_HASH, NOTARIZED_DESTTXID;
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// Struct/type declarations from hush_structs.h
|
||||||
|
#include "hush_structs.h"
|
||||||
|
|
||||||
|
// nSPV type definitions and forward declarations
|
||||||
|
#include "hush_nSPV_defs.h"
|
||||||
|
|
||||||
|
// Extern globals defined in hush_globals.h but missing from hush_defs.h
|
||||||
|
extern uint8_t ASSETCHAINS_BURN;
|
||||||
|
extern uint32_t ASSETCHAINS_MINOPRETURNFEE;
|
||||||
|
extern uint32_t HUSH_STOPAT;
|
||||||
|
extern int32_t HUSH_REWIND;
|
||||||
|
|
||||||
|
// Macros from implementation headers needed by callers
|
||||||
|
#define BURN_ADDRESS "RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY"
|
||||||
|
#ifndef SATOSHIDEN
|
||||||
|
#define SATOSHIDEN ((uint64_t)100000000L)
|
||||||
|
#endif
|
||||||
|
#ifndef dstr
|
||||||
|
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
||||||
|
#endif
|
||||||
|
#define HUSH_NOTARIES_HEIGHT1 814000
|
||||||
|
|
||||||
|
// Forward declarations — hush.h implementation functions
|
||||||
|
void hush_currentheight_set(int32_t height);
|
||||||
|
int32_t hush_currentheight();
|
||||||
|
int32_t hush_parsestatefile(struct hush_state *sp,FILE *fp,char *symbol,char *dest);
|
||||||
|
int32_t hush_parsestatefiledata(struct hush_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest);
|
||||||
|
int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen);
|
||||||
|
void hush_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t HUSHheight,uint32_t HUSHtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth);
|
||||||
|
int32_t hush_validate_chain(uint256 srchash,int32_t notarized_height);
|
||||||
|
int32_t hush_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp);
|
||||||
|
int32_t hush_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]);
|
||||||
|
int32_t hush_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block);
|
||||||
|
|
||||||
|
// Forward declarations — hush_globals.h functions
|
||||||
|
int32_t hush_baseid(char *origbase);
|
||||||
|
uint64_t hush_current_supply(uint32_t nHeight);
|
||||||
|
std::string devtax_scriptpub_for_height(uint32_t nHeight);
|
||||||
|
std::string devtax_address_for_height(uint32_t nHeight);
|
||||||
|
|
||||||
|
// Forward declarations — hush_utils.h functions
|
||||||
|
void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
|
||||||
|
bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen);
|
||||||
|
void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len);
|
||||||
|
uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size);
|
||||||
|
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen);
|
||||||
|
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr);
|
||||||
|
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
|
||||||
|
int32_t hush_is_issuer();
|
||||||
|
int32_t bitweight(uint64_t x);
|
||||||
|
int32_t _unhex(char c);
|
||||||
|
int32_t is_hexstr(char *str,int32_t n);
|
||||||
|
int32_t unhex(char c);
|
||||||
|
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
|
||||||
|
char hexbyte(int32_t c);
|
||||||
|
int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len);
|
||||||
|
char *bits256_str(char hexstr[65],bits256 x);
|
||||||
|
int32_t dragon_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp);
|
||||||
|
int32_t dragon_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp);
|
||||||
|
int32_t hush_scriptitemlen(int32_t *opretlenp,uint8_t *script);
|
||||||
|
uint64_t hush_block_prg(uint32_t nHeight);
|
||||||
|
int64_t hush_block_unlocktime(uint32_t nHeight);
|
||||||
|
long _stripwhite(char *buf,int accept);
|
||||||
|
char *clonestr(char *str);
|
||||||
|
int32_t safecopy(char *dest,char *src,long len);
|
||||||
|
char *parse_conf_line(char *line,char *field);
|
||||||
|
double OS_milliseconds();
|
||||||
|
void OS_randombytes(unsigned char *x,long xlen);
|
||||||
|
uint16_t _hush_userpass(char *username,char *password,FILE *fp);
|
||||||
|
void hush_statefname(char *fname,char *symbol,char *str);
|
||||||
|
void hush_configfile(char *symbol,uint16_t rpcport);
|
||||||
|
uint16_t hush_userpass(char *userpass,char *symbol);
|
||||||
|
uint32_t hush_smartmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen);
|
||||||
|
uint16_t hush_smartport(uint32_t magic,int32_t extralen);
|
||||||
|
uint16_t hush_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extraptr,int32_t extralen);
|
||||||
|
int32_t hush_whoami(char *pubkeystr,int32_t height,uint32_t timestamp);
|
||||||
|
uint64_t hush_max_money();
|
||||||
|
uint64_t hush_block_subsidy(int height);
|
||||||
|
uint64_t hush_sc_block_subsidy(int nHeight);
|
||||||
|
int8_t equihash_params_possible(uint64_t n, uint64_t k);
|
||||||
|
void hush_args(char *argv0);
|
||||||
|
void hush_nameset(char *symbol,char *dest,char *source);
|
||||||
|
void hush_prefetch(FILE *fp);
|
||||||
|
|
||||||
|
// Forward declarations — hush_bitcoind.h functions
|
||||||
|
struct hush_state *hush_stateptr(char *symbol,char *dest);
|
||||||
|
void hush_init(int32_t height);
|
||||||
|
int32_t hush_faststateinit(struct hush_state *sp,char *fname,char *symbol,char *dest);
|
||||||
|
int32_t hush_isrealtime(int32_t *hushheightp);
|
||||||
|
int32_t hush_longestchain();
|
||||||
|
uint64_t hush_paxtotal();
|
||||||
|
int32_t hush_block2height(CBlock *block);
|
||||||
|
int32_t hush_block2pubkey33(uint8_t *pubkey33,CBlock *block);
|
||||||
|
int32_t hush_blockload(CBlock& block, CBlockIndex *pindex);
|
||||||
|
CBlockIndex *hush_chainactive(int32_t height);
|
||||||
|
CBlockIndex *hush_getblockindex(uint256 hash);
|
||||||
|
uint32_t hush_chainactive_timestamp();
|
||||||
|
char *hush_issuemethod(char *userpass,char *method,char *params,uint16_t port);
|
||||||
|
int32_t hush_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
|
||||||
|
int32_t hush_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
|
||||||
|
bool hush_hardfork_active(uint32_t time);
|
||||||
|
|
||||||
|
// Forward declarations — hush_pax.h functions
|
||||||
|
void hush_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t len);
|
||||||
|
|
||||||
|
// Forward declarations — hush_notary.h functions
|
||||||
|
int32_t hush_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp);
|
||||||
|
int32_t hush_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *hushtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *hushstartip,int32_t *hushendip);
|
||||||
|
int32_t hush_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp);
|
||||||
|
|
||||||
|
// Forward declarations — hush_gateway.h functions
|
||||||
|
int32_t hush_isPoS(CBlock *pblock,int32_t height,bool fJustCheck);
|
||||||
|
int32_t hush_checkPOW(int64_t stakeTxValue, int32_t slowflag, CBlock *pblock, int32_t height);
|
||||||
|
void hush_passport_iteration();
|
||||||
|
int32_t hush_opretvalidate(const CBlock *block,CBlockIndex *previndex,int32_t height,CScript scriptPubKey);
|
||||||
|
int32_t hush_scpublic(uint32_t tiptime);
|
||||||
|
int32_t hush_checknotarypay(CBlock *pblock,int32_t height);
|
||||||
|
int32_t hush_checkpoint(int32_t *notarized_heightp, int32_t nHeight, uint256 hash);
|
||||||
|
|
||||||
|
// Forward declarations — hush_bitcoind.h additional functions
|
||||||
|
uint64_t the_commission(const CBlock *pblock, int32_t height);
|
||||||
|
|
||||||
|
// Forward declarations — hush_events.h functions
|
||||||
|
void hush_eventadd_pubkeys(struct hush_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]);
|
||||||
|
void hush_eventadd_pricefeed(struct hush_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num);
|
||||||
|
void hush_eventadd_opreturn(struct hush_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t len);
|
||||||
|
void hush_eventadd_notarized(struct hush_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth);
|
||||||
|
void hush_eventadd_hushheight(struct hush_state *sp,char *symbol,int32_t height,int32_t hushheight,uint32_t timestamp);
|
||||||
|
void hush_event_rewind(struct hush_state *sp,char *symbol,int32_t height);
|
||||||
|
|
||||||
|
// Forward declarations — hush_ccdata.h functions
|
||||||
|
void hush_rwccdata(char *symbol,int32_t rwflag,struct hush_ccdata *ccdata,struct hush_ccdataMoMoM *MoMoMdata);
|
||||||
|
void hush_purge_ccdata(int32_t height);
|
||||||
|
|
||||||
|
// Forward declarations — hush_kv.h / other
|
||||||
|
int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n);
|
||||||
|
bool check_pprevnotarizedht();
|
||||||
|
|
||||||
|
// Forward declarations — nSPV functions (defined in hush_nSPV_*.h, compiled in hush_nSPV_impl.cpp)
|
||||||
|
void hush_nSPVreq(CNode *pfrom,std::vector<uint8_t> request);
|
||||||
|
void hush_nSPVresp(CNode *pfrom,std::vector<uint8_t> response);
|
||||||
|
void hush_nSPV(CNode *pto);
|
||||||
|
|
||||||
|
#endif // HUSH_PRIVATE_IMPLEMENTATION
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,10 +25,21 @@
|
|||||||
/* cJSON */
|
/* cJSON */
|
||||||
/* JSON parser in C. */
|
/* JSON parser in C. */
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "hush_cJSON.h"
|
#include "hush_cJSON.h"
|
||||||
#include "cJSON.c"
|
|
||||||
|
// External dependencies (defined in hush_utils.h, compiled in hush_impl.cpp)
|
||||||
|
#ifndef SATOSHIDEN
|
||||||
|
#define SATOSHIDEN ((uint64_t)100000000L)
|
||||||
|
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
||||||
|
#endif
|
||||||
|
long _stripwhite(char *buf, int accept);
|
||||||
|
char *clonestr(char *str);
|
||||||
|
int32_t decode_hex(uint8_t *bytes, int32_t n, char *hex);
|
||||||
|
char *bits256_str(char hexstr[65], bits256 x);
|
||||||
|
int32_t safecopy(char *dest, char *src, long len);
|
||||||
|
|
||||||
#ifndef DBL_EPSILON
|
#ifndef DBL_EPSILON
|
||||||
#define DBL_EPSILON 2.2204460492503131E-16
|
#define DBL_EPSILON 2.2204460492503131E-16
|
||||||
29
src/hush_impl.cpp
Normal file
29
src/hush_impl.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// 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
|
||||||
|
//
|
||||||
|
// hush_impl.cpp — Compilation unit for all hush_*.h implementation code.
|
||||||
|
//
|
||||||
|
// Previously, the hush implementation headers were #included directly
|
||||||
|
// into main.cpp (a "unity build" pattern), making main.o enormous and
|
||||||
|
// coupling everything into one translation unit. This file replaces
|
||||||
|
// that pattern: it includes hush.h with HUSH_PRIVATE_IMPLEMENTATION
|
||||||
|
// defined, which pulls in all the implementation headers and compiles
|
||||||
|
// them as a separate object file (hush_impl.o).
|
||||||
|
//
|
||||||
|
// main.cpp now includes hush.h WITHOUT HUSH_PRIVATE_IMPLEMENTATION,
|
||||||
|
// receiving only forward declarations.
|
||||||
|
|
||||||
|
// Standard project headers needed by hush implementation code
|
||||||
|
#include "main.h"
|
||||||
|
#include "notarizationdb.h"
|
||||||
|
#include "init.h"
|
||||||
|
#include "txdb.h"
|
||||||
|
#include "hush_nSPV_defs.h"
|
||||||
|
#include "wallet/asyncrpcoperation_sendmany.h"
|
||||||
|
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
|
||||||
|
|
||||||
|
// Enable full implementation mode and HUSH_ZCASH compatibility flag
|
||||||
|
#define HUSH_PRIVATE_IMPLEMENTATION
|
||||||
|
#define HUSH_ZCASH
|
||||||
|
#include "hush.h"
|
||||||
38
src/hush_nSPV_impl.cpp
Normal file
38
src/hush_nSPV_impl.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// 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
|
||||||
|
//
|
||||||
|
// hush_nSPV_impl.cpp — Compilation unit for nSPV (simplified payment
|
||||||
|
// verification) implementation headers.
|
||||||
|
//
|
||||||
|
// Previously, the nSPV implementation headers were #included directly
|
||||||
|
// into main.cpp after hush.h. This file replaces that pattern by
|
||||||
|
// compiling them as a separate object (hush_nSPV_impl.o).
|
||||||
|
|
||||||
|
// Standard project headers needed by nSPV code
|
||||||
|
#include "main.h"
|
||||||
|
#include "notarizationdb.h"
|
||||||
|
#include "rpc/server.h"
|
||||||
|
#include "init.h"
|
||||||
|
#include "txdb.h"
|
||||||
|
#include "core_io.h"
|
||||||
|
#include "key_io.h"
|
||||||
|
#include "merkleblock.h"
|
||||||
|
#include "script/sign.h"
|
||||||
|
#include "cc/CCinclude.h"
|
||||||
|
#include "wallet/asyncrpcoperation_sendmany.h"
|
||||||
|
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
|
||||||
|
|
||||||
|
// Forward declare functions defined in other compilation units
|
||||||
|
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
|
||||||
|
|
||||||
|
// hush.h in declarations-only mode gives us hush function declarations
|
||||||
|
// that nSPV code calls (dragon_rwnum, dragon_rwbignum, hush_notarized_height, etc.)
|
||||||
|
#include "hush.h"
|
||||||
|
|
||||||
|
// nSPV implementation headers — defines, structs, serialization, then fullnode/superlite/wallet
|
||||||
|
#include "hush_nSPV_defs.h"
|
||||||
|
#include "hush_nSPV.h"
|
||||||
|
#include "hush_nSPV_fullnode.h"
|
||||||
|
#include "hush_nSPV_superlite.h"
|
||||||
|
#include "hush_nSPV_wallet.h"
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env python2
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
|
|
||||||
script_dir = os.path.dirname(__file__)
|
|
||||||
with open(script_dir + '/assetchains.json') as file:
|
|
||||||
assetchains = json.load(file)
|
|
||||||
|
|
||||||
for chain in assetchains:
|
|
||||||
print(chain['ac_name'])
|
|
||||||
5596
src/main.cpp
5596
src/main.cpp
File diff suppressed because it is too large
Load Diff
10
src/main.h
10
src/main.h
@@ -289,6 +289,14 @@ void PruneAndFlush();
|
|||||||
/** (try to) add transaction to memory pool **/
|
/** (try to) add transaction to memory pool **/
|
||||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||||
bool* pfMissingInputs, bool fRejectAbsurdFee=false, int dosLevel=-1);
|
bool* pfMissingInputs, bool fRejectAbsurdFee=false, int dosLevel=-1);
|
||||||
|
bool CCTxFixAcceptToMemPoolUnchecked(CTxMemPool& pool, const CTransaction &tx);
|
||||||
|
bool myAddtomempool(CTransaction &tx, CValidationState *pstate, bool fSkipExpiry);
|
||||||
|
|
||||||
|
/** Orphan transaction management */
|
||||||
|
bool AddOrphanTx(const CTransaction& tx, NodeId peer);
|
||||||
|
void EraseOrphanTx(uint256 hash);
|
||||||
|
void EraseOrphansFor(NodeId peer);
|
||||||
|
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
|
||||||
|
|
||||||
|
|
||||||
struct CNodeStateStats {
|
struct CNodeStateStats {
|
||||||
@@ -708,6 +716,8 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde
|
|||||||
bool (*isInitBlockDownload)() = IsInitialBlockDownload,int32_t validateprices=1);
|
bool (*isInitBlockDownload)() = IsInitialBlockDownload,int32_t validateprices=1);
|
||||||
|
|
||||||
/** Apply the effects of this transaction on the UTXO set represented by view */
|
/** Apply the effects of this transaction on the UTXO set represented by view */
|
||||||
|
class CTxUndo;
|
||||||
|
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight);
|
||||||
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
|
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
|
||||||
|
|
||||||
/** Transaction validation functions */
|
/** Transaction validation functions */
|
||||||
|
|||||||
83
src/main_internal.h
Normal file
83
src/main_internal.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Internal shared state for main.cpp and block_processing.cpp
|
||||||
|
// These variables were previously in an anonymous namespace in main.cpp
|
||||||
|
// but need to be shared across translation units after splitting.
|
||||||
|
|
||||||
|
#ifndef HUSH_MAIN_INTERNAL_H
|
||||||
|
#define HUSH_MAIN_INTERNAL_H
|
||||||
|
|
||||||
|
#include "chain.h"
|
||||||
|
#include "sync.h"
|
||||||
|
#include "bloom.h"
|
||||||
|
#include "primitives/block.h"
|
||||||
|
#include "chainparams.h"
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/smart_ptr/scoped_ptr.hpp>
|
||||||
|
|
||||||
|
struct CBlockIndexWorkComparator
|
||||||
|
{
|
||||||
|
bool operator()(CBlockIndex *pa, const CBlockIndex *pb) const {
|
||||||
|
// First sort by most total work, ...
|
||||||
|
|
||||||
|
if (pa->chainPower.chainWork > pb->chainPower.chainWork) return false;
|
||||||
|
if (pa->chainPower.chainWork < pb->chainPower.chainWork) return true;
|
||||||
|
|
||||||
|
// ... then by earliest time received, ...
|
||||||
|
if (pa->nSequenceId < pb->nSequenceId) return false;
|
||||||
|
if (pa->nSequenceId > pb->nSequenceId) return true;
|
||||||
|
|
||||||
|
// Use pointer address as tie breaker (should only happen with blocks
|
||||||
|
// loaded from disk, as those all have id 0).
|
||||||
|
if (pa < pb) return false;
|
||||||
|
if (pa > pb) return true;
|
||||||
|
|
||||||
|
// Identical blocks.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
|
||||||
|
struct QueuedBlock {
|
||||||
|
uint256 hash;
|
||||||
|
CBlockIndex *pindex; //! Optional.
|
||||||
|
int64_t nTime; //! Time of "getdata" request in microseconds.
|
||||||
|
bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
|
||||||
|
int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shared block-processing state — defined in main.cpp
|
||||||
|
extern CBlockIndex *pindexBestInvalid;
|
||||||
|
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
|
||||||
|
extern int nSyncStarted;
|
||||||
|
extern std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
|
||||||
|
|
||||||
|
extern CCriticalSection cs_LastBlockFile;
|
||||||
|
extern std::vector<CBlockFileInfo> vinfoBlockFile, tmpBlockFiles;
|
||||||
|
extern int nLastBlockFile;
|
||||||
|
extern int nLastTmpFile;
|
||||||
|
extern unsigned int maxTempFileSize0;
|
||||||
|
extern unsigned int maxTempFileSize1;
|
||||||
|
extern bool fCheckForPruning;
|
||||||
|
|
||||||
|
extern CCriticalSection cs_nBlockSequenceId;
|
||||||
|
extern uint32_t nBlockSequenceId;
|
||||||
|
|
||||||
|
extern std::map<uint256, NodeId> mapBlockSource;
|
||||||
|
|
||||||
|
extern boost::scoped_ptr<CRollingBloomFilter> recentRejects;
|
||||||
|
extern uint256 hashRecentRejectsChainTip;
|
||||||
|
|
||||||
|
extern std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> > mapBlocksInFlight;
|
||||||
|
extern int nQueuedValidatedHeaders;
|
||||||
|
extern int nPreferredDownload;
|
||||||
|
|
||||||
|
extern std::set<CBlockIndex*> setDirtyBlockIndex;
|
||||||
|
extern std::set<int> setDirtyFileInfo;
|
||||||
|
|
||||||
|
#endif // HUSH_MAIN_INTERNAL_H
|
||||||
524
src/mempool_accept.cpp
Normal file
524
src/mempool_accept.cpp
Normal file
@@ -0,0 +1,524 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Mempool acceptance and orphan transaction management — extracted from main.cpp
|
||||||
|
// Functions: AddOrphanTx, EraseOrphanTx, EraseOrphansFor, LimitOrphanTxSize,
|
||||||
|
// GetMinRelayFee, AcceptToMemoryPool, CCTxFixAcceptToMemPoolUnchecked, myAddtomempool
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "sodium.h"
|
||||||
|
#include "arith_uint256.h"
|
||||||
|
#include "chainparams.h"
|
||||||
|
#include "consensus/upgrades.h"
|
||||||
|
#include "consensus/validation.h"
|
||||||
|
#include "core_io.h"
|
||||||
|
#include "init.h"
|
||||||
|
#include "key_io.h"
|
||||||
|
#include "metrics.h"
|
||||||
|
#include "net.h"
|
||||||
|
#include "script/interpreter.h"
|
||||||
|
#include "timedata.h"
|
||||||
|
#include "txdb.h"
|
||||||
|
#include "txmempool.h"
|
||||||
|
#include "undo.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "utilmoneystr.h"
|
||||||
|
#include "validationinterface.h"
|
||||||
|
#include "hush_defs.h"
|
||||||
|
#include "hush.h"
|
||||||
|
|
||||||
|
#include "librustzcash.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
extern int32_t HUSH_LOADINGBLOCKS,HUSH_LONGESTCHAIN,HUSH_INSYNC,HUSH_CONNECTING,HUSH_EXTRASATOSHI;
|
||||||
|
extern unsigned int expiryDelta;
|
||||||
|
extern CFeeRate minRelayTxFee;
|
||||||
|
extern bool fAddressIndex;
|
||||||
|
extern bool fSpentIndex;
|
||||||
|
extern const bool ishush3;
|
||||||
|
|
||||||
|
#define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000
|
||||||
|
|
||||||
|
// Orphan transaction data — defined in main.cpp
|
||||||
|
struct COrphanTx {
|
||||||
|
CTransaction tx;
|
||||||
|
NodeId fromPeer;
|
||||||
|
};
|
||||||
|
extern map<uint256, COrphanTx> mapOrphanTransactions;
|
||||||
|
extern map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
|
||||||
|
|
||||||
|
bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
|
{
|
||||||
|
uint256 hash = tx.GetHash();
|
||||||
|
if (mapOrphanTransactions.count(hash))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Ignore big transactions, to avoid a
|
||||||
|
// send-big-orphans memory exhaustion attack. If a peer has a legitimate
|
||||||
|
// large transaction with a missing parent then we assume
|
||||||
|
// it will rebroadcast it later, after the parent transaction(s)
|
||||||
|
// have been mined or received.
|
||||||
|
// 10,000 orphans, each of which is at most 5,000 bytes big is
|
||||||
|
// at most 500 megabytes of orphans:
|
||||||
|
unsigned int sz = GetSerializeSize(tx, SER_NETWORK, tx.nVersion);
|
||||||
|
if (sz > 5000)
|
||||||
|
{
|
||||||
|
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapOrphanTransactions[hash].tx = tx;
|
||||||
|
mapOrphanTransactions[hash].fromPeer = peer;
|
||||||
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
|
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
|
||||||
|
|
||||||
|
LogPrint("mempool", "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(),
|
||||||
|
mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
|
{
|
||||||
|
map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(hash);
|
||||||
|
if (it == mapOrphanTransactions.end())
|
||||||
|
return;
|
||||||
|
BOOST_FOREACH(const CTxIn& txin, it->second.tx.vin)
|
||||||
|
{
|
||||||
|
map<uint256, set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash);
|
||||||
|
if (itPrev == mapOrphanTransactionsByPrev.end())
|
||||||
|
continue;
|
||||||
|
itPrev->second.erase(hash);
|
||||||
|
if (itPrev->second.empty())
|
||||||
|
mapOrphanTransactionsByPrev.erase(itPrev);
|
||||||
|
}
|
||||||
|
mapOrphanTransactions.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EraseOrphansFor(NodeId peer)
|
||||||
|
{
|
||||||
|
int nErased = 0;
|
||||||
|
map<uint256, COrphanTx>::iterator iter = mapOrphanTransactions.begin();
|
||||||
|
while (iter != mapOrphanTransactions.end())
|
||||||
|
{
|
||||||
|
map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
|
||||||
|
if (maybeErase->second.fromPeer == peer)
|
||||||
|
{
|
||||||
|
EraseOrphanTx(maybeErase->second.tx.GetHash());
|
||||||
|
++nErased;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx from peer %d\n", nErased, peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
|
{
|
||||||
|
unsigned int nEvicted = 0;
|
||||||
|
while (mapOrphanTransactions.size() > nMaxOrphans)
|
||||||
|
{
|
||||||
|
// Evict a random orphan:
|
||||||
|
uint256 randomhash = GetRandHash();
|
||||||
|
map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
|
||||||
|
if (it == mapOrphanTransactions.end())
|
||||||
|
it = mapOrphanTransactions.begin();
|
||||||
|
EraseOrphanTx(it->first);
|
||||||
|
++nEvicted;
|
||||||
|
}
|
||||||
|
return nEvicted;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LOCK(mempool.cs);
|
||||||
|
uint256 hash = tx.GetHash();
|
||||||
|
double dPriorityDelta = 0;
|
||||||
|
CAmount nFeeDelta = 0;
|
||||||
|
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
|
||||||
|
if (dPriorityDelta > 0 || nFeeDelta > 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes);
|
||||||
|
|
||||||
|
if (fAllowFree)
|
||||||
|
{
|
||||||
|
// There is a free transaction area in blocks created by most miners,
|
||||||
|
// * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
|
||||||
|
// to be considered to fall into this category. We don't want to encourage sending
|
||||||
|
// multiple transactions instead of one big transaction to avoid fees.
|
||||||
|
if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000))
|
||||||
|
nMinFee = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MoneyRange(nMinFee))
|
||||||
|
nMinFee = MAX_MONEY;
|
||||||
|
return nMinFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
|
const uint32_t z2zTransitionWindow = 10;
|
||||||
|
const uint32_t z2zTransitionStart = 340000 - z2zTransitionWindow;
|
||||||
|
const uint32_t nHeight = chainActive.Height();
|
||||||
|
|
||||||
|
// This only applies to HUSH3, other chains can start off z2z via ac_private=1
|
||||||
|
if(ishush3) {
|
||||||
|
if((nHeight >= z2zTransitionStart) || (nHeight <= 340000)) {
|
||||||
|
// During the z2z transition window, only coinbase tx's as part of blocks are allowed
|
||||||
|
// Theory: We want an empty mempool at our fork block height, and the only way to assure that
|
||||||
|
// is to have an empty mempool for a few previous blocks, to take care of potential re-orgs
|
||||||
|
// and edge cases. This empty mempool assures there will be no transactions involving taddrs
|
||||||
|
// stuck in the mempool, when the z2z rule takes effect.
|
||||||
|
// Thanks to jl777 for helping design this
|
||||||
|
fprintf(stderr,"%s: rejecting all tx's during z2z transition window. Please retry after Block %d !!!\n", __func__,nHeight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pfMissingInputs)
|
||||||
|
*pfMissingInputs = false;
|
||||||
|
uint32_t tiptime;
|
||||||
|
int flag=0,nextBlockHeight = chainActive.Height() + 1;
|
||||||
|
auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus());
|
||||||
|
if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 )
|
||||||
|
tiptime = (uint32_t)time(NULL);
|
||||||
|
else tiptime = (uint32_t)chainActive.LastTip()->nTime;
|
||||||
|
|
||||||
|
auto verifier = libzcash::ProofVerifier::Strict();
|
||||||
|
|
||||||
|
if (!CheckTransaction(tiptime,tx, state, verifier, 0, 0))
|
||||||
|
{
|
||||||
|
return error("AcceptToMemoryPool: CheckTransaction failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject duplicate output proofs in a single ztx in mempool
|
||||||
|
// Migrate this to CheckTransaction() to make it a consensus requirement
|
||||||
|
{
|
||||||
|
set<libzcash::GrothProof> vSaplingOutputProof;
|
||||||
|
BOOST_FOREACH(const OutputDescription& output, tx.vShieldedOutput)
|
||||||
|
{
|
||||||
|
if (vSaplingOutputProof.count(output.zkproof))
|
||||||
|
return state.Invalid(error("AcceptToMemoryPool: duplicate output proof"),REJECT_DUPLICATE_OUTPUT_PROOF, "bad-txns-duplicate-output-proof");
|
||||||
|
vSaplingOutputProof.insert(output.zkproof);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject duplicate spend proofs in a single ztx in mempool
|
||||||
|
// Migrate this to CheckTransaction() to make it a consensus requirement
|
||||||
|
{
|
||||||
|
set<libzcash::GrothProof> vSaplingSpendProof;
|
||||||
|
BOOST_FOREACH(const SpendDescription& spend, tx.vShieldedSpend)
|
||||||
|
{
|
||||||
|
if (vSaplingSpendProof.count(spend.zkproof))
|
||||||
|
return state.Invalid(error("AcceptToMemoryPool: duplicate spend proof"),REJECT_DUPLICATE_SPEND_PROOF, "bad-txns-duplicate-spend-proof");
|
||||||
|
vSaplingSpendProof.insert(spend.zkproof);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoS level set to 10 to be more forgiving.
|
||||||
|
// Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
|
||||||
|
if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel))
|
||||||
|
{
|
||||||
|
return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
|
||||||
|
}
|
||||||
|
//fprintf(stderr,"addmempool 2\n");
|
||||||
|
// Coinbase is only valid in a block, not as a loose transaction
|
||||||
|
if (tx.IsCoinBase())
|
||||||
|
{
|
||||||
|
fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n");
|
||||||
|
return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"),REJECT_INVALID, "coinbase");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||||
|
string reason;
|
||||||
|
if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
//fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str());
|
||||||
|
return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason),REJECT_NONSTANDARD, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only accept nLockTime-using transactions that can be mined in the next
|
||||||
|
// block; we don't want our mempool filled up with transactions that can't
|
||||||
|
// be mined yet.
|
||||||
|
if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
|
||||||
|
{
|
||||||
|
//fprintf(stderr,"AcceptToMemoryPool reject non-final\n");
|
||||||
|
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
|
||||||
|
}
|
||||||
|
// is it already in the memory pool?
|
||||||
|
uint256 hash = tx.GetHash();
|
||||||
|
if (pool.exists(hash))
|
||||||
|
{
|
||||||
|
//fprintf(stderr,"already in mempool\n");
|
||||||
|
return state.Invalid(false, REJECT_DUPLICATE, "already in mempool");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for conflicts with in-memory transactions
|
||||||
|
{
|
||||||
|
LOCK(pool.cs); // protect pool.mapNextTx
|
||||||
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
|
{
|
||||||
|
COutPoint outpoint = tx.vin[i].prevout;
|
||||||
|
if (pool.mapNextTx.count(outpoint))
|
||||||
|
{
|
||||||
|
// Disable replacement feature for now
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const SpendDescription &spendDescription : tx.vShieldedSpend) {
|
||||||
|
if (pool.nullifierExists(spendDescription.nullifier, SAPLING)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CCoinsView dummy;
|
||||||
|
CCoinsViewCache view(&dummy);
|
||||||
|
int64_t interest;
|
||||||
|
CAmount nValueIn = 0;
|
||||||
|
{
|
||||||
|
LOCK(pool.cs);
|
||||||
|
CCoinsViewMemPool viewMemPool(pcoinsTip, pool);
|
||||||
|
view.SetBackend(viewMemPool);
|
||||||
|
|
||||||
|
// do we already have it?
|
||||||
|
if (view.HaveCoins(hash)) {
|
||||||
|
//fprintf(stderr,"view.HaveCoins(hash) error\n");
|
||||||
|
return state.Invalid(false, REJECT_DUPLICATE, "already have coins");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// do all inputs exist?
|
||||||
|
// Note that this does not check for the presence of actual outputs (see the next check for that),
|
||||||
|
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
|
||||||
|
BOOST_FOREACH(const CTxIn txin, tx.vin)
|
||||||
|
{
|
||||||
|
if (!view.HaveCoins(txin.prevout.hash)) {
|
||||||
|
if (pfMissingInputs)
|
||||||
|
*pfMissingInputs = true;
|
||||||
|
//fprintf(stderr,"missing inputs\n");
|
||||||
|
return false;
|
||||||
|
// https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490
|
||||||
|
// state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// are the actual inputs available?
|
||||||
|
if (!view.HaveInputs(tx)) {
|
||||||
|
//fprintf(stderr,"accept failure. inputs-spent\n");
|
||||||
|
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// are the zaddr requirements met?
|
||||||
|
if (!view.HaveShieldedRequirements(tx)) {
|
||||||
|
//fprintf(stderr,"accept failure. ztx reqs not met\n");
|
||||||
|
return state.Invalid(error("AcceptToMemoryPool: shielded requirements not met"),REJECT_DUPLICATE, "bad-txns-shielded-requirements-not-met");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bring the best block into scope
|
||||||
|
view.GetBestBlock();
|
||||||
|
|
||||||
|
nValueIn = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime);
|
||||||
|
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
|
||||||
|
view.SetBackend(dummy);
|
||||||
|
}
|
||||||
|
// Check for non-standard pay-to-script-hash in inputs
|
||||||
|
if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId))
|
||||||
|
return error("AcceptToMemoryPool: reject nonstandard transaction input");
|
||||||
|
|
||||||
|
// Check that the transaction doesn't have an excessive number of
|
||||||
|
// sigops, making it impossible to mine. Since the coinbase transaction
|
||||||
|
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
|
||||||
|
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
|
||||||
|
// merely non-standard transaction.
|
||||||
|
unsigned int nSigOps = GetLegacySigOpCount(tx);
|
||||||
|
nSigOps += GetP2SHSigOpCount(tx, view);
|
||||||
|
if (nSigOps > MAX_STANDARD_TX_SIGOPS)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"accept failure.4\n");
|
||||||
|
return state.DoS(1, error("AcceptToMemoryPool: too many sigops %s, %d > %d", hash.ToString(), nSigOps, MAX_STANDARD_TX_SIGOPS),REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount nValueOut = tx.GetValueOut();
|
||||||
|
CAmount nFees = nValueIn-nValueOut;
|
||||||
|
double dPriority = view.GetPriority(tx, chainActive.Height());
|
||||||
|
if ( nValueOut > 777777*COIN && HUSH_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) // some room for blockreward and txfees
|
||||||
|
return state.DoS(100, error("AcceptToMemoryPool: GetValueOut too big"),REJECT_INVALID,"tx valueout is too big");
|
||||||
|
|
||||||
|
// Keep track of transactions that spend a coinbase, which we re-scan
|
||||||
|
// during reorgs to ensure COINBASE_MATURITY is still met.
|
||||||
|
bool fSpendsCoinbase = false;
|
||||||
|
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
||||||
|
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
||||||
|
if (coins->IsCoinBase()) {
|
||||||
|
fSpendsCoinbase = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Grab the branch ID we expect this transaction to commit to. We don't
|
||||||
|
// yet know if it does, but if the entry gets added to the mempool, then
|
||||||
|
// it has passed ContextualCheckInputs and therefore this is correct.
|
||||||
|
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||||
|
|
||||||
|
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx), fSpendsCoinbase, consensusBranchId);
|
||||||
|
unsigned int nSize = entry.GetTxSize();
|
||||||
|
|
||||||
|
// Accept a tx if it contains zspends and has at least the default fee specified by z_sendmany.
|
||||||
|
if (tx.vShieldedSpend.size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) {
|
||||||
|
// In future we will we have more accurate and dynamic computation of fees, derpz
|
||||||
|
} else {
|
||||||
|
// Don't accept it if it can't get into a block, yallz
|
||||||
|
CAmount txMinFee = GetMinRelayFee(tx, nSize, true);
|
||||||
|
if (fLimitFree && nFees < txMinFee) {
|
||||||
|
//fprintf(stderr,"accept failure.5\n");
|
||||||
|
return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require that free transactions have sufficient priority to be mined in the next block.
|
||||||
|
if (GetBoolArg("-relaypriority", false) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
|
||||||
|
fprintf(stderr,"accept failure.6\n");
|
||||||
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continuously rate-limit free (really, very-low-fee) transactions
|
||||||
|
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
||||||
|
// be annoying or make others' transactions take longer to confirm.
|
||||||
|
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize) )
|
||||||
|
{
|
||||||
|
static CCriticalSection csFreeLimiter;
|
||||||
|
static double dFreeCount;
|
||||||
|
static int64_t nLastTime;
|
||||||
|
int64_t nNow = GetTime();
|
||||||
|
|
||||||
|
LOCK(csFreeLimiter);
|
||||||
|
|
||||||
|
// Use an exponentially decaying ~10-minute window:
|
||||||
|
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
|
||||||
|
nLastTime = nNow;
|
||||||
|
// -limitfreerelay unit is thousand-bytes-per-minute
|
||||||
|
// At default rate it would take over a month to fill 1GB
|
||||||
|
if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"accept failure.7\n");
|
||||||
|
return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "rate limited free transaction");
|
||||||
|
}
|
||||||
|
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
||||||
|
dFreeCount += nSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fRejectAbsurdFee = false;
|
||||||
|
|
||||||
|
if ( fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19)
|
||||||
|
// Disable checks for absurd fees when adding to the mempool. Instead, this check is done
|
||||||
|
// when a user attempts to make a transaction with an absurd fee and only rejects absurd
|
||||||
|
// fees when OP_RETURN data is NOT being used. This means users making normal financial
|
||||||
|
// transactions (z2z) are protected from absurd fees, it is only users who are storing
|
||||||
|
// arbitrary data via a z2t transaction are allowed to (or potentially required) to pay high fees
|
||||||
|
// It would be nice to detect the use of OP_RETURN right here but it seems to only be known
|
||||||
|
// inside of IsStandard() inside of IsStandardTx() and we want to avoid doing expensive checks
|
||||||
|
// multiple times.
|
||||||
|
{
|
||||||
|
string errmsg = strprintf("absurdly high fees %s, %d > %d",
|
||||||
|
hash.ToString(),
|
||||||
|
nFees, ::minRelayTxFee.GetFee(nSize) * 10000);
|
||||||
|
LogPrint("mempool", errmsg.c_str());
|
||||||
|
return state.Error("AcceptToMemoryPool: " + errmsg);
|
||||||
|
}
|
||||||
|
//fprintf(stderr,"addmempool 6\n");
|
||||||
|
|
||||||
|
// Check against previous transactions
|
||||||
|
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||||
|
PrecomputedTransactionData txdata(tx);
|
||||||
|
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
|
||||||
|
{
|
||||||
|
//fprintf(stderr,"accept failure.9\n");
|
||||||
|
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check again against just the consensus-critical mandatory script
|
||||||
|
// verification flags, in case of bugs in the standard flags that cause
|
||||||
|
// transactions to pass as valid when they're actually invalid. For
|
||||||
|
// instance the STRICTENC flag was incorrectly allowing certain
|
||||||
|
// CHECKSIG NOT scripts to pass, even though they were invalid.
|
||||||
|
//
|
||||||
|
// There is a similar check in CreateNewBlock() to prevent creating
|
||||||
|
// invalid blocks, however allowing such transactions into the mempool
|
||||||
|
// can be exploited as a DoS attack.
|
||||||
|
// XXX: is this neccesary for CryptoConditions?
|
||||||
|
if ( HUSH_CONNECTING <= 0 && chainActive.LastTip() != 0 )
|
||||||
|
{
|
||||||
|
flag = 1;
|
||||||
|
HUSH_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
|
||||||
|
{
|
||||||
|
if ( flag != 0 )
|
||||||
|
HUSH_CONNECTING = -1;
|
||||||
|
return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString());
|
||||||
|
}
|
||||||
|
if ( flag != 0 )
|
||||||
|
HUSH_CONNECTING = -1;
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(pool.cs);
|
||||||
|
// Store transaction in memory
|
||||||
|
pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
|
||||||
|
|
||||||
|
// Add memory address index
|
||||||
|
if (fAddressIndex) {
|
||||||
|
pool.addAddressIndex(entry, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add memory spent index
|
||||||
|
if (fSpentIndex) {
|
||||||
|
pool.addSpentIndex(entry, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCTxFixAcceptToMemPoolUnchecked(CTxMemPool& pool, const CTransaction &tx)
|
||||||
|
{
|
||||||
|
// called from CheckBlock which is in cs_main and mempool.cs locks already.
|
||||||
|
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||||
|
CTxMemPoolEntry entry(tx, 0, GetTime(), 0, chainActive.Height(), mempool.HasNoInputsOf(tx), false, consensusBranchId);
|
||||||
|
//fprintf(stderr, "adding %s to mempool from block %d\n",tx.GetHash().ToString().c_str(),chainActive.GetHeight());
|
||||||
|
pool.addUnchecked(tx.GetHash(), entry, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool myAddtomempool(CTransaction &tx, CValidationState *pstate, bool fSkipExpiry)
|
||||||
|
{
|
||||||
|
CValidationState state;
|
||||||
|
if (!pstate)
|
||||||
|
pstate = &state;
|
||||||
|
CTransaction Ltx; bool fMissingInputs,fOverrideFees = false;
|
||||||
|
if ( mempool.lookup(tx.GetHash(),Ltx) == 0 )
|
||||||
|
{
|
||||||
|
if ( !fSkipExpiry )
|
||||||
|
return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees, -1));
|
||||||
|
else
|
||||||
|
return(CCTxFixAcceptToMemPoolUnchecked(mempool,tx));
|
||||||
|
}
|
||||||
|
else return(true);
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright 2016-2024 The Hush Developers
|
|
||||||
# Copyright 2022 The DragonX Developers
|
|
||||||
# Released under the GPLv3
|
|
||||||
|
|
||||||
# set working directory to the location of this script
|
|
||||||
# readlink -f does not always exist
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
|
|
||||||
./hush-cli -ac_name=TESTDRAGONX $@
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright 2016-2024 The Hush Developers
|
|
||||||
# Copyright 2022 The DragonX Developers
|
|
||||||
# Released under the GPLv3
|
|
||||||
|
|
||||||
# set working directory to the location of this script
|
|
||||||
# readlink -f does not always exist
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
|
|
||||||
./hush-cli -ac_name=TESTEQUIHASH $@
|
|
||||||
1012
src/tx_validation.cpp
Normal file
1012
src/tx_validation.cpp
Normal file
File diff suppressed because it is too large
Load Diff
18319
src/univalue/configure~
18319
src/univalue/configure~
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
45
src/wallet/rpcwallet_internal.h
Normal file
45
src/wallet/rpcwallet_internal.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Shared declarations for rpcwallet_*.cpp split files.
|
||||||
|
// These helper functions are defined in rpcwallet.cpp but called from other rpcwallet_*.cpp files.
|
||||||
|
|
||||||
|
#ifndef HUSH_WALLET_RPCWALLET_INTERNAL_H
|
||||||
|
#define HUSH_WALLET_RPCWALLET_INTERNAL_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class UniValue;
|
||||||
|
class CPubKey;
|
||||||
|
|
||||||
|
// Macro used by multiple rpcwallet files — call-site must include main.h and hush_globals.h
|
||||||
|
#define THROW_IF_SYNCING(INSYNC) if (HUSH_TESTNODE == 0 && INSYNC == 0) { throw runtime_error(strprintf("%s: Extreme Privacy! Chain still syncing at height %d, aborting to prevent linkability analysis. Please wait until FULLY SYNCED and try again.",__FUNCTION__,chainActive.Tip()->GetHeight())); }
|
||||||
|
|
||||||
|
// Helper functions defined in rpcwallet.cpp
|
||||||
|
bool EnsureWalletIsAvailable(bool avoidException);
|
||||||
|
void EnsureWalletIsUnlocked();
|
||||||
|
std::string HelpRequiringPassphrase();
|
||||||
|
|
||||||
|
// Functions defined in rpcwallet_zops.cpp
|
||||||
|
UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
|
||||||
|
UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
|
||||||
|
// Functions defined in rpcwallet_zindex.cpp
|
||||||
|
UniValue getalldata(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_consolidationstatus(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_sweepstatus(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_listreceivedaddress(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_listsentbyaddress(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_getstats(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_anonsetblockdelta(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_anonsettxdelta(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
UniValue z_getbalances(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||||
|
|
||||||
|
#endif // HUSH_WALLET_RPCWALLET_INTERNAL_H
|
||||||
1193
src/wallet/rpcwallet_zindex.cpp
Normal file
1193
src/wallet/rpcwallet_zindex.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1194
src/wallet/rpcwallet_zops.cpp
Normal file
1194
src/wallet/rpcwallet_zops.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -115,359 +115,6 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
|||||||
return &(it->second);
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate a new Sapling spending key and return its public payment address
|
|
||||||
SaplingPaymentAddress CWallet::GenerateNewSaplingZKey(bool addToWallet)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
|
||||||
|
|
||||||
// Create new metadata
|
|
||||||
int64_t nCreationTime = GetTime();
|
|
||||||
CKeyMetadata metadata(nCreationTime);
|
|
||||||
|
|
||||||
// Try to get the seed
|
|
||||||
HDSeed seed;
|
|
||||||
if (!GetHDSeed(seed))
|
|
||||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): HD seed not found");
|
|
||||||
|
|
||||||
auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
|
||||||
uint32_t bip44CoinType = Params().BIP44CoinType();
|
|
||||||
|
|
||||||
// We use a fixed keypath scheme of m/32'/coin_type'/account'
|
|
||||||
// Derive m/32'
|
|
||||||
auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT);
|
|
||||||
// Derive m/32'/coin_type'
|
|
||||||
auto m_32h_cth = m_32h.Derive(bip44CoinType | ZIP32_HARDENED_KEY_LIMIT);
|
|
||||||
|
|
||||||
// Derive account key at next index, skip keys already known to the wallet
|
|
||||||
libzcash::SaplingExtendedSpendingKey xsk;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
xsk = m_32h_cth.Derive(hdChain.saplingAccountCounter | ZIP32_HARDENED_KEY_LIMIT);
|
|
||||||
metadata.hdKeypath = "m/32'/" + std::to_string(bip44CoinType) + "'/" + std::to_string(hdChain.saplingAccountCounter) + "'";
|
|
||||||
metadata.seedFp = hdChain.seedFp;
|
|
||||||
// Increment childkey index
|
|
||||||
hdChain.saplingAccountCounter++;
|
|
||||||
} while (HaveSaplingSpendingKey(xsk.expsk.full_viewing_key()));
|
|
||||||
|
|
||||||
// Update the chain model in the database
|
|
||||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(hdChain))
|
|
||||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): Writing HD chain model failed");
|
|
||||||
|
|
||||||
auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
|
|
||||||
mapSaplingZKeyMetadata[ivk] = metadata;
|
|
||||||
|
|
||||||
auto addr = xsk.DefaultAddress();
|
|
||||||
if (addToWallet && !AddSaplingZKey(xsk, addr)) {
|
|
||||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed");
|
|
||||||
}
|
|
||||||
// return default sapling payment address.
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add spending key to keystore
|
|
||||||
bool CWallet::AddSaplingZKey(
|
|
||||||
const libzcash::SaplingExtendedSpendingKey &sk,
|
|
||||||
const libzcash::SaplingPaymentAddress &defaultAddr)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
|
||||||
|
|
||||||
if (!CCryptoKeyStore::AddSaplingSpendingKey(sk, defaultAddr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nTimeFirstKey = 1; // No birthday information for viewing keys.
|
|
||||||
if (!fFileBacked) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsCrypted()) {
|
|
||||||
auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
|
|
||||||
return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add payment address -> incoming viewing key map entry
|
|
||||||
bool CWallet::AddSaplingIncomingViewingKey(
|
|
||||||
const libzcash::SaplingIncomingViewingKey &ivk,
|
|
||||||
const libzcash::SaplingPaymentAddress &addr)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
|
||||||
|
|
||||||
if (!CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFileBacked) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsCrypted()) {
|
|
||||||
return CWalletDB(strWalletFile).WriteSaplingPaymentAddress(addr, ivk);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CPubKey CWallet::GenerateNewKey()
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
|
||||||
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
|
|
||||||
|
|
||||||
CKey secret;
|
|
||||||
secret.MakeNewKey(fCompressed);
|
|
||||||
|
|
||||||
// Compressed public keys were introduced in version 0.6.0
|
|
||||||
if (fCompressed)
|
|
||||||
SetMinVersion(FEATURE_COMPRPUBKEY);
|
|
||||||
|
|
||||||
CPubKey pubkey = secret.GetPubKey();
|
|
||||||
assert(secret.VerifyPubKey(pubkey));
|
|
||||||
|
|
||||||
// Create new metadata
|
|
||||||
int64_t nCreationTime = GetTime();
|
|
||||||
mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
|
|
||||||
if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
|
|
||||||
nTimeFirstKey = nCreationTime;
|
|
||||||
|
|
||||||
if (!AddKeyPubKey(secret, pubkey))
|
|
||||||
throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
|
|
||||||
return pubkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
|
||||||
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// check if we need to remove from watch-only
|
|
||||||
CScript script;
|
|
||||||
script = GetScriptForDestination(pubkey.GetID());
|
|
||||||
if (HaveWatchOnly(script))
|
|
||||||
RemoveWatchOnly(script);
|
|
||||||
|
|
||||||
if (!fFileBacked)
|
|
||||||
return true;
|
|
||||||
if (!IsCrypted()) {
|
|
||||||
return CWalletDB(strWalletFile).WriteKey(pubkey,
|
|
||||||
secret.GetPrivKey(),
|
|
||||||
mapKeyMetadata[pubkey.GetID()]);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
|
|
||||||
const vector<unsigned char> &vchCryptedSecret)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
|
|
||||||
return false;
|
|
||||||
if (!fFileBacked)
|
|
||||||
return true;
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
if (pwalletdbEncryption)
|
|
||||||
return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
|
|
||||||
vchCryptedSecret,
|
|
||||||
mapKeyMetadata[vchPubKey.GetID()]);
|
|
||||||
else
|
|
||||||
return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
|
|
||||||
vchCryptedSecret,
|
|
||||||
mapKeyMetadata[vchPubKey.GetID()]);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
|
||||||
const std::vector<unsigned char> &vchCryptedSecret,
|
|
||||||
const libzcash::SaplingPaymentAddress &defaultAddr)
|
|
||||||
{
|
|
||||||
if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr))
|
|
||||||
return false;
|
|
||||||
if (!fFileBacked)
|
|
||||||
return true;
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
if (pwalletdbEncryption) {
|
|
||||||
return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk,
|
|
||||||
vchCryptedSecret,
|
|
||||||
mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
|
|
||||||
} else {
|
|
||||||
return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk,
|
|
||||||
vchCryptedSecret,
|
|
||||||
mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
|
||||||
if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
|
|
||||||
nTimeFirstKey = meta.nCreateTime;
|
|
||||||
|
|
||||||
mapKeyMetadata[pubkey.GetID()] = meta;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
|
||||||
{
|
|
||||||
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CWallet::LoadCryptedSaplingZKey(
|
|
||||||
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
|
||||||
const std::vector<unsigned char> &vchCryptedSecret)
|
|
||||||
{
|
|
||||||
return CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, extfvk.DefaultAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
|
||||||
mapSaplingZKeyMetadata[ivk] = meta;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
|
|
||||||
{
|
|
||||||
return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadSaplingPaymentAddress(
|
|
||||||
const libzcash::SaplingPaymentAddress &addr,
|
|
||||||
const libzcash::SaplingIncomingViewingKey &ivk)
|
|
||||||
{
|
|
||||||
return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::AddCScript(const CScript& redeemScript)
|
|
||||||
{
|
|
||||||
if (!CCryptoKeyStore::AddCScript(redeemScript))
|
|
||||||
return false;
|
|
||||||
if (!fFileBacked)
|
|
||||||
return true;
|
|
||||||
return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadCScript(const CScript& redeemScript)
|
|
||||||
{
|
|
||||||
/* A sanity check was added in pull #3843 to avoid adding redeemScripts
|
|
||||||
* that never can be redeemed. However, old wallets may still contain
|
|
||||||
* these. Do not add them to the wallet and warn. */
|
|
||||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
|
||||||
{
|
|
||||||
std::string strAddr = EncodeDestination(CScriptID(redeemScript));
|
|
||||||
LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
|
|
||||||
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CCryptoKeyStore::AddCScript(redeemScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::AddWatchOnly(const CScript &dest)
|
|
||||||
{
|
|
||||||
if (!CCryptoKeyStore::AddWatchOnly(dest))
|
|
||||||
return false;
|
|
||||||
nTimeFirstKey = 1; // No birthday information for watch-only keys.
|
|
||||||
NotifyWatchonlyChanged(true);
|
|
||||||
if (!fFileBacked)
|
|
||||||
return true;
|
|
||||||
return CWalletDB(strWalletFile).WriteWatchOnly(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::RemoveWatchOnly(const CScript &dest)
|
|
||||||
{
|
|
||||||
AssertLockHeld(cs_wallet);
|
|
||||||
if (!CCryptoKeyStore::RemoveWatchOnly(dest))
|
|
||||||
return false;
|
|
||||||
if (!HaveWatchOnly())
|
|
||||||
NotifyWatchonlyChanged(false);
|
|
||||||
if (fFileBacked)
|
|
||||||
if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadWatchOnly(const CScript &dest)
|
|
||||||
{
|
|
||||||
return CCryptoKeyStore::AddWatchOnly(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
|
|
||||||
{
|
|
||||||
CCrypter crypter;
|
|
||||||
CKeyingMaterial vMasterKey;
|
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
|
||||||
{
|
|
||||||
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
|
||||||
return false;
|
|
||||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
|
||||||
continue; // try another master key
|
|
||||||
if (CCryptoKeyStore::Unlock(vMasterKey))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
|
|
||||||
{
|
|
||||||
bool fWasLocked = IsLocked();
|
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
Lock();
|
|
||||||
|
|
||||||
CCrypter crypter;
|
|
||||||
CKeyingMaterial vMasterKey;
|
|
||||||
BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
|
||||||
{
|
|
||||||
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
|
||||||
return false;
|
|
||||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
|
||||||
return false;
|
|
||||||
if (CCryptoKeyStore::Unlock(vMasterKey))
|
|
||||||
{
|
|
||||||
int64_t nStartTime = GetTimeMillis();
|
|
||||||
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
|
||||||
pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
|
|
||||||
|
|
||||||
nStartTime = GetTimeMillis();
|
|
||||||
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
|
||||||
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
|
|
||||||
|
|
||||||
if (pMasterKey.second.nDeriveIterations < 25000)
|
|
||||||
pMasterKey.second.nDeriveIterations = 25000;
|
|
||||||
|
|
||||||
LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
|
|
||||||
|
|
||||||
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
|
||||||
return false;
|
|
||||||
if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
|
|
||||||
return false;
|
|
||||||
CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
|
|
||||||
if (fWasLocked)
|
|
||||||
Lock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::ChainTip(const CBlockIndex *pindex,
|
void CWallet::ChainTip(const CBlockIndex *pindex,
|
||||||
const CBlock *pblock,
|
const CBlock *pblock,
|
||||||
boost::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>> added)
|
boost::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>> added)
|
||||||
@@ -1216,97 +863,6 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
|
||||||
{
|
|
||||||
if (IsCrypted())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CKeyingMaterial vMasterKey;
|
|
||||||
|
|
||||||
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
|
||||||
GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
|
||||||
|
|
||||||
CMasterKey kMasterKey;
|
|
||||||
|
|
||||||
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
|
||||||
GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
|
||||||
|
|
||||||
CCrypter crypter;
|
|
||||||
int64_t nStartTime = GetTimeMillis();
|
|
||||||
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
|
|
||||||
kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
|
|
||||||
|
|
||||||
nStartTime = GetTimeMillis();
|
|
||||||
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
|
|
||||||
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
|
|
||||||
|
|
||||||
if (kMasterKey.nDeriveIterations < 25000)
|
|
||||||
kMasterKey.nDeriveIterations = 25000;
|
|
||||||
|
|
||||||
LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
|
|
||||||
|
|
||||||
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
|
|
||||||
return false;
|
|
||||||
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
|
|
||||||
if (fFileBacked)
|
|
||||||
{
|
|
||||||
assert(!pwalletdbEncryption);
|
|
||||||
pwalletdbEncryption = new CWalletDB(strWalletFile);
|
|
||||||
if (!pwalletdbEncryption->TxnBegin()) {
|
|
||||||
delete pwalletdbEncryption;
|
|
||||||
pwalletdbEncryption = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EncryptKeys(vMasterKey))
|
|
||||||
{
|
|
||||||
if (fFileBacked) {
|
|
||||||
pwalletdbEncryption->TxnAbort();
|
|
||||||
delete pwalletdbEncryption;
|
|
||||||
}
|
|
||||||
// We now probably have half of our keys encrypted in memory, and half not...
|
|
||||||
// die and let the user reload the unencrypted wallet.
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encryption was introduced in version 0.4.0
|
|
||||||
SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
|
|
||||||
|
|
||||||
if (fFileBacked)
|
|
||||||
{
|
|
||||||
if (!pwalletdbEncryption->TxnCommit()) {
|
|
||||||
delete pwalletdbEncryption;
|
|
||||||
// We now have keys encrypted in memory, but not on disk...
|
|
||||||
// die to avoid confusion and let the user reload the unencrypted wallet.
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pwalletdbEncryption;
|
|
||||||
pwalletdbEncryption = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lock();
|
|
||||||
Unlock(strWalletPassphrase);
|
|
||||||
NewKeyPool();
|
|
||||||
Lock();
|
|
||||||
|
|
||||||
// Need to completely rewrite the wallet file; if we don't, bdb might keep
|
|
||||||
// bits of the unencrypted private key in slack space in the database file.
|
|
||||||
CDB::Rewrite(strWalletFile);
|
|
||||||
|
|
||||||
}
|
|
||||||
NotifyStatusChanged(this);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
|
int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_wallet); // nOrderPosNext
|
AssertLockHeld(cs_wallet); // nOrderPosNext
|
||||||
@@ -2110,92 +1666,6 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
|
|||||||
return nChange;
|
return nChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::IsHDFullyEnabled() const
|
|
||||||
{
|
|
||||||
// Only Sapling addresses are HD for now
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::GenerateNewSeed()
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
|
|
||||||
auto seed = HDSeed::Random(HD_WALLET_SEED_LENGTH);
|
|
||||||
|
|
||||||
int64_t nCreationTime = GetTime();
|
|
||||||
|
|
||||||
// If the wallet is encrypted and locked, this will fail.
|
|
||||||
if (!SetHDSeed(seed))
|
|
||||||
throw std::runtime_error(std::string(__func__) + ": SetHDSeed failed");
|
|
||||||
|
|
||||||
// store the key creation time together with
|
|
||||||
// the child index counter in the database
|
|
||||||
// as a hdchain object
|
|
||||||
CHDChain newHdChain;
|
|
||||||
newHdChain.nVersion = CHDChain::VERSION_HD_BASE;
|
|
||||||
newHdChain.seedFp = seed.Fingerprint();
|
|
||||||
newHdChain.nCreateTime = nCreationTime;
|
|
||||||
SetHDChain(newHdChain, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::SetHDSeed(const HDSeed& seed)
|
|
||||||
{
|
|
||||||
if (!CCryptoKeyStore::SetHDSeed(seed)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFileBacked) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
if (!IsCrypted()) {
|
|
||||||
return CWalletDB(strWalletFile).WriteHDSeed(seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret)
|
|
||||||
{
|
|
||||||
if (!CCryptoKeyStore::SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFileBacked) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
if (pwalletdbEncryption)
|
|
||||||
return pwalletdbEncryption->WriteCryptedHDSeed(seedFp, vchCryptedSecret);
|
|
||||||
else
|
|
||||||
return CWalletDB(strWalletFile).WriteCryptedHDSeed(seedFp, vchCryptedSecret);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
if (!memonly && fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(chain))
|
|
||||||
throw std::runtime_error(std::string(__func__) + ": writing chain failed");
|
|
||||||
|
|
||||||
hdChain = chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadHDSeed(const HDSeed& seed)
|
|
||||||
{
|
|
||||||
return CBasicKeyStore::SetHDSeed(seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed)
|
|
||||||
{
|
|
||||||
return CCryptoKeyStore::SetCryptedHDSeed(seedFp, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData)
|
void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData)
|
||||||
{
|
{
|
||||||
mapSaplingNoteData.clear();
|
mapSaplingNoteData.clear();
|
||||||
@@ -4196,143 +3666,6 @@ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark old keypool keys as used,
|
|
||||||
* and generate all new keys
|
|
||||||
*/
|
|
||||||
bool CWallet::NewKeyPool()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
BOOST_FOREACH(int64_t nIndex, setKeyPool)
|
|
||||||
walletdb.ErasePool(nIndex);
|
|
||||||
setKeyPool.clear();
|
|
||||||
|
|
||||||
if (IsLocked())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
|
|
||||||
for (int i = 0; i < nKeys; i++)
|
|
||||||
{
|
|
||||||
int64_t nIndex = i+1;
|
|
||||||
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
|
|
||||||
setKeyPool.insert(nIndex);
|
|
||||||
}
|
|
||||||
LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::TopUpKeyPool(unsigned int kpSize)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
|
|
||||||
if (IsLocked())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
// Top up key pool
|
|
||||||
unsigned int nTargetSize;
|
|
||||||
if (kpSize > 0)
|
|
||||||
nTargetSize = kpSize;
|
|
||||||
else
|
|
||||||
nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
|
|
||||||
|
|
||||||
while (setKeyPool.size() < (nTargetSize + 1))
|
|
||||||
{
|
|
||||||
int64_t nEnd = 1;
|
|
||||||
if (!setKeyPool.empty())
|
|
||||||
nEnd = *(--setKeyPool.end()) + 1;
|
|
||||||
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
|
|
||||||
throw runtime_error("TopUpKeyPool(): writing generated key failed");
|
|
||||||
setKeyPool.insert(nEnd);
|
|
||||||
LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
|
|
||||||
{
|
|
||||||
nIndex = -1;
|
|
||||||
keypool.vchPubKey = CPubKey();
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
|
|
||||||
if (!IsLocked())
|
|
||||||
TopUpKeyPool();
|
|
||||||
|
|
||||||
// Get the oldest key
|
|
||||||
if(setKeyPool.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
nIndex = *(setKeyPool.begin());
|
|
||||||
setKeyPool.erase(setKeyPool.begin());
|
|
||||||
if (!walletdb.ReadPool(nIndex, keypool))
|
|
||||||
throw runtime_error("ReserveKeyFromKeyPool(): read failed");
|
|
||||||
if (!HaveKey(keypool.vchPubKey.GetID()))
|
|
||||||
throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
|
|
||||||
assert(keypool.vchPubKey.IsValid());
|
|
||||||
//LogPrintf("keypool reserve %d\n", nIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::KeepKey(int64_t nIndex)
|
|
||||||
{
|
|
||||||
// Remove from key pool
|
|
||||||
if (fFileBacked)
|
|
||||||
{
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
walletdb.ErasePool(nIndex);
|
|
||||||
}
|
|
||||||
LogPrintf("keypool keep %d\n", nIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::ReturnKey(int64_t nIndex)
|
|
||||||
{
|
|
||||||
// Return to key pool
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
setKeyPool.insert(nIndex);
|
|
||||||
}
|
|
||||||
//LogPrintf("keypool return %d\n", nIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::GetKeyFromPool(CPubKey& result)
|
|
||||||
{
|
|
||||||
int64_t nIndex = 0;
|
|
||||||
CKeyPool keypool;
|
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
|
||||||
if (nIndex == -1)
|
|
||||||
{
|
|
||||||
if (IsLocked()) return false;
|
|
||||||
result = GenerateNewKey();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
KeepKey(nIndex);
|
|
||||||
result = keypool.vchPubKey;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t CWallet::GetOldestKeyPoolTime()
|
|
||||||
{
|
|
||||||
int64_t nIndex = 0;
|
|
||||||
CKeyPool keypool;
|
|
||||||
ReserveKeyFromKeyPool(nIndex, keypool);
|
|
||||||
if (nIndex == -1)
|
|
||||||
return GetTime();
|
|
||||||
ReturnKey(nIndex);
|
|
||||||
return keypool.nTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
|
std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
|
||||||
{
|
{
|
||||||
map<CTxDestination, CAmount> balances;
|
map<CTxDestination, CAmount> balances;
|
||||||
@@ -4480,59 +3813,6 @@ std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAcco
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
|
|
||||||
{
|
|
||||||
if (nIndex == -1)
|
|
||||||
{
|
|
||||||
CKeyPool keypool;
|
|
||||||
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
|
|
||||||
if (nIndex != -1)
|
|
||||||
vchPubKey = keypool.vchPubKey;
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(vchPubKey.IsValid());
|
|
||||||
pubkey = vchPubKey;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CReserveKey::KeepKey()
|
|
||||||
{
|
|
||||||
if (nIndex != -1)
|
|
||||||
pwallet->KeepKey(nIndex);
|
|
||||||
nIndex = -1;
|
|
||||||
vchPubKey = CPubKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CReserveKey::ReturnKey()
|
|
||||||
{
|
|
||||||
if (nIndex != -1)
|
|
||||||
pwallet->ReturnKey(nIndex);
|
|
||||||
nIndex = -1;
|
|
||||||
vchPubKey = CPubKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
|
|
||||||
{
|
|
||||||
setAddress.clear();
|
|
||||||
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
LOCK2(cs_main, cs_wallet);
|
|
||||||
BOOST_FOREACH(const int64_t& id, setKeyPool)
|
|
||||||
{
|
|
||||||
CKeyPool keypool;
|
|
||||||
if (!walletdb.ReadPool(id, keypool))
|
|
||||||
throw runtime_error("GetAllReserveKeyHashes(): read failed");
|
|
||||||
assert(keypool.vchPubKey.IsValid());
|
|
||||||
CKeyID keyID = keypool.vchPubKey.GetID();
|
|
||||||
if (!HaveKey(keyID))
|
|
||||||
throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
|
|
||||||
setAddress.insert(keyID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWallet::UpdatedTransaction(const uint256 &hashTx)
|
void CWallet::UpdatedTransaction(const uint256 &hashTx)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -4616,96 +3896,6 @@ std::vector<SaplingOutPoint> CWallet::ListLockedSaplingNotes()
|
|||||||
|
|
||||||
/** @} */ // end of Actions
|
/** @} */ // end of Actions
|
||||||
|
|
||||||
class CAffectedKeysVisitor : public boost::static_visitor<void> {
|
|
||||||
private:
|
|
||||||
const CKeyStore &keystore;
|
|
||||||
std::vector<CKeyID> &vKeys;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
|
|
||||||
|
|
||||||
void Process(const CScript &script) {
|
|
||||||
txnouttype type;
|
|
||||||
std::vector<CTxDestination> vDest;
|
|
||||||
int nRequired;
|
|
||||||
if (ExtractDestinations(script, type, vDest, nRequired)) {
|
|
||||||
BOOST_FOREACH(const CTxDestination &dest, vDest)
|
|
||||||
boost::apply_visitor(*this, dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const CKeyID &keyId) {
|
|
||||||
if (keystore.HaveKey(keyId))
|
|
||||||
vKeys.push_back(keyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const CPubKey &key) {
|
|
||||||
CKeyID keyId = key.GetID();
|
|
||||||
if (keystore.HaveKey(keyId))
|
|
||||||
vKeys.push_back(keyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const CScriptID &scriptId) {
|
|
||||||
CScript script;
|
|
||||||
if (keystore.GetCScript(scriptId, script))
|
|
||||||
Process(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const CNoDestination &none) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
|
|
||||||
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
|
||||||
mapKeyBirth.clear();
|
|
||||||
|
|
||||||
// get birth times for keys with metadata
|
|
||||||
for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
|
|
||||||
if (it->second.nCreateTime)
|
|
||||||
mapKeyBirth[it->first] = it->second.nCreateTime;
|
|
||||||
|
|
||||||
// map in which we'll infer heights of other keys
|
|
||||||
CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
|
|
||||||
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
|
|
||||||
std::set<CKeyID> setKeys;
|
|
||||||
GetKeys(setKeys);
|
|
||||||
BOOST_FOREACH(const CKeyID &keyid, setKeys) {
|
|
||||||
if (mapKeyBirth.count(keyid) == 0)
|
|
||||||
mapKeyFirstBlock[keyid] = pindexMax;
|
|
||||||
}
|
|
||||||
setKeys.clear();
|
|
||||||
|
|
||||||
// if there are no such keys, we're done
|
|
||||||
if (mapKeyFirstBlock.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// find first block that affects those keys, if there are any left
|
|
||||||
std::vector<CKeyID> vAffected;
|
|
||||||
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
|
|
||||||
// iterate over all wallet transactions...
|
|
||||||
const CWalletTx &wtx = (*it).second;
|
|
||||||
BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
|
|
||||||
if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
|
|
||||||
// ... which are already in a block
|
|
||||||
int nHeight = blit->second->GetHeight();
|
|
||||||
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
|
|
||||||
// iterate over all their outputs
|
|
||||||
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
|
|
||||||
BOOST_FOREACH(const CKeyID &keyid, vAffected) {
|
|
||||||
// ... and all their affected keys
|
|
||||||
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
|
|
||||||
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->GetHeight())
|
|
||||||
rit->second = blit->second;
|
|
||||||
}
|
|
||||||
vAffected.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract block timestamps for those keys
|
|
||||||
for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
|
|
||||||
mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
|
bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
|
||||||
{
|
{
|
||||||
if (boost::get<CNoDestination>(&dest))
|
if (boost::get<CNoDestination>(&dest))
|
||||||
@@ -4951,109 +4141,3 @@ void CWallet::GetFilteredNotes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Shielded key and address generalizations
|
|
||||||
//
|
|
||||||
|
|
||||||
bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
|
|
||||||
{
|
|
||||||
libzcash::SaplingIncomingViewingKey ivk;
|
|
||||||
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
|
|
||||||
{
|
|
||||||
libzcash::SaplingIncomingViewingKey ivk;
|
|
||||||
|
|
||||||
// If we have a SaplingExtendedSpendingKey in the wallet, then we will
|
|
||||||
// also have the corresponding SaplingFullViewingKey.
|
|
||||||
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
|
||||||
m_wallet->HaveSaplingFullViewingKey(ivk);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
|
|
||||||
{
|
|
||||||
libzcash::SaplingIncomingViewingKey ivk;
|
|
||||||
libzcash::SaplingFullViewingKey fvk;
|
|
||||||
|
|
||||||
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
|
||||||
m_wallet->GetSaplingFullViewingKey(ivk, fvk) &&
|
|
||||||
m_wallet->HaveSaplingSpendingKey(fvk);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::InvalidEncoding& no) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
|
|
||||||
const libzcash::SaplingPaymentAddress &zaddr) const
|
|
||||||
{
|
|
||||||
libzcash::SaplingExtendedSpendingKey extsk;
|
|
||||||
if (m_wallet->GetSaplingExtendedSpendingKey(zaddr, extsk)) {
|
|
||||||
return libzcash::SpendingKey(extsk);
|
|
||||||
} else {
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
|
|
||||||
const libzcash::InvalidEncoding& no) const
|
|
||||||
{
|
|
||||||
// Defaults to InvalidEncoding
|
|
||||||
return libzcash::SpendingKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
|
|
||||||
auto fvk = sk.expsk.full_viewing_key();
|
|
||||||
auto ivk = fvk.in_viewing_key();
|
|
||||||
auto addr = sk.DefaultAddress();
|
|
||||||
{
|
|
||||||
if (log){
|
|
||||||
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
|
|
||||||
}
|
|
||||||
// Don't throw error in case a key is already there
|
|
||||||
if (m_wallet->HaveSaplingSpendingKey(fvk)) {
|
|
||||||
return KeyAlreadyExists;
|
|
||||||
} else {
|
|
||||||
if (!m_wallet-> AddSaplingZKey(sk, addr)) {
|
|
||||||
return KeyNotAdded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sapling addresses can't have been used in transactions prior to activation.
|
|
||||||
if (params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight == Consensus::NetworkUpgrade::ALWAYS_ACTIVE) {
|
|
||||||
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime;
|
|
||||||
} else {
|
|
||||||
// TODO: set a better time for HUSH+DRAGONX
|
|
||||||
// 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
|
|
||||||
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
|
|
||||||
}
|
|
||||||
if (hdKeypath) {
|
|
||||||
m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.get();
|
|
||||||
}
|
|
||||||
if (seedFpStr) {
|
|
||||||
uint256 seedFp;
|
|
||||||
seedFp.SetHex(seedFpStr.get());
|
|
||||||
m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
|
|
||||||
}
|
|
||||||
return KeyAdded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
|
|
||||||
}
|
|
||||||
|
|||||||
975
src/wallet/wallet_keys.cpp
Normal file
975
src/wallet/wallet_keys.cpp
Normal file
@@ -0,0 +1,975 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||||
|
// 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
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||||
|
* *
|
||||||
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||||
|
* the top-level directory of this distribution for the individual copyright *
|
||||||
|
* holder information and the developer policies on copyright and licensing. *
|
||||||
|
* *
|
||||||
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||||
|
* SuperNET software, including this file may be copied, modified, propagated *
|
||||||
|
* or distributed except according to the terms contained in the LICENSE file *
|
||||||
|
* *
|
||||||
|
* Removal or modification of this copyright notice is prohibited. *
|
||||||
|
* *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// Key management, encryption, HD wallet, and keypool operations
|
||||||
|
// Split from wallet.cpp to separate key management from transaction logic
|
||||||
|
|
||||||
|
#include "wallet/wallet.h"
|
||||||
|
#include "key_io.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "rpc/protocol.h"
|
||||||
|
#include "script/script.h"
|
||||||
|
#include "script/sign.h"
|
||||||
|
#include "crypter.h"
|
||||||
|
#include "consensus/upgrades.h"
|
||||||
|
#include "zcash/zip32.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace libzcash;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Key generation and management
|
||||||
|
//
|
||||||
|
|
||||||
|
// Generate a new Sapling spending key and return its public payment address
|
||||||
|
SaplingPaymentAddress CWallet::GenerateNewSaplingZKey(bool addToWallet)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||||
|
|
||||||
|
// Create new metadata
|
||||||
|
int64_t nCreationTime = GetTime();
|
||||||
|
CKeyMetadata metadata(nCreationTime);
|
||||||
|
|
||||||
|
// Try to get the seed
|
||||||
|
HDSeed seed;
|
||||||
|
if (!GetHDSeed(seed))
|
||||||
|
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): HD seed not found");
|
||||||
|
|
||||||
|
auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||||
|
uint32_t bip44CoinType = Params().BIP44CoinType();
|
||||||
|
|
||||||
|
// We use a fixed keypath scheme of m/32'/coin_type'/account'
|
||||||
|
// Derive m/32'
|
||||||
|
auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT);
|
||||||
|
// Derive m/32'/coin_type'
|
||||||
|
auto m_32h_cth = m_32h.Derive(bip44CoinType | ZIP32_HARDENED_KEY_LIMIT);
|
||||||
|
|
||||||
|
// Derive account key at next index, skip keys already known to the wallet
|
||||||
|
libzcash::SaplingExtendedSpendingKey xsk;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
xsk = m_32h_cth.Derive(hdChain.saplingAccountCounter | ZIP32_HARDENED_KEY_LIMIT);
|
||||||
|
metadata.hdKeypath = "m/32'/" + std::to_string(bip44CoinType) + "'/" + std::to_string(hdChain.saplingAccountCounter) + "'";
|
||||||
|
metadata.seedFp = hdChain.seedFp;
|
||||||
|
// Increment childkey index
|
||||||
|
hdChain.saplingAccountCounter++;
|
||||||
|
} while (HaveSaplingSpendingKey(xsk.expsk.full_viewing_key()));
|
||||||
|
|
||||||
|
// Update the chain model in the database
|
||||||
|
if (fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(hdChain))
|
||||||
|
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): Writing HD chain model failed");
|
||||||
|
|
||||||
|
auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
|
||||||
|
mapSaplingZKeyMetadata[ivk] = metadata;
|
||||||
|
|
||||||
|
auto addr = xsk.DefaultAddress();
|
||||||
|
if (addToWallet && !AddSaplingZKey(xsk, addr)) {
|
||||||
|
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed");
|
||||||
|
}
|
||||||
|
// return default sapling payment address.
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add spending key to keystore
|
||||||
|
bool CWallet::AddSaplingZKey(
|
||||||
|
const libzcash::SaplingExtendedSpendingKey &sk,
|
||||||
|
const libzcash::SaplingPaymentAddress &defaultAddr)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||||
|
|
||||||
|
if (!CCryptoKeyStore::AddSaplingSpendingKey(sk, defaultAddr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nTimeFirstKey = 1; // No birthday information for viewing keys.
|
||||||
|
if (!fFileBacked) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsCrypted()) {
|
||||||
|
auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
|
||||||
|
return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add payment address -> incoming viewing key map entry
|
||||||
|
bool CWallet::AddSaplingIncomingViewingKey(
|
||||||
|
const libzcash::SaplingIncomingViewingKey &ivk,
|
||||||
|
const libzcash::SaplingPaymentAddress &addr)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||||
|
|
||||||
|
if (!CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fFileBacked) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsCrypted()) {
|
||||||
|
return CWalletDB(strWalletFile).WriteSaplingPaymentAddress(addr, ivk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CPubKey CWallet::GenerateNewKey()
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||||
|
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
|
||||||
|
|
||||||
|
CKey secret;
|
||||||
|
secret.MakeNewKey(fCompressed);
|
||||||
|
|
||||||
|
// Compressed public keys were introduced in version 0.6.0
|
||||||
|
if (fCompressed)
|
||||||
|
SetMinVersion(FEATURE_COMPRPUBKEY);
|
||||||
|
|
||||||
|
CPubKey pubkey = secret.GetPubKey();
|
||||||
|
assert(secret.VerifyPubKey(pubkey));
|
||||||
|
|
||||||
|
// Create new metadata
|
||||||
|
int64_t nCreationTime = GetTime();
|
||||||
|
mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
|
||||||
|
if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
|
||||||
|
nTimeFirstKey = nCreationTime;
|
||||||
|
|
||||||
|
if (!AddKeyPubKey(secret, pubkey))
|
||||||
|
throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
|
||||||
|
return pubkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||||
|
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check if we need to remove from watch-only
|
||||||
|
CScript script;
|
||||||
|
script = GetScriptForDestination(pubkey.GetID());
|
||||||
|
if (HaveWatchOnly(script))
|
||||||
|
RemoveWatchOnly(script);
|
||||||
|
|
||||||
|
if (!fFileBacked)
|
||||||
|
return true;
|
||||||
|
if (!IsCrypted()) {
|
||||||
|
return CWalletDB(strWalletFile).WriteKey(pubkey,
|
||||||
|
secret.GetPrivKey(),
|
||||||
|
mapKeyMetadata[pubkey.GetID()]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
|
||||||
|
const vector<unsigned char> &vchCryptedSecret)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||||
|
return false;
|
||||||
|
if (!fFileBacked)
|
||||||
|
return true;
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
if (pwalletdbEncryption)
|
||||||
|
return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
|
||||||
|
vchCryptedSecret,
|
||||||
|
mapKeyMetadata[vchPubKey.GetID()]);
|
||||||
|
else
|
||||||
|
return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
|
||||||
|
vchCryptedSecret,
|
||||||
|
mapKeyMetadata[vchPubKey.GetID()]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||||
|
const std::vector<unsigned char> &vchCryptedSecret,
|
||||||
|
const libzcash::SaplingPaymentAddress &defaultAddr)
|
||||||
|
{
|
||||||
|
if (!CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, defaultAddr))
|
||||||
|
return false;
|
||||||
|
if (!fFileBacked)
|
||||||
|
return true;
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
if (pwalletdbEncryption) {
|
||||||
|
return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk,
|
||||||
|
vchCryptedSecret,
|
||||||
|
mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
|
||||||
|
} else {
|
||||||
|
return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk,
|
||||||
|
vchCryptedSecret,
|
||||||
|
mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||||
|
if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
|
||||||
|
nTimeFirstKey = meta.nCreateTime;
|
||||||
|
|
||||||
|
mapKeyMetadata[pubkey.GetID()] = meta;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||||
|
{
|
||||||
|
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CWallet::LoadCryptedSaplingZKey(
|
||||||
|
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||||
|
const std::vector<unsigned char> &vchCryptedSecret)
|
||||||
|
{
|
||||||
|
return CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, extfvk.DefaultAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||||
|
mapSaplingZKeyMetadata[ivk] = meta;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
|
||||||
|
{
|
||||||
|
return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadSaplingPaymentAddress(
|
||||||
|
const libzcash::SaplingPaymentAddress &addr,
|
||||||
|
const libzcash::SaplingIncomingViewingKey &ivk)
|
||||||
|
{
|
||||||
|
return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddCScript(const CScript& redeemScript)
|
||||||
|
{
|
||||||
|
if (!CCryptoKeyStore::AddCScript(redeemScript))
|
||||||
|
return false;
|
||||||
|
if (!fFileBacked)
|
||||||
|
return true;
|
||||||
|
return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadCScript(const CScript& redeemScript)
|
||||||
|
{
|
||||||
|
/* A sanity check was added in pull #3843 to avoid adding redeemScripts
|
||||||
|
* that never can be redeemed. However, old wallets may still contain
|
||||||
|
* these. Do not add them to the wallet and warn. */
|
||||||
|
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||||
|
{
|
||||||
|
std::string strAddr = EncodeDestination(CScriptID(redeemScript));
|
||||||
|
LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
|
||||||
|
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CCryptoKeyStore::AddCScript(redeemScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::AddWatchOnly(const CScript &dest)
|
||||||
|
{
|
||||||
|
if (!CCryptoKeyStore::AddWatchOnly(dest))
|
||||||
|
return false;
|
||||||
|
nTimeFirstKey = 1; // No birthday information for watch-only keys.
|
||||||
|
NotifyWatchonlyChanged(true);
|
||||||
|
if (!fFileBacked)
|
||||||
|
return true;
|
||||||
|
return CWalletDB(strWalletFile).WriteWatchOnly(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::RemoveWatchOnly(const CScript &dest)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet);
|
||||||
|
if (!CCryptoKeyStore::RemoveWatchOnly(dest))
|
||||||
|
return false;
|
||||||
|
if (!HaveWatchOnly())
|
||||||
|
NotifyWatchonlyChanged(false);
|
||||||
|
if (fFileBacked)
|
||||||
|
if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadWatchOnly(const CScript &dest)
|
||||||
|
{
|
||||||
|
return CCryptoKeyStore::AddWatchOnly(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wallet encryption and passphrase management
|
||||||
|
//
|
||||||
|
|
||||||
|
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
|
||||||
|
{
|
||||||
|
CCrypter crypter;
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
||||||
|
{
|
||||||
|
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
||||||
|
continue; // try another master key
|
||||||
|
if (CCryptoKeyStore::Unlock(vMasterKey))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
|
||||||
|
{
|
||||||
|
bool fWasLocked = IsLocked();
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
Lock();
|
||||||
|
|
||||||
|
CCrypter crypter;
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
||||||
|
{
|
||||||
|
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
||||||
|
return false;
|
||||||
|
if (CCryptoKeyStore::Unlock(vMasterKey))
|
||||||
|
{
|
||||||
|
int64_t nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||||
|
pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
|
||||||
|
|
||||||
|
nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||||
|
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
|
||||||
|
|
||||||
|
if (pMasterKey.second.nDeriveIterations < 25000)
|
||||||
|
pMasterKey.second.nDeriveIterations = 25000;
|
||||||
|
|
||||||
|
LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
|
||||||
|
|
||||||
|
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
|
||||||
|
return false;
|
||||||
|
CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
|
||||||
|
if (fWasLocked)
|
||||||
|
Lock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||||
|
{
|
||||||
|
if (IsCrypted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CKeyingMaterial vMasterKey;
|
||||||
|
|
||||||
|
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
|
||||||
|
CMasterKey kMasterKey;
|
||||||
|
|
||||||
|
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
|
||||||
|
CCrypter crypter;
|
||||||
|
int64_t nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
|
||||||
|
kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
|
||||||
|
|
||||||
|
nStartTime = GetTimeMillis();
|
||||||
|
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
|
||||||
|
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
|
||||||
|
|
||||||
|
if (kMasterKey.nDeriveIterations < 25000)
|
||||||
|
kMasterKey.nDeriveIterations = 25000;
|
||||||
|
|
||||||
|
LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
|
||||||
|
|
||||||
|
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
|
||||||
|
return false;
|
||||||
|
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
|
||||||
|
if (fFileBacked)
|
||||||
|
{
|
||||||
|
assert(!pwalletdbEncryption);
|
||||||
|
pwalletdbEncryption = new CWalletDB(strWalletFile);
|
||||||
|
if (!pwalletdbEncryption->TxnBegin()) {
|
||||||
|
delete pwalletdbEncryption;
|
||||||
|
pwalletdbEncryption = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EncryptKeys(vMasterKey))
|
||||||
|
{
|
||||||
|
if (fFileBacked) {
|
||||||
|
pwalletdbEncryption->TxnAbort();
|
||||||
|
delete pwalletdbEncryption;
|
||||||
|
}
|
||||||
|
// We now probably have half of our keys encrypted in memory, and half not...
|
||||||
|
// die and let the user reload the unencrypted wallet.
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encryption was introduced in version 0.4.0
|
||||||
|
SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
|
||||||
|
|
||||||
|
if (fFileBacked)
|
||||||
|
{
|
||||||
|
if (!pwalletdbEncryption->TxnCommit()) {
|
||||||
|
delete pwalletdbEncryption;
|
||||||
|
// We now have keys encrypted in memory, but not on disk...
|
||||||
|
// die to avoid confusion and let the user reload the unencrypted wallet.
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pwalletdbEncryption;
|
||||||
|
pwalletdbEncryption = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock();
|
||||||
|
Unlock(strWalletPassphrase);
|
||||||
|
NewKeyPool();
|
||||||
|
Lock();
|
||||||
|
|
||||||
|
// Need to completely rewrite the wallet file; if we don't, bdb might keep
|
||||||
|
// bits of the unencrypted private key in slack space in the database file.
|
||||||
|
CDB::Rewrite(strWalletFile);
|
||||||
|
|
||||||
|
}
|
||||||
|
NotifyStatusChanged(this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// HD wallet seed management
|
||||||
|
//
|
||||||
|
|
||||||
|
bool CWallet::IsHDFullyEnabled() const
|
||||||
|
{
|
||||||
|
// Only Sapling addresses are HD for now
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::GenerateNewSeed()
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
|
||||||
|
auto seed = HDSeed::Random(HD_WALLET_SEED_LENGTH);
|
||||||
|
|
||||||
|
int64_t nCreationTime = GetTime();
|
||||||
|
|
||||||
|
// If the wallet is encrypted and locked, this will fail.
|
||||||
|
if (!SetHDSeed(seed))
|
||||||
|
throw std::runtime_error(std::string(__func__) + ": SetHDSeed failed");
|
||||||
|
|
||||||
|
// store the key creation time together with
|
||||||
|
// the child index counter in the database
|
||||||
|
// as a hdchain object
|
||||||
|
CHDChain newHdChain;
|
||||||
|
newHdChain.nVersion = CHDChain::VERSION_HD_BASE;
|
||||||
|
newHdChain.seedFp = seed.Fingerprint();
|
||||||
|
newHdChain.nCreateTime = nCreationTime;
|
||||||
|
SetHDChain(newHdChain, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::SetHDSeed(const HDSeed& seed)
|
||||||
|
{
|
||||||
|
if (!CCryptoKeyStore::SetHDSeed(seed)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fFileBacked) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
if (!IsCrypted()) {
|
||||||
|
return CWalletDB(strWalletFile).WriteHDSeed(seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret)
|
||||||
|
{
|
||||||
|
if (!CCryptoKeyStore::SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fFileBacked) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
if (pwalletdbEncryption)
|
||||||
|
return pwalletdbEncryption->WriteCryptedHDSeed(seedFp, vchCryptedSecret);
|
||||||
|
else
|
||||||
|
return CWalletDB(strWalletFile).WriteCryptedHDSeed(seedFp, vchCryptedSecret);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
if (!memonly && fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(chain))
|
||||||
|
throw std::runtime_error(std::string(__func__) + ": writing chain failed");
|
||||||
|
|
||||||
|
hdChain = chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadHDSeed(const HDSeed& seed)
|
||||||
|
{
|
||||||
|
return CBasicKeyStore::SetHDSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed)
|
||||||
|
{
|
||||||
|
return CCryptoKeyStore::SetCryptedHDSeed(seedFp, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Key pool management
|
||||||
|
//
|
||||||
|
|
||||||
|
bool CWallet::NewKeyPool()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
BOOST_FOREACH(int64_t nIndex, setKeyPool)
|
||||||
|
walletdb.ErasePool(nIndex);
|
||||||
|
setKeyPool.clear();
|
||||||
|
|
||||||
|
if (IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
|
||||||
|
for (int i = 0; i < nKeys; i++)
|
||||||
|
{
|
||||||
|
int64_t nIndex = i+1;
|
||||||
|
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
|
||||||
|
setKeyPool.insert(nIndex);
|
||||||
|
}
|
||||||
|
LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::TopUpKeyPool(unsigned int kpSize)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
|
||||||
|
if (IsLocked())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
|
||||||
|
// Top up key pool
|
||||||
|
unsigned int nTargetSize;
|
||||||
|
if (kpSize > 0)
|
||||||
|
nTargetSize = kpSize;
|
||||||
|
else
|
||||||
|
nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
|
||||||
|
|
||||||
|
while (setKeyPool.size() < (nTargetSize + 1))
|
||||||
|
{
|
||||||
|
int64_t nEnd = 1;
|
||||||
|
if (!setKeyPool.empty())
|
||||||
|
nEnd = *(--setKeyPool.end()) + 1;
|
||||||
|
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
|
||||||
|
throw runtime_error("TopUpKeyPool(): writing generated key failed");
|
||||||
|
setKeyPool.insert(nEnd);
|
||||||
|
LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
|
||||||
|
{
|
||||||
|
nIndex = -1;
|
||||||
|
keypool.vchPubKey = CPubKey();
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
|
||||||
|
if (!IsLocked())
|
||||||
|
TopUpKeyPool();
|
||||||
|
|
||||||
|
// Get the oldest key
|
||||||
|
if(setKeyPool.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
|
||||||
|
nIndex = *(setKeyPool.begin());
|
||||||
|
setKeyPool.erase(setKeyPool.begin());
|
||||||
|
if (!walletdb.ReadPool(nIndex, keypool))
|
||||||
|
throw runtime_error("ReserveKeyFromKeyPool(): read failed");
|
||||||
|
if (!HaveKey(keypool.vchPubKey.GetID()))
|
||||||
|
throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
|
||||||
|
assert(keypool.vchPubKey.IsValid());
|
||||||
|
//LogPrintf("keypool reserve %d\n", nIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::KeepKey(int64_t nIndex)
|
||||||
|
{
|
||||||
|
// Remove from key pool
|
||||||
|
if (fFileBacked)
|
||||||
|
{
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
walletdb.ErasePool(nIndex);
|
||||||
|
}
|
||||||
|
LogPrintf("keypool keep %d\n", nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::ReturnKey(int64_t nIndex)
|
||||||
|
{
|
||||||
|
// Return to key pool
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
setKeyPool.insert(nIndex);
|
||||||
|
}
|
||||||
|
//LogPrintf("keypool return %d\n", nIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::GetKeyFromPool(CPubKey& result)
|
||||||
|
{
|
||||||
|
int64_t nIndex = 0;
|
||||||
|
CKeyPool keypool;
|
||||||
|
{
|
||||||
|
LOCK(cs_wallet);
|
||||||
|
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
|
if (nIndex == -1)
|
||||||
|
{
|
||||||
|
if (IsLocked()) return false;
|
||||||
|
result = GenerateNewKey();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
KeepKey(nIndex);
|
||||||
|
result = keypool.vchPubKey;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t CWallet::GetOldestKeyPoolTime()
|
||||||
|
{
|
||||||
|
int64_t nIndex = 0;
|
||||||
|
CKeyPool keypool;
|
||||||
|
ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
|
if (nIndex == -1)
|
||||||
|
return GetTime();
|
||||||
|
ReturnKey(nIndex);
|
||||||
|
return keypool.nTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CReserveKey
|
||||||
|
//
|
||||||
|
|
||||||
|
bool CReserveKey::GetReservedKey(CPubKey& pubkey)
|
||||||
|
{
|
||||||
|
if (nIndex == -1)
|
||||||
|
{
|
||||||
|
CKeyPool keypool;
|
||||||
|
pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
|
||||||
|
if (nIndex != -1)
|
||||||
|
vchPubKey = keypool.vchPubKey;
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(vchPubKey.IsValid());
|
||||||
|
pubkey = vchPubKey;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CReserveKey::KeepKey()
|
||||||
|
{
|
||||||
|
if (nIndex != -1)
|
||||||
|
pwallet->KeepKey(nIndex);
|
||||||
|
nIndex = -1;
|
||||||
|
vchPubKey = CPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CReserveKey::ReturnKey()
|
||||||
|
{
|
||||||
|
if (nIndex != -1)
|
||||||
|
pwallet->ReturnKey(nIndex);
|
||||||
|
nIndex = -1;
|
||||||
|
vchPubKey = CPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
|
||||||
|
{
|
||||||
|
setAddress.clear();
|
||||||
|
|
||||||
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
|
||||||
|
LOCK2(cs_main, cs_wallet);
|
||||||
|
BOOST_FOREACH(const int64_t& id, setKeyPool)
|
||||||
|
{
|
||||||
|
CKeyPool keypool;
|
||||||
|
if (!walletdb.ReadPool(id, keypool))
|
||||||
|
throw runtime_error("GetAllReserveKeyHashes(): read failed");
|
||||||
|
assert(keypool.vchPubKey.IsValid());
|
||||||
|
CKeyID keyID = keypool.vchPubKey.GetID();
|
||||||
|
if (!HaveKey(keyID))
|
||||||
|
throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
|
||||||
|
setAddress.insert(keyID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Key birth times
|
||||||
|
//
|
||||||
|
|
||||||
|
class CAffectedKeysVisitor : public boost::static_visitor<void> {
|
||||||
|
private:
|
||||||
|
const CKeyStore &keystore;
|
||||||
|
std::vector<CKeyID> &vKeys;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
|
||||||
|
|
||||||
|
void Process(const CScript &script) {
|
||||||
|
txnouttype type;
|
||||||
|
std::vector<CTxDestination> vDest;
|
||||||
|
int nRequired;
|
||||||
|
if (ExtractDestinations(script, type, vDest, nRequired)) {
|
||||||
|
BOOST_FOREACH(const CTxDestination &dest, vDest)
|
||||||
|
boost::apply_visitor(*this, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const CKeyID &keyId) {
|
||||||
|
if (keystore.HaveKey(keyId))
|
||||||
|
vKeys.push_back(keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const CPubKey &key) {
|
||||||
|
CKeyID keyId = key.GetID();
|
||||||
|
if (keystore.HaveKey(keyId))
|
||||||
|
vKeys.push_back(keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const CScriptID &scriptId) {
|
||||||
|
CScript script;
|
||||||
|
if (keystore.GetCScript(scriptId, script))
|
||||||
|
Process(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const CNoDestination &none) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
|
||||||
|
AssertLockHeld(cs_wallet); // mapKeyMetadata
|
||||||
|
mapKeyBirth.clear();
|
||||||
|
|
||||||
|
// get birth times for keys with metadata
|
||||||
|
for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
|
||||||
|
if (it->second.nCreateTime)
|
||||||
|
mapKeyBirth[it->first] = it->second.nCreateTime;
|
||||||
|
|
||||||
|
// map in which we'll infer heights of other keys
|
||||||
|
CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
|
||||||
|
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
|
||||||
|
std::set<CKeyID> setKeys;
|
||||||
|
GetKeys(setKeys);
|
||||||
|
BOOST_FOREACH(const CKeyID &keyid, setKeys) {
|
||||||
|
if (mapKeyBirth.count(keyid) == 0)
|
||||||
|
mapKeyFirstBlock[keyid] = pindexMax;
|
||||||
|
}
|
||||||
|
setKeys.clear();
|
||||||
|
|
||||||
|
// if there are no such keys, we're done
|
||||||
|
if (mapKeyFirstBlock.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find first block that affects those keys, if there are any left
|
||||||
|
std::vector<CKeyID> vAffected;
|
||||||
|
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
|
||||||
|
// iterate over all wallet transactions...
|
||||||
|
const CWalletTx &wtx = (*it).second;
|
||||||
|
BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
|
||||||
|
if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
|
||||||
|
// ... which are already in a block
|
||||||
|
int nHeight = blit->second->GetHeight();
|
||||||
|
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
|
||||||
|
// iterate over all their outputs
|
||||||
|
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
|
||||||
|
BOOST_FOREACH(const CKeyID &keyid, vAffected) {
|
||||||
|
// ... and all their affected keys
|
||||||
|
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
|
||||||
|
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->GetHeight())
|
||||||
|
rit->second = blit->second;
|
||||||
|
}
|
||||||
|
vAffected.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract block timestamps for those keys
|
||||||
|
for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
|
||||||
|
mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Shielded key and address generalizations
|
||||||
|
//
|
||||||
|
|
||||||
|
bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
|
||||||
|
{
|
||||||
|
libzcash::SaplingIncomingViewingKey ivk;
|
||||||
|
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
|
||||||
|
{
|
||||||
|
libzcash::SaplingIncomingViewingKey ivk;
|
||||||
|
|
||||||
|
// If we have a SaplingExtendedSpendingKey in the wallet, then we will
|
||||||
|
// also have the corresponding SaplingFullViewingKey.
|
||||||
|
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
||||||
|
m_wallet->HaveSaplingFullViewingKey(ivk);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
|
||||||
|
{
|
||||||
|
libzcash::SaplingIncomingViewingKey ivk;
|
||||||
|
libzcash::SaplingFullViewingKey fvk;
|
||||||
|
|
||||||
|
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
||||||
|
m_wallet->GetSaplingFullViewingKey(ivk, fvk) &&
|
||||||
|
m_wallet->HaveSaplingSpendingKey(fvk);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::InvalidEncoding& no) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
|
||||||
|
const libzcash::SaplingPaymentAddress &zaddr) const
|
||||||
|
{
|
||||||
|
libzcash::SaplingExtendedSpendingKey extsk;
|
||||||
|
if (m_wallet->GetSaplingExtendedSpendingKey(zaddr, extsk)) {
|
||||||
|
return libzcash::SpendingKey(extsk);
|
||||||
|
} else {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
|
||||||
|
const libzcash::InvalidEncoding& no) const
|
||||||
|
{
|
||||||
|
// Defaults to InvalidEncoding
|
||||||
|
return libzcash::SpendingKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
|
||||||
|
auto fvk = sk.expsk.full_viewing_key();
|
||||||
|
auto ivk = fvk.in_viewing_key();
|
||||||
|
auto addr = sk.DefaultAddress();
|
||||||
|
{
|
||||||
|
if (log){
|
||||||
|
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
|
||||||
|
}
|
||||||
|
// Don't throw error in case a key is already there
|
||||||
|
if (m_wallet->HaveSaplingSpendingKey(fvk)) {
|
||||||
|
return KeyAlreadyExists;
|
||||||
|
} else {
|
||||||
|
if (!m_wallet-> AddSaplingZKey(sk, addr)) {
|
||||||
|
return KeyNotAdded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sapling addresses can't have been used in transactions prior to activation.
|
||||||
|
if (params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight == Consensus::NetworkUpgrade::ALWAYS_ACTIVE) {
|
||||||
|
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime;
|
||||||
|
} else {
|
||||||
|
// TODO: set a better time for HUSH+DRAGONX
|
||||||
|
// 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
|
||||||
|
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
|
||||||
|
}
|
||||||
|
if (hdKeypath) {
|
||||||
|
m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.get();
|
||||||
|
}
|
||||||
|
if (seedFpStr) {
|
||||||
|
uint256 seedFp;
|
||||||
|
seedFp.SetHex(seedFpStr.get());
|
||||||
|
m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
|
||||||
|
}
|
||||||
|
return KeyAdded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
|
||||||
|
}
|
||||||
16
src/zush
16
src/zush
@@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright (c) 2016-2024 The Hush developers
|
|
||||||
|
|
||||||
# set working directory to the location of this script
|
|
||||||
# readlink -f does not always exist
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
|
|
||||||
cd $DIR
|
|
||||||
|
|
||||||
NAME=ZUSH
|
|
||||||
|
|
||||||
CLI=${HUSHCLI:-./hush-cli}
|
|
||||||
if [ -f $CLI ]; then
|
|
||||||
$CLI -ac_name=$NAME "$@"
|
|
||||||
fi
|
|
||||||
@@ -82,10 +82,10 @@ cp $SRC_PATH/src/hush-tx $DEB_BIN
|
|||||||
strip $DEB_BIN/hush-tx
|
strip $DEB_BIN/hush-tx
|
||||||
|
|
||||||
# these are scripts and don't require a strip
|
# these are scripts and don't require a strip
|
||||||
cp $SRC_PATH/src/dragonx-cli $DEB_BIN
|
cp $SRC_PATH/contrib/scripts/dragonx-cli $DEB_BIN
|
||||||
cp $SRC_PATH/src/dragonxd $DEB_BIN
|
cp $SRC_PATH/contrib/scripts/dragonxd $DEB_BIN
|
||||||
|
|
||||||
cp $SRC_PATH/src/hush-arrakis-chain $DEB_BIN
|
cp $SRC_PATH/contrib/scripts/hush-arrakis-chain $DEB_BIN
|
||||||
cp $SRC_DEB/changelog $DEB_DOC
|
cp $SRC_DEB/changelog $DEB_DOC
|
||||||
cp $SRC_DEB/copyright $DEB_DOC
|
cp $SRC_DEB/copyright $DEB_DOC
|
||||||
cp -r $SRC_DEB/examples $DEB_DOC
|
cp -r $SRC_DEB/examples $DEB_DOC
|
||||||
|
|||||||
@@ -97,3 +97,34 @@ CXXFLAGS="${EXTRA_CXXFLAGS} -I$PREFIX/include" \
|
|||||||
./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG"
|
./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG"
|
||||||
|
|
||||||
make "$@" V=1 NO_GTEST=1 STATIC=1
|
make "$@" V=1 NO_GTEST=1 STATIC=1
|
||||||
|
|
||||||
|
# Package release
|
||||||
|
echo "Creating macOS release package..."
|
||||||
|
VERSION=$(grep -oP 'define\(_CLIENT_VERSION.*?,\s*\K[0-9]+' configure.ac | head -3 | tr '\n' '.' | sed 's/\.$//')
|
||||||
|
VERSION=${VERSION:-3.10.5}
|
||||||
|
RELEASE_DIR="release/${VERSION}-mac"
|
||||||
|
mkdir -p "$RELEASE_DIR"
|
||||||
|
|
||||||
|
# Strip binaries
|
||||||
|
strip src/hushd src/hush-cli src/hush-tx 2>/dev/null || true
|
||||||
|
|
||||||
|
# Copy binaries
|
||||||
|
cp src/hushd src/hush-cli src/hush-tx "$RELEASE_DIR/"
|
||||||
|
|
||||||
|
# Copy wrapper scripts
|
||||||
|
cp contrib/scripts/hush-arrakis-chain contrib/scripts/dragonxd contrib/scripts/dragonx-cli "$RELEASE_DIR/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Copy required data files
|
||||||
|
cp asmap.dat sapling-spend.params sapling-output.params "$RELEASE_DIR/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Copy bootstrap script
|
||||||
|
cp contrib/bootstrap/bootstrap-dragonx.sh "$RELEASE_DIR/" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Create ZIP
|
||||||
|
rm -f "$RELEASE_DIR/${VERSION}-mac.zip"
|
||||||
|
cd "$RELEASE_DIR"
|
||||||
|
zip -9 "${VERSION}-mac.zip" *
|
||||||
|
cd ../..
|
||||||
|
|
||||||
|
echo "Release package created: $RELEASE_DIR/${VERSION}-mac.zip"
|
||||||
|
ls -lh "$RELEASE_DIR/${VERSION}-mac.zip"
|
||||||
|
|||||||
@@ -39,6 +39,15 @@ fi
|
|||||||
cd $WD
|
cd $WD
|
||||||
|
|
||||||
sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure
|
sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure
|
||||||
|
|
||||||
|
# Clean any stale native-compiled objects before cross-compiling.
|
||||||
|
# If objects were previously built with the native Linux compiler (ELF format),
|
||||||
|
# make won't recompile them for Windows (COFF format), causing link failures.
|
||||||
|
if [ -f src/libbitcoin_server.a ]; then
|
||||||
|
echo "Cleaning previous build objects to ensure Windows cross-compilation..."
|
||||||
|
cd src/ && make clean 2>/dev/null || true && cd ..
|
||||||
|
fi
|
||||||
|
|
||||||
cd src/
|
cd src/
|
||||||
CC="${CC} -g " CXX="${CXX} -g " make V=1 hushd.exe hush-cli.exe hush-tx.exe
|
CC="${CC} -g " CXX="${CXX} -g " make V=1 hushd.exe hush-cli.exe hush-tx.exe
|
||||||
|
|
||||||
@@ -47,7 +56,7 @@ cd $WD
|
|||||||
echo "Creating Windows release package..."
|
echo "Creating Windows release package..."
|
||||||
VERSION=$(grep -oP 'define\(_CLIENT_VERSION.*?,\s*\K[0-9]+' configure.ac | head -3 | tr '\n' '.' | sed 's/\.$//')
|
VERSION=$(grep -oP 'define\(_CLIENT_VERSION.*?,\s*\K[0-9]+' configure.ac | head -3 | tr '\n' '.' | sed 's/\.$//')
|
||||||
VERSION=${VERSION:-3.10.5}
|
VERSION=${VERSION:-3.10.5}
|
||||||
RELEASE_DIR="release-win64"
|
RELEASE_DIR="release/${VERSION}-win"
|
||||||
mkdir -p "$RELEASE_DIR"
|
mkdir -p "$RELEASE_DIR"
|
||||||
|
|
||||||
# Strip binaries
|
# Strip binaries
|
||||||
@@ -89,10 +98,10 @@ EOF
|
|||||||
cp contrib/bootstrap/bootstrap-dragonx.bat "$RELEASE_DIR/"
|
cp contrib/bootstrap/bootstrap-dragonx.bat "$RELEASE_DIR/"
|
||||||
|
|
||||||
# Create ZIP
|
# Create ZIP
|
||||||
rm -f "$RELEASE_DIR/hush-${VERSION}-win64.zip"
|
rm -f "$RELEASE_DIR/${VERSION}-win.zip"
|
||||||
cd "$RELEASE_DIR"
|
cd "$RELEASE_DIR"
|
||||||
zip -9 "hush-${VERSION}-win64.zip" *.exe *.bat *.dat *.params
|
zip -9 "${VERSION}-win.zip" *.exe *.bat *.dat *.params
|
||||||
cd ..
|
cd ../..
|
||||||
|
|
||||||
echo "Release package created: $RELEASE_DIR/hush-${VERSION}-win64.zip"
|
echo "Release package created: $RELEASE_DIR/${VERSION}-win.zip"
|
||||||
ls -lh "$RELEASE_DIR/hush-${VERSION}-win64.zip"
|
ls -lh "$RELEASE_DIR/${VERSION}-win.zip"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ set -x
|
|||||||
#hardcode and uncomment if hushd is not running on this machine
|
#hardcode and uncomment if hushd is not running on this machine
|
||||||
#VERSION=3.6.3
|
#VERSION=3.6.3
|
||||||
VERSION=$(./src/hushd --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="hush-$VERSION-linux-amd64"
|
DIR="$VERSION-linux-amd64"
|
||||||
FILE="$DIR.tar"
|
FILE="$DIR.tar"
|
||||||
TIME=$(perl -e 'print time')
|
TIME=$(perl -e 'print time')
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ cp hushd hush-cli hush-tx hush-arrakis-chain dragonx-cli dragonxd ../$BUILD
|
|||||||
cd ../$BUILD
|
cd ../$BUILD
|
||||||
strip hushd hush-cli hush-tx
|
strip hushd hush-cli hush-tx
|
||||||
cd ..
|
cd ..
|
||||||
tar -f $FILE -c hush-$VERSION-linux-amd64/*
|
tar -f $FILE -c $VERSION-linux-amd64/*
|
||||||
gzip -9 $FILE
|
gzip -9 $FILE
|
||||||
sha256sum *.gz
|
sha256sum *.gz
|
||||||
du -sh *.gz
|
du -sh *.gz
|
||||||
|
|||||||
Reference in New Issue
Block a user