Merge branch 'dev' into jahway603

This commit is contained in:
jahway603
2025-12-30 09:32:43 -05:00
49 changed files with 1918 additions and 2588 deletions

View File

@@ -150,7 +150,6 @@ cd hush3
The links for the Official Hush explorers: The links for the Official Hush explorers:
* [explorer.hush.is](https://explorer.hush.is) * [explorer.hush.is](https://explorer.hush.is)
* [explorer.hush.land](https://explorer.hush.land)
# What is SilentDragon? # What is SilentDragon?

View File

@@ -4,10 +4,30 @@
# Run a regression test network # Run a regression test network
#regtest=0 #regtest=0
# Run a test node (which means you can mine with no peers)
#testnode=1
#set a custom client name/user agent
#clientName=GoldenSandtrout
# Rescan from block height
#rescan=123
# Connect via a SOCKS5 proxy # Connect via a SOCKS5 proxy
#proxy=127.0.0.1:9050 #proxy=127.0.0.1:9050
# Automatically create Tor hidden service
#listenonion=1
#Use separate SOCKS5 proxy to reach peers via Tor hidden services
#onion=1.2.3.4:9050
# Only connect to nodes in network <net> (ipv4, ipv6, onion or i2p)"));
#onlynet=<net>
#Tor control port to use if onion listening enabled
#torcontrol=127.0.0.1:9051
# Bind to given address and always listen on it. Use [host]:port notation for IPv6 # Bind to given address and always listen on it. Use [host]:port notation for IPv6
#bind=<addr> #bind=<addr>
@@ -63,8 +83,9 @@
#rpcbind=<addr> #rpcbind=<addr>
# You must set rpcuser and rpcpassword to secure the JSON-RPC api # You must set rpcuser and rpcpassword to secure the JSON-RPC api
#rpcuser=Ulysses # These will automatically be created for you
#rpcpassword=YourSuperGreatPasswordNumber_DO_NOT_USE_THIS_OR_YOU_WILL_GET_ROBBED_385593 #rpcuser=user
#rpcpassword=supersecretpassword
# How many seconds node will wait for a complete RPC HTTP request. # How many seconds node will wait for a complete RPC HTTP request.
# after the HTTP connection is established. # after the HTTP connection is established.
@@ -83,7 +104,7 @@
#rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96 #rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96
# Listen for RPC connections on this TCP port: # Listen for RPC connections on this TCP port:
#rpcport=8232 #rpcport=1234
# You can use hushd to send commands to hushd # You can use hushd to send commands to hushd
# running on another host using this option: # running on another host using this option:
@@ -100,8 +121,8 @@
# Miscellaneous options # Miscellaneous options
# Enable attempt to mine HUSH # Enable mining at startup
#gen=0 #gen=1
# Set the number of threads to be used for mining (-1 = all cores). # Set the number of threads to be used for mining (-1 = all cores).
#genproclimit=1 #genproclimit=1
@@ -121,7 +142,7 @@
#paytxfee=0.00 #paytxfee=0.00
#Rewind the chain to specific block height. This is useful for creating snapshots at a given block height. #Rewind the chain to specific block height. This is useful for creating snapshots at a given block height.
#rewind=777777 #rewind=555
#Stop the chain a specific block height. This is useful for creating snapshots at a given block height. #Stop the chain a specific block height. This is useful for creating snapshots at a given block height.
#stopat=1000000 #stopat=1000000
@@ -129,9 +150,60 @@
#Set an address to use as change address for all transactions. This value must be set to a 33 byte pubkey. All mined coins will also be sent to this address. #Set an address to use as change address for all transactions. This value must be set to a 33 byte pubkey. All mined coins will also be sent to this address.
#pubkey=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392 #pubkey=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392
#Forfeit all user rewards to miners. Set this to explicitly not claim user rewards. # Disable clearnet (ipv4 and ipv6) connections to this node
#exchange=1 #clearnet=0
#Donate all user rewards to a a specific address. This value must be set to a 33 byte pubkey. # Disable ipv4
#donation=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392 #disableipv4=1
# Disable ipv6
#disableipv6=1
# Enable transaction index
#txindex=1
# Enable address index
#addressindex=1
# Enable timestamp index
#timestampindex=1
# Enable spent index
#spentindex=1
# Enable shielded stats index
#zindex=1
# Attempt to salvage a corrupt wallet
# salvagewallet=1
# Mine all blocks to this address (not good for your privacy and not recommended!)
# Disallowed if clearnet=0
# mineraddress=XXX
# Disable wallet
#disablewallet=1
# Allow mining to an address that is not in the current wallet
#minetolocalwallet=0
# Delete all wallet transactions
#zapwallettxes=1
# Enable sapling consolidation
# consolidation=1
# Enable stratum server
# stratum=1
# Run a command each time a new block is seen
# %s in command is replaced by block hash
#blocknotify=/my/awesome/script.sh %s
# Run a command when wallet gets a new tx
# %s in command is replaced with txid
#walletnotify=/my/cool/script.sh %s
# Run a command when tx expires
# %s in command is replaced with txid
#txexpirynotify=/my/elite/script.sh %s
# Execute this commend to send a tx
# %s is replaced with tx hex
#txsend=/send/it.sh %s

View File

@@ -5,7 +5,6 @@ BASE_CACHE ?= $(BASEDIR)/built
SDK_PATH ?= $(BASEDIR)/SDKs SDK_PATH ?= $(BASEDIR)/SDKs
NO_WALLET ?= NO_WALLET ?=
NO_UPNP ?= NO_UPNP ?=
FALLBACK_DOWNLOAD_PATH ?= https://supernet/depends-sources
BUILD ?= $(shell ./config.guess) BUILD ?= $(shell ./config.guess)
HOST ?= $(BUILD) HOST ?= $(BUILD)

View File

@@ -10,15 +10,15 @@ linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
ifeq (86,$(findstring 86,$(build_arch))) ifeq (86,$(findstring 86,$(build_arch)))
i686_linux_CC=gcc -m32 i686_linux_CC=$(CC) -m32
i686_linux_CXX=g++ -m32 i686_linux_CXX=$(CXX) -m32
i686_linux_AR=ar i686_linux_AR=ar
i686_linux_RANLIB=ranlib i686_linux_RANLIB=ranlib
i686_linux_NM=nm i686_linux_NM=nm
i686_linux_STRIP=strip i686_linux_STRIP=strip
x86_64_linux_CC=gcc -m64 x86_64_linux_CC=$(CC) -m64
x86_64_linux_CXX=g++ -m64 x86_64_linux_CXX=$(CXX) -m64
x86_64_linux_AR=ar x86_64_linux_AR=ar
x86_64_linux_RANLIB=ranlib x86_64_linux_RANLIB=ranlib
x86_64_linux_NM=nm x86_64_linux_NM=nm

View File

@@ -14,7 +14,8 @@ ifneq ($(build_os),darwin)
$(package)_config_opts_darwin=--disable-atomicsupport $(package)_config_opts_darwin=--disable-atomicsupport
endif endif
$(package)_config_opts_aarch64=--disable-atomicsupport $(package)_config_opts_aarch64=--disable-atomicsupport
$(package)_cxxflags+=-std=c++11 $(package)_cxxflags+=-std=c++11 -fPIE
$(package)_cflags+=-std=gnu17 -fPIE
endef endef
define $(package)_preprocess_cmds define $(package)_preprocess_cmds

View File

@@ -1,5 +1,6 @@
package=libgmp package=libgmp
ifeq ($(host_os),mingw32) ifeq ($(host_os),mingw32)
$(package)_download_path=https://github.com/radix42/$(package)/archive $(package)_download_path=https://github.com/radix42/$(package)/archive
$(package)_file_name=$(package)-$($(package)_git_commit).tar.gz $(package)_file_name=$(package)-$($(package)_git_commit).tar.gz
@@ -16,6 +17,7 @@ $(package)_file_name=d613c855-cd92-4efb-b893-658496852019
$(package)_download_file=d613c855-cd92-4efb-b893-658496852019 $(package)_download_file=d613c855-cd92-4efb-b893-658496852019
$(package)_sha256_hash=a8109865f2893f1373b0a8ed5ff7429de8db696fc451b1036bd7bdf95bbeffd6 $(package)_sha256_hash=a8109865f2893f1373b0a8ed5ff7429de8db696fc451b1036bd7bdf95bbeffd6
$(package)_config_opts=--enable-cxx --disable-shared $(package)_config_opts=--enable-cxx --disable-shared
$(package)_patches=gcc-15.patch
endif endif
#else #else
@@ -27,6 +29,10 @@ endif
#$(package)_config_opts=--enable-cxx --disable-shared #$(package)_config_opts=--enable-cxx --disable-shared
#endif #endif
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/gcc-15.patch
endef
define $(package)_config_cmds define $(package)_config_cmds
$($(package)_autoconf) --host=$(host) --build=$(build) $($(package)_autoconf) --host=$(host) --build=$(build)
endef endef

View File

@@ -6,6 +6,8 @@ $(package)_download_file=0d9f589e-a9f9-4ddb-acaa-0f1b423b32eb
$(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1 $(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1
$(package)_dependencies= $(package)_dependencies=
$(package)_config_opts= $(package)_config_opts=
$(package)_cflags=-std=gnu17
ifeq ($(build_os),darwin) ifeq ($(build_os),darwin)
define $(package)_set_vars define $(package)_set_vars
$(package)_build_env=MACOSX_DEPLOYMENT_TARGET="10.11" $(package)_build_env=MACOSX_DEPLOYMENT_TARGET="10.11"

View File

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

View File

@@ -20,6 +20,7 @@ $(package)_download_path=https://github.com/wolfSSL/wolfssl/archive
$(package)_download_file=v$($(package)_version)-stable.tar.gz $(package)_download_file=v$($(package)_version)-stable.tar.gz
define $(package)_set_vars define $(package)_set_vars
$(package)_cflags+=-std=gnu17
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
$(package)_config_opts=--prefix=$(host_prefix) $(package)_config_opts=--prefix=$(host_prefix)
$(package)_config_opts+=--host=$(host) $(package)_config_opts+=--host=$(host)
@@ -64,7 +65,7 @@ endef
#endef #endef
define $(package)_build_cmds define $(package)_build_cmds
$(MAKE) CPPFLAGS='-fPIC' -j1 src/libwolfssl.la $(MAKE) CPPFLAGS='-fPIC' -j$(nproc) src/libwolfssl.la
endef endef
define $(package)_stage_cmds define $(package)_stage_cmds

View File

@@ -0,0 +1,105 @@
diff --git a/acinclude.m4 b/acinclude.m4
index bcc6f52..53705e1 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -602,24 +602,6 @@ int f ()
}
])
-GMP_PROG_CC_WORKS_PART([$1], [long long reliability test 1],
-[/* The following provokes a segfault in the compiler on powerpc-apple-darwin.
- Extracted from tests/mpn/t-iord_u.c. Causes Apple's gcc 3.3 build 1640 and
- 1666 to segfault with e.g., -O2 -mpowerpc64. */
-
-#if defined (__GNUC__) && ! defined (__cplusplus)
-typedef unsigned long long t1;typedef t1*t2;
-void g(){}
-void h(){}
-static __inline__ t1 e(t2 rp,t2 up,int n,t1 v0)
-{t1 c,x,r;int i;if(v0){c=1;for(i=1;i<n;i++){x=up[i];r=x+1;rp[i]=r;}}return c;}
-void f(){static const struct{t1 n;t1 src[9];t1 want[9];}d[]={{1,{0},{1}},};t1 got[9];int i;
-for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
-#else
-int dummy;
-#endif
-])
-
GMP_PROG_CC_WORKS_PART([$1], [long long reliability test 2],
[/* The following provokes an internal compiler error on powerpc-apple-darwin.
Extracted from mpz/cfdiv_q_2exp.c. Causes Apple's gcc 3.3 build 1640 and
diff --git a/configure b/configure
index b9abc1b..04ba451 100755
--- a/configure
+++ b/configure
@@ -6382,71 +6382,6 @@ fi
-if test "$gmp_prog_cc_works" = yes; then
- # remove anything that might look like compiler output to our "||" expression
- rm -f conftest* a.out b.out a.exe a_out.exe
- cat >conftest.c <<EOF
-/* The following provokes a segfault in the compiler on powerpc-apple-darwin.
- Extracted from tests/mpn/t-iord_u.c. Causes Apple's gcc 3.3 build 1640 and
- 1666 to segfault with e.g., -O2 -mpowerpc64. */
-
-#if defined (__GNUC__) && ! defined (__cplusplus)
-typedef unsigned long long t1;typedef t1*t2;
-void g(){}
-void h(){}
-static __inline__ t1 e(t2 rp,t2 up,int n,t1 v0)
-{t1 c,x,r;int i;if(v0){c=1;for(i=1;i<n;i++){x=up[i];r=x+1;rp[i]=r;}}return c;}
-void f(){static const struct{t1 n;t1 src[9];t1 want[9];}d[]={{1,{0},{1}},};t1 got[9];int i;
-for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
-#else
-int dummy;
-#endif
-
-int main () { return 0; }
-EOF
- echo "Test compile: long long reliability test 1" >&5
- gmp_compile="$cc $cflags $cppflags conftest.c >&5"
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$gmp_compile\""; } >&5
- (eval $gmp_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- cc_works_part=yes
- if test "$cross_compiling" = no; then
- if { ac_try='./a.out || ./b.out || ./a.exe || ./a_out.exe || ./conftest'
- { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :;
- else
- cc_works_part=norun
- fi
- fi
- else
- cc_works_part=no
- fi
- if test "$cc_works_part" != yes; then
- echo "failed program was:" >&5
- cat conftest.c >&5
- fi
- rm -f conftest* a.out b.out a.exe a_out.exe
- case $cc_works_part in
- yes)
-
- ;;
- no)
- gmp_prog_cc_works="no, long long reliability test 1"
- ;;
- norun)
- gmp_prog_cc_works="no, long long reliability test 1, program does not run"
- ;;
- esac
-fi
-
-
-
-
if test "$gmp_prog_cc_works" = yes; then
# remove anything that might look like compiler output to our "||" expression
rm -f conftest* a.out b.out a.exe a_out.exe

View File

@@ -10,7 +10,30 @@ and no longer on Github, since they banned Duke Leto and
also because they censor many people around the world and work with also because they censor many people around the world and work with
evil organizations. They also use all your "private" repos to train their AI. evil organizations. They also use all your "private" repos to train their AI.
# Hush 3.10.5 ""
This is an OPTIONAL but RECOMMENDED upgrade.
* Concurrent `z_sendmany` now works
* A longstanding bug relating to run multiple `z_sendmany` operations at
once has been fixed. You can now queue up many `z_sendmany` operations
and they will succeed because they now understand how to avoid spending
coins that another `z_sendmany` process is trying to spend.
* New RPC `z_listlockunspent`
* Lists shielded notes (coins inside a zaddr) which are temporarily unspendable because an RPC process is currently trying to spend them.
* If that operation succeeds, they will become spent. If it fails they will be unlocked and become spendable again.
* Fixed DragonX checkpoints
* Hush checkpoints were mistakenly listed as checkpoints in the 3.10.4
release, which caused some nodes to be unable to sync.
* This release fixes this issue.
* Updated test framework and tests which allowed the fixing of the `z_sendmany` bug above
* Faster compiling of RandomX internals
# Hush 3.10.4 "Hazy Hākuturi" # Hush 3.10.4 "Hazy Hākuturi"
This is an OPTIONAL but RECOMMENDED upgrade. Some seed nodes have changed so if you are having
problems finding nodes, you want to upgrade.
* `z_sendmany` changes: * `z_sendmany` changes:
* Now supports UTF8 strings as memos instead of requiring hex * Now supports UTF8 strings as memos instead of requiring hex
* Give a memo as "utf8:this is my memo" and it will automatically be hex encoded * Give a memo as "utf8:this is my memo" and it will automatically be hex encoded

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
# Copyright (c) 2016-2024 The Hush developers # Copyright (c) 2016-2024 The Hush developers
# Copyright (c) 2018 SuperNET developers # Copyright (c) 2018 SuperNET developers
# Distributed under the GPLv3 software license, see the accompanying # Distributed under the GPLv3 software license, see the accompanying
@@ -8,7 +8,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \ from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \ initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises, assert_true
import time import time
from decimal import Decimal from decimal import Decimal
@@ -21,16 +21,11 @@ def assert_success(result):
def assert_error(result): def assert_error(result):
assert_equal(result['result'], 'error') assert_equal(result['result'], 'error')
def generate_random_string(length): class PrivateTest (BitcoinTestFramework):
random_string = ''.join(choice(ascii_uppercase) for i in range(length))
return random_string
class AssetChainPrivateTest (BitcoinTestFramework):
def setup_chain(self): def setup_chain(self):
print("Initializing ac_private test directory "+self.options.tmpdir) print("Initializing ac_private test directory "+self.options.tmpdir)
self.num_nodes = 1 self.num_nodes = 1
self.options.nocleanup = 1 # do not delete datadir after test run
initialize_chain_clean(self.options.tmpdir, self.num_nodes) initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False): def setup_network(self, split = False):
@@ -39,21 +34,19 @@ class AssetChainPrivateTest (BitcoinTestFramework):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[ extra_args=[[
# always give -ac_name as first extra_arg and port as third # always give -ac_name as first extra_arg and port as third
'-ac_name=REGTEST', '-ac_name=ZZZ',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf', '-conf='+self.options.tmpdir+'/node0/regtest/ZZZ.conf',
'-port=64367', '-port=64367',
'-rpcport=64368', '-rpcport=64368',
'-regtest', '-ac_supply=10',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=0',
'-ac_reward=25600000000', '-ac_reward=25600000000',
'-ac_private=1', '-ac_private=1',
'-allowlist=127.0.0.1', '-allowlist=127.0.0.1',
'-debug', #'-debug',
'-regtest',
'--daemon', '--daemon',
'-rpcuser=rt', '-rpcuser=hush',
'-rpcpassword=rt' '-rpcpassword=puppy'
]] ]]
) )
self.is_network_split = split self.is_network_split = split
@@ -71,23 +64,23 @@ class AssetChainPrivateTest (BitcoinTestFramework):
def run_test (self): def run_test (self):
print("Mining blocks...") print("Mining blocks...")
rpc = self.nodes[0] rpc = self.nodes[0]
# utxos from block 1 become mature in block 101 rpc.generate(1)
rpc.generate(101)
self.sync_all() self.sync_all()
rpc.getinfo() rpc.getinfo()
rpc.getwalletinfo() rpc.getwalletinfo()
taddr = rpc.getnewaddress() taddr = rpc.getnewaddress()
print "Sending to " + taddr
# sending to arbitrary non-notary transparent address is not allowed
assert_raises(JSONRPCException, rpc.sendtoaddress, taddr,1)
# this is a current notary address # sending to arbitrary non-notary transparent address is not allowed
# TODO: keep in sync when notaries change print("Sending to " + taddr)
#dev1_jl777 = "RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc" try:
# taddr vout is only allowed if it is a notary address rpc.sendtoaddress(taddr, 1)
#txid = rpc.sendtoaddress(dev1_jl777, 7) except:
#assert txid, 'got txid' assert_true(1)
# this should work but don't
#assert_raises(JSONRPCException, rpc.sendtoaddress, taddr,1)
if __name__ == '__main__': if __name__ == '__main__':
AssetChainPrivateTest ().main() PrivateTest ().main()

