Browse Source

Merge remote-tracking branch 'remotes/origin/dev' into v1.0.15-dev

v1.0.15-dev
FireMartZ 6 years ago
parent
commit
b03e2b74b4
  1. 136
      INSTALL.md
  2. 6
      README.md
  3. 4
      configure.ac
  4. 6
      depends/packages/libsodium.mk
  5. 3
      depends/packages/proton.mk
  6. 37
      depends/packages/rust.mk
  7. 12
      doc/man/hush-cli.1
  8. 12
      doc/man/hush-tx.1
  9. 16
      doc/man/hushd.1
  10. 4
      doc/unit-tests.md
  11. 1
      qa/pull-tester/rpc-tests.sh
  12. 38
      qa/rpc-tests/dpow.py
  13. 18
      qa/rpc-tests/getchaintips.py
  14. 29
      qa/rpc-tests/test_framework/util.py
  15. 60
      qa/rpc-tests/wallet.py
  16. 2
      src/Makefile.am
  17. 13
      src/chain.h
  18. 3
      src/clientversion.cpp
  19. 13
      src/init.cpp
  20. 227
      src/key_io.cpp
  21. 29
      src/key_io.h
  22. 103
      src/komodo_rpcblockchain.h
  23. 1248
      src/komodo_validation011.h
  24. 28
      src/main.cpp
  25. 1
      src/main.h
  26. 5
      src/primitives/transaction.h
  27. 18
      src/rpcblockchain.cpp
  28. 2
      src/rpcclient.cpp
  29. 91
      src/rpcmisc.cpp
  30. 6
      src/rpcserver.cpp
  31. 9
      src/script/standard.cpp
  32. 3
      src/script/standard.h
  33. 38
      src/wallet/rpcdump.cpp
  34. 27
      src/wallet/rpcwallet.cpp
  35. 63
      src/wallet/wallet.cpp
  36. 83
      src/wallet/wallet.h
  37. 4
      zcutil/build-debian-package.sh

136
INSTALL.md

