Compare commits

...

344 Commits

Author SHA1 Message Date
Kris Nuttycombe bb91c9fbc3
Merge pull request #5549 from therealyingtong/cache-ua
Cache UA recipients passed to `z_sendmany`
2022-02-22 09:05:13 -07:00
therealyingtong 1dae16a41c WriteRecipientMapping: Check that receiver exists in UA.
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2022-02-22 11:53:23 +08:00
ying tong 2943e13c8b
Apply docfixes from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2022-02-22 08:44:09 +08:00
therealyingtong 108e9d4658 CSerializeRecipientAddress: add Read method and make constructor private.
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
2022-02-18 16:39:43 +08:00
therealyingtong 99a69182cd Docfixes. 2022-02-18 13:55:58 +08:00
therealyingtong 4c4ee558d6 ShieldToAddress: Factor out static shieldToAddress() helper. 2022-02-18 13:55:23 +08:00
str4d 6cd5b8792b
Merge pull request #5560 from steven-ecc/z_gettreestate_update_for_orchard
Add Orchard support to the z_gettreestate RPC
2022-02-18 03:17:05 +00:00
Kris Nuttycombe d08c992b5e Move parsing of unified addresses to UnifiedAddress.
In cases where we want to be able to decode a string that
is known to be a unified address, it doesn't make sense to have
to route through KeyIO::DecodePaymentAddress and then return
an error depending upon the result type, when it's possible to
provide unified address parsing more directly.