109
qa/rpc-tests/lockzins.py Executable file
View File

@@ -0,0 +1,109 @@
#!/usr/bin/env python3
# Copyright (c) 2016-2025 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
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises, assert_true, \
wait_and_assert_operationid_status
import time
from decimal import Decimal
from random import choice
from string import ascii_uppercase
def assert_success(result):
assert_equal(result['result'], 'success')
def assert_error(result):
assert_equal(result['result'], 'error')
class LockZinsTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
self.num_nodes = 1
self.options.nocleanup = 1 # do not delete datadir after test run
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=ZZZ',
#'-ac_algo=randomx',
#'-testnode=1', # why does this make the test node hang before run_test() ?
'-conf='+self.options.tmpdir+'/node0/regtest/ZZZ.conf',
'-port=64367',
'-rpcport=64368',
'-ac_supply=1',
'-ac_reward=100000000',
'-ac_private=1',
'-allowlist=127.0.0.1',
#'-debug',
'-regtest',
'--daemon',
'-zrpc',
'-zdebug',
'-zrpcunsafe'
]]
)
self.is_network_split = False
self.rpc = self.nodes[0]
self.sync_all()
print("Done setting up network")
def run_test (self):
print("Mining blocks...")
rpc = self.nodes[0]
# mine initial ac_supply
rpc.generate(1)
self.sync_all()
zaddr1 = rpc.z_getnewaddress()
zaddr2 = rpc.z_getnewaddress()
x = 0
while x < 15:
rpc.generate(1)
self.sync_all()
time.sleep(1)
rpc.z_shieldcoinbase('*', zaddr1, 0, 1)
x = x+1
rpc.generate(11)
self.sync_all()
# rpc.z_listunspent()
rpc.z_getbalances()
recipients = []
recipients.append({"address": zaddr2, "amount": Decimal('3')})
# queue 4 ztxs, which will try to spend the same funds multiple times
# without correct locking of zins
opid1 = rpc.z_sendmany(zaddr1,recipients,1,0)
rpc.z_listlockunspent()
opid2 = rpc.z_sendmany(zaddr1,recipients,1,0)
rpc.z_listlockunspent()
opid3 = rpc.z_sendmany(zaddr1,recipients,1,0)
rpc.z_listlockunspent()
opid4 = rpc.z_sendmany(zaddr1,recipients,1,0)
rpc.generate(1)
self.sync_all()
# now that we have fullyNotified, this may not be needed?
#time.sleep(3)
wait_and_assert_operationid_status(self.nodes[0], opid1)
wait_and_assert_operationid_status(self.nodes[0], opid2)
wait_and_assert_operationid_status(self.nodes[0], opid3)
wait_and_assert_operationid_status(self.nodes[0], opid4)
rpc.z_getoperationstatus()
if __name__ == '__main__':
LockZinsTest ().main()

View File

@@ -0,0 +1,247 @@
#!/usr/bin/env python3
# Copyright (c) 2016-2025 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
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, assert_greater_than, assert_greater_than_or_equal, \
initialize_chain_clean, initialize_chain, start_nodes, start_node, connect_nodes_bi, \
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises, assert_true, \
wait_and_assert_operationid_status
import time
from decimal import Decimal
def assert_success(result):
assert_equal(result['result'], 'success')
def assert_error(result):
assert_equal(result['result'], 'error')
class ShieldCoinbaseDonationTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
self.num_nodes = 1
self.options.nocleanup = 1 # do not delete datadir after test run
#self.options.nocleanup = 0
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self, split = False):
print("Setting up network...")
self.supply = 555
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[[
# always give -ac_name as first extra_arg and port as third
'-ac_name=ZZZ',
#'-ac_algo=randomx',
#'-testnode=1', # why does this make the test node hang before run_test() ?
'-conf='+self.options.tmpdir+'/node0/regtest/ZZZ.conf',
'-port=63367',
'-rpcport=63368',
'-ac_supply=' + str(self.supply),
'-ac_reward=300000000',
'-ac_private=1',
'-allowlist=127.0.0.1',
'-regtest',
'--daemon',
#'-debug',
'-zrpc',
'-zdebug',
'-zrpcunsafe'
]]
)
self.is_network_split = False
self.rpc = self.nodes[0]
self.sync_all()
print("Done setting up network")
def run_test (self):
# NOTE: order of these tests is important
self.run_test_default()
self.run_test_custom()
self.run_test_custom_nondefault_fee()
def run_test_default(self):
rpc = self.nodes[0]
# mine initial ac_supply
rpc.generate(1)
self.sync_all()
zaddr1 = rpc.z_getnewaddress()
#rpc.z_exportkey(zaddr1)
# first we test the default situation where no donation is given and
# it defaults to 0
response = rpc.z_shieldcoinbase('*', zaddr1, 0, 1)
opid = response['opid']
shieldingValue = response['shieldingValue']
assert_true( shieldingValue >= self.supply )
print("opid=" + opid)
time.sleep(2) # give some time for the ztx to complete
# 555 supply plus magic utxo = 555.05537304
# NOTE: if any consensus params for this testcoin are changed above,
# the magic utxo will change and this value will need to be updated
totalSupply = 55505537304 # in puposhis
expectedAmount = totalSupply
json = rpc.z_getoperationstatus()
txid = json[0]['result']['txid']
wait_and_assert_operationid_status(rpc, opid)
rawtx0 = rpc.z_viewtransaction(txid)
assert_equal( rawtx0['outputs'][0]['valueZat'] , expectedAmount, '5% donation sends correct sendAmount')
def run_test_custom_nondefault_fee(self):
rpc = self.nodes[0]
zaddr1 = rpc.z_getnewaddress()
donation = 5
# donation zaddr is already imported from previous test
# NOTE: goal here is to test a situation where
# sendAmount/donationAmount arithmetic leads to a situation where the
# exact amount in satoshis must deal with truncation/rounding
# shield funds to a new zaddr in this wallet with non-default fee
fee = 0.00000001 # 1 puposhi fee will lead to some kind of rounding/truncation arithmetic
response = rpc.z_shieldcoinbase('*', zaddr1, fee, 1, donation)
opid = response['opid']
print("opid=" + opid)
shieldingValue = response['shieldingValue']
# sanity check. None of the expected values below will be correct if
# this is different
assert_equal( str(shieldingValue) , "3.00010000" )
# TODO: this might not be enough time for slow machines, better
# solution would be to wait until the opid finishes
time.sleep(2) # give some time for the ztx to complete
# confirm tx from above
rpc.generate(1)
self.sync_all()
# get the txid
json = rpc.z_getoperationstatus()
# NOTE: this is index 1 because this test runs after the above test
# It would be better to specifically find the data for our opid
txid = json[1]['result']['txid']
print("txid=" + txid)
rpc.z_listunspent()
# (300010000 - 1)*.05
# 15000499.95
# (300010000 - 1) - 15000499
# 285009500
# The above value will be truncated (not rounded) by casting from
# double to CAmount/int64_t which means the donation will be 15000499
# and the sendAmount will be 300010000 - 1 (the fee) - 15000499 = 285009500
# these values assume that 3.0001 was shielded
expectedSendAmount = 285009500
expectedDonationAmount = 15000499
# lookup txid
rawtx1 = rpc.z_viewtransaction(txid)
# TODO: set this up once for all tests since they all use the same zaddr
donation_zaddr = "zregtestsapling1y30nwg0clsu6gcyrnvht8hdyfk3vwtszlh6kc4z5hv9hmpxzg2g0nx7c60xeecggm9x9gma96t4"
# there should be two outputs to different addresses, order is nondeterministic
if rawtx1['outputs'][0]['address'] == donation_zaddr:
donation_zout = 0
other_zout = 1
else:
donation_zout = 1
other_zout = 0
assert_equal( rawtx1['outputs'][donation_zout]['address'] , donation_zaddr, 'correct zaddr gets donation')
assert_equal( rawtx1['outputs'][donation_zout]['valueZat'] , expectedDonationAmount, '5% donation sends correct donationAmount')
assert_equal( rawtx1['outputs'][other_zout]['address'] , zaddr1, 'correct zaddr gets main amount')
assert_equal( rawtx1['outputs'][other_zout]['valueZat'] , expectedSendAmount, '5% donation sends correct sendAmount')
#TODO: assert sum = 3
def run_test_custom(self):
rpc = self.nodes[0]
zaddr1 = rpc.z_getnewaddress()
# generate some new coinbase funds
rpc.generate(1)
self.sync_all()
testing_zaddr = "zregtestsapling1y30nwg0clsu6gcyrnvht8hdyfk3vwtszlh6kc4z5hv9hmpxzg2g0nx7c60xeecggm9x9gma96t4"
testing_privkey = "secret-extended-key-regtest1q0hgrms7qqqqpqrsz6myrtnh3ccp8uzp0kgxj6029wr6vq5hqvyccdlz7a745pgm5eeaamxqp9rxll2xctfrlw2l8xhxsc7zsut2tyz0374rrlk8srjswx7rhm6hcf2d7fuwajazvjesafduzxyka4w02tqjxdehzvghyrsd2zll90k3g2ckdvc5kqd6r7r7nglrtj0ej5a40d6lh8zxrvdlxrpuc59y5m8n9tekdxh4wpqn3smv5nxu4vvu58f8dgwn92qfqrvxqlscchtyh"
# import zaddr that receives donation , no rescan
rpc.z_importkey(testing_privkey, "no")
rpc.z_listaddresses()
# now we test giving a donation parameter
donation = 5
# shield funds to a new zaddr in this wallet with default fee
fee = 0.0001
response = rpc.z_shieldcoinbase('*', zaddr1, fee, 1, donation)
opid = response['opid']
print("opid=" + opid)
#wait_and_assert_operationid_status(rpc, opid)
shieldingValue = response['shieldingValue']
assert_greater_than_or_equal( shieldingValue , 3.0 )
time.sleep(2) # give some time for the ztx to complete
rpc.getinfo()
rpc.generate(1)
self.sync_all()
# get the txid
json = rpc.z_getoperationstatus()
txid = json[0]['result']['txid']
print("txid=" + txid)
rpc.z_listunspent()
# (3 - fee)*0.05
expectedAmount1 = 14999500
# lookup txid
rawtx1 = rpc.z_viewtransaction(txid)
# there should be two outputs to different addresses, order is nondeterministic
if rawtx1['outputs'][0]['address'] == testing_zaddr:
donation_zout = 0
other_zout = 1
else:
donation_zout = 1
other_zout = 0
# print("donation_zout=%d other_zout=%d" % (donation_zout,other_zout) )
assert_equal( rawtx1['outputs'][donation_zout]['address'] , testing_zaddr, 'correct zaddr gets donation')
assert_equal( rawtx1['outputs'][donation_zout]['valueZat'] , expectedAmount1, '5% donation sends correct donationAmount')
# (3 - fee)*0.95
expectedAmount2 = 284990500
assert_equal( rawtx1['outputs'][other_zout]['address'] , zaddr1, 'correct zaddr gets main amount')
assert_equal( rawtx1['outputs'][other_zout]['valueZat'] , expectedAmount2, '5% donation sends correct sendAmount')
assert_equal( expectedAmount1 + expectedAmount2, 299990000, 'sendAmount+donationAmount = targetAmount - fee' )
if __name__ == '__main__':
ShieldCoinbaseDonationTest().main()

View File

