Browse Source

Merge branch 'dev'

pull/57/head
Duke Leto 3 years ago
parent
commit
0cc0f2df8c
  1. 3
      autogen.sh
  2. 4
      configure.ac
  3. 6
      doc/man/hush-cli.1
  4. 6
      doc/man/hush-tx.1
  5. 15
      doc/man/hushd.1
  6. 26
      doc/relnotes/README.md
  7. 16
      src/chain.h
  8. 78
      src/chainparams.cpp
  9. 4
      src/clientversion.h
  10. 14
      src/hush-tx.bat
  11. 2
      src/hushd.bat
  12. 20
      src/init.cpp
  13. 157
      src/main.cpp
  14. 110
      src/main.h
  15. 61
      src/miner.cpp
  16. 77
      src/net.cpp
  17. 1
      src/net.h
  18. 3
      src/rpc/blockchain.cpp
  19. 15
      src/rpc/net.cpp
  20. 4
      src/rpc/rawtransaction.cpp
  21. 10
      src/rpc/server.cpp
  22. 10
      src/transaction_builder.cpp
  23. 2
      src/transaction_builder.h
  24. 2
      src/version.h
  25. 12
      src/wallet/asyncrpcoperation_shieldcoinbase.cpp
  26. 8
      src/wallet/rpcdump.cpp
  27. 14
      src/wallet/rpcwallet.cpp
  28. 30
      src/wallet/wallet.cpp
  29. 4
      src/wallet/wallet.h

3
autogen.sh

@ -1,4 +1,7 @@
#!/bin/sh
# Copyright (c) 2016-2021 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
set -e
srcdir="$(dirname $0)"
cd "$srcdir"

4
configure.ac

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

6
doc/man/hush-cli.1

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
.TH HUSH-CLI "1" "April 2021" "hush-cli v3.7.1" "User Commands"
.TH HUSH-CLI "1" "July 2021" "hush-cli v3.8.0" "User Commands"
.SH NAME
hush-cli \- manual page for hush-cli v3.7.1
hush-cli \- manual page for hush-cli v3.8.0
.SH DESCRIPTION
Hush RPC client version v3.7.1\-2da07fe58\-dirty
Hush RPC client version v3.8.0\-10a6706e7\-dirty
.PP
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://hush.is/security/>.

6
doc/man/hush-tx.1

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
.TH HUSH-TX "1" "April 2021" "hush-tx v3.7.1" "User Commands"
.TH HUSH-TX "1" "July 2021" "hush-tx v3.8.0" "User Commands"
.SH NAME
hush-tx \- manual page for hush-tx v3.7.1
hush-tx \- manual page for hush-tx v3.8.0
.SH DESCRIPTION
hush\-tx utility version v3.7.1\-2da07fe58\-dirty
hush\-tx utility version v3.8.0\-10a6706e7\-dirty
.SS "Usage:"
.TP
hush\-tx [options] <hex\-tx> [commands]