KeyIO::DecodePaymentAddress has been modified to delegate
to UnifiedAddress::Parse
2022-02-17 18:27:15 -07:00
Larry Ruane ba9e020fcd add functional test 2022-02-17 16:47:59 -07:00
Kris Nuttycombe 73a75a37fe Make SaveRecipientMappings polymorphic in RecipientMapping type. 2022-02-17 08:55:59 -07:00
Steven Smith 59c6b028f7 Add Orchard support to the z_gettreestate RPC 2022-02-17 06:14:21 -08:00
therealyingtong 79c0514919 z_sendmany: Only get ua if decoded is ua variant. 2022-02-17 19:38:02 +08:00
Steven ffdc11c378
Merge pull request #5555 from steven-ecc/deprecate_rpcs
Mark z_gettotalbalance and dumpwallet as deprecated
2022-02-16 15:58:46 -08:00
Daira Hopwood 816649db2a
Cosmetic whitespace change 2022-02-16 22:19:59 +00:00
Steven Smith 512c862a5f Mark z_gettotalbalance and dumpwallet as deprecated 2022-02-16 08:47:34 -08:00
str4d d0d6d47aa7
Merge pull request #5545 from LarryRuane/2022-02-z_listreceivedbyaddress-reject-ua-component
z_listreceivedbyaddress: reject UA component addr (#5537)
2022-02-16 16:30:34 +00:00
therealyingtong 94ab8e4c77 Implement read and write for (txid, recipient) -> ua mapping.
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
Co-authored-by: Jack Grigg <jack@z.cash>
2022-02-16 20:15:07 +08:00
Larry Ruane 698f7ba770 z_listreceivedbyaddress: reject UA component addr (#5537) 2022-02-15 09:19:09 -07:00
therealyingtong c7346e802e SendTransaction: Introduce recipients argument. 2022-02-15 09:50:00 +08:00
therealyingtong 6436230562 Move SendManyRecipient to wallet.h and introduce optional ua field. 2022-02-15 09:50:00 +08:00
sasha e568a190f3
Merge pull request #5419 from zcash/feature/wallet_unified_addresses 2022-02-14 08:17:36 -08:00
Kris Nuttycombe 9ca64fc8ba
Merge pull request #5541 from nuttycom/ua_test_vectors
Add test vectors for UFVK derivation
2022-02-13 07:36:14 -07:00
Kris Nuttycombe 96f34b9bbd
Merge pull request #5543 from nuttycom/feature/wallet_unified_addresses-address_review
Rename sapling-specific zip32 FFI methods.
2022-02-13 07:35:08 -07:00
Kris Nuttycombe b1ab30c8d9 Rename sapling-specific zip32 FFI methods.
Also addresses a couple of other minor comments from code review.
2022-02-12 15:24:48 -07:00
Kris Nuttycombe 67e871a40c Add test vectors for UFVK derivation
Also update test vectors for unified addresses.
2022-02-12 15:07:05 -07:00
Kris Nuttycombe e6d3dca2a3
Merge pull request #5542 from LarryRuane/2022-02-z_listreceivedbyaddress-ua-1
fix wallet_listreceived.py, add blockdata to taddr output
2022-02-12 14:59:08 -07:00
Larry Ruane 326dafeebe fix wallet_listreceived.py, add blockdata to taddr output 2022-02-12 13:01:58 -07:00
Kris Nuttycombe 93e12899bb
Merge pull request #5540 from nuttycom/feature/wallet_unified_addresses-fix_osx_build
Fix missing std::variant header that was breaking Darwin builds.
2022-02-11 15:26:08 -07:00
Kris Nuttycombe 85caa659af Fix missing std::variant header that was breaking Darwin builds. 2022-02-11 13:10:47 -07:00
Kris Nuttycombe 29c9632ecb
Merge pull request #5508 from LarryRuane/2022-02-z_listreceivedbyaddress-ua
Update z_listreceivedbyaddress to support unified addresses (5467)
2022-02-11 08:10:00 -07:00
Kris Nuttycombe 007f05493a Add change field to z_listreceivedbyaddress for transparent addrs.
This updates the `IsChange` method to check the HD keypath associated
with the key for whether the address was generated as internal
or external.
2022-02-11 12:48:35 +00:00
Larry Ruane c48e35bb66 Update z_listreceivedbyaddress to support unified addresses (5467) 2022-02-11 12:48:23 +00:00
Kris Nuttycombe 30c20c0046
Merge pull request #5323 from charlieok/update_dockerfile_to_debian_11
Update base image used by Dockerfile from debian 10 to debian 11
2022-02-10 18:29:01 -07:00
Kris Nuttycombe d2b900a0c8
Merge pull request #5531 from str4d/overhaul-legacy-transparent-keypool
Only use legacy transparent keypool for internal keys
2022-02-10 18:06:08 -07:00
Jack Grigg 89b9bbaf33 wallet: Separate counters for external and internal transparent keys
This fixes a potential bug with importing the mnemonic into a third
party transparent wallet. Previously, if a user called `getnewaddress`,
made a bunch of transactions that generated at least 20 change
addresses, and then called `getnewaddress` again, the two external
addresses would be separated by a gap of more than 20. If this mnemonic
were imported into a third party transparent wallet, the wallet would
not detect any funds in the second (or subsequent) transparent addresses
because it would detect 20 unused addresses in a row (via the BIP 44
default gap limit).

Now, we track external and internal keys separately; repeated calls to
`getnewaddress` will return addresses for sequential keys. This has the
added benefit that the sequence of `getnewaddress` outputs will be the
same after restoring from a backup.
2022-02-10 21:26:29 +00:00
Jack Grigg 2555aadf31 wallet: Store internal transparent keys in the keypool
Now that the keypool is not used by any consumers of external
transparent keys, we switch it to only contain internal keys. To handle
the impedance mismatch, we clear out the keypool when a mnemonic seed is
generated for the wallet.
2022-02-10 21:26:29 +00:00
Jack Grigg 11e62fa997 wallet: Remove `CWallet::GetKeyFromPool`
Legacy transparent addresses for external use are now obtained directly
via `GenerateNewKey(true)`.
2022-02-10 21:26:29 +00:00
Kris Nuttycombe d1227b086e
Merge pull request #5525 from nuttycom/feature/wallet_unified_addresses-ua_belongs_to_wallet
Add unified address support to PaymentAddressBelongsToWallet and GetSourceForPaymentAddress
2022-02-09 22:26:54 -07:00
Kris Nuttycombe 2aad87e147
Merge pull request #5526 from str4d/wallet-unified-addrs-in-rpcs
Handle wallet Unified Addresses in RPCs
2022-02-09 21:11:41 -07:00
Kris Nuttycombe 50ad6675a5 Address comments from review. 2022-02-09 20:56:00 -07:00
Kris Nuttycombe 09593559f8
Merge pull request #5522 from nuttycom/feature/wallet_unified_addresses-balance_for_vk
Replace z_getbalanceforaddress with z_getbalanceforviewingkey
2022-02-09 20:30:09 -07:00
Jack Grigg 88dde127f4 wallet: Show UAs instead of Sapling receivers in `z_listunspent`
We also add a `type` field to the output objects (matching the field in
`z_viewtransaction`), now that the output type can't be distinguished
solely from the address encoding.
2022-02-10 02:32:56 +00:00
Kris Nuttycombe f320a6cc24 Add unified address support to GetSourceForPaymentAddress 2022-02-09 18:59:13 -07:00
Kris Nuttycombe d2e8b98364 Implement PaymentAddressBelongsToWallet for unified addresses. 2022-02-09 18:22:14 -07:00
Jack Grigg 0a9c27e8f2 wallet: Don't show Sapling receivers from UAs in `z_listaddresses`
This API is deprecated in favour of `listaddresses`, so we aren't going
to extend it with UA support.
2022-02-10 01:09:46 +00:00
Kris Nuttycombe d24a41496a Clarify documentation of z_getbalanceforviewingkey for Sprout viewing keys. 2022-02-09 17:03:24 -07:00
Kris Nuttycombe bf79be2b57 Replace z_getbalanceforaddress with z_getbalanceforviewingkey 2022-02-09 16:58:55 -07:00
str4d 944453065b
Merge pull request #5517 from daira/deps-graph-override-args
contrib/devtools/rust-deps-graph.sh: allow overriding the arguments to cargo deps
2022-02-09 23:26:40 +00:00
Kris Nuttycombe 08dd842087
Merge pull request #5521 from nuttycom/fix_z_getbalance_locking
Fix locking in z_getbalanceforaddress and z_getbalanceforaccount
2022-02-09 12:30:25 -07:00
Kris Nuttycombe ae1b843b5a Fix locking in z_getbalanceforaddress and z_getbalanceforaccount 2022-02-09 10:48:12 -07:00
Daira Hopwood cf1047324e contrib/devtools/rust-deps-graph.sh: allow overriding the arguments to `cargo deps`.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
2022-02-09 11:48:43 +00:00
str4d d41e10e0c2
Merge pull request #5516 from LarryRuane/2022-02-08-minconf-parse
Fix minconf parsing for z_getbalanceforaccount and z_getbalanceforaddress
2022-02-09 08:29:41 +00:00
Larry Ruane 403c5846c1 fix minconf parsing for z_getbalanceforaccount and z_getbalanceforaddress 2022-02-08 22:58:45 -07:00
str4d 9439c79bab
Merge pull request #5469 from nuttycom/feature/wallet_unified_addresses-z_sendmany
Add support for unified addresses to z_sendmany
2022-02-08 23:42:59 +00:00
Kris Nuttycombe 3f84067658 Fix nondeterministic test failure in wallet_listreceivedby.py 2022-02-08 14:18:18 -07:00
Kris Nuttycombe 282c0db8d5
Merge pull request #5507 from zancas/update_comparison_test_framework
Update comparison test framework
2022-02-08 13:38:19 -07:00
Kris Nuttycombe 1890758b27 Apply suggestions from code review.
Co-authored-by: str4d <thestr4d@gmail.com>
2022-02-08 10:59:15 -07:00
Kris Nuttycombe 9a8038ea62
Merge pull request #5504 from ZcashFoundation/clarify-precomputed-references
Add comment to zcash_script_new_precomputed_tx about references to input buffers
2022-02-08 07:17:33 -07:00
Kris Nuttycombe cf271473eb Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
Co-authored-by: str4d <thestr4d@gmail.com>
2022-02-07 16:52:31 -07:00
Kris Nuttycombe 13ee447a42 Merge branch 'test_wallet_listreceived' into feature/wallet_unified_addresses-z_sendmany 2022-02-07 15:08:35 -07:00
Kris Nuttycombe fa0d4eb473 Use z_shieldcoinbase for Sprout funds in wallet_listreceived tests.
After release 4.7.0, z_sendmany will no longer support sending
funds to Sprout. By using z_shieldcoinbase, we can avoid this
limitation.
2022-02-07 15:06:19 -07:00
str4d 96912d3152
Merge pull request #5490 from LarryRuane/2022-01-ua-shieldcoinbase
allow UA as z_shieldcoinbase destination
2022-02-03 21:44:29 +00:00
Larry Ruane 1e165b8396 allow UA as z_shieldcoinbase destination 2022-02-03 08:31:26 -07:00
Kris Nuttycombe 741ed52436 Fix nondeterministic test error (checking for the wrong error case). 2022-02-02 17:48:35 -07:00
Kris Nuttycombe 6c9b9a53b5 Update librustzcash dependency. 2022-02-02 17:40:36 -07:00
zancas ca04cb0a58
All implementations of ComparisonTestFramework were overriding num_nodes
Moreover, they were all overriding it to the same value (1).
Set the default to 1 and remove redundant subclass constructor code.
2022-02-01 10:27:16 -07:00
zancas 4dce020678
enforce usage of the get_tests comptool interface as ComparisonTestFramework method
In practice all-and-only subclasses of ComparisonTestFramework implement get_tests.
This commit enforces this relation.
2022-02-01 10:27:10 -07:00
Kris Nuttycombe 214567be2c Add a few additional cases to z_sendmany RPC tests. 2022-02-01 08:24:31 -07:00
Kris Nuttycombe a0c27bf254 Address TODOs in rpc-tests/wallet-accounts.py 2022-02-01 08:24:31 -07:00
Kris Nuttycombe a46720aab1 Add accessor method for Sapling IVKs to SaplingDiversifiableFullViewingKey 2022-02-01 08:24:31 -07:00
Kris Nuttycombe 2209a74f38 Fix a bug in the generation of addresses from UFVKs
The use of `std::optional` for the return type of the
`ZcashdUnifiedFullViewingKey::Address` operation obscured
a potential bug where the requested receiver types for a
unified address could not be satisfied because the UFVK
from which the address was being derived did not contain
all of the requested key types.
2022-02-01 08:24:31 -07:00
Kris Nuttycombe 90e59c3be0 Do not add Sapling addresses to the wallet by default when adding extfvks.
Adding the default address to the wallet automatically made sense
prior to support of diversified addresses, but this is no longer
desirable behavior as we have separated key generation from address
derivation.
2022-01-31 11:31:16 -07:00
Conrado Gouvea 269c5c2e7f Add comment to zcash_script_new_precomputed_tx about references to input buffers 2022-01-31 15:16:35 -03:00
Kris Nuttycombe 66530d97e1 Rename AddSaplingIncomingViewingKey -> AddSaplingPaymentAddress
This operation was poorly named; the wallet already contained
the IVK, and this operation was simply adding the ability to
look up the IVK by a specific diversified address derived
from that IVK.
2022-01-30 17:24:52 -07:00
Kris Nuttycombe b80349d246 GenerateLegacySaplingZKey only needs to return an address, not an extfvk. 2022-01-30 11:26:49 -07:00
Kris Nuttycombe ae2213dcdc Fix variable shadowing in change address derivation & add change IVK to the keystore. 2022-01-30 11:15:50 -07:00
Kris Nuttycombe acacc044fc Add gtest for change address derivation.
Check that derivation of the UFVK change address is consistent
irrespective of the path by which it is derived.
2022-01-30 11:09:06 -07:00
Kris Nuttycombe 9afea4f10b Add failing tests for z_sendmany ANY_TADDR -> UA and UA -> <legacy_taddr> 2022-01-30 11:07:00 -07:00
Kris Nuttycombe 91be2f1875 Simplify determination of valid change types. 2022-01-29 13:53:24 -07:00
Kris Nuttycombe b880ef8a1c Fix z_sendmany handling of transparent OVK derivation in the ANY_TADDR case. 2022-01-27 21:29:40 -07:00
Kris Nuttycombe 71f17fa05c Add a check for internal vs. external outputs to wallet_listreceived test. 2022-01-27 21:29:40 -07:00
Kris Nuttycombe 1733c6bc0c Use a BIP 44 change address for change when sending from legacy t-addrs. 2022-01-27 21:29:37 -07:00
Kris Nuttycombe b46d85976d Implement derivation of the internal Sapling spending key. 2022-01-27 21:27:43 -07:00
Kris Nuttycombe 3ddbe1fa06 Implement OVK selection for z_sendmany. 2022-01-27 21:27:43 -07:00
Kris Nuttycombe bdcb12e445 Add a first-class type for transparent full viewing keys. 2022-01-27 21:27:43 -07:00
Kris Nuttycombe c21ffff790 Add correct selection of change addresses to z_sendmany
This also alters `TransactionBuilder::SendChangeTo` to take a
`libzcash::ChangeAddress` value and thus avoids the invalid
t-addr case of CTxDestination.
2022-01-27 21:27:43 -07:00
str4d 992a47103d
Merge pull request #5500 from str4d/ua-wallet-balance-rpcs
Implement balance RPC methods that support Unified Addresses
2022-01-27 20:11:38 +00:00
Kris Nuttycombe d17a0bb9de Merge remote-tracking branch 'upstream/master' into feature/wallet_unified_addresses 2022-01-25 20:27:33 -07:00
Jack Grigg 756f4fc840 wallet: Implement `z_getbalanceforaddress`
Closes zcash/zcash#5182.
2022-01-26 00:34:45 +00:00
Jack Grigg 77c46933aa wallet: Fix account generation bug
When generating a new account, we were setting up the map from account
ID to UFVK ID, but were not setting up the reverse map from UFVK ID to
account ID. The latter map is needed in order to verify that a note in
the wallet belongs to the account. We were correctly loading it from the
account metadata on node start, but between account generation and first
restart, z_getbalanceforaccount would always return zero.

We now initialize the UFVK address metadata map with the account ID when
the account is generated.
2022-01-26 00:02:58 +00:00
Jack Grigg ca0dad0a8c wallet: Implement `z_getbalanceforaccount`
Closes zcash/zcash#5183.
2022-01-25 23:54:30 +00:00
Kris Nuttycombe d8c818bfa5
Merge pull request #5464 from LarryRuane/2022-01-submitblock-log-soln-error
mining: submitblock: log detailed equihash solution error
2022-01-25 12:49:00 -07:00
Kris Nuttycombe 443136c137
Merge pull request #5485 from nuttycom/feature/wallet_unified_addresses-z_sendmany-prereq
Shared utility code needed for z_sendmany and other UA balance-related RPCs.
2022-01-25 12:42:57 -07:00
Kris Nuttycombe 28eddb7c21
Merge pull request #5474 from LarryRuane/2022-01-disable-sprout-addr-gen
rpc: Disable Sprout address generation at Canopy #5368
2022-01-25 10:05:44 -07:00
Charlie O'Keefe 19bfc2f3b8
Merge pull request #5463 from zingolabs/drop_pyblake2_dep
Drop pyblake2 dependency
2022-01-25 09:32:08 -07:00
Kris Nuttycombe b93155c460 Add documentation for `UnifiedAddress::GetPreferredRecipientAddress` 2022-01-25 09:15:51 -07:00
Kris Nuttycombe db104a6329 Use `ZTXOSelector::IncludesSapling` rather than selector internals. 2022-01-25 09:13:08 -07:00
Kris Nuttycombe b8a5131af9 Clarify documentation of CWallet::FindAccountForSelector 2022-01-25 09:08:52 -07:00
Kris Nuttycombe beb0f2bc1f Make `FindSpendableInputs` respect `ZTXOSelector::RequireSpendingKeys()` 2022-01-25 09:00:28 -07:00
Kris Nuttycombe c15f6a9cad Rename ZTXOSelector::SpendingKeysAvailable -> RequireSpendingKeys 2022-01-25 07:39:22 -07:00
Kris Nuttycombe ddb34f612d Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
Co-authored-by: str4d <jack@electriccoin.co>
2022-01-24 20:01:41 -07:00
Kris Nuttycombe babc11eb52 Use libzcash::RecipientAddress for z_sendmany recipients. 2022-01-24 13:10:31 -07:00
Kris Nuttycombe 0abe07c73b Add RecipientAddress type. 2022-01-24 13:10:31 -07:00
Kris Nuttycombe 18282040f5 Add CWallet::FindAccountForSelector 2022-01-24 13:10:31 -07:00
Kris Nuttycombe c4a74087b7 Modify CWallet::FindSpendableInputs to use ZTXOSelector 2022-01-24 13:10:31 -07:00
str4d a6f9c9c0bc Merge pull request #5458 from nuttycom/cleanup/sendmany_txbuilder
Use the transaction builder to implement z_sendmany.
2022-01-21 20:14:58 -07:00
Kris Nuttycombe a43dbb4925 Replace `HaveSpendingKeyForAddress` with checks at ZTXOSelector construction. 2022-01-19 14:37:54 -07:00
Kris Nuttycombe e419899a29 Add support for unified addresses to CWallet::ToZTXOSelector 2022-01-19 13:53:33 -07:00
Kris Nuttycombe f850e89449 Replace the badly-named `PaymentSource` with `ZTXOSelector`
The ZTXOSelector type allows selection of previous Zcash
transaction outputs (both transparent outputs and shielded notes)
on the basis of either a (legacy) bare address, or for a
BIP-44 account.
2022-01-19 13:35:38 -07:00
Kris Nuttycombe c4a7f5c95c Move FindSpendableInputs to CWallet 2022-01-19 13:11:24 -07:00
str4d 6b335ecb4c
Merge pull request #5484 from str4d/5466-ua-validation
Fully-validate contents of UAs and UFVKs on parsing
2022-01-19 02:35:46 +00:00
str4d a5b0725f89
Merge pull request #5475 from str4d/ua-wallet-rpcs
Implement wallet UA RPCs
2022-01-19 00:04:31 +00:00
Jack Grigg 714f14168c rust: Add missing checks for transparent UFVK items 2022-01-18 21:32:33 +00:00
Jack Grigg 9b61806cc6 rust: Add missing checks for shielded UFVK items 2022-01-18 21:32:32 +00:00
Jack Grigg f2e0a8d1f3 rust: Add missing Orchard receiver check in UA parsing
We didn't add it at the time because the necessary API did not exist in
the `orchard` crate. The API has since been added.
2022-01-18 21:31:52 +00:00
Jack Grigg 96c9333b74 wallet: Reverse order of arguments to z_getaddressforaccount
We now use the empty array of pools to indicate that the default pools
should be used when providing a diversifier index parameter, instead of
needing a default sentinel value for the diversifier index parameter
(which was previously suggested as '*' which would have caused issues
for defining a consistent type for that parameter).
2022-01-18 20:02:13 +00:00
Jack Grigg ff0e9f6b95 wallet: Show UAs owned by the wallet in `z_viewtransaction`
Part of zcash/zcash#5186.
2022-01-18 19:44:33 +00:00
Jack Grigg baaa3c4ac0 wallet: Implement `z_listunifiedreceivers`
Closes zcash/zcash#5181.
2022-01-18 19:44:33 +00:00
Jack Grigg 8617622e0d wallet: Implement `z_getaddressforaccount`
Closes zcash/zcash#5180.
2022-01-18 19:43:27 +00:00
Jack Grigg fe384eeb1f wallet: Implement `z_getnewaccount`
Closes zcash/zcash#5178.
2022-01-13 22:35:08 +00:00
str4d 6118432712
Merge pull request #5468 from nuttycom/merge/master_ua
Merge master branch back to the wallet/feature_unified_addresses branch.
2022-01-13 14:15:15 +00:00
Kris Nuttycombe cc392c70a6 Merge branch 'master' into feature/wallet_unified_addresses 2022-01-12 16:54:12 -07:00
str4d 423489c5e8
Merge pull request #5458 from nuttycom/cleanup/sendmany_txbuilder
Use the transaction builder to implement z_sendmany.
2022-01-12 23:50:09 +00:00
Kris Nuttycombe de58fc0b16 Update release notes to reflect z_sendmany changes 2022-01-12 10:45:58 -07:00
Kris Nuttycombe 528ae6d180 Return z_sendmany errors synchronously when possible. 2022-01-12 10:45:58 -07:00
Kris Nuttycombe 0ca7d49626 Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
Co-authored-by: str4d <jack@electriccoin.co>
2022-01-12 10:45:46 -07:00
Kris Nuttycombe 9554ed2dc4 Require an explicit flag to allow cross-pool transfers in z_sendmany.
This adds an `allowRevealedAmounts` argument to z_sendmany. This
flag must be present to allow an amount-revealing cross-pool transfer
to be constructed.
2022-01-11 19:40:02 -07:00
Kris Nuttycombe 322aee238a Fix conditions around dust thresholds. 2022-01-11 19:40:02 -07:00
Kris Nuttycombe b54a63bf18 Transaction builder must not set consensus branch ID for V4 transactions. 2022-01-11 13:28:34 -07:00
Kris Nuttycombe f9477a4499 Use transaction builder for asyncrpcoperation_sendmany.
This replaces the old implementation of asyncrpcoperation_sendmany
with one where all transaction construction is delegated to the
transaction builder. The capabilities of z_sendmany are somewhat
modified in the process:

* z_sendmany now permits sending funds from a Sprout address to
  both transparent and Sapling addresses. PRIVACY NOTE: When
  user sends a Sprout->Sapling transaction, the amount of the
  transaction is publicly revealed.
* z_sendmany no longer supports transactions sending funds into
  the Sprout pool, with the exception of change amounts when
  sending from a Sprout address.
* When sending transparent coinbase funds to a set of shielded
  addresses, the amount sent to recipients must fully consume
  the input value and no change is permitted. This is a slightly
  weaker constraint than was previously implemented; in the past,
  only a single shielded recipient was allowed.
2022-01-11 13:28:34 -07:00
Larry Ruane bc1af5fc2d mining: submitblock: log detailed equihash solution error 2022-01-11 12:52:30 -07:00
zancas 30abf25148
update doctest in gtest suite to prefer hashlib 2022-01-11 10:32:18 -07:00
Kris Nuttycombe d6525e24db
Merge pull request #5445 from rex4539/typos
Fix typos
2022-01-11 10:31:01 -07:00
zancas fbbdb23214
blake2b/s is integrated into hashlib, drop external python package dependency 2022-01-11 10:16:22 -07:00
str4d 005a8624bf
Merge pull request #5440 from nuttycom/cleanup/sendmany_txbuilder-prereq
Prerequisites for replacing manual transaction construction in asyncrpcoperation_sendmany with the transaction builder.
2022-01-11 15:24:55 +00:00
Kris Nuttycombe 951a44de93 Merge remote-tracking branch 'upstream/master' into cleanup/sendmany_txbuilder-prereq 2022-01-10 19:49:23 -07:00
Kris Nuttycombe ed93cf5aff
Merge pull request #5459 from daira/fix-drop-warning
Avoid a warning by explicitly calling drop
2022-01-10 19:46:40 -07:00
Kris Nuttycombe 41eebce355 Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
Co-authored-by: str4d <jack@electriccoin.co>
2022-01-10 19:46:06 -07:00
Daira Hopwood 0e073a53ee Replace call to drop with zeroization.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
2022-01-10 02:39:25 +00:00
Daira Hopwood 4f7d15508f Avoid a warning by explicitly calling drop.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
2022-01-09 23:54:35 +00:00
Kris Nuttycombe d3b599eac1 Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2022-01-07 11:49:09 -07:00
Kris Nuttycombe 864cd8622f Improve error messages in the case of taddr decoding failure. 2022-01-07 11:49:09 -07:00
Kris Nuttycombe 9702b47e2a Use libzcash::PaymentAddress instead of std::string in mergetoaddress 2022-01-07 11:49:09 -07:00
Kris Nuttycombe eb91c7869a Remove a use of KeyIO::DecodeDestination in z_shieldcoinbase 2022-01-07 11:49:09 -07:00
Kris Nuttycombe 20266ac911 Remove uses of KeyIO::DecodeDestination 2022-01-07 11:49:07 -07:00
Kris Nuttycombe d376e28382 Replace `DecodeDestination` in `GetMinerAddress` with `DecodePaymentAddress` 2022-01-06 22:29:44 -07:00
Kris Nuttycombe f5d4f6fef1 Remove `RawAddress`
This adds a new `AddrSet` type for use in note retrieval
as a filter, in place of a heterogeneous list of `RawAddress`
values. `RawAddress` will complicate the handling of addresses
within the wallet after the addition of unified addresses,
because it does not contain transparent receiver types, and
if we retain this polymorphism it means a lot of invalid states
are represented in places we don't want them to be. It's better
to figure out what types of addresses we're working with as soon
as possible after parsing, and use monomorphic calls from there
on in.
2022-01-06 22:29:41 -07:00
Kris Nuttycombe 4f2ff2a9f8 Remove spurious variant from asyncrpcoperation_sendmany
The `spendingkey_` field previously used by asyncrpcoperation_sendmany
caused a situation where call sites would assume the type of the
spending key based upon boolean flags that were derived elsewhere.
In attempting to support unified addresses, it is desirable to remove
these boolean deductions and instead work primarily based on the
direct evidence of the data at hand. This commit therefore removes
the `spendingkey_` field that could potentially produce results
that would disagree with these boolean values, in favor of such
direct evidence, making these call sites a bit less error prone.
2022-01-06 15:32:04 -07:00
Kris Nuttycombe 890e1d841d Add raw transparent address types to PaymentAddress
The addition of `UnifiedAddress` to the `PaymentAddress` type
introduced the need for methods that interact with payment addresses
to support transparent receivers as shielded ones, which is somewhat
inconsistent with previous uses of the `PaymentAddress` type.

This commit adds both `CKeyID` and `CScriptID` as new variants
of the `PaymentAddress` type. Following commits will shift encoding
and decoding to use the `PaymentAddress` type exclusively wherever
possible, rather than the current mix of `CDestination` and
`PaymentAddress` that complicates the wallet codebase.
2022-01-06 13:44:45 -07:00
Kris Nuttycombe c35e2b4438 Remove spurious uses of HaveSpendingKeyForPaymentAddress
There's no need to dispatch through this visitor in cases where
the payment address type is already statically known.
2022-01-06 13:44:45 -07:00
Kris Nuttycombe 62b86d6afc Use CKeyID and CScriptID instead of new P2PKH/P2SHAddress classes. 2022-01-06 13:44:45 -07:00
Kris Nuttycombe b305ad2892 Remove the `InvalidEncoding` type from key & address variants.
The presence of this variant results in a situation where more
of the code than necessary needs to be aware of and handle
decoding failures. This change moves all handling of decoding
failures to the point of decoding.
2022-01-06 13:44:45 -07:00
Kris Nuttycombe 89755a114b
Merge pull request #5450 from nuttycom/feature/wallet_unified_addresses-fix_receiver_order
Make address serialization respect encoding order.
2022-01-06 12:17:10 -07:00
Kris Nuttycombe fe777c5624 Fix encoding order of unified addresses. 2022-01-05 18:30:06 -07:00
Kris Nuttycombe 98967e2ec7 Merge remote-tracking branch 'upstream/master' into feature/wallet_unified_addresses 2022-01-05 18:20:31 -07:00
Kris Nuttycombe 0403799be2
Merge pull request #5454 from zcash/hotfix-v4.6.0-1
Hotfix v4.6.0-1
2022-01-05 18:15:33 -07:00
str4d fe7b87a96c
Merge pull request #5452 from str4d/release-v4.6.0-1
Release v4.6.0-1
2022-01-05 22:18:46 +00:00
Jack Grigg daef0041e0 Add release notes for v4.6.0-1 2022-01-05 20:24:29 +00:00
Jack Grigg cf22fa7fe3 make-release.py: Updated release notes and changelog for 4.6.0-1. 2022-01-05 20:18:43 +00:00
Jack Grigg b97133daaf make-release.py: Updated manpages for 4.6.0-1. 2022-01-05 20:18:43 +00:00
Jack Grigg 5bf937b422 make-release.py: Versioning changes for 4.6.0-1. 2022-01-05 20:16:10 +00:00
str4d 7b820cfa8f
Merge pull request #5451 from zcash/2022-01-getblocktemplate-regression-fix
rpc: Fix regression in getblocktemplate output
2022-01-05 20:07:44 +00:00
Jack Grigg 4559186596 rpc: Fix regression in getblocktemplate output
We added support for the NU5 consensus rules in v4.5.0, which alters the
block header to contain a `hashBlockCommitments` value instead of the
chain history root. However, the output of `getblocktemplate` wasn't
returning this value; once NU5 activated, the `blockcommitmentshash`
field was being set to "null" (all-zeroes).

In v4.6.0 we added full NU5 support to `getblocktemplate`, by adding a
`defaultroots` field that gave default values for `hashBlockCommitments`
and the components required to derive it. However, in doing so we
introduced a regression in the (now-deprecated) legacy fields, where
prior to NU5 activation they contained nonsense.

This commit fixes the output of `getblocktemplate` to have the intended
semantics for all fields:

- The `blockcommitmentshash` and `authdataroot` fields in `defaultroots`
  are now omitted from block templates for heights before NU5 activation.

- The legacy fields now always contain the default value to be placed
  into the block header (regaining their previous semantics).

Co-authored-by: Larry Ruane <larry@z.cash>
2022-01-05 12:07:46 +00:00
Larry Ruane 97a76f1b61 test: Fix ZIP 244 implementation
Script codes must be serialized in their field encoding, which
includes the CompactSize length prefix.

Co-authored-by: Jack Grigg <jack@z.cash>
2022-01-05 12:07:46 +00:00
Larry Ruane dfefab2f55 test: check getblocktemplate output before and after NU5
This test currently fails with submitblock returning the error
"bad-heartwood-root-in-block".

Added authdigest to GBT coinbasetxn field because we can't obtain this
via getrawtransaction.

Co-authored-by: Jack Grigg <jack@z.cash>
2022-01-05 12:07:46 +00:00
str4d 1d7a29ea56
Merge pull request #5395 from nuttycom/feature/wallet_orchard-unified_addrs
Add unified addresses to the zcashd wallet.
2022-01-05 02:30:30 +00:00
Kris Nuttycombe eb53abbbaf Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2022-01-04 16:29:53 -07:00
Kris Nuttycombe ad54591061 Improve documentation of UFVK/UA metadata storage semantics. 2022-01-04 16:29:28 -07:00
Kris Nuttycombe 8d6d178a47 Use Bip44TransparentAccountKeyPath() for Bip44AccountChains keypath construction. 2022-01-04 16:29:28 -07:00
Kris Nuttycombe 16ba83ab1e Make `FindAddress` correctly check for maximum transparent child index.
ZcashdUnifiedFullViewingKey::FindAddress was previously not checking
that the transparent child index did not overflow in unified address
generation. GenerateUnifiedAddress has been modified to search from
the last known diversifier index if no diversifier is specified, and
boundary conditions for transparent addresses are now correctly handled.
2022-01-04 16:29:28 -07:00
Dimitris Apostolou 2006939d27
Fix typos 2022-01-02 23:16:01 +02:00
Kris Nuttycombe 0931aa8908
Merge pull request #5443 from steven-ecc/gtest-fix-for-debug-mode
Lock cs_main prior to calling blockToJSON
2021-12-30 11:18:14 -07:00
Kris Nuttycombe 5d07a8ae79 Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-12-30 10:53:51 -07:00
Steven Smith 56b706d5c7 Lock cs_main prior to calling blockToJSON 2021-12-29 21:22:19 -08:00
Daira Hopwood ba0688da3f
Merge pull request #5441 from LarryRuane/2021-12-28-test-submitblock
test: assert that the return value of submitblock is None
2021-12-29 14:02:57 +00:00
Larry Ruane 1f223ebed7 assert that the return value of submitblock is None 2021-12-28 22:10:13 -07:00
Kris Nuttycombe 74e4bef6f2 Ensure that unified address metadata is always correctly populated.
This reworks the way that address metadata is added to the wallet
to make adding address metadata to the wallet's in-memory cache
the responsibility of a single method rather than distributed
across multiple places in the code.
2021-12-23 09:33:17 -07:00
Sasha ba4b4791c1
Merge pull request #5436 from superbaud/release-v4.6.0
Release v4.6.0
2021-12-22 19:13:55 -08:00
Sasha 25278c312a str4d suggested changes to release-notes-4.6.0.md 2021-12-22 17:36:39 -08:00
Sasha eeecf63dae make-release.py: Updated release notes and changelog for 4.6.0. 2021-12-23 00:35:41 +00:00
Sasha de4dd9f231 make-release.py: Updated manpages for 4.6.0. 2021-12-23 00:35:40 +00:00
Sasha baa3de9250 make-release.py: Versioning changes for 4.6.0. 2021-12-23 00:13:51 +00:00
Sasha bc6e565bcc
Merge pull request #5431 from LarryRuane/2021-12-test-getblocktemplate-submitblock
test: Use result of getblocktemplate to submitblock
2021-12-22 16:06:42 -08:00
Kris Nuttycombe ad5c4dcf09 Remove unused ufvkid argument from AddTransparentSecretKey
All of the necessary relationships between transparent receivers
and UFVKs are set up by `AddUnifiedAddress`, so there's no
need to do so as part of transparent key management otherwise.
2021-12-22 16:09:17 -07:00
Kris Nuttycombe 900cd50741 Rename `ZcashdUnifiedSpendingKeyMetadata` -> `ZcashdUnifiedAccount`
Also, fix a couple of minor documentation issues and
make UA generation tests a little more robust.
2021-12-22 16:09:17 -07:00
Kris Nuttycombe 24e46a16f1 Only derive ZcashdUnifiedFullViewingKey from UnifiedFullViewingKey
This changes ZcashdUnifiedSpendingKey::ToUnifiedFullViewingKey
to return a `UnifiedFullViewingKey` object. This makes the
derivation of ZcashdUnifiedFullViewingKey values more regular,
removing the need to be able to construct these values directly
from the spending key.

This change also modifies ZcashdUnifiedSpendingKey to remove
the `std::optional` wrapper from its member keys. This
optionality is spurious, because it is always possible to
derive a "complete" spending key, and we do not support
import of unified spending keys.
2021-12-22 16:09:17 -07:00
Kris Nuttycombe 735ecd0906 Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2021-12-22 15:57:47 -07:00
Kris Nuttycombe 9b72fff365 Fix handling of unified full viewing key metadata.
This fixes two issues with the management of unified full viewing
key metadata:
* Adds a reverse mapping from ufvkid to account id.
* Ensures that UFVK metadata is correctly initialized when USK
  metadata is loaded from disk.
2021-12-22 15:57:47 -07:00
Kris Nuttycombe b34fd6a816 Add test for CKeyStore::AddUnifiedAddress 2021-12-22 15:57:47 -07:00
Kris Nuttycombe 009ba76b0e Add test for wallet UA generation & detection. 2021-12-22 15:57:47 -07:00
Kris Nuttycombe 700b98f0b0 Add tests for keystore storage and retrieval of UFVKs. 2021-12-22 15:57:47 -07:00
Kris Nuttycombe 0dcdc28a38 Add CWallet::GetUnifiedForReceiver 2021-12-22 15:57:47 -07:00
Kris Nuttycombe 8337442553 Add newly generated transparent UA receivers to the wallet. 2021-12-22 15:57:47 -07:00
Kris Nuttycombe 290985ba48 AddTransparentSecretKey does not need to take a CExtKey 2021-12-22 15:57:47 -07:00
Kris Nuttycombe b29ca10b8d Add unified address generation.
Generate unified addresses from UFVKs, and add the associated
metadata to the wallet database.
2021-12-22 15:57:47 -07:00
Kris Nuttycombe ca20cf512c Add key metadata to walletdb. 2021-12-22 15:57:47 -07:00
Kris Nuttycombe d869d7f4a3 Load unified full viewing keys from the walletdb. 2021-12-22 15:57:47 -07:00
Kris Nuttycombe e56f252a86 Add unified address tracking to KeyStore 2021-12-22 15:55:36 -07:00
Kris Nuttycombe ef068c51a9 Store ufvks to the wallet database. 2021-12-22 15:55:36 -07:00
Larry Ruane b538577359 test: Use result of getblocktemplate to submitblock
This will ensure that miners can use the values returned by
getblocktemplate (in particular, the block commitment hash)
to submit a valid block using the submitblock RPC.
2021-12-22 15:35:46 -07:00
Larry Ruane 8c0177a507 test: fix bugs in test framework 2021-12-22 15:05:38 -07:00
Charlie O'Keefe a2a66df5e0
Merge pull request #5435 from charlieok/add_libtinfo5_to_gitian_packages_list
Add libtinfo5 to gitian packages list
2021-12-21 11:06:43 -08:00
Charlie O'Keefe 04c292a379 Add libtinfo5 to gitian packages list
libtinfo5 is a build dependency of zcashd
https://zcash.readthedocs.io/en/latest/rtd_pages/Debian-Ubuntu-build.html
2021-12-21 09:17:51 -07:00
str4d 213ba58fae
Merge pull request #5434 from superbaud/config.offline-update
update librustzcash hash in config.offline, and remove all other repos from config.offline
2021-12-21 03:02:52 +00:00
Sasha 87101eeaed
only librustzcash in config.offline 2021-12-20 17:11:25 -08:00
Sasha 4e928fa67f
update hash for librustzcash 2021-12-20 16:25:05 -08:00
str4d 3acc68548e
Merge pull request #5300 from LarryRuane/feature/wallet_orchard
Feature/wallet orchard UA RPCs
2021-12-20 20:31:10 +00:00
str4d 12e022a53a
Merge pull request #5430 from str4d/release-v4.6.0-rc1
Release v4.6.0-rc1
2021-12-18 06:30:31 +00:00
Jack Grigg 9c4a1e7ad7 make-release.py: Updated release notes and changelog for 4.6.0-rc1. 2021-12-18 04:25:50 +00:00
Jack Grigg 1c910cf9cc make-release.py: Updated manpages for 4.6.0-rc1. 2021-12-18 04:25:50 +00:00
Jack Grigg d4b850d3f7 make-release.py: Versioning changes for 4.6.0-rc1. 2021-12-18 04:23:05 +00:00
str4d 75b539400c
Merge pull request #5429 from str4d/pre-4.6.0-rc1-changes
Pre-4.6.0-rc1 changes
2021-12-18 04:07:03 +00:00
Jack Grigg 8387aa40cf Update release notes 2021-12-18 01:44:27 +00:00
Jack Grigg d85bfb4744 Migrate to latest revisions of Zcash Rust crates 2021-12-18 01:44:27 +00:00
str4d eb175dddaa
Merge pull request #5426 from str4d/5379-revert-lint-fix
Revert lint: Fix false positive
2021-12-17 22:05:17 +00:00
Kris Nuttycombe 8b093a79da
Merge pull request #5402 from LarryRuane/2021-12-getblocktemplate
Add defaultroots field to getblocktemplate
2021-12-17 12:28:06 -07:00
str4d 72aad89859
Merge pull request #5404 from LarryRuane/2021-12-05-getmininginfo
[rpc] mining: Omit uninitialized currentblockweight, currentblocktx
2021-12-17 18:07:44 +00:00
MarcoFalke 6d60f1a9c9 [rpc] mining: Omit uninitialized currentblockweight, currentblocktx
zcash/zcash:
The `getmininginfo` RPC now omits `currentblockize` and `currentblocktx`
when a block was never assembled via RPC on this node during its current
process instantiation. The relevant RPCs are `generate` (regtest only) and
`getblocktemplate`. Blocks are also assembled when running the internal
miner (`zcashd -gen=1`), after the node mines its first block.

(cherry picked from commit bitcoin/bitcoin@fa178a6385)
2021-12-17 09:35:30 -07:00
str4d 9e4b6f670d
Merge pull request #5398 from str4d/ed25519-zebra-3
`ed25519-zebra` 3
2021-12-17 03:55:46 +00:00
Larry Ruane c937ba5ae5 getblocktemplate: add NU5 commitments to new `defaultroots` section
- merkleroot
- authdataroot
- chainhistoryroot
- blockcommitmentshash
2021-12-16 18:52:04 -07:00
Kris Nuttycombe 5c2d91589f
Merge pull request #5427 from str4d/5321-remove-misleading-log-message
rust: Remove misleading log message
2021-12-16 17:44:49 -07:00
str4d 34a8677c43
Merge pull request #5403 from LarryRuane/2021-12-nuparams
test: automatically add missing nuparams (network upgrade heights)
2021-12-17 00:42:04 +00:00
Jack Grigg 1b7a031e7b rust: Remove misleading log message
We use the `zcash_address` crate to parse Unified Addresses (which we
currently do nothing with). That crate returns an `UnsupportedAddress`
error for unhandled address kinds, which we were previously logging.
However, we _do_ support the other address kinds; we just parse them in
the C++ code.

Closes zcash/zcash#5321.
2021-12-16 22:22:05 +00:00
Jack Grigg 09e0af815f Revert "lint: Fix false positive"
This reverts commit fb38cf0d90.

The lint fix caused a problem on macOS, where the escaped double quote
was interpreted as part of an argument, and not as defining an argument.
We will need to find another way to address the lint.

Closes zcash/zcash#5379.
2021-12-16 21:54:48 +00:00
str4d 6a57389f38
Merge pull request #5424 from str4d/update-deps-4.6.0
Update dependencies for 4.6.0
2021-12-16 20:57:43 +00:00
Kris Nuttycombe ceeede3dc6
Merge pull request #5422 from LarryRuane/2021-12-getspentindex-logging
Dont log ERROR: spent index not enabled
2021-12-16 12:58:10 -07:00
Jack Grigg 407a0d9324 qa: Postpone recent CCache releases 2021-12-16 17:58:05 +00:00
Jack Grigg c37a69a357 depends Update Rust to 1.57.0
Also adds a developer script to make updating the hashes easier.
2021-12-16 17:57:34 +00:00
Jack Grigg 0d310a79ca depends: Update Boost to 1.78.0 2021-12-16 17:57:34 +00:00
Kris Nuttycombe fc1a16f4ff
Merge pull request #5423 from nuttycom/fix/orchard_batch_verifydb
Batch-verify Orchard transactions at the block level.
2021-12-16 10:43:09 -07:00
Jack Grigg e257844261 cargo update
In the three days since the last update, `futures 0.3.18` was yanked due
to panics: https://github.com/rust-lang/futures-rs/issues/2529
2021-12-16 16:55:11 +00:00
Kris Nuttycombe 99b2098f89 Batch-verify Orchard transactions at the block level.
Fixes #5316
2021-12-16 08:58:14 -07:00
Larry Ruane f139cdc4fe Add new and modify existing Orchard RPCs, non-functional
The new RPCs aren't functional, only have argument parsing and sample
outputs, guarded by experimental -orchardwallet flag.

These changes used the tickets linked from
https://github.com/zcash/zcash/issues/5056 as a guide.
2021-12-15 16:40:23 -07:00
Kris Nuttycombe 6d36921b94 Add unified key components to the transparent & Sapling wallet parts. 2021-12-15 13:53:10 -07:00
Kris Nuttycombe 24ff7b36ec Add ZcashdUnifiedKeyMetadata and libzcash::ReceiverType 2021-12-15 13:53:10 -07:00
Kris Nuttycombe 4966bf315a Compute key id for UFVKs. 2021-12-15 13:53:10 -07:00
Kris Nuttycombe 6f702c72a7
Merge pull request #5421 from nuttycom/feature/wallet_unified_addresses-mnemonic_seed_init_validation
Check the output of zip339_phrase_to_seed in MnemonicSeed initialization.
2021-12-15 12:21:15 -07:00
Kris Nuttycombe 00bda351f8 Check the output of zip339_phrase_to_seed in MnemonicSeed initialization.
zip339_phrase_to_seed will return `false` if the string it is being
used to convert to a seed is not valid UTF-8, but this result was
previously unchecked.

Fixes #5399
2021-12-15 08:21:44 -07:00
Larry Ruane d0e836a15e Don't log 'ERROR: spent index not enabled' 2021-12-15 07:53:26 -07:00
Kris Nuttycombe 48446b5e39 Add functions for generating BIP-44 and ZIP-32 keypaths 2021-12-14 15:10:27 -07:00
Larry Ruane cc70cd2c46 add -orchardwallet experimental feature flag
Also, temporarily don't allow -orchardwallet if running mainnet.
2021-12-14 14:42:08 -07:00
Larry Ruane d0b85b69f3 add ParseArbitraryInt() for diversifier index 2021-12-14 14:42:08 -07:00
str4d 87eeee0607
Merge pull request #5400 from nuttycom/feature/wallet_orchard-ufvks
Add types & FFI for serialization of unified full viewing keys.
2021-12-14 21:38:53 +00:00
Kris Nuttycombe 1e18410b55 Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-12-14 13:02:41 -07:00
Kris Nuttycombe d1890ebd24 Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2021-12-13 21:03:36 -07:00
Kris Nuttycombe 6cccc4ad3c Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-12-13 18:53:27 -07:00
Kris Nuttycombe 8ae8ddd7d1 Add tests for ufvk roundtrip serialization. 2021-12-13 18:53:27 -07:00
Kris Nuttycombe 22cd218e83 Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-12-13 18:53:27 -07:00
Kris Nuttycombe 217c56811d Add UnifiedFullViewingKey type.
This type is backed by the `zcash_address` implementaion of
unified full viewing keys. It is intended for serialization
and parsing of UFVKs, and provides conversion functions that
allow for construction to and from ZcashdUnifiedFullViewingKey
values.
2021-12-13 18:53:27 -07:00
Kris Nuttycombe c78887a148 Add Rust FFI components for unified full viewing keys. 2021-12-13 18:53:27 -07:00
Kris Nuttycombe 4257abd328 Adds SaplingDiversifiableFullViewingKey
Adds SaplingDiversifiableFullViewingKey as a superclass of
SaplingExtendedFullViewingKey, and reduces the Sapling component
of UnifiedFullViewingKey to the new intermediate type. This
permits deserialization from the data that will be present
in the serialized form of the Sapling component of a UFVK.
2021-12-13 18:53:25 -07:00
Kris Nuttycombe 640f31463f Update to ufvk zcash_address build. 2021-12-13 18:51:15 -07:00
Jack Grigg df0534e35a cargo update
Thanks to metrics-rs/metrics#231 being merged, our dependency tree is
now almost entirely de-duplicated!
2021-12-13 21:27:02 +00:00
Larry Ruane 7fa0e1a6a9 test: automatically add missing nuparams
This test-only change allows python (rpc) tests to specify, for example,
that NU5 should be activated at height X, without having to specify all
the previous network upgrades. Previous upgrades can (and must) still be
specified if they activate at different block heights (than, in this
example, NU5). This makes tests easier to write (and read), especially
as the number of network upgrades increases over time.

Note that this change only affects zcashd behavior in regtest mode. For
the other network modes (testnet and mainnet), the activation heights
are hard-coded in chainparams.cpp.
2021-12-06 17:32:18 -07:00
Kris Nuttycombe c908a3b059
Merge pull request #5396 from nuttycom/feature/wallet_orchard-unified_addrs_prereq
Prerequisites for adding unified addresses to the wallet.
2021-11-30 18:24:50 -07:00
Kris Nuttycombe 3bfb9d0c84 Remove ZcashdUnifiedAddress in favor of UnifiedAddress 2021-11-30 12:58:29 -07:00
Kris Nuttycombe a2f8e3b56c Use CKeyID and CScriptID instead of new P2PKH/P2SHAddress classes. 2021-11-30 11:24:37 -07:00
Kris Nuttycombe d65200c860 Refine structure of Zcash address generation.
This commit does not include functional changes; it merely
breaks up content previously included in `zcash/address/zip32.h`
into smaller and more focused components.
2021-11-30 11:22:37 -07:00
Kris Nuttycombe aa808eb07d
Merge pull request #5357 from nuttycom/feature/wallet_orchard-add_key_types
Add Orchard Address, IncomingViewingKey, and FullViewingKey types.
2021-11-30 07:13:22 -07:00
Kris Nuttycombe 782c705cb1 Remove Orchard spending key equality implementation. 2021-11-29 14:26:25 -07:00
Kris Nuttycombe bde245d8bc
Remove incorrect FFI method documentation.
Co-authored-by: str4d <jack@electriccoin.co>
2021-11-29 13:08:30 -07:00
Kris Nuttycombe e7c507cfb3 Update orchard & librustzcash dependency versions. 2021-11-29 13:05:54 -07:00
Jack Grigg 6c0bd90ee6 ed25519-zebra 3 2021-11-29 20:01:57 +00:00
Jack Grigg 5ae516f7b0 cargo update 2021-11-29 19:56:48 +00:00
Kris Nuttycombe 6ee0dea218 Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-11-26 08:41:52 -07:00
Kris Nuttycombe 59a4c84112 Adds Orchard Address, IncomingViewingKey, FullViewingKey, and SpendingKey types. 2021-11-24 19:08:17 -07:00
Kris Nuttycombe 8f5591a9c1 Add libzcash::AccountId type. 2021-11-24 18:59:25 -07:00
Kris Nuttycombe 7aaefab2d7
Merge pull request #5389 from superbaud/docker-volume-readme-patch
Correct typo in docker run's volume argument.
2021-11-24 13:24:54 -07:00
Kris Nuttycombe 9202b127d0 Merge remote-tracking branch 'upstream/master' into feature/wallet_orchard 2021-11-23 18:38:07 -07:00
str4d c76b756a68
Merge pull request #5356 from nuttycom/feature/wallet_orchard-rename_tree_types
Rename OrchardMerkleTree -> OrchardMerkleFrontier, remove IncrementalSinsemillaTree
2021-11-23 20:34:23 +00:00
Kris Nuttycombe f49f4c73d8 Rename OrchardMerkleTree -> OrchardMerkleFrontier
Remove IncrementalSinsemillaTree; this will be replaced by
a more full-featured OrchardWallet type which embeds the
incremental merkle tree used in wallet operations.
2021-11-23 07:27:34 -07:00
str4d f8e99e7ba5
Merge pull request #5373 from ZcashFoundation/lib-zcash-script-sigops
Add legacy sigops counts to the zcash_script library API
2021-11-22 16:03:48 +00:00
Kris Nuttycombe 13b9a69230
Merge pull request #5306 from nuttycom/feature/mnemonic_seeds
Adds HD seed derivation from ZIP-339 mnemonic phrases.

This replaces random generation of transparent spending keys with BIP-44-compatible derivation from a mnemonic seed phrase, and replaces the random HD seed previously used for Sapling HD key derivation
with the same mnemonic seed. After this change, all new transparent and Sapling addresses
will be derived from a new randomly generated mnemonic seed, which is produced in such a way that 
it is guaranteed to produce valid unified spending keys at account 0 for all address types.

Closes #5176.
Closes #2673.
2021-11-18 17:52:36 -07:00
Kris Nuttycombe c7089d2086
Merge pull request #5374 from rex4539/typos
Fix typos
2021-11-18 15:08:13 -07:00
Kris Nuttycombe 14f95572fa
Improve documentation of the `-walletrequirebackup` zcashd wallet configuration option. 2021-11-18 15:05:46 -07:00
Kris Nuttycombe 7be1ec9c23
Minor textual fixes to release notes.
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-11-18 11:40:23 -07:00
Sasha 2d25e08fcc
fix typo in docker run's volume argument 2021-11-18 10:39:52 -08:00
Kris Nuttycombe 92445ba0a5 Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2021-11-18 10:54:12 -07:00
str4d e9f450281b
Merge pull request #5388 from str4d/ci-pyflakes
CI: Add Pyflakes to lints workflow
2021-11-18 17:23:35 +00:00
str4d 0268ce0ad0
Merge pull request #5370 from str4d/dep-updates
Dependency updates
2021-11-18 15:01:09 +00:00
Jack Grigg 9fd44c76fa CI: Add Pyflakes to lints workflow 2021-11-18 14:45:39 +00:00
Jack Grigg 675e489aff rust: Move `incremental_sinsemilla_tree_ffi` into crate root
Having this be a submodule of `orchard_ffi` while following Rust 2018
module structure made it impossible to use the `include!` macro on
`orchard_ffi.rs`, which is exactly what the `zcash_script` crate does.
See this comment for details:
    https://github.com/rust-lang/rust/issues/50132#issuecomment-969450868

To resolve this, we restructure the FFI library crate to only have FFI
methods in "leaf" module files.
2021-11-18 11:40:16 +00:00
Kris Nuttycombe 2ec7073459 Fix error message text to refer to zcashd-wallet-tool rather than the RPC method. 2021-11-17 18:03:11 -07:00
Kris Nuttycombe b1d6a514e2 Parameterize HD keypath parsing by coin type. 2021-11-17 18:01:28 -07:00
Kris Nuttycombe b722c40fe2 Minor naming fixes 2021-11-17 18:01:28 -07:00
Kris Nuttycombe 0fe1134337 Only maintain CKeyID for the transparent part of ZcashdUnifiedAddress 2021-11-17 18:01:28 -07:00
Kris Nuttycombe cfee863644 Add diversifier_index_t::ToTransparentChildIndex 2021-11-17 18:01:28 -07:00
Kris Nuttycombe 6e6359229a Use MnemonicSeed instead of HDSeed where appropriate. 2021-11-17 18:01:28 -07:00
Kris Nuttycombe f31b3c2190 Update documentation for GenerateNewSeed. 2021-11-17 18:01:28 -07:00
Kris Nuttycombe 7860d6ede3 Generalize keypath parsing over account id. 2021-11-17 18:01:28 -07:00
Kris Nuttycombe f65d6f63ee Minor cleanup of the code that searches for a valid transparent key. 2021-11-17 18:01:28 -07:00
Kris Nuttycombe de57da38ce Document mnemonic-seed-related RPC method changes & update changelog. 2021-11-17 18:01:28 -07:00
teor bdbd86edb7 Explain how to get rid of a tiny duplicated function 2021-11-16 18:29:04 +00:00
teor f4a8dc57e0 Explain UINT_MAX error return value 2021-11-16 18:29:04 +00:00
teor 7d24ada757 Remove redundant variable
Co-authored-by: str4d <thestr4d@gmail.com>
2021-11-16 18:29:04 +00:00
teor 3bae89c732 Use correct copyright header
Co-authored-by: str4d <thestr4d@gmail.com>
2021-11-16 18:29:04 +00:00
teor 77ab1831a1 Remove an unused header 2021-11-16 18:29:04 +00:00
teor fa181a2d08 Increment the zcash_script API version 2021-11-16 18:29:04 +00:00
teor 31bd2ba4f1 Add sigop count functions to zcash_script library 2021-11-16 18:29:04 +00:00
Janito Vaqueiro Ferreira Filho ae9266a1cd Move `CurrentTxVersionInfo` into a new file
Don't compile it for `zcash_script`.
2021-11-16 18:29:04 +00:00
Dimitris Apostolou e05c1ddf8a
Fix typos 2021-11-14 16:27:09 +02:00
Kris Nuttycombe f626673b89 Fix polymorphism of string serialization.
Co-authored-by: str4d <jack@electriccoin.co>
2021-11-07 10:16:22 -07:00
Kris Nuttycombe ea8e9438af Fix name of menmonic entropy length constant. 2021-11-07 10:16:22 -07:00
Kris Nuttycombe a67fb00d0a Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2021-11-07 10:16:22 -07:00
Kris Nuttycombe 399ed5b4d7 Do not strip quotes when verifying mnemonic seed. 2021-11-07 10:16:22 -07:00
Kris Nuttycombe 551072165a Style fix in BIP 32 path account parsing test. 2021-11-07 10:16:22 -07:00
Kris Nuttycombe 6fdded20bc Restore legacy HDSeed encryption tests. 2021-11-07 10:16:22 -07:00
Kris Nuttycombe d84845d199 Clean up handling of mnemonic seed metadata. 2021-11-07 10:16:22 -07:00
Jack Grigg 5eca8d34ba depends: Update Clang / libcxx to LLVM 13 2021-11-06 21:44:24 +00:00
Jack Grigg 373206027f depends: Update Rust to 1.56.1 2021-11-06 21:06:30 +00:00
Jack Grigg 1364db2ded Bump all postponed dependencies 2021-11-06 21:06:30 +00:00
Jack Grigg ca7160ebab tracing-subscriber 0.3 2021-11-06 21:06:30 +00:00
Jack Grigg 2005c91d41 cargo update 2021-11-06 21:06:30 +00:00
Kris Nuttycombe 4080f48868 Fix max transparent diversifier index. 2021-11-01 21:18:14 -06:00
Kris Nuttycombe 87f7e5fbba Fix naming of unified spending & full viewing keys 2021-11-01 21:12:41 -06:00
Kris Nuttycombe cd01b2d9bf Fix transparent BIP-44 keypaths. 2021-11-01 21:06:32 -06:00
Kris Nuttycombe b54d4cac7d Restore FindAddress comment 2021-11-01 10:13:19 -06:00
Kris Nuttycombe e4e77eb389 Fix diversifier_index_t less than operator. 2021-10-30 08:26:59 -06:00
Kris Nuttycombe 0951fe22d8 Apply suggestions from code review
Co-authored-by: str4d <jack@electriccoin.co>
2021-10-30 08:26:59 -06:00
Kris Nuttycombe 67557df165 Use SecureString for mnemonic phrase. 2021-10-30 08:26:59 -06:00
Kris Nuttycombe d09a0c44f3 Clean up format of recovery information in the wallet dump. 2021-10-29 13:38:36 -06:00
Kris Nuttycombe 30517a002b Move CKeyMetadata back to wallet.h 2021-10-29 13:38:36 -06:00
Kris Nuttycombe dbcdc560de Fix spurious test passage. 2021-10-29 13:38:36 -06:00
Kris Nuttycombe 22fa6b22ea Restore legacy HD seed storage & retrieval tests. 2021-10-29 13:38:36 -06:00
Kris Nuttycombe b67e62d977 Address comments from code review. 2021-10-29 13:38:36 -06:00
Kris Nuttycombe 477a166565 Use hardened derivation for the legacy Sapling key at the address index level. 2021-10-29 13:38:36 -06:00
Kris Nuttycombe 8bf4ec3b4a Require backup of the emergency recovery phrase.
After 4.5.2, all wallets will be populated with an emergency
recovery phrase, and all future addresses will be derived from
the associated seed. To prevent potential loss of funds, we
require that the user explicitly invoke the `walletconfirmbackup`
RPC method to verify that they have backed up this seed.
2021-10-29 13:38:36 -06:00
Kris Nuttycombe 5760a639d2 Use 0x7FFFFFFF for the legacy account ID. 2021-10-25 14:09:21 -06:00
Kris Nuttycombe d6984dbf78 Fix wallet import/export test 2021-10-21 11:44:08 -06:00
Kris Nuttycombe e0ae5362c9 Revert change to the type of GenerateNewKey 2021-10-21 08:21:13 -06:00
Kris Nuttycombe d8d9cd129e Use legacy address for Sapling migration until UA functionality is available to the RPC tests. 2021-10-20 17:13:52 -06:00
Kris Nuttycombe ebab190fdf Replace account ID with ZIP-0032 key path in listaddresses output.
Account ID information is insufficiently granular to identify separate
pools of spend authority.
2021-10-20 13:33:47 -06:00
Kris Nuttycombe dc2c07bbde Generate legacy Sapling addresses from the mnemonic seed.
This further deprecates the legacy seed, by no longer using it
as a source of randomness. Instead of continuing to rely on
successive account identifiers for the legacy seed, it now
takes advantage of the `m/32'/coin_type'/account'/addressIndex'`
keypath scheme defined by ZIP 32. For the purpose of the zcashd
wallet, the account identifier used in generation of Sapling
addresses associated with the legacy address generation code
path is fixed to 0x7FFFFFFE, the same as the account used for
all future transparent address generation.
2021-10-20 13:33:47 -06:00
Kris Nuttycombe 2885ae7643 Derive transparent keys from mnemonic seed. 2021-10-19 17:51:14 -06:00
Kris Nuttycombe 666d135e2e Apply suggestions from code review
Co-authored-by: Daira Hopwood <daira@jacaranda.org>
2021-10-19 11:48:02 -06:00
Kris Nuttycombe daf443c9e6 Update librustzcash dependency version. 2021-10-19 11:48:02 -06:00
Kris Nuttycombe 8f1d58f16f Remove unused forward declaration. 2021-10-19 11:48:02 -06:00
Kris Nuttycombe f99f2e4b3f Fix tests for wallet operations on legacy Sapling keys. 2021-10-19 11:48:02 -06:00
Kris Nuttycombe 290b2e4e39 Use the default UA-based Sapling address for the saplingmigration tool. 2021-10-19 11:48:02 -06:00
Kris Nuttycombe f6ad523ccb Add unified full viewing keys and Zcash-internal unified addresses. 2021-10-19 11:48:02 -06:00
Kris Nuttycombe 83dee7e886 Adds basic unified spending key derivation.
Also, begin pruning Sapling key derivation down to the
minimal amount required to support the legacy Sapling
key derivation process.
2021-10-19 11:48:02 -06:00
Kris Nuttycombe 8883ae8b9e Add support for externally searching for valid Sapling diversifiers.
In order to support generation of unified addresses, it needs
to be possible for the code generating a unified address to search
the space of Sapling diversifiers to obtain a valid diversifier.

Historically, invalid diviersifiers were simply skipped, so we retain
this behavior when obtaining a Sapling address from the legacy HD seed.
2021-10-19 11:48:02 -06:00
Kris Nuttycombe 5677649af1 Derive random HD seeds from ZIP-339 seed phrases.
Add support for dump of legacy HD seeds & persistence of mnemonic-based seeds.
2021-10-19 11:48:02 -06:00
Charlie O'Keefe 21d6835efa Update base image used by Dockerfile from debian 10 to debian 11
I built a docker image with this change and verified that it successfully started zcashd
2021-09-23 14:03:29 -06:00
220 changed files with 12150 additions and 4924 deletions

View File

@ -1,29 +1,9 @@
[source.crates-io]
replace-with = "vendored-sources"
[source."https://github.com/ZcashFoundation/ed25519-zebra.git"]
git = "https://github.com/ZcashFoundation/ed25519-zebra.git"
rev = "d3512400227a362d08367088ffaa9bd4142a69c7"
replace-with = "vendored-sources"
[source."https://github.com/str4d/redjubjub.git"]
git = "https://github.com/str4d/redjubjub.git"
rev = "416a6a8ebf8bd42c114c938883016c04f338de72"
replace-with = "vendored-sources"
[source."https://github.com/zcash/incrementalmerkletree"]
git = "https://github.com/zcash/incrementalmerkletree"
rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb"
replace-with = "vendored-sources"
[source."https://github.com/zcash/librustzcash.git"]
git = "https://github.com/zcash/librustzcash.git"
rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e"
replace-with = "vendored-sources"
[source."https://github.com/zcash/orchard.git"]
git = "https://github.com/zcash/orchard.git"
rev = "2c8241f25b943aa05203eacf9905db117c69bd29"
rev = "5622b060b1f57de7afc3d0b4e425b9b4b22482a0"
replace-with = "vendored-sources"
[source.vendored-sources]

View File

@ -36,7 +36,7 @@ Please provide a general summary of the issue you're experiencing
Tell us what should happen
### Actual behaviour + errors
Tell us what happens instead including any noticable error output (any messages
Tell us what happens instead including any noticeable error output (any messages
displayed on-screen when e.g. a crash occurred)
### The version of Zcash you were using:

View File

@ -34,10 +34,6 @@ jobs:
if: always()
continue-on-error: true # Temporary until we get this passing
- name: Python UTF-8 encoding
run: ./test/lint/lint-python-utf8-encoding.sh
if: always()
- name: Shebang
run: ./test/lint/lint-shebang.sh
if: always()
@ -57,6 +53,22 @@ jobs:
run: ./test/lint/lint-whitespace.sh
if: always()
python:
name: Python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: sudo python3 -m pip install pyflakes
- name: Pyflakes
run: pyflakes qa src zcutil
if: always()
- name: UTF-8 encoding
run: ./test/lint/lint-python-utf8-encoding.sh
if: always()
rust-clippy:
name: Clippy (1.54.0)
runs-on: ubuntu-latest

506
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ repository = "https://github.com/zcash/zcash"
readme = "README.md"
license = "MIT OR Apache-2.0"
edition = "2018"
rust-version = "1.56"
[lib]
name = "rustzcash"
@ -26,28 +27,30 @@ crate-type = ["staticlib"]
[dependencies]
bellman = "0.11"
blake2b_simd = "0.5"
blake2s_simd = "0.5"
blake2b_simd = "1"
blake2s_simd = "1"
bls12_381 = "0.6"
byteorder = "1"
group = "0.11"
incrementalmerkletree = "0.1"
incrementalmerkletree = "0.2"
libc = "0.2"
jubjub = "0.8"
memuse = "0.2"
nonempty = "0.7"
orchard = "0.0"
orchard = "=0.1.0-beta.1"
secp256k1 = "0.20"
subtle = "2.2"
rand_core = "0.6"
tracing = "0.1"
tracing-core = "0.1"
tracing-appender = "0.1"
tracing-appender = "0.2"
zcash_address = "0.0"
zcash_history = "0.2"
zcash_note_encryption = "0.0"
zcash_primitives = "0.5"
zcash_note_encryption = "0.1"
zcash_primitives = { version = "0.5", features = ["transparent-inputs"] }
zcash_proofs = "0.5"
ed25519-zebra = "2.2.0"
ed25519-zebra = "3"
zeroize = "1.4.2"
# Metrics
hyper = { version = "=0.14.2", default-features = false, features = ["server", "tcp", "http1"] }
@ -58,9 +61,9 @@ thiserror = "1"
tokio = { version = "1.0", features = ["rt", "net", "time", "macros"] }
[dependencies.tracing-subscriber]
version = "0.2.12"
version = "0.3"
default-features = false
features = ["ansi", "chrono", "env-filter"]
features = ["ansi", "env-filter", "time"]
[profile.release]
lto = true
@ -68,11 +71,9 @@ panic = 'abort'
codegen-units = 1
[patch.crates-io]
ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" }
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" }
orchard = { git = "https://github.com/zcash/orchard.git", rev = "2c8241f25b943aa05203eacf9905db117c69bd29" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" }
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" }
hdwallet = { git = "https://github.com/nuttycom/hdwallet", rev = "576683b9f2865f1118c309017ff36e01f84420c9" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "4f4a25252f0fc6b84c44316d810107bc7ea7f32a" }
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "4f4a25252f0fc6b84c44316d810107bc7ea7f32a" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "4f4a25252f0fc6b84c44316d810107bc7ea7f32a" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "4f4a25252f0fc6b84c44316d810107bc7ea7f32a" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "4f4a25252f0fc6b84c44316d810107bc7ea7f32a" }

View File

@ -1,4 +1,4 @@
Zcash 4.5.1-1
Zcash 4.6.0-1
<img align="right" width="120" height="80" src="doc/imgs/logo.png">
===========

View File

@ -1,8 +1,8 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 4)
define(_CLIENT_VERSION_MINOR, 5)
define(_CLIENT_VERSION_REVISION, 1)
define(_CLIENT_VERSION_MINOR, 6)
define(_CLIENT_VERSION_REVISION, 0)
define(_CLIENT_VERSION_BUILD, 51)
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)))

View File

@ -1,3 +1,21 @@
zcash (4.6.0+1) stable; urgency=medium
* 4.6.0-1 release.
-- Electric Coin Company <team@electriccoin.co> Wed, 05 Jan 2022 20:18:43 +0000
zcash (4.6.0) stable; urgency=medium
* 4.6.0 release.
-- Electric Coin Company <team@electriccoin.co> Thu, 23 Dec 2021 00:35:41 +0000
zcash (4.6.0~rc1) stable; urgency=medium
* 4.6.0-rc1 release.
-- Electric Coin Company <team@electriccoin.co> Sat, 18 Dec 2021 04:25:50 +0000
zcash (4.5.1+1) stable; urgency=medium
* 4.5.1-1 release.