@@ -1,8 +1,4 @@
#!/usr/bin/env python2 # Copyright (c) 2016-2025 The Hush 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 2011 Jeff Garzik Copyright 2011 Jeff Garzik
@@ -38,45 +34,37 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
try:
import http.client as httplib
except ImportError:
import httplib
import base64 import base64
import decimal import decimal
import json import json
import logging import logging
try: from http.client import HTTPConnection, HTTPSConnection, BadStatusLine
import urllib.parse as urlparse from urllib.parse import urlparse
except ImportError:
import urlparse USER_AGENT = "HushAuthServiceProxy/0.1"
USER_AGENT = "FUCKjl777LULZ"
HTTP_TIMEOUT = 600 HTTP_TIMEOUT = 600
log = logging.getLogger("BitcoinRPC")
log = logging.getLogger("RPC")
class JSONRPCException(Exception): class JSONRPCException(Exception):
def __init__(self, rpc_error): def __init__(self, rpc_error):
Exception.__init__(self) Exception.__init__(self, rpc_error.get("message"))
self.error = rpc_error self.error = rpc_error
def EncodeDecimal(o): def EncodeDecimal(o):
if isinstance(o, decimal.Decimal): if isinstance(o, decimal.Decimal):
return round(o, 8) return str(o)
raise TypeError(repr(o) + " is not JSON serializable") raise TypeError(repr(o) + " is not JSON serializable")
class AuthServiceProxy(object):
class AuthServiceProxy():
__id_count = 0 __id_count = 0
def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None): def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None):
self.__service_url = service_url self.__service_url = service_url
self.__service_name = service_name self._service_name = service_name
self.__url = urlparse.urlparse(service_url) self.__url = urlparse(service_url)
if self.__url.port is None:
port = 80
else:
port = self.__url.port
(user, passwd) = (self.__url.username, self.__url.password) (user, passwd) = (self.__url.username, self.__url.password)
try: try:
user = user.encode('utf8') user = user.encode('utf8')
@@ -89,23 +77,25 @@ class AuthServiceProxy(object):
authpair = user + b':' + passwd authpair = user + b':' + passwd
self.__auth_header = b'Basic ' + base64.b64encode(authpair) self.__auth_header = b'Basic ' + base64.b64encode(authpair)
self.timeout = timeout
self._set_conn(connection)
def _set_conn(self, connection=None):
port = 80 if self.__url.port is None else self.__url.port
if connection: if connection:
# Callables re-use the connection of the original proxy
self.__conn = connection self.__conn = connection
self.timeout = connection.timeout
elif self.__url.scheme == 'https': elif self.__url.scheme == 'https':
self.__conn = httplib.HTTPSConnection(self.__url.hostname, port, self.__conn = HTTPSConnection(self.__url.hostname, port, timeout=self.timeout)
None, None, False,
timeout)
else: else:
self.__conn = httplib.HTTPConnection(self.__url.hostname, port, self.__conn = HTTPConnection(self.__url.hostname, port, timeout=self.timeout)
False, timeout)
def __getattr__(self, name): def __getattr__(self, name):
if name.startswith('__') and name.endswith('__'): if name.startswith('__') and name.endswith('__'):
# Python internal stuff # Python internal stuff
raise AttributeError raise AttributeError
if self.__service_name is not None: if self._service_name is not None:
name = "%s.%s" % (self.__service_name, name) name = "%s.%s" % (self._service_name, name)
return AuthServiceProxy(self.__service_url, name, connection=self.__conn) return AuthServiceProxy(self.__service_url, name, connection=self.__conn)
def _request(self, method, path, postdata): def _request(self, method, path, postdata):
@@ -124,8 +114,9 @@ class AuthServiceProxy(object):
# If connection was closed, try again. # If connection was closed, try again.
# Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset. # Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset.
# ConnectionResetError happens on FreeBSD with Python 3.4. # ConnectionResetError happens on FreeBSD with Python 3.4.
# These classes don't exist in Python 2.x, so we can't refer to them directly. # This can be simplified now that we depend on Python 3 (previously, we could not
if ((isinstance(e, httplib.BadStatusLine) and e.line == "''") # refer to BrokenPipeError or ConnectionResetError which did not exist on Python 2)
if ((isinstance(e, BadStatusLine) and e.line == "''")
or e.__class__.__name__ in ('BrokenPipeError', 'ConnectionResetError')): or e.__class__.__name__ in ('BrokenPipeError', 'ConnectionResetError')):
self.__conn.close() self.__conn.close()
self.__conn.request(method, path, postdata, headers) self.__conn.request(method, path, postdata, headers)
@@ -136,10 +127,10 @@ class AuthServiceProxy(object):
def __call__(self, *args): def __call__(self, *args):
AuthServiceProxy.__id_count += 1 AuthServiceProxy.__id_count += 1
log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self.__service_name, log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self._service_name,
json.dumps(args, default=EncodeDecimal))) json.dumps(args, default=EncodeDecimal)))
postdata = json.dumps({'version': '1.1', postdata = json.dumps({'version': '1.1',
'method': self.__service_name, 'method': self._service_name,
'params': args, 'params': args,
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal) 'id': AuthServiceProxy.__id_count}, default=EncodeDecimal)
response = self._request('POST', self.__url.path, postdata) response = self._request('POST', self.__url.path, postdata)
@@ -162,6 +153,11 @@ class AuthServiceProxy(object):
raise JSONRPCException({ raise JSONRPCException({
'code': -342, 'message': 'missing HTTP response from server'}) 'code': -342, 'message': 'missing HTTP response from server'})
content_type = http_response.getheader('Content-Type')
if content_type != 'application/json':
raise JSONRPCException({
'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)})
responsedata = http_response.read().decode('utf8') responsedata = http_response.read().decode('utf8')
response = json.loads(responsedata, parse_float=decimal.Decimal) response = json.loads(responsedata, parse_float=decimal.Decimal)
if "error" in response and response["error"] is None: if "error" in response and response["error"] is None:

View File

@@ -123,21 +123,26 @@ class BitcoinTestFramework(object):
print("JSONRPC error: "+e.error['message']) print("JSONRPC error: "+e.error['message'])
traceback.print_tb(sys.exc_info()[2]) traceback.print_tb(sys.exc_info()[2])
except AssertionError as e: except AssertionError as e:
print("Assertion failed: "+e.message) print("Assertion failed: " + str(e))
traceback.print_tb(sys.exc_info()[2])
except KeyError as e:
print("key not found: "+ str(e))
traceback.print_tb(sys.exc_info()[2]) traceback.print_tb(sys.exc_info()[2])
except Exception as e: except Exception as e:
print("Unexpected exception caught during testing: "+str(e)) print("Unexpected exception caught during testing: "+str(e))
traceback.print_tb(sys.exc_info()[2]) traceback.print_tb(sys.exc_info()[2])
except KeyboardInterrupt as e:
print("Exiting after " + repr(e))
if not self.options.noshutdown: if not self.options.noshutdown:
print("Stopping nodes") print("Stopping nodes")
stop_nodes(self.nodes) stop_nodes(self.nodes)
wait_bitcoinds() wait_bitcoinds()
else: else:
print("Note: hushds were not stopped and may still be running") print("Note: nodes were not stopped and may still be running")
if not self.options.nocleanup and not self.options.noshutdown: if not self.options.nocleanup and not self.options.noshutdown:
print("Cleaning up") print("Deleting %s" % self.options.tmpdir)
shutil.rmtree(self.options.tmpdir) shutil.rmtree(self.options.tmpdir)
if success: if success:
@@ -169,7 +174,7 @@ class ComparisonTestFramework(BitcoinTestFramework):
help="bitcoind binary to use for reference nodes (if any)") help="bitcoind binary to use for reference nodes (if any)")
def setup_chain(self): def setup_chain(self):
print "Initializing test directory "+self.options.tmpdir print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, self.num_nodes) initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self): def setup_network(self):

View File

@@ -57,7 +57,7 @@ def sync_blocks(rpc_connections, wait=1):
break break
time.sleep(wait) time.sleep(wait)
# Now that the block counts are in sync, wait for the internal # Now that the block counts are in sync, wait for the internal
# notifications to finish # notifications to finish
while True: while True:
notified = [ x.getblockchaininfo()['fullyNotified'] for x in rpc_connections ] notified = [ x.getblockchaininfo()['fullyNotified'] for x in rpc_connections ]
@@ -91,15 +91,17 @@ def sync_mempools(rpc_connections, wait=1):
bitcoind_processes = {} bitcoind_processes = {}
def initialize_datadir(dirname, n): def initialize_datadir(dirname, n):
datadir = os.path.join(dirname, "node"+str(n)) datadir = os.path.join(dirname, "node"+str(n), "regtest")
datadir = os.path.join(datadir,"HUSH3") #datadir = os.path.join(datadir,"ZZZ")
if not os.path.isdir(datadir): if not os.path.isdir(datadir):
print("Creating dirs %s" % datadir)
os.makedirs(datadir) os.makedirs(datadir)
print("Writing to " + os.path.join(datadir,"HUSH3.conf")) print("Writing to " + os.path.join(datadir,"ZZZ.conf"))
with open(os.path.join(datadir, "HUSH3.conf"), 'w') as f: with open(os.path.join(datadir, "ZZZ.conf"), 'w') as f:
f.write("regtest=1\n"); f.write("regtest=1\n");
f.write("txindex=1\n"); f.write("txindex=1\n");
#f.write("testnode=1\n");
f.write("server=1\n"); f.write("server=1\n");
f.write("showmetrics=0\n"); f.write("showmetrics=0\n");
f.write("rpcuser=hush\n"); f.write("rpcuser=hush\n");
@@ -107,13 +109,15 @@ def initialize_datadir(dirname, n):
f.write("port="+str(p2p_port(n))+"\n"); f.write("port="+str(p2p_port(n))+"\n");
rpcport = str(rpc_port(n)) rpcport = str(rpc_port(n))
f.write("rpcport="+rpcport+"\n"); f.write("rpcport="+rpcport+"\n");
print "RPC port=" + rpcport print("RPC port=" + rpcport)
f.write("listenonion=0\n"); f.write("listenonion=0\n");
# TODO: maybe make these optional, via arg to initialize_datadir, defaulted to on for now # TODO: maybe make these optional, via arg to initialize_datadir, defaulted to on for now
f.write("addressindex=1\n"); f.write("addressindex=1\n");
f.write("spentindex=1\n"); f.write("spentindex=1\n");
f.write("timestampindex=1\n"); f.write("timestampindex=1\n");
f.write("zindex=1\n"); #f.write("zindex=1\n");
print("Done writing to %s" % os.path.join(datadir,"ZZZ.conf") )
return datadir return datadir
def initialize_chain(test_dir): def initialize_chain(test_dir):
@@ -136,14 +140,14 @@ def initialize_chain(test_dir):
cmd = os.getenv("BITCOINCLI", "hush-cli") cmd = os.getenv("BITCOINCLI", "hush-cli")
cmd_args = cmd + " -datadir="+datadir + " -rpcwait getblockcount" cmd_args = cmd + " -datadir="+datadir + " -rpcwait getblockcount"
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "initialize_chain: hushd started, calling: " + cmd_args print("initialize_chain: hushd started, calling: " + cmd_args)
strcmd = cmd + " " + "-datadir="+datadir + " -rpcwait getblockcount" strcmd = cmd + " " + "-datadir="+datadir + " -rpcwait getblockcount"
print("Running " + strcmd) print("Running " + strcmd)
subprocess.check_call(strcmd, shell=True); subprocess.check_call(strcmd, shell=True);
#subprocess.check_call([ cmd, "-rpcwait", "getblockcount"], stdout=devnull) #subprocess.check_call([ cmd, "-rpcwait", "getblockcount"], stdout=devnull)
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "initialize_chain: hush-cli -rpcwait getblockcount completed" print("initialize_chain: hush-cli -rpcwait getblockcount completed")
devnull.close() devnull.close()
rpcs = [] rpcs = []
for i in range(4): for i in range(4):
@@ -175,7 +179,7 @@ def initialize_chain(test_dir):
stop_nodes(rpcs) stop_nodes(rpcs)
wait_bitcoinds() wait_bitcoinds()
for i in range(4): for i in range(4):
print "Cleaning up cache dir files" print("Cleaning up cache dir files")
os.remove(log_filename("cache", i, "debug.log")) os.remove(log_filename("cache", i, "debug.log"))
os.remove(log_filename("cache", i, "db.log")) os.remove(log_filename("cache", i, "db.log"))
os.remove(log_filename("cache", i, "peers.dat")) os.remove(log_filename("cache", i, "peers.dat"))
@@ -221,36 +225,41 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
""" """
Start a hushd and return RPC connection to it Start a hushd and return RPC connection to it
""" """
print("Starting node " + str(i)) print("Starting node " + str(i) + " in dir " + dirname)
datadir = os.path.join(dirname, "node"+str(i)) datadir = os.path.join(dirname, "node"+str(i), "regtest")
# creating special config in case of cryptocondition asset chain test # creating special config
if len(extra_args) > 0 and extra_args[0] == '-ac_name=REGTEST': if len(extra_args) > 0 and extra_args[0] == '-ac_name=ZZZ':
configpath = datadir + "/REGTEST.conf" configpath = datadir + "/ZZZ.conf"
with open(configpath, "w+") as config: with open(configpath, "w+") as config:
config.write("regtest=1\n") config.write("rpcuser=hush\n")
config.write("rpcuser=rt\n") config.write("rpcpassword=puppy\n")
config.write("rpcpassword=rt\n")
port = extra_args[3] port = extra_args[3]
config.write("rpcport=" + (port[9:]) + "\n") config.write("rpcport=" + (port[9:]) + "\n")
config.write("server=1\n") config.write("server=1\n")
#config.write("testnode=1\n")
config.write("txindex=1\n") config.write("txindex=1\n")
config.write("rpcworkqueue=256\n") config.write("rpcworkqueue=256\n")
config.write("rpcallowip=127.0.0.1\n") config.write("rpcallowip=127.0.0.1\n")
config.write("bind=127.0.0.1\n") config.write("bind=127.0.0.1\n")
config.write("rpcbind=127.0.0.1") #config.write("listenonion=0\n")
#config.write("torcontrol=127.0.0.1:9999\n")
config.write("rpcbind=127.0.0.1\n")
print("Done writing to %s" % configpath)
if binary is None: if binary is None:
binary = os.getenv("BITCOIND", "hushd") binary = os.getenv("BITCOIND", "src/hushd")
args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ] args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
if extra_args is not None: args.extend(extra_args) if extra_args is not None: args.extend(extra_args)
#print("args=" + ' '.join(args)) print("args=" + ' '.join(args))
bitcoind_processes[i] = subprocess.Popen(args) bitcoind_processes[i] = subprocess.Popen(args)
devnull = open("/dev/null", "w+") devnull = open("/dev/null", "w+")
cmd = os.getenv("BITCOINCLI", "hush-cli") cmd = os.getenv("BITCOINCLI", "src/hush-cli")
print("cmd=" + cmd) print("cmd=" + cmd)
cmd_args = ' '.join(extra_args) + " -rpcwait getblockcount " args = [ extra_args[0], "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
cmd_args = ' '.join(args) + " -rpcwait getblockcount "
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "start_node: hushd started, calling : " + cmd + " " + cmd_args print("start_node: hushd started, calling : " + cmd + " " + cmd_args)
strcmd = cmd + " " + cmd_args strcmd = cmd + " " + cmd_args
print("Running " + strcmd) print("Running " + strcmd)
@@ -261,19 +270,20 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
# _rpchost_to_args(rpchost) + # _rpchost_to_args(rpchost) +
# ["-rpcwait", "-rpcport=6438", "getblockcount"], stdout=devnull) # ["-rpcwait", "-rpcport=6438", "getblockcount"], stdout=devnull)
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "start_node: calling hush-cli -rpcwait getblockcount returned" print("start_node: calling hush-cli -rpcwait getblockcount returned")
devnull.close() devnull.close()
#port = extra_args[3] port = extra_args[3]
port = rpc_port(i) #port = rpc_port(i)
#print("port=%s" % port)
username = rpc_username() username = rpc_username()
password = rpc_password() password = rpc_password()
url = "http://%s:%s@%s:%d" % (username, password, rpchost or '127.0.0.1', int(port[9:])) url = "http://%s:%s@%s:%s" % (username, password, rpchost or '127.0.0.1', port[9:])
print("connecting to " + url) print("connecting to " + url)
if timewait is not None: if timewait is not None:
proxy = AuthServiceProxy(url, timeout=timewait) proxy = AuthServiceProxy(url, timeout=timewait)
else: else:
proxy = AuthServiceProxy(url) proxy = AuthServiceProxy(url)
print("created proxy") #print("created proxy")
proxy.url = url # store URL on proxy for info proxy.url = url # store URL on proxy for info
return proxy return proxy
@@ -470,7 +480,7 @@ def assert_raises(exc, fun, *args, **kwds):
def wait_and_assert_operationid_status(node, myopid, in_status='success', in_errormsg=None, timeout=300): def wait_and_assert_operationid_status(node, myopid, in_status='success', in_errormsg=None, timeout=300):
print('waiting for async operation {}'.format(myopid)) print('waiting for async operation {}'.format(myopid))
result = None result = None
for _ in xrange(1, timeout): for _ in range(1, timeout):
results = node.z_getoperationresult([myopid]) results = node.z_getoperationresult([myopid])
if len(results) > 0: if len(results) > 0:
result = results[0] result = results[0]

View File

@@ -5,7 +5,7 @@
DIST_SUBDIRS = secp256k1 univalue DIST_SUBDIRS = secp256k1 univalue
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS)
AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) -std=c++17
AM_CPPFLAGS = $(HARDENED_CPPFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS)
EXTRA_LIBRARIES = EXTRA_LIBRARIES =
@@ -594,7 +594,7 @@ libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBOOST_SPIRIT_THREADSAFE -DHAV
#libzcash_a_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) #libzcash_a_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
#libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMONTGOMERY_OUTPUT #libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMONTGOMERY_OUTPUT
libzcash_a_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing libzcash_a_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing -std=gnu17
libzcash_a_LDFLAGS = $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) libzcash_a_LDFLAGS = $(SAN_LDFLAGS) $(HARDENED_LDFLAGS)
libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT
@@ -636,7 +636,7 @@ libhush_a_SOURCES = \
libhush_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) -pipe -O1 -g -Wstack-protector -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) libhush_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) -pipe -O1 -g -Wstack-protector -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES)
libhush_a_CXXFLAGS = $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing libhush_a_CXXFLAGS = $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing -std=gnu17
libhush_a_LDFLAGS = $(HARDENED_LDFLAGS) libhush_a_LDFLAGS = $(HARDENED_LDFLAGS)

