Merge branch 'dev' into jahway603
This commit is contained in:
@@ -150,7 +150,6 @@ cd hush3
|
||||
|
||||
The links for the Official Hush explorers:
|
||||
* [explorer.hush.is](https://explorer.hush.is)
|
||||
* [explorer.hush.land](https://explorer.hush.land)
|
||||
|
||||
# What is SilentDragon?
|
||||
|
||||
|
||||
@@ -4,10 +4,30 @@
|
||||
|
||||
# Run a regression test network
|
||||
#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
|
||||
#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=<addr>
|
||||
|
||||
@@ -63,8 +83,9 @@
|
||||
#rpcbind=<addr>
|
||||
|
||||
# You must set rpcuser and rpcpassword to secure the JSON-RPC api
|
||||
#rpcuser=Ulysses
|
||||
#rpcpassword=YourSuperGreatPasswordNumber_DO_NOT_USE_THIS_OR_YOU_WILL_GET_ROBBED_385593
|
||||
# These will automatically be created for you
|
||||
#rpcuser=user
|
||||
#rpcpassword=supersecretpassword
|
||||
|
||||
# How many seconds node will wait for a complete RPC HTTP request.
|
||||
# after the HTTP connection is established.
|
||||
@@ -83,7 +104,7 @@
|
||||
#rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96
|
||||
|
||||
# Listen for RPC connections on this TCP port:
|
||||
#rpcport=8232
|
||||
#rpcport=1234
|
||||
|
||||
# You can use hushd to send commands to hushd
|
||||
# running on another host using this option:
|
||||
@@ -100,8 +121,8 @@
|
||||
|
||||
# Miscellaneous options
|
||||
|
||||
# Enable attempt to mine HUSH
|
||||
#gen=0
|
||||
# Enable mining at startup
|
||||
#gen=1
|
||||
|
||||
# Set the number of threads to be used for mining (-1 = all cores).
|
||||
#genproclimit=1
|
||||
@@ -121,7 +142,7 @@
|
||||
#paytxfee=0.00
|
||||
|
||||
#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.
|
||||
#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.
|
||||
#pubkey=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392
|
||||
|
||||
#Forfeit all user rewards to miners. Set this to explicitly not claim user rewards.
|
||||
#exchange=1
|
||||
# Disable clearnet (ipv4 and ipv6) connections to this node
|
||||
#clearnet=0
|
||||
|
||||
#Donate all user rewards to a a specific address. This value must be set to a 33 byte pubkey.
|
||||
#donation=027dc7b5cfb5efca96674b45e9fda18df069d040b9fd9ff32c35df56005e330392
|
||||
# Disable ipv4
|
||||
#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
|
||||
|
||||
@@ -5,7 +5,6 @@ BASE_CACHE ?= $(BASEDIR)/built
|
||||
SDK_PATH ?= $(BASEDIR)/SDKs
|
||||
NO_WALLET ?=
|
||||
NO_UPNP ?=
|
||||
FALLBACK_DOWNLOAD_PATH ?= https://supernet/depends-sources
|
||||
|
||||
BUILD ?= $(shell ./config.guess)
|
||||
HOST ?= $(BUILD)
|
||||
|
||||
@@ -10,15 +10,15 @@ linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
|
||||
linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
||||
|
||||
ifeq (86,$(findstring 86,$(build_arch)))
|
||||
i686_linux_CC=gcc -m32
|
||||
i686_linux_CXX=g++ -m32
|
||||
i686_linux_CC=$(CC) -m32
|
||||
i686_linux_CXX=$(CXX) -m32
|
||||
i686_linux_AR=ar
|
||||
i686_linux_RANLIB=ranlib
|
||||
i686_linux_NM=nm
|
||||
i686_linux_STRIP=strip
|
||||
|
||||
x86_64_linux_CC=gcc -m64
|
||||
x86_64_linux_CXX=g++ -m64
|
||||
x86_64_linux_CC=$(CC) -m64
|
||||
x86_64_linux_CXX=$(CXX) -m64
|
||||
x86_64_linux_AR=ar
|
||||
x86_64_linux_RANLIB=ranlib
|
||||
x86_64_linux_NM=nm
|
||||
|
||||
@@ -14,7 +14,8 @@ ifneq ($(build_os),darwin)
|
||||
$(package)_config_opts_darwin=--disable-atomicsupport
|
||||
endif
|
||||
$(package)_config_opts_aarch64=--disable-atomicsupport
|
||||
$(package)_cxxflags+=-std=c++11
|
||||
$(package)_cxxflags+=-std=c++11 -fPIE
|
||||
$(package)_cflags+=-std=gnu17 -fPIE
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package=libgmp
|
||||
|
||||
|
||||
ifeq ($(host_os),mingw32)
|
||||
$(package)_download_path=https://github.com/radix42/$(package)/archive
|
||||
$(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)_sha256_hash=a8109865f2893f1373b0a8ed5ff7429de8db696fc451b1036bd7bdf95bbeffd6
|
||||
$(package)_config_opts=--enable-cxx --disable-shared
|
||||
$(package)_patches=gcc-15.patch
|
||||
endif
|
||||
|
||||
#else
|
||||
@@ -27,6 +29,10 @@ endif
|
||||
#$(package)_config_opts=--enable-cxx --disable-shared
|
||||
#endif
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
patch -p1 < $($(package)_patch_dir)/gcc-15.patch
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
$($(package)_autoconf) --host=$(host) --build=$(build)
|
||||
endef
|
||||
|
||||
@@ -6,6 +6,8 @@ $(package)_download_file=0d9f589e-a9f9-4ddb-acaa-0f1b423b32eb
|
||||
$(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1
|
||||
$(package)_dependencies=
|
||||
$(package)_config_opts=
|
||||
$(package)_cflags=-std=gnu17
|
||||
|
||||
ifeq ($(build_os),darwin)
|
||||
define $(package)_set_vars
|
||||
$(package)_build_env=MACOSX_DEPLOYMENT_TARGET="10.11"
|
||||
|
||||
@@ -39,8 +39,8 @@ native_packages := native_ccache
|
||||
wallet_packages=bdb
|
||||
|
||||
ifeq ($(host_os),linux)
|
||||
packages := boost wolfssl libevent $(zcash_packages) googletest libcurl #googlemock
|
||||
packages := boost wolfssl libevent $(zcash_packages) libcurl #googlemock googletest
|
||||
else
|
||||
packages := boost wolfssl libevent $(zcash_packages) libcurl googletest #googlemock
|
||||
packages := boost wolfssl libevent $(zcash_packages) libcurl #googlemock googletest
|
||||
endif
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ $(package)_download_path=https://github.com/wolfSSL/wolfssl/archive
|
||||
$(package)_download_file=v$($(package)_version)-stable.tar.gz
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_cflags+=-std=gnu17
|
||||
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
|
||||
$(package)_config_opts=--prefix=$(host_prefix)
|
||||
$(package)_config_opts+=--host=$(host)
|
||||
@@ -64,7 +65,7 @@ endef
|
||||
#endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE) CPPFLAGS='-fPIC' -j1 src/libwolfssl.la
|
||||
$(MAKE) CPPFLAGS='-fPIC' -j$(nproc) src/libwolfssl.la
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
|
||||
105
depends/patches/libgmp/gcc-15.patch
Normal file
105
depends/patches/libgmp/gcc-15.patch
Normal 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
|
||||
@@ -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
|
||||
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"
|
||||
|
||||
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:
|
||||
* 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2016-2024 The Hush developers
|
||||
# Copyright (c) 2018 SuperNET developers
|
||||
# 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.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
|
||||
stop_nodes, sync_blocks, sync_mempools, wait_bitcoinds, rpc_port, assert_raises, assert_true
|
||||
|
||||
import time
|
||||
from decimal import Decimal
|
||||
@@ -21,16 +21,11 @@ def assert_success(result):
|
||||
def assert_error(result):
|
||||
assert_equal(result['result'], 'error')
|
||||
|
||||
def generate_random_string(length):
|
||||
random_string = ''.join(choice(ascii_uppercase) for i in range(length))
|
||||
return random_string
|
||||
|
||||
|
||||
class AssetChainPrivateTest (BitcoinTestFramework):
|
||||
|
||||
class PrivateTest (BitcoinTestFramework):
|
||||
def setup_chain(self):
|
||||
print("Initializing ac_private 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):
|
||||
@@ -39,21 +34,19 @@ class AssetChainPrivateTest (BitcoinTestFramework):
|
||||
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=REGTEST',
|
||||
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
|
||||
'-ac_name=ZZZ',
|
||||
'-conf='+self.options.tmpdir+'/node0/regtest/ZZZ.conf',
|
||||
'-port=64367',
|
||||
'-rpcport=64368',
|
||||
'-regtest',
|
||||
'-addressindex=1',
|
||||
'-spentindex=1',
|
||||
'-ac_supply=0',
|
||||
'-ac_supply=10',
|
||||
'-ac_reward=25600000000',
|
||||
'-ac_private=1',
|
||||
'-allowlist=127.0.0.1',
|
||||
'-debug',
|
||||
#'-debug',
|
||||
'-regtest',
|
||||
'--daemon',
|
||||
'-rpcuser=rt',
|
||||
'-rpcpassword=rt'
|
||||
'-rpcuser=hush',
|
||||
'-rpcpassword=puppy'
|
||||
]]
|
||||
)
|
||||
self.is_network_split = split
|
||||
@@ -71,23 +64,23 @@ class AssetChainPrivateTest (BitcoinTestFramework):
|
||||
def run_test (self):
|
||||
print("Mining blocks...")
|
||||
rpc = self.nodes[0]
|
||||
# utxos from block 1 become mature in block 101
|
||||
rpc.generate(101)
|
||||
rpc.generate(1)
|
||||
self.sync_all()
|
||||
rpc.getinfo()
|
||||
rpc.getwalletinfo()
|
||||
|
||||
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
|
||||
# TODO: keep in sync when notaries change
|
||||
#dev1_jl777 = "RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc"
|
||||
# taddr vout is only allowed if it is a notary address
|
||||
#txid = rpc.sendtoaddress(dev1_jl777, 7)
|
||||
#assert txid, 'got txid'
|
||||
# sending to arbitrary non-notary transparent address is not allowed
|
||||
print("Sending to " + taddr)
|
||||
try:
|
||||
rpc.sendtoaddress(taddr, 1)
|
||||
except:
|
||||
assert_true(1)
|
||||
|
||||
# this should work but don't
|
||||
#assert_raises(JSONRPCException, rpc.sendtoaddress, taddr,1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
AssetChainPrivateTest ().main()
|
||||
PrivateTest ().main()
|
||||
|
||||
109
qa/rpc-tests/lockzins.py
Executable file
109
qa/rpc-tests/lockzins.py
Executable 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()
|
||||
247
qa/rpc-tests/shieldcoinbase_donation.py
Executable file
247
qa/rpc-tests/shieldcoinbase_donation.py
Executable 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()
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
# 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 (c) 2016-2025 The Hush developers
|
||||
"""
|
||||
Copyright 2011 Jeff Garzik
|
||||
|
||||
@@ -38,45 +34,37 @@
|
||||
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 decimal
|
||||
import json
|
||||
import logging
|
||||
try:
|
||||
import urllib.parse as urlparse
|
||||
except ImportError:
|
||||
import urlparse
|
||||
from http.client import HTTPConnection, HTTPSConnection, BadStatusLine
|
||||
from urllib.parse import urlparse
|
||||
|
||||
USER_AGENT = "HushAuthServiceProxy/0.1"
|
||||
|
||||
USER_AGENT = "FUCKjl777LULZ"
|
||||
HTTP_TIMEOUT = 600
|
||||
log = logging.getLogger("BitcoinRPC")
|
||||
|
||||
log = logging.getLogger("RPC")
|
||||
|
||||
class JSONRPCException(Exception):
|
||||
def __init__(self, rpc_error):
|
||||
Exception.__init__(self)
|
||||
Exception.__init__(self, rpc_error.get("message"))
|
||||
self.error = rpc_error
|
||||
|
||||
|
||||
def EncodeDecimal(o):
|
||||
if isinstance(o, decimal.Decimal):
|
||||
return round(o, 8)
|
||||
return str(o)
|
||||
raise TypeError(repr(o) + " is not JSON serializable")
|
||||
|
||||
class AuthServiceProxy(object):
|
||||
|
||||
class AuthServiceProxy():
|
||||
__id_count = 0
|
||||
|
||||
def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None):
|
||||
self.__service_url = service_url
|
||||
self.__service_name = service_name
|
||||
self.__url = urlparse.urlparse(service_url)
|
||||
if self.__url.port is None:
|
||||
port = 80
|
||||
else:
|
||||
port = self.__url.port
|
||||
self._service_name = service_name
|
||||
self.__url = urlparse(service_url)
|
||||
(user, passwd) = (self.__url.username, self.__url.password)
|
||||
try:
|
||||
user = user.encode('utf8')
|
||||
@@ -89,23 +77,25 @@ class AuthServiceProxy(object):
|
||||
authpair = user + b':' + passwd
|
||||
self.__auth_header = b'Basic ' + base64.b64encode(authpair)
|
||||
|
||||
if connection:
|
||||
# Callables re-use the connection of the original proxy
|
||||
self.__conn = connection
|
||||
elif self.__url.scheme == 'https':
|
||||
self.__conn = httplib.HTTPSConnection(self.__url.hostname, port,
|
||||
None, None, False,
|
||||
timeout)
|
||||
else:
|
||||
self.__conn = httplib.HTTPConnection(self.__url.hostname, port,
|
||||
False, timeout)
|
||||
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:
|
||||
self.__conn = connection
|
||||
self.timeout = connection.timeout
|
||||
elif self.__url.scheme == 'https':
|
||||
self.__conn = HTTPSConnection(self.__url.hostname, port, timeout=self.timeout)
|
||||
else:
|
||||
self.__conn = HTTPConnection(self.__url.hostname, port, timeout=self.timeout)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name.startswith('__') and name.endswith('__'):
|
||||
# Python internal stuff
|
||||
raise AttributeError
|
||||
if self.__service_name is not None:
|
||||
name = "%s.%s" % (self.__service_name, name)
|
||||
if self._service_name is not None:
|
||||
name = "%s.%s" % (self._service_name, name)
|
||||
return AuthServiceProxy(self.__service_url, name, connection=self.__conn)
|
||||
|
||||
def _request(self, method, path, postdata):
|
||||
@@ -124,8 +114,9 @@ class AuthServiceProxy(object):
|
||||
# If connection was closed, try again.
|
||||
# Python 3.5+ raises BrokenPipeError instead of BadStatusLine when the connection was reset.
|
||||
# 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.
|
||||
if ((isinstance(e, httplib.BadStatusLine) and e.line == "''")
|
||||
# This can be simplified now that we depend on Python 3 (previously, we could not
|
||||
# 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')):
|
||||
self.__conn.close()
|
||||
self.__conn.request(method, path, postdata, headers)
|
||||
@@ -136,10 +127,10 @@ class AuthServiceProxy(object):
|
||||
def __call__(self, *args):
|
||||
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)))
|
||||
postdata = json.dumps({'version': '1.1',
|
||||
'method': self.__service_name,
|
||||
'method': self._service_name,
|
||||
'params': args,
|
||||
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal)
|
||||
response = self._request('POST', self.__url.path, postdata)
|
||||
@@ -161,6 +152,11 @@ class AuthServiceProxy(object):
|
||||
if http_response is None:
|
||||
raise JSONRPCException({
|
||||
'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')
|
||||
response = json.loads(responsedata, parse_float=decimal.Decimal)
|
||||
|
||||
@@ -123,21 +123,26 @@ class BitcoinTestFramework(object):
|
||||
print("JSONRPC error: "+e.error['message'])
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
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])
|
||||
except Exception as e:
|
||||
print("Unexpected exception caught during testing: "+str(e))
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
except KeyboardInterrupt as e:
|
||||
print("Exiting after " + repr(e))
|
||||
|
||||
if not self.options.noshutdown:
|
||||
print("Stopping nodes")
|
||||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
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:
|
||||
print("Cleaning up")
|
||||
print("Deleting %s" % self.options.tmpdir)
|
||||
shutil.rmtree(self.options.tmpdir)
|
||||
|
||||
if success:
|
||||
@@ -169,7 +174,7 @@ class ComparisonTestFramework(BitcoinTestFramework):
|
||||
help="bitcoind binary to use for reference nodes (if any)")
|
||||
|
||||
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)
|
||||
|
||||
def setup_network(self):
|
||||
|
||||
@@ -57,7 +57,7 @@ def sync_blocks(rpc_connections, wait=1):
|
||||
break
|
||||
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
|
||||
while True:
|
||||
notified = [ x.getblockchaininfo()['fullyNotified'] for x in rpc_connections ]
|
||||
@@ -91,15 +91,17 @@ def sync_mempools(rpc_connections, wait=1):
|
||||
bitcoind_processes = {}
|
||||
|
||||
def initialize_datadir(dirname, n):
|
||||
datadir = os.path.join(dirname, "node"+str(n))
|
||||
datadir = os.path.join(datadir,"HUSH3")
|
||||
datadir = os.path.join(dirname, "node"+str(n), "regtest")
|
||||
#datadir = os.path.join(datadir,"ZZZ")
|
||||
if not os.path.isdir(datadir):
|
||||
print("Creating dirs %s" % datadir)
|
||||
os.makedirs(datadir)
|
||||
|
||||
print("Writing to " + os.path.join(datadir,"HUSH3.conf"))
|
||||
with open(os.path.join(datadir, "HUSH3.conf"), 'w') as f:
|
||||
print("Writing to " + os.path.join(datadir,"ZZZ.conf"))
|
||||
with open(os.path.join(datadir, "ZZZ.conf"), 'w') as f:
|
||||
f.write("regtest=1\n");
|
||||
f.write("txindex=1\n");
|
||||
#f.write("testnode=1\n");
|
||||
f.write("server=1\n");
|
||||
f.write("showmetrics=0\n");
|
||||
f.write("rpcuser=hush\n");
|
||||
@@ -107,13 +109,15 @@ def initialize_datadir(dirname, n):
|
||||
f.write("port="+str(p2p_port(n))+"\n");
|
||||
rpcport = str(rpc_port(n))
|
||||
f.write("rpcport="+rpcport+"\n");
|
||||
print "RPC port=" + rpcport
|
||||
print("RPC port=" + rpcport)
|
||||
f.write("listenonion=0\n");
|
||||
# TODO: maybe make these optional, via arg to initialize_datadir, defaulted to on for now
|
||||
f.write("addressindex=1\n");
|
||||
f.write("spentindex=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
|
||||
|
||||
def initialize_chain(test_dir):
|
||||
@@ -136,14 +140,14 @@ def initialize_chain(test_dir):
|
||||
cmd = os.getenv("BITCOINCLI", "hush-cli")
|
||||
cmd_args = cmd + " -datadir="+datadir + " -rpcwait getblockcount"
|
||||
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"
|
||||
|
||||
print("Running " + strcmd)
|
||||
subprocess.check_call(strcmd, shell=True);
|
||||
#subprocess.check_call([ cmd, "-rpcwait", "getblockcount"], stdout=devnull)
|
||||
if os.getenv("PYTHON_DEBUG", ""):
|
||||
print "initialize_chain: hush-cli -rpcwait getblockcount completed"
|
||||
print("initialize_chain: hush-cli -rpcwait getblockcount completed")
|
||||
devnull.close()
|
||||
rpcs = []
|
||||
for i in range(4):
|
||||
@@ -175,7 +179,7 @@ def initialize_chain(test_dir):
|
||||
stop_nodes(rpcs)
|
||||
wait_bitcoinds()
|
||||
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, "db.log"))
|
||||
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
|
||||
"""
|
||||
print("Starting node " + str(i))
|
||||
datadir = os.path.join(dirname, "node"+str(i))
|
||||
# creating special config in case of cryptocondition asset chain test
|
||||
if len(extra_args) > 0 and extra_args[0] == '-ac_name=REGTEST':
|
||||
configpath = datadir + "/REGTEST.conf"
|
||||
print("Starting node " + str(i) + " in dir " + dirname)
|
||||
datadir = os.path.join(dirname, "node"+str(i), "regtest")
|
||||
# creating special config
|
||||
if len(extra_args) > 0 and extra_args[0] == '-ac_name=ZZZ':
|
||||
configpath = datadir + "/ZZZ.conf"
|
||||
with open(configpath, "w+") as config:
|
||||
config.write("regtest=1\n")
|
||||
config.write("rpcuser=rt\n")
|
||||
config.write("rpcpassword=rt\n")
|
||||
config.write("rpcuser=hush\n")
|
||||
config.write("rpcpassword=puppy\n")
|
||||
port = extra_args[3]
|
||||
config.write("rpcport=" + (port[9:]) + "\n")
|
||||
config.write("server=1\n")
|
||||
#config.write("testnode=1\n")
|
||||
config.write("txindex=1\n")
|
||||
config.write("rpcworkqueue=256\n")
|
||||
config.write("rpcallowip=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:
|
||||
binary = os.getenv("BITCOIND", "hushd")
|
||||
binary = os.getenv("BITCOIND", "src/hushd")
|
||||
args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
|
||||
if extra_args is not None: args.extend(extra_args)
|
||||
#print("args=" + ' '.join(args))
|
||||
print("args=" + ' '.join(args))
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
devnull = open("/dev/null", "w+")
|
||||
|
||||
cmd = os.getenv("BITCOINCLI", "hush-cli")
|
||||
cmd = os.getenv("BITCOINCLI", "src/hush-cli")
|
||||
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", ""):
|
||||
print "start_node: hushd started, calling : " + cmd + " " + cmd_args
|
||||
print("start_node: hushd started, calling : " + cmd + " " + cmd_args)
|
||||
strcmd = cmd + " " + cmd_args
|
||||
|
||||
print("Running " + strcmd)
|
||||
@@ -261,19 +270,20 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
|
||||
# _rpchost_to_args(rpchost) +
|
||||
# ["-rpcwait", "-rpcport=6438", "getblockcount"], stdout=devnull)
|
||||
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()
|
||||
#port = extra_args[3]
|
||||
port = rpc_port(i)
|
||||
port = extra_args[3]
|
||||
#port = rpc_port(i)
|
||||
#print("port=%s" % port)
|
||||
username = rpc_username()
|
||||
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)
|
||||
if timewait is not None:
|
||||
proxy = AuthServiceProxy(url, timeout=timewait)
|
||||
else:
|
||||
proxy = AuthServiceProxy(url)
|
||||
print("created proxy")
|
||||
#print("created proxy")
|
||||
proxy.url = url # store URL on proxy for info
|
||||
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):
|
||||
print('waiting for async operation {}'.format(myopid))
|
||||
result = None
|
||||
for _ in xrange(1, timeout):
|
||||
for _ in range(1, timeout):
|
||||
results = node.z_getoperationresult([myopid])
|
||||
if len(results) > 0:
|
||||
result = results[0]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
DIST_SUBDIRS = secp256k1 univalue
|
||||
|
||||
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)
|
||||
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_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_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_CXXFLAGS = $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing
|
||||
libhush_a_CXXFLAGS = $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing -std=gnu17
|
||||
|
||||
libhush_a_LDFLAGS = $(HARDENED_LDFLAGS)
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
SHELL = /bin/sh
|
||||
CC = gcc
|
||||
CC_DARWIN = g++-8
|
||||
CC_WIN = x86_64-w64-mingw32-gcc-posix
|
||||
CC_AARCH64 = aarch64-linux-gnu-g++
|
||||
|
||||
1459
src/chainparams.cpp
1459
src/chainparams.cpp
File diff suppressed because it is too large
Load Diff
@@ -301,7 +301,7 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType)
|
||||
bool bInitialized = false;
|
||||
WOLFSSL_CTX* tlsCtx = NULL;
|
||||
|
||||
byte *pem;
|
||||
unsigned char *pem;
|
||||
int plen = 0;
|
||||
|
||||
if ((tlsCtx = wolfSSL_CTX_new(ctxType == SERVER_CONTEXT ? wolfTLSv1_3_server_method() : wolfTLSv1_3_client_method()))) {
|
||||
|
||||
@@ -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_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN)
|
||||
|
||||
//#ifndef TESTMODE
|
||||
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
|
||||
//#else
|
||||
//#define PRICES_DAYWINDOW (7)
|
||||
//#endif
|
||||
|
||||
extern uint8_t ASSETCHAINS_CLEARNET;
|
||||
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
|
||||
extern int8_t ASSETCHAINS_ADAPTIVEPOW;
|
||||
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 std::vector<std::string> ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS;
|
||||
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 std::string CCerror,ASSETCHAINS_CCLIB;
|
||||
extern uint8_t ASSETCHAINS_CCDISABLES[256];
|
||||
extern int32_t USE_EXTERNAL_PUBKEY;
|
||||
extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS;
|
||||
extern std::string DONATION_PUBKEY;
|
||||
extern uint8_t ASSETCHAINS_PRIVATE;
|
||||
extern int32_t USE_EXTERNAL_PUBKEY;
|
||||
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);
|
||||
int32_t hush_priceind(const char *symbol);
|
||||
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();
|
||||
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_notarized_bracket(struct notarized_checkpoint *nps[2],int32_t height);
|
||||
arith_uint256 hush_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime);
|
||||
|
||||
1510
src/hush_gateway.h
1510
src/hush_gateway.h
File diff suppressed because it is too large
Load Diff
@@ -45,11 +45,12 @@ int COINBASE_MATURITY = _COINBASE_MATURITY;//100;
|
||||
unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10;
|
||||
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;
|
||||
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;
|
||||
int8_t ASSETCHAINS_ADAPTIVEPOW;
|
||||
uint8_t ASSETCHAINS_CLEARNET = 1;
|
||||
uint8_t ASSETCHAINS_BURN = 0;
|
||||
uint32_t ASSETCHAINS_MINOPRETURNFEE = 0;
|
||||
std::vector<uint8_t> Mineropret;
|
||||
|
||||
@@ -1339,7 +1339,7 @@ void hush_statefname(char *fname,char *symbol,char *str)
|
||||
fname[len - n] = 0;
|
||||
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]);
|
||||
return;
|
||||
}
|
||||
@@ -1763,9 +1763,7 @@ void hush_args(char *argv0)
|
||||
{
|
||||
HUSH_MININGTHREADS = GetArg("-genproclimit",-1);
|
||||
}
|
||||
DONATION_PUBKEY = GetArg("-donation", "");
|
||||
NOTARY_PUBKEY = GetArg("-pubkey", "");
|
||||
HUSH_DEALERNODE = GetArg("-dealer",0);
|
||||
HUSH_TESTNODE = GetArg("-testnode",0);
|
||||
|
||||
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);
|
||||
|
||||
ASSETCHAINS_BURN = GetArg("-ac_burn", 0);
|
||||
ASSETCHAINS_CLEARNET = GetArg("-ac_clearnet", 1);
|
||||
ASSETCHAINS_MINOPRETURNFEE = GetArg("-ac_minopreturnfee", 0);
|
||||
|
||||
// -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)
|
||||
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);
|
||||
}
|
||||
|
||||
if ( ASSETCHAINS_CLEARNET == 0 )
|
||||
{
|
||||
extralen += dragon_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_CLEARNET),(void *)&ASSETCHAINS_CLEARNET);
|
||||
}
|
||||
}
|
||||
|
||||
addn = GetArg("-seednode","");
|
||||
|
||||
17
src/init.cpp
17
src/init.cpp
@@ -146,7 +146,9 @@ std::atomic<bool> fRequestShutdown(false);
|
||||
|
||||
void StartShutdown()
|
||||
{
|
||||
fprintf(stderr,"%s: fRequestShudown=true\n", __FUNCTION__);
|
||||
if(fDebug) {
|
||||
fprintf(stderr,"%s: fRequestShudown=true\n", __FUNCTION__);
|
||||
}
|
||||
fRequestShutdown = true;
|
||||
}
|
||||
bool ShutdownRequested()
|
||||
@@ -208,7 +210,9 @@ void Shutdown()
|
||||
RenameThread(shutoffstr);
|
||||
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();
|
||||
StopREST();
|
||||
StopRPC();
|
||||
@@ -225,7 +229,9 @@ void Shutdown()
|
||||
GenerateBitcoins(false, 0);
|
||||
#endif
|
||||
#endif
|
||||
fprintf(stderr,"%s: stopping node\n", __FUNCTION__);
|
||||
if(fDebug) {
|
||||
fprintf(stderr,"%s: stopping node\n", __FUNCTION__);
|
||||
}
|
||||
StopNode();
|
||||
StopTorControl();
|
||||
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_minopreturnfee", _("OP_RETURN minimum fee per tx, regardless of tx size, default is 1 coin"));
|
||||
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_end", _("Block height at which block rewards will end"));
|
||||
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__);
|
||||
|
||||
// Disable clearnet peers if -clearnet=0
|
||||
if (!GetBoolArg("-clearnet", DEFAULT_CLEARNET)) {
|
||||
// Disable clearnet peers if -clearnet=0 for this node or -ac_clearnet=0 for this chain
|
||||
if (ASSETCHAINS_CLEARNET == 0 || !GetBoolArg("-clearnet", DEFAULT_CLEARNET)) {
|
||||
#ifdef ENABLE_MINING
|
||||
// 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
|
||||
|
||||
@@ -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 uint32_t ASSETCHAINS_MAGIC;
|
||||
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 uint64_t ASSETCHAINS_CBOPRET;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <hush/tlsmanager.cpp>
|
||||
using namespace hush;
|
||||
extern int32_t HUSH_TESTNODE;
|
||||
extern uint8_t ASSETCHAINS_CLEARNET;
|
||||
|
||||
// Dump addresses to peers.dat every 5 minutes (300s)
|
||||
// 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() {
|
||||
// No health check if clearnet is disabled
|
||||
if (!GetBoolArg("-clearnet", DEFAULT_CLEARNET)) {
|
||||
if (ASSETCHAINS_CLEARNET == 0 || !GetBoolArg("-clearnet", DEFAULT_CLEARNET)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,9 @@
|
||||
#undef TFM_TIMING_RESISTANT
|
||||
#define ECC_TIMING_RESISTANT 420
|
||||
#define TFM_TIMING_RESISTANT 420
|
||||
#define byte unsigned char
|
||||
#include <wolfssl/ssl.h>
|
||||
#undef byte
|
||||
|
||||
class CAddrMan;
|
||||
class CBlockIndex;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <tuple>
|
||||
|
||||
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 */
|
||||
bool CNetAddr::IsReachableNetwork() {
|
||||
|
||||
@@ -639,12 +639,6 @@ UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
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)
|
||||
{
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
@@ -1061,9 +1055,6 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t hush_pending_withdraws(char *opretstr);
|
||||
extern char CURRENCIES[][8];
|
||||
|
||||
UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
{
|
||||
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()));
|
||||
}
|
||||
|
||||
// this helps our tests work correctly
|
||||
if (Params().NetworkIDString() == "regtest") {
|
||||
obj.pushKV("fullyNotified", ChainIsFullyNotified());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,10 +90,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "getblock", 1 },
|
||||
{ "getblockheader", 1 },
|
||||
{ "getchaintxstats", 0 },
|
||||
{ "getlastsegidstakes", 0 },
|
||||
{ "gettransaction", 1 },
|
||||
{ "getrawtransaction", 1 },
|
||||
{ "getlastsegidstakes", 0 },
|
||||
{ "createrawtransaction", 0 },
|
||||
{ "createrawtransaction", 1 },
|
||||
{ "createrawtransaction", 2 },
|
||||
|
||||
@@ -320,7 +320,6 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "blockchain", "getblockhashes", &getblockhashes, true },
|
||||
{ "blockchain", "getblockhash", &getblockhash, true },
|
||||
{ "blockchain", "getblockheader", &getblockheader, true },
|
||||
{ "blockchain", "getlastsegidstakes", &getlastsegidstakes, true },
|
||||
{ "blockchain", "getchaintips", &getchaintips, true },
|
||||
{ "blockchain", "getdifficulty", &getdifficulty, true },
|
||||
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true },
|
||||
@@ -429,9 +428,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true },
|
||||
{ "wallet", "cleanwallettransactions", &cleanwallettransactions, false },
|
||||
{ "wallet", "getbalance", &getbalance, false },
|
||||
{ "wallet", "getbalance64", &getbalance64, false },
|
||||
{ "wallet", "getnewaddress", &getnewaddress, true },
|
||||
// { "wallet", "getnewaddress64", &getnewaddress64, true },
|
||||
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, true },
|
||||
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false },
|
||||
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false },
|
||||
@@ -462,6 +459,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "wallet", "walletlock", &walletlock, true },
|
||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
|
||||
{ "wallet", "walletpassphrase", &walletpassphrase, true },
|
||||
{ "wallet", "z_listlockunspent", &z_listlockunspent, false },
|
||||
{ "wallet", "z_listreceivedbyaddress",&z_listreceivedbyaddress,false },
|
||||
{ "wallet", "z_listreceivedaddress", &z_listreceivedaddress, false },
|
||||
{ "wallet", "z_getbalance", &z_getbalance, false },
|
||||
|
||||
@@ -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 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 getrawchangeaddress(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 cleanwallettransactions(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 movecmd(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 geterablockheights(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 getblockchaininfo(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 lockunspent(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 decoderawtransaction(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 getblockhash(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 gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||
extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||
|
||||
@@ -54,6 +54,9 @@ void TransactionBuilder::AddSaplingOutput(
|
||||
CAmount value,
|
||||
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);
|
||||
outputs.emplace_back(ovk, note, memo);
|
||||
mtx.valueBalance -= value;
|
||||
@@ -150,7 +153,7 @@ boost::optional<CTransaction> TransactionBuilder::Build()
|
||||
change -= tOut.nValue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
CDBBatch batch(*this);
|
||||
if (fZdebug)
|
||||
if (fDebug)
|
||||
fprintf(stderr, "%s: Writing block files\n", __FUNCTION__);
|
||||
for (const auto& it : fileInfo) {
|
||||
batch.Write(make_pair(DB_BLOCK_FILES, it.first), *it.second);
|
||||
}
|
||||
batch.Write(DB_LAST_BLOCK, nLastFile);
|
||||
if (fZdebug)
|
||||
if (fDebug)
|
||||
fprintf(stderr, "%s: Writing block index\n", __FUNCTION__);
|
||||
for (const auto& it : blockinfo) {
|
||||
std::pair<char, uint256> key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash());
|
||||
|
||||
@@ -53,13 +53,13 @@ using namespace libzcash;
|
||||
extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||
|
||||
AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
||||
boost::optional<TransactionBuilder> builder,
|
||||
CMutableTransaction contextualTx,
|
||||
std::vector<MergeToAddressInputUTXO> utxoInputs,
|
||||
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs,
|
||||
MergeToAddressRecipient recipient,
|
||||
CAmount fee,
|
||||
UniValue contextInfo) :
|
||||
boost::optional<TransactionBuilder> builder,
|
||||
CMutableTransaction contextualTx,
|
||||
std::vector<MergeToAddressInputUTXO> utxoInputs,
|
||||
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs,
|
||||
MergeToAddressRecipient recipient,
|
||||
CAmount fee,
|
||||
UniValue contextInfo) :
|
||||
tx_(contextualTx), utxoInputs_(utxoInputs), saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), contextinfo_(contextInfo)
|
||||
{
|
||||
if (fee < 0 || fee > MAX_MONEY) {
|
||||
@@ -182,7 +182,6 @@ void AsyncRPCOperation_mergetoaddress::main()
|
||||
|
||||
// Notes:
|
||||
// 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()
|
||||
{
|
||||
assert(isToTaddr_ != isToZaddr_);
|
||||
@@ -192,22 +191,6 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
|
||||
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;
|
||||
for (MergeToAddressInputUTXO& t : utxoInputs_) {
|
||||
t_inputs_total += std::get<1>(t);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) 2017 The Zcash 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
|
||||
|
||||
@@ -28,12 +27,9 @@
|
||||
#include "transaction_builder.h"
|
||||
#include "wallet.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "zcash/JoinSplit.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
// Default transaction fee if caller does not specify one.
|
||||
@@ -90,9 +86,6 @@ private:
|
||||
CTxDestination toTaddr_;
|
||||
PaymentAddress toPaymentAddress_;
|
||||
|
||||
uint256 joinSplitPubKey_;
|
||||
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
|
||||
|
||||
std::vector<MergeToAddressInputUTXO> utxoInputs_;
|
||||
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs_;
|
||||
|
||||
|
||||
@@ -74,6 +74,8 @@ void AsyncRPCOperation_saplingconsolidation::main() {
|
||||
}
|
||||
|
||||
LogPrintf("%s", s);
|
||||
unlock_notes(); // clean up
|
||||
LogPrint("zrpc", "%s: consolidation input notes unlocked\n", getId());
|
||||
}
|
||||
|
||||
bool AsyncRPCOperation_saplingconsolidation::main_impl() {
|
||||
@@ -102,6 +104,11 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
|
||||
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) {
|
||||
const vector<string>& v = mapMultiArgs["-consolidatesaplingaddress"];
|
||||
for(int i = 0; i < v.size(); i++) {
|
||||
@@ -233,6 +240,10 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
|
||||
break;
|
||||
}
|
||||
|
||||
// Lock shielded input notes
|
||||
lock_notes();
|
||||
LogPrint("zrpc", "%s: consolidation input notes locked\n", getId());
|
||||
|
||||
if(pwalletMain->CommitAutomatedTx(tx)) {
|
||||
LogPrintf("%s: Committed consolidation transaction with txid=%s\n",opid, tx.GetHash().ToString());
|
||||
amountConsolidated += actualAmountToSend;
|
||||
@@ -240,10 +251,15 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
|
||||
numTxCreated++;
|
||||
} else {
|
||||
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);
|
||||
status = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,3 +291,19 @@ UniValue AsyncRPCOperation_saplingconsolidation::getStatus() const {
|
||||
obj.push_back(Pair("target_height", targetHeight_));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "univalue.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "zcash/zip32.h"
|
||||
#include "wallet.h" // for SaplingNoteEntry
|
||||
|
||||
//Default fee used for consolidation transactions, in puposhis
|
||||
static const CAmount DEFAULT_CONSOLIDATION_FEE = 10000;
|
||||
@@ -32,10 +33,14 @@ public:
|
||||
|
||||
virtual UniValue getStatus() const;
|
||||
|
||||
void lock_notes();
|
||||
void unlock_notes();
|
||||
|
||||
private:
|
||||
int targetHeight_;
|
||||
|
||||
bool main_impl();
|
||||
std::vector<SaplingNoteEntry> z_sapling_inputs_;
|
||||
|
||||
void setConsolidationResult(int numTxCreated, const CAmount& amountConsolidated, const std::vector<std::string>& consolidationTxIds);
|
||||
|
||||
|
||||
@@ -63,11 +63,12 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
std::string fromAddress,
|
||||
std::vector<SendManyRecipient> tOutputs,
|
||||
std::vector<SendManyRecipient> zOutputs,
|
||||
std::vector<SendManyInputSaplingNote> saplingNoteInputs,
|
||||
int minDepth,
|
||||
CAmount fee,
|
||||
UniValue contextInfo,
|
||||
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);
|
||||
|
||||
@@ -119,14 +120,25 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
} else {
|
||||
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() {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
set_state(OperationStatus::EXECUTING);
|
||||
start_execution_clock();
|
||||
@@ -162,6 +174,10 @@ void AsyncRPCOperation_sendmany::main() {
|
||||
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_WALLET
|
||||
GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 1));
|
||||
@@ -172,6 +188,7 @@ void AsyncRPCOperation_sendmany::main() {
|
||||
|
||||
stop_execution_clock();
|
||||
|
||||
|
||||
if (success) {
|
||||
set_state(OperationStatus::SUCCESS);
|
||||
} else {
|
||||
@@ -185,22 +202,14 @@ void AsyncRPCOperation_sendmany::main() {
|
||||
s += strprintf(", error=%s)\n", getErrorMessage());
|
||||
}
|
||||
LogPrintf("%s",s);
|
||||
|
||||
}
|
||||
|
||||
// Notes:
|
||||
// 1. #1159 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
|
||||
// 1. Currently there is no limit set on the number of shielded spends, so size of tx could be invalid.
|
||||
bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
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 isMultipleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()>=1);
|
||||
bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0);
|
||||
@@ -227,9 +236,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
}
|
||||
|
||||
if (isfromzaddr_ && !find_unspent_notes()) {
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds, no unspent notes found for zaddr from address.");
|
||||
}
|
||||
// Lock UTXOs
|
||||
lock_utxos();
|
||||
|
||||
CAmount t_inputs_total = 0;
|
||||
for (SendManyInputUTXO & t : t_inputs_) {
|
||||
@@ -237,8 +245,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
|
||||
CAmount z_inputs_total = 0;
|
||||
for (auto t : z_sapling_inputs_) {
|
||||
z_inputs_total += t.note.value();
|
||||
for (auto t : saplingNoteInputs_) {
|
||||
z_inputs_total += std::get<1>(t).value();
|
||||
}
|
||||
|
||||
CAmount t_outputs_total = 0;
|
||||
@@ -252,8 +260,11 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
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 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(!isfromzaddr_ || t_inputs_total == 0);
|
||||
@@ -309,23 +320,6 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
t_inputs_ = selectedTInputs;
|
||||
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
|
||||
if (isUsingBuilder_) {
|
||||
CScript scriptPubKey;
|
||||
@@ -415,15 +409,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
if(fZdebug)
|
||||
LogPrintf("%s: Selecting Sapling notes\n", __FUNCTION__);
|
||||
std::vector<SaplingOutPoint> ops;
|
||||
std::vector<SaplingNote> notes;
|
||||
CAmount sum = 0;
|
||||
for (auto t : z_sapling_inputs_) {
|
||||
ops.push_back(t.op);
|
||||
notes.push_back(t.note);
|
||||
sum += t.note.value();
|
||||
if (sum >= targetAmount) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(const auto t : saplingNoteInputs_) {
|
||||
ops.push_back(std::get<0>(t));
|
||||
}
|
||||
|
||||
// Fetch Sapling anchor and witnesses
|
||||
@@ -435,14 +424,19 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
pwalletMain->GetSaplingNoteWitnesses(ops, witnesses, anchor);
|
||||
}
|
||||
|
||||
LogPrintf("%s: ops.size=%d witnesses.size=%d\n", __func__, ops.size(), witnesses.size() );
|
||||
|
||||
// Add Sapling spends
|
||||
for (size_t i = 0; i < notes.size(); i++) {
|
||||
if (!witnesses[i]) {
|
||||
for (size_t i = 0; i < saplingNoteInputs_.size(); i++) {
|
||||
if (!witnesses.at(i)) {
|
||||
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
|
||||
@@ -454,7 +448,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
assert(boost::get<libzcash::SaplingPaymentAddress>(&addr) != nullptr);
|
||||
auto to = boost::get<libzcash::SaplingPaymentAddress>(addr);
|
||||
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);
|
||||
|
||||
@@ -488,6 +482,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
// Send the transaction
|
||||
// TODO: Use CWallet::CommitTransaction instead of sendrawtransaction
|
||||
auto signedtxn = EncodeHexTx(tx_);
|
||||
|
||||
if (!testmode) {
|
||||
UniValue params = UniValue(UniValue::VARR);
|
||||
params.push_back(signedtxn);
|
||||
@@ -659,37 +654,6 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
||||
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() {
|
||||
|
||||
CMutableTransaction rawTx(tx_);
|
||||
@@ -781,3 +745,53 @@ UniValue AsyncRPCOperation_sendmany::getStatus() const {
|
||||
obj.push_back(Pair("params", contextinfo_ ));
|
||||
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__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,14 +25,11 @@
|
||||
#include "amount.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "transaction_builder.h"
|
||||
#include "zcash/JoinSplit.hpp"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "wallet.h"
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
// 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)
|
||||
typedef std::tuple<uint256, int, CAmount, bool, CTxDestination> SendManyInputUTXO;
|
||||
|
||||
// A struct to help us track the witness and anchor for a given JSOutPoint
|
||||
struct WitnessAnchorData {
|
||||
boost::optional<SproutWitness> witness;
|
||||
uint256 anchor;
|
||||
};
|
||||
// Input note is a tuple of output, note, amount, spending key
|
||||
typedef std::tuple<SaplingOutPoint, SaplingNote, CAmount, SaplingExpandedSpendingKey> SendManyInputSaplingNote;
|
||||
|
||||
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
|
||||
public:
|
||||
@@ -60,6 +54,7 @@ public:
|
||||
std::string fromAddress,
|
||||
std::vector<SendManyRecipient> tOutputs,
|
||||
std::vector<SendManyRecipient> zOutputs,
|
||||
std::vector<SendManyInputSaplingNote> saplingNoteInputs,
|
||||
int minDepth,
|
||||
CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE,
|
||||
UniValue contextInfo = NullUniValue,
|
||||
@@ -96,17 +91,11 @@ private:
|
||||
SpendingKey spendingkey_;
|
||||
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> z_outputs_;
|
||||
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_;
|
||||
CTransaction tx_;
|
||||
@@ -119,6 +108,11 @@ private:
|
||||
bool main_impl();
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
@@ -54,8 +54,9 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
|
||||
std::vector<ShieldCoinbaseUTXO> inputs,
|
||||
std::string toAddress,
|
||||
CAmount fee,
|
||||
uint8_t donation,
|
||||
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
|
||||
|
||||
@@ -67,6 +68,10 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
|
||||
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
|
||||
auto address = DecodePaymentAddress(toAddress);
|
||||
if (IsValidPaymentAddress(address)) {
|
||||
@@ -161,24 +166,7 @@ void AsyncRPCOperation_shieldcoinbase::main() {
|
||||
bool AsyncRPCOperation_shieldcoinbase::main_impl() {
|
||||
|
||||
CAmount minersFee = fee_;
|
||||
|
||||
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));
|
||||
}
|
||||
*/
|
||||
size_t numInputs = inputs_.size();
|
||||
|
||||
CAmount targetAmount = 0;
|
||||
for (ShieldCoinbaseUTXO & utxo : inputs_) {
|
||||
@@ -192,10 +180,10 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() {
|
||||
}
|
||||
|
||||
CAmount sendAmount = targetAmount - minersFee;
|
||||
LogPrint("zrpc", "%s: spending %s to shield %s with fee %s\n",
|
||||
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee));
|
||||
LogPrint("zrpc", "%s: spending %s to shield %s with fee %s, donation=%d\n",
|
||||
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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
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
|
||||
m_op->builder_.SendChangeTo(zaddr, ovk);
|
||||
//TODO: TESTING zaddr only, only use on regtest
|
||||
//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
|
||||
auto maybe_tx = m_op->builder_.Build();
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
std::vector<ShieldCoinbaseUTXO> inputs,
|
||||
std::string toAddress,
|
||||
CAmount fee = SHIELD_COINBASE_DEFAULT_MINERS_FEE,
|
||||
uint8_t donation = 0,
|
||||
UniValue contextInfo = NullUniValue);
|
||||
virtual ~AsyncRPCOperation_shieldcoinbase();
|
||||
|
||||
@@ -63,7 +64,6 @@ public:
|
||||
virtual UniValue getStatus() const;
|
||||
|
||||
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:
|
||||
friend class ShieldToAddress;
|
||||
@@ -74,11 +74,11 @@ private:
|
||||
CAmount fee_;
|
||||
PaymentAddress tozaddr_;
|
||||
|
||||
uint256 joinSplitPubKey_;
|
||||
unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES];
|
||||
|
||||
std::vector<ShieldCoinbaseUTXO> inputs_;
|
||||
|
||||
// this is a donation % between 0 and 10, not a CAmount
|
||||
uint8_t donation_;
|
||||
|
||||
TransactionBuilder builder_;
|
||||
CTransaction tx_;
|
||||
|
||||
@@ -87,7 +87,6 @@ private:
|
||||
void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error
|
||||
|
||||
void lock_utxos();
|
||||
|
||||
void unlock_utxos();
|
||||
};
|
||||
|
||||
@@ -96,15 +95,15 @@ class ShieldToAddress : public boost::static_visitor<bool>
|
||||
private:
|
||||
AsyncRPCOperation_shieldcoinbase *m_op;
|
||||
CAmount sendAmount;
|
||||
uint8_t donation = 0;
|
||||
public:
|
||||
ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount) :
|
||||
m_op(op), sendAmount(sendAmount) {}
|
||||
ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount, uint8_t donation) :
|
||||
m_op(op), sendAmount(sendAmount), donation(donation) {}
|
||||
|
||||
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
|
||||
|
||||
// To test private methods, a friend class can act as a proxy
|
||||
class TEST_FRIEND_AsyncRPCOperation_shieldcoinbase {
|
||||
public:
|
||||
@@ -135,6 +134,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* ASYNCRPCOPERATION_SHIELDCOINBASE_H */
|
||||
|
||||
|
||||
@@ -704,7 +704,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, e.what());
|
||||
}
|
||||
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 clean = SanitizeFilename(unclean);
|
||||
|
||||
@@ -82,9 +82,7 @@ char *uint256_str(char *dest,uint256 txid);
|
||||
// Private method:
|
||||
UniValue z_getoperationstatus_IMPL(const UniValue&, bool);
|
||||
|
||||
#define PLAN_NAME_MAX 8
|
||||
#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())); }
|
||||
#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())); }
|
||||
|
||||
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"
|
||||
+ HelpExampleCli("sendfrom", "\"\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01") +
|
||||
"\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"
|
||||
+ 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 )
|
||||
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);
|
||||
|
||||
std::string strAccount = AccountFromValue(params[0]);
|
||||
CTxDestination dest = DecodeDestination(params[1].get_str());
|
||||
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]);
|
||||
if (nAmount <= 0)
|
||||
@@ -2647,6 +2645,49 @@ UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
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)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
@@ -4083,7 +4124,6 @@ UniValue z_getbalances(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
{
|
||||
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"
|
||||
" \"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"
|
||||
" \"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"
|
||||
" \"amount\": xxxxx, (numeric) the amount of value in the note\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;
|
||||
pwalletMain->GetSaplingIncomingViewingKey(boost::get<libzcash::SaplingPaymentAddress>(entry.address), ivk);
|
||||
pwalletMain->GetSaplingFullViewingKey(ivk, fvk);
|
||||
bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKey(fvk);
|
||||
const bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKey(fvk);
|
||||
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("amount", ValueFromAmount(CAmount(entry.note.value())))); // note.value() is equivalent to plaintext.value()
|
||||
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);
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
fromaddress = vPotentialAddresses[ GetRandInt(nPotentials) ];
|
||||
} 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.");
|
||||
}
|
||||
} else {
|
||||
@@ -5149,6 +5194,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Recipients
|
||||
std::vector<SendManyRecipient> taddrRecipients;
|
||||
std::vector<SendManyRecipient> zaddrRecipients;
|
||||
@@ -5238,6 +5284,38 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
|
||||
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
|
||||
// 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
|
||||
@@ -5290,18 +5368,6 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
|
||||
mtx.nVersion = SAPLING_TX_VERSION;
|
||||
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.
|
||||
// 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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
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);
|
||||
|
||||
if(fZdebug)
|
||||
LogPrintf("%s: Submitted to async queue\n", __FUNCTION__);
|
||||
AsyncRPCOperationId operationId = operation->getId();
|
||||
@@ -5420,9 +5487,9 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() < 2 || params.size() > 4)
|
||||
if (fHelp || params.size() < 2 || params.size() > 5)
|
||||
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"
|
||||
"\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"
|
||||
@@ -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"
|
||||
"3. fee (numeric, optional, default="
|
||||
+ 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"
|
||||
"5. donation (integer, optional, default=0) Percentage of coinbase funds to donate. Must be between 0 and 10 inclusive.\n"
|
||||
"\nResult:\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"
|
||||
" \"shieldingUTXOs\": xxx (numeric) Number 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"
|
||||
" \"shieldingUTXOs\": xxx (integer) Number 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"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
|
||||
+ HelpExampleRpc("z_shieldcoinbase", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
|
||||
+ HelpExampleCli("z_shieldcoinbase", "'*'\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
|
||||
+ HelpExampleRpc("z_shieldcoinbase", "'*'\", \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
|
||||
);
|
||||
|
||||
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;
|
||||
bool overwinterActive = nextBlockHeight>=1 ? true : false; // NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
|
||||
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("toaddress", params[1]));
|
||||
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
|
||||
int blockHeight = chainActive.LastTip()->GetHeight();
|
||||
nextBlockHeight = blockHeight + 1;
|
||||
// (used if no Sapling addresses are involved)
|
||||
CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(
|
||||
Params().GetConsensus(), nextBlockHeight);
|
||||
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
|
||||
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);
|
||||
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("shieldingUTXOs", static_cast<uint64_t>(numUtxos)));
|
||||
o.push_back(Pair("shieldingValue", ValueFromAmount(shieldedValue)));
|
||||
o.push_back(Pair("donation", donation));
|
||||
o.push_back(Pair("opid", operationId));
|
||||
return o;
|
||||
}
|
||||
@@ -5951,7 +6030,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp
|
||||
// Contextual transaction we will build on
|
||||
CMutableTransaction contextualTx; //= CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight);
|
||||
|
||||
// Builder (used if Sapling addresses are involved)
|
||||
// Builder (used if zaddrs are involved)
|
||||
boost::optional<TransactionBuilder> builder;
|
||||
if (isToSaplingZaddr || saplingNoteInputs.size() > 0) {
|
||||
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
|
||||
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
|
||||
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);
|
||||
AsyncRPCOperationId operationId = operation->getId();
|
||||
|
||||
@@ -6186,49 +6265,6 @@ UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
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 convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||
extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk);
|
||||
|
||||
@@ -66,7 +66,6 @@ bool fPayAtLeastCustomFee = true;
|
||||
#include "hush_defs.h"
|
||||
|
||||
CBlockIndex *hush_chainactive(int32_t height);
|
||||
extern std::string DONATION_PUBKEY;
|
||||
extern int32_t HUSH_LOADINGBLOCKS;
|
||||
int32_t hush_dpowconfs(int32_t height,int32_t numconfs);
|
||||
int tx_height( const uint256 &hash );
|
||||
@@ -1840,19 +1839,17 @@ void CWallet::GetSaplingNoteWitnesses(std::vector<SaplingOutPoint> notes,
|
||||
auto noteData = mapWallet[note.hash].mapSaplingNoteData;
|
||||
auto nWitnesses = noteData[note].witnesses.size();
|
||||
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();
|
||||
if (!rt) {
|
||||
//fprintf(stderr,"%s: Setting witness root\n",__func__);
|
||||
rt = witnesses[i]->root();
|
||||
} else {
|
||||
if(*rt == witnesses[i]->root()) {
|
||||
//fprintf(stderr,"%s: rt=%s\n",__func__,rt.GetHash().ToString().c_str());
|
||||
//fprintf(stderr,"%s: witnesses[%d]->root()=%s\n",__func__,i,witnesses[i]->root().GetHash().ToString().c_str());
|
||||
} else {
|
||||
// Something is fucky
|
||||
std::string err = string("CWallet::GetSaplingNoteWitnesses: Invalid witness root! rt=") + rt.get().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());
|
||||
}
|
||||
|
||||
@@ -4587,12 +4584,14 @@ void CWallet::LockNote(const SaplingOutPoint& output)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
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)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
setLockedSaplingNotes.erase(output);
|
||||
fprintf(stderr,"%s: unlocking note %s...\n", __func__, output.hash.ToString().substr(0,8).c_str() );
|
||||
}
|
||||
|
||||
void CWallet::UnlockAllSaplingNotes()
|
||||
@@ -4879,6 +4878,8 @@ void CWallet::GetFilteredNotes(
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
|
||||
LogPrintf("%s ignoreLocked=%d\n", __func__, ignoreLocked);
|
||||
|
||||
for (auto & p : mapWallet) {
|
||||
CWalletTx wtx = p.second;
|
||||
|
||||
@@ -4940,8 +4941,8 @@ void CWallet::GetFilteredNotes(
|
||||
}
|
||||
|
||||
// skip locked notes
|
||||
// TODO: Add locking for Sapling notes -> done
|
||||
if (ignoreLocked && IsLockedNote(op)) {
|
||||
LogPrintf("%s: skipping locked note %s\n", __func__, op.hash.ToString().substr(0,10).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
11
test.sh
Executable file
11
test.sh
Executable 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
|
||||
@@ -125,18 +125,19 @@ eval "$MAKE" --version | head -n2
|
||||
as --version | head -n1
|
||||
as --version | tail -n1
|
||||
ld -v
|
||||
autoconf --version
|
||||
|
||||
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
|
||||
WD=$PWD
|
||||
cd src/cc
|
||||
echo $PWD
|
||||
./makecustom
|
||||
CFLAGS=-std=gnu17 CC=${CC:-gcc} ./makecustom
|
||||
cd $WD
|
||||
|
||||
# Build RandomX
|
||||
@@ -147,9 +148,10 @@ then
|
||||
else
|
||||
mkdir build && cd build
|
||||
cmake -DARCH=native ..
|
||||
make
|
||||
# pass along potential -jX and other args
|
||||
time make "$@"
|
||||
fi
|
||||
|
||||
cd $WD
|
||||
|
||||
"$MAKE" "$@" V=1
|
||||
time "$MAKE" "$@" V=1
|
||||
|
||||
Reference in New Issue
Block a user