@ -1,95 +1,87 @@
# Installing Hush
## Install
## Download and Install Hush v2.0.0 Stable Release
echo 'deb https://dl.bintray.com/myhush/hush/ hush main' | sudo tee --append /etc/apt/sources.list.d/hush.list
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61
sudo apt-get update
sudo apt-get install hush
## Create a HUSH configuration file (*important*):
```
mkdir -p ~/.hush
echo "rpcuser=username" >> ~/.hush/hush.conf
echo "rpcpassword=`head -c 32 /dev/urandom | base64`" >>~/.hush/hush.conf
echo "addnode=explorer.myhush.org" >> ~/.hush/hush.conf
echo "addnode=dnsseed.myhush.org" >> ~/.hush/hush.conf
echo "addnode=dnsseed2.myhush.org" >> ~/.hush/hush.conf
echo "addnode=dnsseed.bleuzero.com" >> ~/.hush/hush.conf
echo "addnode=dnsseed.hush.quebec" >> ~/.hush/hush.conf
```
## Download proving key
This will download a Zcash Sprout proving key, if you already have one on this system, you only need one
and this script will just verify that it is correct.
This method can be used to install release packages:
```sh
cd ~
sudo wget https://github.com/MyHush/hush/releases/download/v2.0.0/hush-2.0.0-c7d6ba61-amd64.deb
sudo dpkg -i hush-2.0.0-c7d6ba61-amd64.deb
```
./zcutil/fetch-params.sh
```
# Building Hush from source
Building Hush from source will take some time but your efforts will be rewarded :)
## Requirements
To install Hush from source, read on.
You will need at least 4GB of RAM to build hush from git source, OR
you can enable a swap file. To enable a 4GB swap file on modern Linux
distributions:
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
You will need to have Git and a C++ compiler and libtool and a
a few other libraries, depending on your setup.
## Building
## Build HUSH dependencies
The following build process generally applies to Ubuntu (and similar) Linux
distributions. For best results it is recommended to use Ubuntu Linux 16.04
or later.
Build HUSH along with most dependencies from source by running:
## Swap Space (Optional)
You will need at least 4GB of RAM to build hush from git source, OR you can
enable a swap file. To enable a 4GB swap file on modern Linux distributions:
## Linux
Get dependencies:
```{r, engine='bash'}
sudo apt-get install \
build-essential pkg-config libc6-dev m4 g++-multilib \
autoconf libtool ncurses-dev unzip git python \
zlib1g-dev wget bsdmainutils automake cmake g++-mingw-w64-x86-64
```sh
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```
Downloading Git source repo, building and running Hush:
## Build on Linux:
```{r, engine='bash'}
```sh
# install build depedencies
sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib \
autoconf libtool ncurses-dev unzip git python zlib1g-dev wget \
bsdmainutils automake curl unzip nano
# pull
git clone https://github.com/MyHush/hush.git
cd hush
# fetch key
./zcutil/fetch-params.sh
# Build
./zcutil/build.sh -j$(nproc)
# Run a HUSH node
./src/hushd
```
## Download proving key:
```sh
./zcutil/fetch-params.sh
```
## Create a HUSH configuration file (*important*):
You can compile Hush without this, but need a config file to run hushd.
```sh
mkdir -p ~/.hush
echo "rpcuser=username" >> ~/.hush/hush.conf
echo "rpcpassword=`head -c 32 /dev/urandom | base64`" >>~/.hush/hush.conf
echo "addnode=explorer.myhush.org" >> ~/.hush/hush.conf
echo "addnode=dnsseed.myhush.org" >> ~/.hush/hush.conf
echo "addnode=dnsseed2.myhush.org" >> ~/.hush/hush.conf
echo "addnode=dnsseed.bleuzero.com" >> ~/.hush/hush.conf
echo "addnode=dnsseed.hush.quebec" >> ~/.hush/hush.conf
```
## Run a HUSH Node
```sh
./hushd
```
## Windows (cross-compiled on Linux)
Get dependencies:
```{r, engine='bash'}
```ssh
sudo apt-get install \
build-essential pkg-config libc6-dev m4 g++-multilib \
autoconf libtool ncurses-dev unzip git python \
zlib1g-dev wget bsdmainutils automake mingw-w64
zlib1g-dev wget bsdmainutils automake mingw-w64 cmake
```
Downloading Git source repo, building and running Hush:
```{r, engine='bash'}
```sh
# pull
git clone https://github.com/MyHush/hush.git
cd hush
@ -102,28 +94,19 @@ cd hush
```
## Mac
Get dependencies:
Install Xcode CLI tools:
```{r, engine='bash'}
# Install xcode
```sh
xcode-select --install
# Install brew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install cmake autoconf libtool automake coreutils pkgconfig gmp wget
brew install gcc5 --without-multilib
```
Downloading Git source repo, building and running Hush:
```{r, engine='bash'}
```sh
# pull
git clone https://github.com/MyHush/hush.git
cd hush
# fetch key
./zcutil/fetch-params.sh
# Build
./zcutil/build-mac.sh
git clone -b v2.0.0 https://github.com/FireMartZ/hush-apple.git
cd hush-apple
source environment
make
# Run a HUSH node
./src/hushd
```
@ -144,4 +127,3 @@ set.
This also means that RaspberryPi devices will not work, unless they have a
newer ARMv8-based Raspberry Pi.

6
README.md

@ -1,4 +1,4 @@
# HUSH 1.0.15
# HUSH 2.0.0
## What is HUSH?
@ -7,7 +7,7 @@
HUSH (formerly Zdash) is a code fork of [ZCash](https://z.cash/) which has it's own genesis block.
Based on Bitcoin's code, it intends to offer a far higher standard of privacy
through a sophisticated zero-knowledge proving scheme that preserves
confidentiality of transaction metadata.
confidentiality of transaction metadata.
This software is the HUSH node and command-line client. It downloads and stores the entire history
of HUSH transactions; depending on the speed of your computer and network
@ -94,7 +94,7 @@ The section of using the command line is relevant to HUSH.
### Not content with command line use of HUSH?
A [HUSH GUI Wallet](https://github.com/MyHush/hush-swing-wallet-ui/releases/tag/v0.71.2-beta)
A [HUSH GUI Wallet](https://github.com/MyHush/hush-swing-wallet-ui/releases)
License
-------

4
configure.ac

@ -1,8 +1,8 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 1)
define(_CLIENT_VERSION_MAJOR, 2)
define(_CLIENT_VERSION_MINOR, 0)
define(_CLIENT_VERSION_REVISION, 15)
define(_CLIENT_VERSION_REVISION, 0)
define(_CLIENT_VERSION_BUILD, 50)
define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))

6
depends/packages/libsodium.mk

@ -1,8 +1,8 @@
package=libsodium
$(package)_version=1.0.15
$(package)_version=1.0.16
$(package)_download_path=https://download.libsodium.org/libsodium/releases/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4
$(package)_file_name=libsodium-1.0.16.tar.gz
$(package)_sha256_hash=eeadc7e1e1bcef09680fb4837d448fbdf57224978f865ac1c16745868fbd0533
$(package)_dependencies=
$(package)_config_opts=

3
depends/packages/proton.mk

@ -1,6 +1,6 @@
package=proton
$(package)_version=0.17.0
$(package)_download_path=http://apache.cs.utah.edu/qpid/proton/$($(package)_version)
$(package)_download_path=https://archive.apache.org/dist/qpid/proton/$($(package)_version)
$(package)_file_name=qpid-proton-$($(package)_version).tar.gz
$(package)_sha256_hash=6ffd26d3d0e495bfdb5d9fefc5349954e6105ea18cc4bb191161d27742c5a01a
$(package)_patches=minimal-build.patch
@ -21,4 +21,3 @@ endef
define $(package)_stage_cmds
cd build; $(MAKE) VERBOSE=1 DESTDIR=$($(package)_staging_prefix_dir) install
endef

37
depends/packages/rust.mk

@ -1,11 +1,40 @@
package=rust
$(package)_version=1.16.0
$(package)_version=1.28.0
$(package)_download_path=https://static.rust-lang.org/dist
$(package)_file_name=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz
$(package)_sha256_hash=48621912c242753ba37cad5145df375eeba41c81079df46f93ffb4896542e8fd
$(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz
$(package)_sha256_hash_linux=2a1390340db1d24a9498036884e6b2748e9b4b057fc5219694e298bdaa37b810
$(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz
$(package)_sha256_hash_darwin=2d08259ee038d3a2c77a93f1a31fc59e7a1d6d1bbfcba3dba3c8213b2e5d1926
$(package)_sha256_hash_darwin=5d7a70ed4701fe9410041c1eea025c95cad97e5b3d8acc46426f9ac4f9f02393
$(package)_file_name_mingw32=rust-$($(package)_version)-x86_64-pc-windows-gnu.tar.gz
$(package)_sha256_hash_mingw32=55c07426f791c51c8a2b6934b35784175c4abb4e03f123f3e847109c4dc1ad8b
ifeq ($(host_os),mingw32)
$(package)_build_subdir=buildos
$(package)_extra_sources = $($(package)_file_name_$(build_os))
define $(package)_fetch_cmds
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_file_name_$(build_os)),$($(package)_file_name_$(build_os)),$($(package)_sha256_hash_$(build_os)))
endef
define $(package)_extract_cmds
mkdir -p $($(package)_extract_dir) && \
echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
echo "$($(package)_sha256_hash_$(build_os)) $($(package)_source_dir)/$($(package)_file_name_$(build_os))" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
$(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
mkdir mingw32 && \
tar --strip-components=1 -xf $($(package)_source) -C mingw32 && \
mkdir buildos && \
tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_file_name_$(build_os)) -C buildos
endef
define $(package)_stage_cmds
./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \
cp -r ../mingw32/rust-std-x86_64-pc-windows-gnu/lib/rustlib/x86_64-pc-windows-gnu $($(package)_staging_dir)$(host_prefix)/native/lib/rustlib
endef
else
define $(package)_stage_cmds
./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig
endef
endif

12
doc/man/hush-cli.1

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
.TH HUSH-CLI "1" "March 2018" "hush-cli v1.0.14-a0d4aef" "User Commands"
.TH HUSH-CLI "1" "October 2018" "hush-cli v2.0.0" "User Commands"
.SH NAME
hush-cli \- manual page for hush-cli v1.0.14-a0d4aef
hush-cli \- manual page for hush-cli v2.0.0
.SH DESCRIPTION
Hush RPC client version v1.0.14\-a0d4aef
Hush RPC client version v2.0.0
.PP
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://github.com/MyHush/hush/blob/master/doc/security.md>.
@ -70,9 +70,9 @@ Timeout in seconds during HTTP requests, or 0 for no timeout. (default:
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://github.com/MyHush/hush/blob/master/doc/security.md>.
Copyright (C) 2009-2017 The Bitcoin Core Developers
Copyright (C) 2015-2017 The Zcash Developers
Copyright (C) 2016-2017 The Hush Developers
Copyright (C) 2009-2018 The Bitcoin Core Developers
Copyright (C) 2015-2018 The Zcash Developers
Copyright (C) 2016-2018 The Hush Developers
This is experimental software.

12
doc/man/hush-tx.1

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
.TH HUSH-TX "1" "March 2018" "hush-tx v1.0.14-a0d4aef" "User Commands"
.TH HUSH-TX "1" "October 2018" "hush-tx v2.0.0" "User Commands"
.SH NAME
hush-tx \- manual page for hush-tx v1.0.14-a0d4aef
hush-tx \- manual page for hush-tx v2.0.0
.SH DESCRIPTION
Hush hush\-tx utility version v1.0.14\-a0d4aef
Hush hush\-tx utility version v2.0.0
.SS "Usage:"
.TP
hush\-tx [options] <hex\-tx> [commands]
@ -88,9 +88,9 @@ Set register NAME to given JSON\-STRING
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://github.com/MyHush/hush/blob/master/doc/security.md>.
Copyright (C) 2009-2017 The Bitcoin Core Developers
Copyright (C) 2015-2017 The Zcash Developers
Copyright (C) 2016-2017 The Hush Developers
Copyright (C) 2009-2018 The Bitcoin Core Developers
Copyright (C) 2015-2018 The Zcash Developers
Copyright (C) 2016-2018 The Hush Developers
This is experimental software.

16
doc/man/hushd.1

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3.
.TH HUSHD "1" "March 2018" "hushd v1.0.14-a0d4aef" "User Commands"
.TH HUSHD "1" "October 2018" "hushd v2.0.0" "User Commands"
.SH NAME
hushd \- manual page for hushd v1.0.14-a0d4aef
hushd \- manual page for hushd v2.0.0
.SH DESCRIPTION
Hush Daemon version v1.0.14\-a0d4aef
Hush Daemon version v2.0.0
.PP
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://github.com/MyHush/hush/blob/master/doc/security.md>.
@ -54,7 +54,7 @@ Specify data directory
\fB\-disabledeprecation=\fR<version>
.IP
Disable block\-height node deprecation and automatic shutdown (example:
\fB\-disabledeprecation\fR=\fI\,1\/\fR.0.14)
\fB\-disabledeprecation\fR=\fI\,2\/\fR.0.0)
.HP
\fB\-exportdir=\fR<dir>
.IP
@ -79,7 +79,7 @@ mempool will accept (default: 0 = no limit applied)
.HP
\fB\-par=\fR<n>
.IP
Set the number of script verification threads (\fB\-2\fR to 16, 0 = auto, <0 =
Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 =
leave that many cores free, default: 0)
.HP
\fB\-pid=\fR<file>
@ -504,9 +504,9 @@ console, 600 otherwise)
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://github.com/MyHush/hush/blob/master/doc/security.md>.
Copyright (C) 2009-2017 The Bitcoin Core Developers
Copyright (C) 2015-2017 The Zcash Developers
Copyright (C) 2016-2017 The Hush Developers
Copyright (C) 2009-2018 The Bitcoin Core Developers
Copyright (C) 2015-2018 The Zcash Developers
Copyright (C) 2016-2018 The Hush Developers
This is experimental software.

4
doc/unit-tests.md

@ -6,12 +6,12 @@ and tests weren't explicitly disabled.
There are two scripts for running tests:
* ``qa/zcash/full-test-suite.sh``, to run the main test suite
* ``qa/hush/full-test-suite.sh``, to run the main test suite
* ``qa/pull-tester/rpc-tests.sh``, to run the RPC tests.
The main test suite uses two different testing frameworks. Tests using the Boost
framework are under ``src/test/``; tests using the Google Test/Google Mock
framework are under ``src/gtest/`` and ``src/wallet/gtest/``. The latter framework
is preferred for new Zcash unit tests.
is preferred for new Hush unit tests.
RPC tests are implemented in Python under the ``qa/rpc-tests/`` directory.

1
qa/pull-tester/rpc-tests.sh

@ -11,6 +11,7 @@ export BITCOIND=${REAL_BITCOIND}
#Run the tests
testScripts=(
'dpow.py'
'paymentdisclosure.py'
'prioritisetransaction.py'
'wallet_treestate.py'

38
qa/rpc-tests/dpow.py

@ -0,0 +1,38 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Hush developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, initialize_chain_clean, \
start_node, stop_node, wait_bitcoinds
class DPoWTest(BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
num_nodes = 1
initialize_chain_clean(self.options.tmpdir, num_nodes)
def setup_network(self):
self.nodes = []
self.is_network_split = False
self.nodes.append(start_node(0, self.options.tmpdir))
self.sync_all()
def run_test(self):
self.nodes[0].generate(3)
rpc = self.nodes[0]
result = rpc.getinfo()
print result
# TODO: actually do notarizations on regtest and test for specific data
# regtest should have no notarization data, this test makes sure we do not see mainnet values as well!
assert_equal(result['notarized'],0)
assert_equal(result['notarizedhash'],'0000000000000000000000000000000000000000000000000000000000000000')
assert_equal(result['notarizedtxid'],'0000000000000000000000000000000000000000000000000000000000000000')
if __name__ == '__main__':
DPoWTest().main()

18
qa/rpc-tests/getchaintips.py

@ -13,13 +13,15 @@ from test_framework.util import assert_equal
class GetChainTipsTest (BitcoinTestFramework):
def run_test (self):
BitcoinTestFramework.run_test (self)
rpc = self.nodes[0]
#for node in self.nodes:
# node.generate(200)
tips = self.nodes[0].getchaintips ()
tips = self.nodes[0].getchaintips()
assert_equal (len (tips), 1)
assert_equal (tips[0]['branchlen'], 0)
assert_equal (tips[0]['height'], 200)
assert_equal (tips[0]['status'], 'active')
assert_equal (tips[0]['branchlen'], 0)
assert_equal (tips[0]['height'], 0)
# Split the network and build two chains of different lengths.
self.split_network ()
@ -31,14 +33,14 @@ class GetChainTipsTest (BitcoinTestFramework):
assert_equal (len (tips), 1)
shortTip = tips[0]
assert_equal (shortTip['branchlen'], 0)
assert_equal (shortTip['height'], 210)
assert_equal (shortTip['height'], 10)
assert_equal (tips[0]['status'], 'active')
tips = self.nodes[3].getchaintips ()
assert_equal (len (tips), 1)
longTip = tips[0]
assert_equal (longTip['branchlen'], 0)
assert_equal (longTip['height'], 220)
assert_equal (longTip['height'], 20)
assert_equal (tips[0]['status'], 'active')
# Join the network halves and check that we now have two tips
@ -55,5 +57,9 @@ class GetChainTipsTest (BitcoinTestFramework):
tips[1]['status'] = 'active'
assert_equal (tips[1], shortTip)
# test optional minBranchLen
tips = self.nodes[0].getchaintips(42)
assert_equal (len (tips), 0)
if __name__ == '__main__':
GetChainTipsTest ().main ()

29
qa/rpc-tests/test_framework/util.py

@ -83,30 +83,35 @@ def initialize_datadir(dirname, n):
f.write("port="+str(p2p_port(n))+"\n");
f.write("rpcport="+str(rpc_port(n))+"\n");
f.write("listenonion=0\n");
# TODO: maybe make these optional, defaulted to on for now
f.write("addressindex=1\n");
f.write("spentindex=1\n");
f.write("timestampindex=1\n");
return datadir
def initialize_chain(test_dir):
"""
Create (or copy from cache) a 200-block-long chain and
4 wallets.
bitcoind and bitcoin-cli must be in search path.
hushd and hush-cli must be in search path.
"""
if not os.path.isdir(os.path.join("cache", "node0")):
devnull = open("/dev/null", "w+")
# Create cache directories, run bitcoinds:
# Create cache directories, run hushds:
for i in range(4):
datadir=initialize_datadir("cache", i)
args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
args = [ os.getenv("BITCOIND", "hushd"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
if i > 0:
args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
bitcoind_processes[i] = subprocess.Popen(args)
if os.getenv("PYTHON_DEBUG", ""):
print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir,
print "initialize_chain: hushd started, calling hush-cli -rpcwait getblockcount"
print [ os.getenv("BITCOINCLI", "hush-cli"), "-datadir="+datadir, "-rpcwait", "getblockcount"]
subprocess.check_call([ os.getenv("BITCOINCLI", "hush-cli"), "-datadir="+datadir,
"-rpcwait", "getblockcount"], stdout=devnull)
if os.getenv("PYTHON_DEBUG", ""):
print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed"
print "initialize_chain: hush-cli -rpcwait getblockcount completed"
devnull.close()
rpcs = []
for i in range(4):
@ -177,22 +182,22 @@ def _rpchost_to_args(rpchost):
def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None):
"""
Start a bitcoind and return RPC connection to it
Start a hushd and return RPC connection to it
"""
datadir = os.path.join(dirname, "node"+str(i))
if binary is None:
binary = os.getenv("BITCOIND", "bitcoind")
binary = os.getenv("BITCOIND", "hushd")
args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args)
devnull = open("/dev/null", "w+")
if os.getenv("PYTHON_DEBUG", ""):
print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] +
print "start_node: hushd started, calling hush-cli -rpcwait getblockcount"
subprocess.check_call([ os.getenv("BITCOINCLI", "hush-cli"), "-datadir="+datadir] +
_rpchost_to_args(rpchost) +
["-rpcwait", "getblockcount"], stdout=devnull)
if os.getenv("PYTHON_DEBUG", ""):
print "start_node: calling bitcoin-cli -rpcwait getblockcount returned"
print "start_node: calling hush-cli -rpcwait getblockcount returned"
devnull.close()
url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
if timewait is not None:
@ -204,7 +209,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
"""
Start multiple bitcoinds, return RPC connections to them
Start multiple hushds, return RPC connections to them
"""
if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
if binary is None: binary = [ None for i in range(num_nodes) ]

60
qa/rpc-tests/wallet.py

@ -43,8 +43,8 @@ class WalletTest (BitcoinTestFramework):
self.nodes[1].generate(101)
self.sync_all()
# These are different from upstream because Hush does not have a
# Founders Reward
# These are different from upstream because Hush does not have a
# Founders Reward
assert_equal(self.nodes[0].getbalance(), 160000)
assert_equal(self.nodes[1].getbalance(), 12.5)
assert_equal(self.nodes[2].getbalance(), 0)
@ -469,6 +469,62 @@ class WalletTest (BitcoinTestFramework):
assert_equal("not an integer" in errorString, True);
myzaddr = self.nodes[0].z_getnewaddress()
recipients = [ {"address": myzaddr, "amount": Decimal('0.0') } ]
errorString = ''
# Make sure that amount=0 transactions can use the default fee
# without triggering "absurd fee" errors
try:
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
assert(myopid)
except JSONRPCException,e:
errorString = e.error['message']
print errorString
assert(False)
# This fee is larger than the default fee and since amount=0
# it should trigger error
fee = Decimal('0.1')
recipients = [ {"address": myzaddr, "amount": Decimal('0.0') } ]
minconf = 1
errorString = ''
try:
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, fee)
except JSONRPCException,e:
errorString = e.error['message']
assert('Small transaction amount' in errorString)
#### This fee is less than default and greater than amount, but still valid
fee = Decimal('0.0000001')
recipients = [ {"address": myzaddr, "amount": Decimal('0.00000001') } ]
minconf = 1
errorString = ''
try:
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, fee)
assert(myopid)
except JSONRPCException,e:
errorString = e.error['message']
print errorString
assert(False)
### Make sure amount=0, fee=0 transaction are valid to add to mempool
# though miners decide whether to add to a block
fee = Decimal('0.0')
minconf = 1
recipients = [ {"address": myzaddr, "amount": Decimal('0.0') } ]
errorString = ''
try:
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, fee)
assert(myopid)
except JSONRPCException,e:
errorString = e.error['message']
print errorString
assert(False)
if __name__ == '__main__':
WalletTest ().main ()

2
src/Makefile.am

@ -611,7 +611,7 @@ clean-local:
.rc.o:
@test -f $(WINDRES)
$(AM_V_GEN) $(WINDRES) -DWINDRES_PREPROC -i $< -o $@
$(AM_V_GEN) $(WINDRES) -DWINDRES_PREPROC -DHAVE_CONFIG_H -i $< -o $@
.mm.o:
$(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \

13
src/chain.h

@ -17,6 +17,8 @@
#include <boost/foreach.hpp>
static const int SPROUT_VALUE_VERSION = 1001400;
static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
struct CDiskBlockPos
{
@ -178,6 +180,9 @@ public:
//! (memory only) Sequential id assigned to distinguish order in which blocks are received.
uint32_t nSequenceId;
//! (memory only) Maximum nTime in the chain up to and including this block.
unsigned int nTimeMax;
void SetNull()
{
phashBlock = NULL;
@ -268,6 +273,11 @@ public:
return (int64_t)nTime;
}
int64_t GetBlockTimeMax() const
{
return (int64_t)nTimeMax;
}
enum { nMedianTimeSpan=11 };
int64_t GetMedianTimePast() const
@ -465,6 +475,9 @@ public:
/** Find the last common block between this chain and a block index entry. */
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
/** Find the earliest block with timestamp equal or greater than the given. */
CBlockIndex* FindEarliestAtLeast(int64_t nTime) const;
};
#endif // BITCOIN_CHAIN_H

3
src/clientversion.cpp

@ -1,4 +1,5 @@
// Copyright (c) 2012-2014 The Bitcoin Core developers
// Copyright (c) 2017-2018 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -19,7 +20,7 @@
* for both bitcoind and bitcoin-core, to make it harder for attackers to
* target servers or GUI users specifically.
*/
const std::string CLIENT_NAME("BalefulStatic");
const std::string CLIENT_NAME("AuspiciousHerald");
/**
* Client version number

13
src/init.cpp

@ -706,7 +706,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
}
/** Sanity checks
* Ensure that Bitcoin is running in a usable environment with all
* Ensure that Hush is running in a usable environment with all
* necessary library support.
*/
bool InitSanityCheck(void)
@ -769,7 +769,9 @@ bool AppInitServers(boost::thread_group& threadGroup)
return true;
}
/** Initialize bitcoin.
int32_t komodo_init();
/** Initialize Hush
* @pre Parameters should be parsed and config file should be read.
*/
bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
@ -922,6 +924,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections)
nMaxConnections = nFD - MIN_CORE_FILEDESCRIPTORS;
komodo_init();
// if using block pruning, then disable txindex
// also disable the wallet (for now, until SPV support is implemented in wallet)
if (GetArg("-prune", 0)) {
@ -1151,7 +1155,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
#endif
// Make sure only a single Bitcoin process is using the data directory.
// Make sure only a single Hush process is using the data directory.
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file);
@ -1630,6 +1634,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
strErrors << _("Error loading wallet.dat") << "\n";
}
// Wallet has been successfully loaded
vpwallets.push_back(pwalletMain);
if (GetBoolArg("-upgradewallet", fFirstRun))
{
int nMaxVersion = GetArg("-upgradewallet", 0);

227
src/key_io.cpp

@ -0,0 +1,227 @@
// Copyright (c) 2014-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key_io.h>
#include <base58.h>
#include <bech32.h>
#include <script/script.h>
#include <utilstrencodings.h>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <assert.h>
#include <string.h>
#include <algorithm>
namespace
{
class DestinationEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;
public:
DestinationEncoder(const CChainParams& params) : m_params(params) {}
std::string operator()(const CKeyID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}
std::string operator()(const CScriptID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}
std::string operator()(const WitnessV0KeyHash& id) const
{
std::vector<unsigned char> data = {0};
data.reserve(33);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessV0ScriptHash& id) const
{
std::vector<unsigned char> data = {0};
data.reserve(53);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessUnknown& id) const
{
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
return {};
}
std::vector<unsigned char> data = {(unsigned char)id.version};
data.reserve(1 + (id.length * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
return bech32::Encode(m_params.Bech32HRP(), data);
}
std::string operator()(const CNoDestination& no) const { return {}; }
};
CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
{
std::vector<unsigned char> data;
uint160 hash;
if (DecodeBase58Check(str, data)) {
// base58-encoded Bitcoin addresses.
// Public-key-hash-addresses have version 0 (or 111 testnet).
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
return CKeyID(hash);
}
// Script-hash-addresses have version 5 (or 196 testnet).
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
return CScriptID(hash);
}
}
data.clear();
auto bech = bech32::Decode(str);
if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
// Bech32 decoding
int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
// The rest of the symbols are converted witness program bytes.
data.reserve(((bech.second.size() - 1) * 5) / 8);
if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin() + 1, bech.second.end())) {
if (version == 0) {
{
WitnessV0KeyHash keyid;
if (data.size() == keyid.size()) {
std::copy(data.begin(), data.end(), keyid.begin());
return keyid;
}
}
{
WitnessV0ScriptHash scriptid;
if (data.size() == scriptid.size()) {
std::copy(data.begin(), data.end(), scriptid.begin());
return scriptid;
}
}
return CNoDestination();
}
if (version > 16 || data.size() < 2 || data.size() > 40) {
return CNoDestination();
}
WitnessUnknown unk;
unk.version = version;
std::copy(data.begin(), data.end(), unk.program);
unk.length = data.size();
return unk;
}
}
return CNoDestination();
}
} // namespace
CKey DecodeSecret(const std::string& str)
{
CKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
bool compressed = data.size() == 33 + privkey_prefix.size();
key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
}
}
memory_cleanse(data.data(), data.size());
return key;
}
std::string EncodeSecret(const CKey& key)
{
assert(key.IsValid());
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
data.insert(data.end(), key.begin(), key.end());
if (key.IsCompressed()) {
data.push_back(1);
}
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}
CExtPubKey DecodeExtPubKey(const std::string& str)
{
CExtPubKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
key.Decode(data.data() + prefix.size());
}
}
return key;
}
std::string EncodeExtPubKey(const CExtPubKey& key)
{
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
size_t size = data.size();
data.resize(size + BIP32_EXTKEY_SIZE);
key.Encode(data.data() + size);
std::string ret = EncodeBase58Check(data);
return ret;
}
CExtKey DecodeExtKey(const std::string& str)
{
CExtKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
key.Decode(data.data() + prefix.size());
}
}
return key;
}
std::string EncodeExtKey(const CExtKey& key)
{
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
size_t size = data.size();
data.resize(size + BIP32_EXTKEY_SIZE);
key.Encode(data.data() + size);
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}
std::string EncodeDestination(const CTxDestination& dest)
{
return boost::apply_visitor(DestinationEncoder(Params()), dest);
}
CTxDestination DecodeDestination(const std::string& str)
{
return DecodeDestination(str, Params());
}
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
{
return IsValidDestination(DecodeDestination(str, params));
}
bool IsValidDestinationString(const std::string& str)
{
return IsValidDestinationString(str, Params());
}

29
src/key_io.h

@ -0,0 +1,29 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KEYIO_H
#define BITCOIN_KEYIO_H
#include <chainparams.h>
#include <key.h>
#include <pubkey.h>
#include <script/standard.h>
#include <string>
CKey DecodeSecret(const std::string& str);
std::string EncodeSecret(const CKey& key);
CExtKey DecodeExtKey(const std::string& str);
std::string EncodeExtKey(const CExtKey& extkey);
CExtPubKey DecodeExtPubKey(const std::string& str);
std::string EncodeExtPubKey(const CExtPubKey& extpubkey);
std::string EncodeDestination(const CTxDestination& dest);
CTxDestination DecodeDestination(const std::string& str);
bool IsValidDestinationString(const std::string& str);
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
#endif // BITCOIN_KEYIO_H

103
src/komodo_rpcblockchain.h

@ -0,0 +1,103 @@
/******************************************************************************
* Copyright © 2014-2018 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 komodo_rpcblockchain_h
#define komodo_rpcblockchain_h
#include "main.h"
int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip);
uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
extern char ASSETCHAINS_SYMBOL[65];
int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip)
{
int32_t depth,notarized_ht; uint256 MoM,kmdtxid;
depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip);
memset(MoMp,0,sizeof(*MoMp));
memset(kmdtxidp,0,sizeof(*kmdtxidp));
*notarized_heightp = 0;
if ( depth > 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht )
{
*MoMp = MoM;
*notarized_heightp = notarized_ht;
*kmdtxidp = kmdtxid;
}
return(depth);
}
UniValue calc_MoM(const UniValue& params, bool fHelp)
{
int32_t height,MoMdepth; uint256 MoM; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
if ( fHelp || params.size() != 2 )
throw runtime_error("calc_MoM height MoMdepth\n");
LOCK(cs_main);
height = atoi(params[0].get_str().c_str());
MoMdepth = atoi(params[1].get_str().c_str());
if ( height <= 0 )
throw runtime_error("calc_MoM illegal height, must be positive\n");
if ( MoMdepth <= 0 || MoMdepth >= height )
throw runtime_error("calc_MoM illegal MoMdepth, must be positive and less than height\n");
//fprintf(stderr,"height_MoM height.%d\n",height);
MoM = komodo_calcMoM(height,MoMdepth);
ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
ret.push_back(Pair("height",height));
ret.push_back(Pair("MoMdepth",MoMdepth));
ret.push_back(Pair("MoM",MoM.GetHex()));
return ret;
}
UniValue height_MoM(const UniValue& params, bool fHelp)
{
int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
if ( fHelp || params.size() != 1 )
throw runtime_error("height_MoM height\n");
LOCK(cs_main);
height = atoi(params[0].get_str().c_str());
if ( height <= 0 )
{
if ( chainActive.Tip() == 0 )
{
ret.push_back(Pair("error",(char *)"no active chain yet"));
return(ret);
}
height = chainActive.Tip()->nHeight;
}
//fprintf(stderr,"height_MoM height.%d\n",height);
depth = komodo_MoM(&notarized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi);
ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
ret.push_back(Pair("height",height));
ret.push_back(Pair("timestamp",(uint64_t)timestamp));
if ( depth > 0 )
{
ret.push_back(Pair("depth",depth));
ret.push_back(Pair("notarized_height",notarized_height));
ret.push_back(Pair("MoM",MoM.GetHex()));
ret.push_back(Pair("kmdtxid",kmdtxid.GetHex()));
if ( ASSETCHAINS_SYMBOL[0] != 0 )
{
ret.push_back(Pair("MoMoM",MoMoM.GetHex()));
ret.push_back(Pair("MoMoMoffset",MoMoMoffset));
ret.push_back(Pair("MoMoMdepth",MoMoMdepth));
ret.push_back(Pair("kmdstarti",kmdstarti));
ret.push_back(Pair("kmdendi",kmdendi));
}
} else ret.push_back(Pair("error",(char *)"no MoM for height"));
return ret;
}
#endif /* komodo_rpcblockchain_h */

1248
src/komodo_validation011.h

File diff suppressed because it is too large

28
src/main.cpp

@ -4,7 +4,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "main.h"
#include "sodium.h"
@ -30,6 +29,7 @@
#include "util.h"
#include "utilmoneystr.h"
#include "validationinterface.h"
#include "wallet/wallet.h"
#include "wallet/asyncrpcoperation_sendmany.h"
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
@ -215,6 +215,9 @@ namespace {
set<int> setDirtyFileInfo;
} // anon namespace
char ASSETCHAINS_SYMBOL[65] = { "HUSH" };
#include "komodo_validation011.h"
//////////////////////////////////////////////////////////////////////////////
//
// Registration of network node signals.
@ -2093,6 +2096,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
return error("DisconnectBlock(): block and undo data inconsistent");
komodo_disconnect((CBlockIndex *)pindex,(CBlock *)&block);
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
@ -2655,6 +2660,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3;
LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001);
komodo_connectblock(pindex,*(CBlock *)&block);
return true;
}
@ -2829,6 +2835,15 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
CBlock block;
if (!ReadBlockFromDisk(block, pindexDelete))
return AbortNode(state, "Failed to read block");
int32_t prevMoMheight; uint256 notarizedhash,txid;
komodo_notarized_height(&prevMoMheight,&notarizedhash,&txid);
if ( block.GetHash() == notarizedhash )
{
fprintf(stderr,"DisconnectTip trying to disconnect notarized block at ht.%d\n",(int32_t)pindexDelete->nHeight);
return(false);
}
// Apply the block atomically to the chain state.
uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor();
int64_t nStart = GetTimeMicros();
@ -3535,6 +3550,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
const CChainParams& chainParams = Params();
const Consensus::Params& consensusParams = chainParams.GetConsensus();
uint256 hash = block.GetHash();
int32_t notarized_height;
if (hash == consensusParams.hashGenesisBlock)
return true;
@ -3558,6 +3575,15 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight));
else if ( komodo_checkpoint(&notarized_height,(int32_t)nHeight,hash) < 0 )
{
CBlockIndex *heightblock = chainActive[nHeight];
if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
{
//fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight);
return true;
} else return state.DoS(100, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height));
}
}
// Reject block.nVersion < 4 blocks

1
src/main.h

@ -101,6 +101,7 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
/** Maximum length of reject messages. */
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
static const bool DEFAULT_TXINDEX = false;
static const bool DEFAULT_ADDRESSINDEX = false;
static const bool DEFAULT_TIMESTAMPINDEX = false;
static const bool DEFAULT_SPENTINDEX = false;

5
src/primitives/transaction.h

@ -13,6 +13,7 @@
#include "uint256.h"
#include "consensus/consensus.h"
#include <memory>
#include <boost/array.hpp>
#include "zcash/NoteEncryption.hpp"
@ -462,6 +463,10 @@ public:
std::string ToString() const;
};
typedef std::shared_ptr<const CTransaction> CTransactionRef;
static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
/** A mutable version of CTransaction. */
struct CMutableTransaction
{

18
src/rpcblockchain.cpp

@ -1020,7 +1020,7 @@ struct CompareBlocksByHeight
UniValue getchaintips(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
if (fHelp || params.size() > 1)
throw runtime_error(
"getchaintips\n"
"Return information about all known tips in the block tree,"
@ -1053,6 +1053,10 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
LOCK(cs_main);
int minBranchLen = 0;
if (params.size() > 0)
minBranchLen = params[0].get_int();
/* Build up a list of chain tips. We start with the list of all
known blocks, and successively remove blocks that appear as pprev
of another block. */
@ -1066,18 +1070,22 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
setTips.erase(pprev);
}
// Always report the currently active tip.
setTips.insert(chainActive.Tip());
if (minBranchLen == 0) {
// insert currently active tip
setTips.insert(chainActive.Tip());
}
/* Construct the output array. */
UniValue res(UniValue::VARR);
BOOST_FOREACH(const CBlockIndex* block, setTips)
{
const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
if (branchLen < minBranchLen)
continue;
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("height", block->nHeight));
obj.push_back(Pair("hash", block->phashBlock->GetHex()));
const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
obj.push_back(Pair("branchlen", branchLen));
string status;

2
src/rpcclient.cpp

@ -46,6 +46,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getbalance", 1 },
{ "getbalance", 2 },
{ "getblockhash", 0 },
{ "getchaintips", 0 },
{ "move", 2 },
{ "move", 3 },
{ "sendfrom", 2 },
@ -86,6 +87,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "lockunspent", 1 },
{ "importprivkey", 2 },
{ "importaddress", 2 },
{ "importpubkey", 2 },
{ "verifychain", 0 },
{ "verifychain", 1 },
{ "keypoolrefill", 0 },

91
src/rpcmisc.cpp

@ -28,19 +28,6 @@
using namespace std;
/**
* @note Do not add or change anything in the information returned by this
* method. `getinfo` exists for backwards-compatibility only. It combines
* information from wildly different sources in the program, which is a mess,
* and is thus planned to be deprecated eventually.
*
* Based on the source of the information, new information should be added to:
* - `getblockchaininfo`,
* - `getnetworkinfo` or
* - `getwalletinfo`
*
* Or alternatively, create a specific query method for the information.
**/
UniValue getinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@ -108,6 +95,14 @@ UniValue getinfo(const UniValue& params, bool fHelp)
#endif
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
extern uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID;
extern int32_t NOTARIZED_HEIGHT;
obj.push_back(Pair("notarizedhash", NOTARIZED_HASH.GetHex()));
obj.push_back(Pair("notarizedtxid", NOTARIZED_DESTTXID.GetHex()));
obj.push_back(Pair("notarized", (int)NOTARIZED_HEIGHT));
return obj;
}
@ -941,7 +936,77 @@ UniValue getaddresstxids(const UniValue& params, bool fHelp)
}
return result;
}
//void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel);
UniValue importpubkey(const UniValue& params, bool fHelp)
{
CWallet * const pwallet = vpwallets[0];
if (!pwallet) {
return NullUniValue;
}
if (fHelp || params.size() < 1 || params.size() > 4)
throw std::runtime_error(
"importpubkey \"pubkey\" ( \"label\" rescan )\n"
"\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
"\nArguments:\n"
"1. \"pubkey\" (string, required) The hex-encoded public key\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
"\nExamples:\n"
"\nImport a public key with rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\"") +
"\nImport using a label without rescan\n"
+ HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false")
);
std::string strLabel;
if (!params[1].isNull())
strLabel = params[1].get_str();
// Whether to perform rescan after import
bool fRescan = true;
if (!params[2].isNull())
fRescan = params[2].get_bool();
if (fRescan && fPruneMode)
throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
WalletRescanReserver reserver(pwallet);
if (fRescan && !reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
if (!IsHex(params[0].get_str()))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string");
std::vector<unsigned char> data(ParseHex(params[0].get_str()));
CPubKey pubKey(data.begin(), data.end());
if (!pubKey.IsFullyValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key");
{
LOCK2(cs_main, pwallet->cs_wallet);
for (const auto& dest : GetAllDestinationsForKey(pubKey)) {
ImportAddress(pwallet, dest, strLabel);
}
//ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
//pwallet->LearnAllRelatedScripts(pubKey);
}
if (fRescan)
{
pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */);
pwallet->ReacceptWalletTransactions();
}
return NullUniValue;
}
UniValue getspentinfo(const UniValue& params, bool fHelp)

6
src/rpcserver.cpp

@ -27,6 +27,7 @@
#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp>
#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
#include "komodo_rpcblockchain.h"
using namespace RPCServer;
using namespace std;
@ -252,6 +253,8 @@ UniValue stop(const UniValue& params, bool fHelp)
return "Hush server stopping";
}
extern UniValue importpubkey(const UniValue &params, bool fHelp);
/**
* Call Table
*/
@ -296,6 +299,8 @@ static const CRPCCommand vRPCCommands[] =
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
{ "blockchain", "verifychain", &verifychain, true },
{ "blockchain", "getspentinfo", &getspentinfo, false },
{ "blockchain", "calc_MoM", &calc_MoM, true },
{ "blockchain", "height_MoM", &height_MoM, true },
/* Mining */
{ "mining", "getblocktemplate", &getblocktemplate, true },
@ -367,6 +372,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false },
{ "wallet", "getwalletinfo", &getwalletinfo, false },
{ "wallet", "importprivkey", &importprivkey, true },
{ "wallet", "importpubkey", &importpubkey, true },
{ "wallet", "importwallet", &importwallet, true },
{ "wallet", "importaddress", &importaddress, true },
{ "wallet", "keypoolrefill", &keypoolrefill, true },

9
src/script/standard.cpp

@ -306,6 +306,11 @@ CScript GetScriptForDestination(const CTxDestination& dest)
return script;
}
CScript GetScriptForRawPubKey(const CPubKey& pubKey)
{
return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
}
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
{
CScript script;
@ -316,3 +321,7 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
return script;
}
bool IsValidDestination(const CTxDestination& dest) {
return dest.which() != 0;
}

3
src/script/standard.h

@ -84,6 +84,8 @@ typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
const char* GetTxnOutputType(txnouttype t);
bool IsValidDestination(const CTxDestination& dest);
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
@ -92,5 +94,6 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
CScript GetScriptForDestination(const CTxDestination& dest);
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
CScript GetScriptForRawPubKey(const CPubKey& pubkey);
#endif // BITCOIN_SCRIPT_STANDARD_H

38
src/wallet/rpcdump.cpp

@ -74,6 +74,44 @@ std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel);
void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript);
void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
{
if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
}
pwallet->MarkDirty();
if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
if (isRedeemScript) {
if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
ImportAddress(pwallet, CBitcoinAddress( CScriptID(script) ), strLabel);
} else {
CTxDestination destination;
if (ExtractDestination(script, destination)) {
pwallet->SetAddressBook(destination, strLabel, "receive");
}
}
}
void ImportAddress(CWallet* const pwallet, const CBitcoinAddress& address, const std::string& strLabel)
{
CScript script = GetScriptForDestination(address.Get());
ImportScript(pwallet, script, strLabel, false);
// add to address book or update label
if (address.IsValid())
pwallet->SetAddressBook(address.Get(), strLabel, "receive");
}
UniValue importprivkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))

27
src/wallet/rpcwallet.cpp

@ -948,7 +948,7 @@ UniValue sendmany(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
"sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
"\nSend multiple times. Amounts are double-precision floating point numbers."
"\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
@ -3500,8 +3500,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 2 || params.size() > 4)
throw runtime_error(
"z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n"
"\nSend multiple times. Amounts are double-precision floating point numbers."
"\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself."
"\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
"\nChange generated from a taddr flows to a new taddr address, while change generated from a zaddr returns to itself."
"\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed."
+ strprintf("\nCurrently, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS)
+ HelpRequiringPassphrase() + "\n"
@ -3643,8 +3643,10 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
}
// Fee in Zatoshis, not currency format)
CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
// Fee in Puposhis, not currency format
CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
CAmount nDefaultFee = nFee;
if (params.size() > 3) {
if (params[3].get_real() == 0.0) {
nFee = 0;
@ -3652,9 +3654,18 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
nFee = AmountFromValue( params[3] );
}
// Check that the user specified fee is sane.
if (nFee > nTotalOut) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s", FormatMoney(nFee), FormatMoney(nTotalOut)));
// This allows amount=0 (and all amount < nDefaultFee) transactions to use the default network fee
// or anything less than nDefaultFee
// instead of being forced to use a custom fee and leak metadata
if (nTotalOut < nDefaultFee) {
if (nFee > nDefaultFee) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Small transaction amount %s has fee %s that is greater than the default fee %s", FormatMoney(nTotalOut), FormatMoney(nFee), FormatMoney(nDefaultFee)));
}
} else {
// Check that the user specified fee is sane.
if (nFee > nTotalOut) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s", FormatMoney(nFee), FormatMoney(nTotalOut)));
}
}
}

63
src/wallet/wallet.cpp

@ -39,6 +39,7 @@ unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
bool bSpendZeroConfChange = true;
bool fSendFreeTransactions = false;
bool fPayAtLeastCustomFee = true;
std::vector<CWalletRef> vpwallets;
/**
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
@ -1682,6 +1683,43 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
}
/**
* Scan active chain for relevant transactions after importing keys. This should
* be called whenever new keys are added to the wallet, with the oldest key
* creation time.
*
* @return Earliest timestamp that could be successfully scanned from. Timestamp
* returned will be higher than startTime if relevant blocks could not be read.
*/
int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update)
{
// Find starting block. May be null if nCreateTime is greater than the
// highest blockchain timestamp, in which case there is nothing that needs
// to be scanned.
CBlockIndex* startBlock = nullptr;
{
LOCK(cs_main);
startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
}
if (startBlock) {
//const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, false); //nullptr, reserver, update);
//if (failedBlock) {
// return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1;
//}
ScanForWalletTransactions(startBlock, false); //nullptr, reserver, update);
}
return startTime;
}
CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime) const
{
std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
[](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
return (lower == vChain.end() ? nullptr : *lower);
}
void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
{
@ -3390,6 +3428,12 @@ void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
}
}
std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
{
CKeyID keyid = key.GetID();
return std::vector<CTxDestination>{std::move(keyid)};
}
void CWallet::UpdatedTransaction(const uint256 &hashTx)
{
{
@ -3868,4 +3912,21 @@ void CWallet::GetUnspentFilteredNotes(
}
}
}
}
}
void CWallet::LearnRelatedScripts(const CPubKey& key, OutputType type)
{
if (key.IsCompressed() && (type == OutputType::P2SH_SEGWIT || type == OutputType::BECH32)) {
//CTxDestination witdest = WitnessV0KeyHash(key.GetID());
//CScript witprog = GetScriptForDestination(witdest);
// Make sure the resulting program is solvable.
//assert(IsSolvable(*this, witprog));
//AddCScript(witprog);
}
}
void CWallet::LearnAllRelatedScripts(const CPubKey& key)
{
// OutputType::P2SH_SEGWIT always adds all necessary scripts for all types.
LearnRelatedScripts(key, OutputType::P2SH_SEGWIT);
}

83
src/wallet/wallet.h

@ -32,6 +32,11 @@
#include <string>
#include <utility>
#include <vector>
#include <mutex>
typedef CWallet* CWalletRef;
extern std::vector<CWalletRef> vpwallets;
static const int64_t TIMESTAMP_MIN = 0;
/**
* Settings
@ -68,6 +73,13 @@ class CScript;
class CTxMemPool;
class CWalletTx;
enum class OutputType {
NONE,
LEGACY,
P2SH_SEGWIT,
BECH32,
};
/** (client) version numbers for particular wallet features */
enum WalletFeature
{
@ -286,6 +298,7 @@ private:
int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
public:
CTransactionRef tx;
uint256 hashBlock;
std::vector<uint256> vMerkleBranch;
int nIndex;
@ -296,6 +309,13 @@ public:
CMerkleTx()
{
SetTx(MakeTransactionRef());
Init();
}
explicit CMerkleTx(CTransactionRef arg)
{
SetTx(std::move(arg));
Init();
}
@ -311,6 +331,11 @@ public:
fMerkleVerified = false;
}
void SetTx(CTransactionRef arg)
{
tx = std::move(arg);
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
@ -658,6 +683,8 @@ private:
};
class WalletRescanReserver; //forward declarations for ScanForWalletTransactions/RescanFromTime
/**
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
* and provides the ability to create new transactions.
@ -669,6 +696,10 @@ private:
CWalletDB *pwalletdbEncryption;
std::atomic<bool> fScanningWallet; //controlled by WalletRescanReserver
std::mutex mutexScanning;
friend class WalletRescanReserver;
//! the current wallet version: clients below this version are not able to load the wallet
int nWalletVersion;
@ -1003,6 +1034,8 @@ public:
std::vector<uint256> commitments,
std::vector<boost::optional<ZCIncrementalWitness>>& witnesses,
uint256 &final_anchor);
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
//CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime);
@ -1156,6 +1189,19 @@ public:
int minDepth=1,
int maxDepth=INT_MAX,
bool ignoreUnspendable=true);
/**
* Explicitly make the wallet learn the related scripts for outputs to the
* given key. This is purely to make the wallet file compatible with older
* software, as CBasicKeyStore automatically does this implicitly for all
* keys now.
*/
void LearnRelatedScripts(const CPubKey& key, OutputType);
/**
* Same as LearnRelatedScripts, but when the OutputType is not known (and could
* be anything).
*/
void LearnAllRelatedScripts(const CPubKey& key);
};
/** A key allocated from the key pool. */
@ -1212,4 +1258,41 @@ public:
}
};
/** RAII object to check and reserve a wallet rescan */
class WalletRescanReserver
{
private:
CWalletRef m_wallet;
bool m_could_reserve;
public:
explicit WalletRescanReserver(CWalletRef w) : m_wallet(w), m_could_reserve(false) {}
bool reserve()
{
assert(!m_could_reserve);
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
if (m_wallet->fScanningWallet) {
return false;
}
m_wallet->fScanningWallet = true;
m_could_reserve = true;
return true;
}
bool isReserved() const
{
return (m_could_reserve && m_wallet->fScanningWallet);
}
~WalletRescanReserver()
{
std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
if (m_could_reserve) {
m_wallet->fScanningWallet = false;
}
}
};
std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key);
#endif // BITCOIN_WALLET_WALLET_H

4
zcutil/build-debian-package.sh

@ -51,8 +51,8 @@ cp $SRC_DOC/man/hushd.1 $DEB_MAN
cp $SRC_DOC/man/hush-cli.1 $DEB_MAN
cp $SRC_DOC/man/hush-fetch-params.1 $DEB_MAN
# Copy bash completion files
cp $SRC_PATH/contrib/bitcoind.bash-completion $DEB_CMP/hushd
cp $SRC_PATH/contrib/bitcoin-cli.bash-completion $DEB_CMP/hush-cli
cp $SRC_PATH/contrib/hushd.bash-completion $DEB_CMP/hushd
cp $SRC_PATH/contrib/hush-cli.bash-completion $DEB_CMP/hush-cli
# Gzip files
gzip --best -n $DEB_DOC/changelog
gzip --best -n $DEB_DOC/changelog.Debian

Loading…
Cancel
Save