View File

@@ -1,5 +1,4 @@
SHELL = /bin/sh SHELL = /bin/sh
CC = gcc
CC_DARWIN = g++-8 CC_DARWIN = g++-8
CC_WIN = x86_64-w64-mingw32-gcc-posix CC_WIN = x86_64-w64-mingw32-gcc-posix
CC_AARCH64 = aarch64-linux-gnu-g++ CC_AARCH64 = aarch64-linux-gnu-g++

File diff suppressed because it is too large Load Diff

View File

@@ -301,7 +301,7 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType)
bool bInitialized = false; bool bInitialized = false;
WOLFSSL_CTX* tlsCtx = NULL; WOLFSSL_CTX* tlsCtx = NULL;
byte *pem; unsigned char *pem;
int plen = 0; int plen = 0;
if ((tlsCtx = wolfSSL_CTX_new(ctxType == SERVER_CONTEXT ? wolfTLSv1_3_server_method() : wolfTLSv1_3_client_method()))) { if ((tlsCtx = wolfSSL_CTX_new(ctxType == SERVER_CONTEXT ? wolfTLSv1_3_server_method() : wolfTLSv1_3_client_method()))) {

View File

@@ -556,12 +556,7 @@ static const char *notaries_list[NUM_HUSH_SEASONS][NUM_HUSH_NOTARIES][2] =
#define HUSH_BIT63SET(x) ((x) & ((uint64_t)1 << 63)) #define HUSH_BIT63SET(x) ((x) & ((uint64_t)1 << 63))
#define HUSH_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN) #define HUSH_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN)
//#ifndef TESTMODE extern uint8_t ASSETCHAINS_CLEARNET;
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
//#else
//#define PRICES_DAYWINDOW (7)
//#endif
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
extern int8_t ASSETCHAINS_ADAPTIVEPOW; extern int8_t ASSETCHAINS_ADAPTIVEPOW;
int32_t MAX_BLOCK_SIZE(int32_t height); int32_t MAX_BLOCK_SIZE(int32_t height);
@@ -582,13 +577,12 @@ extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTP
extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA; extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA;
extern std::vector<std::string> ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; extern std::vector<std::string> ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS;
extern uint256 HUSH_EARLYTXID; extern uint256 HUSH_EARLYTXID;
extern int32_t HUSH_CONNECTING,HUSH_CCACTIVATE,HUSH_DEALERNODE; extern int32_t HUSH_CONNECTING,HUSH_CCACTIVATE;
extern uint32_t ASSETCHAINS_CC; extern uint32_t ASSETCHAINS_CC;
extern std::string CCerror,ASSETCHAINS_CCLIB; extern std::string CCerror,ASSETCHAINS_CCLIB;
extern uint8_t ASSETCHAINS_CCDISABLES[256]; extern uint8_t ASSETCHAINS_CCDISABLES[256];
extern int32_t USE_EXTERNAL_PUBKEY; extern int32_t USE_EXTERNAL_PUBKEY;
extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS;
extern std::string DONATION_PUBKEY;
extern uint8_t ASSETCHAINS_PRIVATE; extern uint8_t ASSETCHAINS_PRIVATE;
extern int32_t USE_EXTERNAL_PUBKEY; extern int32_t USE_EXTERNAL_PUBKEY;
extern char NOTARYADDRS[64][64]; extern char NOTARYADDRS[64][64];
@@ -622,12 +616,8 @@ int32_t hush_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeigh
char *hush_pricename(char *name,int32_t ind); char *hush_pricename(char *name,int32_t ind);
int32_t hush_priceind(const char *symbol); int32_t hush_priceind(const char *symbol);
int32_t hush_pricesinit(); int32_t hush_pricesinit();
int64_t hush_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip);
int64_t hush_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth);
int32_t hush_nextheight(); int32_t hush_nextheight();
uint32_t hush_heightstamp(int32_t height); uint32_t hush_heightstamp(int32_t height);
int64_t hush_pricemult(int32_t ind);
int32_t hush_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks);
int32_t hush_currentheight(); int32_t hush_currentheight();
int32_t hush_notarized_bracket(struct notarized_checkpoint *nps[2],int32_t height); int32_t hush_notarized_bracket(struct notarized_checkpoint *nps[2],int32_t height);
arith_uint256 hush_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime); arith_uint256 hush_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime);

File diff suppressed because it is too large Load Diff

View File

@@ -45,11 +45,12 @@ int COINBASE_MATURITY = _COINBASE_MATURITY;//100;
unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10;
uint256 HUSH_EARLYTXID; uint256 HUSH_EARLYTXID;
int32_t HUSH_MININGTHREADS = -1,IS_HUSH_NOTARY,USE_EXTERNAL_PUBKEY,HUSH_CHOSEN_ONE,ASSETCHAINS_SEED,HUSH_ON_DEMAND,HUSH_EXTERNAL_NOTARIES,HUSH_PASSPORT_INITDONE,HUSH_PAX,HUSH_EXCHANGEWALLET,HUSH_REWIND,HUSH_CONNECTING = -1,HUSH_DEALERNODE,HUSH_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,HUSH_NSPV; int32_t HUSH_MININGTHREADS = -1,IS_HUSH_NOTARY,USE_EXTERNAL_PUBKEY,HUSH_CHOSEN_ONE,ASSETCHAINS_SEED,HUSH_ON_DEMAND,HUSH_EXTERNAL_NOTARIES,HUSH_PASSPORT_INITDONE,HUSH_PAX,HUSH_EXCHANGEWALLET,HUSH_REWIND,HUSH_CONNECTING = -1,HUSH_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,HUSH_NSPV;
int32_t HUSH_INSYNC,HUSH_LASTMINED,prevHUSH_LASTMINED,HUSH_CCACTIVATE; int32_t HUSH_INSYNC,HUSH_LASTMINED,prevHUSH_LASTMINED,HUSH_CCACTIVATE;
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA; uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA;
int8_t ASSETCHAINS_ADAPTIVEPOW; int8_t ASSETCHAINS_ADAPTIVEPOW;
uint8_t ASSETCHAINS_CLEARNET = 1;
uint8_t ASSETCHAINS_BURN = 0; uint8_t ASSETCHAINS_BURN = 0;
uint32_t ASSETCHAINS_MINOPRETURNFEE = 0; uint32_t ASSETCHAINS_MINOPRETURNFEE = 0;
std::vector<uint8_t> Mineropret; std::vector<uint8_t> Mineropret;

View File

@@ -1339,7 +1339,7 @@ void hush_statefname(char *fname,char *symbol,char *str)
fname[len - n] = 0; fname[len - n] = 0;
else else
{ {
if ( strcmp(symbol,"REGTEST") != 0 ) if ( strcmp(symbol,"ZZZ") != 0 )
printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,SMART_CHAIN_SYMBOL,n,len,&fname[len - n]); printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,SMART_CHAIN_SYMBOL,n,len,&fname[len - n]);
return; return;
} }
@@ -1763,9 +1763,7 @@ void hush_args(char *argv0)
{ {
HUSH_MININGTHREADS = GetArg("-genproclimit",-1); HUSH_MININGTHREADS = GetArg("-genproclimit",-1);
} }
DONATION_PUBKEY = GetArg("-donation", "");
NOTARY_PUBKEY = GetArg("-pubkey", ""); NOTARY_PUBKEY = GetArg("-pubkey", "");
HUSH_DEALERNODE = GetArg("-dealer",0);
HUSH_TESTNODE = GetArg("-testnode",0); HUSH_TESTNODE = GetArg("-testnode",0);
if ( strlen(NOTARY_PUBKEY.c_str()) == 66 ) if ( strlen(NOTARY_PUBKEY.c_str()) == 66 )
@@ -1853,6 +1851,7 @@ void hush_args(char *argv0)
Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0);
ASSETCHAINS_BURN = GetArg("-ac_burn", 0); ASSETCHAINS_BURN = GetArg("-ac_burn", 0);
ASSETCHAINS_CLEARNET = GetArg("-ac_clearnet", 1);
ASSETCHAINS_MINOPRETURNFEE = GetArg("-ac_minopreturnfee", 0); ASSETCHAINS_MINOPRETURNFEE = GetArg("-ac_minopreturnfee", 0);
// -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height....
@@ -2180,7 +2179,7 @@ void hush_args(char *argv0)
} }
} }
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || HUSH_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 || ASSETCHAINS_BURN != 0 || ASSETCHAINS_MINOPRETURNFEE) if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || HUSH_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 || ASSETCHAINS_BURN != 0 || ASSETCHAINS_MINOPRETURNFEE || (ASSETCHAINS_CLEARNET == 0) )
{ {
if(fDebug) if(fDebug)
fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size());
@@ -2350,6 +2349,11 @@ void hush_args(char *argv0)
{ {
extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_MINOPRETURNFEE),(void *)&ASSETCHAINS_MINOPRETURNFEE); extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_MINOPRETURNFEE),(void *)&ASSETCHAINS_MINOPRETURNFEE);
} }
if ( ASSETCHAINS_CLEARNET == 0 )
{
extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_CLEARNET),(void *)&ASSETCHAINS_CLEARNET);
}
} }
addn = GetArg("-seednode",""); addn = GetArg("-seednode","");

View File

@@ -146,7 +146,9 @@ std::atomic<bool> fRequestShutdown(false);
void StartShutdown() void StartShutdown()
{ {
fprintf(stderr,"%s: fRequestShudown=true\n", __FUNCTION__); if(fDebug) {
fprintf(stderr,"%s: fRequestShudown=true\n", __FUNCTION__);
}
fRequestShutdown = true; fRequestShutdown = true;
} }
bool ShutdownRequested() bool ShutdownRequested()
@@ -208,7 +210,9 @@ void Shutdown()
RenameThread(shutoffstr); RenameThread(shutoffstr);
mempool.AddTransactionsUpdated(1); mempool.AddTransactionsUpdated(1);
fprintf(stderr,"%s: stopping HUSH HTTP/REST/RPC\n", __FUNCTION__); if(fDebug) {
fprintf(stderr,"%s: stopping HUSH HTTP/REST/RPC\n", __FUNCTION__);
}
StopHTTPRPC(); StopHTTPRPC();
StopREST(); StopREST();
StopRPC(); StopRPC();
@@ -225,7 +229,9 @@ void Shutdown()
GenerateBitcoins(false, 0); GenerateBitcoins(false, 0);
#endif #endif
#endif #endif
fprintf(stderr,"%s: stopping node\n", __FUNCTION__); if(fDebug) {
fprintf(stderr,"%s: stopping node\n", __FUNCTION__);
}
StopNode(); StopNode();
StopTorControl(); StopTorControl();
UnregisterNodeSignals(GetNodeSignals()); UnregisterNodeSignals(GetNodeSignals());
@@ -606,6 +612,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-ac_burn", _("Allow sending funds to the transparent burn address when -ac_private=1")); strUsage += HelpMessageOpt("-ac_burn", _("Allow sending funds to the transparent burn address when -ac_private=1"));
strUsage += HelpMessageOpt("-ac_minopreturnfee", _("OP_RETURN minimum fee per tx, regardless of tx size, default is 1 coin")); strUsage += HelpMessageOpt("-ac_minopreturnfee", _("OP_RETURN minimum fee per tx, regardless of tx size, default is 1 coin"));
strUsage += HelpMessageOpt("-ac_coda", _("CODA integration")); strUsage += HelpMessageOpt("-ac_coda", _("CODA integration"));
strUsage += HelpMessageOpt("-ac_clearnet", _("Enable or disable clearnet connections for the entire blockchain. Setting to 0 will disable clearnet and use sane defaults for Tor/i2p and require all nodes to do the same") + " " + strprintf(_("(default: %u)"), DEFAULT_CLEARNET));
strUsage += HelpMessageOpt("-ac_decay", _("Percentage of block reward decrease at each halving")); strUsage += HelpMessageOpt("-ac_decay", _("Percentage of block reward decrease at each halving"));
strUsage += HelpMessageOpt("-ac_end", _("Block height at which block rewards will end")); strUsage += HelpMessageOpt("-ac_end", _("Block height at which block rewards will end"));
strUsage += HelpMessageOpt("-ac_eras", _("Block reward eras")); strUsage += HelpMessageOpt("-ac_eras", _("Block reward eras"));
@@ -1647,8 +1654,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
} }
//fprintf(stderr,"%s tik18\n", __FUNCTION__); //fprintf(stderr,"%s tik18\n", __FUNCTION__);
// Disable clearnet peers if -clearnet=0 // Disable clearnet peers if -clearnet=0 for this node or -ac_clearnet=0 for this chain
if (!GetBoolArg("-clearnet", DEFAULT_CLEARNET)) { if (ASSETCHAINS_CLEARNET == 0 || !GetBoolArg("-clearnet", DEFAULT_CLEARNET)) {
#ifdef ENABLE_MINING #ifdef ENABLE_MINING
// mining to the same taddr links different txs together as from the same owner // mining to the same taddr links different txs together as from the same owner
// and if using -clearnet=0 that can be used to link together different .onions // and if using -clearnet=0 that can be used to link together different .onions

View File

@@ -116,7 +116,7 @@ extern char SMART_CHAIN_SYMBOL[HUSH_SMART_CHAIN_MAXLEN];
extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1];
extern uint32_t ASSETCHAINS_MAGIC; extern uint32_t ASSETCHAINS_MAGIC;
extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY;
extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_CLEARNET;
extern int32_t ASSETCHAINS_STAKED; extern int32_t ASSETCHAINS_STAKED;
extern uint64_t ASSETCHAINS_CBOPRET; extern uint64_t ASSETCHAINS_CBOPRET;

View File

@@ -45,6 +45,7 @@
#include <hush/tlsmanager.cpp> #include <hush/tlsmanager.cpp>
using namespace hush; using namespace hush;
extern int32_t HUSH_TESTNODE; extern int32_t HUSH_TESTNODE;
extern uint8_t ASSETCHAINS_CLEARNET;
// Dump addresses to peers.dat every 5 minutes (300s) // Dump addresses to peers.dat every 5 minutes (300s)
// Satoshi originally used 10 seconds(!), did they know something Peter Wuille didn't? // Satoshi originally used 10 seconds(!), did they know something Peter Wuille didn't?
@@ -1653,7 +1654,7 @@ int64_t PoissonNextSend(int64_t now, int average_interval_seconds)
void ASMapHealthCheck() { void ASMapHealthCheck() {
// No health check if clearnet is disabled // No health check if clearnet is disabled
if (!GetBoolArg("-clearnet", DEFAULT_CLEARNET)) { if (ASSETCHAINS_CLEARNET == 0 || !GetBoolArg("-clearnet", DEFAULT_CLEARNET)) {
return; return;
} }

View File

@@ -51,7 +51,9 @@
#undef TFM_TIMING_RESISTANT #undef TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT 420 #define ECC_TIMING_RESISTANT 420
#define TFM_TIMING_RESISTANT 420 #define TFM_TIMING_RESISTANT 420
#define byte unsigned char
#include <wolfssl/ssl.h> #include <wolfssl/ssl.h>
#undef byte
class CAddrMan; class CAddrMan;
class CBlockIndex; class CBlockIndex;

View File

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

View File

@@ -639,12 +639,6 @@ UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk)
return pblockindex->GetBlockHash().GetHex(); return pblockindex->GetBlockHash().GetHex();
} }
UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk)
{
UniValue ret(UniValue::VOBJ);
return ret;
}
UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk)
{ {
if (fHelp || params.size() < 1 || params.size() > 2) if (fHelp || params.size() < 1 || params.size() > 2)
@@ -1061,9 +1055,6 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk)
return ret; return ret;
} }
int32_t hush_pending_withdraws(char *opretstr);
extern char CURRENCIES[][8];
UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk)
{ {
if (fHelp || params.size() < 2 || params.size() > 3) if (fHelp || params.size() < 2 || params.size() > 3)
@@ -1344,6 +1335,12 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my
obj.push_back(Pair("pruneheight", block->GetHeight())); obj.push_back(Pair("pruneheight", block->GetHeight()));
} }
// this helps our tests work correctly
if (Params().NetworkIDString() == "regtest") {
obj.pushKV("fullyNotified", ChainIsFullyNotified());
}
return obj; return obj;
} }