View File

@ -2,7 +2,11 @@
export LC_ALL=C
cargo deps --no-transitive-deps | dot \
# default arguments are --no-transitive-deps
ARGS="${*:---no-transitive-deps}"
echo "Using args: $ARGS"
cargo deps $ARGS | dot \
-Earrowhead=vee \
-Gratio=0.45 \
-Gsize=50 \

View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
export LC_ALL=C
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
RUST_PACKAGE="$SCRIPT_DIR/../../depends/packages/native_rust.mk"
RUST_VERSION=$( cat $RUST_PACKAGE | grep -oP "_version=\K.*" )
update_hash() {
url="https://static.rust-lang.org/dist/$1-$RUST_VERSION-$2.tar.gz"
echo "Fetching $url"
hash=$( curl $url | sha256sum | awk '{print $1}' )
sed -i "/\$(package)_$3_$4=/c\\\$(package)_$3_$4=$hash" $RUST_PACKAGE
}
update_rust_hash() {
update_hash rust $1 sha256_hash $2
}
update_stdlib_hash() {
update_hash rust-std $1 rust_std_sha256_hash $1
}
# For native targets
# update_rust_hash RUST_TARGET MAKEFILE_PACKAGE_IDENTIFIER
update_rust_hash aarch64-unknown-linux-gnu aarch64_linux
update_rust_hash x86_64-apple-darwin darwin
update_rust_hash x86_64-unknown-linux-gnu linux
update_rust_hash x86_64-unknown-freebsd freebsd
# For cross-compilation targets
# update_stdlib_hash RUST_TARGET
update_stdlib_hash aarch64-unknown-linux-gnu
update_stdlib_hash x86_64-apple-darwin
update_stdlib_hash x86_64-pc-windows-gnu
update_stdlib_hash x86_64-unknown-freebsd

View File

@ -1,4 +1,4 @@
FROM debian:10
FROM debian:11
RUN apt-get update \
&& apt-get install -y gnupg2 apt-transport-https curl

View File

@ -76,7 +76,7 @@ mkdir {./zcash-params-dir,./zcash-data-dir}
sudo chown -R 2001.2001 {./zcash-params-dir,./zcash-data-dir}
docker run -d --name my_zcashd \
-v $(pwd)/zcash-data-dir:/srv/zcashd/.zcash \
-v $(pwd)/zcash-params-dir/srv/zcashd/.zcash-params \
-v $(pwd)/zcash-params-dir:/srv/zcashd/.zcash-params \
electriccoinco/zcashd
```

View File

@ -1,5 +1,5 @@
---
name: "zcash-4.5.1-1"
name: "zcash-4.6.0-1"
enable_cache: true
distro: "debian"
suites:
@ -18,6 +18,7 @@ packages:
- "g++-multilib"
- "git-core"
- "libc6-dev"
- "libtinfo5"
- "libtool"
- "libxml2"
- "m4"

View File

@ -1,8 +1,8 @@
package=boost
$(package)_version=1_77_0
$(package)_version=1_78_0
$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$(subst _,.,$($(package)_version))/source/
$(package)_file_name=boost_$($(package)_version).tar.bz2
$(package)_sha256_hash=fc9f85fc030e233142908241af7a846e60630aa7388de9a5fafb1f3a26840854
$(package)_sha256_hash=8681f175d4bdb26c52222665793eef08490d7758529330f98d3b29dd0735bccc
$(package)_dependencies=native_b2
ifneq ($(host_os),darwin)

View File

@ -8,10 +8,10 @@ ifneq ($(host_os),mingw32)
$(package)_download_path=$(native_clang_download_path)
$(package)_download_file_aarch64_linux=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz
$(package)_file_name_aarch64_linux=clang-llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz
$(package)_sha256_hash_aarch64_linux=3d4ad804b7c85007686548cbc917ab067bf17eaedeab43d9eb83d3a683d8e9d4
$(package)_sha256_hash_aarch64_linux=968d65d2593850ee9b37fcda074fb7641529bd45d2f976af6c8197de3c22612f
$(package)_download_file_linux=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz
$(package)_file_name_linux=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz
$(package)_sha256_hash_linux=6b3cc55d3ef413be79785c4dc02828ab3bd6b887872b143e3091692fc6acefe7
$(package)_sha256_hash_linux=76d0bf002ede7a893f69d9ad2c4e101d15a8f4186fbfe24e74856c8449acd7c1
define $(package)_stage_cmds
mkdir -p $($(package)_staging_prefix_dir)/lib && \
@ -22,13 +22,13 @@ endef
else
# For Windows cross-compilation, use the MSYS2 binaries.
$(package)_download_path=https://repo.msys2.org/mingw/x86_64
$(package)_download_file=mingw-w64-x86_64-libc++-12.0.1-1-any.pkg.tar.zst
$(package)_file_name=mingw-w64-x86_64-libcxx-12.0.1-1-any.pkg.tar.zst
$(package)_sha256_hash=847d86435c35f12b4bc779c91c800a86499ba5c9d419d6ed5e2386c7582c2e81
$(package)_download_file=mingw-w64-x86_64-libc++-13.0.0-3-any.pkg.tar.zst
$(package)_file_name=mingw-w64-x86_64-libcxx-13.0.0-3-any.pkg.tar.zst
$(package)_sha256_hash=0f8819e88273579f7c9262456c6b8f4d73e1693095c2364d1192c61c5f6a1a4f
$(package)_libcxxabi_download_file=mingw-w64-x86_64-libc++abi-12.0.1-1-any.pkg.tar.zst
$(package)_libcxxabi_file_name=mingw-w64-x86_64-libcxxabi-12.0.1-1-any.pkg.tar.zst
$(package)_libcxxabi_sha256_hash=a60294cb611916f4b9db27b7a6f3d6dc0f75d9006ad6a5bb830427df9b5bc9d2
$(package)_libcxxabi_download_file=mingw-w64-x86_64-libc++abi-13.0.0-3-any.pkg.tar.zst
$(package)_libcxxabi_file_name=mingw-w64-x86_64-libcxxabi-13.0.0-3-any.pkg.tar.zst
$(package)_libcxxabi_sha256_hash=7224a7252a566938afe91ea8f130682abd29b10e13c9a3c2347af523ca0d7c42
$(package)_extra_sources += $($(package)_libcxxabi_file_name)

View File

@ -1,23 +1,22 @@
package=native_clang
$(package)_major_version=12
$(package)_version=12.0.1
$(package)_major_version=13
$(package)_version=13.0.0
$(package)_download_path=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version)
$(package)_download_path_linux=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version)
$(package)_download_file_linux=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz
$(package)_file_name_linux=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-16.04.tar.xz
$(package)_sha256_hash_linux=6b3cc55d3ef413be79785c4dc02828ab3bd6b887872b143e3091692fc6acefe7
$(package)_sha256_hash_linux=76d0bf002ede7a893f69d9ad2c4e101d15a8f4186fbfe24e74856c8449acd7c1
$(package)_download_path_darwin=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_major_version).0.0
$(package)_download_file_darwin=clang+llvm-$($(package)_major_version).0.0-x86_64-apple-darwin.tar.xz
$(package)_file_name_darwin=clang-llvm-$($(package)_major_version).0.0-x86_64-apple-darwin.tar.xz
$(package)_sha256_hash_darwin=7bc2259bf75c003f644882460fc8e844ddb23b27236fe43a2787870a4cd8ab50
$(package)_sha256_hash_darwin=d051234eca1db1f5e4bc08c64937c879c7098900f7a0370f3ceb7544816a8b09
$(package)_download_path_freebsd=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version)
$(package)_download_file_freebsd=clang+llvm-$($(package)_version)-amd64-unknown-freebsd12.tar.xz
$(package)_file_name_freebsd=clang-llvm-$($(package)_version)-amd64-unknown-freebsd12.tar.xz
$(package)_sha256_hash_freebsd=38857da36489880b0504ae7142b74abe41cf18711a6bb25ca96792d8190e8b0e
$(package)_sha256_hash_freebsd=e579747a36ff78aa0a5533fe43bc1ed1f8ed449c9bfec43c358d953ffbbdcf76
$(package)_download_file_aarch64_linux=clang+llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz
$(package)_file_name_aarch64_linux=clang-llvm-$($(package)_version)-aarch64-linux-gnu.tar.xz
$(package)_sha256_hash_aarch64_linux=3d4ad804b7c85007686548cbc917ab067bf17eaedeab43d9eb83d3a683d8e9d4
$(package)_sha256_hash_aarch64_linux=968d65d2593850ee9b37fcda074fb7641529bd45d2f976af6c8197de3c22612f
# Ensure we have clang native to the builder, not the target host
ifneq ($(canonical_host),$(build))

View File

@ -1,14 +1,14 @@
package=native_rust
$(package)_version=1.55.0
$(package)_version=1.57.0
$(package)_download_path=https://static.rust-lang.org/dist
$(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.tar.gz
$(package)_sha256_hash_linux=2080253a2ec36ac8ed6e060d30802d888533124b8d16545cfd4af898b365eaac
$(package)_sha256_hash_linux=ea0253784b2e5c22659ff148d492a68d2e11da734491714ebc61cc93896efcda
$(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz
$(package)_sha256_hash_darwin=2e345ac7724c192c9487a2c6bd4f6c52c884d791981510288830d27d9a0bf2f3
$(package)_sha256_hash_darwin=15ceffc4743434c19d08f73fb4edd6642b7fd8162ed7101d3e6ca2c691fcb699
$(package)_file_name_freebsd=rust-$($(package)_version)-x86_64-unknown-freebsd.tar.gz
$(package)_sha256_hash_freebsd=7ddb8ec4d431f64dd6428df93d46f726516970b0ca83c71c3efbfe34a42d3113
$(package)_sha256_hash_freebsd=ebe96fa1f15e8d70c91e81aab7e0c341717b909225029f37d52fbdfa506e3fab
$(package)_file_name_aarch64_linux=rust-$($(package)_version)-aarch64-unknown-linux-gnu.tar.gz
$(package)_sha256_hash_aarch64_linux=eebdb2e659ed14884a49f0457d44e5e8c9f89fca3414533752c6dbb96232c156
$(package)_sha256_hash_aarch64_linux=d66847f7cf7b548ecb328c400ac4f691ee2aea6ff5cd9286ad8733239569556c
# Mapping from GCC canonical hosts to Rust targets
# If a mapping is not present, we assume they are identical, unless $host_os is
@ -17,9 +17,10 @@ $(package)_rust_target_x86_64-pc-linux-gnu=x86_64-unknown-linux-gnu
$(package)_rust_target_x86_64-w64-mingw32=x86_64-pc-windows-gnu
# Mapping from Rust targets to SHA-256 hashes
$(package)_rust_std_sha256_hash_aarch64-unknown-linux-gnu=e30063a259e32cd0e31baadcee82112ef840e0f654d5128dd79fc715ede92058
$(package)_rust_std_sha256_hash_x86_64-apple-darwin=8888fb0a1cbc645f86e1551d27cc127697361fecab9cd414691e434976412733
$(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=8dfab5489b485417d76a7d266fc795608ba61f9c423f8a71616e01f33e146487
$(package)_rust_std_sha256_hash_aarch64-unknown-linux-gnu=4c70901d1cbddec9ea99fbd62b20f454d30e1ffbb48a21169ac823b3f02a1fbc
$(package)_rust_std_sha256_hash_x86_64-apple-darwin=c1eb892ddb50ebeed288b7aa8171ad46d62362bb26b2d82d2b463dfd45606dc2
$(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=75c910899ed36a90b155e3a01c21b863000675867efc56f2b68c44edd4b7e18c
$(package)_rust_std_sha256_hash_x86_64-unknown-freebsd=1528a4bc7e3ba42da164bcc7b952dfa73048333c5b9254ce2d03db6bab6081e8
define rust_target
$(if $($(1)_rust_target_$(2)),$($(1)_rust_target_$(2)),$(if $(findstring darwin,$(3)),x86_64-apple-darwin,$(if $(findstring freebsd,$(3)),x86_64-unknown-freebsd,$(2))))

View File

@ -1,29 +1,29 @@
Zcash Contributors
==================
Jack Grigg (1123)
Jack Grigg (1127)
Simon Liu (460)
Sean Bowe (367)
Daira Hopwood (270)
Eirik Ogilvie-Wigley (216)
Kris Nuttycombe (174)
Kris Nuttycombe (181)
Wladimir J. van der Laan (150)
Alfredo Garcia (116)
Taylor Hornby (114)
Marshall Gaucher (110)
Marshall Gaucher (111)
Pieter Wuille (102)
Jonas Schnelli (89)
Jay Graber (89)
Marco Falke (81)
Marco Falke (82)
Cory Fields (75)
Larry Ruane (61)
Larry Ruane (72)
Ying Tong Lai (56)
Nathan Wilcox (56)
Matt Corallo (52)
practicalswift (38)
Kevin Gallagher (38)
fanquake (36)
Dimitris Apostolou (34)
Dimitris Apostolou (35)
Carl Dong (26)
Gregory Maxwell (23)
Jorge Timón (22)
@ -46,12 +46,13 @@ Alex Morcos (11)
Philip Kaufmann (10)
Peter Todd (10)
João Barbosa (10)
Charlie O'Keefe (10)
nomnombtc (9)
Marius Kjærstad (9)
teor (8)
kozyilmaz (8)
Jeremy Rubin (8)
Jeff Garzik (8)
Charlie O'Keefe (8)
Ben Wilson (8)
Karl-Johan Alm (7)
ying tong (6)
@ -63,6 +64,7 @@ Chun Kuan Lee (6)
Casey Rodarmor (6)
jnewbery (5)
ca333 (5)
Sasha (5)
MeshCollider (5)
Johnathan Corgan (5)
George Tankersley (5)
@ -75,6 +77,7 @@ WO (4)
Sjors Provoost (4)
Russell Yanofsky (4)
Nate Wilcox (4)
Alex Wied (4)
mruddy (3)
lpescher (3)
isle2983 (3)
@ -90,7 +93,6 @@ Eric Lombrozo (3)
Danny Willems (3)
Anthony Towns (3)
Alfie John (3)
Alex Wied (3)
whythat (2)
rofl0r (2)
ptschip (2)
@ -134,7 +136,7 @@ vim88 (1)
unsystemizer (1)
tulip (1)
tpantin (1)
teor (1)
sgmoore (1)
randy-waterhouse (1)
plutoforever (1)
murrayn (1)
@ -202,6 +204,7 @@ Josh Ellithorpe (1)
Jonas Nick (1)
Jesse Cohen (1)
Jeffrey Walton (1)
Janito Vaqueiro Ferreira Filho (1)
Jainan-Tandel (1)
Igor Cota (1)
Ian T (1)

View File

@ -5,7 +5,7 @@ where possible.
## Adding new dependencies in online-Rust mode
The `zcashd` build system pins all dependencies, and in order to faciliate
The `zcashd` build system pins all dependencies, and in order to facilitate
deterministic builds, `cargo` is configured to run in offline mode with vendored
crates. This means that if, for example, you add the `foobar` crate to
`Cargo.toml`, you will likely see an error similar to this:

View File

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
.TH ZCASH-CLI "1" "October 2021" "zcash-cli v4.5.1-1" "User Commands"
.TH ZCASH-CLI "1" "January 2022" "zcash-cli v4.6.0-1" "User Commands"
.SH NAME
zcash-cli \- manual page for zcash-cli v4.5.1-1
zcash-cli \- manual page for zcash-cli v4.6.0-1
.SH DESCRIPTION
Zcash RPC client version v4.5.1\-1
Zcash RPC client version v4.6.0\-1
.PP
In order to ensure you are adequately protecting your privacy when using Zcash,
please see <https://z.cash/support/security/>.

View File

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
.TH ZCASH-TX "1" "October 2021" "zcash-tx v4.5.1-1" "User Commands"
.TH ZCASH-TX "1" "January 2022" "zcash-tx v4.6.0-1" "User Commands"
.SH NAME
zcash-tx \- manual page for zcash-tx v4.5.1-1
zcash-tx \- manual page for zcash-tx v4.6.0-1
.SH DESCRIPTION
Zcash zcash\-tx utility version v4.5.1\-1
Zcash zcash\-tx utility version v4.6.0\-1
.SS "Usage:"
.TP
zcash\-tx [options] <hex\-tx> [commands]

View File

@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13.
.TH ZCASHD "1" "October 2021" "zcashd v4.5.1-1" "User Commands"
.TH ZCASHD "1" "January 2022" "zcashd v4.6.0-1" "User Commands"
.SH NAME
zcashd \- manual page for zcashd v4.5.1-1
zcashd \- manual page for zcashd v4.6.0-1
.SH DESCRIPTION
Zcash Daemon version v4.5.1\-1
Zcash Daemon version v4.6.0\-1
.PP
In order to ensure you are adequately protecting your privacy when using Zcash,
please see <https://z.cash/support/security/>.

View File

@ -4,3 +4,90 @@ release-notes at release time)
Notable changes
===============
Mnemonic Recovery Phrases
-------------------------
The zcashd wallet has been modified to support BIP 39, which describes how to
derive the wallet's HD seed from a mnemonic phrase. The mnemonic phrase will
be generated on load of the wallet, or the first time the wallet is unlocked,
and is available via the `z_exportwallet` RPC call. All new addresses produced
by the wallet are now derived from this seed using the HD wallet functionality
described in ZIP 32 and ZIP 316. For users upgrading an existing Zcashd wallet,
it is recommended that the wallet be backed up prior to upgrading to the 4.5.2
Zcashd release.
Following the upgrade to 4.5.2, Zcashd will require that the user confirm that
they have backed up their new emergency recovery phrase, which may be obtained
from the output of the `z_exportwallet` RPC call. This confirmation can be
performed manually using the `zcashd-wallet-tool` utility that is supplied with
this release. The wallet will not allow the generation of new addresses until
this confirmation has been performed. It is recommended that after this
upgrade, that funds tied to preexisting addresses be migrated to newly
generated addresses so that all wallet funds are recoverable using the
emergency recovery phrase going forward. If you choose not to migrate funds in
this fashion, you will continue to need to securely back up the entire
`wallet.dat` file to ensure that you do not lose access to existing funds;
EXISTING FUNDS WILL NOT BE RECOVERABLE USING THE EMERGENCY RECOVERY PHRASE
UNLESS THEY HAVE BEEN MOVED TO A NEWLY GENERATED ADDRESS FOLLOWING THE 4.5.2
UPGRADE.
New RPC Methods
---------------
- 'walletconfirmbackup' This newly created API checks a provided emergency
recovery phrase against the wallet's emergency recovery phrase; if the phrases
match then it updates the wallet state to allow the generation of new addresses.
This backup confirmation workflow can be disabled by starting zcashd with
`-requirewalletbackup=false` but this is not recommended unless you know what
you're doing (and have otherwise backed up the wallet's recovery phrase anyway).
For security reasons, this RPC method is not intended for use via zcash-cli
but is provided to enable `zcashd-wallet-tool` and other third-party wallet
interfaces to satisfy the backup confirmation requirement. Use of the
`walletconfirmbackup` API via zcash-cli would risk that the recovery phrase
being confirmed might be leaked via the user's shell history or the system
process table; `zcashd-wallet-tool` is specifically provided to avoid this
problem.
- 'z_getbalanceforviewingkey' This newly created API allows a user to obtain
balance information for funds visible to a Sapling or Unified full
viewing key; if a Sprout viewing key is provided, this method allows
retrieval of the balance only in the case that the wallet controls the
corresponding spending key.
RPC Changes
-----------
- The results of the 'dumpwallet' and 'z_exportwallet' RPC methods have been modified
to now include the wallet's newly generated emergency recovery phrase as part of the
exported data.
- The results of the 'getwalletinfo' RPC have been modified to return two new fields:
`mnemonic_seedfp` and `legacy_seedfp`, the latter of which replaces the field that
was previously named `seedfp`.
Wallet
------
'z_sendmany'
------------
- The 'z_sendmany' RPC call no longer permits Sprout recipients in the
list of recipient addresses. Transactions spending Sprout funds will
still result in change being sent back into the Sprout pool, but no
other `Sprout->Sprout` transactions will be constructed by the Zcashd
wallet.
- The restriction that prohibited `Sprout->Sapling` transactions has been
lifted; however, since such transactions reveal the amount crossing
pool boundaries, they must be explicitly enabled via a parameter to
the 'z_sendmany' call.
- A new boolean parameter, `allowRevealedAmounts`, has been added to the
list of arguments accepted by 'z_sendmany'. This parameter defaults to
`false` and is only required when the transaction being constructed
would reveal transaction amounts as a consequence of ZEC value crossing
shielded pool boundaries via the turnstile.
- Since Sprout outputs are no longer created (with the exception of change)
'z_sendmany' no longer generates payment disclosures (which were only
available for Sprout outputs) when the `-paymentdisclosure` experimental
feature flag is set.

View File

@ -0,0 +1,37 @@
`getblocktemplate` regression fix
=================================
We added support for the NU5 consensus rules in v4.5.0, which alters the
block header to contain a `hashBlockCommitments` value instead of the
chain history root. However, the output of `getblocktemplate` wasn't
returning this value; once NU5 activated, the `blockcommitmentshash`
field was being set to "null" (all-zeroes).
In v4.6.0 we added full NU5 support to `getblocktemplate`, by adding a
`defaultroots` field that gave default values for `hashBlockCommitments`
and the components required to derive it. However, in doing so we
introduced a regression in the (now-deprecated) legacy fields, where
prior to NU5 activation they contained nonsense.
This release fixes the output of `getblocktemplate` to have the intended
semantics for all fields:
- The `blockcommitmentshash` and `authdataroot` fields in `defaultroots`
are now omitted from block templates for heights before NU5 activation.
- The legacy fields now always contain the default value to be placed
into the block header (regaining their previous semantics).
Changelog
=========
Jack Grigg (3):
rpc: Fix regression in getblocktemplate output
make-release.py: Versioning changes for 4.6.0-1.
make-release.py: Updated manpages for 4.6.0-1.
Larry Ruane (3):
assert that the return value of submitblock is None
test: check getblocktemplate output before and after NU5
test: Fix ZIP 244 implementation

View File

@ -0,0 +1,111 @@
Notable changes
===============
Wallet
------
From this release, newly-created wallets will save the chain name ("Zcash") and
network identifier (e.g. "main") to the `wallet.dat` file. This will enable the
`zcashd` node to check on subsequent starts that the `wallet.dat` file matches
the node's configuration. Existing wallets will start saving this information in
a later release.
`libzcash_script`
-----------------
Two new APIs have been added to this library (`zcash_script_legacy_sigop_count`
and `zcash_script_legacy_sigop_count_precomputed`), for counting the number of
signature operations in the transparent inputs and outputs of a transaction.
The presence of these APIs is indicated by a library API version of 2.
Updated RPCs
------------
- Fixed an issue where `ERROR: spent index not enabled` would be logged
unnecessarily on nodes that have either insightexplorer or lightwalletd
configuration options enabled.
- The `getmininginfo` RPC now omits `currentblockize` and `currentblocktx`
when a block was never assembled via RPC on this node during its current
process instantiation. (#5404)
Changelog
=========
Alex Wied (1):
Update support for FreeBSD
Charlie O'Keefe (1):
Add buster to the list of suites used by gitian
Dimitris Apostolou (1):
Fix typos
Jack Grigg (22):
contrib: Update Debian copyright file to follow the v1 format
contrib: Add license information for libc++ and libevent
cargo update
tracing-subscriber 0.3
Bump all postponed dependencies
depends: Update Rust to 1.56.1
depends: Update Clang / libcxx to LLVM 13
rust: Move `incremental_sinsemilla_tree_ffi` into crate root
CI: Add Pyflakes to lints workflow
cargo update
ed25519-zebra 3
cargo update
cargo update
depends: Update Boost to 1.78.0
depends Update Rust to 1.57.0
qa: Postpone recent CCache releases
Revert "lint: Fix false positive"
rust: Remove misleading log message
Migrate to latest revisions of Zcash Rust crates
Update release notes
make-release.py: Versioning changes for 4.6.0-rc1.
make-release.py: Updated manpages for 4.6.0-rc1.
Janito Vaqueiro Ferreira Filho (1):
Move `CurrentTxVersionInfo` into a new file
Kris Nuttycombe (7):
Add BIP 44 coin type to persisted wallet state.
Persist network id string instead of bip44 coin type.
Add a check to test that wallet load fails if we're on the wrong network.
Remove unused `AddDestData` method.
Fix wallet-related wording in doc/reduce-traffic.md
Rename OrchardMerkleTree -> OrchardMerkleFrontier
Batch-verify Orchard transactions at the block level.
Larry Ruane (6):
add TestSetIBD(bool) for testing
Disable IBD for all boost tests
better wallet network info error handling
test: automatically add missing nuparams
Don't log 'ERROR: spent index not enabled'
getblocktemplate: add NU5 commitments to new `defaultroots` section
Marco Falke (1):
[rpc] mining: Omit uninitialized currentblockweight, currentblocktx
Marshall Gaucher (1):
Update entrypoint.sh
Sasha (1):
fix typo in docker run's volume argument
sgmoore (1):
Update reduce-traffic.md - add one word
Jack Grigg (1):
contrib: Add space between URL and period
teor (7):
Add sigop count functions to zcash_script library
Increment the zcash_script API version
Remove an unused header
Use correct copyright header
Remove redundant variable
Explain UINT_MAX error return value
Explain how to get rid of a tiny duplicated function

View File

@ -0,0 +1,126 @@
Notable changes
===============
Wallet
------
From this release, newly-created wallets will save the chain name ("Zcash") and
network identifier (e.g. "main") to the `wallet.dat` file. This will enable the
`zcashd` node to check on subsequent starts that the `wallet.dat` file matches
the node's configuration. Existing wallets will start saving this information in
a later release.
`libzcash_script`
-----------------
Two new APIs have been added to this library (`zcash_script_legacy_sigop_count`
and `zcash_script_legacy_sigop_count_precomputed`), for counting the number of
signature operations in the transparent inputs and outputs of a transaction.
The presence of these APIs is indicated by a library API version of 2.
Updated RPCs
------------
- The `getblocktemplate` RPC method output now includes a `defaultroots` field,
which provides various tree roots and block commitments matching the contents
of the block template. If any part of the block template marked as `mutable`
in the RPC method output is mutated, these roots may need to be recomputed.
For more information on the derivation process, see the block header changes
in [ZIP 244](https://zips.z.cash/zip-0244#block-header-changes).
- Fixed an issue where `ERROR: spent index not enabled` would be logged
unnecessarily on nodes that have either `-insightexplorer` or `-lightwalletd`
configuration options enabled.
- The `getmininginfo` RPC now omits `currentblocksize` and `currentblocktx`
when a block was never assembled via RPC on this node during its current
process instantiation. (#5404)
Changelog
=========
Alex Wied (1):
Update support for FreeBSD
Charlie O'Keefe (2):
Add buster to the list of suites used by gitian
Add libtinfo5 to gitian packages list
Dimitris Apostolou (1):
Fix typos
Jack Grigg (23):
contrib: Update Debian copyright file to follow the v1 format
contrib: Add license information for libc++ and libevent
cargo update
tracing-subscriber 0.3
Bump all postponed dependencies
depends: Update Rust to 1.56.1
depends: Update Clang / libcxx to LLVM 13
rust: Move `incremental_sinsemilla_tree_ffi` into crate root
CI: Add Pyflakes to lints workflow
cargo update
ed25519-zebra 3
cargo update
cargo update
depends: Update Boost to 1.78.0
depends Update Rust to 1.57.0
qa: Postpone recent CCache releases
Revert "lint: Fix false positive"
rust: Remove misleading log message
Migrate to latest revisions of Zcash Rust crates
Update release notes
make-release.py: Versioning changes for 4.6.0-rc1.
make-release.py: Updated manpages for 4.6.0-rc1.
make-release.py: Updated release notes and changelog for 4.6.0-rc1.
Janito Vaqueiro Ferreira Filho (1):
Move `CurrentTxVersionInfo` into a new file
Kris Nuttycombe (7):
Add BIP 44 coin type to persisted wallet state.
Persist network id string instead of bip44 coin type.
Add a check to test that wallet load fails if we're on the wrong network.
Remove unused `AddDestData` method.
Fix wallet-related wording in doc/reduce-traffic.md
Rename OrchardMerkleTree -> OrchardMerkleFrontier
Batch-verify Orchard transactions at the block level.
Larry Ruane (8):
add TestSetIBD(bool) for testing
Disable IBD for all boost tests
better wallet network info error handling
test: automatically add missing nuparams
Don't log 'ERROR: spent index not enabled'
getblocktemplate: add NU5 commitments to new `defaultroots` section
test: fix bugs in test framework
test: Use result of getblocktemplate to submitblock
Marco Falke (1):
[rpc] mining: Omit uninitialized currentblockweight, currentblocktx
Marshall Gaucher (1):
Update entrypoint.sh
Sasha (5):
fix typo in docker run's volume argument
update hash for librustzcash
only librustzcash in config.offline
make-release.py: Versioning changes for 4.6.0.
make-release.py: Updated manpages for 4.6.0.
sgmoore (1):
Update reduce-traffic.md - add one word
Jack Grigg (1):
contrib: Add space between URL and period
teor (7):
Add sigop count functions to zcash_script library
Increment the zcash_script API version
Remove an unused header
Use correct copyright header
Remove redundant variable
Explain UINT_MAX error return value
Explain how to get rid of a tiny duplicated function

View File

@ -32,7 +32,7 @@ Check that dependencies are up-to-date or have been postponed:
$ ./qa/zcash/updatecheck.py
```
If you are missing the `.updatecheck-token` file requried to run this script,
If you are missing the `.updatecheck-token` file required to run this script,
please ask Taylor or another Zcash developer for a copy, or create an
unprivileged personal access token for a github account and save it to the
file in the format `username:hex-token`.

View File