15
doc/man/hushd.1

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
.TH HUSHD "1" "April 2021" "hushd v3.7.1" "User Commands"
.TH HUSHD "1" "July 2021" "hushd v3.8.0" "User Commands"
.SH NAME
hushd \- manual page for hushd v3.7.1
hushd \- manual page for hushd v3.8.0
.SH DESCRIPTION
Hush Daemon version v3.7.1\-2da07fe58\-dirty
Hush Daemon version v3.8.0\-10a6706e7\-dirty
.PP
In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://hush.is/security/>.
@ -341,10 +341,19 @@ Minimum fee (in HUSH/kB) to allow for OP_RETURN transactions (default:
.IP
Fee (in HUSH/kB) to add to transactions you send (default: 0.00)
.HP
\fB\-keepnotewitnesscache\fR
.IP
Keep partial Sapling Note Witness cache. Must be used with \fB\-rescanheight\fR
to find missing cache items.
.HP
\fB\-rescan\fR
.IP
Rescan the block chain for missing wallet transactions on startup
.HP
\fB\-rescanheight\fR
.IP
Rescan from specified height when rescan=1 on startup
.HP
\fB\-salvagewallet\fR
.IP
Attempt to recover private keys from a corrupt wallet.dat on startup

26
doc/relnotes/README.md

@ -10,6 +10,32 @@ 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.
# Hush 3.8.0 "XXX YYY"
This is an OPTIONAL release, but since it contains many privacy improvements, it's HIGHLY RECOMMENDED for all users to upgrade.
* New Sietch feature: Randomized change output location
* Zcash and Pirate always put the change as the last shielded output, which leaks metadata. Hush no longer has this metadata leakage.
* This feature improves the `z_sendmany`, `z_mergetoaddress` and `z_shieldtocoinbase` since it's done in the Hush TransactionBuilder.
* New Sietch feature: Sitech-ified `z_shieldcoinbase`
* This RPC now leaks less metadata by making it hard for blockchain analysts to know which of the three outputs has value.
* This also increases Hush's "anonset velocity", which is how fast we increase our anonymity set, or "anonset".
* Previously you could only run `stop` while Hush was in RPC warmup, but now additional RPCs are allowed:
* `stop` - Oops, you started hushd on accident a few seconds ago? Now you can stop it without waiting.
* `help` - Get help during long rescans, finally!
* `z_listaddresses` - See a list of all zaddrs in this wallet, even during a long rescan!
* `z_exportkey` - Export a key from this node, even during rescan!
* `listaddresses` - See a list of taddrs as soon as we load the wallet.
* `dumpprivkey` - Dump the private key of a taddr, even when node isn't fully synced!
* `getpeerinfo` - See current peers even before we get enough peers to start syncing or a long rescan!
* `-keepnotewitnesscache` prevents the Sapling Note Witness cache from being deleted from wallet.dat on shutdown.
* `-rescanheight` can be used with `-keepnotewitnesscache` and `-rescan` to do a partial rescan of history and avoid completely rebuilding the Witness Cache.
* `-zindex` data is now stored on disk in the new `zindex.dat` file
* All nodes that use `-zindex` will now have reliable anonset statistics even after a restart
* Improvements to the RPC help documentation
* `hushd.bat` for Windows now uses the ASN map via `-asmap` and has the latest seed nodes
* `hushd-tx.bat` for Windows now exists for making raw transactions on Windows
# Hush 3.7.1 "Neologistic Nautilus"
```

16
src/chain.h

@ -266,7 +266,7 @@ public:
int64_t nPayments;
//! (memory only) Number of shielded transactions (of any kind) in the block up to and including this block.
//! A shielded transaction is defined as a transaction that contains at least 1 JoinSplit, which includes
//! A shielded transaction is defined as a transaction that contains at least 1 ShieldedInput or ShieldedOutput
//! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as
//! inputs and outputs.
int64_t nShieldedTx;
@ -278,7 +278,7 @@ public:
int64_t nShieldedSpends;
//! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined
//! as a transaction containing JoinSplits and only shielded inputs and outputs, i.e. no transparent
//! as a transaction containing only shielded inputs and outputs, i.e. no transparent
// inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc...
int64_t nFullyShieldedTx;
@ -295,7 +295,7 @@ public:
int64_t nFullyShieldedPayments;
//! (memory only) Number of deshielding transactions. A deshielding transaction is defined
//! as a transaction containing JoinSplits and at least one transparent output.
//! as a transaction containing ShieldedInputs and at least one transparent output.
int64_t nDeshieldingTx;
//! (memory only) Number of deshielding payments. A deshielding payment is defined
@ -303,7 +303,7 @@ public:
int64_t nDeshieldingPayments;
//! (memory only) Number of shielding transactions. A shielding transaction is defined
//! as a transaction containing JoinSplits and at least one transparent input
//! as a transaction containing ShieldedOutputs and at least one transparent input
// i.e. t->z or t->(z,t) or z->(z,z,t)
int64_t nShieldingTx;
@ -322,7 +322,7 @@ public:
int64_t nChainPayments;
//! (memory only) Number of shielded transactions (of any kind) in the chain up to and including this block.
//! A shielded transaction is defined as a transaction that contains at least 1 JoinSplit, which includes
//! A shielded transaction is defined as a transaction that contains at least 1 ShieldedInput or ShieldedOutput
//! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as
//! inputs and outputs.
int64_t nChainShieldedTx;
@ -334,7 +334,7 @@ public:
int64_t nChainShieldedSpends;
//! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined
//! as a transaction containing JoinSplits and only shielded inputs and outputs, i.e. no transparent
//! as a transaction containing and only shielded inputs and outputs, i.e. no transparent
// inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc...
int64_t nChainFullyShieldedTx;
@ -351,7 +351,7 @@ public:
int64_t nChainFullyShieldedPayments;
//! (memory only) Number of deshielding transactions. A deshielding transaction is defined
//! as a transaction containing JoinSplits and at least one transparent output.
//! as a transaction containing ShieldedInputs and at least one transparent output.
int64_t nChainDeshieldingTx;
//! (memory only) Number of deshielding payments. A deshielding payment is defined
@ -359,7 +359,7 @@ public:
int64_t nChainDeshieldingPayments;
//! (memory only) Number of shielding transactions. A shielding transaction is defined
//! as a transaction containing JoinSplits and at least one transparent input
//! as a transaction containing ShieldedOutputs and at least one transparent input
// i.e. t->z or t->(z,t) or z->(z,z,t)
int64_t nChainShieldingTx;

78
src/chainparams.cpp

@ -783,11 +783,79 @@ void *chainparams_commandline() {
(492000, uint256S("0x00000013bbbff98ddab19a3178a0088a20628791e94963e5d1ea635015dfa9c6"))
(493000, uint256S("0x00000001ed829c061ba14f6953e79d99577079adf5526f1e43e6dc9d9f9571bf"))
(494000, uint256S("0x00000018dfeced2d1584a1003fefa4349810239bade096e53b4fa6bbc38a1685"))
(495000, uint256S("0x0000001816af55724cd49c0bfe02c9eac29b4a73db2b7d868b958218a03e6c94"))
(496000, uint256S("0x000000007e2019c5246db5a75122c6826822fa154d68a51eee2ff23f54ec668e")),
(int64_t) 1618760194, // time of last checkpointed block
(int64_t) 842496, // total txs
(double) 1812 // txs in the last day before block 496013
(495000, uint256S("0x0000001816af55724cd49c0bfe02c9eac29b4a73db2b7d868b958218a03e6c94"))
(496000, uint256S("0x000000007e2019c5246db5a75122c6826822fa154d68a51eee2ff23f54ec668e"))
(497000, uint256S("0x0000000aa5803c0825cfa1a34227d0ecb80be191674365a372f71611eacdc742"))
(498000, uint256S("0x000000166385022d4b4ade0921a5f6c7d4aec56257cd679f7c441aeb0552b28c"))
(499000, uint256S("0x0000002ce5e48efb664e936c9551b2781c742416e519d3a023d087036519507b"))
(500000, uint256S("0x0000000cdfe9389bde0e9f1d649dd2f19ee69d765b00907aa681c3cdaad0bdb6"))
(501000, uint256S("0x00000028736fd4ce6995a46d217c0022d2882165b5f716e94f255877c73f474a"))
(502000, uint256S("0x000000459520215ade21db91a83ad47a806320ba3e290d686149bcf5672e132a"))
(503000, uint256S("0x000000086aee5827d0254e1176a4dfd5c8a7958ee1f61458bdb1eb4d6ffbc131"))
(504000, uint256S("0x000000474906b6ad537fe14eca1316c7be23f181bc554a2244c97634a6d361a7"))
(505000, uint256S("0x00000035db569efc139988b7d506529bb482284bf2dfc40060159b321883974d"))
(506000, uint256S("0x0000000c55ddd54e1f0aa6a59abe774f0e14501743c2594184772031f5bf51fd"))
(507000, uint256S("0x000000061ca0ea34d5d3ddd5d8ceb0dcf9a0720483efd98155c0aa3774387e60"))
(508000, uint256S("0x00000004bd6cdfbbee3945b897c4d6b6f49199d788151fe5536417d31d2f36ab"))
(509000, uint256S("0x0000000b73f9dd08528827a8224decf6635462d2adabac9301e5c17b7a24a5f4"))
(510000, uint256S("0x00000004c41a5b61302564abc741195c915fdf9edd12669f93ac5d4443613664"))
(511000, uint256S("0x000000094319bb7199e5697e458520e95639dcec5180d4442e1470f48feaf125"))
(512000, uint256S("0x00000014516f2d52467edd913c52e1742ca8a767debd9294bbbf8f39bdbae506"))
(513000, uint256S("0x000000177739b5379d196b74faeaabf35dbb9d3f6f9e172f659f68b3288a71c3"))
(514000, uint256S("0x0000000940533509d21f249ab0b0144923e65050a24dbf53863c9c07fd21fd6b"))
(515000, uint256S("0x000000007d256fc4cbfff1c05f83550b8dfdf093b060a98fafac6a090e349bc1"))
(516000, uint256S("0x000000029ee7abc14842e22b4f3e7e3c640c55fa2a898773c83ff34ceb2a5482"))
(517000, uint256S("0x00000019ca7705b4a8b35ae1aa4071401ed1de7449306ef8a34716637f43c2f1"))
(518000, uint256S("0x00000013f4aa06fca6c2a57e80c3950d0e7613f3bcba0b52887d4c7579e5b20a"))
(519000, uint256S("0x0000000b7d1e4efbbb38c91e838a50876be93a6549fdaeb534ec1d8657117e69"))
(520000, uint256S("0x00000000c2fb98b56bf9c549406710b57308081663230a477c7b5983720a456a"))
(521000, uint256S("0x0000000d48660709c9fd60f01b71260e0e6ba3875cdb109b7b037ec6b80f3098"))
(522000, uint256S("0x00000019d0ad6bdebc9d39a5b9a6ae4d844b45bbfcdd97885841a1d8033c956f"))
(523000, uint256S("0x000000121da004ec14c89b67151439765a19aadbdf4d4feca701cce7c3820efb"))
(524000, uint256S("0x00000003d3445c4cb6e980751cd8119679d572f57bbaa3b9c9114e397841827e"))
(525000, uint256S("0x0000000b2a079f083c86f9ab8b0f73dc511c20f6aa44d7735f29409df966f026"))
(526000, uint256S("0x00000004d3ae427a98336ee4bc5e60f00ebd4c88f9ffdd18003f17535465888a"))
(527000, uint256S("0x000000057e5cb13f42332f59b6c2d6f333369b8e4d9bdf6fa9bb441e2ddb5c51"))
(528000, uint256S("0x000000045f51825c19aab9d1d620d7073c2114ccf3e40f63d66c729c71c2bc05"))
(529000, uint256S("0x000000116ac2795cdbde2d3af6d804d9dbf445d2ed12d7cf13c155540f10c119"))
(530000, uint256S("0x0000000be4932b469923d826991810109f2c2ca50d5fa0133c765b5ab96bf315"))
(531000, uint256S("0x0000000a7fdd8ce073da5d95fcbefba5d0366c9b834cac914889108094d0cd18"))
(532000, uint256S("0x0000000600d2ea28f32220c054e2ae66ec8471a2f755ef219a0c81e4a4296135"))
(533000, uint256S("0x0000000a5f4a460970f6dcd3a271315f936648c854c1a7bb251dbc7996f90e92"))
(534000, uint256S("0x00000009b5d0615eb98f06820cc6d66af542b8bbde0cabe5b54b6e7625e77803"))
(535000, uint256S("0x0000000ac06f5d79b927f2dfb54eecd72f9ada28fa59092f5c3c83627b281605"))
(536000, uint256S("0x000000037a51adb2cccf29b9c164386c8418959db16606b70a1389fb8755829f"))
(537000, uint256S("0x0000000a129157792e233e233f85693625abb14be90362ff727ab97e8d5ec340"))
(538000, uint256S("0x00000015e13085045c090a51e9c1114749fa7b465009f2ad70ff278d9ae05b5c"))
(539000, uint256S("0x00000001953384069e477f7e1839dc0498cbeb951adb32bcbf3b96ef487fce4a"))
(540000, uint256S("0x0000000281246b5d2e845aa711b6af76c8cc0d1f39ba25fe414f83bbe47544bb"))
(541000, uint256S("0x0000000f27b777a942d6317438836258c4e34bd3761736a2b32cc2b7c8305d71"))
(542000, uint256S("0x00000005d4667fb45a862d91ba843acbaee033915bf75536c67aeca1a2a3a5ff"))
(543000, uint256S("0x0000000509b08619049b1aec8e715d971b8dbc2175acf7874a37b9ce13dfb137"))
(544000, uint256S("0x0000000582563d79bf72a925ae3bc5c6f0eacbdb317c92fa89eb56d570427fd7"))
(545000, uint256S("0x0000000ff9df3d3a00d682f069819acbc5697b42da69a78f6e07486ac68f0e49"))
(546000, uint256S("0x00000004653460c603fa7a70292a85e286272b587f0b9cea7e73b765e8b0ef7b"))
(547000, uint256S("0x000000074c5f411190c5bf788a37a00506935015df4872cc5471416abadb757d"))
(548000, uint256S("0x00000005444a4ecd1eea940ad5395f2f7839967ee5b01be4a9b68755de4395ac"))
(549000, uint256S("0x0000000216eafee0e40374b8e8db63118cb4e3adc3159068bdafff1f0e0d9deb"))
(550000, uint256S("0x0000000056b84bc88604b9df668b60c020a6926b2dfdcd09955e5d8d3e7a5ca7"))
(551000, uint256S("0x0000000adaaeb79c5c6c49038d7206f88d5b4ecaaf21aaca09b5a7d548f76b25"))
(552000, uint256S("0x00000004185669b566e62cbebc9c50930c8ae0d5c42f23280262a7f55b726553"))
(553000, uint256S("0x00000010112434cdb0203a053e0c22ef16b9d39b8feed2328d7ff97013b216be"))
(554000, uint256S("0x00000006dacee96c0f48fc7250c71cc1e746befa84af8cd2ed0499d8d24cc6cb"))
(555000, uint256S("0x00000001b3b2c149029d5a2e7cedb0683c97692a52cbc91bb532cb78bbcadcc0"))
(556000, uint256S("0x0000000397bdd61939cc3d2c39360c5e3713ef9dd82b8cedac17075b8e177304"))
(557000, uint256S("0x0000000414bb81b82a2e71608086ac585dba19ca249067c9e967d6f44a1d3163"))
(558000, uint256S("0x00000003516d27423b1b5b60eab97d425e7be3f08f14bafd935666b1e955608e"))
(559000, uint256S("0x00000005c44ef4543da5924e65f0fd2d2c8fe926b2f3995b83ccfd1463b443d7"))
(560000, uint256S("0x00000002eb33454ba48e61a50351686115c47cb59b8fb0496432ad58e0484acf"))
(561000, uint256S("0x00000004172d5940c07ec6d493e410fbab8a05dc73e350505e1540d7336eb353"))
(562000, uint256S("0x00000000d9caaf66ad7782046886d3bfdf966c0a015dbae64042cd0c35e516e4"))
(563000, uint256S("0x000000000d953e53c65145bfb41ba544a9ce9e5432c9ed8eabd39873dfcb8ab0"))
(564000, uint256S("0x0000000d49258678c42bc2ea6f9e5d1206c578da8dc564d1a6114ce68bf77817")),
(int64_t) 1623979514, // time of last checkpointed block
(int64_t) 922687, // total txs
(double) 1219 // txs in the last day before block 564690
};
} else {

4
src/clientversion.h

@ -29,8 +29,8 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
// Must be kept in sync with configure.ac , ugh!
#define CLIENT_VERSION_MAJOR 3
#define CLIENT_VERSION_MINOR 7
#define CLIENT_VERSION_REVISION 1
#define CLIENT_VERSION_MINOR 8
#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_BUILD 50
//! Set to true for release, false for prerelease or test build

14
src/hush-tx.bat

@ -0,0 +1,14 @@
@call :GET_CURRENT_DIR
@cd %THIS_DIR%
komodo-tx.exe -ac_name=HUSH3 %1 %2 %3 %4 %5 %6 %7 %8 %9
@goto :EOF
:GET_CURRENT_DIR
@pushd %~dp0
@set THIS_DIR=%CD%
@popd
@goto :EOF

2
src/hushd.bat

@ -1,6 +1,6 @@
@call :GET_CURRENT_DIR
@cd %THIS_DIR%
komodod.exe -ac_name=HUSH3 -ac_sapling=1 -ac_reward=0,1125000000,562500000 -ac_halving=129,340000,840000 -ac_end=128,340000,5422111 -ac_eras=3 -ac_blocktime=150 -ac_cc=2 -ac_ccenable=228,234,235,236,241 -ac_founders=1 -ac_supply=6178674 -ac_perc=11111111 -clientname=GoldenSandtrout -addnode=64.120.113.130 -addnode=209.58.144.205 -addnode=94.130.35.94 -addnode=188.165.212.101 -ac_cclib=hush3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac -daemon %1 %2 %3 %4 %5 %6 %7 %8 %9
komodod.exe -ac_name=HUSH3 -ac_sapling=1 -ac_reward=0,1125000000,562500000 -ac_halving=129,340000,840000 -ac_end=128,340000,5422111 -ac_eras=3 -ac_blocktime=150 -ac_cc=2 -ac_ccenable=228,234,235,236,241 -ac_founders=1 -ac_supply=6178674 -ac_perc=11111111 -clientname=GoldenSandtrout -asmap -addnode=node1.hush.is -addnode=node2.hush.is -addnode=node3.hush.is -addnode=node4.hush.is -addnode=node5.hush.is -addnode=node6.hush.is -addnode=node7.hush.is -addnode=node8.hush.is -ac_cclib=hush3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac -daemon %1 %2 %3 %4 %5 %6 %7 %8 %9
@goto :EOF
:GET_CURRENT_DIR

20
src/init.cpp

@ -466,7 +466,11 @@ std::string HelpMessage(HelpMessageMode mode)
CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-opretmintxfee=<amt>", strprintf(_("Minimum fee (in %s/kB) to allow for OP_RETURN transactions (default: %s)"), CURRENCY_UNIT, 400000 ));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
// If this is used incorrectly (-rescanheight too large), then the local wallet may attempt to spend funds which it does not have witness data about
// which will cause a "missing inputs" error when added to the mempool. Rescanning from correct height will fix this.
strUsage += HelpMessageOpt("-keepnotewitnesscache", _("Keep partial Sapling Note Witness cache. Must be used with -rescanheight to find missing cache items."));
strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup"));
strUsage += HelpMessageOpt("-rescanheight", _("Rescan from specified height when rescan=1 on startup"));
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup"));
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0));
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1));
@ -2072,8 +2076,22 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
CBlockIndex *pindexRescan = chainActive.Tip();
if (clearWitnessCaches || GetBoolArg("-rescan", false))
{
pwalletMain->ClearNoteWitnessCache();
int rescanHeight = GetArg("-rescanheight", 0);
// Must be used with -rescanheight
if( GetBoolArg("-keepnotewitnesscache", false) && rescanHeight > 0 ) {
LogPrintf("%s: keeping NoteWitnessCache with rescan height=%d\n", __func__, rescanHeight);
} else {
pwalletMain->ClearNoteWitnessCache();
}
pindexRescan = chainActive.Genesis();
if (rescanHeight > 0) {
if (rescanHeight > chainActive.Tip()->GetHeight()) {
pindexRescan = chainActive.Tip();
} else {
pindexRescan = chainActive[rescanHeight];
}
}
} else {
CWalletDB walletdb(strWalletFile);
CBlockLocator locator;

157
src/main.cpp

@ -76,6 +76,7 @@ using namespace std;
CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t HUSH_LOADINGBLOCKS,HUSH_LONGESTCHAIN,HUSH_INSYNC,HUSH_CONNECTING,HUSH_EXTRASATOSHI;
extern CZindexStats zstats;
int32_t HUSH_NEWBLOCKS;
int32_t hush_block2pubkey33(uint8_t *pubkey33,CBlock *block);
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
@ -572,6 +573,102 @@ namespace {
} // anon namespace
// CZindexDB
CZindexDB::CZindexDB()
{
pathAddr = GetDataDir() / "zindex.dat";
}
bool CZindexDB::Read(CZindexStats& zstats)
{
// open input file, and associate with CAutoFile
FILE *file = fopen(pathAddr.string().c_str(), "rb");
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
if (filein.IsNull())
return error("%s: Failed to open file %s", __func__, pathAddr.string());
// use file size to size memory buffer
int fileSize = boost::filesystem::file_size(pathAddr);
int dataSize = fileSize - sizeof(uint256);
// Don't try to resize to a negative number if file is small
if (dataSize < 0)
dataSize = 0;
vector<unsigned char> vchData;
vchData.resize(dataSize);
uint256 hashIn;
// read data and checksum from file
try {
filein.read((char *)&vchData[0], dataSize);
filein >> hashIn;
}
catch (const std::exception& e) {
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
filein.fclose();
CDataStream ssZstats(vchData, SER_DISK, CLIENT_VERSION);
// verify stored checksum matches input data
uint256 hashTmp = Hash(ssZstats.begin(), ssZstats.end());
if (hashIn != hashTmp)
return error("%s: zstats Checksum mismatch, data corrupted", __func__);
unsigned char pchMsgTmp[4];
try {
// de-serialize file header (network specific magic number) and ..
ssZstats >> FLATDATA(pchMsgTmp);
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
return error("%s: Invalid network magic number", __func__);
// de-serialize data into one CZindexStats object
ssZstats >> zstats;
} catch (const std::exception& e) {
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
return true;
}
bool CZindexDB::Write(const CZindexStats& zstats)
{
// Generate random temporary filename
unsigned short randv = 0;
GetRandBytes((unsigned char*)&randv, sizeof(randv));
std::string tmpfn = strprintf("zindex.dat.%04x", randv);
// serialize zstats, checksum data up to that point, then append checksum
CDataStream ssZstats(SER_DISK, CLIENT_VERSION);
ssZstats << FLATDATA(Params().MessageStart());
ssZstats << zstats;
uint256 hash = Hash(ssZstats.begin(), ssZstats.end());
ssZstats << hash;
// open temp output file, and associate with CAutoFile
boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
FILE *file = fopen(pathTmp.string().c_str(), "wb");
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
if (fileout.IsNull())
return error("%s: Failed to open file %s", __func__, pathTmp.string());
// Write and commit header, data
try {
fileout << ssZstats;
} catch (const std::exception& e) {
return error("%s: Serialize or I/O error - %s", __func__, e.what());
}
FileCommit(fileout.Get());
fileout.fclose();
// replace existing zindex.dat, if any, with new zindex.dat.XXXX
if (!RenameOver(pathTmp, pathAddr))
return error("%s: Rename-into-place failed", __func__);
return true;
}
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
LOCK(cs_main);
CNodeState *state = State(nodeid);
@ -3928,7 +4025,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
if ( HUSH_LONGESTCHAIN != 0 && (pindexNew->GetHeight() == HUSH_LONGESTCHAIN || pindexNew->GetHeight() == HUSH_LONGESTCHAIN+1) )
if ( HUSH_LONGESTCHAIN != 0 && (pindexNew->GetHeight() >= HUSH_LONGESTCHAIN ))
HUSH_INSYNC = (int32_t)pindexNew->GetHeight();
else HUSH_INSYNC = 0;
//fprintf(stderr,"connect.%d insync.%d ASSETCHAINS_SAPLING.%d\n",(int32_t)pindexNew->GetHeight(),HUSH_INSYNC,ASSETCHAINS_SAPLING);
@ -4429,13 +4526,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
// pool. So we invert the sign here.
saplingValue += -tx.valueBalance;
/*
for (auto js : tx.vjoinsplit) {
sproutValue += js.vpub_old;
sproutValue -= js.vpub_new;
}
*/
// Ignore following stats unless -zindex enabled
if (!fZindex)
continue;
@ -4560,6 +4650,39 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
if (fZdebug) {
//fprintf(stderr,"%s: setting blockchain zstats with zspends=%d, zouts=%d\n", __FUNCTION__, nShieldedSpendsInBlock, nShieldedOutputsInBlock );
}
if (pindex->pprev) {
// If chain stats are zero (such as after restart), load data from zindex.dat
if (pindex->pprev->nChainNotarizations == 0)
pindex->pprev->nChainNotarizations = zstats.nChainNotarizations;
if (pindex->pprev->nChainShieldedTx == 0)
pindex->pprev->nChainShieldedTx = zstats.nChainShieldedTx;
if (pindex->pprev->nChainShieldedOutputs == 0)
pindex->pprev->nChainShieldedOutputs = zstats.nChainShieldedOutputs;
if (pindex->pprev->nChainShieldedSpends == 0) {
pindex->pprev->nChainShieldedSpends = zstats.nChainShieldedSpends;
// TODO: if zstats.nHeight != chainActive.Height() the stats will be off
fprintf(stderr, "%s: loaded anonymity set of %li at stats height=%li vs local height=%d from disk\n", __func__, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends, zstats.nHeight, chainActive.Height() );
}
if (pindex->pprev->nChainFullyShieldedTx == 0)
pindex->pprev->nChainFullyShieldedTx = zstats.nChainFullyShieldedTx;
if (pindex->pprev->nChainShieldingTx == 0)
pindex->pprev->nChainShieldingTx = zstats.nChainShieldingTx;
if (pindex->pprev->nChainDeshieldingTx == 0)
pindex->pprev->nChainDeshieldingTx = zstats.nChainDeshieldingTx;
if (pindex->pprev->nChainPayments == 0) {
fprintf(stderr, "%s: setting nChainPayments=%li at height %d\n", __func__, zstats.nChainPayments, chainActive.Height() );
pindex->pprev->nChainPayments = zstats.nChainPayments;
}
if (pindex->pprev->nChainShieldedPayments == 0)
pindex->pprev->nChainShieldedPayments = zstats.nChainShieldedPayments;
if (pindex->pprev->nChainFullyShieldedPayments == 0)
pindex->pprev->nChainFullyShieldedPayments = zstats.nChainFullyShieldedPayments;
if (pindex->pprev->nChainShieldingPayments == 0)
pindex->pprev->nChainShieldingPayments = zstats.nChainShieldingPayments;
if (pindex->pprev->nChainDeshieldingPayments == 0)
pindex->pprev->nChainDeshieldingPayments = zstats.nChainDeshieldingPayments;
}
pindex->nChainNotarizations = (pindex->pprev ? pindex->pprev->nChainNotarizations : 0) + pindex->nNotarizations;
pindex->nChainShieldedTx = (pindex->pprev ? pindex->pprev->nChainShieldedTx : 0) + pindex->nShieldedTx;
pindex->nChainShieldedOutputs = (pindex->pprev ? pindex->pprev->nChainShieldedOutputs : 0) + pindex->nShieldedOutputs;
@ -4572,6 +4695,23 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
pindex->nChainFullyShieldedPayments = (pindex->pprev ? pindex->pprev->nChainFullyShieldedPayments : 0) + pindex->nFullyShieldedPayments;
pindex->nChainShieldingPayments = (pindex->pprev ? pindex->pprev->nChainShieldingPayments : 0) + pindex->nShieldingPayments;
pindex->nChainDeshieldingPayments = (pindex->pprev ? pindex->pprev->nChainDeshieldingPayments : 0) + pindex->nDeshieldingPayments;
// Update in-memory structure that gets serialized to zindex.dat
zstats.nHeight = pindex->GetHeight();
zstats.nChainNotarizations = pindex->nChainNotarizations ;
zstats.nChainShieldedTx = pindex->nChainShieldedTx ;
zstats.nChainShieldedOutputs = pindex->nChainShieldedOutputs ;
zstats.nChainShieldedSpends = pindex->nChainShieldedSpends ;
zstats.nChainFullyShieldedTx = pindex->nChainFullyShieldedTx ;
zstats.nChainShieldingTx = pindex->nChainShieldingTx ;
zstats.nChainDeshieldingTx = pindex->nChainDeshieldingTx ;
zstats.nChainPayments = pindex->nChainPayments ;
zstats.nChainShieldedPayments = pindex->nChainShieldedPayments ;
zstats.nChainFullyShieldedPayments = pindex->nChainFullyShieldedPayments ;
zstats.nChainShieldingPayments = pindex->nChainShieldingPayments ;
zstats.nChainDeshieldingPayments = pindex->nChainDeshieldingPayments ;
fprintf(stderr,"%s: setting zstats with height,zouts,zspends,anonset=%li,%li,%li,%li\n", __FUNCTION__, zstats.nHeight, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends);
}
if (pindex->pprev) {
@ -4610,6 +4750,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
}
}
if (fZindex)
fprintf(stderr, "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, ShieldedOutputs=%d, FullyShieldedTx=%d, ntz=%d\n",
pindexNew->GetHeight(), nShieldedPayments, nShieldedTx, nShieldedOutputs, nFullyShieldedTx, nNotarizations );

110
src/main.h

@ -950,4 +950,114 @@ std::pair<std::map<CBlockIndex*, std::list<CTransaction>>, uint64_t> DrainRecent
void SetChainNotifiedSequence(uint64_t recentlyConflictedSequence);
bool ChainIsFullyNotified();
class CZindexStats
{
//private:
public:
int64_t nHeight;
int64_t nChainTx;
int64_t nChainNotarizations;
int64_t nChainPayments;
int64_t nChainShieldedTx;
int64_t nChainShieldedOutputs;
int64_t nChainShieldedSpends;
int64_t nChainFullyShieldedTx;
int64_t nChainShieldingPayments;
int64_t nChainShieldedPayments;
int64_t nChainFullyShieldedPayments;
int64_t nChainDeshieldingTx;
int64_t nChainDeshieldingPayments;
int64_t nChainShieldingTx;
size_t Height() const
{
return nHeight;
}
void Clear()
{
LOCK(cs_main);
nChainTx=0;
nChainNotarizations=0;
nChainPayments=0;
nChainShieldedTx=0;
nChainShieldedOutputs=0;
nChainShieldedSpends=0;
nChainFullyShieldedTx=0;
nChainShieldingPayments=0;
nChainShieldedPayments=0;
nChainFullyShieldedPayments=0;
nChainDeshieldingTx=0;
nChainDeshieldingPayments=0;
nChainShieldingTx=0;
}
CZindexStats()
{
Clear();
}
~CZindexStats()
{
}
template<typename Stream> void Serialize(Stream &s) const
{
LOCK(cs_main);
// So we can detect a new version and force a rescan
unsigned char nVersion = 1;
s << nVersion;
s << nHeight;
s << nChainTx;
s << nChainNotarizations;
s << nChainPayments;
s << nChainShieldedTx;
s << nChainShieldedOutputs;
s << nChainShieldedSpends;
s << nChainFullyShieldedTx;
s << nChainShieldingPayments;
s << nChainShieldedPayments;
s << nChainFullyShieldedPayments;
s << nChainDeshieldingTx;
s << nChainDeshieldingPayments;
s << nChainShieldingTx;
}
template<typename Stream> void Unserialize(Stream& s)
{
LOCK(cs_main);
Clear();
unsigned char nVersion;
s >> nVersion;
s >> nHeight;
s >> nChainTx;
s >> nChainNotarizations;
s >> nChainPayments;
s >> nChainShieldedTx;
s >> nChainShieldedOutputs;
s >> nChainShieldedSpends;
s >> nChainFullyShieldedTx;
s >> nChainShieldingPayments;
s >> nChainShieldedPayments;
s >> nChainFullyShieldedPayments;
s >> nChainDeshieldingTx;
s >> nChainDeshieldingPayments;
s >> nChainShieldingTx;
}
};
// Wrapper for zindex.dat stats
class CZindexDB
{
private:
boost::filesystem::path pathAddr;
public:
CZindexDB();
bool Write(const CZindexStats& zstats);
bool Read(CZindexStats& zstats);
};
#endif // HUSH_MAIN_H

61
src/miner.cpp

@ -210,10 +210,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
// Collect memory pool transactions into the block
CAmount nFees = 0;
// we will attempt to spend any cheats we see
CTransaction cheatTx;
boost::optional<CTransaction> cheatSpend;
uint256 cbHash;
boost::this_thread::interruption_point(); // exit thread before entering locks.
@ -861,19 +857,26 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight,
scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG;
} else {
{
if (!reservekey.GetReservedKey(pubkey))
{
return NULL;
}
scriptPubKey.resize(35);
ptr = (uint8_t *)pubkey.begin();
scriptPubKey[0] = 33;
for (i=0; i<33; i++) {
scriptPubKey[i+1] = ptr[i];
}
scriptPubKey[34] = OP_CHECKSIG;
}
}
// Support mining with -disablewallet and minetolocalwallet=0
if (!GetBoolArg("-disablewallet", false)) {
// wallet enabled
if (!reservekey.GetReservedKey(pubkey))
return NULL;
scriptPubKey.clear();
scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
} else {
// wallet disabled
CTxDestination dest = DecodeDestination(GetArg("-mineraddress", ""));
if (IsValidDestination(dest)) {
// CKeyID keyID = boost::get<CKeyID>(dest);
// scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
scriptPubKey = GetScriptForDestination(dest);
} else {
return NULL;
}
}
}
}
return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake);
}
@ -895,29 +898,6 @@ void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,st
}
}
void komodo_broadcast(CBlock *pblock,int32_t limit)
{
if (IsInitialBlockDownload())
return;
int32_t n = 1;
//fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if ( pnode->hSocket == INVALID_SOCKET )
continue;
if ( (rand() % n) == 0 )
{
pnode->PushMessage("block", *pblock);
if ( n++ > limit )
break;
}
}
}
//fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
}
static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
#else
static bool ProcessBlockFound(CBlock* pblock)
@ -972,7 +952,6 @@ static bool ProcessBlockFound(CBlock* pblock)
return error("HushMiner: ProcessNewBlock, block not accepted");
TrackMinedBlock(pblock->GetHash());
//komodo_broadcast(pblock,16);
return true;
}

77
src/net.cpp

@ -48,6 +48,11 @@ using namespace hush;
// Satoshi originally used 10 seconds(!), did they know something Peter Wuille didn't?
#define DUMP_ADDRESSES_INTERVAL 300
// This is every 2 blocks, on avg, on HUSH3
#define DUMP_ZINDEX_INTERVAL 150
#define CHECK_PLZ_STOP_INTERVAL 120
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
#endif
@ -89,10 +94,10 @@ namespace {
};
}
// Global state variables
extern uint16_t ASSETCHAINS_P2PPORT;
extern char SMART_CHAIN_SYMBOL[65];
bool fDiscover = true;
bool fListen = true;
uint64_t nLocalServices = NODE_NETWORK | NODE_NSPV;
@ -103,11 +108,14 @@ static CNode* pnodeLocalHost = NULL;
uint64_t nLocalHostNonce = 0;
static std::vector<ListenSocket> vhListenSocket;
CAddrMan addrman;
CZindexStats zstats;
int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
bool fAddressesInitialized = false;
std::string strSubVersion;
TLSManager tlsmanager = TLSManager();
extern void StartShutdown();
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
map<CInv, CDataStream> mapRelay;
@ -1400,6 +1408,28 @@ void DumpAddresses()
LogPrint("net", "Flushed %d addresses to peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart);
}
void DumpZindexStats()
{
int64_t nStart = GetTimeMillis();
CZindexDB zdb;
zdb.Write(zstats);
LogPrintf("Flushed stats at height %li to zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart);
}
void CheckIfWeShouldStop()
{
// If the RPC interface is "stuck", such as filling up with deadlocks
// and cannot process any more requests, the only option was to kill the full node.
// This is a disk-based method where a node can realize it should stop, and which
// can help avoid extremely long rescans
if(boost::filesystem::exists(GetDataDir() / "plz_stop")) {
LogPrintf("%s: Found plz_stop file, shutting down...\n", __func__);
StartShutdown();
}
}
void static ProcessOneShot()
{
string strDest;
@ -1909,8 +1939,40 @@ void static Discover(boost::thread_group& threadGroup)
#endif
}
//extern CWallet pwalletMain;
void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
{
CheckIfWeShouldStop();
if (fZindex) {
uiInterface.InitMessage(_("Loading zindex stats..."));
int64_t nStart = GetTimeMillis();
{
CZindexDB zdb;
if (!zdb.Read(zstats)) {
// The first time nodes use zindex.dat code, no file will be found
// TODO: rescan if invalid only
LogPrintf("Invalid or missing zindex.dat! Generating new...\n");
//bool update = true;
//pwalletMain->ScanForWalletTransactions(chainActive.Genesis(),update);
// We assume this is the first startup with zindex.dat code, and serialize current data to disk.
DumpZindexStats();
// Now read-in the stats we just wrote to disk to memory
if(!zdb.Read(zstats)) {
LogPrintf("Invalid or missing zindex.dat! Stats may be corrupt\n");
} else {
LogPrintf("Loaded stats at height %li from zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart);
}
} else {
LogPrintf("Loaded stats at height %li from zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart);
}
}
}
uiInterface.InitMessage(_("Loading addresses..."));
// Load addresses for peers.dat
int64_t nStart = GetTimeMillis();
@ -1919,8 +1981,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!adb.Read(addrman))
LogPrintf("Invalid or missing peers.dat! This can happen when upgrading. Whatevz, recreating\n");
}
LogPrintf("Loaded %i addresses from peers.dat %dms\n",
addrman.size(), GetTimeMillis() - nStart);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart);
fAddressesInitialized = true;
if (semOutbound == NULL) {
@ -1968,6 +2029,13 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
// Dump network addresses
scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL);
// Dump zindex stats if -zindex is enabled
if (fZindex) {
scheduler.scheduleEvery(&DumpZindexStats, DUMP_ZINDEX_INTERVAL);
}
scheduler.scheduleEvery(&CheckIfWeShouldStop, CHECK_PLZ_STOP_INTERVAL);
}
bool StopNode()
@ -1977,6 +2045,9 @@ bool StopNode()
for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++)
semOutbound->post();
// persist current zindex stats to disk before we exit
DumpZindexStats();
if (HUSH_NSPV_FULLNODE && fAddressesInitialized)
{
DumpAddresses();

1
src/net.h

@ -223,6 +223,7 @@ public:
int nStartingHeight;
uint64_t nSendBytes;
uint64_t nRecvBytes;
bool fRelayTxes;
bool fAllowlisted; // If true this node bypasses DoS ban limits
bool fFeeler; // If true this node is being used as a short lived feeler.
double dPingTime;

3
src/rpc/blockchain.cpp

@ -1660,10 +1660,12 @@ UniValue getchaintxstats(const UniValue& params, bool fHelp, const CPubKey& mypk
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1");
}
}
LogPrintf("%s: blockcount = %d\n", __func__, blockcount);
const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->GetHeight() - blockcount);
int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast();
int nTxDiff = pindex->nChainTx - pindexPast->nChainTx;
LogPrintf("%s: pindexPast.height = %d, pindex.height = %d\n", __func__, pindexPast->GetHeight(), pindex->GetHeight() );
UniValue ret(UniValue::VOBJ);
ret.pushKV("time", (int64_t)pindex->nTime);
@ -1695,6 +1697,7 @@ UniValue getchaintxstats(const UniValue& params, bool fHelp, const CPubKey& mypk
ret.pushKV("window_tx_count", nTxDiff);
ret.pushKV("window_interval", nTimeDiff);
int64_t nPaymentsDiff = pindex->nChainPayments - pindexPast->nChainPayments;
LogPrintf("%s: pindexPast.nChainPayments = %d, pindex.nChainPayments = %d\n", __func__, pindexPast->nChainPayments, pindex->nChainPayments );
int64_t nShieldedTxDiff = pindex->nChainShieldedTx - pindexPast->nChainShieldedTx;
int64_t nShieldingTxDiff = pindex->nChainShieldingTx - pindexPast->nChainShieldingTx;
int64_t nDeshieldingTxDiff = pindex->nChainDeshieldingTx - pindexPast->nChainDeshieldingTx;

15
src/rpc/net.cpp

@ -95,6 +95,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
" \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
" \"bytessent\": n, (numeric) The total bytes sent\n"
" \"bytesrecv\": n, (numeric) The total bytes received\n"
" \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n"
" \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"timeoffset\": ttt, (numeric) The time offset in seconds (deprecated, always 0)\n"
" \"pingtime\": n, (numeric) ping time\n"
@ -146,6 +147,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
obj.push_back(Pair("lastrecv", stats.nLastRecv));
obj.push_back(Pair("bytessent", stats.nSendBytes));
obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
obj.push_back(Pair("relaytxes", stats.fRelayTxes));
obj.push_back(Pair("conntime", stats.nTimeConnected));
obj.push_back(Pair("timeoffset", 0));
obj.push_back(Pair("pingtime", stats.dPingTime));
@ -177,15 +180,15 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
}
int32_t HUSH_LONGESTCHAIN;
static int32_t hush_longest_depth = 0;
int32_t hush_longestchain()
{
static int32_t depth;
int32_t ht,n=0,num=0,maxheight=0,height = 0;
if ( depth < 0 )
depth = 0;
if ( depth == 0 )
if ( hush_longest_depth < 0 )
hush_longest_depth = 0;
if ( hush_longest_depth == 0 )
{
depth++;
hush_longest_depth++;
vector<CNodeStats> vstats;
{
//LOCK(cs_main);
@ -212,7 +215,7 @@ int32_t hush_longestchain()
if ( ht > height )
height = ht;
}
depth--;
hush_longest_depth--;
if ( num > (n >> 1) )
{
if ( 0 && height != HUSH_LONGESTCHAIN )

4
src/rpc/rawtransaction.cpp

@ -646,7 +646,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey&
" ]\n"
"2. \"outputs\" (object, required) a json object with outputs\n"
" {\n"
" \"address\": x.xxx, (numeric or string, required) The key is the komodo address or script (in hex), the numeric value (can be string) is the " + CURRENCY_UNIT + " amount\n"
" \"address\": x.xxx, (numeric or string, required) The key is the HUSH address or script (in hex), the numeric value (can be string) is the " + CURRENCY_UNIT + " amount\n"
" \"data\": \"hex\" (string, required) The key is \"data\", the value is hex encoded data\n"
" ,...\n"
" }\n"
@ -821,7 +821,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey&
" \"reqSigs\" : n, (numeric) The required sigs\n"
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
" \"addresses\" : [ (json array of string)\n"
" \"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\" (string) komodo address\n"
" \"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\" (string) HUSH address\n"
" ,...\n"
" ]\n"
" }\n"

10
src/rpc/server.cpp

@ -825,9 +825,13 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue &params
{
LOCK(cs_rpcWarmup);
if (fRPCInWarmup) {
// hush-cli stop is the only valid RPC command during warmup
// We don't know if we have valid blocks or wallet yet, nothing else is safe
if (pcmd->name != "stop") {
// Most RPCs are unsafe to run during warmup, but stop+help are fine
// Others may not have data loaded yet, such as wallet details, but
// those RPCs are written defensively to deal with that. Allowing these
// few RPCs means we can see our addresses and make private key backups
// while a very long wallet rescan is happening
if (pcmd->name != "stop" && pcmd->name != "help" && pcmd->name != "z_listaddresses" && pcmd->name != "z_exportkey" &&
pcmd->name != "listaddresses" && pcmd->name != "dumpprivkey" && pcmd->name != "getpeerinfo" ) {
throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
}
}

10
src/transaction_builder.cpp

@ -59,6 +59,13 @@ void TransactionBuilder::AddSaplingOutput(
mtx.valueBalance -= value;
}
// randomize the order of outputs
void TransactionBuilder::ShuffleOutputs()
{
LogPrintf("%s: Shuffling %d zouts\n", __func__, outputs.size() );
random_shuffle( outputs.begin(), outputs.end(), GetRandInt );
}
void TransactionBuilder::AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value, uint32_t _nSequence)
{
if (keystore == nullptr) {
@ -212,6 +219,9 @@ boost::optional<CTransaction> TransactionBuilder::Build()
mtx.vShieldedSpend.push_back(sdesc);
}
// Prevent leaking metadata about the position of change output
ShuffleOutputs();
// Create Sapling OutputDescriptions
for (auto output : outputs) {
auto cm = output.note.cm();

2
src/transaction_builder.h

@ -92,6 +92,8 @@ public:
CAmount value,
std::array<unsigned char, HUSH_MEMO_SIZE> memo = {{0}});
void ShuffleOutputs();
// Assumes that the value correctly corresponds to the provided UTXO.
void AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value, uint32_t nSequence = 0xffffffff);

2
src/version.h

@ -21,7 +21,7 @@
#define HUSH_VERSION_H
// network protocol versioning
static const int PROTOCOL_VERSION = 1987422;
static const int PROTOCOL_VERSION = 1987423;
//! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
//! In this version, 'getheaders' was introduced.

12
src/wallet/asyncrpcoperation_shieldcoinbase.cpp

@ -46,6 +46,7 @@
using namespace libzcash;
extern uint64_t ASSETCHAINS_TIMELOCKGTE;
extern string randomSietchZaddr();
AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
TransactionBuilder builder,
@ -229,6 +230,17 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c
// 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);
// Build the transaction
auto maybe_tx = m_op->builder_.Build();
if (!maybe_tx) {

8
src/wallet/rpcdump.cpp

@ -201,7 +201,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk)
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. height (integer, optional, default=0) start at block height?\n"
"5. secret_key (integer, optional, default=188) decimal value used to import WIFs of other coins\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
"\nNote: This call can take a long time to complete if rescan is true.\n"
"\nExamples:\n"
"\nDump a private key\n"
+ HelpExampleCli("dumpprivkey", "\"myaddress\"") +
@ -295,7 +295,7 @@ UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk)
"1. \"address\" (string, required) The address\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
"\nNote: This call can take a long time to complete if rescan is true.\n"
"\nExamples:\n"
"\nImport an address with rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\"") +
@ -749,7 +749,7 @@ UniValue z_importkey(const UniValue& params, bool fHelp, const CPubKey& mypk)
"1. \"zkey\" (string, required) The zkey (see z_exportkey)\n"
"2. rescan (string, optional, default=\"whenkeyisnew\") Rescan the wallet for transactions - can be \"yes\", \"no\" or \"whenkeyisnew\"\n"
"3. startHeight (numeric, optional, default=0) Block height to start rescan from\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
"\nNote: This call can take a long time to complete if rescan is true.\n"
"\nExamples:\n"
"\nExport a zkey\n"
+ HelpExampleCli("z_exportkey", "\"myaddress\"") +
@ -841,7 +841,7 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& m
"2. rescan (string, optional, default=\"whenkeyisnew\") Rescan the wallet for transactions - can be \"yes\", \"no\" or \"whenkeyisnew\"\n"
"3. startHeight (numeric, optional, default=0) Block height to start rescan from\n"
"4. zaddr (string, optional, default=\"\") zaddr in case of importing viewing key for Sapling\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
"\nNote: This call can take a long time to complete if rescan is true.\n"
"\nExamples:\n"
"\nImport a viewing key\n"
+ HelpExampleCli("z_importviewingkey", "\"vkey\"") +

14
src/wallet/rpcwallet.cpp

@ -1103,7 +1103,7 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK
if (fHelp || params.size() > 1 )
throw runtime_error(
"cleanwallettransactions \"txid\"\n"
"\nRemove all txs that are spent. You can clear all txs bar one, by specifiying a txid.\n"
"\nRemove all transparent UTXOs that are spent. You can clear all transactions bar one, by specifiying a txid.\n"
"\nPlease backup your wallet.dat before running this command.\n"
"\nArguments:\n"
"1. \"txid\" (string, optional) The transaction id to keep.\n"
@ -1133,9 +1133,7 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK
if ( !pwalletMain->IsMine(tmp_tx) )
{
throw runtime_error("\nThe transaction is not yours!\n");
}
else
{
} else {
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
@ -1145,14 +1143,10 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK
}
}
}
}
else
{
} else {
throw runtime_error("\nThe transaction could not be found!\n");
}
}
else
{
} else {
// get all locked utxos to relock them later.
vector<COutPoint> vLockedUTXO;
pwalletMain->ListLockedCoins(vLockedUTXO);

30
src/wallet/wallet.cpp

@ -480,13 +480,19 @@ void CWallet::ChainTip(const CBlockIndex *pindex,
pblock->GetBlockTime() > GetTime() - 144*ASSETCHAINS_BLOCKTIME)
{
BuildWitnessCache(pindex, false);
RunSaplingConsolidation(pindex->GetHeight());
DeleteWalletTransactions(pindex);
if (fSaplingConsolidationEnabled) {
RunSaplingConsolidation(pindex->GetHeight());
}
if (fTxDeleteEnabled) {
DeleteWalletTransactions(pindex);
}
} else {
//Build initial witnesses on every block
BuildWitnessCache(pindex, true);
if (initialDownloadCheck && pindex->GetHeight() % fDeleteInterval == 0) {
DeleteWalletTransactions(pindex);
if (fTxDeleteEnabled) {
if (initialDownloadCheck && pindex->GetHeight() % fDeleteInterval == 0) {
DeleteWalletTransactions(pindex);
}
}
}
} else {
@ -902,12 +908,15 @@ int64_t CWallet::NullifierCount()
void CWallet::ClearNoteWitnessCache()
{
LOCK(cs_wallet);
int notes = 0;
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) {
item.second.witnesses.clear();
item.second.witnessHeight = -1;
notes++;
}
}
LogPrintf("%s: Cleared witness data from %d wallet items and %d SaplingNotes\n", __func__, mapWallet.size(), notes);
}
void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex)
@ -1122,6 +1131,7 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
nd->witnessHeight = pblockindex->GetHeight();
}
}
}
}
@ -2378,12 +2388,6 @@ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
return pwalletdb->WriteTx(GetHash(), *this);
}
void CWallet::WitnessNoteCommitment(std::vector<uint256> commitments,
std::vector<boost::optional<SproutWitness>>& witnesses,
uint256 &final_anchor)
{
}
/**
* Reorder the transactions based on block hieght and block index.
* Transactions can get out of order when they are deleted and subsequently
@ -2734,8 +2738,10 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
BuildWitnessCache(pindex, true);
//Delete Transactions
if (pindex->GetHeight() % fDeleteInterval == 0)
DeleteWalletTransactions(pindex);
if (fTxDeleteEnabled) {
if (pindex->GetHeight() % fDeleteInterval == 0)
DeleteWalletTransactions(pindex);
}
if (GetTime() >= nNow + 60) {
nNow = GetTime();

4
src/wallet/wallet.h

@ -1122,10 +1122,6 @@ public:
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
void RescanWallet();
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
void WitnessNoteCommitment(
std::vector<uint256> commitments,
std::vector<boost::optional<SproutWitness>>& witnesses,
uint256 &final_anchor);
void ReorderWalletTransactions(std::map<std::pair<int,int>, CWalletTx*> &mapSorted, int64_t &maxOrderPos);
void UpdateWalletTransactionOrder(std::map<std::pair<int,int>, CWalletTx*> &mapSorted, bool resetOrder);
void DeleteTransactions(std::vector<uint256> &removeTxs);

Loading…
Cancel
Save