View File

@@ -90,10 +90,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getblock", 1 }, { "getblock", 1 },
{ "getblockheader", 1 }, { "getblockheader", 1 },
{ "getchaintxstats", 0 }, { "getchaintxstats", 0 },
{ "getlastsegidstakes", 0 },
{ "gettransaction", 1 }, { "gettransaction", 1 },
{ "getrawtransaction", 1 }, { "getrawtransaction", 1 },
{ "getlastsegidstakes", 0 },
{ "createrawtransaction", 0 }, { "createrawtransaction", 0 },
{ "createrawtransaction", 1 }, { "createrawtransaction", 1 },
{ "createrawtransaction", 2 }, { "createrawtransaction", 2 },

View File

@@ -320,7 +320,6 @@ static const CRPCCommand vRPCCommands[] =
{ "blockchain", "getblockhashes", &getblockhashes, true }, { "blockchain", "getblockhashes", &getblockhashes, true },
{ "blockchain", "getblockhash", &getblockhash, true }, { "blockchain", "getblockhash", &getblockhash, true },
{ "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getblockheader", &getblockheader, true },
{ "blockchain", "getlastsegidstakes", &getlastsegidstakes, true },
{ "blockchain", "getchaintips", &getchaintips, true }, { "blockchain", "getchaintips", &getchaintips, true },
{ "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getdifficulty", &getdifficulty, true },
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true },
@@ -429,9 +428,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true }, { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true },
{ "wallet", "cleanwallettransactions", &cleanwallettransactions, false }, { "wallet", "cleanwallettransactions", &cleanwallettransactions, false },
{ "wallet", "getbalance", &getbalance, false }, { "wallet", "getbalance", &getbalance, false },
{ "wallet", "getbalance64", &getbalance64, false },
{ "wallet", "getnewaddress", &getnewaddress, true }, { "wallet", "getnewaddress", &getnewaddress, true },
// { "wallet", "getnewaddress64", &getnewaddress64, true },
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, true }, { "wallet", "getrawchangeaddress", &getrawchangeaddress, true },
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false }, { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false }, { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false },
@@ -462,6 +459,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "walletlock", &walletlock, true }, { "wallet", "walletlock", &walletlock, true },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true }, { "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
{ "wallet", "walletpassphrase", &walletpassphrase, true }, { "wallet", "walletpassphrase", &walletpassphrase, true },
{ "wallet", "z_listlockunspent", &z_listlockunspent, false },
{ "wallet", "z_listreceivedbyaddress",&z_listreceivedbyaddress,false }, { "wallet", "z_listreceivedbyaddress",&z_listreceivedbyaddress,false },
{ "wallet", "z_listreceivedaddress", &z_listreceivedaddress, false }, { "wallet", "z_listreceivedaddress", &z_listreceivedaddress, false },
{ "wallet", "z_getbalance", &z_getbalance, false }, { "wallet", "z_getbalance", &z_getbalance, false },

View File

@@ -245,7 +245,6 @@ extern UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& myp
extern UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
//extern UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp
extern UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk);
@@ -259,7 +258,6 @@ extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const C
extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk);
@@ -286,7 +284,6 @@ extern UniValue getdragonjson(const UniValue& params, bool fHelp, const CPubKey&
extern UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue setstakingsplit(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getnetworkinfo(const UniValue& params, bool fHelp, const CPubKey& mypk);
@@ -297,6 +294,7 @@ extern UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPub
extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue z_listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue decodescript(const UniValue& params, bool fHelp, const CPubKey& mypk);
@@ -316,7 +314,6 @@ extern UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey
extern UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getblockdeltas(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk);

View File

@@ -54,6 +54,9 @@ void TransactionBuilder::AddSaplingOutput(
CAmount value, CAmount value,
std::array<unsigned char, HUSH_MEMO_SIZE> memo) std::array<unsigned char, HUSH_MEMO_SIZE> memo)
{ {
if(fZdebug) {
LogPrintf("%s: adding output with value=%ld\n", __func__, value);
}
auto note = libzcash::SaplingNote(to, value); auto note = libzcash::SaplingNote(to, value);
outputs.emplace_back(ovk, note, memo); outputs.emplace_back(ovk, note, memo);
mtx.valueBalance -= value; mtx.valueBalance -= value;
@@ -150,7 +153,7 @@ boost::optional<CTransaction> TransactionBuilder::Build()
change -= tOut.nValue; change -= tOut.nValue;
} }
if (change < 0) { if (change < 0) {
LogPrintf("%s: negative change!\n", __func__); LogPrintf("%s: negative change=%lu mtx.valueBalance=%lu fee=%lu!\n", __func__, change, mtx.valueBalance, fee);
return boost::none; return boost::none;
} }

View File

@@ -271,13 +271,13 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<CBlockIndex*>& blockinfo) { bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<CBlockIndex*>& blockinfo) {
CDBBatch batch(*this); CDBBatch batch(*this);
if (fZdebug) if (fDebug)
fprintf(stderr, "%s: Writing block files\n", __FUNCTION__); fprintf(stderr, "%s: Writing block files\n", __FUNCTION__);
for (const auto& it : fileInfo) { for (const auto& it : fileInfo) {
batch.Write(make_pair(DB_BLOCK_FILES, it.first), *it.second); batch.Write(make_pair(DB_BLOCK_FILES, it.first), *it.second);
} }
batch.Write(DB_LAST_BLOCK, nLastFile); batch.Write(DB_LAST_BLOCK, nLastFile);
if (fZdebug) if (fDebug)
fprintf(stderr, "%s: Writing block index\n", __FUNCTION__); fprintf(stderr, "%s: Writing block index\n", __FUNCTION__);
for (const auto& it : blockinfo) { for (const auto& it : blockinfo) {
std::pair<char, uint256> key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash()); std::pair<char, uint256> key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash());

View File

@@ -53,13 +53,13 @@ using namespace libzcash;
extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk);
AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress( AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
boost::optional<TransactionBuilder> builder, boost::optional<TransactionBuilder> builder,
CMutableTransaction contextualTx, CMutableTransaction contextualTx,
std::vector<MergeToAddressInputUTXO> utxoInputs, std::vector<MergeToAddressInputUTXO> utxoInputs,
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs, std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs,
MergeToAddressRecipient recipient, MergeToAddressRecipient recipient,
CAmount fee, CAmount fee,
UniValue contextInfo) : UniValue contextInfo) :
tx_(contextualTx), utxoInputs_(utxoInputs), saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), contextinfo_(contextInfo) tx_(contextualTx), utxoInputs_(utxoInputs), saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), contextinfo_(contextInfo)
{ {
if (fee < 0 || fee > MAX_MONEY) { if (fee < 0 || fee > MAX_MONEY) {
@@ -182,7 +182,6 @@ void AsyncRPCOperation_mergetoaddress::main()
// Notes: // Notes:
// 1. #1359 Currently there is no limit set on the number of inputs+outputs, so size of tx could be invalid. // 1. #1359 Currently there is no limit set on the number of inputs+outputs, so size of tx could be invalid.
// 2. #1277 Spendable notes are not locked, so an operation running in parallel could also try to use them.
bool AsyncRPCOperation_mergetoaddress::main_impl() bool AsyncRPCOperation_mergetoaddress::main_impl()
{ {
assert(isToTaddr_ != isToZaddr_); assert(isToTaddr_ != isToZaddr_);
@@ -192,22 +191,6 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
size_t numInputs = utxoInputs_.size(); size_t numInputs = utxoInputs_.size();
/*
// Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
{
LOCK(cs_main);
if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
limit = 0;
}
}
if (limit > 0 && numInputs > limit) {
throw JSONRPCError(RPC_WALLET_ERROR,
strprintf("Number of transparent inputs %d is greater than mempooltxinputlimit of %d",
numInputs, limit));
}
*/
CAmount t_inputs_total = 0; CAmount t_inputs_total = 0;
for (MergeToAddressInputUTXO& t : utxoInputs_) { for (MergeToAddressInputUTXO& t : utxoInputs_) {
t_inputs_total += std::get<1>(t); t_inputs_total += std::get<1>(t);

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2017 The Zcash developers // Copyright (c) 2017 The Zcash developers
// 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
@@ -28,12 +27,9 @@
#include "transaction_builder.h" #include "transaction_builder.h"
#include "wallet.h" #include "wallet.h"
#include "zcash/Address.hpp" #include "zcash/Address.hpp"
#include "zcash/JoinSplit.hpp"
#include <array> #include <array>
#include <tuple> #include <tuple>
#include <unordered_map> #include <unordered_map>
#include <univalue.h> #include <univalue.h>
// Default transaction fee if caller does not specify one. // Default transaction fee if caller does not specify one.
@@ -90,9 +86,6 @@ private:
CTxDestination toTaddr_; CTxDestination toTaddr_;
PaymentAddress toPaymentAddress_; PaymentAddress toPaymentAddress_;
uint256 joinSplitPubKey_;
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
std::vector<MergeToAddressInputUTXO> utxoInputs_; std::vector<MergeToAddressInputUTXO> utxoInputs_;
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs_; std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs_;

View File

@@ -74,6 +74,8 @@ void AsyncRPCOperation_saplingconsolidation::main() {
} }
LogPrintf("%s", s); LogPrintf("%s", s);
unlock_notes(); // clean up
LogPrint("zrpc", "%s: consolidation input notes unlocked\n", getId());
} }
bool AsyncRPCOperation_saplingconsolidation::main_impl() { bool AsyncRPCOperation_saplingconsolidation::main_impl() {
@@ -102,6 +104,11 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
return true; return true;
} }
// store sapling inputs so we can correctly lock and unlock them
for (auto entry : saplingEntries) {
z_sapling_inputs_.push_back(entry);
}
if (fConsolidationMapUsed) { if (fConsolidationMapUsed) {
const vector<string>& v = mapMultiArgs["-consolidatesaplingaddress"]; const vector<string>& v = mapMultiArgs["-consolidatesaplingaddress"];
for(int i = 0; i < v.size(); i++) { for(int i = 0; i < v.size(); i++) {
@@ -233,6 +240,10 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
break; break;
} }
// Lock shielded input notes
lock_notes();
LogPrint("zrpc", "%s: consolidation input notes locked\n", getId());
if(pwalletMain->CommitAutomatedTx(tx)) { if(pwalletMain->CommitAutomatedTx(tx)) {
LogPrintf("%s: Committed consolidation transaction with txid=%s\n",opid, tx.GetHash().ToString()); LogPrintf("%s: Committed consolidation transaction with txid=%s\n",opid, tx.GetHash().ToString());
amountConsolidated += actualAmountToSend; amountConsolidated += actualAmountToSend;
@@ -240,10 +251,15 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
numTxCreated++; numTxCreated++;
} else { } else {
LogPrintf("%s: Consolidation transaction FAILED in CommitTransaction, txid=%s\n",opid , tx.GetHash().ToString()); LogPrintf("%s: Consolidation transaction FAILED in CommitTransaction, txid=%s\n",opid , tx.GetHash().ToString());
unlock_notes();
LogPrint("zrpc", "%s: consolidatoin input notes unlocked\n", getId());
setConsolidationResult(numTxCreated, amountConsolidated, consolidationTxIds); setConsolidationResult(numTxCreated, amountConsolidated, consolidationTxIds);
status = false; status = false;
break; break;
} }
} }
} }
@@ -275,3 +291,19 @@ UniValue AsyncRPCOperation_saplingconsolidation::getStatus() const {
obj.push_back(Pair("target_height", targetHeight_)); obj.push_back(Pair("target_height", targetHeight_));
return obj; return obj;
} }
// Lock input notes
void AsyncRPCOperation_saplingconsolidation::lock_notes() {
LOCK2(cs_main, pwalletMain->cs_wallet);
for (auto note : z_sapling_inputs_) {
pwalletMain->LockNote(note.op);
}
}
// Unlock input notes
void AsyncRPCOperation_saplingconsolidation::unlock_notes() {
LOCK2(cs_main, pwalletMain->cs_wallet);
for (auto note : z_sapling_inputs_) {
pwalletMain->UnlockNote(note.op);
}
}

View File

@@ -8,6 +8,7 @@
#include "univalue.h" #include "univalue.h"
#include "zcash/Address.hpp" #include "zcash/Address.hpp"
#include "zcash/zip32.h" #include "zcash/zip32.h"
#include "wallet.h" // for SaplingNoteEntry
//Default fee used for consolidation transactions, in puposhis //Default fee used for consolidation transactions, in puposhis
static const CAmount DEFAULT_CONSOLIDATION_FEE = 10000; static const CAmount DEFAULT_CONSOLIDATION_FEE = 10000;
@@ -32,10 +33,14 @@ public:
virtual UniValue getStatus() const; virtual UniValue getStatus() const;
void lock_notes();
void unlock_notes();
private: private:
int targetHeight_; int targetHeight_;
bool main_impl(); bool main_impl();
std::vector<SaplingNoteEntry> z_sapling_inputs_;
void setConsolidationResult(int numTxCreated, const CAmount& amountConsolidated, const std::vector<std::string>& consolidationTxIds); void setConsolidationResult(int numTxCreated, const CAmount& amountConsolidated, const std::vector<std::string>& consolidationTxIds);

View File

@@ -63,11 +63,12 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
std::string fromAddress, std::string fromAddress,
std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> tOutputs,
std::vector<SendManyRecipient> zOutputs, std::vector<SendManyRecipient> zOutputs,
std::vector<SendManyInputSaplingNote> saplingNoteInputs,
int minDepth, int minDepth,
CAmount fee, CAmount fee,
UniValue contextInfo, UniValue contextInfo,
CScript opret) : CScript opret) :
tx_(contextualTx), fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo), opret_(opret) tx_(contextualTx), fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), saplingNoteInputs_(saplingNoteInputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo), opret_(opret)
{ {
assert(fee_ >= 0); assert(fee_ >= 0);
@@ -119,14 +120,25 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
} else { } else {
LogPrint("zrpc", "%s: z_sendmany initialized\n", getId()); LogPrint("zrpc", "%s: z_sendmany initialized\n", getId());
} }
//TODO: lock_utxos() ?
// Lock shielded input notes (zins) stored in saplingNoteInputs
lock_notes();
LogPrintf("%s: %s z_sendmany input notes locked\n", __func__, getId());
} }
AsyncRPCOperation_sendmany::~AsyncRPCOperation_sendmany() { AsyncRPCOperation_sendmany::~AsyncRPCOperation_sendmany() {
} }
void AsyncRPCOperation_sendmany::main() { void AsyncRPCOperation_sendmany::main() {
if (isCancelled())
// clean up locks if we are cancelled
if (isCancelled()) {
// We are more likely to be spending notes, so unlock them first
unlock_notes();
unlock_utxos();
return; return;
}
set_state(OperationStatus::EXECUTING); set_state(OperationStatus::EXECUTING);
start_execution_clock(); start_execution_clock();
@@ -162,6 +174,10 @@ void AsyncRPCOperation_sendmany::main() {
set_error_message("unknown error"); set_error_message("unknown error");
} }
unlock_notes();
unlock_utxos();
LogPrintf("%s: %s z_sendmany input notes+utxos unlocked\n", __func__, getId());
#ifdef ENABLE_MINING #ifdef ENABLE_MINING
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 1)); GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 1));
@@ -172,6 +188,7 @@ void AsyncRPCOperation_sendmany::main() {
stop_execution_clock(); stop_execution_clock();
if (success) { if (success) {
set_state(OperationStatus::SUCCESS); set_state(OperationStatus::SUCCESS);
} else { } else {
@@ -185,22 +202,14 @@ void AsyncRPCOperation_sendmany::main() {
s += strprintf(", error=%s)\n", getErrorMessage()); s += strprintf(", error=%s)\n", getErrorMessage());
} }
LogPrintf("%s",s); LogPrintf("%s",s);
} }
// Notes: // Notes:
// 1. #1159 Currently there is no limit set on the number of shielded spends, so size of tx could be invalid. // 1. Currently there is no limit set on the number of shielded spends, so size of tx could be invalid.
// 2. #1360 Note selection is not optimal
// 3. #1277 Spendable notes are not locked, so an operation running in parallel could also try to use them
bool AsyncRPCOperation_sendmany::main_impl() { bool AsyncRPCOperation_sendmany::main_impl() {
assert(isfromtaddr_ != isfromzaddr_); assert(isfromtaddr_ != isfromzaddr_);
/* TODO: this needs to allow DPoW addresses. Consensus-time checks do it correctly.
if(t_outputs_.size() > 0) {
throw JSONRPCError(RPC_WALLET_ERROR, "Extreme Privacy! You cannot send to a transparent address.");
}
*/
bool isSingleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()==1); bool isSingleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()==1);
bool isMultipleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()>=1); bool isMultipleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()>=1);
bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0); bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0);
@@ -227,9 +236,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
} }
} }
if (isfromzaddr_ && !find_unspent_notes()) { // Lock UTXOs
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds, no unspent notes found for zaddr from address."); lock_utxos();
}
CAmount t_inputs_total = 0; CAmount t_inputs_total = 0;
for (SendManyInputUTXO & t : t_inputs_) { for (SendManyInputUTXO & t : t_inputs_) {
@@ -237,8 +245,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
} }
CAmount z_inputs_total = 0; CAmount z_inputs_total = 0;
for (auto t : z_sapling_inputs_) { for (auto t : saplingNoteInputs_) {
z_inputs_total += t.note.value(); z_inputs_total += std::get<1>(t).value();
} }
CAmount t_outputs_total = 0; CAmount t_outputs_total = 0;
@@ -252,8 +260,11 @@ bool AsyncRPCOperation_sendmany::main_impl() {
z_outputs_total += std::get<1>(t); z_outputs_total += std::get<1>(t);
} }
LogPrintf("%s: z_inputs_total=%s z_outputs_total=%s\n", __func__, FormatMoney(z_inputs_total), FormatMoney(z_outputs_total) );
CAmount sendAmount = z_outputs_total + t_outputs_total; CAmount sendAmount = z_outputs_total + t_outputs_total;
CAmount targetAmount = sendAmount + minersFee; CAmount targetAmount = sendAmount + minersFee;
LogPrintf("%s: targetAmount=%s sendAmount=%s minersFee=%s\n", __func__, FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee) );
assert(!isfromtaddr_ || z_inputs_total == 0); assert(!isfromtaddr_ || z_inputs_total == 0);
assert(!isfromzaddr_ || t_inputs_total == 0); assert(!isfromzaddr_ || t_inputs_total == 0);
@@ -309,23 +320,6 @@ bool AsyncRPCOperation_sendmany::main_impl() {
t_inputs_ = selectedTInputs; t_inputs_ = selectedTInputs;
t_inputs_total = selectedUTXOAmount; t_inputs_total = selectedUTXOAmount;
/*
// Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
const size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
{
LOCK(cs_main);
if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
limit = 0;
}
}
if (limit > 0) {
size_t n = t_inputs_.size();
if (n > limit) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Too many transparent inputs %zu > limit %zu", n, limit));
}
}
*/
// update the transaction with these inputs // update the transaction with these inputs
if (isUsingBuilder_) { if (isUsingBuilder_) {
CScript scriptPubKey; CScript scriptPubKey;
@@ -415,15 +409,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
if(fZdebug) if(fZdebug)
LogPrintf("%s: Selecting Sapling notes\n", __FUNCTION__); LogPrintf("%s: Selecting Sapling notes\n", __FUNCTION__);
std::vector<SaplingOutPoint> ops; std::vector<SaplingOutPoint> ops;
std::vector<SaplingNote> notes;
CAmount sum = 0; CAmount sum = 0;
for (auto t : z_sapling_inputs_) {
ops.push_back(t.op); for(const auto t : saplingNoteInputs_) {
notes.push_back(t.note); ops.push_back(std::get<0>(t));
sum += t.note.value();
if (sum >= targetAmount) {
break;
}
} }
// Fetch Sapling anchor and witnesses // Fetch Sapling anchor and witnesses
@@ -435,14 +424,19 @@ bool AsyncRPCOperation_sendmany::main_impl() {
pwalletMain->GetSaplingNoteWitnesses(ops, witnesses, anchor); pwalletMain->GetSaplingNoteWitnesses(ops, witnesses, anchor);
} }
LogPrintf("%s: ops.size=%d witnesses.size=%d\n", __func__, ops.size(), witnesses.size() );
// Add Sapling spends // Add Sapling spends
for (size_t i = 0; i < notes.size(); i++) { for (size_t i = 0; i < saplingNoteInputs_.size(); i++) {
if (!witnesses[i]) { if (!witnesses.at(i)) {
throw JSONRPCError(RPC_WALLET_ERROR, throw JSONRPCError(RPC_WALLET_ERROR,
strprintf( "Missing witness for Sapling note at outpoint %s", z_sapling_inputs_[i].op.ToString()) strprintf( "Missing witness for Sapling note at outpoint %s", std::get<0>(saplingNoteInputs_[i]).ToString())
); );
} }
assert(builder_.AddSaplingSpend(expsk, notes[i], anchor, witnesses[i].get())); if(fZdebug)
LogPrintf("%s: Adding Sapling spend\n", __func__);
assert(builder_.AddSaplingSpend(expsk, std::get<1>(saplingNoteInputs_[i]), anchor, witnesses[i].get()));
} }
// Add Sapling outputs // Add Sapling outputs
@@ -454,7 +448,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
assert(boost::get<libzcash::SaplingPaymentAddress>(&addr) != nullptr); assert(boost::get<libzcash::SaplingPaymentAddress>(&addr) != nullptr);
auto to = boost::get<libzcash::SaplingPaymentAddress>(addr); auto to = boost::get<libzcash::SaplingPaymentAddress>(addr);
if(fZdebug) if(fZdebug)
LogPrintf("%s: Adding Sapling output to address %s\n", __FUNCTION__, address.c_str()); LogPrintf("%s: Adding Sapling output with value=%s to address %s\n", __func__, FormatMoney(value), address.c_str());
auto memo = get_memo_from_hex_string(hexMemo); auto memo = get_memo_from_hex_string(hexMemo);
@@ -488,6 +482,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
// Send the transaction // Send the transaction
// TODO: Use CWallet::CommitTransaction instead of sendrawtransaction // TODO: Use CWallet::CommitTransaction instead of sendrawtransaction
auto signedtxn = EncodeHexTx(tx_); auto signedtxn = EncodeHexTx(tx_);
if (!testmode) { if (!testmode) {
UniValue params = UniValue(UniValue::VARR); UniValue params = UniValue(UniValue::VARR);
params.push_back(signedtxn); params.push_back(signedtxn);
@@ -659,37 +654,6 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
return t_inputs_.size() > 0; return t_inputs_.size() > 0;
} }
bool AsyncRPCOperation_sendmany::find_unspent_notes() {
if(fZdebug)
LogPrintf("%s: For address %s depth=%d\n", __FUNCTION__, fromaddress_.c_str(), mindepth_);
std::vector<SaplingNoteEntry> saplingEntries;
{
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->GetFilteredNotes(saplingEntries, fromaddress_, mindepth_);
}
for (auto entry : saplingEntries) {
z_sapling_inputs_.push_back(entry);
std::string data(entry.memo.begin(), entry.memo.end());
LogPrint("zrpcunsafe", "%s: found unspent Sapling note (txid=%s, vShieldedSpend=%d, amount=%s, memo=%s)\n",
getId(),
entry.op.hash.ToString().substr(0, 10),
entry.op.n,
FormatMoney(entry.note.value()),
HexStr(data).substr(0, 10));
}
// sort in descending order, so big notes appear first
std::sort(z_sapling_inputs_.begin(), z_sapling_inputs_.end(),
[](SaplingNoteEntry i, SaplingNoteEntry j) -> bool {
return i.note.value() > j.note.value();
});
return true;
}
void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() { void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() {
CMutableTransaction rawTx(tx_); CMutableTransaction rawTx(tx_);
@@ -781,3 +745,53 @@ UniValue AsyncRPCOperation_sendmany::getStatus() const {
obj.push_back(Pair("params", contextinfo_ )); obj.push_back(Pair("params", contextinfo_ ));
return obj; return obj;
} }
// Lock input utxos
void AsyncRPCOperation_sendmany::lock_utxos() {
LOCK2(cs_main, pwalletMain->cs_wallet);
for (auto utxo : t_inputs_) {
uint256 txid = std::get<0>(utxo);
int vout = std::get<1>(utxo);
COutPoint outpt(txid, vout);
pwalletMain->LockCoin(outpt);
}
}
// Unlock input utxos
void AsyncRPCOperation_sendmany::unlock_utxos() {
LOCK2(cs_main, pwalletMain->cs_wallet);
for (auto utxo : t_inputs_) {
uint256 txid = std::get<0>(utxo);
int vout = std::get<1>(utxo);
COutPoint outpt(txid, vout);
pwalletMain->UnlockCoin(outpt);
}
}
// Lock input notes
void AsyncRPCOperation_sendmany::lock_notes() {
LOCK2(cs_main, pwalletMain->cs_wallet);
LogPrintf("%s: found %lu notes to lock\n", __func__, saplingNoteInputs_.size() );
for (auto note : saplingNoteInputs_) {
if(pwalletMain->IsLockedNote(std::get<0>(note))) {
LogPrintf("%s: note already locked!\n", __func__);
} else {
pwalletMain->LockNote(std::get<0>(note));
}
}
}
// Unlock input notes
void AsyncRPCOperation_sendmany::unlock_notes() {
LOCK2(cs_main, pwalletMain->cs_wallet);
LogPrintf("%s: found %lu notes to unlock\n", __func__, saplingNoteInputs_.size() );
for (auto note : saplingNoteInputs_) {
if(pwalletMain->IsLockedNote(std::get<0>(note))) {
pwalletMain->UnlockNote(std::get<0>(note));
} else {
LogPrintf("%s: note already unlocked!\n", __func__);
}
}
}

View File

@@ -25,14 +25,11 @@
#include "amount.h" #include "amount.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "transaction_builder.h" #include "transaction_builder.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Address.hpp" #include "zcash/Address.hpp"
#include "wallet.h" #include "wallet.h"
#include <array> #include <array>
#include <unordered_map> #include <unordered_map>
#include <tuple> #include <tuple>
#include <univalue.h> #include <univalue.h>
// Default transaction fee if caller does not specify one. // Default transaction fee if caller does not specify one.
@@ -46,11 +43,8 @@ typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
// Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase) // Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase)
typedef std::tuple<uint256, int, CAmount, bool, CTxDestination> SendManyInputUTXO; typedef std::tuple<uint256, int, CAmount, bool, CTxDestination> SendManyInputUTXO;
// A struct to help us track the witness and anchor for a given JSOutPoint // Input note is a tuple of output, note, amount, spending key
struct WitnessAnchorData { typedef std::tuple<SaplingOutPoint, SaplingNote, CAmount, SaplingExpandedSpendingKey> SendManyInputSaplingNote;
boost::optional<SproutWitness> witness;
uint256 anchor;
};
class AsyncRPCOperation_sendmany : public AsyncRPCOperation { class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
public: public:
@@ -60,6 +54,7 @@ public:
std::string fromAddress, std::string fromAddress,
std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> tOutputs,
std::vector<SendManyRecipient> zOutputs, std::vector<SendManyRecipient> zOutputs,
std::vector<SendManyInputSaplingNote> saplingNoteInputs,
int minDepth, int minDepth,
CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE,
UniValue contextInfo = NullUniValue, UniValue contextInfo = NullUniValue,
@@ -96,17 +91,11 @@ private:
SpendingKey spendingkey_; SpendingKey spendingkey_;
CScript opret_ = CScript(); CScript opret_ = CScript();
uint256 joinSplitPubKey_;
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
// The key is the result string from calling JSOutPoint::ToString()
std::unordered_map<std::string, WitnessAnchorData> jsopWitnessAnchorMap;
std::vector<SendManyRecipient> t_outputs_; std::vector<SendManyRecipient> t_outputs_;
std::vector<SendManyRecipient> z_outputs_; std::vector<SendManyRecipient> z_outputs_;
std::vector<SendManyInputUTXO> t_inputs_; std::vector<SendManyInputUTXO> t_inputs_;
//std::vector<SendManyInputJSOP> z_sprout_inputs_; //std::vector<SaplingNoteEntry> z_sapling_inputs_;
std::vector<SaplingNoteEntry> z_sapling_inputs_; std::vector<SendManyInputSaplingNote> saplingNoteInputs_;
TransactionBuilder builder_; TransactionBuilder builder_;
CTransaction tx_; CTransaction tx_;
@@ -119,6 +108,11 @@ private:
bool main_impl(); bool main_impl();
void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error
void lock_utxos();
void unlock_utxos();
void lock_notes();
void unlock_notes();
}; };
@@ -172,6 +166,4 @@ public:
} }
}; };
#endif /* ASYNCRPCOPERATION_SENDMANY_H */ #endif /* ASYNCRPCOPERATION_SENDMANY_H */

View File

@@ -54,8 +54,9 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
std::vector<ShieldCoinbaseUTXO> inputs, std::vector<ShieldCoinbaseUTXO> inputs,
std::string toAddress, std::string toAddress,
CAmount fee, CAmount fee,
uint8_t donation,
UniValue contextInfo) : UniValue contextInfo) :
builder_(builder), tx_(contextualTx), inputs_(inputs), fee_(fee), contextinfo_(contextInfo) builder_(builder), tx_(contextualTx), inputs_(inputs), fee_(fee), donation_(donation), contextinfo_(contextInfo)
{ {
assert(contextualTx.nVersion >= 2); // transaction format version must support vjoinsplit assert(contextualTx.nVersion >= 2); // transaction format version must support vjoinsplit
@@ -67,6 +68,10 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Empty inputs"); throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Empty inputs");
} }
if (donation < 0 || donation > 10 ) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid donation percentage, must be an integer between 0 and 10 inclusive");
}
// Check the destination address is valid for this network i.e. not testnet being used on mainnet // Check the destination address is valid for this network i.e. not testnet being used on mainnet
auto address = DecodePaymentAddress(toAddress); auto address = DecodePaymentAddress(toAddress);
if (IsValidPaymentAddress(address)) { if (IsValidPaymentAddress(address)) {
@@ -161,24 +166,7 @@ void AsyncRPCOperation_shieldcoinbase::main() {
bool AsyncRPCOperation_shieldcoinbase::main_impl() { bool AsyncRPCOperation_shieldcoinbase::main_impl() {
CAmount minersFee = fee_; CAmount minersFee = fee_;
size_t numInputs = inputs_.size();
size_t numInputs = inputs_.size();
/*
// Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
{
LOCK(cs_main);
if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
limit = 0;
}
}
if (limit>0 && numInputs > limit) {
throw JSONRPCError(RPC_WALLET_ERROR,
strprintf("Number of inputs %d is greater than mempooltxinputlimit of %d",
numInputs, limit));
}
*/
CAmount targetAmount = 0; CAmount targetAmount = 0;
for (ShieldCoinbaseUTXO & utxo : inputs_) { for (ShieldCoinbaseUTXO & utxo : inputs_) {
@@ -192,10 +180,10 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() {
} }
CAmount sendAmount = targetAmount - minersFee; CAmount sendAmount = targetAmount - minersFee;
LogPrint("zrpc", "%s: spending %s to shield %s with fee %s\n", LogPrint("zrpc", "%s: spending %s to shield %s with fee %s, donation=%d\n",
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee)); getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee), donation_);
return boost::apply_visitor(ShieldToAddress(this, sendAmount), tozaddr_); return boost::apply_visitor(ShieldToAddress(this, sendAmount, donation_), tozaddr_);
} }
extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk);
@@ -228,20 +216,55 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c
m_op->builder_.AddTransparentInput(COutPoint(t.txid, t.vout), t.scriptPubKey, t.amount); m_op->builder_.AddTransparentInput(COutPoint(t.txid, t.vout), t.scriptPubKey, t.amount);
} }
} }
if(donation) {
//if donation>0, send X% of value to zaddr and Y% of of value to donatezaddr where X+Y=100%
// Send all value to the target z-addr //TODO: TESTING zaddr only, only use on regtest
m_op->builder_.SendChangeTo(zaddr, ovk); //TODO: randomly select from a set
auto dzaddr = "zregtestsapling1y30nwg0clsu6gcyrnvht8hdyfk3vwtszlh6kc4z5hv9hmpxzg2g0nx7c60xeecggm9x9gma96t4";
auto donationZaddr = DecodePaymentAddress(dzaddr);
if (!IsValidPaymentAddress(donationZaddr)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid donation zaddr, Unknown address format: ") + dzaddr);
}
// calculate donation as a double then convert to CAmount
double amount = (static_cast<double>(donation)/100)*static_cast<double>(sendAmount);
CAmount donationAmount = static_cast<CAmount>(amount);
// add original recipient as first output, with sendAmount less the donation
CAmount newAmount = sendAmount - donationAmount;
m_op->builder_.AddSaplingOutput(ovk, zaddr, newAmount);
auto donationZout = boost::get<libzcash::SaplingPaymentAddress>(donationZaddr);
m_op->builder_.AddSaplingOutput(ovk, donationZout, donationAmount);
if(fZdebug) {
LogPrintf("%s: donation=%ld, sendAmount=%ld, newAmount=%ld, donationAmount=%ld, newAmount+donationAmount=%ld fee=%ld\n", __func__,
donation, sendAmount, newAmount, donationAmount, newAmount+donationAmount, m_op->fee_);
}
// zdust as third output, so donation txs are indistinguishable from
// non-donation z_shieldcoinbase txs
auto zdust1 = DecodePaymentAddress(randomSietchZaddr());
auto sietchZout1 = boost::get<libzcash::SaplingPaymentAddress>(zdust1);
m_op->builder_.AddSaplingOutput(ovk, sietchZout1, 0);
} else {
// Send all value to the target z-addr
m_op->builder_.SendChangeTo(zaddr, ovk);
// Sietchified Shielding of Coinbase Funds
// Add Sietch zouts so it's unclear which zout contains value :)
// This reduces metadata leakage of coinbase t=>z tx's
CAmount amount = 0;
auto zdust1 = DecodePaymentAddress(randomSietchZaddr());
auto zdust2 = DecodePaymentAddress(randomSietchZaddr());
auto sietchZout1 = boost::get<libzcash::SaplingPaymentAddress>(zdust1);
auto sietchZout2 = boost::get<libzcash::SaplingPaymentAddress>(zdust2);
m_op->builder_.AddSaplingOutput(ovk, sietchZout1, amount);
m_op->builder_.AddSaplingOutput(ovk, sietchZout2, amount);
}
// Sietchified Shielding of Coinbase Funds
// Add Sietch zouts so it's unclear which zout contains value :)
// This reduces metadata leakage of coinbase t=>z tx's
CAmount amount = 0;
auto zdust1 = DecodePaymentAddress(randomSietchZaddr());
auto zdust2 = DecodePaymentAddress(randomSietchZaddr());
auto sietchZout1 = boost::get<libzcash::SaplingPaymentAddress>(zdust1);
auto sietchZout2 = boost::get<libzcash::SaplingPaymentAddress>(zdust2);
m_op->builder_.AddSaplingOutput(ovk, sietchZout1, amount);
m_op->builder_.AddSaplingOutput(ovk, sietchZout2, amount);
// Build the transaction // Build the transaction
auto maybe_tx = m_op->builder_.Build(); auto maybe_tx = m_op->builder_.Build();

