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 #!/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 set -e
srcdir="$(dirname $0)" srcdir="$(dirname $0)"
cd "$srcdir" cd "$srcdir"

4
configure.ac

@ -1,8 +1,8 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60]) AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 3) define(_CLIENT_VERSION_MAJOR, 3)
define(_CLIENT_VERSION_MINOR, 7) define(_CLIENT_VERSION_MINOR, 8)
define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_REVISION, 0)
define(_CLIENT_VERSION_BUILD, 50) 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(_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))) 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. .\" 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 .SH NAME
hush-cli \- manual page for hush-cli v3.7.1 hush-cli \- manual page for hush-cli v3.8.0
.SH DESCRIPTION .SH DESCRIPTION
Hush RPC client version v3.7.1\-2da07fe58\-dirty Hush RPC client version v3.8.0\-10a6706e7\-dirty
.PP .PP
In order to ensure you are adequately protecting your privacy when using Hush, In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://hush.is/security/>. 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. .\" 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 .SH NAME
hush-tx \- manual page for hush-tx v3.7.1 hush-tx \- manual page for hush-tx v3.8.0
.SH DESCRIPTION .SH DESCRIPTION
hush\-tx utility version v3.7.1\-2da07fe58\-dirty hush\-tx utility version v3.8.0\-10a6706e7\-dirty
.SS "Usage:" .SS "Usage:"
.TP .TP
hush\-tx [options] <hex\-tx> [commands] 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. .\" 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 .SH NAME
hushd \- manual page for hushd v3.7.1 hushd \- manual page for hushd v3.8.0
.SH DESCRIPTION .SH DESCRIPTION
Hush Daemon version v3.7.1\-2da07fe58\-dirty Hush Daemon version v3.8.0\-10a6706e7\-dirty
.PP .PP
In order to ensure you are adequately protecting your privacy when using Hush, In order to ensure you are adequately protecting your privacy when using Hush,
please see <https://hush.is/security/>. please see <https://hush.is/security/>.
@ -341,10 +341,19 @@ Minimum fee (in HUSH/kB) to allow for OP_RETURN transactions (default:
.IP .IP
Fee (in HUSH/kB) to add to transactions you send (default: 0.00) Fee (in HUSH/kB) to add to transactions you send (default: 0.00)
.HP .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 \fB\-rescan\fR
.IP .IP
Rescan the block chain for missing wallet transactions on startup Rescan the block chain for missing wallet transactions on startup
.HP .HP
\fB\-rescanheight\fR
.IP
Rescan from specified height when rescan=1 on startup
.HP
\fB\-salvagewallet\fR \fB\-salvagewallet\fR
.IP .IP
Attempt to recover private keys from a corrupt wallet.dat on startup 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 also because they censor many people around the world and work with
evil organizations. 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" # Hush 3.7.1 "Neologistic Nautilus"
``` ```

16
src/chain.h

@ -266,7 +266,7 @@ public:
int64_t nPayments; int64_t nPayments;
//! (memory only) Number of shielded transactions (of any kind) in the block up to and including this block. //! (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 //! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as
//! inputs and outputs. //! inputs and outputs.
int64_t nShieldedTx; int64_t nShieldedTx;
@ -278,7 +278,7 @@ public:
int64_t nShieldedSpends; int64_t nShieldedSpends;
//! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined //! (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... // inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc...
int64_t nFullyShieldedTx; int64_t nFullyShieldedTx;
@ -295,7 +295,7 @@ public:
int64_t nFullyShieldedPayments; int64_t nFullyShieldedPayments;
//! (memory only) Number of deshielding transactions. A deshielding transaction is defined //! (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; int64_t nDeshieldingTx;
//! (memory only) Number of deshielding payments. A deshielding payment is defined //! (memory only) Number of deshielding payments. A deshielding payment is defined
@ -303,7 +303,7 @@ public:
int64_t nDeshieldingPayments; int64_t nDeshieldingPayments;
//! (memory only) Number of shielding transactions. A shielding transaction is defined //! (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) // i.e. t->z or t->(z,t) or z->(z,z,t)
int64_t nShieldingTx; int64_t nShieldingTx;
@ -322,7 +322,7 @@ public:
int64_t nChainPayments; int64_t nChainPayments;
//! (memory only) Number of shielded transactions (of any kind) in the chain up to and including this block. //! (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 //! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as
//! inputs and outputs. //! inputs and outputs.
int64_t nChainShieldedTx; int64_t nChainShieldedTx;
@ -334,7 +334,7 @@ public:
int64_t nChainShieldedSpends; int64_t nChainShieldedSpends;
//! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined //! (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... // inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc...
int64_t nChainFullyShieldedTx; int64_t nChainFullyShieldedTx;
@ -351,7 +351,7 @@ public:
int64_t nChainFullyShieldedPayments; int64_t nChainFullyShieldedPayments;
//! (memory only) Number of deshielding transactions. A deshielding transaction is defined //! (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; int64_t nChainDeshieldingTx;
//! (memory only) Number of deshielding payments. A deshielding payment is defined //! (memory only) Number of deshielding payments. A deshielding payment is defined
@ -359,7 +359,7 @@ public:
int64_t nChainDeshieldingPayments; int64_t nChainDeshieldingPayments;
//! (memory only) Number of shielding transactions. A shielding transaction is defined //! (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) // i.e. t->z or t->(z,t) or z->(z,z,t)
int64_t nChainShieldingTx; int64_t nChainShieldingTx;

78
src/chainparams.cpp

@ -783,11 +783,79 @@ void *chainparams_commandline() {
(492000, uint256S("0x00000013bbbff98ddab19a3178a0088a20628791e94963e5d1ea635015dfa9c6")) (492000, uint256S("0x00000013bbbff98ddab19a3178a0088a20628791e94963e5d1ea635015dfa9c6"))
(493000, uint256S("0x00000001ed829c061ba14f6953e79d99577079adf5526f1e43e6dc9d9f9571bf")) (493000, uint256S("0x00000001ed829c061ba14f6953e79d99577079adf5526f1e43e6dc9d9f9571bf"))
(494000, uint256S("0x00000018dfeced2d1584a1003fefa4349810239bade096e53b4fa6bbc38a1685")) (494000, uint256S("0x00000018dfeced2d1584a1003fefa4349810239bade096e53b4fa6bbc38a1685"))
(495000, uint256S("0x0000001816af55724cd49c0bfe02c9eac29b4a73db2b7d868b958218a03e6c94")) (495000, uint256S("0x0000001816af55724cd49c0bfe02c9eac29b4a73db2b7d868b958218a03e6c94"))
(496000, uint256S("0x000000007e2019c5246db5a75122c6826822fa154d68a51eee2ff23f54ec668e")), (496000, uint256S("0x000000007e2019c5246db5a75122c6826822fa154d68a51eee2ff23f54ec668e"))
(int64_t) 1618760194, // time of last checkpointed block (497000, uint256S("0x0000000aa5803c0825cfa1a34227d0ecb80be191674365a372f71611eacdc742"))
(int64_t) 842496, // total txs (498000, uint256S("0x000000166385022d4b4ade0921a5f6c7d4aec56257cd679f7c441aeb0552b28c"))
(double) 1812 // txs in the last day before block 496013 (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 { } 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 //! 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! // Must be kept in sync with configure.ac , ugh!
#define CLIENT_VERSION_MAJOR 3 #define CLIENT_VERSION_MAJOR 3
#define CLIENT_VERSION_MINOR 7 #define CLIENT_VERSION_MINOR 8
#define CLIENT_VERSION_REVISION 1 #define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_BUILD 50 #define CLIENT_VERSION_BUILD 50
//! Set to true for release, false for prerelease or test build //! 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 @call :GET_CURRENT_DIR
@cd %THIS_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 @goto :EOF
:GET_CURRENT_DIR :GET_CURRENT_DIR

20
src/init.cpp

@ -466,7 +466,11 @@ std::string HelpMessage(HelpMessageMode mode)
CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK()))); 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("-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()))); 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("-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("-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("-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)); 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(); CBlockIndex *pindexRescan = chainActive.Tip();
if (clearWitnessCaches || GetBoolArg("-rescan", false)) 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(); pindexRescan = chainActive.Genesis();
if (rescanHeight > 0) {
if (rescanHeight > chainActive.Tip()->GetHeight()) {
pindexRescan = chainActive.Tip();
} else {
pindexRescan = chainActive[rescanHeight];
}
}
} else { } else {
CWalletDB walletdb(strWalletFile); CWalletDB walletdb(strWalletFile);
CBlockLocator locator; CBlockLocator locator;

157
src/main.cpp

@ -76,6 +76,7 @@ using namespace std;
CCriticalSection cs_main; CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33]; extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t HUSH_LOADINGBLOCKS,HUSH_LONGESTCHAIN,HUSH_INSYNC,HUSH_CONNECTING,HUSH_EXTRASATOSHI; extern int32_t HUSH_LOADINGBLOCKS,HUSH_LONGESTCHAIN,HUSH_INSYNC,HUSH_CONNECTING,HUSH_EXTRASATOSHI;
extern CZindexStats zstats;
int32_t HUSH_NEWBLOCKS; int32_t HUSH_NEWBLOCKS;
int32_t hush_block2pubkey33(uint8_t *pubkey33,CBlock *block); int32_t hush_block2pubkey33(uint8_t *pubkey33,CBlock *block);
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
@ -572,6 +573,102 @@ namespace {
} // anon 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) { bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
LOCK(cs_main); LOCK(cs_main);
CNodeState *state = State(nodeid); 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; 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 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); 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(); HUSH_INSYNC = (int32_t)pindexNew->GetHeight();
else HUSH_INSYNC = 0; else HUSH_INSYNC = 0;
//fprintf(stderr,"connect.%d insync.%d ASSETCHAINS_SAPLING.%d\n",(int32_t)pindexNew->GetHeight(),HUSH_INSYNC,ASSETCHAINS_SAPLING); //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. // pool. So we invert the sign here.
saplingValue += -tx.valueBalance; saplingValue += -tx.valueBalance;
/*
for (auto js : tx.vjoinsplit) {
sproutValue += js.vpub_old;
sproutValue -= js.vpub_new;
}
*/
// Ignore following stats unless -zindex enabled // Ignore following stats unless -zindex enabled
if (!fZindex) if (!fZindex)
continue; continue;
@ -4560,6 +4650,39 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
if (fZdebug) { if (fZdebug) {
//fprintf(stderr,"%s: setting blockchain zstats with zspends=%d, zouts=%d\n", __FUNCTION__, nShieldedSpendsInBlock, nShieldedOutputsInBlock ); //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->nChainNotarizations = (pindex->pprev ? pindex->pprev->nChainNotarizations : 0) + pindex->nNotarizations;
pindex->nChainShieldedTx = (pindex->pprev ? pindex->pprev->nChainShieldedTx : 0) + pindex->nShieldedTx; pindex->nChainShieldedTx = (pindex->pprev ? pindex->pprev->nChainShieldedTx : 0) + pindex->nShieldedTx;
pindex->nChainShieldedOutputs = (pindex->pprev ? pindex->pprev->nChainShieldedOutputs : 0) + pindex->nShieldedOutputs; 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->nChainFullyShieldedPayments = (pindex->pprev ? pindex->pprev->nChainFullyShieldedPayments : 0) + pindex->nFullyShieldedPayments;
pindex->nChainShieldingPayments = (pindex->pprev ? pindex->pprev->nChainShieldingPayments : 0) + pindex->nShieldingPayments; pindex->nChainShieldingPayments = (pindex->pprev ? pindex->pprev->nChainShieldingPayments : 0) + pindex->nShieldingPayments;
pindex->nChainDeshieldingPayments = (pindex->pprev ? pindex->pprev->nChainDeshieldingPayments : 0) + pindex->nDeshieldingPayments; 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) { if (pindex->pprev) {
@ -4610,6 +4750,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
} }
} }
if (fZindex) if (fZindex)
fprintf(stderr, "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, ShieldedOutputs=%d, FullyShieldedTx=%d, ntz=%d\n", fprintf(stderr, "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, ShieldedOutputs=%d, FullyShieldedTx=%d, ntz=%d\n",
pindexNew->GetHeight(), nShieldedPayments, nShieldedTx, nShieldedOutputs, nFullyShieldedTx, nNotarizations ); 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); void SetChainNotifiedSequence(uint64_t recentlyConflictedSequence);
bool ChainIsFullyNotified(); 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 #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 // Collect memory pool transactions into the block
CAmount nFees = 0; CAmount nFees = 0;
// we will attempt to spend any cheats we see
CTransaction cheatTx;
boost::optional<CTransaction> cheatSpend;
uint256 cbHash; uint256 cbHash;
boost::this_thread::interruption_point(); // exit thread before entering locks. 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; scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG;
} else { } else {
{ {
if (!reservekey.GetReservedKey(pubkey)) // Support mining with -disablewallet and minetolocalwallet=0
{ if (!GetBoolArg("-disablewallet", false)) {
return NULL; // wallet enabled
} if (!reservekey.GetReservedKey(pubkey))
scriptPubKey.resize(35); return NULL;
ptr = (uint8_t *)pubkey.begin(); scriptPubKey.clear();
scriptPubKey[0] = 33; scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
for (i=0; i<33; i++) { } else {
scriptPubKey[i+1] = ptr[i]; // wallet disabled
} CTxDestination dest = DecodeDestination(GetArg("-mineraddress", ""));
scriptPubKey[34] = OP_CHECKSIG; 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); 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) static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
#else #else
static bool ProcessBlockFound(CBlock* pblock) static bool ProcessBlockFound(CBlock* pblock)
@ -972,7 +952,6 @@ static bool ProcessBlockFound(CBlock* pblock)
return error("HushMiner: ProcessNewBlock, block not accepted"); return error("HushMiner: ProcessNewBlock, block not accepted");
TrackMinedBlock(pblock->GetHash()); TrackMinedBlock(pblock->GetHash());
//komodo_broadcast(pblock,16);
return true; 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? // Satoshi originally used 10 seconds(!), did they know something Peter Wuille didn't?
#define DUMP_ADDRESSES_INTERVAL 300 #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) #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0 #define MSG_NOSIGNAL 0
#endif #endif
@ -89,10 +94,10 @@ namespace {
}; };
} }
// Global state variables // Global state variables
extern uint16_t ASSETCHAINS_P2PPORT; extern uint16_t ASSETCHAINS_P2PPORT;
extern char SMART_CHAIN_SYMBOL[65]; extern char SMART_CHAIN_SYMBOL[65];
bool fDiscover = true; bool fDiscover = true;
bool fListen = true; bool fListen = true;
uint64_t nLocalServices = NODE_NETWORK | NODE_NSPV; uint64_t nLocalServices = NODE_NETWORK | NODE_NSPV;
@ -103,11 +108,14 @@ static CNode* pnodeLocalHost = NULL;
uint64_t nLocalHostNonce = 0; uint64_t nLocalHostNonce = 0;
static std::vector<ListenSocket> vhListenSocket; static std::vector<ListenSocket> vhListenSocket;
CAddrMan addrman; CAddrMan addrman;
CZindexStats zstats;
int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
bool fAddressesInitialized = false; bool fAddressesInitialized = false;
std::string strSubVersion; std::string strSubVersion;
TLSManager tlsmanager = TLSManager(); TLSManager tlsmanager = TLSManager();
extern void StartShutdown();
vector<CNode*> vNodes; vector<CNode*> vNodes;
CCriticalSection cs_vNodes; CCriticalSection cs_vNodes;
map<CInv, CDataStream> mapRelay; map<CInv, CDataStream> mapRelay;
@ -1400,6 +1408,28 @@ void DumpAddresses()
LogPrint("net", "Flushed %d addresses to peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); 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() void static ProcessOneShot()
{ {
string strDest; string strDest;
@ -1909,8 +1939,40 @@ void static Discover(boost::thread_group& threadGroup)
#endif #endif
} }
//extern CWallet pwalletMain;
void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) 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...")); uiInterface.InitMessage(_("Loading addresses..."));
// Load addresses for peers.dat // Load addresses for peers.dat
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
@ -1919,8 +1981,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!adb.Read(addrman)) if (!adb.Read(addrman))
LogPrintf("Invalid or missing peers.dat! This can happen when upgrading. Whatevz, recreating\n"); LogPrintf("Invalid or missing peers.dat! This can happen when upgrading. Whatevz, recreating\n");
} }
LogPrintf("Loaded %i addresses from peers.dat %dms\n", LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart);
addrman.size(), GetTimeMillis() - nStart);
fAddressesInitialized = true; fAddressesInitialized = true;
if (semOutbound == NULL) { if (semOutbound == NULL) {
@ -1968,6 +2029,13 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
// Dump network addresses // Dump network addresses
scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL); 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() bool StopNode()
@ -1977,6 +2045,9 @@ bool StopNode()
for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++)
semOutbound->post(); semOutbound->post();
// persist current zindex stats to disk before we exit
DumpZindexStats();
if (HUSH_NSPV_FULLNODE && fAddressesInitialized) if (HUSH_NSPV_FULLNODE && fAddressesInitialized)
{ {
DumpAddresses(); DumpAddresses();

1
src/net.h

@ -223,6 +223,7 @@ public:
int nStartingHeight; int nStartingHeight;
uint64_t nSendBytes; uint64_t nSendBytes;
uint64_t nRecvBytes; uint64_t nRecvBytes;
bool fRelayTxes;
bool fAllowlisted; // If true this node bypasses DoS ban limits bool fAllowlisted; // If true this node bypasses DoS ban limits
bool fFeeler; // If true this node is being used as a short lived feeler. bool fFeeler; // If true this node is being used as a short lived feeler.
double dPingTime; 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"); 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); const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->GetHeight() - blockcount);
int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast(); int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast();
int nTxDiff = pindex->nChainTx - pindexPast->nChainTx; int nTxDiff = pindex->nChainTx - pindexPast->nChainTx;
LogPrintf("%s: pindexPast.height = %d, pindex.height = %d\n", __func__, pindexPast->GetHeight(), pindex->GetHeight() );
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
ret.pushKV("time", (int64_t)pindex->nTime); 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_tx_count", nTxDiff);
ret.pushKV("window_interval", nTimeDiff); ret.pushKV("window_interval", nTimeDiff);
int64_t nPaymentsDiff = pindex->nChainPayments - pindexPast->nChainPayments; 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 nShieldedTxDiff = pindex->nChainShieldedTx - pindexPast->nChainShieldedTx;
int64_t nShieldingTxDiff = pindex->nChainShieldingTx - pindexPast->nChainShieldingTx; int64_t nShieldingTxDiff = pindex->nChainShieldingTx - pindexPast->nChainShieldingTx;
int64_t nDeshieldingTxDiff = pindex->nChainDeshieldingTx - pindexPast->nChainDeshieldingTx; 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" " \"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" " \"bytessent\": n, (numeric) The total bytes sent\n"
" \"bytesrecv\": n, (numeric) The total bytes received\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" " \"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" " \"timeoffset\": ttt, (numeric) The time offset in seconds (deprecated, always 0)\n"
" \"pingtime\": n, (numeric) ping time\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("lastrecv", stats.nLastRecv));
obj.push_back(Pair("bytessent", stats.nSendBytes)); obj.push_back(Pair("bytessent", stats.nSendBytes));
obj.push_back(Pair("bytesrecv", stats.nRecvBytes)); 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("conntime", stats.nTimeConnected));
obj.push_back(Pair("timeoffset", 0)); obj.push_back(Pair("timeoffset", 0));
obj.push_back(Pair("pingtime", stats.dPingTime)); 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; int32_t HUSH_LONGESTCHAIN;
static int32_t hush_longest_depth = 0;
int32_t hush_longestchain() int32_t hush_longestchain()
{ {
static int32_t depth;
int32_t ht,n=0,num=0,maxheight=0,height = 0; int32_t ht,n=0,num=0,maxheight=0,height = 0;
if ( depth < 0 ) if ( hush_longest_depth < 0 )
depth = 0; hush_longest_depth = 0;
if ( depth == 0 ) if ( hush_longest_depth == 0 )
{ {
depth++; hush_longest_depth++;
vector<CNodeStats> vstats; vector<CNodeStats> vstats;
{ {
//LOCK(cs_main); //LOCK(cs_main);
@ -212,7 +215,7 @@ int32_t hush_longestchain()
if ( ht > height ) if ( ht > height )
height = ht; height = ht;
} }
depth--; hush_longest_depth--;
if ( num > (n >> 1) ) if ( num > (n >> 1) )
{ {
if ( 0 && height != HUSH_LONGESTCHAIN ) if ( 0 && height != HUSH_LONGESTCHAIN )

4
src/rpc/rawtransaction.cpp

@ -646,7 +646,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp, const CPubKey&
" ]\n" " ]\n"
"2. \"outputs\" (object, required) a json object with outputs\n" "2. \"outputs\" (object, required) a json object with outputs\n"
" {\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" " \"data\": \"hex\" (string, required) The key is \"data\", the value is hex encoded data\n"
" ,...\n" " ,...\n"
" }\n" " }\n"
@ -821,7 +821,7 @@ UniValue decoderawtransaction(const UniValue& params, bool fHelp, const CPubKey&
" \"reqSigs\" : n, (numeric) The required sigs\n" " \"reqSigs\" : n, (numeric) The required sigs\n"
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
" \"addresses\" : [ (json array of string)\n" " \"addresses\" : [ (json array of string)\n"
" \"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\" (string) komodo address\n" " \"RTZMZHDFSTFQst8XmX2dR4DaH87cEUs3gC\" (string) HUSH address\n"
" ,...\n" " ,...\n"
" ]\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); LOCK(cs_rpcWarmup);
if (fRPCInWarmup) { if (fRPCInWarmup) {
// hush-cli stop is the only valid RPC command during warmup // Most RPCs are unsafe to run during warmup, but stop+help are fine
// We don't know if we have valid blocks or wallet yet, nothing else is safe // Others may not have data loaded yet, such as wallet details, but
if (pcmd->name != "stop") { // 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); throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
} }
} }

10
src/transaction_builder.cpp

@ -59,6 +59,13 @@ void TransactionBuilder::AddSaplingOutput(
mtx.valueBalance -= value; 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) void TransactionBuilder::AddTransparentInput(COutPoint utxo, CScript scriptPubKey, CAmount value, uint32_t _nSequence)
{ {
if (keystore == nullptr) { if (keystore == nullptr) {
@ -212,6 +219,9 @@ boost::optional<CTransaction> TransactionBuilder::Build()
mtx.vShieldedSpend.push_back(sdesc); mtx.vShieldedSpend.push_back(sdesc);
} }
// Prevent leaking metadata about the position of change output
ShuffleOutputs();
// Create Sapling OutputDescriptions // Create Sapling OutputDescriptions
for (auto output : outputs) { for (auto output : outputs) {
auto cm = output.note.cm(); auto cm = output.note.cm();

2
src/transaction_builder.h

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

2
src/version.h

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

12
src/wallet/asyncrpcoperation_shieldcoinbase.cpp

@ -46,6 +46,7 @@
using namespace libzcash; using namespace libzcash;
extern uint64_t ASSETCHAINS_TIMELOCKGTE; extern uint64_t ASSETCHAINS_TIMELOCKGTE;
extern string randomSietchZaddr();
AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
TransactionBuilder builder, TransactionBuilder builder,
@ -229,6 +230,17 @@ bool ShieldToAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) c
// Send all value to the target z-addr // Send all value to the target z-addr
m_op->builder_.SendChangeTo(zaddr, ovk); 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 // Build the transaction
auto maybe_tx = m_op->builder_.Build(); auto maybe_tx = m_op->builder_.Build();
if (!maybe_tx) { 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" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. height (integer, optional, default=0) start at block height?\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" "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" "\nExamples:\n"
"\nDump a private key\n" "\nDump a private key\n"
+ HelpExampleCli("dumpprivkey", "\"myaddress\"") + + HelpExampleCli("dumpprivkey", "\"myaddress\"") +
@ -295,7 +295,7 @@ UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk)
"1. \"address\" (string, required) The address\n" "1. \"address\" (string, required) The address\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n" "2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\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" "\nExamples:\n"
"\nImport an address with rescan\n" "\nImport an address with rescan\n"
+ HelpExampleCli("importaddress", "\"myaddress\"") + + 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" "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" "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" "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" "\nExamples:\n"
"\nExport a zkey\n" "\nExport a zkey\n"
+ HelpExampleCli("z_exportkey", "\"myaddress\"") + + 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" "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" "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" "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" "\nExamples:\n"
"\nImport a viewing key\n" "\nImport a viewing key\n"
+ HelpExampleCli("z_importviewingkey", "\"vkey\"") + + 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 ) if (fHelp || params.size() > 1 )
throw runtime_error( throw runtime_error(
"cleanwallettransactions \"txid\"\n" "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" "\nPlease backup your wallet.dat before running this command.\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"txid\" (string, optional) The transaction id to keep.\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) ) if ( !pwalletMain->IsMine(tmp_tx) )
{ {
throw runtime_error("\nThe transaction is not yours!\n"); 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) for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{ {
const CWalletTx& wtx = (*it).second; 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"); throw runtime_error("\nThe transaction could not be found!\n");
} }
} } else {
else
{
// get all locked utxos to relock them later. // get all locked utxos to relock them later.
vector<COutPoint> vLockedUTXO; vector<COutPoint> vLockedUTXO;
pwalletMain->ListLockedCoins(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) pblock->GetBlockTime() > GetTime() - 144*ASSETCHAINS_BLOCKTIME)
{ {
BuildWitnessCache(pindex, false); BuildWitnessCache(pindex, false);
RunSaplingConsolidation(pindex->GetHeight()); if (fSaplingConsolidationEnabled) {
DeleteWalletTransactions(pindex); RunSaplingConsolidation(pindex->GetHeight());
}
if (fTxDeleteEnabled) {
DeleteWalletTransactions(pindex);
}
} else { } else {
//Build initial witnesses on every block //Build initial witnesses on every block
BuildWitnessCache(pindex, true); BuildWitnessCache(pindex, true);
if (initialDownloadCheck && pindex->GetHeight() % fDeleteInterval == 0) { if (fTxDeleteEnabled) {
DeleteWalletTransactions(pindex); if (initialDownloadCheck && pindex->GetHeight() % fDeleteInterval == 0) {
DeleteWalletTransactions(pindex);
}
} }
} }
} else { } else {
@ -902,12 +908,15 @@ int64_t CWallet::NullifierCount()
void CWallet::ClearNoteWitnessCache() void CWallet::ClearNoteWitnessCache()
{ {
LOCK(cs_wallet); LOCK(cs_wallet);
int notes = 0;
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) { for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) { for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) {
item.second.witnesses.clear(); item.second.witnesses.clear();
item.second.witnessHeight = -1; 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) void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex)
@ -1122,6 +1131,7 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
nd->witnessHeight = pblockindex->GetHeight(); nd->witnessHeight = pblockindex->GetHeight();
} }
} }
} }
} }
@ -2378,12 +2388,6 @@ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
return pwalletdb->WriteTx(GetHash(), *this); 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. * Reorder the transactions based on block hieght and block index.
* Transactions can get out of order when they are deleted and subsequently * 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); BuildWitnessCache(pindex, true);
//Delete Transactions //Delete Transactions
if (pindex->GetHeight() % fDeleteInterval == 0) if (fTxDeleteEnabled) {
DeleteWalletTransactions(pindex); if (pindex->GetHeight() % fDeleteInterval == 0)
DeleteWalletTransactions(pindex);
}
if (GetTime() >= nNow + 60) { if (GetTime() >= nNow + 60) {
nNow = GetTime(); nNow = GetTime();

4
src/wallet/wallet.h

@ -1122,10 +1122,6 @@ public:
void SyncTransaction(const CTransaction& tx, const CBlock* pblock); void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
void RescanWallet(); void RescanWallet();
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); 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 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 UpdateWalletTransactionOrder(std::map<std::pair<int,int>, CWalletTx*> &mapSorted, bool resetOrder);
void DeleteTransactions(std::vector<uint256> &removeTxs); void DeleteTransactions(std::vector<uint256> &removeTxs);

Loading…
Cancel
Save