@ -46,6 +46,8 @@ BASE_SCRIPTS= [
'zcjoinsplit.py',
'mergetoaddress_mixednotes.py',
'wallet_shieldcoinbase_sapling.py',
'wallet_shieldcoinbase_ua_sapling.py',
'wallet_shieldcoinbase_ua_nu5.py',
'turnstile.py',
'walletbackup.py',
'zkey_import_export.py',
@ -62,9 +64,9 @@ BASE_SCRIPTS= [
'reorg_limit.py',
'mempool_limit.py',
'p2p-fullblocktest.py',
'paymentdisclosure.py',
# vv Tests less than 30s vv
'wallet_1941.py',
'wallet_accounts.py',
'wallet_addresses.py',
'wallet_anchorfork.py',
'wallet_changeindicator.py',
@ -103,6 +105,7 @@ BASE_SCRIPTS= [
'disablewallet.py',
'keypool.py',
'getblocktemplate.py',
'getmininginfo.py',
'bip65-cltv-p2p.py',
'bipdersig-p2p.py',
'invalidblockrequest.py',
@ -122,6 +125,7 @@ BASE_SCRIPTS= [
'feature_zip239.py',
'feature_zip244_blockcommitments.py',
'upgrade_golden.py',
'nuparams.py',
'post_heartwood_rollback.py',
'feature_logging.py',
'feature_walletfile.py',

View File

@ -23,10 +23,6 @@ TODO: factor out common code from {bipdersig-p2p,bip65-cltv-p2p}.py.
class BIP65Test(ComparisonTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 1
def setup_network(self):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[['-debug', '-whitelist=127.0.0.1']],

View File

@ -23,10 +23,6 @@ TODO: factor out common code from {bipdersig-p2p,bip65-cltv-p2p}.py.
'''
class BIP66Test(ComparisonTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 1
def setup_network(self):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
extra_args=[['-debug', '-whitelist=127.0.0.1']],

View File

@ -6,9 +6,11 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
NU5_BRANCH_ID,
assert_equal,
connect_nodes_bi,
get_coinbase_address,
nuparams,
start_nodes,
wait_and_assert_operationid_status,
)
@ -17,6 +19,7 @@ from decimal import Decimal
SPROUT_TREE_EMPTY_ROOT = "59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7"
SAPLING_TREE_EMPTY_ROOT = "3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb"
ORCHARD_TREE_EMPTY_ROOT = "2fd8e51a03d9bbe2dd809831b1497aeb68a6e37ddf707ced4aa2d8dff13529ae"
NULL_FIELD = "0000000000000000000000000000000000000000000000000000000000000000"
# Verify block header field 'hashFinalSaplingRoot' (returned in rpc as 'finalsaplingroot')
@ -25,17 +28,16 @@ class FinalSaplingRootTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 4
self.num_nodes = 2
self.setup_clean_chain = True
def setup_network(self, split=False):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[
'-txindex' # Avoid JSONRPC error: No information available about transaction
'-txindex', # Avoid JSONRPC error: No information available about transaction
nuparams(NU5_BRANCH_ID, 210),
'-debug',
]] * self.num_nodes)
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
connect_nodes_bi(self.nodes,0,3)
self.is_network_split=False
self.sync_all()
@ -43,7 +45,7 @@ class FinalSaplingRootTest(BitcoinTestFramework):
self.nodes[0].generate(200)
self.sync_all()
# Verfify genesis block contains null field for what is now called the final sapling root field.
# Verify genesis block contains null field for what is now called the final sapling root field.
blk = self.nodes[0].getblock("0")
assert_equal(blk["finalsaplingroot"], NULL_FIELD)
treestate = self.nodes[0].z_gettreestate("0")
@ -52,13 +54,19 @@ class FinalSaplingRootTest(BitcoinTestFramework):
assert_equal(treestate["sprout"]["commitments"]["finalRoot"], SPROUT_TREE_EMPTY_ROOT)
assert_equal(treestate["sprout"]["commitments"]["finalState"], "000000")
assert("skipHash" not in treestate["sprout"])
assert "skipHash" not in treestate["sprout"]
assert_equal(treestate["sapling"]["commitments"]["finalRoot"], NULL_FIELD)
# There is no sapling state tree yet, and trying to find it in an earlier
# block won't succeed (we're at genesis block), so skipHash is absent.
assert("finalState" not in treestate["sapling"])
assert("skipHash" not in treestate["sapling"])
assert "finalState" not in treestate["sapling"]
assert "skipHash" not in treestate["sapling"]
assert_equal(treestate["orchard"]["commitments"]["finalRoot"], NULL_FIELD)
# There is no orchard state tree yet, and trying to find it in an earlier
# block won't succeed (we're at genesis block), so skipHash is absent.
assert "finalState" not in treestate["orchard"]
assert "skipHash" not in treestate["orchard"]
# Verify all generated blocks contain the empty root of the Sapling tree.
blockcount = self.nodes[0].getblockcount()
@ -70,14 +78,18 @@ class FinalSaplingRootTest(BitcoinTestFramework):
assert_equal(treestate["height"], height)
assert_equal(treestate["hash"], self.nodes[0].getblockhash(height))
assert("skipHash" not in treestate["sprout"])
assert "skipHash" not in treestate["sprout"]
assert_equal(treestate["sprout"]["commitments"]["finalRoot"], SPROUT_TREE_EMPTY_ROOT)
assert_equal(treestate["sprout"]["commitments"]["finalState"], "000000")
assert("skipHash" not in treestate["sapling"])
assert "skipHash" not in treestate["sapling"]
assert_equal(treestate["sapling"]["commitments"]["finalRoot"], SAPLING_TREE_EMPTY_ROOT)
assert_equal(treestate["sapling"]["commitments"]["finalState"], "000000")
assert "skipHash" not in treestate["orchard"]
assert_equal(treestate["orchard"]["commitments"]["finalRoot"], NULL_FIELD)
# Node 0 shields some funds
taddr0 = get_coinbase_address(self.nodes[0])
saplingAddr0 = self.nodes[0].z_getnewaddress('sapling')
@ -93,8 +105,8 @@ class FinalSaplingRootTest(BitcoinTestFramework):
# Verify the final Sapling root has changed
blk = self.nodes[0].getblock("201")
root = blk["finalsaplingroot"]
assert(root is not SAPLING_TREE_EMPTY_ROOT)
assert(root is not NULL_FIELD)
assert root is not SAPLING_TREE_EMPTY_ROOT
assert root is not NULL_FIELD
# Verify there is a Sapling output description (its commitment was added to tree)
result = self.nodes[0].getrawtransaction(mytxid, 1)
@ -105,8 +117,8 @@ class FinalSaplingRootTest(BitcoinTestFramework):
new_treestate = self.nodes[0].z_gettreestate(str(-1))
assert_equal(new_treestate["sapling"]["commitments"]["finalRoot"], root)
assert_equal(new_treestate["sprout"], treestate["sprout"])
assert(new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"])
assert(new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"])
assert new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"]
assert new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"]
assert_equal(len(new_treestate["sapling"]["commitments"]["finalRoot"]), 64)
assert_equal(len(new_treestate["sapling"]["commitments"]["finalState"]), 70)
treestate = new_treestate
@ -131,10 +143,8 @@ class FinalSaplingRootTest(BitcoinTestFramework):
# Mine a block with a Sprout shielded tx and verify the final Sapling root does not change
zaddr1 = self.nodes[1].z_getnewaddress('sprout')
recipients = []
recipients.append({"address": zaddr1, "amount": Decimal('10')})
myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0)
wait_and_assert_operationid_status(self.nodes[0], myopid)
result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr1, 0, 1)
wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.sync_all()
self.nodes[0].generate(1)
@ -147,8 +157,8 @@ class FinalSaplingRootTest(BitcoinTestFramework):
new_treestate = self.nodes[0].z_gettreestate(str(-1))
assert_equal(new_treestate["sapling"]["commitments"]["finalRoot"], root)
assert_equal(new_treestate["sapling"], treestate["sapling"])
assert(new_treestate["sprout"]["commitments"]["finalRoot"] != treestate["sprout"]["commitments"]["finalRoot"])
assert(new_treestate["sprout"]["commitments"]["finalState"] != treestate["sprout"]["commitments"]["finalState"])
assert new_treestate["sprout"]["commitments"]["finalRoot"] != treestate["sprout"]["commitments"]["finalRoot"]
assert new_treestate["sprout"]["commitments"]["finalState"] != treestate["sprout"]["commitments"]["finalState"]
assert_equal(len(new_treestate["sprout"]["commitments"]["finalRoot"]), 64)
assert_equal(len(new_treestate["sprout"]["commitments"]["finalState"]), 134)
treestate = new_treestate
@ -166,7 +176,7 @@ class FinalSaplingRootTest(BitcoinTestFramework):
assert_equal(len(self.nodes[0].getblock("205")["tx"]), 2)
assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal("12.34"))
assert(root is not self.nodes[0].getblock("205")["finalsaplingroot"])
assert root is not self.nodes[0].getblock("205")["finalsaplingroot"]
# Verify there is a Sapling output description (its commitment was added to tree)
result = self.nodes[0].getrawtransaction(mytxid, 1)
@ -174,8 +184,8 @@ class FinalSaplingRootTest(BitcoinTestFramework):
new_treestate = self.nodes[0].z_gettreestate(str(-1))
assert_equal(new_treestate["sprout"], treestate["sprout"])
assert(new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"])
assert(new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"])
assert new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"]
assert new_treestate["sapling"]["commitments"]["finalState"] != treestate["sapling"]["commitments"]["finalState"]
assert_equal(len(new_treestate["sapling"]["commitments"]["finalRoot"]), 64)
assert_equal(len(new_treestate["sapling"]["commitments"]["finalState"]), 136)
treestate = new_treestate
@ -202,6 +212,21 @@ class FinalSaplingRootTest(BitcoinTestFramework):
assert_equal(new_treestate["sprout"], treestate["sprout"])
assert_equal(new_treestate["sapling"], treestate["sapling"])
# Activate NU5; more testing should be added once we can mine orchard transactions.
self.sync_all()
self.nodes[0].generate(4)
self.sync_all()
new_treestate = self.nodes[0].z_gettreestate(str(-1))
# sprout and sapling results should not change
assert_equal(new_treestate["sprout"], treestate["sprout"])
assert_equal(new_treestate["sapling"], treestate["sapling"])
assert "skipHash" not in treestate["orchard"]
assert_equal(new_treestate["orchard"]["commitments"]["finalRoot"], ORCHARD_TREE_EMPTY_ROOT)
assert_equal(new_treestate["orchard"]["commitments"]["finalState"], "00")
pass
if __name__ == '__main__':
FinalSaplingRootTest().main()

View File

@ -73,7 +73,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
fee = rawtxfund['fee']
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs
assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs
##############################
# simple test with two coins #

View File

@ -3,63 +3,185 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from io import BytesIO
import codecs
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, connect_nodes_bi, \
start_nodes
from test_framework.util import (
assert_equal,
CANOPY_BRANCH_ID,
NU5_BRANCH_ID,
hex_str_to_bytes,
nuparams,
start_nodes,
wait_and_assert_operationid_status,
)
from test_framework.mininode import (
CTransaction,
uint256_from_str,
)
from test_framework.blocktools import (
create_block
)
from decimal import Decimal
class GetBlockTemplateTest(BitcoinTestFramework):
'''
Test getblocktemplate.
Test getblocktemplate, ensure that a block created from its result
can be submitted and accepted.
'''
def __init__(self):
super().__init__()
self.num_nodes = 2
self.num_nodes = 1
self.setup_clean_chain = True
def setup_network(self, split=False):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
connect_nodes_bi(self.nodes,0,1)
self.is_network_split=False
args = [
nuparams(CANOPY_BRANCH_ID, 115),
nuparams(NU5_BRANCH_ID, 130),
]
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [args] * self.num_nodes)
self.is_network_split = False
self.node = self.nodes[0]
def add_nu5_v4_tx_to_mempool(self):
node = self.node
# sprout to transparent (v4)
recipients = [{"address": self.transparent_addr, "amount": Decimal('0.1')}]
myopid = node.z_sendmany(self.sprout_addr, recipients)
wait_and_assert_operationid_status(node, myopid)
def add_transparent_tx_to_mempool(self):
node = self.node
# transparent to transparent (v5 after nu5)
outputs = {self.transparent_addr: 0.1}
node.sendmany('', outputs)
def gbt_submitblock(self, nu5_active):
node = self.node
mempool_tx_list = node.getrawmempool()
gbt = node.getblocktemplate()
# make sure no transactions were left out (or added)
assert_equal(len(mempool_tx_list), len(gbt['transactions']))
assert_equal(set(mempool_tx_list), set([tx['hash'] for tx in gbt['transactions']]))
prevhash = int(gbt['previousblockhash'], 16)
nTime = gbt['mintime']
nBits = int(gbt['bits'], 16)
if nu5_active:
blockcommitmentshash = int(gbt['defaultroots']['blockcommitmentshash'], 16)
else:
blockcommitmentshash = int(gbt['defaultroots']['chainhistoryroot'], 16)
assert 'blockcommitmentshash' not in gbt['defaultroots']
# Confirm that the legacy fields match this default value.
assert_equal(blockcommitmentshash, int(gbt['blockcommitmentshash'], 16))
assert_equal(blockcommitmentshash, int(gbt['lightclientroothash'], 16))
assert_equal(blockcommitmentshash, int(gbt['finalsaplingroothash'], 16))
f = BytesIO(hex_str_to_bytes(gbt['coinbasetxn']['data']))
coinbase = CTransaction()
coinbase.deserialize(f)
coinbase.calc_sha256()
assert_equal(coinbase.hash, gbt['coinbasetxn']['hash'])
assert_equal(coinbase.auth_digest_hex, gbt['coinbasetxn']['authdigest'])
block = create_block(prevhash, coinbase, nTime, nBits, blockcommitmentshash)
# copy the non-coinbase transactions from the block template to the block
for gbt_tx in gbt['transactions']:
f = BytesIO(hex_str_to_bytes(gbt_tx['data']))
tx = CTransaction()
tx.deserialize(f)
tx.calc_sha256()
assert_equal(tx.auth_digest_hex, node.getrawtransaction(tx.hash, 1)['authdigest'])
block.vtx.append(tx)
block.hashMerkleRoot = int(gbt['defaultroots']['merkleroot'], 16)
assert_equal(block.hashMerkleRoot, block.calc_merkle_root(), "merkleroot")
assert_equal(len(block.vtx), len(gbt['transactions']) + 1, "number of transactions")
assert_equal(block.hashPrevBlock, int(gbt['previousblockhash'], 16), "prevhash")
if nu5_active:
assert_equal(uint256_from_str(block.calc_auth_data_root()), int(gbt['defaultroots']['authdataroot'], 16))
else:
assert 'authdataroot' not in gbt['defaultroots']
block.solve()
block.calc_sha256()
submitblock_reply = node.submitblock(codecs.encode(block.serialize(), 'hex_codec'))
assert_equal(None, submitblock_reply)
assert_equal(block.hash, node.getbestblockhash())
# Wait until the wallet has been notified of all blocks, so that it doesn't try to
# double-spend transparent coins in subsequent test phases.
self.sync_all()
def run_test(self):
node = self.nodes[0]
node.generate(1) # Mine a block to leave initial block download
node = self.node
# Test 1: Default to coinbasetxn
tmpl = node.getblocktemplate()
assert('coinbasetxn' in tmpl)
assert('coinbasevalue' not in tmpl)
# Generate Sprout funds before Canopy activates; using the Sprout address will
# force the generation of v4 transactions from NU5.
print("Generating pre-Canopy blocks to create sprout funds")
# coinbase only becomes mature after 100 blocks, so make one mature.
node.generate(105)
# Test 2: Get coinbasetxn if requested
tmpl = node.getblocktemplate({'capabilities': ['coinbasetxn']})
assert('coinbasetxn' in tmpl)
assert('coinbasevalue' not in tmpl)
self.sprout_addr = node.z_getnewaddress('sprout')
myopid = node.z_shieldcoinbase('*', self.sprout_addr)['opid']
wait_and_assert_operationid_status(node, myopid)
# Test 3: coinbasevalue not supported if requested
tmpl = node.getblocktemplate({'capabilities': ['coinbasevalue']})
assert('coinbasetxn' in tmpl)
assert('coinbasevalue' not in tmpl)
self.transparent_addr = node.getnewaddress()
node.generate(15)
# Test 4: coinbasevalue not supported if both requested
tmpl = node.getblocktemplate({'capabilities': ['coinbasetxn', 'coinbasevalue']})
assert('coinbasetxn' in tmpl)
assert('coinbasevalue' not in tmpl)
# at height 120, NU5 is not active
assert_equal(node.getblockchaininfo()['upgrades']['37519621']['status'], 'pending')
# Test 5: General checks
tmpl = node.getblocktemplate()
assert_equal(16, len(tmpl['noncerange']))
print("Testing getblocktemplate for pre-NU5")
# Test 6: coinbasetxn checks
assert('foundersreward' in tmpl['coinbasetxn'])
assert(tmpl['coinbasetxn']['required'])
# Only the coinbase; this covers the case where the Merkle root
# is equal to the coinbase txid.
print("- only coinbase")
self.gbt_submitblock(False)
# Adding one transaction triggering a single Merkle digest.
print("- one transaction (plus coinbase)")
self.add_transparent_tx_to_mempool()
self.gbt_submitblock(False)
# Adding two transactions to trigger hash Merkle root edge case.
print("- two transactions (plus coinbase)")
self.add_transparent_tx_to_mempool()
self.add_transparent_tx_to_mempool()
self.gbt_submitblock(False)
# Activate NU5, repeat the above cases
node.generate(7)
assert_equal(node.getblockchaininfo()['upgrades']['37519621']['status'], 'active')
print("Testing getblocktemplate for post-NU5")
# Only the coinbase; this covers the case where the block authdata root
# is equal to the coinbase authdata
print("- only coinbase")
self.gbt_submitblock(True)
# Adding one transaction triggering a single Merkle digest.
print("- one transaction (plus coinbase)")
self.add_transparent_tx_to_mempool()
self.gbt_submitblock(True)
# Adding two transactions to trigger hash Merkle root edge case.
print("- two transactions (plus coinbase)")
self.add_transparent_tx_to_mempool()
self.add_transparent_tx_to_mempool()
self.gbt_submitblock(True)
# Adding both v4 and v5 to cover legacy auth digest.
print("- both v4 and v5 transactions (plus coinbase)")
self.add_nu5_v4_tx_to_mempool()
self.add_transparent_tx_to_mempool()
self.add_transparent_tx_to_mempool()
self.gbt_submitblock(True)
# Test 7: hashFinalSaplingRoot checks
assert('finalsaplingroothash' in tmpl)
finalsaplingroothash = '3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb'
assert_equal(finalsaplingroothash, tmpl['finalsaplingroothash'])
if __name__ == '__main__':
GetBlockTemplateTest().main()

47
qa/rpc-tests/getmininginfo.py Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import start_nodes
class GetMiningInfoTest(BitcoinTestFramework):
'''
Test getmininginfo.
'''
def __init__(self):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = True
def setup_network(self, split=False):
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
self.is_network_split = False
self.sync_all()
def run_test(self):
node = self.nodes[0]
info = node.getmininginfo()
assert(info['blocks'] == 0)
# No blocks have been mined yet, so these fields should not be present.
assert('currentblocksize' not in info)
assert('currentblocktx' not in info)
node.generate(1)
info = node.getmininginfo()
assert(info['blocks'] == 1)
# One block has been mined, so these fields should now be present.
assert('currentblocksize' in info)
assert('currentblocktx' in info)
assert(info['currentblocksize'] > 0)
# The transaction count doesn't include the coinbase
assert(info['currentblocktx'] == 0)
if __name__ == '__main__':
GetMiningInfoTest().main()

View File

@ -26,10 +26,6 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
''' Can either run this test as 1 node with expected answers, or two and compare them.
Change the "outcome" variable from each TestInstance object to only do the comparison. '''
def __init__(self):
super().__init__()
self.num_nodes = 1
def run_test(self):
test = TestManager(self, self.options.tmpdir)
test.add_all_connections(self.nodes)

View File

@ -20,10 +20,6 @@ class InvalidTxRequestTest(ComparisonTestFramework):
''' Can either run this test as 1 node with expected answers, or two and compare them.
Change the "outcome" variable from each TestInstance object to only do the comparison. '''
def __init__(self):
super().__init__()
self.num_nodes = 1
def run_test(self):
test = TestManager(self, self.options.tmpdir)
test.add_all_connections(self.nodes)

View File

@ -40,13 +40,13 @@ class KeyPoolTest(BitcoinTestFramework):
bitcoind_processes[0].wait()
# Restart node 0
nodes[0] = start_node(0, self.options.tmpdir)
# Keep creating keys
addr = nodes[0].getnewaddress()
# We can't create any external addresses, which don't use the keypool.
# We should get an error that we need to unlock the wallet.
try:
addr = nodes[0].getnewaddress()
raise AssertionError('Keypool should be exhausted after one address')
raise AssertionError('Wallet should be locked.')
except JSONRPCException as e:
assert(e.error['code']==-12)
assert_equal(e.error['code'], -13)
# put three new keys in the keypool
nodes[0].walletpassphrase('test', 12000)

View File

@ -29,8 +29,8 @@ class MergeToAddressMixedNotes(BitcoinTestFramework):
saplingAddr = self.nodes[0].z_getnewaddress('sapling')
t_addr = self.nodes[1].getnewaddress()
opid = self.nodes[0].z_sendmany(coinbase_addr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0)
wait_and_assert_operationid_status(self.nodes[0], opid)
result = self.nodes[0].z_shieldcoinbase(coinbase_addr, sproutAddr, 0, 1)
wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.nodes[0].generate(1)
self.sync_all()
assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10'))

View File

@ -75,7 +75,7 @@ class MerkleBlockTest(BitcoinTestFramework):
txid_spent = txin_spent["txid"]
txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2
# We cant find the block from a fully-spent tx
# We can't find the block from a fully-spent tx
assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent])
# ...but we can if we specify the block
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent])

View File

@ -27,7 +27,7 @@ class NodeHandlingTest (BitcoinTestFramework):
###########################
assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point
self.nodes[2].setban("127.0.0.1", "add")
time.sleep(3) #wait till the nodes are disconected
time.sleep(3) #wait till the nodes are disconnected
assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point
assert_equal(len(self.nodes[2].listbanned()), 1)
self.nodes[2].clearbanned()

217
qa/rpc-tests/nuparams.py Executable file
View File

@ -0,0 +1,217 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
start_nodes,
nuparams,
HEARTWOOD_BRANCH_ID,
NU5_BRANCH_ID,
)
class NuparamsTest(BitcoinTestFramework):
'''
Test that unspecified network upgrades are activated automatically;
this is really more of a test of the test framework.
'''
def __init__(self):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = True
def setup_network(self, split=False):
args = [[
nuparams(HEARTWOOD_BRANCH_ID, 3),
nuparams(NU5_BRANCH_ID, 5),
] * self.num_nodes]
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, args)
self.is_network_split = False
self.sync_all()
def run_test(self):
node = self.nodes[0]
# No blocks have been created, only the genesis block exists (height 0)
bci = node.getblockchaininfo()
assert_equal(bci['blocks'], 0)
upgrades = bci['upgrades']
overwinter = upgrades['5ba81b19']
assert_equal(overwinter['name'], 'Overwinter')
assert_equal(overwinter['activationheight'], 1)
assert_equal(overwinter['status'], 'pending')
sapling = upgrades['76b809bb']
assert_equal(sapling['name'], 'Sapling')
assert_equal(sapling['activationheight'], 1)
assert_equal(sapling['status'], 'pending')
blossom = upgrades['2bb40e60']
assert_equal(blossom['name'], 'Blossom')
assert_equal(blossom['activationheight'], 3)
assert_equal(blossom['status'], 'pending')
heartwood = upgrades['f5b9230b']
assert_equal(heartwood['name'], 'Heartwood')
assert_equal(heartwood['activationheight'], 3)
assert_equal(heartwood['status'], 'pending')
canopy = upgrades['e9ff75a6']
assert_equal(canopy['name'], 'Canopy')
assert_equal(canopy['activationheight'], 5)
assert_equal(canopy['status'], 'pending')
nu5 = upgrades['37519621']
assert_equal(nu5['name'], 'NU5')
assert_equal(nu5['activationheight'], 5)
assert_equal(nu5['status'], 'pending')
node.generate(1)
# start_node() hardcodes Sapling and Overwinter to activate a height 1
bci = node.getblockchaininfo()
assert_equal(bci['blocks'], 1)
upgrades = bci['upgrades']
overwinter = upgrades['5ba81b19']
assert_equal(overwinter['name'], 'Overwinter')
assert_equal(overwinter['activationheight'], 1)
assert_equal(overwinter['status'], 'active')
sapling = upgrades['76b809bb']
assert_equal(sapling['name'], 'Sapling')
assert_equal(sapling['activationheight'], 1)
assert_equal(sapling['status'], 'active')
blossom = upgrades['2bb40e60']
assert_equal(blossom['name'], 'Blossom')
assert_equal(blossom['activationheight'], 3)
assert_equal(blossom['status'], 'pending')
heartwood = upgrades['f5b9230b']
assert_equal(heartwood['name'], 'Heartwood')
assert_equal(heartwood['activationheight'], 3)
assert_equal(heartwood['status'], 'pending')
canopy = upgrades['e9ff75a6']
assert_equal(canopy['name'], 'Canopy')
assert_equal(canopy['activationheight'], 5)
assert_equal(canopy['status'], 'pending')
nu5 = upgrades['37519621']
assert_equal(nu5['name'], 'NU5')
assert_equal(nu5['activationheight'], 5)
assert_equal(nu5['status'], 'pending')
node.generate(1)
bci = node.getblockchaininfo()
assert_equal(bci['blocks'], 2)
upgrades = bci['upgrades']
overwinter = upgrades['5ba81b19']
assert_equal(overwinter['name'], 'Overwinter')
assert_equal(overwinter['activationheight'], 1)
assert_equal(overwinter['status'], 'active')
sapling = upgrades['76b809bb']
assert_equal(sapling['name'], 'Sapling')
assert_equal(sapling['activationheight'], 1)
assert_equal(sapling['status'], 'active')
blossom = upgrades['2bb40e60']
assert_equal(blossom['name'], 'Blossom')
assert_equal(blossom['activationheight'], 3)
assert_equal(blossom['status'], 'pending')
heartwood = upgrades['f5b9230b']
assert_equal(heartwood['name'], 'Heartwood')
assert_equal(heartwood['activationheight'], 3)
assert_equal(heartwood['status'], 'pending')
canopy = upgrades['e9ff75a6']
assert_equal(canopy['name'], 'Canopy')
assert_equal(canopy['activationheight'], 5)
assert_equal(canopy['status'], 'pending')
nu5 = upgrades['37519621']
assert_equal(nu5['name'], 'NU5')
assert_equal(nu5['activationheight'], 5)
assert_equal(nu5['status'], 'pending')
node.generate(2)
bci = node.getblockchaininfo()
assert_equal(bci['blocks'], 4)
upgrades = bci['upgrades']
overwinter = upgrades['5ba81b19']
assert_equal(overwinter['name'], 'Overwinter')
assert_equal(overwinter['activationheight'], 1)
assert_equal(overwinter['status'], 'active')
sapling = upgrades['76b809bb']
assert_equal(sapling['name'], 'Sapling')
assert_equal(sapling['activationheight'], 1)
assert_equal(sapling['status'], 'active')
blossom = upgrades['2bb40e60']
assert_equal(blossom['name'], 'Blossom')
assert_equal(blossom['activationheight'], 3)
assert_equal(blossom['status'], 'active')
heartwood = upgrades['f5b9230b']
assert_equal(heartwood['name'], 'Heartwood')
assert_equal(heartwood['activationheight'], 3)
assert_equal(heartwood['status'], 'active')
canopy = upgrades['e9ff75a6']
assert_equal(canopy['name'], 'Canopy')
assert_equal(canopy['activationheight'], 5)
assert_equal(canopy['status'], 'pending')
nu5 = upgrades['37519621']
assert_equal(nu5['name'], 'NU5')
assert_equal(nu5['activationheight'], 5)
assert_equal(nu5['status'], 'pending')
node.generate(1)
bci = node.getblockchaininfo()
assert_equal(bci['blocks'], 5)
upgrades = bci['upgrades']
overwinter = upgrades['5ba81b19']
assert_equal(overwinter['name'], 'Overwinter')
assert_equal(overwinter['activationheight'], 1)
assert_equal(overwinter['status'], 'active')
sapling = upgrades['76b809bb']
assert_equal(sapling['name'], 'Sapling')
assert_equal(sapling['activationheight'], 1)
assert_equal(sapling['status'], 'active')
blossom = upgrades['2bb40e60']
assert_equal(blossom['name'], 'Blossom')
assert_equal(blossom['activationheight'], 3)
assert_equal(blossom['status'], 'active')
heartwood = upgrades['f5b9230b']
assert_equal(heartwood['name'], 'Heartwood')
assert_equal(heartwood['activationheight'], 3)
assert_equal(heartwood['status'], 'active')
canopy = upgrades['e9ff75a6']
assert_equal(canopy['name'], 'Canopy')
assert_equal(canopy['activationheight'], 5)
assert_equal(canopy['status'], 'active')
nu5 = upgrades['37519621']
assert_equal(nu5['name'], 'NU5')
assert_equal(nu5['activationheight'], 5)
assert_equal(nu5['status'], 'active')
if __name__ == '__main__':
NuparamsTest().main()

View File

@ -39,7 +39,6 @@ class FullBlockTest(ComparisonTestFramework):
Change the "outcome" variable from each TestInstance object to only do the comparison. '''
def __init__(self):
super().__init__()
self.num_nodes = 1
self.block_heights = {}
self.coinbase_key = CECKey()
self.coinbase_key.set_secretbytes(b"horsebattery")
@ -159,7 +158,7 @@ class FullBlockTest(ComparisonTestFramework):
yield test
# Start by bulding a couple of blocks on top (which output is spent is in parentheses):
# Start by building a couple of blocks on top (which output is spent is in parentheses):
# genesis -> b1 (0) -> b2 (1)
out0 = get_spendable_output()
block(1, spend=out0)

View File

@ -1,218 +0,0 @@
#!/usr/bin/env python3
# Copyright (c) 2017 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, \
start_node, connect_nodes_bi, wait_and_assert_operationid_status, \
get_coinbase_address, DEFAULT_FEE
from decimal import Decimal
class PaymentDisclosureTest (BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 3
self.setup_clean_chain = True
def setup_network(self, split=False):
args = ['-debug=zrpcunsafe,paymentdisclosure', '-experimentalfeatures', '-paymentdisclosure', '-txindex=1']
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.nodes.append(start_node(1, self.options.tmpdir, args))
# node 2 does not enable payment disclosure
args2 = ['-debug=zrpcunsafe', '-experimentalfeatures', '-txindex=1']
self.nodes.append(start_node(2, self.options.tmpdir, args2))
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
self.is_network_split=False
self.sync_all()
def run_test (self):
print("Mining blocks...")
self.nodes[0].generate(4)
self.sync_all()
walletinfo = self.nodes[0].getwalletinfo()
assert_equal(walletinfo['immature_balance'], 40)
assert_equal(walletinfo['balance'], 0)
self.sync_all()
self.nodes[2].generate(3)
self.sync_all()
self.nodes[1].generate(101)
self.sync_all()
assert_equal(self.nodes[0].getbalance(), 40)
assert_equal(self.nodes[1].getbalance(), 10)
assert_equal(self.nodes[2].getbalance(), 30)
mytaddr = get_coinbase_address(self.nodes[0])
myzaddr = self.nodes[0].z_getnewaddress('sprout')
# Check that Node 2 has payment disclosure disabled.
try:
self.nodes[2].z_getpaymentdisclosure("invalidtxid", 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("payment disclosure is disabled" in errorString)
# Check that Node 0 returns an error for an unknown txid
try:
self.nodes[0].z_getpaymentdisclosure("invalidtxid", 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("No information available about transaction" in errorString)
# Shield coinbase utxos from node 0 of value 40, default fee
recipients = [{"address": myzaddr, "amount": Decimal('40.0') - DEFAULT_FEE}]
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
txid = wait_and_assert_operationid_status(self.nodes[0], myopid)
# Check the tx has joinsplits
assert( len(self.nodes[0].getrawtransaction("" + txid, 1)["vjoinsplit"]) > 0 )
# Sync mempools
self.sync_all()
# Confirm that you can't create a payment disclosure for an unconfirmed tx
try:
self.nodes[0].z_getpaymentdisclosure(txid, 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Transaction has not been confirmed yet" in errorString)
try:
self.nodes[1].z_getpaymentdisclosure(txid, 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Transaction has not been confirmed yet" in errorString)
# Mine tx
self.nodes[0].generate(1)
self.sync_all()
# Confirm that Node 1 cannot create a payment disclosure for a transaction which does not impact its wallet
try:
self.nodes[1].z_getpaymentdisclosure(txid, 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Transaction does not belong to the wallet" in errorString)
# Check that an invalid joinsplit index is rejected
try:
self.nodes[0].z_getpaymentdisclosure(txid, 1, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Invalid js_index" in errorString)
try:
self.nodes[0].z_getpaymentdisclosure(txid, -1, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Invalid js_index" in errorString)
# Check that an invalid output index is rejected
try:
self.nodes[0].z_getpaymentdisclosure(txid, 0, 2)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Invalid output_index" in errorString)
try:
self.nodes[0].z_getpaymentdisclosure(txid, 0, -1)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Invalid output_index" in errorString)
# Ask Node 0 to create and validate a payment disclosure for output 0
message = "Here is proof of my payment!"
pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 0, message)
result = self.nodes[0].z_validatepaymentdisclosure(pd)
assert(result["valid"])
output_value_sum = Decimal(result["value"])
# Ask Node 1 to confirm the payment disclosure is valid
result = self.nodes[1].z_validatepaymentdisclosure(pd)
assert(result["valid"])
assert_equal(result["message"], message)
assert_equal(result["value"], output_value_sum)
# Confirm that payment disclosure begins with prefix zpd:
assert(pd.startswith("zpd:"))
# Confirm that payment disclosure without prefix zpd: fails validation
try:
self.nodes[1].z_validatepaymentdisclosure(pd[4:])
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("payment disclosure prefix not found" in errorString)
# Check that total value of output index 0 and index 1 should equal shielding amount of 40 less standard fee.
pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 1)
result = self.nodes[0].z_validatepaymentdisclosure(pd)
output_value_sum += Decimal(result["value"])
assert_equal(output_value_sum, Decimal('40.0') - DEFAULT_FEE)
# Create a z->z transaction, sending shielded funds from node 0 to node 1
node1zaddr = self.nodes[1].z_getnewaddress('sprout')
recipients = [{"address":node1zaddr, "amount":Decimal('1')}]
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
txid = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
# Confirm that Node 0 can create a valid payment disclosure
pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 0, "a message of your choice")
result = self.nodes[0].z_validatepaymentdisclosure(pd)
assert(result["valid"])
# Confirm that Node 1, even as recipient of shielded funds, cannot create a payment disclosure
# as the transaction was created by Node 0 and Node 1's payment disclosure database does not
# contain the necessary data to do so, where the data would only have been available on Node 0
# when executing z_shieldcoinbase.
try:
self.nodes[1].z_getpaymentdisclosure(txid, 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Could not find payment disclosure info for the given joinsplit output" in errorString)
# Payment disclosures cannot be created for transparent transactions.
txid = self.nodes[2].sendtoaddress(mytaddr, 1.0)
self.sync_all()
# No matter the type of transaction, if it has not been confirmed, it is ignored.
try:
self.nodes[0].z_getpaymentdisclosure(txid, 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Transaction has not been confirmed yet" in errorString)
self.nodes[0].generate(1)
self.sync_all()
# Confirm that a payment disclosure can only be generated for a shielded transaction.
try:
self.nodes[0].z_getpaymentdisclosure(txid, 0, 0)
assert(False)
except JSONRPCException as e:
errorString = e.error['message']
assert("Transaction is not a shielded transaction" in errorString)
if __name__ == '__main__':
PaymentDisclosureTest().main()

View File

@ -152,7 +152,7 @@ class PruneTest(BitcoinTestFramework):
print("Invalidating block at height:",invalidheight,badhash)
self.nodes[1].invalidateblock(badhash)
# We've now switched to our previously mined-24 block fork on node 1, but thats not what we want
# We've now switched to our previously mined-24 block fork on node 1, but that's not what we want
# So invalidate that fork as well, until we're on the same chain as node 0/2 (but at an ancestor 288 blocks ago)
mainchainhash = self.nodes[0].getblockhash(invalidheight - 1)
curhash = self.nodes[1].getblockhash(invalidheight - 1)
@ -210,7 +210,7 @@ class PruneTest(BitcoinTestFramework):
goalbesthash = self.mainchainhash2
# As of 0.10 the current block download logic is not able to reorg to the original chain created in
# create_chain_with_stale_blocks because it doesn't know of any peer thats on that chain from which to
# create_chain_with_stale_blocks because it doesn't know of any peer that's on that chain from which to
# redownload its missing blocks.
# Invalidate the reorg_test chain in node 0 as well, it can successfully switch to the original chain
# because it has all the block data.

View File

@ -41,6 +41,7 @@ class RemoveSproutShieldingTest (BitcoinTestFramework):
# Shield coinbase to Sprout on node 0. Should pass
sprout_addr = self.nodes[0].z_getnewaddress('sprout')
sprout_addr_node2 = self.nodes[2].z_getnewaddress('sprout')
myopid = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), sprout_addr, 0)['opid']
wait_and_assert_operationid_status(self.nodes[0], myopid)
print("taddr -> Sprout z_shieldcoinbase tx accepted before Canopy on node 0")
@ -59,14 +60,6 @@ class RemoveSproutShieldingTest (BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all()
# Create taddr -> Sprout transaction and mine on node 0 before it is Canopy-aware. Should pass
sendmany_tx_0 = self.nodes[0].z_sendmany(taddr_0, [{"address": self.nodes[1].z_getnewaddress('sprout'), "amount": 1}])
wait_and_assert_operationid_status(self.nodes[0], sendmany_tx_0)
print("taddr -> Sprout z_sendmany tx accepted before Canopy on node 0")
self.nodes[0].generate(1)
self.sync_all()
# Create mergetoaddress taddr -> Sprout transaction and mine on node 0 before it is Canopy-aware. Should pass
merge_tx_0 = self.nodes[0].z_mergetoaddress(["ANY_TADDR"], self.nodes[1].z_getnewaddress('sprout'))
wait_and_assert_operationid_status(self.nodes[0], merge_tx_0['opid'])
@ -75,8 +68,9 @@ class RemoveSproutShieldingTest (BitcoinTestFramework):
# Mine to one block before Canopy activation on node 0; adding value
# to the Sprout pool will fail now since the transaction must be
# included in the next (or later) block, after Canopy has activated.
self.nodes[0].generate(4)
self.nodes[0].generate(5)
self.sync_all()
assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['e9ff75a6']['status'], 'pending')
# Shield coinbase to Sprout on node 0. Should fail
sprout_addr = self.nodes[0].z_getnewaddress('sprout')
@ -91,7 +85,7 @@ class RemoveSproutShieldingTest (BitcoinTestFramework):
sprout_addr = self.nodes[1].z_getnewaddress('sprout')
assert_raises_message(
JSONRPCException,
"Sprout shielding is not supported after Canopy",
"Sending funds into the Sprout pool is not supported by z_sendmany",
self.nodes[0].z_sendmany,
taddr_0, [{"address": sprout_addr, "amount": 1}])
print("taddr -> Sprout z_sendmany tx rejected at Canopy activation on node 0")
@ -109,8 +103,17 @@ class RemoveSproutShieldingTest (BitcoinTestFramework):
wait_and_assert_operationid_status(self.nodes[0], merge_tx_1['opid'])
print("Sprout -> Sprout z_mergetoaddress tx accepted at Canopy activation on node 0")
# Activate Canopy
self.nodes[0].generate(1)
self.sync_all()
assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['e9ff75a6']['status'], 'active')
# Generating a Sprout address should fail after Canopy.
assert_raises_message(
JSONRPCException,
"Invalid address type, \"sprout\" is not allowed after Canopy",
self.nodes[0].z_getnewaddress, 'sprout')
print("Sprout z_getnewaddress rejected at Canopy activation on node 0")
# Shield coinbase to Sapling on node 0. Should pass
sapling_addr = self.nodes[0].z_getnewaddress('sapling')
@ -123,7 +126,7 @@ class RemoveSproutShieldingTest (BitcoinTestFramework):
self.sync_all()
# Create z_mergetoaddress Sprout -> Sprout transaction on node 1. Should pass
merge_tx_2 = self.nodes[1].z_mergetoaddress(["ANY_SPROUT"], self.nodes[2].z_getnewaddress('sprout'))
merge_tx_2 = self.nodes[1].z_mergetoaddress(["ANY_SPROUT"], sprout_addr_node2)
wait_and_assert_operationid_status(self.nodes[1], merge_tx_2['opid'])
print("Sprout -> Sprout z_mergetoaddress tx accepted at NU5 activation on node 1")

View File

@ -29,7 +29,7 @@ def satoshi_round(amount):
def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment):
'''
Create and send a transaction with a random fee.
The transaction pays to a trival P2SH script, and assumes that its inputs
The transaction pays to a trivial P2SH script, and assumes that its inputs
are of the same form.
The function takes a list of confirmed outputs and unconfirmed outputs
and attempts to use the confirmed list first for its inputs.

View File

@ -158,8 +158,8 @@ class SproutSaplingMigration(BitcoinTestFramework):
def send_to_sprout_zaddr(self, tAddr, sproutAddr):
# Send some ZEC to a Sprout address
opid = self.nodes[0].z_sendmany(tAddr, [{"address": sproutAddr, "amount": Decimal('10')}], 1, 0)
wait_and_assert_operationid_status(self.nodes[0], opid)
result = self.nodes[0].z_shieldcoinbase(tAddr, sproutAddr, 0, 1)
wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.nodes[0].generate(1)
self.sync_all()

View File

@ -4,7 +4,7 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from pyblake2 import blake2b
from hashlib import blake2b
from .mininode import CBlock, CTransaction, CTxIn, CTxOut, COutPoint
from .script import CScript, OP_0, OP_EQUAL, OP_HASH160, OP_TRUE, OP_CHECKSIG

View File

@ -30,6 +30,8 @@ using a script provided.
To use, create a class that implements get_tests(), and pass it in
as the test generator to TestManager. get_tests() should be a python
generator that returns TestInstance objects. See below for definition.
In practice get_tests is always implemented on a subclass of ComparisonTestFramework.
'''
# TestNode behaves as follows:

View File

@ -1,4 +1,4 @@
from pyblake2 import blake2b
from hashlib import blake2b
import struct
from typing import (List, Optional)

View File

@ -36,7 +36,7 @@ from threading import RLock
from threading import Thread
import logging
import copy
from pyblake2 import blake2b
from hashlib import blake2b
from .equihash import (
gbp_basic,
@ -660,7 +660,7 @@ class OutputDescription(object):
self.encCiphertext = f.read(580)
self.outCiphertext = f.read(80)
self.zkproof = Groth16Proof()
self.zkproof.deserialize()
self.zkproof.deserialize(f)
def serialize(self):
r = b""
@ -971,6 +971,8 @@ class CTransaction(object):
self.nLockTime = 0
self.nExpiryHeight = 0
self.valueBalance = 0
self.saplingBundle = SaplingBundle()
self.orchardBundle = OrchardBundle()
self.shieldedSpends = []
self.shieldedOutputs = []
self.vJoinSplit = []
@ -988,6 +990,8 @@ class CTransaction(object):
self.nLockTime = tx.nLockTime
self.nExpiryHeight = tx.nExpiryHeight
self.valueBalance = tx.valueBalance
self.saplingBundle = copy.deepcopy(tx.saplingBundle)
self.orchardBundle = copy.deepcopy(tx.orchardBundle)
self.shieldedSpends = copy.deepcopy(tx.shieldedSpends)
self.shieldedOutputs = copy.deepcopy(tx.shieldedOutputs)
self.vJoinSplit = copy.deepcopy(tx.vJoinSplit)
@ -1075,6 +1079,7 @@ class CTransaction(object):
# Common transaction fields
r += struct.pack("<I", header)
r += struct.pack("<I", self.nVersionGroupId)
r += struct.pack("<I", self.nConsensusBranchId)
r += struct.pack("<I", self.nLockTime)
r += struct.pack("<I", self.nExpiryHeight)
@ -1121,11 +1126,14 @@ class CTransaction(object):
if self.nVersion >= 5:
from . import zip244
txid = zip244.txid_digest(self)
self.auth_digest = zip244.auth_digest(self)
else:
txid = hash256(self.serialize())
self.auth_digest = b'\xFF'*32
if self.sha256 is None:
self.sha256 = uint256_from_str(txid)
self.hash = encode(txid[::-1], 'hex_codec').decode('ascii')
self.auth_digest_hex = encode(self.auth_digest[::-1], 'hex_codec').decode('ascii')
def is_valid(self):
self.calc_sha256()
@ -1258,6 +1266,27 @@ class CBlock(CBlockHeader):
hashes = newhashes
return uint256_from_str(hashes[0])
def calc_auth_data_root(self):
hashes = []
nleaves = 0
for tx in self.vtx:
tx.calc_sha256()
hashes.append(tx.auth_digest)
nleaves += 1
# Continue adding leaves (of zeros) until reaching a power of 2
while nleaves & (nleaves-1) > 0:
hashes.append(b'\x00'*32)
nleaves += 1
while len(hashes) > 1:
newhashes = []
for i in range(0, len(hashes), 2):
digest = blake2b(digest_size=32, person=b'ZcashAuthDatHash')
digest.update(hashes[i])
digest.update(hashes[i+1])
newhashes.append(digest.digest())
hashes = newhashes
return hashes[0]
def is_valid(self, n=48, k=5):
# H(I||...
digest = blake2b(digest_size=(512//n)*n//8, person=zcash_person(n, k))

View File

@ -22,7 +22,7 @@ if sys.version > '3':
bchr = lambda x: bytes([x])
bord = lambda x: x
from pyblake2 import blake2b
from hashlib import blake2b
from binascii import hexlify
import struct

View File

@ -186,7 +186,7 @@ class ComparisonTestFramework(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 2
self.num_nodes = 1
self.setup_clean_chain = True
def add_options(self, parser):
@ -203,3 +203,6 @@ class ComparisonTestFramework(BitcoinTestFramework):
extra_args=[['-debug', '-whitelist=127.0.0.1']] * self.num_nodes,
binary=[self.options.testbinary] +
[self.options.refbinary]*(self.num_nodes-1))
def get_tests(self):
raise NotImplementedError

View File

@ -13,9 +13,9 @@
import struct
from pyblake2 import blake2b
from hashlib import blake2b
from .mininode import ser_uint256
from .mininode import ser_string, ser_uint256
from .script import (
SIGHASH_ANYONECANPAY,
SIGHASH_NONE,
@ -41,7 +41,7 @@ def transparent_digest(tx):
def transparent_scripts_digest(tx):
digest = blake2b(digest_size=32, person=b'ZTxAuthTransHash')
for x in tx.vin:
digest.update(bytes(x.scriptSig))
digest.update(ser_string(x.scriptSig))
return digest.digest()
# Sapling
@ -52,7 +52,7 @@ def sapling_digest(saplingBundle):
if len(saplingBundle.spends) + len(saplingBundle.outputs) > 0:
digest.update(sapling_spends_digest(saplingBundle))
digest.update(sapling_outputs_digest(saplingBundle))
digest.update(struct.pack('<Q', saplingBundle.valueBalance))
digest.update(struct.pack('<q', saplingBundle.valueBalance))
return digest.digest()
@ -126,7 +126,7 @@ def sapling_outputs_noncompact_digest(saplingBundle):
for desc in saplingBundle.outputs:
digest.update(ser_uint256(desc.cv))
digest.update(desc.encCiphertext[564:])
digest.update(desc.outCipherText)
digest.update(desc.outCiphertext)
return digest.digest()
# Orchard
@ -139,7 +139,7 @@ def orchard_digest(orchardBundle):
digest.update(orchard_actions_memos_digest(orchardBundle))
digest.update(orchard_actions_noncompact_digest(orchardBundle))
digest.update(struct.pack('<B', orchardBundle.flags()))
digest.update(struct.pack('<Q', orchardBundle.valueBalance))
digest.update(struct.pack('<q', orchardBundle.valueBalance))
digest.update(bytes(orchardBundle.anchor))
return digest.digest()
@ -288,7 +288,7 @@ def outputs_sig_digest(tx, nHashType, txin):
def txin_sig_digest(tx, txin):
digest = blake2b(digest_size=32, person=b'Zcash___TxInHash')
digest.update(bytes(tx.vin[txin.nIn].prevout))
digest.update(bytes(txin.scriptCode))
digest.update(ser_string(txin.scriptCode))
digest.update(struct.pack('<Q', txin.amount))
digest.update(struct.pack('<I', tx.vin[txin.nIn].nSequence))
return digest.digest()

View File

@ -29,6 +29,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
fail,
get_coinbase_address,
start_node, start_nodes,
sync_blocks, sync_mempools,
@ -88,9 +89,14 @@ class TurnstileTest (BitcoinTestFramework):
# Node 0 shields some funds
dest_addr = self.nodes[0].z_getnewaddress(POOL_NAME.lower())
taddr0 = get_coinbase_address(self.nodes[0])
recipients = []
recipients.append({"address": dest_addr, "amount": Decimal('10')})
myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0)
if (POOL_NAME == "SPROUT"):
myopid = self.nodes[0].z_shieldcoinbase(taddr0, dest_addr, 0, 1)['opid']
elif (POOL_NAME == "SAPLING"):
recipients = []
recipients.append({"address": dest_addr, "amount": Decimal('10')})
myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0)
else:
fail("Unrecognized pool name: " + POOL_NAME)
wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
self.nodes[0].generate(1)

View File

@ -44,7 +44,7 @@ class UpgradeGoldenTest(BitcoinTestFramework):
logging.info("Initializing the network in "+self.options.tmpdir)
# Node 0 will always be running with the most recent network upgrade version.
# The remaining nodes start with the nework upgrade versions in order that they
# The remaining nodes start with the network upgrade versions in order that they
# are specified in the upgrades list.
upgrade_args = [self.upgrades[-1].extra_args] + [u.extra_args for u in self.upgrades]
self.nodes = start_nodes(len(self.upgrades) + 1, self.options.tmpdir, extra_args=upgrade_args)

133
qa/rpc-tests/wallet_accounts.py Executable file
View File

@ -0,0 +1,133 @@
#!/usr/bin/env python3
# Copyright (c) 2022 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.authproxy import JSONRPCException
from test_framework.mininode import COIN
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_message,
get_coinbase_address,
start_nodes,
wait_and_assert_operationid_status,
)
from decimal import Decimal
# Test wallet accounts behaviour
class WalletAccountsTest(BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(self.num_nodes, self.options.tmpdir, [[
'-experimentalfeatures',
'-orchardwallet',
]] * self.num_nodes)
def check_receiver_types(self, ua, expected):
actual = self.nodes[0].z_listunifiedreceivers(ua)
assert_equal(set(expected), set(actual))
# Check we only have balances in the expected pools.
# Remember that empty pools are omitted from the output.
def _check_balance_for_rpc(self, rpcmethod, node, account, expected, minconf):
rpc = getattr(self.nodes[node], rpcmethod)
actual = rpc(account) if minconf is None else rpc(account, minconf)
assert_equal(set(expected), set(actual['pools']))
for pool in expected:
assert_equal(expected[pool] * COIN, actual['pools'][pool]['valueZat'])
assert_equal(actual['minimum_confirmations'], 1 if minconf is None else minconf)
def check_balance(self, node, account, address, expected, minconf=None):
self._check_balance_for_rpc('z_getbalanceforaccount', node, account, expected, minconf)
fvk = self.nodes[node].z_exportviewingkey(address)
self._check_balance_for_rpc('z_getbalanceforviewingkey', node, fvk, expected, minconf)
def run_test(self):
# With a new wallet, the first account will be 0.
account0 = self.nodes[0].z_getnewaccount()
assert_equal(account0['account'], 0)
# The next account will be 1.
account1 = self.nodes[0].z_getnewaccount()
assert_equal(account1['account'], 1)
# Generate the first address for account 0.
addr0 = self.nodes[0].z_getaddressforaccount(0)
assert_equal(addr0['account'], 0)
assert_equal(set(addr0['pools']), set(['transparent', 'sapling']))
ua0 = addr0['unifiedaddress']
# We pick mnemonic phrases to ensure that we can always generate the default
# address in account 0; this is however not necessarily at diversifier index 0.
# We should be able to generate it directly and get the exact same data.
j = addr0['diversifier_index']
assert_equal(self.nodes[0].z_getaddressforaccount(0, [], j), addr0)
if j > 0:
# We should get an error if we generate the address at diversifier index 0.
assert_raises_message(
JSONRPCException,
'no address at diversifier index 0',
self.nodes[0].z_getaddressforaccount, 0, [], 0)
# The first address for account 1 is different to account 0.
addr1 = self.nodes[0].z_getaddressforaccount(1)
assert_equal(addr1['account'], 1)
assert_equal(set(addr1['pools']), set(['transparent', 'sapling']))
ua1 = addr1['unifiedaddress']
assert(ua0 != ua1)
# The UA contains the expected receiver kinds.
self.check_receiver_types(ua0, ['transparent', 'sapling'])
self.check_receiver_types(ua1, ['transparent', 'sapling'])
# The balances of the accounts are all zero.
self.check_balance(0, 0, ua0, {})
self.check_balance(0, 1, ua1, {})
# Manually send funds to one of the receivers in the UA.
recipients = [{'address': ua0, 'amount': Decimal('10')}]
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
txid = wait_and_assert_operationid_status(self.nodes[0], opid)
# The wallet should detect the new note as belonging to the UA.
tx_details = self.nodes[0].z_viewtransaction(txid)
assert_equal(len(tx_details['outputs']), 1)
assert_equal(tx_details['outputs'][0]['type'], 'sapling')
assert_equal(tx_details['outputs'][0]['address'], ua0)
# The new balance should not be visible with the default minconf, but should be
# visible with minconf=0.
self.sync_all()
self.check_balance(0, 0, ua0, {})
self.check_balance(0, 0, ua0, {'sapling': 10}, 0)
self.nodes[2].generate(1)
self.sync_all()
# The default minconf should now detect the balance.
self.check_balance(0, 0, ua0, {'sapling': 10})
# Manually send funds from the UA receiver.
node1sapling = self.nodes[1].z_getnewaddress('sapling')
recipients = [{'address': node1sapling, 'amount': Decimal('1')}]
opid = self.nodes[0].z_sendmany(ua0, recipients, 1, 0)
txid = wait_and_assert_operationid_status(self.nodes[0], opid)
# The wallet should detect the spent note as belonging to the UA.
tx_details = self.nodes[0].z_viewtransaction(txid)
assert_equal(len(tx_details['spends']), 1)
assert_equal(tx_details['spends'][0]['type'], 'sapling')
assert_equal(tx_details['spends'][0]['address'], ua0)
# The balances of the account should reflect whether zero-conf transactions are
# being considered. We will show either 0 (because the spent 10-ZEC note is never
# shown, as that transaction has been created and broadcast, and _might_ get mined
# up until the transaction expires), or 9 (if we include the unmined transaction).
self.sync_all()
self.check_balance(0, 0, ua0, {})
self.check_balance(0, 0, ua0, {'sapling': 9}, 0)
if __name__ == '__main__':
WalletAccountsTest().main()

View File

@ -13,7 +13,7 @@ class WalletBroadcastTest(BitcoinTestFramework):
#do some -walletbroadcast tests
stop_nodes(self.nodes)
wait_bitcoinds()
self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]])
self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"]] * 3)
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)

View File

@ -81,15 +81,11 @@ class WalletChangeAddressesTest(BitcoinTestFramework):
taddr = self.nodes[0].getnewaddress()
saplingAddr = self.nodes[0].z_getnewaddress('sapling')
sproutAddr = self.nodes[0].z_getnewaddress('sprout')
print()
print('Checking z_sendmany(taddr->Sapling)')
check_change_taddr_reuse(saplingAddr)
print()
print('Checking z_sendmany(taddr->Sprout)')
check_change_taddr_reuse(sproutAddr)
print()
print('Checking z_sendmany(taddr->taddr)')
check_change_taddr_reuse(taddr)

View File

@ -3,13 +3,16 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.authproxy import JSONRPCException
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_true, start_nodes
class WalletImportExportTest (BitcoinTestFramework):
def setup_network(self, split=False):
num_nodes = 3
extra_args = [["-exportdir={}/export{}".format(self.options.tmpdir, i)] for i in range(num_nodes)]
extra_args = [([
"-exportdir={}/export{}".format(self.options.tmpdir, i),
] + (["-walletrequirebackup"] if i == 0 else [])) for i in range(num_nodes)]
self.nodes = start_nodes(num_nodes, self.options.tmpdir, extra_args)
def run_test(self):
@ -17,12 +20,28 @@ class WalletImportExportTest (BitcoinTestFramework):
privkey2 = self.nodes[2].z_exportkey(sapling_address2)
self.nodes[0].z_importkey(privkey2)
# test walletconfirmbackup
try:
self.nodes[0].getnewaddress()
except JSONRPCException as e:
errorString = e.error['message']
assert_equal("Error: Please acknowledge that you have backed up" in errorString, True)
try:
self.nodes[0].z_getnewaddress('sapling')
except JSONRPCException as e:
errorString = e.error['message']
assert_equal("Error: Please acknowledge that you have backed up" in errorString, True)
dump_path0 = self.nodes[0].z_exportwallet('walletdumpmnem')
(mnemonic, _, _, _) = parse_wallet_file(dump_path0)
self.nodes[0].walletconfirmbackup(mnemonic)
# Now that we've confirmed backup, we can generate addresses
sprout_address0 = self.nodes[0].z_getnewaddress('sprout')
sapling_address0 = self.nodes[0].z_getnewaddress('sapling')
# node 0 should have the keys
dump_path0 = self.nodes[0].z_exportwallet('walletdump')
(t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0)
(_, t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0)
sapling_line_lengths = [len(sapling_key0.split(' #')[0].split()) for sapling_key0 in sapling_keys0.splitlines()]
assert_equal(2, len(sapling_line_lengths), "Should have 2 sapling keys")
@ -35,7 +54,7 @@ class WalletImportExportTest (BitcoinTestFramework):
# node 1 should not have the keys
dump_path1 = self.nodes[1].z_exportwallet('walletdumpbefore')
(t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1)
(_, t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1)
assert_true(sprout_address0 not in sprout_keys1)
assert_true(sapling_address0 not in sapling_keys1)
@ -45,13 +64,13 @@ class WalletImportExportTest (BitcoinTestFramework):
# node 1 should now have the keys
dump_path1 = self.nodes[1].z_exportwallet('walletdumpafter')
(t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1)
(_, t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1)
assert_true(sprout_address0 in sprout_keys1)
assert_true(sapling_address0 in sapling_keys1)
assert_true(sapling_address2 in sapling_keys1)
# make sure we have perserved the metadata
# make sure we have preserved the metadata
for sapling_key0 in sapling_keys0.splitlines():
assert_true(sapling_key0 in sapling_keys1)
@ -59,15 +78,15 @@ class WalletImportExportTest (BitcoinTestFramework):
def parse_wallet_file(dump_path):
file_lines = open(dump_path, "r", encoding="utf8").readlines()
# We expect information about the HDSeed and fingerpring in the header
assert_true("HDSeed" in file_lines[4], "Expected HDSeed")
assert_true("fingerprint" in file_lines[4], "Expected fingerprint")
seed_comment_line = file_lines[4][2:].split() # ["HDSeed=...", "fingerprint=..."]
assert_true(seed_comment_line[0].split("=")[1] != seed_comment_line[1].split("=")[1], "The seed should not equal the fingerprint")
assert_true("recovery_phrase" in file_lines[5], "Expected emergency recovery phrase")
assert_true("language" in file_lines[6], "Expected mnemonic seed language")
assert_true("fingerprint" in file_lines[7], "Expected mnemonic seed fingerprint")
mnemonic = file_lines[5].split("=")[1].replace("\"", "").strip()
(t_keys, i) = parse_wallet_file_lines(file_lines, 0)
(sprout_keys, i) = parse_wallet_file_lines(file_lines, i)
(sapling_keys, i) = parse_wallet_file_lines(file_lines, i)
return (t_keys, sprout_keys, sapling_keys)
return (mnemonic, t_keys, sprout_keys, sapling_keys)
def parse_wallet_file_lines(file_lines, i):
keys = []
@ -81,4 +100,4 @@ def parse_wallet_file_lines(file_lines, i):
return ("".join(keys), i)
if __name__ == '__main__':
WalletImportExportTest().main()
WalletImportExportTest().main()

View File

@ -6,7 +6,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
get_coinbase_address,
wait_and_assert_operationid_status,
DEFAULT_FEE
)
@ -20,7 +19,6 @@ class WalletListNotes(BitcoinTestFramework):
# Current height = 200
assert_equal(200, self.nodes[0].getblockcount())
sproutzaddr = self.nodes[0].z_getnewaddress('sprout')
saplingzaddr = self.nodes[0].z_getnewaddress('sapling')
# we've got lots of coinbase (taddr) but no shielded funds yet
assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private']))
@ -30,11 +28,10 @@ class WalletListNotes(BitcoinTestFramework):
self.sync_all()
assert_equal(201, self.nodes[0].getblockcount())
# Shield coinbase funds (must be a multiple of 10, no change allowed)
receive_amount_10 = Decimal('10.0') - DEFAULT_FEE
recipients = [{"address":sproutzaddr, "amount":receive_amount_10}]
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients)
txid_1 = wait_and_assert_operationid_status(self.nodes[0], myopid)
# Shield one coinbase output
receive_amount_1 = Decimal('10.0') - DEFAULT_FEE
result = self.nodes[0].z_shieldcoinbase('*', sproutzaddr, DEFAULT_FEE, 1)
txid_1 = wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.sync_all()
# No funds (with (default) one or more confirmations) in sproutzaddr yet
@ -49,9 +46,10 @@ class WalletListNotes(BitcoinTestFramework):
assert_equal(1, len(unspent_cb))
assert_equal(False, unspent_cb[0]['change'])
assert_equal(txid_1, unspent_cb[0]['txid'])
assert_equal('sprout', unspent_cb[0]['type'])
assert_equal(True, unspent_cb[0]['spendable'])
assert_equal(sproutzaddr, unspent_cb[0]['address'])
assert_equal(receive_amount_10, unspent_cb[0]['amount'])
assert_equal(receive_amount_1, unspent_cb[0]['amount'])
# list unspent, filtering by address, should produce same result
unspent_cb_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr])
@ -64,13 +62,13 @@ class WalletListNotes(BitcoinTestFramework):
# Current height = 202
assert_equal(202, self.nodes[0].getblockcount())
# Send 1.0 minus default fee from sproutzaddr to a new zaddr
sproutzaddr2 = self.nodes[0].z_getnewaddress('sprout')
receive_amount_1 = Decimal('1.0') - DEFAULT_FEE
change_amount_9 = receive_amount_10 - Decimal('1.0')
assert_equal('sprout', self.nodes[0].z_validateaddress(sproutzaddr2)['type'])
recipients = [{"address": sproutzaddr2, "amount":receive_amount_1}]
myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients)
# Send 1.0 minus default fee from sproutzaddr to a new Sapling zaddr
saplingzaddr = self.nodes[0].z_getnewaddress('sapling')
receive_amount_2 = Decimal('1.0')
change_amount_2 = receive_amount_1 - receive_amount_2 - DEFAULT_FEE
assert_equal('sapling', self.nodes[0].z_validateaddress(saplingzaddr)['type'])
recipients = [{"address": saplingzaddr, "amount":receive_amount_2}]
myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, DEFAULT_FEE, True)
txid_2 = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
@ -81,17 +79,19 @@ class WalletListNotes(BitcoinTestFramework):
unspent_tx = sorted(unspent_tx, key=lambda k: k['amount'])
assert_equal(False, unspent_tx[0]['change'])
assert_equal(txid_2, unspent_tx[0]['txid'])
assert_equal('sapling', unspent_tx[0]['type'])
assert_equal(True, unspent_tx[0]['spendable'])
assert_equal(sproutzaddr2, unspent_tx[0]['address'])
assert_equal(receive_amount_1, unspent_tx[0]['amount'])
assert_equal(saplingzaddr, unspent_tx[0]['address'])
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
assert_equal(True, unspent_tx[1]['change'])
assert_equal(txid_2, unspent_tx[1]['txid'])
assert_equal('sprout', unspent_tx[1]['type'])
assert_equal(True, unspent_tx[1]['spendable'])
assert_equal(sproutzaddr, unspent_tx[1]['address'])
assert_equal(change_amount_9, unspent_tx[1]['amount'])
assert_equal(change_amount_2, unspent_tx[1]['amount'])
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr2])
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr])
assert_equal(1, len(unspent_tx_filter))
assert_equal(unspent_tx[0], unspent_tx_filter[0])
@ -99,15 +99,15 @@ class WalletListNotes(BitcoinTestFramework):
assert_equal(1, len(unspent_tx_filter))
assert_equal(unspent_tx[1], unspent_tx_filter[0])
# No funds in saplingzaddr yet
assert_equal(0, len(self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr])))
self.nodes[0].generate(1)
self.sync_all()
# Send 2.0 minus default fee to our sapling zaddr
# (sending from a sprout zaddr to a sapling zaddr is disallowed,
# so send from coin base)
receive_amount_2 = Decimal('2.0') - DEFAULT_FEE
recipients = [{"address": saplingzaddr, "amount":receive_amount_2}]
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients)
# Send 2.0 minus default fee to a new sapling zaddr
saplingzaddr2 = self.nodes[0].z_getnewaddress('sapling')
receive_amount_3 = Decimal('2.0')
change_amount_3 = change_amount_2 - receive_amount_3 - DEFAULT_FEE
recipients = [{"address": saplingzaddr2, "amount":receive_amount_3}]
myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients, 1, DEFAULT_FEE, True)
txid_3 = wait_and_assert_operationid_status(self.nodes[0], myopid)
self.sync_all()
unspent_tx = self.nodes[0].z_listunspent(0)
@ -118,32 +118,35 @@ class WalletListNotes(BitcoinTestFramework):
assert_equal(False, unspent_tx[0]['change'])
assert_equal(txid_2, unspent_tx[0]['txid'])
assert_equal('sapling', unspent_tx[0]['type'])
assert_equal(True, unspent_tx[0]['spendable'])
assert_equal(sproutzaddr2, unspent_tx[0]['address'])
assert_equal(receive_amount_1, unspent_tx[0]['amount'])
assert_equal(saplingzaddr, unspent_tx[0]['address'])
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
assert_equal(False, unspent_tx[1]['change'])
assert_equal(txid_3, unspent_tx[1]['txid'])
assert_equal('sapling', unspent_tx[1]['type'])
assert_equal(True, unspent_tx[1]['spendable'])
assert_equal(saplingzaddr, unspent_tx[1]['address'])
assert_equal(receive_amount_2, unspent_tx[1]['amount'])
assert_equal(saplingzaddr2, unspent_tx[1]['address'])
assert_equal(receive_amount_3, unspent_tx[1]['amount'])
assert_equal(True, unspent_tx[2]['change'])
assert_equal(txid_2, unspent_tx[2]['txid'])
assert_equal(txid_3, unspent_tx[2]['txid'])
assert_equal('sprout', unspent_tx[2]['type'])
assert_equal(True, unspent_tx[2]['spendable'])
assert_equal(sproutzaddr, unspent_tx[2]['address'])
assert_equal(change_amount_9, unspent_tx[2]['amount'])
assert_equal(change_amount_3, unspent_tx[2]['amount'])
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr])
assert_equal(1, len(unspent_tx_filter))
assert_equal(unspent_tx[1], unspent_tx_filter[0])
assert_equal(unspent_tx[0], unspent_tx_filter[0])
# test that pre- and post-sapling can be filtered in a single call
unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False,
[sproutzaddr, saplingzaddr])
assert_equal(2, len(unspent_tx_filter))
unspent_tx_filter = sorted(unspent_tx_filter, key=lambda k: k['amount'])
assert_equal(unspent_tx[1], unspent_tx_filter[0])
assert_equal(unspent_tx[0], unspent_tx_filter[0])
assert_equal(unspent_tx[2], unspent_tx_filter[1])
# so far, this node has no watchonly addresses, so results are the same

View File

@ -3,9 +3,19 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
from test_framework.authproxy import JSONRPCException
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_true, assert_false, DEFAULT_FEE, DEFAULT_FEE_ZATS
from test_framework.util import wait_and_assert_operationid_status
from test_framework.util import (
assert_equal,
assert_true,
assert_false,
assert_raises_message,
connect_nodes_bi,
get_coinbase_address,
DEFAULT_FEE,
DEFAULT_FEE_ZATS
)
from test_framework.util import wait_and_assert_operationid_status, start_nodes
from decimal import Decimal
my_memo_str = 'c0ffee' # stay awake
@ -15,21 +25,190 @@ my_memo = my_memo + '0'*(1024-len(my_memo))
no_memo = 'f6' + ('0'*1022) # see section 5.5 of the protocol spec
class ListReceivedTest (BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 3
self.setup_clean_chain = True
def setup_network(self):
self.nodes = start_nodes(
self.num_nodes, self.options.tmpdir,
extra_args=[['-experimentalfeatures', '-orchardwallet']] * self.num_nodes)
connect_nodes_bi(self.nodes, 0, 1)
connect_nodes_bi(self.nodes, 1, 2)
connect_nodes_bi(self.nodes, 0, 2)
self.is_network_split = False
self.sync_all()
def generate_and_sync(self, new_height):
current_height = self.nodes[0].getblockcount()
assert(new_height > current_height)
self.sync_all()
self.nodes[0].generate(new_height - current_height)
self.sync_all()
assert_equal(new_height, self.nodes[0].getblockcount())
def run_test_release(self, release, height):
def test_received_sprout(self, height):
self.generate_and_sync(height+2)
zaddr1 = self.nodes[1].z_getnewaddress('sprout')
# Send 10 ZEC each zaddr1 and zaddrExt via z_shieldcoinbase
result = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), zaddr1, 0, 1)
txid_shielding1 = wait_and_assert_operationid_status(self.nodes[0], result['opid'])
zaddrExt = self.nodes[2].z_getnewaddress('sprout')
result = self.nodes[0].z_shieldcoinbase(get_coinbase_address(self.nodes[0]), zaddrExt, 0, 1)
txid_shieldingExt = wait_and_assert_operationid_status(self.nodes[0], result['opid'])
self.sync_all()
# Decrypted transaction details should not be visible on node 0
pt = self.nodes[0].z_viewtransaction(txid_shielding1)
assert_equal(pt['txid'], txid_shielding1)
assert_equal(len(pt['spends']), 0)
assert_equal(len(pt['outputs']), 0)
# Decrypted transaction details should be correct on node 1
pt = self.nodes[1].z_viewtransaction(txid_shielding1)
assert_equal(pt['txid'], txid_shielding1)
assert_equal(len(pt['spends']), 0)
assert_equal(len(pt['outputs']), 1)
assert_equal(pt['outputs'][0]['type'], 'sprout')
assert_equal(pt['outputs'][0]['js'], 0)
assert_equal(pt['outputs'][0]['address'], zaddr1)
assert_equal(pt['outputs'][0]['value'], Decimal('10'))
assert_equal(pt['outputs'][0]['valueZat'], 1000000000)
assert_equal(pt['outputs'][0]['memo'], no_memo)
jsOutputPrev = pt['outputs'][0]['jsOutput']
# Second transaction should not be known to node 1
assert_raises_message(
JSONRPCException,
"Invalid or non-wallet transaction id",
self.nodes[1].z_viewtransaction,
txid_shieldingExt)
# Second transaction should be visible on node0
pt = self.nodes[2].z_viewtransaction(txid_shieldingExt)
assert_equal(pt['txid'], txid_shieldingExt)
assert_equal(len(pt['spends']), 0)
assert_equal(len(pt['outputs']), 1)
assert_equal(pt['outputs'][0]['type'], 'sprout')
assert_equal(pt['outputs'][0]['js'], 0)
assert_equal(pt['outputs'][0]['address'], zaddrExt)
assert_equal(pt['outputs'][0]['value'], Decimal('10'))
assert_equal(pt['outputs'][0]['valueZat'], 1000000000)
assert_equal(pt['outputs'][0]['memo'], no_memo)
r = self.nodes[1].z_listreceivedbyaddress(zaddr1)
assert_equal(0, len(r), "Should have received no confirmed note")
c = self.nodes[1].z_getnotescount()
assert_equal(0, c['sprout'], "Count of confirmed notes should be 0")
# No confirmation required, one note should be present
r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0)
assert_equal(1, len(r), "Should have received one (unconfirmed) note")
assert_equal(txid_shielding1, r[0]['txid'])
assert_equal(10, r[0]['amount'])
assert_equal(1000000000, r[0]['amountZat'])
assert_false(r[0]['change'], "Note should not be change")
assert_equal(no_memo, r[0]['memo'])
assert_equal(0, r[0]['confirmations'])
assert_equal(-1, r[0]['blockindex'])
assert_equal(0, r[0]['blockheight'])
c = self.nodes[1].z_getnotescount(0)
assert_equal(1, c['sprout'], "Count of unconfirmed notes should be 1")
# Confirm transaction (10 ZEC shielded)
self.generate_and_sync(height+3)
# Require one confirmation, note should be present
r0 = self.nodes[1].z_listreceivedbyaddress(zaddr1)
assert_equal(1, len(r0), "Should have received one (unconfirmed) note")
assert_equal(txid_shielding1, r0[0]['txid'])
assert_equal(10, r0[0]['amount'])
assert_equal(1000000000, r0[0]['amountZat'])
assert_false(r0[0]['change'], "Note should not be change")
assert_equal(no_memo, r0[0]['memo'])
assert_equal(1, r0[0]['confirmations'])
assert_equal(height + 3, r0[0]['blockheight'])
taddr = self.nodes[1].getnewaddress()
# Generate some change by sending part of zaddr1 back to taddr
opid = self.nodes[1].z_sendmany(zaddr1, [{'address': taddr, 'amount': 0.6}])
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
self.generate_and_sync(height+4)
# Decrypted transaction details should be correct
pt = self.nodes[1].z_viewtransaction(txid)
assert_equal(pt['txid'], txid)
assert_equal(len(pt['spends']), 1)
# TODO: enable once z_viewtransaction displays transparent elements
# assert_equal(len(pt['outputs']), 2)
assert_equal(len(pt['outputs']), 1)
assert_equal(pt['spends'][0]['type'], 'sprout')
assert_equal(pt['spends'][0]['txidPrev'], txid_shielding1)
assert_equal(pt['spends'][0]['js'], 0)
assert_equal(pt['spends'][0]['jsPrev'], 0)
assert_equal(pt['spends'][0]['jsOutputPrev'], jsOutputPrev)
assert_equal(pt['spends'][0]['address'], zaddr1)
assert_equal(pt['spends'][0]['value'], Decimal('10.0'))
assert_equal(pt['spends'][0]['valueZat'], 1000000000)
# We expect a transparent output and a Sprout output, but the RPC does
# not define any particular ordering of these within the returned JSON.
outputs = [{
'type': output['type'],
'address': output['address'],
'value': output['value'],
'valueZat': output['valueZat'],
} for output in pt['outputs']]
for (i, output) in enumerate(pt['outputs']):
if 'memo' in output:
outputs[i]['memo'] = output['memo']
# TODO: enable once z_viewtransaction displays transparent elements
# assert({
# 'type': 'transparent',
# 'address': taddr,
# 'value': Decimal('0.6'),
# 'valueZat': 60000000,
# } in outputs)
assert({
'type': 'sprout',
'address': zaddr1,
'value': Decimal('9.4') - DEFAULT_FEE,
'valueZat': 940000000 - DEFAULT_FEE_ZATS,
'memo': no_memo,
} in outputs)
# zaddr1 should have a note with change
r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0)
assert_equal(2, len(r), "zaddr1 Should have received 2 notes")
r = sorted(r, key = lambda received: received['amount'])
assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('9.4')-DEFAULT_FEE, r[0]['amount'])
assert_equal(940000000-DEFAULT_FEE_ZATS, r[0]['amountZat'])
assert_true(r[0]['change'], "Note valued at (9.4-"+str(DEFAULT_FEE)+") should be change")
assert_equal(no_memo, r[0]['memo'])
# The old note still exists (it's immutable), even though it is spent
assert_equal(Decimal('10.0'), r[1]['amount'])
assert_equal(1000000000, r[1]['amountZat'])
assert_false(r[1]['change'], "Note valued at 10.0 should not be change")
assert_equal(no_memo, r[1]['memo'])
def test_received_sapling(self, height):
self.generate_and_sync(height+1)
taddr = self.nodes[1].getnewaddress()
zaddr1 = self.nodes[1].z_getnewaddress(release)
zaddrExt = self.nodes[3].z_getnewaddress(release)
zaddr1 = self.nodes[1].z_getnewaddress('sapling')
zaddrExt = self.nodes[2].z_getnewaddress('sapling')
self.nodes[0].sendtoaddress(taddr, 4.0)
txid_taddr = self.nodes[0].sendtoaddress(taddr, 4.0)
self.generate_and_sync(height+2)
# Send 1 ZEC to zaddr1
@ -42,62 +221,35 @@ class ListReceivedTest (BitcoinTestFramework):
# Decrypted transaction details should be correct
pt = self.nodes[1].z_viewtransaction(txid)
assert_equal(pt['txid'], txid)
assert_equal(len(pt['spends']), 0)
assert_equal(len(pt['outputs']), 1 if release == 'sprout' else 2)
assert_equal(len(pt['outputs']), 2)
# Output orders can be randomized, so we check the output
# positions and contents separately
outputs = []
# Outputs are not returned in a defined order but the amounts are deterministic
outputs = sorted(pt['outputs'], key=lambda x: x['valueZat'])
assert_equal(outputs[0]['type'], 'sapling')
assert_equal(outputs[0]['address'], zaddr1)
assert_equal(outputs[0]['value'], Decimal('1'))
assert_equal(outputs[0]['valueZat'], 100000000)
assert_equal(outputs[0]['output'], 0)
assert_equal(outputs[0]['outgoing'], False)
assert_equal(outputs[0]['memo'], my_memo)
assert_equal(outputs[0]['memoStr'], my_memo_str)
assert_equal(pt['outputs'][0]['type'], release)
if release == 'sprout':
assert_equal(pt['outputs'][0]['js'], 0)
jsOutputPrev = pt['outputs'][0]['jsOutput']
elif pt['outputs'][0]['address'] == zaddr1:
assert_equal(pt['outputs'][0]['outgoing'], False)
assert_equal(pt['outputs'][0]['memoStr'], my_memo_str)
else:
assert_equal(pt['outputs'][0]['outgoing'], True)
outputs.append({
'address': pt['outputs'][0]['address'],
'value': pt['outputs'][0]['value'],
'valueZat': pt['outputs'][0]['valueZat'],
'memo': pt['outputs'][0]['memo'],
})
if release != 'sprout':
assert_equal(pt['outputs'][1]['type'], release)
if pt['outputs'][1]['address'] == zaddr1:
assert_equal(pt['outputs'][1]['outgoing'], False)
assert_equal(pt['outputs'][1]['memoStr'], my_memo_str)
else:
assert_equal(pt['outputs'][1]['outgoing'], True)
outputs.append({
'address': pt['outputs'][1]['address'],
'value': pt['outputs'][1]['value'],
'valueZat': pt['outputs'][1]['valueZat'],
'memo': pt['outputs'][1]['memo'],
})
assert({
'address': zaddr1,
'value': Decimal('1'),
'valueZat': 100000000,
'memo': my_memo,
} in outputs)
if release != 'sprout':
assert({
'address': zaddrExt,
'value': Decimal('2'),
'valueZat': 200000000,
'memo': no_memo,
} in outputs)
assert_equal(outputs[1]['type'], 'sapling')
assert_equal(outputs[1]['address'], zaddrExt)
assert_equal(outputs[1]['value'], Decimal('2'))
assert_equal(outputs[1]['valueZat'], 200000000)
assert_equal(outputs[1]['output'], 1)
assert_equal(outputs[1]['outgoing'], True)
assert_equal(outputs[1]['memo'], no_memo)
assert 'memoStr' not in outputs[1]
r = self.nodes[1].z_listreceivedbyaddress(zaddr1)
assert_equal(0, len(r), "Should have received no confirmed note")
c = self.nodes[1].z_getnotescount()
assert_equal(0, c[release], "Count of confirmed notes should be 0")
assert_equal(0, c['sapling'], "Count of confirmed notes should be 0")
# No confirmation required, one note should be present
r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0)
@ -112,7 +264,7 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(0, r[0]['blockheight'])
c = self.nodes[1].z_getnotescount(0)
assert_equal(1, c[release], "Count of unconfirmed notes should be 1")
assert_equal(1, c['sapling'], "Count of unconfirmed notes should be 1")
# Confirm transaction (1 ZEC from taddr to zaddr1)
self.generate_and_sync(height+3)
@ -129,7 +281,7 @@ class ListReceivedTest (BitcoinTestFramework):
# Generate some change by sending part of zaddr1 to zaddr2
txidPrev = txid
zaddr2 = self.nodes[1].z_getnewaddress(release)
zaddr2 = self.nodes[1].z_getnewaddress('sapling')
opid = self.nodes[1].z_sendmany(zaddr1,
[{'address': zaddr2, 'amount': 0.6}])
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
@ -142,92 +294,150 @@ class ListReceivedTest (BitcoinTestFramework):
assert_equal(len(pt['spends']), 1)
assert_equal(len(pt['outputs']), 2)
assert_equal(pt['spends'][0]['type'], release)
assert_equal(pt['spends'][0]['type'], 'sapling')
assert_equal(pt['spends'][0]['txidPrev'], txidPrev)
if release == 'sprout':
assert_equal(pt['spends'][0]['js'], 0)
# jsSpend is randomised during transaction creation
assert_equal(pt['spends'][0]['jsPrev'], 0)
assert_equal(pt['spends'][0]['jsOutputPrev'], jsOutputPrev)
else:
assert_equal(pt['spends'][0]['spend'], 0)
assert_equal(pt['spends'][0]['outputPrev'], 0)
assert_equal(pt['spends'][0]['spend'], 0)
assert_equal(pt['spends'][0]['outputPrev'], 0)
assert_equal(pt['spends'][0]['address'], zaddr1)
assert_equal(pt['spends'][0]['value'], Decimal('1.0'))
assert_equal(pt['spends'][0]['valueZat'], 100000000)
# Output orders can be randomized, so we check the output
# positions and contents separately
outputs = []
# Outputs are not returned in a defined order but the amounts are deterministic
outputs = sorted(pt['outputs'], key=lambda x: x['valueZat'])
assert_equal(outputs[0]['type'], 'sapling')
assert_equal(outputs[0]['address'], zaddr1)
assert_equal(outputs[0]['value'], Decimal('0.4') - DEFAULT_FEE)
assert_equal(outputs[0]['valueZat'], 40000000 - DEFAULT_FEE_ZATS)
assert_equal(outputs[0]['output'], 1)
assert_equal(outputs[0]['outgoing'], False)
assert_equal(outputs[0]['memo'], no_memo)
assert 'memoStr' not in outputs[0]
assert_equal(pt['outputs'][0]['type'], release)
if release == 'sapling':
assert_equal(pt['outputs'][0]['output'], 0)
assert_equal(pt['outputs'][0]['outgoing'], False)
outputs.append({
'address': pt['outputs'][0]['address'],
'value': pt['outputs'][0]['value'],
'valueZat': pt['outputs'][0]['valueZat'],
'memo': pt['outputs'][0]['memo'],
})
assert_equal(pt['outputs'][1]['type'], release)
if release == 'sapling':
assert_equal(pt['outputs'][1]['output'], 1)
assert_equal(pt['outputs'][1]['outgoing'], False)
outputs.append({
'address': pt['outputs'][1]['address'],
'value': pt['outputs'][1]['value'],
'valueZat': pt['outputs'][1]['valueZat'],
'memo': pt['outputs'][1]['memo'],
})
assert({
'address': zaddr2,
'value': Decimal('0.6'),
'valueZat': 60000000,
'memo': no_memo,
} in outputs)
assert({
'address': zaddr1,
'value': Decimal('0.4') - DEFAULT_FEE,
'valueZat': 40000000 - DEFAULT_FEE_ZATS,
'memo': no_memo,
} in outputs)
assert_equal(outputs[1]['type'], 'sapling')
assert_equal(outputs[1]['address'], zaddr2)
assert_equal(outputs[1]['value'], Decimal('0.6'))
assert_equal(outputs[1]['valueZat'], 60000000)
assert_equal(outputs[1]['output'], 0)
assert_equal(outputs[1]['outgoing'], False)
assert_equal(outputs[1]['memo'], no_memo)
assert 'memoStr' not in outputs[1]
# zaddr1 should have a note with change
r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0)
r = sorted(r, key = lambda received: received['amount'])
assert_equal(2, len(r), "zaddr1 Should have received 2 notes")
r = sorted(r, key = lambda received: received['amount'])
assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('0.4')-DEFAULT_FEE, r[0]['amount'])
assert_equal(40000000-DEFAULT_FEE_ZATS, r[0]['amountZat'])
assert_true(r[0]['change'], "Note valued at (0.4-"+str(DEFAULT_FEE)+") should be change")
assert_equal(r[0]['change'], True, "Note valued at (0.4-"+str(DEFAULT_FEE)+") should be change")
assert_equal(no_memo, r[0]['memo'])
# The old note still exists (it's immutable), even though it is spent
assert_equal(Decimal('1.0'), r[1]['amount'])
assert_equal(100000000, r[1]['amountZat'])
assert_false(r[1]['change'], "Note valued at 1.0 should not be change")
assert_equal(r[1]['change'], False, "Note valued at 1.0 should not be change")
assert_equal(my_memo, r[1]['memo'])
# zaddr2 should not have change
r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0)
assert_equal(len(r), 1, "zaddr2 Should have received 1 notes")
r = sorted(r, key = lambda received: received['amount'])
assert_equal(1, len(r), "zaddr2 Should have received 1 notes")
assert_equal(txid, r[0]['txid'])
assert_equal(Decimal('0.6'), r[0]['amount'])
assert_equal(60000000, r[0]['amountZat'])
assert_false(r[0]['change'], "Note valued at 0.6 should not be change")
assert_equal(no_memo, r[0]['memo'])
assert_equal(r[0]['txid'], txid)
assert_equal(r[0]['amount'], Decimal('0.6'))
assert_equal(r[0]['amountZat'], 60000000)
assert_equal(r[0]['change'], False, "Note valued at 0.6 should not be change")
assert_equal(r[0]['memo'], no_memo)
assert 0 <= r[0]['outindex'] < 2
c = self.nodes[1].z_getnotescount(0)
assert_equal(3, c[release], "Count of unconfirmed notes should be 3(2 in zaddr1 + 1 in zaddr2)")
assert_equal(c['sapling'], 3, "Count of unconfirmed notes should be 3(2 in zaddr1 + 1 in zaddr2)")
# As part of UA support, a transparent address is now accepted
r = self.nodes[1].z_listreceivedbyaddress(taddr, 0)
assert_equal(len(r), 1)
assert_equal(r[0]['pool'], 'transparent')
assert_equal(r[0]['txid'], txid_taddr)
assert_equal(r[0]['amount'], Decimal('4'))
assert_equal(r[0]['amountZat'], 400000000)
assert_equal(r[0]['confirmations'], 3)
assert 0 <= r[0]['outindex'] < 2
# Test unified address
node = self.nodes[1]
# Create a unified address on one node, try z_listreceivedbyaddress on another node
account = self.nodes[0].z_getnewaccount()['account']
r = self.nodes[0].z_getaddressforaccount(account)
unified_addr = r['unifiedaddress']
# this address isn't in node1's wallet
assert_raises_message(
JSONRPCException,
"From address does not belong to this node",
node.z_listreceivedbyaddress, unified_addr, 0)
# create a UA on node1
r = node.z_getnewaccount()
account = r['account']
r = node.z_getaddressforaccount(account)
unified_addr = r['unifiedaddress']
receivers = node.z_listunifiedreceivers(unified_addr)
assert_equal(len(receivers), 2)
assert 'transparent' in receivers
assert 'sapling' in receivers
assert_raises_message(
JSONRPCException,
"The provided address is a bare receiver from a Unified Address in this wallet.",
node.z_listreceivedbyaddress, receivers['transparent'], 0)
assert_raises_message(
JSONRPCException,
"The provided address is a bare receiver from a Unified Address in this wallet.",
node.z_listreceivedbyaddress, receivers['sapling'], 0)
# Wallet contains no notes
r = node.z_listreceivedbyaddress(unified_addr, 0)
assert_equal(len(r), 0, "unified_addr should have received zero notes")
# Create a note in this UA on node1
opid = node.z_sendmany(zaddr1, [{'address': unified_addr, 'amount': 0.1}])
txid_sapling = wait_and_assert_operationid_status(node, opid)
self.generate_and_sync(height+5)
# Create a UTXO that unified_address's transparent component references, on node1
outputs = {receivers['transparent']: 0.2}
txid_taddr = node.sendmany("", outputs)
r = node.z_listreceivedbyaddress(unified_addr, 0)
assert_equal(len(r), 2, "unified_addr should have received 2 payments")
# The return list order isn't defined, so sort by pool name
r = sorted(r, key=lambda x: x['pool'])
assert_equal(r[0]['pool'], 'sapling')
assert_equal(r[0]['txid'], txid_sapling)
assert_equal(r[0]['amount'], Decimal('0.1'))
assert_equal(r[0]['amountZat'], 10000000)
assert_equal(r[0]['memo'], no_memo)
assert 0 <= r[0]['outindex'] < 2
assert_equal(r[0]['confirmations'], 1)
assert_equal(r[0]['change'], False)
assert_equal(r[0]['blockheight'], height+5)
assert_equal(r[0]['blockindex'], 1)
assert 'blocktime' in r[0]
assert_equal(r[1]['pool'], 'transparent')
assert_equal(r[1]['txid'], txid_taddr)
assert_equal(r[1]['amount'], Decimal('0.2'))
assert_equal(r[1]['amountZat'], 20000000)
assert 0 <= r[1]['outindex'] < 2
assert_equal(r[1]['confirmations'], 0)
assert_equal(r[1]['change'], False)
assert 'memo' not in r[1]
assert_equal(r[1]['blockheight'], 0) # not yet mined
assert_equal(r[1]['blockindex'], -1) # not yet mined
assert 'blocktime' in r[1]
def run_test(self):
self.run_test_release('sprout', 200)
self.run_test_release('sapling', 214)
self.test_received_sprout(200)
self.test_received_sapling(214)
if __name__ == '__main__':
ListReceivedTest().main()

View File

@ -72,10 +72,8 @@ class WalletOverwinterTxTest (BitcoinTestFramework):
# Node 0 shields to Node 2, a coinbase utxo of value 10.0 less default fee
zsendamount = Decimal('10.0') - DEFAULT_FEE
recipients = []
recipients.append({"address":zaddr2, "amount": zsendamount})
myopid = self.nodes[0].z_sendmany(taddr0, recipients)
txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr2, DEFAULT_FEE, 1)
txid_shielded = wait_and_assert_operationid_status(self.nodes[0], result['opid'])
# Skip over the three blocks prior to activation; no transactions can be mined
# in them due to the nearly-expiring restrictions.
@ -143,10 +141,8 @@ class WalletOverwinterTxTest (BitcoinTestFramework):
# Node 0 shields to Node 3, a coinbase utxo of value 10.0 less default fee
zsendamount = Decimal('10.0') - DEFAULT_FEE
recipients = []
recipients.append({"address":zaddr3, "amount": zsendamount})
myopid = self.nodes[0].z_sendmany(taddr0, recipients)
txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
result = self.nodes[0].z_shieldcoinbase(taddr0, zaddr3, DEFAULT_FEE, 1)
txid_shielded = wait_and_assert_operationid_status(self.nodes[0], result['opid'])
# Mine the first Blossom block
self.sync_all()

View File

@ -36,7 +36,7 @@ class WalletPersistenceTest (BitcoinTestFramework):
# Verify Sapling address is persisted in wallet
sapling_addr = self.nodes[0].z_getnewaddress('sapling')
# Make sure the node has the addresss
# Make sure the node has the address
addresses = self.nodes[0].z_listaddresses()
assert_true(sapling_addr in addresses, "Should contain address before restart")

View File

@ -169,7 +169,7 @@ class WalletSaplingTest(BitcoinTestFramework):
)
raise AssertionError("Should have thrown an exception")
except JSONRPCException as e:
assert_equal("Cannot send to both Sprout and Sapling addresses using z_sendmany", e.error['message'])
assert_equal("Sending funds into the Sprout pool is not supported by z_sendmany", e.error['message'])
if __name__ == '__main__':
WalletSaplingTest().main()

View File

@ -21,14 +21,6 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
node3taddr1 = self.nodes[3].getnewaddress()
node3taddr2 = self.nodes[3].getnewaddress()
# We should not be able to spend multiple coinbase UTXOs at once.
wait_and_assert_operationid_status(
self.nodes[3],
self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 100}]),
'failed',
'Could not find any non-coinbase UTXOs to spend. Coinbase UTXOs can only be sent to a single zaddr recipient from a single taddr.',
)
# Prepare some non-coinbase UTXOs
wait_and_assert_operationid_status(
self.nodes[3],

View File

@ -7,21 +7,24 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.authproxy import JSONRPCException
from test_framework.util import assert_equal, initialize_chain_clean, \
start_node, connect_nodes_bi, sync_blocks, sync_mempools, \
wait_and_assert_operationid_status, get_coinbase_address, DEFAULT_FEE
wait_and_assert_operationid_status, get_coinbase_address, DEFAULT_FEE, \
NU5_BRANCH_ID, nuparams
from decimal import Decimal
class WalletShieldCoinbaseTest (BitcoinTestFramework):
def __init__(self, addr_type):
super(WalletShieldCoinbaseTest, self).__init__()
self.addr_type = addr_type
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, 4)
def setup_network(self, split=False):
args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe']
args = [
'-regtestprotectcoinbase',
'-debug=zrpcunsafe',
'-experimentalfeatures',
'-orchardwallet',
nuparams(NU5_BRANCH_ID, self.nu5_activation),
]
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.nodes.append(start_node(1, self.options.tmpdir, args))
@ -52,11 +55,13 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
assert_equal(self.nodes[1].getbalance(), 10)
assert_equal(self.nodes[2].getbalance(), 30)
# create one zaddr that is the target of all shielding
myzaddr = self.test_init_zaddr(self.nodes[0])
do_not_shield_taddr = get_coinbase_address(self.nodes[0], 1)
# Prepare to send taddr->zaddr
mytaddr = get_coinbase_address(self.nodes[0], 4)
myzaddr = self.nodes[0].z_getnewaddress(self.addr_type)
# Shielding will fail when trying to spend from watch-only address
self.nodes[2].importaddress(mytaddr)
@ -111,7 +116,7 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
# Confirm balances and that do_not_shield_taddr containing funds of 10 was left alone
assert_equal(self.nodes[0].getbalance(), 10)
assert_equal(self.nodes[0].z_getbalance(do_not_shield_taddr), Decimal('10.0'))
assert_equal(self.nodes[0].z_getbalance(myzaddr), Decimal('40.0') - DEFAULT_FEE)
self.test_check_balance_zaddr(self.nodes[0], Decimal('40.0') - DEFAULT_FEE)
assert_equal(self.nodes[1].getbalance(), 20)
assert_equal(self.nodes[2].getbalance(), 30)
@ -123,7 +128,7 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
self.sync_all()
assert_equal(self.nodes[0].getbalance(), 10)
assert_equal(self.nodes[0].z_getbalance(myzaddr), Decimal('70.0') - DEFAULT_FEE)
self.test_check_balance_zaddr(self.nodes[0], Decimal('70.0') - DEFAULT_FEE)
assert_equal(self.nodes[1].getbalance(), 30)
assert_equal(self.nodes[2].getbalance(), 0)
@ -151,7 +156,7 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
assert_equal(result["remainingUTXOs"], Decimal('0'))
opid2 = result['opid']
# wait for both aysnc operations to complete
# wait for both async operations to complete
wait_and_assert_operationid_status(self.nodes[0], opid1)
wait_and_assert_operationid_status(self.nodes[0], opid2)
@ -185,3 +190,6 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
sync_mempools(self.nodes[:2])
self.nodes[1].generate(1)
self.sync_all()
# Note, no "if __name__ == '__main__" and call the test here; it's called from
# pool-specific derived classes in wallet_shieldcoinbase_*.py

View File

@ -1,10 +1,22 @@
#!/usr/bin/env python3
from wallet_shieldcoinbase import WalletShieldCoinbaseTest
from wallet_shieldcoinbase import WalletShieldCoinbaseTest
from test_framework.util import assert_equal
class WalletShieldCoinbaseSapling(WalletShieldCoinbaseTest):
def __init__(self):
super(WalletShieldCoinbaseSapling, self).__init__('sapling')
super(WalletShieldCoinbaseSapling, self).__init__()
self.nu5_activation = 99999
def test_init_zaddr(self, node):
self.addr = node.z_getnewaddress('sapling')
return self.addr
def test_check_balance_zaddr(self, node, expected):
balance = node.z_getbalance(self.addr)
assert_equal(balance, expected)
if __name__ == '__main__':
print("Test shielding to a sapling address")
WalletShieldCoinbaseSapling().main()

View File

@ -1,10 +1,22 @@
#!/usr/bin/env python3
from wallet_shieldcoinbase import WalletShieldCoinbaseTest
from wallet_shieldcoinbase import WalletShieldCoinbaseTest
from test_framework.util import assert_equal
class WalletShieldCoinbaseSprout(WalletShieldCoinbaseTest):
def __init__(self):
super(WalletShieldCoinbaseSprout, self).__init__('sprout')
super(WalletShieldCoinbaseSprout, self).__init__()
self.nu5_activation = 99999
def test_init_zaddr(self, node):
self.addr = node.z_getnewaddress('sprout')
return self.addr
def test_check_balance_zaddr(self, node, expected):
balance = node.z_getbalance(self.addr)
assert_equal(balance, expected)
if __name__ == '__main__':
print("Test shielding to a sapling address")
WalletShieldCoinbaseSprout().main()

View File

@ -0,0 +1,41 @@
#!/usr/bin/env python3
from wallet_shieldcoinbase import WalletShieldCoinbaseTest
from test_framework.util import assert_equal
from test_framework.mininode import COIN
class WalletShieldCoinbaseUANU5(WalletShieldCoinbaseTest):
def __init__(self):
super(WalletShieldCoinbaseUANU5, self).__init__()
self.account = None
# activate after initial setup, before the first z_shieldcoinbase RPC
self.nu5_activation = 109
def test_init_zaddr(self, node):
# this function may be called no more than once
assert(self.account is None)
self.account = node.z_getnewaccount()['account']
self.addr = node.z_getaddressforaccount(self.account)['unifiedaddress']
return self.addr
def test_check_balance_zaddr(self, node, expected):
balances = node.z_getbalanceforaccount(self.account)
assert('transparent' not in balances['pools'])
assert('sprout' not in balances['pools'])
# assert('sapling' not in balances['pools'])
assert_equal(balances['pools']['sapling']['valueZat'], expected * COIN)
# assert_equal(balances['pools']['orchard']['valueZat'], expected * COIN)
# While we're at it, check that z_listunspent only shows outputs with
# the Unified Address (not the Orchard receiver), and of the expected
# type.
unspent = node.z_listunspent(1, 999999, False, [self.addr])
assert_equal(
[{'type': 'sapling', 'address': self.addr} for _ in unspent],
[{'type': x['type'], 'address': x['address']} for x in unspent],
)
if __name__ == '__main__':
print("Test shielding to a unified address with NU5 activated")
WalletShieldCoinbaseUANU5().main()

View File

@ -0,0 +1,39 @@
#!/usr/bin/env python3
from wallet_shieldcoinbase import WalletShieldCoinbaseTest
from test_framework.util import assert_equal
from test_framework.mininode import COIN
class WalletShieldCoinbaseUASapling(WalletShieldCoinbaseTest):
def __init__(self):
super(WalletShieldCoinbaseUASapling, self).__init__()
self.account = None
self.nu5_activation = 99999
def test_init_zaddr(self, node):
# this function may be called no more than once
assert(self.account is None)
self.account = node.z_getnewaccount()['account']
self.addr = node.z_getaddressforaccount(self.account)['unifiedaddress']
return self.addr
def test_check_balance_zaddr(self, node, expected):
balances = node.z_getbalanceforaccount(self.account)
assert('transparent' not in balances['pools'])
assert('sprout' not in balances['pools'])
assert_equal(balances['pools']['sapling']['valueZat'], expected * COIN)
assert('orchard' not in balances['pools'])
# While we're at it, check that z_listunspent only shows outputs with
# the Unified Address (not the Sapling receiver), and of the expected
# type.
unspent = node.z_listunspent(1, 999999, False, [self.addr])
assert_equal(
[{'type': 'sapling', 'address': self.addr} for _ in unspent],
[{'type': x['type'], 'address': x['address']} for x in unspent],
)
if __name__ == '__main__':
print("Test shielding to a unified address with sapling activated (but not NU5)")
WalletShieldCoinbaseUASapling().main()

View File

@ -61,10 +61,10 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), 0)
assert_equal(self.nodes[3].getbalance(), 0)
check_value_pool(self.nodes[0], 'sprout', 0)
check_value_pool(self.nodes[1], 'sprout', 0)
check_value_pool(self.nodes[2], 'sprout', 0)
check_value_pool(self.nodes[3], 'sprout', 0)
check_value_pool(self.nodes[0], 'sapling', 0)
check_value_pool(self.nodes[1], 'sapling', 0)
check_value_pool(self.nodes[2], 'sapling', 0)
check_value_pool(self.nodes[3], 'sapling', 0)
# Send will fail because we are enforcing the consensus rule that
# coinbase utxos can only be sent to a zaddr.
@ -77,24 +77,31 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
# Prepare to send taddr->zaddr
mytaddr = get_coinbase_address(self.nodes[0])
myzaddr = self.nodes[0].z_getnewaddress('sprout')
myzaddr = self.nodes[0].z_getnewaddress('sapling')
# Node 3 will test that watch only address utxos are not selected
self.nodes[3].importaddress(mytaddr)
recipients= [{"address":myzaddr, "amount": Decimal('1')}]
myopid = self.nodes[3].z_sendmany(mytaddr, recipients)
try:
myopid = self.nodes[3].z_sendmany(mytaddr, recipients)
except JSONRPCException as e:
errorString = e.error['message']
assert_equal("Invalid from address, no payment source found for address.", errorString);
wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient transparent funds, no UTXOs found for taddr from address.", 10)
# This send will fail because our wallet does not allow any change when shielding a coinbase utxo,
# as it's currently not possible to specify a change address in z_sendmany.
# This send will fail because our consensus does not allow transparent change when
# shielding a coinbase utxo.
# TODO: After upgrading to unified address support, change will be sent to the most
# recent shielded spend authority corresponding to the account of the source address
# and this send will succeed, causing this test to fail.
recipients = []
recipients.append({"address":myzaddr, "amount":Decimal('1.23456789')})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
error_result = wait_and_assert_operationid_status_result(self.nodes[0], myopid, "failed", ("Change 8.76542211 not allowed. "
"When shielding coinbase funds, the wallet does not allow any change "
"as there is currently no way to specify a change address in z_sendmany."), 10)
error_result = wait_and_assert_operationid_status_result(
self.nodes[0],
myopid, "failed",
"When shielding coinbase funds, the wallet does not allow any change. The proposed transaction would result in 8.76542211 in change.",
10)
# Test that the returned status object contains a params field with the operation's input parameters
assert_equal(error_result["method"], "z_sendmany")
@ -122,6 +129,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
assert(len(results) == 0)
results = self.nodes[0].z_listunspent(0) # set minconf to zero
assert(len(results) == 1)
assert_equal(results[0]["type"], "sapling")
assert_equal(results[0]["address"], myzaddr)
assert_equal(results[0]["amount"], shieldvalue)
assert_equal(results[0]["confirmations"], 0)
@ -133,6 +141,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
# Verify that z_listunspent returns one note which has been confirmed
results = self.nodes[0].z_listunspent()
assert(len(results) == 1)
assert_equal(results[0]["type"], "sapling")
assert_equal(results[0]["address"], myzaddr)
assert_equal(results[0]["amount"], shieldvalue)
assert_equal(results[0]["confirmations"], 1)
@ -141,6 +150,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
# Verify that z_listunspent returns note for watchonly address on node 3.
results = self.nodes[3].z_listunspent(1, 999, True)
assert(len(results) == 1)
assert_equal(results[0]["type"], "sapling")
assert_equal(results[0]["address"], myzaddr)
assert_equal(results[0]["amount"], shieldvalue)
assert_equal(results[0]["confirmations"], 1)
@ -151,7 +161,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
results = self.nodes[1].z_listunspent(1, 999, False, [myzaddr])
except JSONRPCException as e:
errorString = e.error['message']
assert_equal("Invalid parameter, spending key for address does not belong to wallet" in errorString, True)
assert_equal("Invalid parameter, spending key for an address does not belong to the wallet.", errorString)
# Verify that debug=zrpcunsafe logs params, and that full txid is associated with opid
initialized_line = check_node_log(self, 0, myopid + ": z_sendmany initialized", False)
@ -165,8 +175,8 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
assert_equal(Decimal(resp["total"]), Decimal('40.0') - DEFAULT_FEE)
# The Sprout value pool should reflect the send
sproutvalue = shieldvalue
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
saplingvalue = shieldvalue
check_value_pool(self.nodes[0], 'sapling', saplingvalue)
# A custom fee of 0 is okay. Here the node will send the note value back to itself.
recipients = []
@ -181,8 +191,8 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
assert_equal(Decimal(resp["private"]), Decimal('20.0') - DEFAULT_FEE)
assert_equal(Decimal(resp["total"]), Decimal('40.0') - DEFAULT_FEE)
# The Sprout value pool should be unchanged
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
# The Sapling value pool should be unchanged
check_value_pool(self.nodes[0], 'sapling', saplingvalue)
# convert note to transparent funds
unshieldvalue = Decimal('10.0')
@ -201,12 +211,12 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
self.sync_all()
# check balances
sproutvalue -= unshieldvalue + DEFAULT_FEE
saplingvalue -= unshieldvalue + DEFAULT_FEE
resp = self.nodes[0].z_gettotalbalance()
assert_equal(Decimal(resp["transparent"]), Decimal('30.0'))
assert_equal(Decimal(resp["private"]), Decimal('10.0') - 2*DEFAULT_FEE)
assert_equal(Decimal(resp["total"]), Decimal('40.0') - 2*DEFAULT_FEE)
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
check_value_pool(self.nodes[0], 'sapling', saplingvalue)
# z_sendmany will return an error if there is transparent change output considered dust.
# UTXO selection in z_sendmany sorts in ascending order, so smallest utxos are consumed first.
@ -215,7 +225,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
amount = Decimal('10.0') - DEFAULT_FEE - Decimal('0.00000001') # this leaves change at 1 zatoshi less than dust threshold
recipients.append({"address":self.nodes[0].getnewaddress(), "amount":amount })
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient transparent funds, have 10.00, need 0.00000053 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000054)")
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 10.00, need 0.00000053 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000054)")
# Send will fail because send amount is too big, even when including coinbase utxos
errorString = ""
@ -229,9 +239,9 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
recipients = []
recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')})
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient transparent funds, have 10.00, need 10000.00001")
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 10.00, need 10000.00001; note that coinbase outputs will not be selected if you specify ANY_TADDR or if any transparent recipients are included.")
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient shielded funds, have 9.99998, need 10000.00001")
wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Insufficient funds: have 9.99998, need 10000.00001; note that coinbase outputs will not be selected if you specify ANY_TADDR or if any transparent recipients are included.")
# Send will fail because of insufficient funds unless sender uses coinbase utxos
try:
@ -282,9 +292,9 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
# check balance
node2balance = amount_per_recipient * num_t_recipients
sproutvalue -= node2balance + DEFAULT_FEE
saplingvalue -= node2balance + DEFAULT_FEE
assert_equal(self.nodes[2].getbalance(), node2balance)
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
check_value_pool(self.nodes[0], 'sapling', saplingvalue)
# Send will fail because fee is negative
try:
@ -330,7 +340,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
custom_fee = Decimal('0.00012345')
zbalance = self.nodes[0].z_getbalance(myzaddr)
for i in range(0,num_recipients):
newzaddr = self.nodes[2].z_getnewaddress('sprout')
newzaddr = self.nodes[2].z_getnewaddress('sapling')
recipients.append({"address":newzaddr, "amount":amount_per_recipient})
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, custom_fee)
wait_and_assert_operationid_status(self.nodes[0], myopid)
@ -348,8 +358,8 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
resp = self.nodes[0].z_getbalance(myzaddr)
assert_equal(Decimal(resp), zbalance - custom_fee - send_amount)
sproutvalue -= custom_fee
check_value_pool(self.nodes[0], 'sprout', sproutvalue)
saplingvalue -= custom_fee
check_value_pool(self.nodes[0], 'sapling', saplingvalue)
notes = self.nodes[0].z_listunspent(1, 99999, False, [myzaddr])
sum_of_notes = sum([note["amount"] for note in notes])

View File

@ -7,18 +7,37 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_greater_than, connect_nodes_bi, \
DEFAULT_FEE, start_nodes, wait_and_assert_operationid_status
from test_framework.authproxy import JSONRPCException
from test_framework.mininode import COIN
from decimal import Decimal
# Test wallet address behaviour across network upgrades
class WalletZSendmanyTest(BitcoinTestFramework):
def setup_network(self, split=False):
self.nodes = start_nodes(3, self.options.tmpdir)
self.nodes = start_nodes(3, self.options.tmpdir, [[
'-experimentalfeatures',
'-orchardwallet',
]] * self.num_nodes)
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
self.is_network_split=False
self.sync_all()
# Check we only have balances in the expected pools.
# Remember that empty pools are omitted from the output.
def _check_balance_for_rpc(self, rpcmethod, node, account, expected, minconf):
rpc = getattr(self.nodes[node], rpcmethod)
actual = rpc(account) if minconf is None else rpc(account, minconf)
assert_equal(set(expected), set(actual['pools']))
for pool in expected:
assert_equal(expected[pool] * COIN, actual['pools'][pool]['valueZat'])
assert_equal(actual['minimum_confirmations'], 1 if minconf is None else minconf)
def check_balance(self, node, account, address, expected, minconf=None):
self._check_balance_for_rpc('z_getbalanceforaccount', node, account, expected, minconf)
fvk = self.nodes[node].z_exportviewingkey(address)
self._check_balance_for_rpc('z_getbalanceforviewingkey', node, fvk, expected, minconf)
def run_test(self):
# z_sendmany is expected to fail if tx size breaks limit
myzaddr = self.nodes[0].z_getnewaddress()
@ -65,8 +84,8 @@ class WalletZSendmanyTest(BitcoinTestFramework):
# send node 2 taddr to zaddr
recipients = []
recipients.append({"address":myzaddr, "amount":7})
mytxid = wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(mytaddr, recipients))
opid = self.nodes[2].z_sendmany(mytaddr, recipients)
mytxid = wait_and_assert_operationid_status(self.nodes[2], opid)
self.sync_all()
@ -87,13 +106,14 @@ class WalletZSendmanyTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance("*"), node2utxobalance)
# check zaddr balance with z_getbalance
assert_equal(self.nodes[2].z_getbalance(myzaddr), zsendmanynotevalue)
zbalance = zsendmanynotevalue
assert_equal(self.nodes[2].z_getbalance(myzaddr), zbalance)
# check via z_gettotalbalance
resp = self.nodes[2].z_gettotalbalance()
assert_equal(Decimal(resp["transparent"]), node2utxobalance)
assert_equal(Decimal(resp["private"]), zsendmanynotevalue)
assert_equal(Decimal(resp["total"]), node2utxobalance + zsendmanynotevalue)
assert_equal(Decimal(resp["private"]), zbalance)
assert_equal(Decimal(resp["total"]), node2utxobalance + zbalance)
# check confirmed shielded balance with getwalletinfo
wallet_info = self.nodes[2].getwalletinfo()
@ -118,7 +138,9 @@ class WalletZSendmanyTest(BitcoinTestFramework):
recipients.append({"address":self.nodes[0].getnewaddress(), "amount":1})
recipients.append({"address":self.nodes[2].getnewaddress(), "amount":1.0})
wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(myzaddr, recipients))
opid = self.nodes[2].z_sendmany(myzaddr, recipients)
wait_and_assert_operationid_status(self.nodes[2], opid)
zbalance -= Decimal('2.0') + zsendmanyfee
self.sync_all()
self.nodes[2].generate(1)
@ -131,5 +153,77 @@ class WalletZSendmanyTest(BitcoinTestFramework):
assert_equal(Decimal(self.nodes[2].getbalance()), node2balance)
assert_equal(Decimal(self.nodes[2].getbalance("*")), node2balance)
# Get a new unified account on node 2 & generate a UA
n0account0 = self.nodes[0].z_getnewaccount()['account']
n0ua0 = self.nodes[0].z_getaddressforaccount(n0account0)['unifiedaddress']
# Change went to a fresh address, so use `ANY_TADDR` which
# should hold the rest of our transparent funds.
recipients = []
recipients.append({"address":n0ua0, "amount":10})
opid = self.nodes[2].z_sendmany('ANY_TADDR', recipients, 1, 0)
wait_and_assert_operationid_status(self.nodes[2], opid)
self.nodes[2].generate(1)
self.sync_all()
node2balance -= Decimal('10.0')
node0balance += Decimal('10.0')
assert_equal(Decimal(self.nodes[2].getbalance()), node2balance)
assert_equal(Decimal(self.nodes[0].getbalance()), node0balance)
self.check_balance(0, 0, n0ua0, {'sapling': 10})
# Send some funds to a specific legacy taddr that we can spend from
recipients = []
recipients.append({"address":mytaddr, "amount":5})
opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0)
wait_and_assert_operationid_status(self.nodes[0], opid)
self.nodes[0].generate(1)
self.sync_all()
node2balance += Decimal('5.0')
self.check_balance(0, 0, n0ua0, {'sapling': 5})
assert_equal(Decimal(self.nodes[2].getbalance()), node2balance)
# Send some funds to a legacy sapling address that we can spend from
recipients = []
recipients.append({"address":myzaddr, "amount":3})
opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0)
wait_and_assert_operationid_status(self.nodes[0], opid)
self.nodes[0].generate(1)
self.sync_all()
zbalance += Decimal('3.0')
self.check_balance(0, 0, n0ua0, {'sapling': 2})
assert_equal(Decimal(self.nodes[2].z_getbalance(myzaddr)), zbalance)
# Send funds back from the legacy taddr to the UA
recipients = []
recipients.append({"address":n0ua0, "amount":4})
opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, 0)
wait_and_assert_operationid_status(self.nodes[2], opid)
self.nodes[2].generate(1)
self.sync_all()
node2balance -= Decimal('4.0')
self.check_balance(0, 0, n0ua0, {'sapling': 6})
assert_equal(Decimal(self.nodes[2].getbalance()), node2balance)
# Send funds back from the legacy zaddr to the UA
recipients = []
recipients.append({"address":n0ua0, "amount":2})
opid = self.nodes[2].z_sendmany(myzaddr, recipients, 1, 0)
wait_and_assert_operationid_status(self.nodes[2], opid)
self.nodes[2].generate(1)
self.sync_all()
zbalance -= Decimal('2.0')
self.check_balance(0, 0, n0ua0, {'sapling': 8})
assert_equal(Decimal(self.nodes[2].z_getbalance(myzaddr)), zbalance)
if __name__ == '__main__':
WalletZSendmanyTest().main()

View File

@ -96,10 +96,10 @@ class WalletBackupTest(BitcoinTestFramework):
self.sync_all()
# As above, this mirrors the original bash test.
def start_three(self):
self.nodes[0] = start_node(0, self.options.tmpdir)
self.nodes[1] = start_node(1, self.options.tmpdir)
self.nodes[2] = start_node(2, self.options.tmpdir)
def start_three(self, extra_args=None):
self.nodes[0] = start_node(0, self.options.tmpdir, extra_args)
self.nodes[1] = start_node(1, self.options.tmpdir, extra_args)
self.nodes[2] = start_node(2, self.options.tmpdir, extra_args)
connect_nodes(self.nodes[0], 3)
connect_nodes(self.nodes[1], 3)
connect_nodes(self.nodes[2], 3)
@ -191,6 +191,29 @@ class WalletBackupTest(BitcoinTestFramework):
self.start_three()
sync_blocks(self.nodes)
# We made extra transactions that involved addresses generated after the
# backups were taken, and external addresses do not use the keypool, so
# the balances shouldn't line up.
balance0backup = self.nodes[0].getbalance()
balance1backup = self.nodes[1].getbalance()
balance2backup = self.nodes[2].getbalance()
assert(balance0backup != balance0)
assert(balance1backup != balance1)
assert(balance2backup != balance2)
# However, because addresses are derived deterministically, we can
# recover the balances by generating the extra addresses and then
# rescanning.
for i in range(5):
self.nodes[0].getnewaddress()
self.nodes[1].getnewaddress()
self.nodes[2].getnewaddress()
logging.info("Re-starting nodes with -rescan")
self.stop_three()
self.start_three(['-rescan'])
sync_blocks(self.nodes)
assert_equal(self.nodes[0].getbalance(), balance0)
assert_equal(self.nodes[1].getbalance(), balance1)
assert_equal(self.nodes[2].getbalance(), balance2)
@ -215,9 +238,9 @@ class WalletBackupTest(BitcoinTestFramework):
sync_blocks(self.nodes)
assert_equal(self.nodes[0].getbalance(), balance0)
assert_equal(self.nodes[1].getbalance(), balance1)
assert_equal(self.nodes[2].getbalance(), balance2)
assert_equal(self.nodes[0].getbalance(), balance0backup)
assert_equal(self.nodes[1].getbalance(), balance1backup)
assert_equal(self.nodes[2].getbalance(), balance2backup)
if __name__ == '__main__':

View File

@ -75,7 +75,7 @@ class ZapWalletTXesTest (BitcoinTestFramework):
print(e)
aException = True
assert_equal(aException, True) # there must be a expection because the unconfirmed wallettx0 must be gone by now
assert_equal(aException, True) # there must be an exception because the unconfirmed wallet tx0 must be gone by now
tx0 = self.nodes[0].gettransaction(txid0)
assert_equal(tx0['txid'], txid0) # tx0 (confirmed) must still be available because it was confirmed

View File

@ -39,7 +39,7 @@
# Name : checksec.sh
# Version : 1.7.0
# Author : Brian Davis
# Date : Feburary 2014
# Date : February 2014
# Download: https://github.com/slimm609/checksec.sh
#
# --- Modified Version ---
@ -298,9 +298,9 @@ echo_message() {
# check selinux status
getsestatus() {
local status
${debug} && echo -e "\n***fuction getsestatus"
${debug} && echo -e "\n***function getsestatus"
if (command_exists getenforce); then
${debug} && echo "***fuction getsestatus->getenforce"
${debug} && echo "***function getsestatus->getenforce"
sestatus=$(getenforce)
if [[ "${sestatus}" == "Disabled" ]]; then
status=0
@ -310,7 +310,7 @@ getsestatus() {
status=2
fi
elif (command_exists sestatus); then
${debug} && echo "***fuction getsestatus->sestatus"
${debug} && echo "***function getsestatus->sestatus"
sestatus=$(sestatus | grep "SELinux status" | awk '{ print $3}')
if [[ "${sestatus}" == "disabled" ]]; then
status=0
@ -328,7 +328,7 @@ return ${status}
# check if directory exists
dir_exists () {
${debug} && echo "fuction dir_exists"
${debug} && echo "function dir_exists"
if [[ -d "${1}" ]] ; then
return 0
else
@ -842,7 +842,7 @@ kernelcheck() {
fi
echo_message " Kernel heap randomization: " "" "" ""
# NOTE: y means it turns off kernel heap randomization for backwards compatability (libc5)
# NOTE: y means it turns off kernel heap randomization for backwards compatibility (libc5)
if ${kconfig} | grep -qi 'CONFIG_COMPAT_BRK=y'; then
echo_message "\033[31mDisabled\033[m\n" "Disabled," " kernel_heap_randomization='no'" ', "kernel_heap_randomization":"no"'
else
@ -1123,7 +1123,7 @@ kernelcheck() {
sestatus=$?
if [[ ${sestatus} == 0 ]]; then
echo_message "\033[31mDisabled\033[m\n" "Disabled,," " <selinux enabled='no'" '"selinux":{ "enabled":"no"'
echo_message "\n SELinux infomation available here: \n" "" "" ""
echo_message "\n SELinux information available here: \n" "" "" ""
echo_message " https://selinuxproject.org/\n" "" "" ""
elif [[ ${sestatus} == 1 ]]; then
echo_message "\033[33mPermissive\033[m\n" "Permissive," " <selinux enabled='yes' mode='permissive'" '"selinux":{ "enabled":"yes", "mode":"permissive"'
@ -1132,7 +1132,7 @@ kernelcheck() {
fi
else
echo_message "\033[31mNo SELinux\033[m\n" "Disabled,," " <selinux enabled='no'" '"selinux":{ "enabled":"no"'
echo_message "\n SELinux infomation available here: \n" "" "" ""
echo_message "\n SELinux information available here: \n" "" "" ""
echo_message " https://selinuxproject.org/\n" "" "" ""
fi

View File

@ -5,23 +5,23 @@
#
# Ccache 4.0 requires adding CMake to the depends system.
native_ccache 4.0 2021-11-01
native_ccache 4.1 2021-11-01
native_ccache 4.2 2021-11-01
native_ccache 4.2.1 2021-11-01
native_ccache 4.3 2021-11-01
native_ccache 4.4 2021-11-01
native_ccache 4.4.1 2021-11-01
native_ccache 4.4.2 2021-11-01
native_ccache 4.0 2022-02-01
native_ccache 4.1 2022-02-01
native_ccache 4.2 2022-02-01
native_ccache 4.2.1 2022-02-01
native_ccache 4.3 2022-02-01
native_ccache 4.4 2022-02-01
native_ccache 4.4.1 2022-02-01
native_ccache 4.4.2 2022-02-01
native_ccache 4.5 2022-02-01
native_ccache 4.5.1 2022-02-01
# Clang is currently pinned to LLVM 12
native_clang 13.0.0 2021-11-01
libcxx 13.0.0 2021-11-01
# Clang is currently pinned to LLVM 13
# Rust is currently pinned to 1.55.0
# Rust is currently pinned to 1.56.1
bdb 18.1.40 2022-02-01
# Google Test 1.10.0 requires adding CMake to the depends system.
googletest 1.10.0 2021-11-01
googletest 1.11.0 2021-11-01
googletest 1.10.0 2022-02-01
googletest 1.11.0 2022-02-01

View File

@ -172,7 +172,7 @@ def wait_for_balance(zcash, zaddr, expected=None):
ttl = 300
def wait_and_check_balance(results, case, zcash, addr, expected):
#Wait for aysnc call to finish and persist completely to caller
#Wait for async call to finish and persist completely to caller
time.sleep(5)
balance = wait_for_balance(zcash, addr, expected)
if balance != expected and results is not None and len(case) > 0:

View File

@ -1 +1 @@
1.55.0
1.56.1

View File

@ -39,7 +39,14 @@ if ENABLE_WALLET
LIBBITCOIN_WALLET=libbitcoin_wallet.a
endif
RUST_ENV_VARS = RUSTC="$(RUSTC)" TERM=dumb
# We depend on the secp256k1 crate for some logic on the Rust side of the FFI. This crate
# is a wrapper around libsecp256k1, which we already vendor in our code; the crate vendors
# its own copy with non-colliding symbols. To ensure that we only use a single version of
# libsecp256k1, we disable symbol renaming in the secp256k1-sys crate so it links to the
# same library as the C++ code.
# - Note that this does not prevent the secp256k1-sys vendored code from being built; this
# requires https://github.com/rust-bitcoin/rust-secp256k1/issues/380 to be addressed.
RUST_ENV_VARS = RUSTC="$(RUSTC)" TERM=dumb RUSTFLAGS="--cfg=rust_secp_no_symbol_renaming"
RUST_BUILD_OPTS = --lib --release --target $(RUST_TARGET)
rust_verbose = $(rust_verbose_@AM_V@)
@ -107,8 +114,12 @@ LIBZCASH_H = \
zcash/IncrementalMerkleTree.hpp \
zcash/NoteEncryption.hpp \
zcash/Address.hpp \
zcash/address/transparent.h \
zcash/address/mnemonic.h \
zcash/address/orchard.h \
zcash/address/sapling.hpp \
zcash/address/sprout.hpp \
zcash/address/unified.h \
zcash/address/zip32.h \
zcash/History.hpp \
zcash/JoinSplit.hpp \
@ -393,6 +404,7 @@ libbitcoin_common_a_SOURCES = \
netbase.cpp \
primitives/block.cpp \
primitives/transaction.cpp \
primitives/tx_version_info.cpp \
proof_verifier.cpp \
protocol.cpp \
pubkey.cpp \
@ -502,6 +514,7 @@ zcash_cli_LDADD = \
$(LIBZCASH) \
$(LIBRUSTZCASH) \
$(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1) \
$(LIBZCASH_LIBS)
#
@ -534,8 +547,12 @@ libzcash_a_SOURCES = \
zcash/IncrementalMerkleTree.cpp \
zcash/NoteEncryption.cpp \
zcash/Address.cpp \
zcash/address/transparent.cpp \
zcash/address/mnemonic.cpp \
zcash/address/orchard.cpp \
zcash/address/sapling.cpp \
zcash/address/sprout.cpp \
zcash/address/unified.cpp \
zcash/address/zip32.cpp \
zcash/History.cpp \
zcash/JoinSplit.cpp \
@ -558,6 +575,7 @@ libzcash_script_la_SOURCES = \
crypto/sha512.cpp \
hash.cpp \
primitives/transaction.cpp \
primitives/tx_version_info.cpp \
pubkey.cpp \
script/zcash_script.cpp \
script/interpreter.cpp \

View File

@ -21,7 +21,8 @@ zcash_gtest_SOURCES = \
# depend on global state (see #1539)
if ENABLE_WALLET
zcash_gtest_SOURCES += \
wallet/gtest/test_wallet_zkeys.cpp
wallet/gtest/test_wallet_zkeys.cpp \
wallet/gtest/test_orchard_zkeys.cpp
endif
zcash_gtest_SOURCES += \
test/data/merkle_roots_orchard.h \

View File

@ -44,6 +44,7 @@ JSON_TEST_FILES = \
test/data/merkle_commitments_sapling.json \
test/data/sapling_key_components.json \
test/data/unified_addrs.json \
test/data/unified_full_viewing_keys.json \
test/data/zip0244.json
RAW_TEST_FILES = test/data/alertTests.raw

View File

@ -6,7 +6,7 @@
#if defined(__i386__) || defined(__x86_64__)
/* These architectures support quering the cycle counter
/* These architectures support querying the cycle counter
* from user space, no need for any syscall overhead.
*/
void perf_init(void) { }

View File

@ -25,8 +25,7 @@ static void ECDSA(benchmark::State& state)
mtx.nVersion = SAPLING_TX_VERSION;
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
CKey key;
key.MakeNewKey(false);
CKey key = CKey::TestOnlyRandomKey(false);
CBasicKeyStore keystore;
keystore.AddKeyPubKey(key, key.GetPubKey());
CKeyID hash = key.GetPubKey().GetID();

View File

@ -52,7 +52,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
* transaction cannot be spent since it did not originally exist in the
* database (and is in any case of zero value).
*
* >>> from pyblake2 import blake2s
* >>> from hashlib import blake2s
* >>> 'Zcash' + blake2s(b'The Economist 2016-10-29 Known unknown: Another crypto-currency is born. BTC#436254 0000000000000000044f321997f336d2908cf8c8d6893e88dbf067e2d949487d ETH#2521903 483039a6b6bd8bd05f0584f9a078d075e454925eb71c1f13eaff59b405a721bb DJIA close on 27 Oct 2016: 18,169.68').hexdigest()
*
* CBlock(hash=00040fe8, ver=4, hashPrevBlock=00000000000000, hashMerkleRoot=c4eaa5, nTime=1477641360, nBits=1f07ffff, nNonce=4695, vtx=1)
@ -86,7 +86,7 @@ public:
CMainParams() {
keyConstants.strNetworkID = "main";
strCurrencyUnits = "ZEC";
bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md
keyConstants.bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md
consensus.fCoinbaseMustBeShielded = true;
consensus.nSubsidySlowStartInterval = 20000;
consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL;
@ -370,7 +370,7 @@ public:
CTestNetParams() {
keyConstants.strNetworkID = "test";
strCurrencyUnits = "TAZ";
bip44CoinType = 1;
keyConstants.bip44CoinType = 1;
consensus.fCoinbaseMustBeShielded = true;
consensus.nSubsidySlowStartInterval = 20000;
consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL;
@ -621,7 +621,7 @@ public:
CRegTestParams() {
keyConstants.strNetworkID = "regtest";
strCurrencyUnits = "REG";
bip44CoinType = 1;
keyConstants.bip44CoinType = 1;
consensus.fCoinbaseMustBeShielded = false;
consensus.nSubsidySlowStartInterval = 0;
consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL;
@ -729,6 +729,9 @@ public:
// Founders reward script expects a vector of 2-of-3 multisig addresses
vFoundersRewardAddress = { "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" };
assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight(0));
// do not require the wallet backup to be confirmed in regtest mode
fRequireWalletBackup = false;
}
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight)
@ -822,10 +825,10 @@ CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const {
assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight(nHeight));
KeyIO keyIO(*this);
CTxDestination address = keyIO.DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str());
assert(IsValidDestination(address));
assert(IsScriptDestination(address));
CScriptID scriptID = std::get<CScriptID>(address); // address is a variant
auto address = keyIO.DecodePaymentAddress(GetFoundersRewardAddressAtHeight(nHeight).c_str());
assert(address.has_value());
assert(std::holds_alternative<CScriptID>(address.value()));
CScriptID scriptID = std::get<CScriptID>(address.value());
CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
return script;
}

View File

@ -32,17 +32,6 @@ struct CCheckpointData {
double fTransactionsPerDay;
};
class CBaseKeyConstants : public KeyConstants {
public:
std::string NetworkIDString() const { return strNetworkID; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; }
std::string strNetworkID;
std::vector<unsigned char> base58Prefixes[KeyConstants::MAX_BASE58_TYPES];
std::string bech32HRPs[KeyConstants::MAX_BECH32_TYPES];
};
/**
* CChainParams defines various tweakable parameters of a given instance of the
* Bitcoin system. There are three: the main network on which people trade goods
@ -50,7 +39,7 @@ public:
* a regression test mode which is intended for private networks only. It has
* minimal difficulty to ensure that blocks can be found instantly.
*/
class CChainParams: public KeyConstants
class CChainParams: public KeyConstants
{
public:
const Consensus::Params& GetConsensus() const { return consensus; }
@ -62,6 +51,7 @@ public:
CAmount SproutValuePoolCheckpointBalance() const { return nSproutValuePoolCheckpointBalance; }
uint256 SproutValuePoolCheckpointBlockHash() const { return hashSproutValuePoolCheckpointBlock; }
bool ZIP209Enabled() const { return fZIP209Enabled; }
bool RequireWalletBackup() const { return fRequireWalletBackup; }
const CBlock& GenesisBlock() const { return genesis; }
/** Make miner wait to have peers to avoid wasting work */
@ -72,19 +62,24 @@ public:
bool RequireStandard() const { return fRequireStandard; }
int64_t PruneAfterHeight() const { return nPruneAfterHeight; }
std::string CurrencyUnits() const { return strCurrencyUnits; }
uint32_t BIP44CoinType() const { return bip44CoinType; }
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
/** In the future use NetworkIDString() for RPC fields */
bool TestnetToBeDeprecatedFieldRPC() const { return fTestnetToBeDeprecatedFieldRPC; }
/** Return the BIP70 network string (main, test or regtest) */
std::string NetworkIDString() const { return keyConstants.NetworkIDString(); }
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const {
return keyConstants.Base58Prefix(type);
/** Return the BIP70 network string (main, test or regtest) */
std::string NetworkIDString() const {
return keyConstants.NetworkIDString();
}
const std::string& Bech32HRP(Bech32Type type) const {
return keyConstants.Bech32HRP(type);
/** Return the BIP44 coin type for addresses created by the zcashd embedded wallet. */
uint32_t BIP44CoinType() const {
return keyConstants.BIP44CoinType();
}
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const {
return keyConstants.Base58Prefix(type);
}
const std::string& Bech32HRP(Bech32Type type) const {
return keyConstants.Bech32HRP(type);
}
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
@ -106,7 +101,6 @@ protected:
std::vector<CDNSSeedData> vSeeds;
CBaseKeyConstants keyConstants;
std::string strCurrencyUnits;
uint32_t bip44CoinType;
CBlock genesis;
std::vector<SeedSpec6> vFixedSeeds;
bool fMiningRequiresPeers = false;
@ -121,6 +115,7 @@ protected:
CAmount nSproutValuePoolCheckpointBalance = 0;
uint256 hashSproutValuePoolCheckpointBlock;
bool fZIP209Enabled = false;
bool fRequireWalletBackup = true;
};
/**

View File

@ -16,8 +16,8 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 4
#define CLIENT_VERSION_MINOR 5
#define CLIENT_VERSION_REVISION 1
#define CLIENT_VERSION_MINOR 6
#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_BUILD 51
//! Set to true for release, false for prerelease or test build

View File

@ -46,7 +46,7 @@ bool CCoins::Spend(uint32_t nPos)
}
bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return false; }
bool CCoinsView::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return false; }
bool CCoinsView::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const { return false; }
bool CCoinsView::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const { return false; }
bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return false; }
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
@ -75,7 +75,7 @@ CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); }
bool CCoinsViewBacked::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return base->GetSaplingAnchorAt(rt, tree); }
bool CCoinsViewBacked::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const { return base->GetOrchardAnchorAt(rt, tree); }
bool CCoinsViewBacked::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const { return base->GetOrchardAnchorAt(rt, tree); }
bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return base->GetNullifier(nullifier, type); }
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
@ -191,7 +191,7 @@ bool CCoinsViewCache::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &t
return true;
}
bool CCoinsViewCache::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const {
bool CCoinsViewCache::GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const {
CAnchorsOrchardMap::const_iterator it = cacheOrchardAnchors.find(rt);
if (it != cacheOrchardAnchors.end()) {
if (it->second.entered) {
@ -321,9 +321,9 @@ template<> void CCoinsViewCache::PushAnchor(const SaplingMerkleTree &tree)
);
}
template<> void CCoinsViewCache::PushAnchor(const OrchardMerkleTree &tree)
template<> void CCoinsViewCache::PushAnchor(const OrchardMerkleFrontier &tree)
{
AbstractPushAnchor<OrchardMerkleTree, CAnchorsOrchardMap, CAnchorsOrchardMap::iterator, CAnchorsOrchardCacheEntry>(
AbstractPushAnchor<OrchardMerkleFrontier, CAnchorsOrchardMap, CAnchorsOrchardMap::iterator, CAnchorsOrchardCacheEntry>(
tree,
ORCHARD,
cacheOrchardAnchors,
@ -352,7 +352,7 @@ void CCoinsViewCache::BringBestAnchorIntoCache(
template<>
void CCoinsViewCache::BringBestAnchorIntoCache(
const uint256 &currentRoot,
OrchardMerkleTree &tree
OrchardMerkleFrontier &tree
)
{
assert(GetOrchardAnchorAt(currentRoot, tree));
@ -1069,7 +1069,7 @@ std::optional<UnsatisfiedShieldedReq> CCoinsViewCache::HaveShieldedRequirements(
std::optional<uint256> root = tx.GetOrchardBundle().GetAnchor();
if (root) {
OrchardMerkleTree tree;
OrchardMerkleFrontier tree;
if (!GetOrchardAnchorAt(root.value(), tree)) {
auto txid = tx.GetHash().ToString();
auto anchor = root.value().ToString();

View File

@ -304,7 +304,7 @@ struct CAnchorsSaplingCacheEntry
struct CAnchorsOrchardCacheEntry
{
bool entered; // This will be false if the anchor is removed from the cache
OrchardMerkleTree tree; // The tree itself
OrchardMerkleFrontier tree; // The tree itself
unsigned char flags;
enum Flags {
@ -368,7 +368,7 @@ public:
virtual bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const;
//! Retrieve the tree (Orchard) at a particular anchored root in the chain
virtual bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const;
virtual bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const;
//! Determine whether a nullifier is spent or not
virtual bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
@ -428,7 +428,7 @@ public:
CCoinsViewBacked(CCoinsView *viewIn);
bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const;
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const;
bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const;
bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const;
bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const;
@ -521,7 +521,7 @@ public:
// Standard CCoinsView methods
bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const;
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const;
bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleTree &tree) const;
bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const;
bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
bool GetCoins(const uint256 &txid, CCoins &coins) const;
bool HaveCoins(const uint256 &txid) const;

View File

@ -9,6 +9,7 @@
#include <script/standard.h>
#include "upgrades.h"
#include "util.h"
#include "util/match.h"
namespace Consensus {
bool Params::NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const {
@ -163,17 +164,26 @@ namespace Consensus {
// Parse the address strings into concrete types.
std::vector<FundingStreamAddress> addresses;
for (auto addr : strAddresses) {
auto taddr = keyIO.DecodeDestination(addr);
if (IsValidDestination(taddr)) {
addresses.push_back(GetScriptForDestination(taddr));
} else {
auto zaddr = keyIO.DecodePaymentAddress(addr);
// If the string is not a valid transparent or Sapling address, we will
// throw here.
addresses.push_back(std::get<libzcash::SaplingPaymentAddress>(zaddr));
for (const auto& strAddr : strAddresses) {
auto addr = keyIO.DecodePaymentAddress(strAddr);
if (!addr.has_value()) {
throw std::runtime_error("Funding stream address was not a valid " PACKAGE_NAME " address.");
}
std::visit(match {
[&](const CKeyID& keyId) {
addresses.push_back(GetScriptForDestination(keyId));
},
[&](const CScriptID& scriptId) {
addresses.push_back(GetScriptForDestination(scriptId));
},
[&](const libzcash::SaplingPaymentAddress& zaddr) {
addresses.push_back(zaddr);
},
[&](const auto& zaddr) {
throw std::runtime_error("Funding stream address was not a valid transparent P2SH or Sapling address.");
}
}, addr.value());
}
auto validationResult = FundingStream::ValidateFundingStream(params, startHeight, endHeight, addresses);

View File

@ -10,7 +10,7 @@
// Per https://zips.z.cash/zip-0200
// Shut down nodes running this version of code, 16 weeks' worth of blocks after the estimated
// release block height. A warning is shown during the 14 days' worth of blocks prior to shut down.
static const int APPROX_RELEASE_HEIGHT = 1396476;
static const int APPROX_RELEASE_HEIGHT = 1504042;
static const int RELEASE_TO_DEPRECATION_WEEKS = 16;
static const int EXPECTED_BLOCKS_PER_HOUR = 3600 / Consensus::POST_BLOSSOM_POW_TARGET_SPACING;
static_assert(EXPECTED_BLOCKS_PER_HOUR == 48, "The value of Consensus::POST_BLOSSOM_POW_TARGET_SPACING was chosen such that this assertion holds.");

View File

@ -11,6 +11,7 @@ bool fExperimentalDeveloperSetPoolSizeZero = false;
bool fExperimentalPaymentDisclosure = false;
bool fExperimentalInsightExplorer = false;
bool fExperimentalLightWalletd = false;
bool fExperimentalOrchardWallet = false;
std::optional<std::string> InitExperimentalMode()
{
@ -20,6 +21,7 @@ std::optional<std::string> InitExperimentalMode()
fExperimentalPaymentDisclosure = GetBoolArg("-paymentdisclosure", false);
fExperimentalInsightExplorer = GetBoolArg("-insightexplorer", false);
fExperimentalLightWalletd = GetBoolArg("-lightwalletd", false);
fExperimentalOrchardWallet = GetBoolArg("-orchardwallet", false);
// Fail if user has set experimental options without the global flag
if (!fExperimentalMode) {
@ -33,6 +35,8 @@ std::optional<std::string> InitExperimentalMode()
return _("Insight explorer requires -experimentalfeatures.");
} else if (fExperimentalLightWalletd) {
return _("Light Walletd requires -experimentalfeatures.");
} else if (fExperimentalOrchardWallet) {
return _("Orchard-enabled wallet requires -experimentalfeatures.");
}
}
return std::nullopt;
@ -51,6 +55,8 @@ std::vector<std::string> GetExperimentalFeatures()
experimentalfeatures.push_back("insightexplorer");
if (fExperimentalLightWalletd)
experimentalfeatures.push_back("lightwalletd");
if (fExperimentalOrchardWallet)
experimentalfeatures.push_back("orchardwallet");
return experimentalfeatures;
}

View File

@ -14,6 +14,7 @@ extern bool fExperimentalDeveloperSetPoolSizeZero;
extern bool fExperimentalPaymentDisclosure;
extern bool fExperimentalInsightExplorer;
extern bool fExperimentalLightWalletd;
extern bool fExperimentalOrchardWallet;
std::optional<std::string> InitExperimentalMode();
std::vector<std::string> GetExperimentalFeatures();

View File

@ -221,11 +221,11 @@ TEST(Joinsplit, HSig)
/*
// by Taylor Hornby
import pyblake2
import hashlib
import binascii
def hSig(randomSeed, nf1, nf2, joinSplitPubKey):
return pyblake2.blake2b(
return hashlib.blake2b(
data=(randomSeed + nf1 + nf2 + joinSplitPubKey),
digest_size=32,
person=b"ZcashComputehSig"

View File

@ -10,6 +10,7 @@
#include "json_test_vectors.h"
#include "test/data/unified_addrs.json.h"
#include "test/data/unified_full_viewing_keys.json.h"
TEST(Keys, EncodeAndDecodeSapling)
{
@ -27,11 +28,11 @@ TEST(Keys, EncodeAndDecodeSapling)
Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY));
auto spendingkey2 = keyIO.DecodeSpendingKey(sk_string);
EXPECT_TRUE(IsValidSpendingKey(spendingkey2));
EXPECT_TRUE(spendingkey2.has_value());
ASSERT_TRUE(std::get_if<libzcash::SaplingExtendedSpendingKey>(&spendingkey2) != nullptr);
auto sk2 = std::get<libzcash::SaplingExtendedSpendingKey>(spendingkey2);
EXPECT_EQ(sk, sk2);
auto sk2 = std::get_if<libzcash::SaplingExtendedSpendingKey>(&spendingkey2.value());
EXPECT_NE(sk2, nullptr);
EXPECT_EQ(sk, *sk2);
}
{
auto extfvk = sk.ToXFVK();
@ -41,14 +42,14 @@ TEST(Keys, EncodeAndDecodeSapling)
Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_FVK));
auto viewingkey2 = keyIO.DecodeViewingKey(vk_string);
EXPECT_TRUE(IsValidViewingKey(viewingkey2));
EXPECT_TRUE(viewingkey2.has_value());
ASSERT_TRUE(std::get_if<libzcash::SaplingExtendedFullViewingKey>(&viewingkey2) != nullptr);
auto extfvk2 = std::get<libzcash::SaplingExtendedFullViewingKey>(viewingkey2);
EXPECT_EQ(extfvk, extfvk2);
auto extfvk2 = std::get_if<libzcash::SaplingExtendedFullViewingKey>(&viewingkey2.value());
EXPECT_NE(extfvk2, nullptr);
EXPECT_EQ(extfvk, *extfvk2);
}
{
auto addr = sk.DefaultAddress();
auto addr = sk.ToXFVK().DefaultAddress();
std::string addr_string = keyIO.EncodePaymentAddress(addr);
EXPECT_EQ(
@ -56,11 +57,11 @@ TEST(Keys, EncodeAndDecodeSapling)
Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS));
auto paymentaddr2 = keyIO.DecodePaymentAddress(addr_string);
EXPECT_TRUE(IsValidPaymentAddress(paymentaddr2));
EXPECT_TRUE(paymentaddr2.has_value());
ASSERT_TRUE(std::get_if<libzcash::SaplingPaymentAddress>(&paymentaddr2) != nullptr);
auto addr2 = std::get<libzcash::SaplingPaymentAddress>(paymentaddr2);
EXPECT_EQ(addr, addr2);
auto addr2 = std::get_if<libzcash::SaplingPaymentAddress>(&paymentaddr2.value());
EXPECT_NE(addr2, nullptr);
EXPECT_EQ(addr, *addr2);
}
}
}
@ -78,11 +79,11 @@ namespace libzcash {
return tfm::format("Sapling(%s)", HexStr(ss.begin(), ss.end()));
}
std::string operator()(const P2SHAddress &p2sh) const {
std::string operator()(const CScriptID &p2sh) const {
return tfm::format("P2SH(%s)", p2sh.GetHex());
}
std::string operator()(const P2PKHAddress &p2pkh) const {
std::string operator()(const CKeyID &p2pkh) const {
return tfm::format("P2PKH(%s)", p2pkh.GetHex());
}
@ -102,7 +103,7 @@ namespace libzcash {
}
}
TEST(Keys, EncodeAndDecodeUnified)
TEST(Keys, EncodeAndDecodeUnifiedAddresses)
{
SelectParams(CBaseChainParams::MAIN);
KeyIO keyIO(Params());
@ -121,7 +122,7 @@ TEST(Keys, EncodeAndDecodeUnified)
try {
libzcash::UnifiedAddress ua;
// ["p2pkh_bytes, p2sh_bytes, sapling_raw_addr, orchard_raw_addr, unified_addr"]
// ["p2pkh_bytes, p2sh_bytes, sapling_raw_addr, orchard_raw_addr, unknown_typecode, unknown_bytes, unified_addr, root_seed, account, diversifier_index"],
// These were added to the UA in preference order by the Python test vectors.
if (!test[3].isNull()) {
auto data = ParseHex(test[3].get_str());
@ -131,8 +132,7 @@ TEST(Keys, EncodeAndDecodeUnified)
if (!test[2].isNull()) {
auto data = ParseHex(test[2].get_str());
CDataStream ss(
reinterpret_cast<const char*>(data.data()),
reinterpret_cast<const char*>(data.data() + data.size()),
data,
SER_NETWORK,
PROTOCOL_VERSION);
libzcash::SaplingPaymentAddress r;
@ -140,20 +140,22 @@ TEST(Keys, EncodeAndDecodeUnified)
ua.AddReceiver(r);
}
if (!test[1].isNull()) {
libzcash::P2SHAddress r(ParseHex(test[1].get_str()));
CScriptID r(ParseHex(test[1].get_str()));
ua.AddReceiver(r);
}
if (!test[0].isNull()) {
libzcash::P2PKHAddress r(ParseHex(test[0].get_str()));
CKeyID r(ParseHex(test[0].get_str()));
ua.AddReceiver(r);
}
auto expectedBytes = ParseHex(test[4].get_str());
auto expectedBytes = ParseHex(test[6].get_str());
std::string expected(expectedBytes.begin(), expectedBytes.end());
auto decoded = keyIO.DecodePaymentAddress(expected);
ASSERT_TRUE(std::holds_alternative<libzcash::UnifiedAddress>(decoded));
EXPECT_EQ(std::get<libzcash::UnifiedAddress>(decoded), ua);
EXPECT_TRUE(decoded.has_value());
auto ua_ptr = std::get_if<libzcash::UnifiedAddress>(&decoded.value());
EXPECT_NE(ua_ptr, nullptr);
EXPECT_EQ(*ua_ptr, ua);
auto encoded = keyIO.EncodePaymentAddress(ua);
EXPECT_EQ(encoded, expected);
@ -164,3 +166,143 @@ TEST(Keys, EncodeAndDecodeUnified)
}
}
}
TEST(Keys, DeriveUnifiedFullViewingKeys)
{
SelectParams(CBaseChainParams::MAIN);
KeyIO keyIO(Params());
UniValue ua_tests = read_json(MAKE_STRING(json_tests::unified_full_viewing_keys));
for (size_t idx = 0; idx < ua_tests.size(); idx++) {
UniValue test = ua_tests[idx];
std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
FAIL() << "Bad test: " << strTest;
continue;
}
if (test.size() == 1) continue; // comment
try {
auto seed_hex = test[6].get_str();
auto seed_data = ParseHex(seed_hex);
RawHDSeed raw_seed(seed_data.begin(), seed_data.end());
ASSERT_EQ(HexStr(raw_seed), seed_hex);
HDSeed hdseed(raw_seed);
auto usk = libzcash::ZcashdUnifiedSpendingKey::ForAccount(
hdseed,
133, //ZCASH_MAIN_COINTYPE
test[7].get_int());
ASSERT_TRUE(usk.has_value());
auto ufvk = usk->ToFullViewingKey();
if (!test[0].isNull()) {
auto expectedHex = test[0].get_str();
// Ensure that the serialized transparent account key matches the test data.
auto tkey = ufvk.GetTransparentKey().value();
CDataStream ssEncode(SER_NETWORK, PROTOCOL_VERSION);
ssEncode << tkey.GetChainablePubKey();
EXPECT_EQ(ssEncode.size(), 65);
auto tkeyHex = HexStr(ssEncode.begin(), ssEncode.end());
EXPECT_EQ(expectedHex, tkeyHex);
// Ensure that parsing the test data derives the correct account pubkey.
auto data = ParseHex(expectedHex);
ASSERT_EQ(data.size(), 65);
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
auto expected = libzcash::transparent::AccountPubKey(CChainablePubKey::Read(ss));
EXPECT_EQ(expected, tkey);
}
if (!test[1].isNull()) {
auto expectedHex = test[1].get_str();
// Ensure that the serialized Sapling dfvk matches the test data.
auto saplingKey = ufvk.GetSaplingKey().value();
CDataStream ssEncode(SER_NETWORK, PROTOCOL_VERSION);
ssEncode << saplingKey;
EXPECT_EQ(ssEncode.size(), 128);
auto skeyHex = HexStr(ssEncode.begin(), ssEncode.end());
EXPECT_EQ(expectedHex, skeyHex);
// Ensure that parsing the test data derives the correct dfvk
auto data = ParseHex(expectedHex);
ASSERT_EQ(data.size(), 128);
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
auto key = libzcash::SaplingDiversifiableFullViewingKey::Read(ss);
EXPECT_EQ(key, saplingKey);
}
// Enable the following after Orchard keys are supported.
//{
// auto fvk_data = ParseHex(test[5].get_str());
// std::string expected(fvk_data.begin(), fvk_data.end());
// EXPECT_EQ(expected, ufvk.Encode(Params(CBaseChainParams::MAIN)));
//}
} catch (const std::exception& ex) {
FAIL() << "Bad test, couldn't deserialize data: " << strTest << ": " << ex.what();
} catch (...) {
FAIL() << "Bad test, couldn't deserialize data: " << strTest;
}
}
}
TEST(Keys, EncodeAndDecodeUnifiedFullViewingKeys)
{
SelectParams(CBaseChainParams::MAIN);
KeyIO keyIO(Params());
UniValue ua_tests = read_json(MAKE_STRING(json_tests::unified_full_viewing_keys));
for (size_t idx = 0; idx < ua_tests.size(); idx++) {
UniValue test = ua_tests[idx];
std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
FAIL() << "Bad test: " << strTest;
continue;
}
if (test.size() == 1) continue; // comment
libzcash::UnifiedFullViewingKeyBuilder builder;
// ["t_key_bytes, sapling_fvk_bytes, orchard_fvk_bytes, unknown_fvk_typecode, unknown_fvk_bytes, unified_fvk"]
// These were added to the UA in preference order by the Python test vectors.
if (!test[0].isNull()) {
auto data = ParseHex(test[0].get_str());
ASSERT_EQ(data.size(), 65);
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
auto decoded = CChainablePubKey::Read(ss);
ASSERT_TRUE(builder.AddTransparentKey(decoded));
}
if (!test[1].isNull()) {
auto data = ParseHex(test[1].get_str());
ASSERT_EQ(data.size(), 128);
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
auto key = libzcash::SaplingDiversifiableFullViewingKey::Read(ss);
ASSERT_TRUE(builder.AddSaplingKey(key));
}
// Orchard keys and unknown items are not yet supported; instead,
// we just test that we're able to parse the unified key string
// and that the constituent items match the elements; if no Sapling
// key is present then UFVK construction would fail because it might
// presume the UFVK to be transparent-only.
if (test[1].isNull())
continue;
auto built = builder.build();
ASSERT_TRUE(built.has_value());
auto keystrBytes = ParseHex(test[5].get_str());
std::string keystr(keystrBytes.begin(), keystrBytes.end());
auto decoded = libzcash::UnifiedFullViewingKey::Decode(keystr, Params());
ASSERT_TRUE(decoded.has_value());
EXPECT_EQ(decoded.value().GetTransparentKey(), built.value().GetTransparentKey());
EXPECT_EQ(decoded.value().GetSaplingKey(), built.value().GetSaplingKey());
}
}

View File

@ -14,37 +14,88 @@
#define MAKE_STRING(x) std::string((x), (x)+sizeof(x))
TEST(KeystoreTests, StoreAndRetrieveHDSeed) {
using namespace libzcash;
const uint32_t SLIP44_TESTNET_TYPE = 1;
TEST(KeystoreTests, StoreAndRetrieveMnemonicSeed) {
CBasicKeyStore keyStore;
HDSeed seedOut;
// When we haven't set a seed, we shouldn't get one
EXPECT_FALSE(keyStore.HaveHDSeed());
EXPECT_FALSE(keyStore.GetHDSeed(seedOut));
EXPECT_FALSE(keyStore.HaveMnemonicSeed());
auto seedOut = keyStore.GetMnemonicSeed();
EXPECT_FALSE(seedOut.has_value());
// Generate a random seed
auto seed = HDSeed::Random();
auto seed = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
// We should be able to set and retrieve the seed
ASSERT_TRUE(keyStore.SetHDSeed(seed));
EXPECT_TRUE(keyStore.HaveHDSeed());
ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed, seedOut);
ASSERT_TRUE(keyStore.SetMnemonicSeed(seed));
EXPECT_TRUE(keyStore.HaveMnemonicSeed());
seedOut = keyStore.GetMnemonicSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
// Generate another random seed
auto seed2 = HDSeed::Random();
auto seed2 = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
EXPECT_NE(seed, seed2);
// We should not be able to set and retrieve a different seed
EXPECT_FALSE(keyStore.SetHDSeed(seed2));
ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed, seedOut);
EXPECT_FALSE(keyStore.SetMnemonicSeed(seed2));
seedOut = keyStore.GetMnemonicSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
}
TEST(KeystoreTests, DecodeInvalidMnemonic) {
SecureString mnemonic("\xff");
EXPECT_FALSE(MnemonicSeed::ForPhrase(Language::English, mnemonic).has_value());
}
TEST(KeystoreTests, DeserializeMnemonic) {
CDataStream ss0(SER_NETWORK, CLIENT_VERSION);
ss0 << (uint32_t)English;
ss0 << SecureString("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
EXPECT_NO_THROW(MnemonicSeed::Read(ss0));
CDataStream ss(SER_NETWORK, CLIENT_VERSION);
ss << (uint32_t)English;
ss << SecureString("\xff");
EXPECT_THROW(MnemonicSeed::Read(ss), std::ios_base::failure);
}
TEST(KeystoreTests, StoreAndRetrieveLegacyHDSeed) {
CBasicKeyStore keyStore;
// When we haven't set a seed, we shouldn't get one
std::optional<HDSeed> seedOut = keyStore.GetLegacyHDSeed();
EXPECT_FALSE(seedOut.has_value());
// Generate a random seed
// (We use MnemonicSeed purely to generate a seed, and then drop the mnemonic part.)
HDSeed seed = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
// We should be able to set and retrieve the seed
ASSERT_TRUE(keyStore.SetLegacyHDSeed(seed));
seedOut = keyStore.GetLegacyHDSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
// Generate another random seed
HDSeed seed2 = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
EXPECT_NE(seed, seed2);
// We should not be able to set and retrieve a different seed
EXPECT_FALSE(keyStore.SetLegacyHDSeed(seed2));
seedOut = keyStore.GetLegacyHDSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
}
TEST(KeystoreTests, SaplingKeys) {
// ["sk, ask, nsk, ovk, ak, nk, ivk, default_d, default_pk_d, note_v, note_r, note_cm, note_pos, note_nf"],
UniValue sapling_keys = read_json(MAKE_STRING(json_tests::sapling_key_components));
// Skipping over comments in sapling_key_components.json file
for (size_t i = 2; i < 12; i++) {
uint256 skSeed, ask, nsk, ovk, ak, nk, ivk;
@ -55,40 +106,40 @@ TEST(KeystoreTests, SaplingKeys) {
ak.SetHex(sapling_keys[i][4].getValStr());
nk.SetHex(sapling_keys[i][5].getValStr());
ivk.SetHex(sapling_keys[i][6].getValStr());
libzcash::diversifier_t default_d;
std::copy_n(ParseHex(sapling_keys[i][7].getValStr()).begin(), 11, default_d.begin());
uint256 default_pk_d;
default_pk_d.SetHex(sapling_keys[i][8].getValStr());
auto sk = libzcash::SaplingSpendingKey(skSeed);
// Check that expanded spending key from primitives and from sk are the same
auto exp_sk_2 = libzcash::SaplingExpandedSpendingKey(ask, nsk, ovk);
auto exp_sk = sk.expanded_spending_key();
EXPECT_EQ(exp_sk, exp_sk_2);
// Check that full viewing key derived from sk and expanded sk are the same
auto full_viewing_key = sk.full_viewing_key();
EXPECT_EQ(full_viewing_key, exp_sk.full_viewing_key());
// Check that full viewing key from primitives and from sk are the same
auto full_viewing_key_2 = libzcash::SaplingFullViewingKey(ak, nk, ovk);
EXPECT_EQ(full_viewing_key, full_viewing_key_2);
// Check that incoming viewing key from primitives and from sk are the same
auto in_viewing_key = full_viewing_key.in_viewing_key();
auto in_viewing_key_2 = libzcash::SaplingIncomingViewingKey(ivk);
EXPECT_EQ(in_viewing_key, in_viewing_key_2);
// Check that the default address from primitives and from sk method are the same
auto default_addr = sk.default_address();
auto addrOpt2 = in_viewing_key.address(default_d);
EXPECT_TRUE(addrOpt2);
auto default_addr_2 = addrOpt2.value();
EXPECT_EQ(default_addr, default_addr_2);
auto default_addr_3 = libzcash::SaplingPaymentAddress(default_d, default_pk_d);
EXPECT_EQ(default_addr_2, default_addr_3);
EXPECT_EQ(default_addr, default_addr_3);
@ -200,8 +251,8 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingSpendingKey) {
auto sk = GetTestMasterSaplingSpendingKey();
auto extfvk = sk.ToXFVK();
auto ivk = extfvk.fvk.in_viewing_key();
auto addr = sk.DefaultAddress();
auto ivk = extfvk.ToIncomingViewingKey();
auto addr = sk.ToXFVK().DefaultAddress();
// Sanity-check: we can't get a key we haven't added
EXPECT_FALSE(keyStore.HaveSaplingSpendingKey(extfvk));
@ -209,9 +260,6 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingSpendingKey) {
// Sanity-check: we can't get a full viewing key we haven't added
EXPECT_FALSE(keyStore.HaveSaplingFullViewingKey(ivk));
EXPECT_FALSE(keyStore.GetSaplingFullViewingKey(ivk, extfvkOut));
// Sanity-check: we can't get an incoming viewing key we haven't added
EXPECT_FALSE(keyStore.HaveSaplingIncomingViewingKey(addr));
EXPECT_FALSE(keyStore.GetSaplingIncomingViewingKey(addr, ivkOut));
// When we specify the default address, we get the full mapping
keyStore.AddSaplingSpendingKey(sk);
@ -219,6 +267,12 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingSpendingKey) {
EXPECT_TRUE(keyStore.GetSaplingSpendingKey(extfvk, skOut));
EXPECT_TRUE(keyStore.HaveSaplingFullViewingKey(ivk));
EXPECT_TRUE(keyStore.GetSaplingFullViewingKey(ivk, extfvkOut));
// We can't get an incoming viewing key for an address we haven't added
EXPECT_FALSE(keyStore.HaveSaplingIncomingViewingKey(addr));
EXPECT_FALSE(keyStore.GetSaplingIncomingViewingKey(addr, ivkOut));
keyStore.AddSaplingPaymentAddress(ivk, addr);
EXPECT_TRUE(keyStore.HaveSaplingIncomingViewingKey(addr));
EXPECT_TRUE(keyStore.GetSaplingIncomingViewingKey(addr, ivkOut));
EXPECT_EQ(sk, skOut);
@ -234,8 +288,8 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingFullViewingKey) {
auto sk = GetTestMasterSaplingSpendingKey();
auto extfvk = sk.ToXFVK();
auto ivk = extfvk.fvk.in_viewing_key();
auto addr = sk.DefaultAddress();
auto ivk = extfvk.ToIncomingViewingKey();
auto addr = sk.ToXFVK().DefaultAddress();
// Sanity-check: we can't get a full viewing key we haven't added
EXPECT_FALSE(keyStore.HaveSaplingFullViewingKey(ivk));
@ -258,11 +312,14 @@ TEST(KeystoreTests, StoreAndRetrieveSaplingFullViewingKey) {
EXPECT_TRUE(keyStore.GetSaplingFullViewingKey(ivk, extfvkOut));
EXPECT_EQ(extfvk, extfvkOut);
// We should still not have the spending key...
// We should still not have the spending key or
// be able to retrieve the IVK by the default address...
EXPECT_FALSE(keyStore.HaveSaplingSpendingKey(extfvk));
EXPECT_FALSE(keyStore.GetSaplingSpendingKey(extfvk, skOut));
EXPECT_FALSE(keyStore.HaveSaplingIncomingViewingKey(addr));
// ... but we should have an incoming viewing key
// The IVK must be manually associated with the address...
keyStore.AddSaplingPaymentAddress(ivk, addr);
EXPECT_TRUE(keyStore.HaveSaplingIncomingViewingKey(addr));
EXPECT_TRUE(keyStore.GetSaplingIncomingViewingKey(addr, ivkOut));
EXPECT_EQ(ivk, ivkOut);
@ -281,24 +338,26 @@ public:
bool Unlock(const CKeyingMaterial& vMasterKeyIn) { return CCryptoKeyStore::Unlock(vMasterKeyIn); }
};
TEST(KeystoreTests, StoreAndRetrieveHDSeedInEncryptedStore) {
TEST(KeystoreTests, StoreAndRetrieveMnemonicSeedInEncryptedStore) {
TestCCryptoKeyStore keyStore;
CKeyingMaterial vMasterKey(32, 0);
GetRandBytes(vMasterKey.data(), 32);
HDSeed seedOut;
// 1) Test adding a seed to an unencrypted key store, then encrypting it
auto seed = HDSeed::Random();
EXPECT_FALSE(keyStore.HaveHDSeed());
EXPECT_FALSE(keyStore.GetHDSeed(seedOut));
auto seed = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
EXPECT_FALSE(keyStore.HaveMnemonicSeed());
auto seedOut = keyStore.GetMnemonicSeed();
EXPECT_FALSE(seedOut.has_value());
ASSERT_TRUE(keyStore.SetHDSeed(seed));
EXPECT_TRUE(keyStore.HaveHDSeed());
ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed, seedOut);
ASSERT_TRUE(keyStore.SetMnemonicSeed(seed));
EXPECT_TRUE(keyStore.HaveMnemonicSeed());
seedOut = keyStore.GetMnemonicSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
ASSERT_TRUE(keyStore.EncryptKeys(vMasterKey));
EXPECT_FALSE(keyStore.GetHDSeed(seedOut));
seedOut = keyStore.GetMnemonicSeed();
EXPECT_FALSE(seedOut.has_value());
// Unlocking with a random key should fail
CKeyingMaterial vRandomKey(32, 0);
@ -312,15 +371,17 @@ TEST(KeystoreTests, StoreAndRetrieveHDSeedInEncryptedStore) {
// Unlocking with vMasterKey should succeed
ASSERT_TRUE(keyStore.Unlock(vMasterKey));
ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed, seedOut);
seedOut = keyStore.GetMnemonicSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
// 2) Test replacing the seed in an already-encrypted key store fails
auto seed2 = HDSeed::Random();
EXPECT_FALSE(keyStore.SetHDSeed(seed2));
EXPECT_TRUE(keyStore.HaveHDSeed());
ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed, seedOut);
auto seed2 = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
EXPECT_FALSE(keyStore.SetMnemonicSeed(seed2));
EXPECT_TRUE(keyStore.HaveMnemonicSeed());
seedOut = keyStore.GetMnemonicSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
// 3) Test adding a new seed to an already-encrypted key store
TestCCryptoKeyStore keyStore2;
@ -331,14 +392,77 @@ TEST(KeystoreTests, StoreAndRetrieveHDSeedInEncryptedStore) {
ASSERT_TRUE(keyStore2.EncryptKeys(vMasterKey));
ASSERT_TRUE(keyStore2.Unlock(vMasterKey));
EXPECT_FALSE(keyStore2.HaveHDSeed());
EXPECT_FALSE(keyStore2.GetHDSeed(seedOut));
EXPECT_FALSE(keyStore2.HaveMnemonicSeed());
seedOut = keyStore2.GetMnemonicSeed();
EXPECT_FALSE(seedOut.has_value());
auto seed3 = HDSeed::Random();
ASSERT_TRUE(keyStore2.SetHDSeed(seed3));
EXPECT_TRUE(keyStore2.HaveHDSeed());
ASSERT_TRUE(keyStore2.GetHDSeed(seedOut));
EXPECT_EQ(seed3, seedOut);
auto seed3 = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
ASSERT_TRUE(keyStore2.SetMnemonicSeed(seed3));
EXPECT_TRUE(keyStore2.HaveMnemonicSeed());
seedOut = keyStore2.GetMnemonicSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed3, seedOut.value());
}
TEST(KeystoreTests, StoreAndRetrieveLegacyHDSeedInEncryptedStore) {
TestCCryptoKeyStore keyStore;
CKeyingMaterial vMasterKey(32, 0);
GetRandBytes(vMasterKey.data(), 32);
// 1) Test adding a seed to an unencrypted key store, then encrypting it
// We use a mnemonic seed, then disregard the mnemonic itself.
auto seed = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
auto seedOut = keyStore.GetLegacyHDSeed();
EXPECT_FALSE(seedOut.has_value());
ASSERT_TRUE(keyStore.SetLegacyHDSeed(seed));
seedOut = keyStore.GetLegacyHDSeed();
ASSERT_TRUE(seedOut.has_value());
ASSERT_TRUE(keyStore.EncryptKeys(vMasterKey));
seedOut = keyStore.GetLegacyHDSeed();
EXPECT_FALSE(seedOut.has_value());
// Unlocking with a random key should fail
CKeyingMaterial vRandomKey(32, 0);
GetRandBytes(vRandomKey.data(), 32);
EXPECT_FALSE(keyStore.Unlock(vRandomKey));
// Unlocking with a slightly-modified vMasterKey should fail
CKeyingMaterial vModifiedKey(vMasterKey);
vModifiedKey[0] += 1;
EXPECT_FALSE(keyStore.Unlock(vModifiedKey));
// Unlocking with vMasterKey should succeed
ASSERT_TRUE(keyStore.Unlock(vMasterKey));
seedOut = keyStore.GetLegacyHDSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
// 2) Test replacing the seed in an already-encrypted key store fails
auto seed2 = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
EXPECT_FALSE(keyStore.SetLegacyHDSeed(seed2));
seedOut = keyStore.GetLegacyHDSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed, seedOut.value());
// 3) Test adding a new seed to an already-encrypted key store
TestCCryptoKeyStore keyStore2;
// Add a Sprout address so the wallet has something to test when decrypting
ASSERT_TRUE(keyStore2.AddSproutSpendingKey(libzcash::SproutSpendingKey::random()));
ASSERT_TRUE(keyStore2.EncryptKeys(vMasterKey));
ASSERT_TRUE(keyStore2.Unlock(vMasterKey));
seedOut = keyStore2.GetLegacyHDSeed();
EXPECT_FALSE(seedOut.has_value());
auto seed3 = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
ASSERT_TRUE(keyStore2.SetLegacyHDSeed(seed3));
seedOut = keyStore2.GetLegacyHDSeed();
ASSERT_TRUE(seedOut.has_value());
EXPECT_EQ(seed3, seedOut.value());
}
TEST(KeystoreTests, StoreAndRetrieveSpendingKeyInEncryptedStore) {
@ -415,4 +539,62 @@ TEST(KeystoreTests, StoreAndRetrieveSpendingKeyInEncryptedStore) {
ASSERT_EQ(1, addrs.count(addr));
ASSERT_EQ(1, addrs.count(addr2));
}
TEST(KeystoreTests, StoreAndRetrieveUFVK) {
SelectParams(CBaseChainParams::TESTNET);
CBasicKeyStore keyStore;
auto seed = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
auto usk = ZcashdUnifiedSpendingKey::ForAccount(seed, SLIP44_TESTNET_TYPE, 0);
EXPECT_TRUE(usk.has_value());
auto ufvk = usk.value().ToFullViewingKey();
auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(Params(), ufvk);
auto ufvkid = zufvk.GetKeyID();
EXPECT_FALSE(keyStore.GetUnifiedFullViewingKey(ufvkid).has_value());
EXPECT_TRUE(keyStore.AddUnifiedFullViewingKey(zufvk));
EXPECT_EQ(keyStore.GetUnifiedFullViewingKey(ufvkid).value(), zufvk);
auto addrPair = std::get<std::pair<UnifiedAddress, diversifier_index_t>>(zufvk.FindAddress(diversifier_index_t(0), {ReceiverType::Sapling}));
EXPECT_TRUE(addrPair.first.GetSaplingReceiver().has_value());
auto saplingReceiver = addrPair.first.GetSaplingReceiver().value();
auto ufvkmeta = keyStore.GetUFVKMetadataForReceiver(saplingReceiver);
EXPECT_FALSE(ufvkmeta.has_value());
auto saplingIvk = zufvk.GetSaplingKey().value().ToIncomingViewingKey();
keyStore.AddSaplingPaymentAddress(saplingIvk, saplingReceiver);
ufvkmeta = keyStore.GetUFVKMetadataForReceiver(saplingReceiver);
EXPECT_TRUE(ufvkmeta.has_value());
EXPECT_EQ(ufvkmeta.value().first, ufvkid);
EXPECT_FALSE(ufvkmeta.value().second.has_value());
}
TEST(KeystoreTests, AddTransparentReceiverForUnifiedAddress) {
SelectParams(CBaseChainParams::TESTNET);
CBasicKeyStore keyStore;
auto seed = MnemonicSeed::Random(SLIP44_TESTNET_TYPE);
auto usk = ZcashdUnifiedSpendingKey::ForAccount(seed, SLIP44_TESTNET_TYPE, 0);
EXPECT_TRUE(usk.has_value());
auto ufvk = usk.value().ToFullViewingKey();
auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(Params(), ufvk);
auto ufvkid = zufvk.GetKeyID();
auto addrPair = std::get<std::pair<UnifiedAddress, diversifier_index_t>>(zufvk.FindAddress(diversifier_index_t(0), {ReceiverType::P2PKH, ReceiverType::Sapling}));
EXPECT_TRUE(addrPair.first.GetP2PKHReceiver().has_value());
auto ufvkmeta = keyStore.GetUFVKMetadataForReceiver(addrPair.first.GetP2PKHReceiver().value());
EXPECT_FALSE(ufvkmeta.has_value());
keyStore.AddTransparentReceiverForUnifiedAddress(ufvkid, addrPair.second, addrPair.first);
ufvkmeta = keyStore.GetUFVKMetadataForReceiver(addrPair.first.GetP2PKHReceiver().value());
EXPECT_TRUE(ufvkmeta.has_value());
EXPECT_EQ(ufvkmeta.value().first, ufvkid);
}
#endif

View File

@ -293,13 +293,13 @@ TEST(orchardMerkleTree, emptyroot) {
// an integer, which is converted to little-endian internally.
uint256 expected = uint256S("2fd8e51a03d9bbe2dd809831b1497aeb68a6e37ddf707ced4aa2d8dff13529ae");
ASSERT_EQ(OrchardMerkleTree::empty_root(), expected);
ASSERT_EQ(OrchardMerkleFrontier::empty_root(), expected);
}
TEST(orchardMerkleTree, appendBundle) {
OrchardMerkleTree newTree;
OrchardMerkleFrontier newTree;
ASSERT_EQ(newTree.root(), OrchardMerkleTree::empty_root());
ASSERT_EQ(newTree.root(), OrchardMerkleFrontier::empty_root());
for (int i = 0; i < 1; i++) {
CDataStream ssBundleData(merkle_roots_orchard[i].bundle, SER_NETWORK, PROTOCOL_VERSION);

View File

@ -4,6 +4,7 @@
#include "chain.h"
#include "chainparams.h"
#include "clientversion.h"
#include "main.h"
#include "primitives/block.h"
#include "rpc/server.h"
#include "streams.h"
@ -23,6 +24,7 @@ TEST(rpc, CheckBlockToJSONReturnsMinifiedSolution) {
CBlockIndex index {block};
index.nHeight = 1391;
LOCK(cs_main);
UniValue obj = blockToJSON(block, &index);
EXPECT_EQ("009f44ff7505d789b964d6817734b8ce1377d456255994370d06e59ac99bd5791b6ad174a66fd71c70e60cfc7fd88243ffe06f80b1ad181625f210779c745524629448e25348a5fce4f346a1735e60fdf53e144c0157dbc47c700a21a236f1efb7ee75f65b8d9d9e29026cfd09048233175202b211b9a49de4ab46f1cac71b6ea57a686377bd612378746e70c61a659c9cd683269e9c2a5cbc1d19f1149345302bbd0a1e62bf4bab01e9caeea789a1519441a61b146de35a4cc75dbdf01029127e311ad5073e7e96397f47226a7df9df66b2086b70756db013bbaeb068260157014b2602fc7dc71336e1439c887d2742d9730b4e79b08ec7839c3e2a037ae1565d04e05e351bb3531e5ef42cf7b71ca1482a9205245dd41f4db0f71644f8bdb88e845558537c03834c06ac83f336651e54e2edfc12e15ea9b7ea2c074e6155654d44c4d3bd90d9511050e9ad87d170db01448e5be6f45419cd86008978db5e3ceab79890234f992648d69bf1053855387db646ccdee5575c65f81dd0f670b016d9f9a84707d91f77b862f697b8bb08365ba71fbe6bfa47af39155a75ebdcb1e5d69f59c40c9e3a64988c1ec26f7f5159eef5c244d504a9e46125948ecc389c2ec3028ac4ff39ffd66e7743970819272b21e0c2df75b308bc62896873952147e57ed79446db4cdb5a563e76ec4c25899d41128afb9a5f8fc8063621efb7a58b9dd666d30c73e318cdcf3393bfec200e160f500e645f7baac263db99fa4a7c1cb4fea219fc512193102034d379f244c21a81821301b8d47c90247713a3e902c762d7bafa6cdb744eeb6d3b50dd175599d02b6e9f5bbda59366e04862aa765135968426e7ac0116de7351940dc57c0ae451d63f667e39891bc81e09e6c76f6f8a7582f7447c6f5945f717b0e52a7e3dd0c6db4061362123cc53fd8ede4abed4865201dc4d8eb4e5d48baa565183b69a5304a44c0600bb24dcaeee9d95ceebd27c1b0a33e0b46f23797d7d7907300b2bb7d62ef2fc5aa139250c73930c621bb5f41fc235534ee8014dfaddd5245aeb01198420ba7b5c076545329c94d54fa725a8e807579f5f0cc9d98170598023268f5930893620190275e6b3c6f5181e36310a9a475208316911d78f917d724c5946c553b7ec042c563c540114b6b78bd4c6e808ee391a4a9d93e127032983c5b3708037b14aa604cfb034e7c8b0ffdd6936446fe80216178506a87402653a373926eeff66e704daf992a0a9a5c3ad80566c0339be9e5b8e35b3b3226b2f7767e20d992ea6c3d6e322eca37b0c7f7e60060802f5abcc1975841365cadbdc3867063addfc803766ae525375ecddee61f9df9ffcd20343c83ab82b0e91de039c59cb435c8d3159cc338b4901f40c9b5c27043bcf2bd5fa9b685b65c9ba5a1e11a51dd3f773051560341f9ec81d05bf259e2d4b7161f896fbb6812cfc924a32120b7367d5e40439e267adda6a1315bb0d6200ce6a503174c8d2a638ea6fd6b1f486d68db11bdca63c4f4a725d1ab6231ea875484e70b27d293c05803386924f283d4c12bb953474d92b7dd43d2d97193bd96281ebb63fa075d2f9ecd310c70ee1d97b5330bd8fb5791c5943ecf084e5f2c83915acac57519c46b166136068d6f9ec0dd598616e32c591128ce13705a283ca39d5b211409600e07b3713113374d9700207a45394eac5b3b7afc9b1b2bad7d89fd3f35f6b2413ce615ee7869b3569009403b96fdacdb32ef0a7e5229e2b666d51e95bdfb009b892e88bde70621a9b6509f068781392df4bdbc5723bb15071993f0d9a11575af5ff6ef85eaea39bc86805b35d8beee91b779354147f2d85304b8b49d053e7444fdd3deb9d16de331f2552af5b3be7766bb8f3f6a78c62148efb231f2268", find_value(obj, "solution").get_str());
}

View File

@ -268,17 +268,6 @@ TEST(TransactionBuilder, RejectsInvalidTransparentOutput)
ASSERT_THROW(builder.AddTransparentOutput(taddr, 50), UniValue);
}
TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress)
{
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& consensusParams = Params().GetConsensus();
// Default CTxDestination type is an invalid address
CTxDestination taddr;
auto builder = TransactionBuilder(consensusParams, 1);
ASSERT_THROW(builder.SendChangeTo(taddr), UniValue);
}
TEST(TransactionBuilder, FailsWithNegativeChange)
{
auto consensusParams = RegtestActivateSapling();
@ -344,7 +333,6 @@ TEST(TransactionBuilder, ChangeOutput)
CKey tsk = AddTestCKeyToKeyStore(keystore);
auto tkeyid = tsk.GetPubKey().GetID();
auto scriptPubKey = GetScriptForDestination(tkeyid);
CTxDestination taddr = tkeyid;
// No change address and no Sapling spends
{
@ -387,7 +375,7 @@ TEST(TransactionBuilder, ChangeOutput)
{
auto builder = TransactionBuilder(consensusParams, 1, &keystore);
builder.AddTransparentInput(COutPoint(), scriptPubKey, 25000);
builder.SendChangeTo(taddr);
builder.SendChangeTo(tkeyid, {});
auto tx = builder.Build().GetTxOrThrow();
EXPECT_EQ(tx.vin.size(), 1);

View File

@ -58,10 +58,10 @@ TEST(ZIP32, TestVectors) {
m_1.ToXFVK().DefaultAddress().d,
testing::ElementsAreArray({ 0x8b, 0x41, 0x38, 0x32, 0x0d, 0xfa, 0xfd, 0x7b, 0x39, 0x97, 0x81 }));
auto m_1_2h = m_1.Derive(2 | ZIP32_HARDENED_KEY_LIMIT);
auto m_1_2h = m_1.Derive(2 | HARDENED_KEY_LIMIT);
EXPECT_EQ(m_1_2h.depth, 2);
EXPECT_EQ(m_1_2h.parentFVKTag, 0x079e99db);
EXPECT_EQ(m_1_2h.childIndex, 2 | ZIP32_HARDENED_KEY_LIMIT);
EXPECT_EQ(m_1_2h.childIndex, 2 | HARDENED_KEY_LIMIT);
EXPECT_EQ(
m_1_2h.chaincode,
uint256S("35d4a883737742ca41a4baa92323bdb3c93dcb3b462a26b039971bedf415ce97"));
@ -84,7 +84,7 @@ TEST(ZIP32, TestVectors) {
auto m_1_2hv = m_1_2h.ToXFVK();
EXPECT_EQ(m_1_2hv.depth, 2);
EXPECT_EQ(m_1_2hv.parentFVKTag, 0x079e99db);
EXPECT_EQ(m_1_2hv.childIndex, 2 | ZIP32_HARDENED_KEY_LIMIT);
EXPECT_EQ(m_1_2hv.childIndex, 2 | HARDENED_KEY_LIMIT);
EXPECT_EQ(
m_1_2hv.chaincode,
uint256S("35d4a883737742ca41a4baa92323bdb3c93dcb3b462a26b039971bedf415ce97"));
@ -103,7 +103,7 @@ TEST(ZIP32, TestVectors) {
EXPECT_EQ(m_1_2hv.DefaultAddress(), m_1_2h.ToXFVK().DefaultAddress());
// Hardened derivation from an xfvk fails
EXPECT_FALSE(m_1_2hv.Derive(3 | ZIP32_HARDENED_KEY_LIMIT));
EXPECT_FALSE(m_1_2hv.Derive(3 | HARDENED_KEY_LIMIT));
// Non-hardened derivation succeeds
auto maybe_m_1_2hv_3 = m_1_2hv.Derive(3);
@ -132,3 +132,57 @@ TEST(ZIP32, TestVectors) {
m_1_2hv_3.DefaultAddress().d,
testing::ElementsAreArray({ 0x03, 0x0f, 0xfb, 0x26, 0x3a, 0x93, 0x9e, 0x23, 0x0e, 0x96, 0xdd }));
}
TEST(ZIP32, ParseHDKeypathAccount) {
auto expect_account = [](std::string sAccount, uint32_t coinType, long expected) {
auto result = libzcash::ParseHDKeypathAccount(32, coinType, sAccount);
EXPECT_TRUE(result.has_value());
EXPECT_EQ(result.value(), expected);
};
std::string sAccount = "m/32'/1234'/5'";
expect_account(sAccount, 1234, 5);
sAccount = "m/32'/1234'/50'";
expect_account(sAccount, 1234, 50);
sAccount = "m/32'/1234'/5'/0";
expect_account(sAccount, 1234, 5);
sAccount = "m/32'/133'/2147483646'/1";
expect_account(sAccount, 133, 2147483646);
}
TEST(ZIP32, diversifier_index_t_increment)
{
libzcash::diversifier_index_t d_zero(0);
libzcash::diversifier_index_t d_one(1);
EXPECT_TRUE(d_zero.increment());
EXPECT_EQ(d_zero, d_one);
}
TEST(ZIP32, diversifier_index_t_lt)
{
EXPECT_TRUE(libzcash::diversifier_index_t(0) < libzcash::diversifier_index_t(1));
EXPECT_FALSE(libzcash::diversifier_index_t(1) < libzcash::diversifier_index_t(0));
EXPECT_FALSE(libzcash::diversifier_index_t(0) < libzcash::diversifier_index_t(0));
EXPECT_TRUE(libzcash::diversifier_index_t(0xfffffffe) < libzcash::diversifier_index_t(0xffffffff));
EXPECT_FALSE(libzcash::diversifier_index_t(0xffffffff) < libzcash::diversifier_index_t(0xfffffffe));
EXPECT_TRUE(libzcash::diversifier_index_t(0x01) < libzcash::diversifier_index_t(0xffffffff));
EXPECT_FALSE(libzcash::diversifier_index_t(0xffffffff) < libzcash::diversifier_index_t(0x01));
}
TEST(ZIP32, DeriveChangeAddress)
{
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
HDSeed seed(rawSeed);
auto accountSk = libzcash::SaplingExtendedSpendingKey::ForAccount(seed, 1, 0);
auto extfvk = accountSk.first.ToXFVK();
auto changeSk = accountSk.first.DeriveInternalKey();
EXPECT_EQ(changeSk.ToXFVK().DefaultAddress(), extfvk.GetChangeAddress());
}

Some files were not shown because too many files have changed in this diff Show More