View File

@@ -49,6 +49,7 @@ public:
std::vector<ShieldCoinbaseUTXO> inputs, std::vector<ShieldCoinbaseUTXO> inputs,
std::string toAddress, std::string toAddress,
CAmount fee = SHIELD_COINBASE_DEFAULT_MINERS_FEE, CAmount fee = SHIELD_COINBASE_DEFAULT_MINERS_FEE,
uint8_t donation = 0,
UniValue contextInfo = NullUniValue); UniValue contextInfo = NullUniValue);
virtual ~AsyncRPCOperation_shieldcoinbase(); virtual ~AsyncRPCOperation_shieldcoinbase();
@@ -63,7 +64,6 @@ public:
virtual UniValue getStatus() const; virtual UniValue getStatus() const;
bool testmode = false; // Set to true to disable sending txs and generating proofs bool testmode = false; // Set to true to disable sending txs and generating proofs
bool cheatSpend = false; // set when this is shielding a cheating coinbase
private: private:
friend class ShieldToAddress; friend class ShieldToAddress;
@@ -74,11 +74,11 @@ private:
CAmount fee_; CAmount fee_;
PaymentAddress tozaddr_; PaymentAddress tozaddr_;
uint256 joinSplitPubKey_;
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
std::vector<ShieldCoinbaseUTXO> inputs_; std::vector<ShieldCoinbaseUTXO> inputs_;
// this is a donation % between 0 and 10, not a CAmount
uint8_t donation_;
TransactionBuilder builder_; TransactionBuilder builder_;
CTransaction tx_; CTransaction tx_;
@@ -87,7 +87,6 @@ private:
void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error
void lock_utxos(); void lock_utxos();
void unlock_utxos(); void unlock_utxos();
}; };
@@ -96,15 +95,15 @@ class ShieldToAddress : public boost::static_visitor<bool>
private: private:
AsyncRPCOperation_shieldcoinbase *m_op; AsyncRPCOperation_shieldcoinbase *m_op;
CAmount sendAmount; CAmount sendAmount;
uint8_t donation = 0;
public: public:
ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount) : ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount, uint8_t donation) :
m_op(op), sendAmount(sendAmount) {} m_op(op), sendAmount(sendAmount), donation(donation) {}
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
bool operator()(const libzcash::InvalidEncoding& no) const; bool operator()(const libzcash::InvalidEncoding& no) const;
}; };
// To test private methods, a friend class can act as a proxy // To test private methods, a friend class can act as a proxy
class TEST_FRIEND_AsyncRPCOperation_shieldcoinbase { class TEST_FRIEND_AsyncRPCOperation_shieldcoinbase {
public: public:
@@ -135,6 +134,4 @@ public:
} }
}; };
#endif /* ASYNCRPCOPERATION_SHIELDCOINBASE_H */ #endif /* ASYNCRPCOPERATION_SHIELDCOINBASE_H */

View File

@@ -704,7 +704,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
throw JSONRPCError(RPC_INTERNAL_ERROR, e.what()); throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
} }
if (exportdir.empty()) { if (exportdir.empty()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot export wallet until the hushd -exportdir option has been set"); throw JSONRPCError(RPC_WALLET_ERROR, "Cannot export wallet until the -exportdir option has been set");
} }
std::string unclean = params[0].get_str(); std::string unclean = params[0].get_str();
std::string clean = SanitizeFilename(unclean); std::string clean = SanitizeFilename(unclean);

View File

@@ -82,9 +82,7 @@ char *uint256_str(char *dest,uint256 txid);
// Private method: // Private method:
UniValue z_getoperationstatus_IMPL(const UniValue&, bool); UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
#define PLAN_NAME_MAX 8 #define THROW_IF_SYNCING(INSYNC) if (Params().NetworkIDString() != "regtest" && 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())); }
#define VALID_PLAN_NAME(x) (strlen(x) <= PLAN_NAME_MAX)
#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())); }
int tx_height( const uint256 &hash ); int tx_height( const uint256 &hash );
@@ -1343,19 +1341,19 @@ UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk)
"\nSend 0.01 " + strprintf("%s",hush_chainname()) + " from the default account to the address, must have at least 1 confirmation\n" "\nSend 0.01 " + strprintf("%s",hush_chainname()) + " from the default account to the address, must have at least 1 confirmation\n"
+ HelpExampleCli("sendfrom", "\"\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01") + + HelpExampleCli("sendfrom", "\"\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01") +
"\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n" "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
+ HelpExampleCli("sendfrom", "\"tabby\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01 6 \"donation\" \"seans outpost\"") + + HelpExampleCli("sendfrom", "\"tabby\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01 6 \"donation\" \"Hush Puppy Freedom Fund\"") +
"\nAs a json rpc call\n" "\nAs a json rpc call\n"
+ HelpExampleRpc("sendfrom", "\"tabby\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.01, 6, \"donation\", \"seans outpost\"") + HelpExampleRpc("sendfrom", "\"tabby\", \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", 0.01, 6, \"donation\", \"Hush Puppy Freedom Fund\"")
); );
if ( ASSETCHAINS_PRIVATE != 0 ) if ( ASSETCHAINS_PRIVATE != 0 )
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "cant use transparent addresses in private chain"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use transparent addresses in private chain");
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
std::string strAccount = AccountFromValue(params[0]); std::string strAccount = AccountFromValue(params[0]);
CTxDestination dest = DecodeDestination(params[1].get_str()); CTxDestination dest = DecodeDestination(params[1].get_str());
if (!IsValidDestination(dest)) { if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address!"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address!");
} }
CAmount nAmount = AmountFromValue(params[2]); CAmount nAmount = AmountFromValue(params[2]);
if (nAmount <= 0) if (nAmount <= 0)
@@ -2647,6 +2645,49 @@ UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
return true; return true;
} }
UniValue z_listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (fHelp || params.size() > 0)
throw runtime_error(
"z_listlockunspent\n"
"\nReturns list of temporarily locked shielded outputs which are currently unspendable. They are locked\n"
"\nbecause they are currently in the process of being spent by an operation such as z_sendmany/z_mergetoaddress/etc.\n"
"\nIf that operation succeeds, they will become spent. If it fails they will be unlocked and become\n"
"\nspendable again.\n"
"\nResult:\n"
"[\n"
" {\n"
" \"txid\" : \"transactionid\", (string) The transaction id locked\n"
" \"outindex\" : n (integer) The shielded output index\n"
" }\n"
" ,...\n"
"]\n"
"\nExamples:\n"
"\nList the locked Sapling notes\n"
+ HelpExampleCli("z_listlockunspent", "") +
"\nAs a json rpc call\n"
+ HelpExampleRpc("z_listlockunspent", "")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
vector<SaplingOutPoint> ops = pwalletMain->ListLockedSaplingNotes();
UniValue ret(UniValue::VARR);
BOOST_FOREACH(SaplingOutPoint &op, ops) {
UniValue o(UniValue::VOBJ);
o.push_back(Pair("txid", op.hash.GetHex()));
o.push_back(Pair("outindex", (int) op.n));
ret.push_back(o);
}
return ret;
}
UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue listlockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
{ {
if (!EnsureWalletIsAvailable(fHelp)) if (!EnsureWalletIsAvailable(fHelp))
@@ -4083,7 +4124,6 @@ UniValue z_getbalances(const UniValue& params, bool fHelp, const CPubKey& mypk)
return results; return results;
} }
UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
{ {
if (!EnsureWalletIsAvailable(fHelp)) if (!EnsureWalletIsAvailable(fHelp))
@@ -4113,6 +4153,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
" \"outindex\" (sapling) : n (numeric) the output index\n" " \"outindex\" (sapling) : n (numeric) the output index\n"
" \"confirmations\" : n (numeric) the number of confirmations\n" " \"confirmations\" : n (numeric) the number of confirmations\n"
" \"spendable\" : true|false (boolean) true if note can be spent by wallet, false if note has zero confirmations, false if address is watchonly\n" " \"spendable\" : true|false (boolean) true if note can be spent by wallet, false if note has zero confirmations, false if address is watchonly\n"
" \"locked\" : true|false (boolean) true if note is part of an in-process async operation to spend it, such as z_mergetoaddress/z_sendmany/etc\n"
" \"address\" : \"address\", (string) the shielded address\n" " \"address\" : \"address\", (string) the shielded address\n"
" \"amount\": xxxxx, (numeric) the amount of value in the note\n" " \"amount\": xxxxx, (numeric) the amount of value in the note\n"
" \"memo\": xxxxx, (string) hexademical string representation of memo field\n" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
@@ -4218,8 +4259,12 @@ UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
libzcash::SaplingFullViewingKey fvk; libzcash::SaplingFullViewingKey fvk;
pwalletMain->GetSaplingIncomingViewingKey(boost::get<libzcash::SaplingPaymentAddress>(entry.address), ivk); pwalletMain->GetSaplingIncomingViewingKey(boost::get<libzcash::SaplingPaymentAddress>(entry.address), ivk);
pwalletMain->GetSaplingFullViewingKey(ivk, fvk); pwalletMain->GetSaplingFullViewingKey(ivk, fvk);
bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKey(fvk); const bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKey(fvk);
obj.push_back(Pair("spendable", hasSaplingSpendingKey)); obj.push_back(Pair("spendable", hasSaplingSpendingKey));
const bool isLocked = pwalletMain->IsLockedNote(entry.op);
obj.push_back(Pair("locked", isLocked));
obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); // note.value() is equivalent to plaintext.value() obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); // note.value() is equivalent to plaintext.value()
obj.push_back(Pair("memo", HexStr(entry.memo))); obj.push_back(Pair("memo", HexStr(entry.memo)));
@@ -4783,7 +4828,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my
UniValue entry(UniValue::VOBJ); UniValue entry(UniValue::VOBJ);
if (!pwalletMain->mapWallet.count(hash)) if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet Hush transaction id!"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id!");
const CWalletTx& wtx = pwalletMain->mapWallet[hash]; const CWalletTx& wtx = pwalletMain->mapWallet[hash];
entry.push_back(Pair("txid", hash.GetHex())); entry.push_back(Pair("txid", hash.GetHex()));
@@ -5126,7 +5171,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
fprintf(stderr,"%s: Selecting one of %lu potential source zaddrs\n", __func__, nPotentials); fprintf(stderr,"%s: Selecting one of %lu potential source zaddrs\n", __func__, nPotentials);
fromaddress = vPotentialAddresses[ GetRandInt(nPotentials) ]; fromaddress = vPotentialAddresses[ GetRandInt(nPotentials) ];
} else { } else {
// Automagic zaddr source election failed, exit honorably // Automagic zaddr source selection failed, exit honorably
throw JSONRPCError(RPC_INVALID_PARAMETER, "No single zaddr currently has enough funds to make that transaction, you may need to wait for confirmations."); throw JSONRPCError(RPC_INVALID_PARAMETER, "No single zaddr currently has enough funds to make that transaction, you may need to wait for confirmations.");
} }
} else { } else {
@@ -5149,6 +5194,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
} }
} }
// Recipients // Recipients
std::vector<SendManyRecipient> taddrRecipients; std::vector<SendManyRecipient> taddrRecipients;
std::vector<SendManyRecipient> zaddrRecipients; std::vector<SendManyRecipient> zaddrRecipients;
@@ -5238,6 +5284,38 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
nTotalOut += nAmount; nTotalOut += nAmount;
} }
std::vector<SaplingNoteEntry> saplingEntries;
// find all unspent and unlocked notes in this zaddr
pwalletMain->GetFilteredNotes(saplingEntries, fromaddress);
// sort notes from largest to smallest, which means
// we will spend the largest first
std::sort(saplingEntries.begin(), saplingEntries.end(),
[](SaplingNoteEntry i, SaplingNoteEntry j) -> bool {
return i.note.value() > j.note.value();
});
CAmount total_value = 0;
std::vector<SendManyInputSaplingNote> saplingNoteInputs;
// Decide which sapling notes will be spent
for (const SaplingNoteEntry& entry : saplingEntries) {
CAmount nValue = entry.note.value();
libzcash::SaplingExtendedSpendingKey extsk;
if (!pwalletMain->GetSaplingExtendedSpendingKey(entry.address, extsk)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find spending key for payment address.");
}
saplingNoteInputs.emplace_back(entry.op, entry.note, nValue, extsk.expsk);
total_value += nValue;
LogPrintf("%s: adding note to spend with value=%s, total_value=%s\n", __func__, FormatMoney(nValue), FormatMoney(total_value) );
if (total_value >= nTotalOut) {
// we have enough note value to make the tx
LogPrintf("%s: found enough notes, nTotalOut=%s total_value=%s\n", __func__, FormatMoney(nTotalOut), FormatMoney(total_value) );
break;
}
}
// SIETCH: Sprinkle our cave with some magic privacy zdust // SIETCH: Sprinkle our cave with some magic privacy zdust
// End goal is to have this be as large as possible without slowing xtns down too much // End goal is to have this be as large as possible without slowing xtns down too much
// A value of 7 will provide much stronger linkability privacy versus pre-Sietch operations // A value of 7 will provide much stronger linkability privacy versus pre-Sietch operations
@@ -5290,18 +5368,6 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
mtx.nVersion = SAPLING_TX_VERSION; mtx.nVersion = SAPLING_TX_VERSION;
unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
/*
const bool sapling = true; //NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
if (!sapling) {
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
mtx.nVersion = OVERWINTER_TX_VERSION;
} else {
mtx.fOverwintered = false;
mtx.nVersion = 2;
}
}
*/
// As a sanity check, estimate and verify that the size of the transaction will be valid. // As a sanity check, estimate and verify that the size of the transaction will be valid.
// Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid. // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
@@ -5370,7 +5436,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s and also greater than the default fee", FormatMoney(nFee), FormatMoney(nTotalOut))); throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s and also greater than the default fee", FormatMoney(nFee), FormatMoney(nTotalOut)));
} }
} }
} }
} }
// Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult. // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult.
@@ -5393,8 +5459,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
// Create operation and add to global queue // Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue(); std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(builder, contextualTx, fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo, opret) ); std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(builder, contextualTx, fromaddress, taddrRecipients, zaddrRecipients, saplingNoteInputs, nMinDepth, nFee, contextInfo, opret) );
q->addOperation(operation); q->addOperation(operation);
if(fZdebug) if(fZdebug)
LogPrintf("%s: Submitted to async queue\n", __FUNCTION__); LogPrintf("%s: Submitted to async queue\n", __FUNCTION__);
AsyncRPCOperationId operationId = operation->getId(); AsyncRPCOperationId operationId = operation->getId();
@@ -5420,9 +5487,9 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
if (!EnsureWalletIsAvailable(fHelp)) if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue; return NullUniValue;
if (fHelp || params.size() < 2 || params.size() > 4) if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error( throw runtime_error(
"z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit )\n" "z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit ) ( donation )\n"
"\nShield transparent coinbase funds by sending to a shielded zaddr. This is an asynchronous operation and utxos" "\nShield transparent coinbase funds by sending to a shielded zaddr. This is an asynchronous operation and utxos"
"\nselected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent`" "\nselected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent`"
"\ncan be used to return a list of locked utxos. The number of coinbase utxos selected for shielding can be limited" "\ncan be used to return a list of locked utxos. The number of coinbase utxos selected for shielding can be limited"
@@ -5435,19 +5502,22 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
"2. \"toaddress\" (string, required) The address is a zaddr.\n" "2. \"toaddress\" (string, required) The address is a zaddr.\n"
"3. fee (numeric, optional, default=" "3. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n" + strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"4. limit (numeric, optional, default=" "4. limit (integer, optional, default="
+ strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield. Set to 0 to use as many as will fit in the transaction.\n" + strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield. Set to 0 to use as many as will fit in the transaction.\n"
"5. donation (integer, optional, default=0) Percentage of coinbase funds to donate. Must be between 0 and 10 inclusive.\n"
"\nResult:\n" "\nResult:\n"
"{\n" "{\n"
" \"remainingUTXOs\": xxx (numeric) Number of coinbase utxos still available for shielding.\n" " \"remainingUTXOs\": xxx (integer) Number of coinbase utxos still available for shielding.\n"
" \"remainingValue\": xxx (numeric) Value of coinbase utxos still available for shielding.\n" " \"remainingValue\": xxx (numeric) Value of coinbase utxos still available for shielding.\n"
" \"shieldingUTXOs\": xxx (numeric) Number of coinbase utxos being shielded.\n" " \"shieldingUTXOs\": xxx (integer) Number of coinbase utxos being shielded.\n"
" \"shieldingValue\": xxx (numeric) Value of coinbase utxos being shielded.\n" " \"shieldingValue\": xxx (numeric) Value of coinbase utxos being shielded.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n" " \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n" "}\n"
"\nExamples:\n" "\nExamples:\n"
+ HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"") + HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
+ HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"") + HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
+ HelpExampleCli("z_shieldcoinbase", "'*'\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
+ HelpExampleRpc("z_shieldcoinbase", "'*'\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
@@ -5490,6 +5560,16 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
} }
} }
uint8_t donation = 0;
if (params.size() > 4) {
donation = params[4].get_int();
if (donation < 0 || donation > 10 ) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid donation percentage, must be an integer between 0 and 10");
}
}
LogPrintf("%s: donation=%d\n", __func__, donation);
int nextBlockHeight = chainActive.Height() + 1; int nextBlockHeight = chainActive.Height() + 1;
bool overwinterActive = nextBlockHeight>=1 ? true : false; // NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER); bool overwinterActive = nextBlockHeight>=1 ? true : false; // NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING;
@@ -5590,15 +5670,13 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
contextInfo.push_back(Pair("fromaddress", params[0])); contextInfo.push_back(Pair("fromaddress", params[0]));
contextInfo.push_back(Pair("toaddress", params[1])); contextInfo.push_back(Pair("toaddress", params[1]));
contextInfo.push_back(Pair("fee", ValueFromAmount(nFee))); contextInfo.push_back(Pair("fee", ValueFromAmount(nFee)));
contextInfo.push_back(Pair("donation", donation));
// Builder (used if Sapling addresses are involved) TransactionBuilder builder = TransactionBuilder( Params().GetConsensus(), nextBlockHeight, pwalletMain);
TransactionBuilder builder = TransactionBuilder(
Params().GetConsensus(), nextBlockHeight, pwalletMain);
// Contextual transaction we will build on // Contextual transaction we will build on
int blockHeight = chainActive.LastTip()->GetHeight(); int blockHeight = chainActive.LastTip()->GetHeight();
nextBlockHeight = blockHeight + 1; nextBlockHeight = blockHeight + 1;
// (used if no Sapling addresses are involved)
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
Params().GetConsensus(), nextBlockHeight); Params().GetConsensus(), nextBlockHeight);
contextualTx.nLockTime = chainActive.LastTip()->GetHeight(); contextualTx.nLockTime = chainActive.LastTip()->GetHeight();
@@ -5609,7 +5687,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
// Create operation and add to global queue // Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue(); std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(builder, contextualTx, inputs, destaddress, nFee, contextInfo) ); std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(builder, contextualTx, inputs, destaddress, nFee, donation, contextInfo) );
q->addOperation(operation); q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId(); AsyncRPCOperationId operationId = operation->getId();
@@ -5619,6 +5697,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue))); o.push_back(Pair("remainingValue", ValueFromAmount(remainingValue)));
o.push_back(Pair("shieldingUTXOs", static_cast<uint64_t>(numUtxos))); o.push_back(Pair("shieldingUTXOs", static_cast<uint64_t>(numUtxos)));
o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue))); o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue)));
o.push_back(Pair("donation", donation));
o.push_back(Pair("opid", operationId)); o.push_back(Pair("opid", operationId));
return o; return o;
} }
@@ -5951,7 +6030,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp
// Contextual transaction we will build on // Contextual transaction we will build on
CMutableTransaction contextualTx; //= CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); CMutableTransaction contextualTx; //= CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight);
// Builder (used if Sapling addresses are involved) // Builder (used if zaddrs are involved)
boost::optional<TransactionBuilder> builder; boost::optional<TransactionBuilder> builder;
if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain);
@@ -5962,7 +6041,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp
// Create operation and add to global queue // Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue(); std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( std::shared_ptr<AsyncRPCOperation> operation(
new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, saplingNoteInputs, recipient, nFee, contextInfo) ); new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, saplingNoteInputs, recipient, nFee, contextInfo) );
q->addOperation(operation); q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId(); AsyncRPCOperationId operationId = operation->getId();
@@ -6186,49 +6265,6 @@ UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk)
return result; return result;
} }
UniValue getbalance64(const UniValue& params, bool fHelp, const CPubKey& mypk)
{
set<CBitcoinAddress> setAddress; vector<COutput> vecOutputs;
UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR),b(UniValue::VARR); CTxDestination address;
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
const CKeyStore& keystore = *pwalletMain;
CAmount nValues[64],nValues2[64],nValue,total,total2; int32_t i,segid;
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (params.size() > 0)
throw runtime_error("getbalance64\n");
total = total2 = 0;
memset(nValues,0,sizeof(nValues));
memset(nValues2,0,sizeof(nValues2));
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
BOOST_FOREACH(const COutput& out, vecOutputs)
{
nValue = out.tx->vout[out.i].nValue;
if ( ExtractDestination(out.tx->vout[out.i].scriptPubKey, address) )
{
segid = (hush_segid32((char *)CBitcoinAddress(address).ToString().c_str()) & 0x3f);
if ( out.nDepth < 100 )
nValues2[segid] += nValue, total2 += nValue;
else nValues[segid] += nValue, total += nValue;
//fprintf(stderr,"%s %.8f depth.%d segid.%d\n",(char *)CBitcoinAddress(address).ToString().c_str(),(double)nValue/COIN,(int32_t)out.nDepth,segid);
} else fprintf(stderr,"no destination\n");
}
ret.push_back(Pair("mature",(double)total/COIN));
ret.push_back(Pair("immature",(double)total2/COIN));
for (i=0; i<64; i++)
{
a.push_back((uint64_t)nValues[i]);
b.push_back((uint64_t)nValues2[i]);
}
ret.push_back(Pair("staking", a));
ret.push_back(Pair("notstaking", b));
return ret;
}
extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp
extern UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk);
extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk);

View File

@@ -66,7 +66,6 @@ bool fPayAtLeastCustomFee = true;
#include "hush_defs.h" #include "hush_defs.h"
CBlockIndex *hush_chainactive(int32_t height); CBlockIndex *hush_chainactive(int32_t height);
extern std::string DONATION_PUBKEY;
extern int32_t HUSH_LOADINGBLOCKS; extern int32_t HUSH_LOADINGBLOCKS;
int32_t hush_dpowconfs(int32_t height,int32_t numconfs); int32_t hush_dpowconfs(int32_t height,int32_t numconfs);
int tx_height( const uint256 &hash ); int tx_height( const uint256 &hash );
@@ -1840,19 +1839,17 @@ void CWallet::GetSaplingNoteWitnesses(std::vector<SaplingOutPoint> notes,
auto noteData = mapWallet[note.hash].mapSaplingNoteData; auto noteData = mapWallet[note.hash].mapSaplingNoteData;
auto nWitnesses = noteData[note].witnesses.size(); auto nWitnesses = noteData[note].witnesses.size();
if (mapWallet.count(note.hash) && noteData.count(note) && nWitnesses > 0) { if (mapWallet.count(note.hash) && noteData.count(note) && nWitnesses > 0) {
fprintf(stderr,"%s: Found %lu witnesses for note %s\n", __func__, nWitnesses, note.hash.ToString().c_str() ); fprintf(stderr,"%s: Found %lu witnesses for note %s...\n", __func__, nWitnesses, note.hash.ToString().substr(0,8).c_str() );
witnesses[i] = noteData[note].witnesses.front(); witnesses[i] = noteData[note].witnesses.front();
if (!rt) { if (!rt) {
//fprintf(stderr,"%s: Setting witness root\n",__func__); //fprintf(stderr,"%s: Setting witness root\n",__func__);
rt = witnesses[i]->root(); rt = witnesses[i]->root();
} else { } else {
if(*rt == witnesses[i]->root()) { if(*rt == witnesses[i]->root()) {
//fprintf(stderr,"%s: rt=%s\n",__func__,rt.GetHash().ToString().c_str()); } else {
//fprintf(stderr,"%s: witnesses[%d]->root()=%s\n",__func__,i,witnesses[i]->root().GetHash().ToString().c_str());
// Something is fucky // Something is fucky
std::string err = string("CWallet::GetSaplingNoteWitnesses: Invalid witness root! rt=") + rt.get().ToString(); std::string err = string("CWallet::GetSaplingNoteWitnesses: Invalid witness root! rt=") + rt.get().ToString();
err += string("\n!= witness[i]->root()=") + witnesses[i]->root().ToString(); err += string("\n!= witness[i]->root()=") + witnesses[i]->root().ToString();
//throw std::logic_error(err);
fprintf(stderr,"%s: IGNORING %s\n", __func__,err.c_str()); fprintf(stderr,"%s: IGNORING %s\n", __func__,err.c_str());
} }
@@ -4587,12 +4584,14 @@ void CWallet::LockNote(const SaplingOutPoint& output)
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
setLockedSaplingNotes.insert(output); setLockedSaplingNotes.insert(output);
fprintf(stderr,"%s: locking note %s...\n", __func__, output.hash.ToString().substr(0,8).c_str() );
} }
void CWallet::UnlockNote(const SaplingOutPoint& output) void CWallet::UnlockNote(const SaplingOutPoint& output)
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
setLockedSaplingNotes.erase(output); setLockedSaplingNotes.erase(output);
fprintf(stderr,"%s: unlocking note %s...\n", __func__, output.hash.ToString().substr(0,8).c_str() );
} }
void CWallet::UnlockAllSaplingNotes() void CWallet::UnlockAllSaplingNotes()
@@ -4879,6 +4878,8 @@ void CWallet::GetFilteredNotes(
{ {
LOCK2(cs_main, cs_wallet); LOCK2(cs_main, cs_wallet);
LogPrintf("%s ignoreLocked=%d\n", __func__, ignoreLocked);
for (auto & p : mapWallet) { for (auto & p : mapWallet) {
CWalletTx wtx = p.second; CWalletTx wtx = p.second;
@@ -4940,8 +4941,8 @@ void CWallet::GetFilteredNotes(
} }
// skip locked notes // skip locked notes
// TODO: Add locking for Sapling notes -> done
if (ignoreLocked && IsLockedNote(op)) { if (ignoreLocked && IsLockedNote(op)) {
LogPrintf("%s: skipping locked note %s\n", __func__, op.hash.ToString().substr(0,10).c_str());
continue; continue;
} }

11
test.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Copyright 2016-2025 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
#export PYTHON_DEBUG=1
export PYTHONPATH=./qa/rpc-tests/test_framework/
#./qa/rpc-tests/ac_private.py
# ./qa/rpc-tests/lockzins.py --tracerpc
./qa/rpc-tests/shieldcoinbase_donation.py --tracerpc

View File

@@ -125,18 +125,19 @@ eval "$MAKE" --version | head -n2
as --version | head -n1 as --version | head -n1
as --version | tail -n1 as --version | tail -n1
ld -v ld -v
autoconf --version
HOST="$HOST" BUILD="$BUILD" "$MAKE" "$@" -C ./depends/ V=1 HOST="$HOST" BUILD="$BUILD" "$MAKE" "$@" -C ./depends/ V=1
./autogen.sh time ./autogen.sh
CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" $CONFIGURE_FLAGS CXXFLAGS='-g' CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" $CONFIGURE_FLAGS CXXFLAGS='-g' CFLAGS='-std=gnu17'
# Build CryptoConditions stuff # Build CryptoConditions stuff
WD=$PWD WD=$PWD
cd src/cc cd src/cc
echo $PWD echo $PWD
./makecustom CFLAGS=-std=gnu17 CC=${CC:-gcc} ./makecustom
cd $WD cd $WD
# Build RandomX # Build RandomX
@@ -147,9 +148,10 @@ then
else else
mkdir build && cd build mkdir build && cd build
cmake -DARCH=native .. cmake -DARCH=native ..
make # pass along potential -jX and other args
time make "$@"
fi fi
cd $WD cd $WD
"$MAKE" "$@" V=1 time "$MAKE" "$@" V=1