Compare commits
344 Commits
c4b2ef7c4e
...
bb91c9fbc3
Author | SHA1 | Date |
---|---|---|
Kris Nuttycombe | bb91c9fbc3 | |
therealyingtong | 1dae16a41c | |
ying tong | 2943e13c8b | |
therealyingtong | 108e9d4658 | |
therealyingtong | 99a69182cd | |
therealyingtong | 4c4ee558d6 | |
str4d | 6cd5b8792b | |
Kris Nuttycombe | d08c992b5e | |
Larry Ruane | ba9e020fcd | |
Kris Nuttycombe | 73a75a37fe | |
Steven Smith | 59c6b028f7 | |
therealyingtong | 79c0514919 | |
Steven | ffdc11c378 | |
Daira Hopwood | 816649db2a | |
Steven Smith | 512c862a5f | |
str4d | d0d6d47aa7 | |
therealyingtong | 94ab8e4c77 | |
Larry Ruane | 698f7ba770 | |
therealyingtong | c7346e802e | |
therealyingtong | 6436230562 | |
sasha | e568a190f3 | |
Kris Nuttycombe | 9ca64fc8ba | |
Kris Nuttycombe | 96f34b9bbd | |
Kris Nuttycombe | b1ab30c8d9 | |
Kris Nuttycombe | 67e871a40c | |
Kris Nuttycombe | e6d3dca2a3 | |
Larry Ruane | 326dafeebe | |
Kris Nuttycombe | 93e12899bb | |
Kris Nuttycombe | 85caa659af | |
Kris Nuttycombe | 29c9632ecb | |
Kris Nuttycombe | 007f05493a | |
Larry Ruane | c48e35bb66 | |
Kris Nuttycombe | 30c20c0046 | |
Kris Nuttycombe | d2b900a0c8 | |
Jack Grigg | 89b9bbaf33 | |
Jack Grigg | 2555aadf31 | |
Jack Grigg | 11e62fa997 | |
Kris Nuttycombe | d1227b086e | |
Kris Nuttycombe | 2aad87e147 | |
Kris Nuttycombe | 50ad6675a5 | |
Kris Nuttycombe | 09593559f8 | |
Jack Grigg | 88dde127f4 | |
Kris Nuttycombe | f320a6cc24 | |
Kris Nuttycombe | d2e8b98364 | |
Jack Grigg | 0a9c27e8f2 | |
Kris Nuttycombe | d24a41496a | |
Kris Nuttycombe | bf79be2b57 | |
str4d | 944453065b | |
Kris Nuttycombe | 08dd842087 | |
Kris Nuttycombe | ae1b843b5a | |
Daira Hopwood | cf1047324e | |
str4d | d41e10e0c2 | |
Larry Ruane | 403c5846c1 | |
str4d | 9439c79bab | |
Kris Nuttycombe | 3f84067658 | |
Kris Nuttycombe | 282c0db8d5 | |
Kris Nuttycombe | 1890758b27 | |
Kris Nuttycombe | 9a8038ea62 | |
Kris Nuttycombe | cf271473eb | |
Kris Nuttycombe | 13ee447a42 | |
Kris Nuttycombe | fa0d4eb473 | |
str4d | 96912d3152 | |
Larry Ruane | 1e165b8396 | |
Kris Nuttycombe | 741ed52436 | |
Kris Nuttycombe | 6c9b9a53b5 | |
zancas | ca04cb0a58 | |
zancas | 4dce020678 | |
Kris Nuttycombe | 214567be2c | |
Kris Nuttycombe | a0c27bf254 | |
Kris Nuttycombe | a46720aab1 | |
Kris Nuttycombe | 2209a74f38 | |
Kris Nuttycombe | 90e59c3be0 | |
Conrado Gouvea | 269c5c2e7f | |
Kris Nuttycombe | 66530d97e1 | |
Kris Nuttycombe | b80349d246 | |
Kris Nuttycombe | ae2213dcdc | |
Kris Nuttycombe | acacc044fc | |
Kris Nuttycombe | 9afea4f10b | |
Kris Nuttycombe | 91be2f1875 | |
Kris Nuttycombe | b880ef8a1c | |
Kris Nuttycombe | 71f17fa05c | |
Kris Nuttycombe | 1733c6bc0c | |
Kris Nuttycombe | b46d85976d | |
Kris Nuttycombe | 3ddbe1fa06 | |
Kris Nuttycombe | bdcb12e445 | |
Kris Nuttycombe | c21ffff790 | |
str4d | 992a47103d | |
Kris Nuttycombe | d17a0bb9de | |
Jack Grigg | 756f4fc840 | |
Jack Grigg | 77c46933aa | |
Jack Grigg | ca0dad0a8c | |
Kris Nuttycombe | d8c818bfa5 | |
Kris Nuttycombe | 443136c137 | |
Kris Nuttycombe | 28eddb7c21 | |
Charlie O'Keefe | 19bfc2f3b8 | |
Kris Nuttycombe | b93155c460 | |
Kris Nuttycombe | db104a6329 | |
Kris Nuttycombe | b8a5131af9 | |
Kris Nuttycombe | beb0f2bc1f | |
Kris Nuttycombe | c15f6a9cad | |
Kris Nuttycombe | ddb34f612d | |
Kris Nuttycombe | babc11eb52 | |
Kris Nuttycombe | 0abe07c73b | |
Kris Nuttycombe | 18282040f5 | |
Kris Nuttycombe | c4a74087b7 | |
str4d | a6f9c9c0bc | |
Kris Nuttycombe | a43dbb4925 | |
Kris Nuttycombe | e419899a29 | |
Kris Nuttycombe | f850e89449 | |
Kris Nuttycombe | c4a7f5c95c | |
str4d | 6b335ecb4c | |
str4d | a5b0725f89 | |
Jack Grigg | 714f14168c | |
Jack Grigg | 9b61806cc6 | |
Jack Grigg | f2e0a8d1f3 | |
Jack Grigg | 96c9333b74 | |
Jack Grigg | ff0e9f6b95 | |
Jack Grigg | baaa3c4ac0 | |
Jack Grigg | 8617622e0d | |
Jack Grigg | fe384eeb1f | |
str4d | 6118432712 | |
Kris Nuttycombe | cc392c70a6 | |
str4d | 423489c5e8 | |
Kris Nuttycombe | de58fc0b16 | |
Kris Nuttycombe | 528ae6d180 | |
Kris Nuttycombe | 0ca7d49626 | |
Kris Nuttycombe | 9554ed2dc4 | |
Kris Nuttycombe | 322aee238a | |
Kris Nuttycombe | b54a63bf18 | |
Kris Nuttycombe | f9477a4499 | |
Larry Ruane | bc1af5fc2d | |
zancas | 30abf25148 | |
Kris Nuttycombe | d6525e24db | |
zancas | fbbdb23214 | |
str4d | 005a8624bf | |
Kris Nuttycombe | 951a44de93 | |
Kris Nuttycombe | ed93cf5aff | |
Kris Nuttycombe | 41eebce355 | |
Daira Hopwood | 0e073a53ee | |
Daira Hopwood | 4f7d15508f | |
Kris Nuttycombe | d3b599eac1 | |
Kris Nuttycombe | 864cd8622f | |
Kris Nuttycombe | 9702b47e2a | |
Kris Nuttycombe | eb91c7869a | |
Kris Nuttycombe | 20266ac911 | |
Kris Nuttycombe | d376e28382 | |
Kris Nuttycombe | f5d4f6fef1 | |
Kris Nuttycombe | 4f2ff2a9f8 | |
Kris Nuttycombe | 890e1d841d | |
Kris Nuttycombe | c35e2b4438 | |
Kris Nuttycombe | 62b86d6afc | |
Kris Nuttycombe | b305ad2892 | |
Kris Nuttycombe | 89755a114b | |
Kris Nuttycombe | fe777c5624 | |
Kris Nuttycombe | 98967e2ec7 | |
Kris Nuttycombe | 0403799be2 | |
str4d | fe7b87a96c | |
Jack Grigg | daef0041e0 | |
Jack Grigg | cf22fa7fe3 | |
Jack Grigg | b97133daaf | |
Jack Grigg | 5bf937b422 | |
str4d | 7b820cfa8f | |
Jack Grigg | 4559186596 | |
Larry Ruane | 97a76f1b61 | |
Larry Ruane | dfefab2f55 | |
str4d | 1d7a29ea56 | |
Kris Nuttycombe | eb53abbbaf | |
Kris Nuttycombe | ad54591061 | |
Kris Nuttycombe | 8d6d178a47 | |
Kris Nuttycombe | 16ba83ab1e | |
Dimitris Apostolou | 2006939d27 | |
Kris Nuttycombe | 0931aa8908 | |
Kris Nuttycombe | 5d07a8ae79 | |
Steven Smith | 56b706d5c7 | |
Daira Hopwood | ba0688da3f | |
Larry Ruane | 1f223ebed7 | |
Kris Nuttycombe | 74e4bef6f2 | |
Sasha | ba4b4791c1 | |
Sasha | 25278c312a | |
Sasha | eeecf63dae | |
Sasha | de4dd9f231 | |
Sasha | baa3de9250 | |
Sasha | bc6e565bcc | |
Kris Nuttycombe | ad5c4dcf09 | |
Kris Nuttycombe | 900cd50741 | |
Kris Nuttycombe | 24e46a16f1 | |
Kris Nuttycombe | 735ecd0906 | |
Kris Nuttycombe | 9b72fff365 | |
Kris Nuttycombe | b34fd6a816 | |
Kris Nuttycombe | 009ba76b0e | |
Kris Nuttycombe | 700b98f0b0 | |
Kris Nuttycombe | 0dcdc28a38 | |
Kris Nuttycombe | 8337442553 | |
Kris Nuttycombe | 290985ba48 | |
Kris Nuttycombe | b29ca10b8d | |
Kris Nuttycombe | ca20cf512c | |
Kris Nuttycombe | d869d7f4a3 | |
Kris Nuttycombe | e56f252a86 | |
Kris Nuttycombe | ef068c51a9 | |
Larry Ruane | b538577359 | |
Larry Ruane | 8c0177a507 | |
Charlie O'Keefe | a2a66df5e0 | |
Charlie O'Keefe | 04c292a379 | |
str4d | 213ba58fae | |
Sasha | 87101eeaed | |
Sasha | 4e928fa67f | |
str4d | 3acc68548e | |
str4d | 12e022a53a | |
Jack Grigg | 9c4a1e7ad7 | |
Jack Grigg | 1c910cf9cc | |
Jack Grigg | d4b850d3f7 | |
str4d | 75b539400c | |
Jack Grigg | 8387aa40cf | |
Jack Grigg | d85bfb4744 | |
str4d | eb175dddaa | |
Kris Nuttycombe | 8b093a79da | |
str4d | 72aad89859 | |
MarcoFalke | 6d60f1a9c9 | |
str4d | 9e4b6f670d | |
Larry Ruane | c937ba5ae5 | |
Kris Nuttycombe | 5c2d91589f | |
str4d | 34a8677c43 | |
Jack Grigg | 1b7a031e7b | |
Jack Grigg | 09e0af815f | |
str4d | 6a57389f38 | |
Kris Nuttycombe | ceeede3dc6 | |
Jack Grigg | 407a0d9324 | |
Jack Grigg | c37a69a357 | |
Jack Grigg | 0d310a79ca | |
Kris Nuttycombe | fc1a16f4ff | |
Jack Grigg | e257844261 | |
Kris Nuttycombe | 99b2098f89 | |
Larry Ruane | f139cdc4fe | |
Kris Nuttycombe | 6d36921b94 | |
Kris Nuttycombe | 24ff7b36ec | |
Kris Nuttycombe | 4966bf315a | |
Kris Nuttycombe | 6f702c72a7 | |
Kris Nuttycombe | 00bda351f8 | |
Larry Ruane | d0e836a15e | |
Kris Nuttycombe | 48446b5e39 | |
Larry Ruane | cc70cd2c46 | |
Larry Ruane | d0b85b69f3 | |
str4d | 87eeee0607 | |
Kris Nuttycombe | 1e18410b55 | |
Kris Nuttycombe | d1890ebd24 | |
Kris Nuttycombe | 6cccc4ad3c | |
Kris Nuttycombe | 8ae8ddd7d1 | |
Kris Nuttycombe | 22cd218e83 | |
Kris Nuttycombe | 217c56811d | |
Kris Nuttycombe | c78887a148 | |
Kris Nuttycombe | 4257abd328 | |
Kris Nuttycombe | 640f31463f | |
Jack Grigg | df0534e35a | |
Larry Ruane | 7fa0e1a6a9 | |
Kris Nuttycombe | c908a3b059 | |
Kris Nuttycombe | 3bfb9d0c84 | |
Kris Nuttycombe | a2f8e3b56c | |
Kris Nuttycombe | d65200c860 | |
Kris Nuttycombe | aa808eb07d | |
Kris Nuttycombe | 782c705cb1 | |
Kris Nuttycombe | bde245d8bc | |
Kris Nuttycombe | e7c507cfb3 | |
Jack Grigg | 6c0bd90ee6 | |
Jack Grigg | 5ae516f7b0 | |
Kris Nuttycombe | 6ee0dea218 | |
Kris Nuttycombe | 59a4c84112 | |
Kris Nuttycombe | 8f5591a9c1 | |
Kris Nuttycombe | 7aaefab2d7 | |
Kris Nuttycombe | 9202b127d0 | |
str4d | c76b756a68 | |
Kris Nuttycombe | f49f4c73d8 | |
str4d | f8e99e7ba5 | |
Kris Nuttycombe | 13b9a69230 | |
Kris Nuttycombe | c7089d2086 | |
Kris Nuttycombe | 14f95572fa | |
Kris Nuttycombe | 7be1ec9c23 | |
Sasha | 2d25e08fcc | |
Kris Nuttycombe | 92445ba0a5 | |
str4d | e9f450281b | |
str4d | 0268ce0ad0 | |
Jack Grigg | 9fd44c76fa | |
Jack Grigg | 675e489aff | |
Kris Nuttycombe | 2ec7073459 | |
Kris Nuttycombe | b1d6a514e2 | |
Kris Nuttycombe | b722c40fe2 | |
Kris Nuttycombe | 0fe1134337 | |
Kris Nuttycombe | cfee863644 | |
Kris Nuttycombe | 6e6359229a | |
Kris Nuttycombe | f31b3c2190 | |
Kris Nuttycombe | 7860d6ede3 | |
Kris Nuttycombe | f65d6f63ee | |
Kris Nuttycombe | de57da38ce | |
teor | bdbd86edb7 | |
teor | f4a8dc57e0 | |
teor | 7d24ada757 | |
teor | 3bae89c732 | |
teor | 77ab1831a1 | |
teor | fa181a2d08 | |
teor | 31bd2ba4f1 | |
Janito Vaqueiro Ferreira Filho | ae9266a1cd | |
Dimitris Apostolou | e05c1ddf8a | |
Kris Nuttycombe | f626673b89 | |
Kris Nuttycombe | ea8e9438af | |
Kris Nuttycombe | a67fb00d0a | |
Kris Nuttycombe | 399ed5b4d7 | |
Kris Nuttycombe | 551072165a | |
Kris Nuttycombe | 6fdded20bc | |
Kris Nuttycombe | d84845d199 | |
Jack Grigg | 5eca8d34ba | |
Jack Grigg | 373206027f | |
Jack Grigg | 1364db2ded | |
Jack Grigg | ca7160ebab | |
Jack Grigg | 2005c91d41 | |
Kris Nuttycombe | 4080f48868 | |
Kris Nuttycombe | 87f7e5fbba | |
Kris Nuttycombe | cd01b2d9bf | |
Kris Nuttycombe | b54d4cac7d | |
Kris Nuttycombe | e4e77eb389 | |
Kris Nuttycombe | 0951fe22d8 | |
Kris Nuttycombe | 67557df165 | |
Kris Nuttycombe | d09a0c44f3 | |
Kris Nuttycombe | 30517a002b | |
Kris Nuttycombe | dbcdc560de | |
Kris Nuttycombe | 22fa6b22ea | |
Kris Nuttycombe | b67e62d977 | |
Kris Nuttycombe | 477a166565 | |
Kris Nuttycombe | 8bf4ec3b4a | |
Kris Nuttycombe | 5760a639d2 | |
Kris Nuttycombe | d6984dbf78 | |
Kris Nuttycombe | e0ae5362c9 | |
Kris Nuttycombe | d8d9cd129e | |
Kris Nuttycombe | ebab190fdf | |
Kris Nuttycombe | dc2c07bbde | |
Kris Nuttycombe | 2885ae7643 | |
Kris Nuttycombe | 666d135e2e | |
Kris Nuttycombe | daf443c9e6 | |
Kris Nuttycombe | 8f1d58f16f | |
Kris Nuttycombe | f99f2e4b3f | |
Kris Nuttycombe | 290b2e4e39 | |
Kris Nuttycombe | f6ad523ccb | |
Kris Nuttycombe | 83dee7e886 | |
Kris Nuttycombe | 8883ae8b9e | |
Kris Nuttycombe | 5677649af1 | |
Charlie O'Keefe | 21d6835efa |
|
@ -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]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
37
Cargo.toml
37
Cargo.toml
|
@ -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" }
|
||||
|
|
|
@ -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">
|
||||
===========
|
||||
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
FROM debian:10
|
||||
FROM debian:11
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y gnupg2 apt-transport-https curl
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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/>.
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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/>.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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`.
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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']],
|
||||
|
|
|
@ -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']],
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 #
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
|
@ -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.
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from pyblake2 import blake2b
|
||||
from hashlib import blake2b
|
||||
import struct
|
||||
from typing import (List, Optional)
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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
|
|
@ -1,10 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
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()
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
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()
|
||||
|
|
|
@ -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()
|
|
@ -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()
|
|
@ -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])
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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__':
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.55.0
|
||||
1.56.1
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) { }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -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,14 +62,19 @@ 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; }
|
||||
/** Return the BIP70 network string (main, test or regtest) */
|
||||
std::string NetworkIDString() const {
|
||||
return keyConstants.NetworkIDString();
|
||||
}
|
||||
/** 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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ¤tRoot,
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,31 +14,82 @@
|
|||
|
||||
#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) {
|
||||
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue