Merge pull request #5917 from nuttycom/feature/wallet_orchard-checkpoint_depth
Select anchors at `-anchorconfirmations` depth.
This commit is contained in:
commit
5c1a99a288
|
@ -4,9 +4,24 @@ linker = "aarch64-linux-gnu-gcc"
|
|||
[source.crates-io]
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/zcash/halo2.git"]
|
||||
git = "https://github.com/zcash/halo2.git"
|
||||
rev = "0c33fa4e6e41464884765c8fb4cefebafd300ca2"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/zcash/incrementalmerkletree.git"]
|
||||
git = "https://github.com/zcash/incrementalmerkletree.git"
|
||||
rev = "f23e3d89507849a24543121839eea6f40b141aff"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/zcash/librustzcash.git"]
|
||||
git = "https://github.com/zcash/librustzcash.git"
|
||||
rev = "d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/zcash/orchard.git"]
|
||||
git = "https://github.com/zcash/orchard.git"
|
||||
rev = "a30caec124aa6c6e7818b5100293204425c49de3"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/nuttycom/hdwallet.git"]
|
||||
|
|
|
@ -139,7 +139,7 @@ version = "0.11.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0944d18a9a37691b87733b39c9360c9950af9aa5f97e2455bc108d8eb64fc1c1"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bitvec 0.22.3",
|
||||
"blake2s_simd 0.5.11",
|
||||
"byteorder",
|
||||
"crossbeam-channel",
|
||||
|
@ -154,16 +154,6 @@ dependencies = [
|
|||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bigint"
|
||||
version = "4.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crunchy 0.1.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bip0039"
|
||||
version = "0.9.0"
|
||||
|
@ -190,10 +180,22 @@ version = "0.22.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"funty 1.2.0",
|
||||
"radium 0.6.2",
|
||||
"tap",
|
||||
"wyz",
|
||||
"wyz 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b"
|
||||
dependencies = [
|
||||
"funty 2.0.0",
|
||||
"radium 0.7.0",
|
||||
"tap",
|
||||
"wyz 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -291,6 +293,12 @@ version = "3.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
@ -428,12 +436,6 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
|
@ -562,7 +564,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
|||
[[package]]
|
||||
name = "equihash"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
|
@ -571,7 +573,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "f4jumble"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
]
|
||||
|
@ -582,11 +584,23 @@ version = "0.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bitvec 0.22.3",
|
||||
"rand_core 0.6.3",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"rand 0.8.5",
|
||||
"rustc-hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -613,6 +627,12 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.21"
|
||||
|
@ -719,11 +739,10 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "halo2_gadgets"
|
||||
version = "0.1.0-beta.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7524b798b8b3689a198cd87ee1d22fe3ca007a51d35c4093f32d75c0efc30abe"
|
||||
source = "git+https://github.com/zcash/halo2.git?rev=0c33fa4e6e41464884765c8fb4cefebafd300ca2#0c33fa4e6e41464884765c8fb4cefebafd300ca2"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.2",
|
||||
"bitvec",
|
||||
"bitvec 0.22.3",
|
||||
"ff",
|
||||
"group",
|
||||
"halo2_proofs",
|
||||
|
@ -737,11 +756,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "halo2_proofs"
|
||||
version = "0.1.0-beta.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0240b05b791cccfd6451b010b19711280e63b87f495bd84df0103f35c9139e7"
|
||||
source = "git+https://github.com/zcash/halo2.git?rev=0c33fa4e6e41464884765c8fb4cefebafd300ca2#0c33fa4e6e41464884765c8fb4cefebafd300ca2"
|
||||
dependencies = [
|
||||
"blake2b_simd",
|
||||
"bumpalo",
|
||||
"ff",
|
||||
"group",
|
||||
"pasta_curves",
|
||||
|
@ -851,11 +868,30 @@ dependencies = [
|
|||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-codec"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f"
|
||||
dependencies = [
|
||||
"parity-scale-codec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-trait-for-tuples"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "incrementalmerkletree"
|
||||
version = "0.3.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5812f2cfa06a7694b842402e9a100529d80fdc3022ead65ad98ce0af0bcd3311"
|
||||
source = "git+https://github.com/zcash/incrementalmerkletree.git?rev=f23e3d89507849a24543121839eea6f40b141aff#f23e3d89507849a24543121839eea6f40b141aff"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -906,7 +942,7 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7baec19d4e83f9145d4891178101a604565edff9645770fc979804138b04c"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"bitvec 0.22.3",
|
||||
"bls12_381",
|
||||
"ff",
|
||||
"group",
|
||||
|
@ -1252,11 +1288,10 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||
[[package]]
|
||||
name = "orchard"
|
||||
version = "0.1.0-beta.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3bb8c5f5a0977683b5071650f1e7d91f296e344a796fda585086d5b4b0a74ea"
|
||||
source = "git+https://github.com/zcash/orchard.git?rev=a30caec124aa6c6e7818b5100293204425c49de3#a30caec124aa6c6e7818b5100293204425c49de3"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bitvec",
|
||||
"bitvec 0.22.3",
|
||||
"blake2b_simd",
|
||||
"ff",
|
||||
"fpe",
|
||||
|
@ -1294,6 +1329,32 @@ dependencies = [
|
|||
"group",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-scale-codec"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.2",
|
||||
"bitvec 1.0.0",
|
||||
"byte-slice-cast",
|
||||
"impl-trait-for-tuples",
|
||||
"parity-scale-codec-derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-scale-codec-derive"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
|
@ -1422,6 +1483,27 @@ version = "0.2.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "primitive-types"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a"
|
||||
dependencies = [
|
||||
"fixed-hash",
|
||||
"impl-codec",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.37"
|
||||
|
@ -1462,6 +1544,12 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "radix_trie"
|
||||
version = "0.2.1"
|
||||
|
@ -1680,6 +1768,12 @@ version = "0.1.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hex"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
|
@ -1930,6 +2024,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.1"
|
||||
|
@ -2011,12 +2114,12 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
|||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.9.1"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f"
|
||||
checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crunchy 0.2.2",
|
||||
"crunchy",
|
||||
"hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
@ -2198,10 +2301,19 @@ dependencies = [
|
|||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zcash_address"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"bs58",
|
||||
|
@ -2212,7 +2324,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_encoding"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"nonempty",
|
||||
|
@ -2221,17 +2333,17 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_history"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"bigint",
|
||||
"blake2b_simd",
|
||||
"byteorder",
|
||||
"primitive-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zcash_note_encryption"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"chacha20",
|
||||
"chacha20poly1305",
|
||||
|
@ -2242,11 +2354,11 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_primitives"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bip0039",
|
||||
"bitvec",
|
||||
"bitvec 0.22.3",
|
||||
"blake2b_simd",
|
||||
"blake2s_simd 1.0.0",
|
||||
"bls12_381",
|
||||
|
@ -2278,7 +2390,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "zcash_proofs"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=d14e7a707ce01cefcbc82651dad48f002185dded#d14e7a707ce01cefcbc82651dad48f002185dded"
|
||||
source = "git+https://github.com/zcash/librustzcash.git?rev=68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b#68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"blake2b_simd",
|
||||
|
|
16
Cargo.toml
16
Cargo.toml
|
@ -84,10 +84,14 @@ panic = 'abort'
|
|||
codegen-units = 1
|
||||
|
||||
[patch.crates-io]
|
||||
halo2_gadgets = { git = "https://github.com/zcash/halo2.git", rev = "0c33fa4e6e41464884765c8fb4cefebafd300ca2" }
|
||||
halo2_proofs = { git = "https://github.com/zcash/halo2.git", rev = "0c33fa4e6e41464884765c8fb4cefebafd300ca2" }
|
||||
hdwallet = { git = "https://github.com/nuttycom/hdwallet.git", rev = "9b4c1bdbe0517e3a7a8f285d6048a37d472ba3bc" }
|
||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
||||
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
||||
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "f23e3d89507849a24543121839eea6f40b141aff" }
|
||||
orchard = { git = "https://github.com/zcash/orchard.git", rev = "a30caec124aa6c6e7818b5100293204425c49de3" }
|
||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||
|
|
|
@ -188,6 +188,14 @@ Files: depends/*/vendored-sources/instant/*
|
|||
Copyright: 2019 Sébastien Crozet
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: depends/*/vendored-sources/parity-scale-codec/*
|
||||
Copyright: 2018-2022 Parity Technologies
|
||||
License: Apache-2.0
|
||||
|
||||
Files: depends/*/vendored-sources/parity-scale-codec-derive/*
|
||||
Copyright: 2018-2022 Parity Technologies
|
||||
License: Apache-2.0
|
||||
|
||||
Files: depends/*/vendored-sources/subtle/*
|
||||
Copyright: 2016-2017 isis agora lovecruft, Henry de Valence
|
||||
License: BSD-3-clause
|
||||
|
|
|
@ -57,6 +57,21 @@ Option handling
|
|||
- The `-reindex` and `-reindex-chainstate` options now imply `-rescan`
|
||||
(provided that the wallet is enabled and pruning is disabled, and unless
|
||||
`-rescan=0` is specified explicitly).
|
||||
- A new `-anchorconfirmations` argument has been added to allow the user
|
||||
to specify the number of blocks back from the chain tip that anchors will be
|
||||
selected from when spending notes. By default, anchors will now be selected
|
||||
to have 3 confirmations. Values greater than 100 are not supported.
|
||||
|
||||
RPC Interface
|
||||
-------------
|
||||
|
||||
- The default `minconf` value for `z_sendmany` is now 10 confirmations instead
|
||||
of 1. If `minconf` and specifies a value less than that provided for
|
||||
`-anchorconfirmations`, it will also override that value as it is not
|
||||
possible to spend notes that are more recent than the anchor. Selecting
|
||||
`minconf` values less than 3 is not recommended, as it allows the transaction
|
||||
to be distinguished from transactions using the default for
|
||||
`-anchorconfirmations`.
|
||||
|
||||
RPC Changes
|
||||
-----------
|
||||
|
|
|
@ -89,9 +89,9 @@ class MempoolLimit(BitcoinTestFramework):
|
|||
print("Checking mempool size reset after block mined...")
|
||||
self.check_mempool_sizes(0)
|
||||
zaddr4 = self.nodes[0].z_getnewaddress('sapling')
|
||||
opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('10.0') - 2*DEFAULT_FEE}])
|
||||
opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('10.0') - 2*DEFAULT_FEE}], 1)
|
||||
wait_and_assert_operationid_status(self.nodes[0], opid4)
|
||||
opid5 = self.nodes[0].z_sendmany(zaddr2, [{"address": zaddr4, "amount": Decimal('10.0') - 2*DEFAULT_FEE}])
|
||||
opid5 = self.nodes[0].z_sendmany(zaddr2, [{"address": zaddr4, "amount": Decimal('10.0') - 2*DEFAULT_FEE}], 1)
|
||||
wait_and_assert_operationid_status(self.nodes[0], opid5)
|
||||
self.sync_all()
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ class MempoolTxExpiryTest(BitcoinTestFramework):
|
|||
zsendamount = Decimal('1.0') - DEFAULT_FEE
|
||||
recipients = []
|
||||
recipients.append({"address": z_bob, "amount": zsendamount})
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1)
|
||||
persist_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
persist_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||
# Verify transparent transaction is version 4 intended for Sapling branch
|
||||
|
@ -157,7 +157,7 @@ class MempoolTxExpiryTest(BitcoinTestFramework):
|
|||
self.split_network()
|
||||
|
||||
print("\nBlockheight advances to equal expiry block height. After reorg, txs should persist in mempool")
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1)
|
||||
persist_shielded_2 = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
persist_transparent_2 = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||
rawtx_trans = self.nodes[0].getrawtransaction(persist_transparent_2, 1)
|
||||
|
@ -192,7 +192,7 @@ class MempoolTxExpiryTest(BitcoinTestFramework):
|
|||
|
||||
print("\nBlockheight advances to greater than expiry block height. After reorg, txs should expire from mempool")
|
||||
print("Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance())
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1)
|
||||
expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||
print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks'])
|
||||
|
@ -223,7 +223,7 @@ class MempoolTxExpiryTest(BitcoinTestFramework):
|
|||
|
||||
print("\nBlockheight advances to just before expiring soon threshold. Txs should be rejected from entering mempool.")
|
||||
print("Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance())
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(z_alice, recipients, 1)
|
||||
expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||
print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks'])
|
||||
|
|
|
@ -12,7 +12,8 @@ from mergetoaddress_helper import assert_mergetoaddress_exception
|
|||
|
||||
class MergeToAddressMixedNotes(BitcoinTestFramework):
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir)
|
||||
self.num_nodes = 4
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-anchorconfirmations=1']] * self.num_nodes)
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
|
|
|
@ -16,7 +16,7 @@ class MergeToAddressSapling (BitcoinTestFramework):
|
|||
self.helper.setup_chain(self)
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.helper.setup_network(self)
|
||||
self.helper.setup_network(self, ['-anchorconfirmations=1'])
|
||||
|
||||
def run_test(self):
|
||||
self.helper.run_test(self)
|
||||
|
|
|
@ -16,7 +16,7 @@ class MergeToAddressSprout (BitcoinTestFramework):
|
|||
self.helper.setup_chain(self)
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.helper.setup_network(self)
|
||||
self.helper.setup_network(self, ['-anchorconfirmations=1'])
|
||||
|
||||
def run_test(self):
|
||||
self.helper.run_test(self)
|
||||
|
|
|
@ -20,8 +20,7 @@ class RegtestSignrawtransactionTest (BitcoinTestFramework):
|
|||
|
||||
# Create and sign Sapling transaction.
|
||||
# If the incorrect consensus branch id is selected, there will be a signing error.
|
||||
opid = self.nodes[1].z_sendmany(taddr,
|
||||
[{'address': zaddr1, 'amount': 1}])
|
||||
opid = self.nodes[1].z_sendmany(taddr, [{'address': zaddr1, 'amount': 1}], 1)
|
||||
wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -20,7 +20,9 @@ from test_framework.util import (
|
|||
|
||||
import logging
|
||||
|
||||
HAS_CANOPY = ['-nurejectoldversions=false',
|
||||
HAS_CANOPY = [
|
||||
'-nurejectoldversions=false',
|
||||
'-anchorconfirmations=1',
|
||||
nuparams(BLOSSOM_BRANCH_ID, 205),
|
||||
nuparams(HEARTWOOD_BRANCH_ID, 210),
|
||||
nuparams(CANOPY_BRANCH_ID, 220),
|
||||
|
|
|
@ -142,7 +142,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
|||
|
||||
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}])
|
||||
opid = self.nodes[1].z_sendmany(zaddr1, [{'address': taddr, 'amount': 0.6}], 1)
|
||||
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
|
||||
self.generate_and_sync(height+4)
|
||||
|
@ -220,7 +220,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
|||
opid = self.nodes[1].z_sendmany(taddr, [
|
||||
{'address': zaddr1, 'amount': 1, 'memo': my_memo},
|
||||
{'address': zaddrExt, 'amount': 2},
|
||||
])
|
||||
], 1)
|
||||
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
self.sync_all()
|
||||
|
||||
|
@ -287,8 +287,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
|||
# Generate some change by sending part of zaddr1 to zaddr2
|
||||
txidPrev = txid
|
||||
zaddr2 = self.nodes[1].z_getnewaddress('sapling')
|
||||
opid = self.nodes[1].z_sendmany(zaddr1,
|
||||
[{'address': zaddr2, 'amount': 0.6}])
|
||||
opid = self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6}], 1)
|
||||
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
self.sync_all()
|
||||
self.generate_and_sync(height+4)
|
||||
|
@ -404,7 +403,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
|||
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}])
|
||||
opid = node.z_sendmany(zaddr1, [{'address': unified_addr, 'amount': 0.1}], 1)
|
||||
txid_sapling = wait_and_assert_operationid_status(node, opid)
|
||||
self.generate_and_sync(height+5)
|
||||
|
||||
|
@ -499,7 +498,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
|||
opid = self.nodes[1].z_sendmany(uao, [
|
||||
{'address': uaso, 'amount': Decimal('0.3')},
|
||||
{'address': ua_node0, 'amount': Decimal('0.2')}
|
||||
])
|
||||
], 1)
|
||||
txid1 = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
self.sync_all()
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ class WalletNullifiersTest (BitcoinTestFramework):
|
|||
recipients = []
|
||||
recipients.append({"address":myzaddr, "amount":7.0})
|
||||
|
||||
wait_and_assert_operationid_status(self.nodes[0], self.nodes[0].z_sendmany(myzaddr0, recipients), timeout=120)
|
||||
wait_and_assert_operationid_status(self.nodes[0], self.nodes[0].z_sendmany(myzaddr0, recipients, 1), timeout=120)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
|
@ -71,7 +71,7 @@ class WalletNullifiersTest (BitcoinTestFramework):
|
|||
recipients = []
|
||||
recipients.append({"address":myzaddr3, "amount":2.0})
|
||||
|
||||
wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(myzaddr, recipients), timeout=120)
|
||||
wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(myzaddr, recipients, 1), timeout=120)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[2].generate(1)
|
||||
|
@ -93,7 +93,7 @@ class WalletNullifiersTest (BitcoinTestFramework):
|
|||
recipients = []
|
||||
recipients.append({"address":mytaddr1, "amount":1.0})
|
||||
|
||||
wait_and_assert_operationid_status(self.nodes[1], self.nodes[1].z_sendmany(myzaddr, recipients), timeout=120)
|
||||
wait_and_assert_operationid_status(self.nodes[1], self.nodes[1].z_sendmany(myzaddr, recipients, 1), timeout=120)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[1].generate(1)
|
||||
|
|
|
@ -32,6 +32,10 @@ class WalletOrchardPersistenceTest(BitcoinTestFramework):
|
|||
# Sanity-check the test harness
|
||||
assert_equal(self.nodes[0].getblockcount(), 200)
|
||||
|
||||
# activate NU5
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# Send some Orchard funds to node 2 for later spending after we split the network
|
||||
acct0 = self.nodes[0].z_getnewaccount()['account']
|
||||
ua0 = self.nodes[0].z_getaddressforaccount(acct0, ['sapling', 'orchard'])['address']
|
||||
|
@ -40,7 +44,7 @@ class WalletOrchardPersistenceTest(BitcoinTestFramework):
|
|||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
|
||||
# Mine the tx & activate NU5
|
||||
# Mine the tx
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
|
|
@ -53,6 +53,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
|||
{'address': node3taddr1, 'amount': 60},
|
||||
{'address': node3taddr2, 'amount': 75},
|
||||
],
|
||||
1
|
||||
),
|
||||
)
|
||||
self.sync_all()
|
||||
|
@ -67,7 +68,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
|||
# We should be able to spend multiple UTXOs at once
|
||||
wait_and_assert_operationid_status(
|
||||
self.nodes[3],
|
||||
self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 100}]),
|
||||
self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 100}], 1),
|
||||
)
|
||||
|
||||
self.sync_all()
|
||||
|
@ -84,7 +85,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
|||
# Send from a change t-address.
|
||||
wait_and_assert_operationid_status(
|
||||
self.nodes[3],
|
||||
self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 20}]),
|
||||
self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 20}], 1),
|
||||
)
|
||||
|
||||
self.sync_all()
|
||||
|
@ -95,7 +96,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
|||
assert_equal(self.nodes[1].z_getbalance(recipient), 120)
|
||||
|
||||
# Check that ANY_TADDR note selection doesn't attempt a double-spend
|
||||
myopid = self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 20}])
|
||||
myopid = self.nodes[3].z_sendmany('ANY_TADDR', [{'address': recipient, 'amount': 20}], 1)
|
||||
wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient funds: have 14.99998, need 20.00001")
|
||||
|
||||
# Create an expired transaction on node 3.
|
||||
|
|
|
@ -107,7 +107,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
assert_equal(error_result["method"], "z_sendmany")
|
||||
params = error_result["params"]
|
||||
assert_equal(params["fee"], DEFAULT_FEE) # default
|
||||
assert_equal(params["minconf"], Decimal('1')) # default
|
||||
assert_equal(params["minconf"], Decimal('10')) # default
|
||||
assert_equal(params["fromaddress"], mytaddr)
|
||||
assert_equal(params["amounts"][0]["address"], myzaddr)
|
||||
assert_equal(params["amounts"][0]["amount"], Decimal('1.23456789'))
|
||||
|
@ -198,7 +198,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
unshieldvalue = Decimal('10.0')
|
||||
recipients = []
|
||||
recipients.append({"address":mytaddr, "amount": unshieldvalue})
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1)
|
||||
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
assert(mytxid is not None)
|
||||
self.sync_all()
|
||||
|
@ -224,7 +224,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
recipients = []
|
||||
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)
|
||||
myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1)
|
||||
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
|
||||
|
@ -238,9 +238,9 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
# z_sendmany will fail because of insufficient funds
|
||||
recipients = []
|
||||
recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')})
|
||||
myopid = self.nodes[0].z_sendmany(mytaddr, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(mytaddr, recipients, 1)
|
||||
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)
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1)
|
||||
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
|
||||
|
@ -276,7 +276,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
self.nodes[0].getinfo()
|
||||
# Issue #2263 Workaround END
|
||||
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1)
|
||||
try:
|
||||
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
except JSONRPCException as e:
|
||||
|
|
|
@ -75,7 +75,7 @@ class WalletTreeStateTest (BitcoinTestFramework):
|
|||
recipients = []
|
||||
recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('18.0')})
|
||||
recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('12.0') - 4*DEFAULT_FEE})
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
|
||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1)
|
||||
|
||||
# Wait for Tx 2 to begin executing...
|
||||
for x in range(1, 60):
|
||||
|
|
|
@ -23,7 +23,7 @@ from decimal import Decimal
|
|||
class WalletZSendmanyTest(BitcoinTestFramework):
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir, [[
|
||||
nuparams(NU5_BRANCH_ID, 220),
|
||||
nuparams(NU5_BRANCH_ID, 238),
|
||||
]] * self.num_nodes)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
|
@ -91,7 +91,7 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
|||
# send from node 0 to node 2 taddr
|
||||
mytxid = self.nodes[0].sendtoaddress(mytaddr, 10.0)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.nodes[0].generate(10)
|
||||
self.sync_all()
|
||||
|
||||
# send node 2 taddr to zaddr
|
||||
|
@ -112,7 +112,7 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
|||
assert_equal(Decimal(wallet_info["shielded_unconfirmed_balance"]), zsendmanynotevalue)
|
||||
assert_equal(Decimal(wallet_info["shielded_balance"]), Decimal('0.0'))
|
||||
|
||||
self.nodes[2].generate(1)
|
||||
self.nodes[2].generate(10)
|
||||
self.sync_all()
|
||||
|
||||
assert_equal(self.nodes[2].getbalance(), node2utxobalance)
|
||||
|
|
|
@ -362,7 +362,8 @@ void orchard_wallet_get_potential_spends_from_nullifier(
|
|||
OrchardSpendInfoPtr* orchard_wallet_get_spend_info(
|
||||
const OrchardWalletPtr* wallet,
|
||||
const unsigned char txid[32],
|
||||
uint32_t action_idx);
|
||||
uint32_t action_idx,
|
||||
const unsigned char as_of_root[32]);
|
||||
|
||||
/**
|
||||
* Run the garbage collection operation on the wallet's note commitment
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use incrementalmerkletree::{
|
||||
bridgetree::{BridgeTree, Checkpoint},
|
||||
Hashable,
|
||||
Hashable, Position,
|
||||
};
|
||||
use zcash_encoding::{Optional, Vector};
|
||||
use zcash_primitives::merkle_tree::{
|
||||
incremental::{
|
||||
read_bridge_v1, read_leu64_usize, read_position, write_bridge_v1, write_position,
|
||||
write_usize_leu64, SER_V1,
|
||||
write_usize_leu64, SER_V1, SER_V2,
|
||||
},
|
||||
HashSer,
|
||||
};
|
||||
|
||||
pub fn write_checkpoint_v1<W: Write>(mut writer: W, checkpoint: &Checkpoint) -> io::Result<()> {
|
||||
pub fn write_checkpoint_v2<W: Write>(mut writer: W, checkpoint: &Checkpoint) -> io::Result<()> {
|
||||
write_usize_leu64(&mut writer, checkpoint.bridges_len())?;
|
||||
writer.write_u8(if checkpoint.is_witnessed() { 1 } else { 0 })?;
|
||||
Vector::write_sized(&mut writer, checkpoint.witnessed().iter(), |w, p| {
|
||||
write_position(w, *p)
|
||||
})?;
|
||||
Vector::write_sized(
|
||||
&mut writer,
|
||||
checkpoint.forgotten().iter(),
|
||||
|
@ -29,25 +33,54 @@ pub fn write_checkpoint_v1<W: Write>(mut writer: W, checkpoint: &Checkpoint) ->
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_checkpoint_v1<R: Read>(mut reader: R) -> io::Result<Checkpoint> {
|
||||
pub fn read_checkpoint_v1<R: Read>(
|
||||
mut reader: R,
|
||||
save_positions: &mut BTreeMap<usize, Position>,
|
||||
) -> io::Result<Checkpoint> {
|
||||
let bridges_len = read_leu64_usize(&mut reader)?;
|
||||
let is_witnessed = reader.read_u8()? == 1;
|
||||
let forgotten = Vector::read_collected(&mut reader, |mut r| {
|
||||
Ok((read_position(&mut r)?, read_leu64_usize(&mut r)?))
|
||||
})?;
|
||||
|
||||
// v1 checkpoints lacked information about the witnesses that were made during their
|
||||
// span of blocks, so we assume that a witness was made in the first checkpoint
|
||||
// with a corresponding bridge index.
|
||||
let witnessed = if let Some(position) = save_positions.remove(&bridges_len) {
|
||||
BTreeSet::from([position])
|
||||
} else {
|
||||
BTreeSet::new()
|
||||
};
|
||||
|
||||
Ok(Checkpoint::from_parts(
|
||||
bridges_len,
|
||||
is_witnessed,
|
||||
witnessed,
|
||||
forgotten,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn read_checkpoint_v2<R: Read>(mut reader: R) -> io::Result<Checkpoint> {
|
||||
Ok(Checkpoint::from_parts(
|
||||
read_leu64_usize(&mut reader)?,
|
||||
reader.read_u8()? == 1,
|
||||
Vector::read_collected(&mut reader, |r| read_position(r))?,
|
||||
Vector::read_collected(&mut reader, |mut r| {
|
||||
Ok((read_position(&mut r)?, read_leu64_usize(&mut r)?))
|
||||
})?,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn write_tree_v1<H: Hashable + HashSer + Ord, W: Write>(
|
||||
pub fn write_tree<H: Hashable + HashSer + Ord, W: Write>(
|
||||
mut writer: W,
|
||||
tree: &BridgeTree<H, 32>,
|
||||
) -> io::Result<()> {
|
||||
Vector::write(&mut writer, tree.prior_bridges(), |w, b| {
|
||||
write_bridge_v1(w, b)
|
||||
writer.write_u8(SER_V2)?;
|
||||
Vector::write(&mut writer, tree.prior_bridges(), |mut w, b| {
|
||||
write_bridge_v1(&mut w, b)
|
||||
})?;
|
||||
Optional::write(&mut writer, tree.current_bridge().as_ref(), |w, b| {
|
||||
write_bridge_v1(w, b)
|
||||
Optional::write(&mut writer, tree.current_bridge().as_ref(), |mut w, b| {
|
||||
write_bridge_v1(&mut w, b)
|
||||
})?;
|
||||
Vector::write_sized(
|
||||
&mut writer,
|
||||
|
@ -58,7 +91,7 @@ pub fn write_tree_v1<H: Hashable + HashSer + Ord, W: Write>(
|
|||
},
|
||||
)?;
|
||||
Vector::write(&mut writer, tree.checkpoints(), |w, c| {
|
||||
write_checkpoint_v1(w, c)
|
||||
write_checkpoint_v2(w, c)
|
||||
})?;
|
||||
write_usize_leu64(&mut writer, tree.max_checkpoints())?;
|
||||
|
||||
|
@ -66,17 +99,35 @@ pub fn write_tree_v1<H: Hashable + HashSer + Ord, W: Write>(
|
|||
}
|
||||
|
||||
#[allow(clippy::redundant_closure)]
|
||||
pub fn read_tree_v1<H: Hashable + HashSer + Ord + Clone, R: Read>(
|
||||
pub fn read_tree<H: Hashable + HashSer + Ord + Clone, R: Read>(
|
||||
mut reader: R,
|
||||
) -> io::Result<BridgeTree<H, 32>> {
|
||||
let ser_version = reader.read_u8()?;
|
||||
let prior_bridges = Vector::read(&mut reader, |r| read_bridge_v1(r))?;
|
||||
let current_bridge = Optional::read(&mut reader, |r| read_bridge_v1(r))?;
|
||||
let saved: BTreeMap<Position, usize> = Vector::read_collected(&mut reader, |mut r| {
|
||||
Ok((read_position(&mut r)?, read_leu64_usize(&mut r)?))
|
||||
})?;
|
||||
|
||||
let checkpoints = match ser_version {
|
||||
SER_V1 => {
|
||||
let mut save_positions = saved.iter().map(|(p, i)| (*i, *p)).collect();
|
||||
Vector::read_collected_mut(&mut reader, |r| read_checkpoint_v1(r, &mut save_positions))
|
||||
}
|
||||
SER_V2 => Vector::read_collected(&mut reader, |r| read_checkpoint_v2(r)),
|
||||
flag => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("Unrecognized tree serialization version: {:?}", flag),
|
||||
)),
|
||||
}?;
|
||||
let max_checkpoints = read_leu64_usize(&mut reader)?;
|
||||
|
||||
BridgeTree::from_parts(
|
||||
Vector::read(&mut reader, |r| read_bridge_v1(r))?,
|
||||
Optional::read(&mut reader, |r| read_bridge_v1(r))?,
|
||||
Vector::read_collected(&mut reader, |mut r| {
|
||||
Ok((read_position(&mut r)?, read_leu64_usize(&mut r)?))
|
||||
})?,
|
||||
Vector::read(&mut reader, |r| read_checkpoint_v1(r))?,
|
||||
read_leu64_usize(&mut reader)?,
|
||||
prior_bridges,
|
||||
current_bridge,
|
||||
saved,
|
||||
checkpoints,
|
||||
max_checkpoints,
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
|
@ -88,23 +139,3 @@ pub fn read_tree_v1<H: Hashable + HashSer + Ord + Clone, R: Read>(
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_tree<H: Hashable + HashSer + Ord, W: Write>(
|
||||
mut writer: W,
|
||||
tree: &BridgeTree<H, 32>,
|
||||
) -> io::Result<()> {
|
||||
writer.write_u8(SER_V1)?;
|
||||
write_tree_v1(&mut writer, tree)
|
||||
}
|
||||
|
||||
pub fn read_tree<H: Hashable + HashSer + Ord + Clone, R: Read>(
|
||||
mut reader: R,
|
||||
) -> io::Result<BridgeTree<H, 32>> {
|
||||
match reader.read_u8()? {
|
||||
SER_V1 => read_tree_v1(&mut reader),
|
||||
flag => Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("Unrecognized tree serialization version: {:?}", flag),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use incrementalmerkletree::{bridgetree, bridgetree::BridgeTree, Frontier, Position, Tree};
|
||||
use incrementalmerkletree::{bridgetree, bridgetree::BridgeTree, Position, Tree};
|
||||
use libc::c_uchar;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::convert::TryInto;
|
||||
|
@ -201,6 +201,8 @@ pub enum SpendRetrievalError {
|
|||
NoIvkForRecipient(Address),
|
||||
FvkNotFound(IncomingViewingKey),
|
||||
NoteNotPositioned(OutPoint),
|
||||
InvalidMerkleRoot,
|
||||
WitnessNotAvailableAtRoot(MerkleHashOrchard),
|
||||
}
|
||||
|
||||
/// A struct used to return metadata about how a bundle was determined
|
||||
|
@ -686,19 +688,23 @@ impl Wallet {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn note_commitment_tree_root(&self) -> MerkleHashOrchard {
|
||||
self.witness_tree.root()
|
||||
/// Returns the note of the Orchard note commitment tree, as of the specified checkpoint
|
||||
/// depth. A depth of 0 corresponds to the chain tip.
|
||||
pub fn note_commitment_tree_root(&self, checkpoint_depth: usize) -> Option<MerkleHashOrchard> {
|
||||
self.witness_tree.root(checkpoint_depth)
|
||||
}
|
||||
|
||||
/// Fetches the information necessary to spend the note at the given `OutPoint`,
|
||||
/// relative to the current root known to the wallet of the Orchard commitment tree.
|
||||
/// relative to the specified root of the Orchard note commitment tree.
|
||||
///
|
||||
/// Returns `None` if the `OutPoint` is not known to the wallet, or the Orchard bundle
|
||||
/// containing the note has not been passed to `Wallet::append_bundle_commitments`.
|
||||
/// containing the note had not been passed to `Wallet::append_bundle_commitments` at
|
||||
/// the specified checkpoint depth.
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
pub fn get_spend_info(
|
||||
&self,
|
||||
outpoint: OutPoint,
|
||||
as_of_root: MerkleHashOrchard,
|
||||
) -> Result<OrchardSpendInfo, SpendRetrievalError> {
|
||||
// TODO: Take `confirmations` parameter and obtain the Merkle path to the root at
|
||||
// that checkpoint, not the latest root.
|
||||
|
@ -738,8 +744,8 @@ impl Wallet {
|
|||
|
||||
let path = self
|
||||
.witness_tree
|
||||
.authentication_path(*position)
|
||||
.expect("wallet always has paths to positioned notes");
|
||||
.authentication_path(*position, &as_of_root)
|
||||
.ok_or(SpendRetrievalError::WitnessNotAvailableAtRoot(as_of_root))?;
|
||||
|
||||
Ok(OrchardSpendInfo::from_parts(
|
||||
fvk.clone(),
|
||||
|
@ -939,7 +945,9 @@ pub extern "C" fn orchard_wallet_commitment_tree_root(
|
|||
let wallet = unsafe { wallet.as_ref() }.expect("Wallet pointer may not be null");
|
||||
let root_ret = unsafe { root_ret.as_mut() }.expect("Cannot return to the null pointer.");
|
||||
|
||||
*root_ret = wallet.note_commitment_tree_root().to_bytes();
|
||||
// there is always a valid note commitment tree root at depth 0
|
||||
// (it may be the empty root)
|
||||
*root_ret = wallet.note_commitment_tree_root(0).unwrap().to_bytes();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1213,13 +1221,23 @@ pub extern "C" fn orchard_wallet_get_spend_info(
|
|||
wallet: *const Wallet,
|
||||
txid: *const [c_uchar; 32],
|
||||
action_idx: usize,
|
||||
as_of_root: *const [c_uchar; 32],
|
||||
) -> *mut OrchardSpendInfo {
|
||||
let wallet = unsafe { wallet.as_ref() }.expect("Wallet pointer may not be null.");
|
||||
let txid = TxId::from_bytes(*unsafe { txid.as_ref() }.expect("txid may not be null."));
|
||||
let as_of_root = MerkleHashOrchard::from_bytes(
|
||||
unsafe { as_of_root.as_ref() }.expect("note commitment tree root may not be null."),
|
||||
);
|
||||
|
||||
let outpoint = OutPoint { txid, action_idx };
|
||||
|
||||
match wallet.get_spend_info(outpoint) {
|
||||
let as_of_root = if as_of_root.is_some().into() {
|
||||
Ok(as_of_root.unwrap())
|
||||
} else {
|
||||
Err(SpendRetrievalError::InvalidMerkleRoot)
|
||||
};
|
||||
|
||||
match as_of_root.and_then(|root| wallet.get_spend_info(outpoint, root)) {
|
||||
Ok(ret) => Box::into_raw(Box::new(ret)),
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
|
|
|
@ -259,7 +259,8 @@ TransactionBuilder::TransactionBuilder(
|
|||
nHeight(nHeight),
|
||||
keystore(keystore),
|
||||
coinsView(coinsView),
|
||||
cs_coinsView(cs_coinsView)
|
||||
cs_coinsView(cs_coinsView),
|
||||
orchardAnchor(orchardAnchor)
|
||||
{
|
||||
mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
|
||||
|
||||
|
@ -292,6 +293,11 @@ bool TransactionBuilder::SupportsOrchard() const {
|
|||
return orchardBuilder.has_value();
|
||||
}
|
||||
|
||||
std::optional<uint256> TransactionBuilder::GetOrchardAnchor() const {
|
||||
return orchardAnchor;
|
||||
}
|
||||
|
||||
|
||||
bool TransactionBuilder::AddOrchardSpend(
|
||||
libzcash::OrchardSpendingKey sk,
|
||||
orchard::SpendInfo spendInfo)
|
||||
|
|
|
@ -260,6 +260,7 @@ private:
|
|||
CCriticalSection* cs_coinsView;
|
||||
CMutableTransaction mtx;
|
||||
CAmount fee = 10000;
|
||||
std::optional<uint256> orchardAnchor;
|
||||
std::optional<orchard::Builder> orchardBuilder;
|
||||
CAmount valueBalanceOrchard = 0;
|
||||
|
||||
|
@ -297,6 +298,7 @@ public:
|
|||
cs_coinsView(std::move(builder.cs_coinsView)),
|
||||
mtx(std::move(builder.mtx)),
|
||||
fee(std::move(builder.fee)),
|
||||
orchardAnchor(std::move(builder.orchardAnchor)),
|
||||
orchardBuilder(std::move(builder.orchardBuilder)),
|
||||
valueBalanceOrchard(std::move(builder.valueBalanceOrchard)),
|
||||
spends(std::move(builder.spends)),
|
||||
|
@ -337,6 +339,8 @@ public:
|
|||
|
||||
bool SupportsOrchard() const;
|
||||
|
||||
std::optional<uint256> GetOrchardAnchor() const;
|
||||
|
||||
bool AddOrchardSpend(
|
||||
libzcash::OrchardSpendingKey sk,
|
||||
orchard::SpendInfo spendInfo);
|
||||
|
|
|
@ -327,7 +327,11 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
std::vector<std::optional<SaplingWitness>> witnesses;
|
||||
{
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
pwalletMain->GetSaplingNoteWitnesses(saplingOPs, witnesses, anchor);
|
||||
if (!pwalletMain->GetSaplingNoteWitnesses(saplingOPs, nAnchorConfirmations, witnesses, anchor)) {
|
||||
// This error should not appear once we're nAnchorConfirmations blocks past
|
||||
// Sapling activation.
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Insufficient Sapling witnesses.");
|
||||
};
|
||||
}
|
||||
|
||||
// Add Sapling spends
|
||||
|
@ -447,7 +451,11 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
std::vector<JSOutPoint> vOutPoints = {jso};
|
||||
uint256 inputAnchor;
|
||||
std::vector<std::optional<SproutWitness>> vInputWitnesses;
|
||||
pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor);
|
||||
if (!pwalletMain->GetSproutNoteWitnesses(vOutPoints, nAnchorConfirmations, vInputWitnesses, inputAnchor)) {
|
||||
// This error should not appear once we're nAnchorConfirmations blocks past
|
||||
// Sprout activation.
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Insufficient Sprout witnesses.");
|
||||
};
|
||||
jsopWitnessAnchorMap[jso.ToString()] = MergeToAddressWitnessAnchorData{vInputWitnesses[0], inputAnchor};
|
||||
}
|
||||
}
|
||||
|
@ -752,7 +760,11 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInf
|
|||
uint256 anchor;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pwalletMain->GetSproutNoteWitnesses(outPoints, witnesses, anchor);
|
||||
if (!pwalletMain->GetSproutNoteWitnesses(outPoints, nAnchorConfirmations, witnesses, anchor)) {
|
||||
// This error should not appear once we're nAnchorConfirmations blocks past
|
||||
// Sprout activation.
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Insufficient Sprout witnesses.");
|
||||
}
|
||||
}
|
||||
return perform_joinsplit(info, witnesses, anchor);
|
||||
}
|
||||
|
|
|
@ -137,12 +137,15 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
|
|||
libzcash::SproutSpendingKey sproutSk;
|
||||
pwalletMain->GetSproutSpendingKey(sproutEntry.address, sproutSk);
|
||||
std::vector<JSOutPoint> vOutPoints = {sproutEntry.jsop};
|
||||
// Each migration transaction SHOULD specify an anchor at height N-10
|
||||
// Each migration transaction uses the anchor at height N-nAnchorConfirmations
|
||||
// for each Sprout JoinSplit description
|
||||
// TODO: the above functionality (in comment) is not implemented in zcashd
|
||||
uint256 inputAnchor;
|
||||
std::vector<std::optional<SproutWitness>> vInputWitnesses;
|
||||
pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor);
|
||||
if (!pwalletMain->GetSproutNoteWitnesses(vOutPoints, nAnchorConfirmations, vInputWitnesses, inputAnchor)) {
|
||||
// This error should not appear once we're nAnchorConfirmations blocks past
|
||||
// Sprout activation.
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Insufficient Sprout witnesses.");
|
||||
}
|
||||
builder.AddSproutInput(sproutSk, sproutEntry.note, vInputWitnesses[0].value());
|
||||
// Send change to the address of the first input
|
||||
if (!changeAddr.has_value()) {
|
||||
|
|
|
@ -48,11 +48,12 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
|||
ZTXOSelector ztxoSelector,
|
||||
std::vector<SendManyRecipient> recipients,
|
||||
int minDepth,
|
||||
unsigned int anchorDepth,
|
||||
TransactionStrategy strategy,
|
||||
CAmount fee,
|
||||
UniValue contextInfo) :
|
||||
builder_(std::move(builder)), ztxoSelector_(ztxoSelector), recipients_(recipients),
|
||||
mindepth_(minDepth), strategy_(strategy), fee_(fee),
|
||||
mindepth_(minDepth), anchordepth_(anchorDepth), strategy_(strategy), fee_(fee),
|
||||
contextinfo_(contextInfo)
|
||||
{
|
||||
assert(fee_ >= 0);
|
||||
|
@ -496,8 +497,14 @@ uint256 AsyncRPCOperation_sendmany::main_impl() {
|
|||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> orchardSpendInfo;
|
||||
{
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
pwalletMain->GetSaplingNoteWitnesses(saplingOutPoints, witnesses, anchor);
|
||||
orchardSpendInfo = pwalletMain->GetOrchardSpendInfo(spendable.orchardNoteMetadata);
|
||||
if (!pwalletMain->GetSaplingNoteWitnesses(saplingOutPoints, anchordepth_, witnesses, anchor)) {
|
||||
// This error should not appear once we're nAnchorConfirmations blocks past
|
||||
// Sapling activation.
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Insufficient Sapling witnesses.");
|
||||
}
|
||||
if (builder_.GetOrchardAnchor().has_value()) {
|
||||
orchardSpendInfo = pwalletMain->GetOrchardSpendInfo(spendable.orchardNoteMetadata, builder_.GetOrchardAnchor().value());
|
||||
}
|
||||
}
|
||||
|
||||
// Add Orchard spends
|
||||
|
@ -582,7 +589,11 @@ uint256 AsyncRPCOperation_sendmany::main_impl() {
|
|||
|
||||
// inputAnchor is not needed by builder_.AddSproutInput as it is for Sapling.
|
||||
uint256 inputAnchor;
|
||||
pwalletMain->GetSproutNoteWitnesses(vOutPoints, vSproutWitnesses, inputAnchor);
|
||||
if (!pwalletMain->GetSproutNoteWitnesses(vOutPoints, anchordepth_, vSproutWitnesses, inputAnchor)) {
|
||||
// This error should not appear once we're nAnchorConfirmations blocks past
|
||||
// Sprout activation.
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Insufficient Sprout witnesses.");
|
||||
}
|
||||
}
|
||||
|
||||
// Add Sprout spends
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
ZTXOSelector ztxoSelector,
|
||||
std::vector<SendManyRecipient> recipients,
|
||||
int minDepth,
|
||||
unsigned int anchorDepth,
|
||||
TransactionStrategy strategy,
|
||||
CAmount fee = DEFAULT_FEE,
|
||||
UniValue contextInfo = NullUniValue);
|
||||
|
@ -72,6 +73,7 @@ private:
|
|||
ZTXOSelector ztxoSelector_;
|
||||
std::vector<SendManyRecipient> recipients_;
|
||||
int mindepth_{1};
|
||||
unsigned int anchordepth_{nAnchorConfirmations};
|
||||
CAmount fee_;
|
||||
UniValue contextinfo_; // optional data to include in return value from getStatus()
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
|
|||
|
||||
// If we attempt to get spend info now, it will fail because the note hasn't
|
||||
// been witnessed in the Orchard commitment tree.
|
||||
EXPECT_THROW(wallet.GetSpendInfo(notes), std::logic_error);
|
||||
EXPECT_THROW(wallet.GetSpendInfo(notes, wallet.GetLatestAnchor()), std::logic_error);
|
||||
|
||||
// Append the bundle to the wallet's commitment tree.
|
||||
CBlock fakeBlock;
|
||||
|
@ -119,7 +119,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
|
|||
ASSERT_TRUE(wallet.AppendNoteCommitments(2, fakeBlock));
|
||||
|
||||
// Now we can get spend info for the note.
|
||||
auto spendInfo = wallet.GetSpendInfo(notes);
|
||||
auto spendInfo = wallet.GetSpendInfo(notes, wallet.GetLatestAnchor());
|
||||
EXPECT_EQ(spendInfo[0].second.Value(), 40000);
|
||||
|
||||
// Get the root of the commitment tree.
|
||||
|
|
|
@ -288,7 +288,7 @@ TEST(WalletRPCTests, RPCZsendmanyTaddrToSapling)
|
|||
auto selector = pwalletMain->ZTXOSelectorForAddress(taddr, true, false).value();
|
||||
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, pa, 1*COIN, "ABCD") };
|
||||
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedSenders);
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 0, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 0, 0, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
|
||||
|
||||
// Enable test mode so tx is not sent
|
||||
|
@ -350,4 +350,4 @@ TEST(WalletRPCTests, RPCZsendmanyTaddrToSapling)
|
|||
// Revert to default
|
||||
RegtestDeactivateSapling();
|
||||
UnloadGlobalWallet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,17 +115,19 @@ std::pair<JSOutPoint, SaplingOutPoint> CreateValidBlock(TestWallet& wallet,
|
|||
return std::make_pair(jsoutpt, saplingNotes[0]);
|
||||
}
|
||||
|
||||
std::pair<uint256, uint256> GetWitnessesAndAnchors(TestWallet& wallet,
|
||||
std::vector<JSOutPoint>& sproutNotes,
|
||||
std::vector<SaplingOutPoint>& saplingNotes,
|
||||
std::pair<uint256, uint256> GetWitnessesAndAnchors(
|
||||
const TestWallet& wallet,
|
||||
const std::vector<JSOutPoint>& sproutNotes,
|
||||
const std::vector<SaplingOutPoint>& saplingNotes,
|
||||
const unsigned int anchorDepth,
|
||||
std::vector<std::optional<SproutWitness>>& sproutWitnesses,
|
||||
std::vector<std::optional<SaplingWitness>>& saplingWitnesses) {
|
||||
sproutWitnesses.clear();
|
||||
saplingWitnesses.clear();
|
||||
uint256 sproutAnchor;
|
||||
uint256 saplingAnchor;
|
||||
wallet.GetSproutNoteWitnesses(sproutNotes, sproutWitnesses, sproutAnchor);
|
||||
wallet.GetSaplingNoteWitnesses(saplingNotes, saplingWitnesses, saplingAnchor);
|
||||
assert(wallet.GetSproutNoteWitnesses(sproutNotes, anchorDepth, sproutWitnesses, sproutAnchor));
|
||||
assert(wallet.GetSaplingNoteWitnesses(saplingNotes, anchorDepth, saplingWitnesses, saplingAnchor));
|
||||
return std::make_pair(sproutAnchor, saplingAnchor);
|
||||
}
|
||||
|
||||
|
@ -884,8 +886,8 @@ TEST(WalletTests, GetConflictedOrchardNotes) {
|
|||
auto recipient2 = ivk.Address(j2);
|
||||
|
||||
// Generate tx to spend note A
|
||||
auto noteToSpend = std::move(wallet.GetOrchardSpendInfo(orchardEntries)[0]);
|
||||
auto builder2 = TransactionBuilder(consensusParams, 2, orchardTree.root());
|
||||
auto noteToSpend = std::move(wallet.GetOrchardSpendInfo(orchardEntries, orchardTree.root())[0]);
|
||||
builder2.AddOrchardSpend(std::move(noteToSpend.first), std::move(noteToSpend.second));
|
||||
auto maybeTx2 = builder2.Build();
|
||||
EXPECT_TRUE(maybeTx2.IsTx());
|
||||
|
@ -897,7 +899,7 @@ TEST(WalletTests, GetConflictedOrchardNotes) {
|
|||
CWalletTx wtx2 {&wallet, tx2};
|
||||
|
||||
// Generate conflicting tx to spend note A
|
||||
auto noteToSpend2 = std::move(wallet.GetOrchardSpendInfo(orchardEntries)[0]);
|
||||
auto noteToSpend2 = std::move(wallet.GetOrchardSpendInfo(orchardEntries, orchardTree.root())[0]);
|
||||
auto builder3 = TransactionBuilder(consensusParams, 2, orchardTree.root());
|
||||
builder3.AddOrchardSpend(std::move(noteToSpend2.first), std::move(noteToSpend2.second));
|
||||
auto maybeTx3 = builder3.Build();
|
||||
|
@ -1374,7 +1376,7 @@ TEST(WalletTests, CachedWitnessesEmptyChain) {
|
|||
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||
|
||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, nAnchorConfirmations, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) sproutWitnesses[1]);
|
||||
|
@ -1382,7 +1384,7 @@ TEST(WalletTests, CachedWitnessesEmptyChain) {
|
|||
|
||||
wallet.LoadWalletTx(wtx);
|
||||
|
||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, nAnchorConfirmations, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) sproutWitnesses[1]);
|
||||
|
@ -1392,16 +1394,52 @@ TEST(WalletTests, CachedWitnessesEmptyChain) {
|
|||
block.vtx.push_back(wtx);
|
||||
CBlockIndex index(block);
|
||||
MerkleFrontiers frontiers;
|
||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index, &block, frontiers, true);
|
||||
const auto& params = Params().GetConsensus();
|
||||
wallet.IncrementNoteWitnesses(params, &index, &block, frontiers, true);
|
||||
|
||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
// this death will occur because there will not be sufficient Sprout witnesses to reach the
|
||||
// default anchor depth
|
||||
EXPECT_DEATH(::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, nAnchorConfirmations, sproutWitnesses, saplingWitnesses),
|
||||
"GetSproutNoteWitnesses");
|
||||
|
||||
// add another block; we still don't have enough witnesses
|
||||
{
|
||||
CBlock another_block;
|
||||
CBlockIndex another_index(another_block);
|
||||
another_index.nHeight = 1;
|
||||
wallet.IncrementNoteWitnesses(params, &another_index, &another_block, frontiers, true);
|
||||
}
|
||||
|
||||
EXPECT_DEATH(::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, nAnchorConfirmations, sproutWitnesses, saplingWitnesses),
|
||||
"GetSproutNoteWitnesses");
|
||||
|
||||
for (int i = 2; i <= 8; i++) {
|
||||
CBlock another_block;
|
||||
CBlockIndex another_index(another_block);
|
||||
another_index.nHeight = i;
|
||||
wallet.IncrementNoteWitnesses(params, &another_index, &another_block, frontiers, true);
|
||||
}
|
||||
|
||||
CBlock last_block;
|
||||
CBlockIndex last_index(last_block);
|
||||
last_index.nHeight = 9;
|
||||
wallet.IncrementNoteWitnesses(params, &last_index, &last_block, frontiers, true);
|
||||
|
||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, nAnchorConfirmations, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_TRUE((bool) sproutWitnesses[0]);
|
||||
EXPECT_TRUE((bool) sproutWitnesses[1]);
|
||||
EXPECT_TRUE((bool) saplingWitnesses[0]);
|
||||
|
||||
for (int i = 9; i >= 1; i--) {
|
||||
CBlock another_block;
|
||||
CBlockIndex another_index(another_block);
|
||||
another_index.nHeight = i;
|
||||
wallet.DecrementNoteWitnesses(params, &another_index);
|
||||
}
|
||||
|
||||
// Until #1302 is implemented, this should trigger an assertion
|
||||
EXPECT_DEATH(wallet.DecrementNoteWitnesses(Params().GetConsensus(), &index),
|
||||
EXPECT_DEATH(wallet.DecrementNoteWitnesses(params, &index),
|
||||
".*nWitnessCacheSize > 0.*");
|
||||
}
|
||||
|
||||
|
@ -1429,7 +1467,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
|||
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||
|
||||
anchors1 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
anchors1 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
EXPECT_NE(anchors1.first, anchors1.second);
|
||||
}
|
||||
|
||||
|
@ -1451,7 +1489,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
|||
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||
|
||||
GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) saplingWitnesses[0]);
|
||||
|
@ -1465,7 +1503,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
|||
MerkleFrontiers frontiers2 = { .sprout = frontiers.sprout, .sapling = frontiers.sapling };
|
||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers2, true);
|
||||
|
||||
auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
EXPECT_NE(anchors2.first, anchors2.second);
|
||||
|
||||
EXPECT_TRUE((bool) sproutWitnesses[0]);
|
||||
|
@ -1475,7 +1513,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
|||
|
||||
// Decrementing should give us the previous anchor
|
||||
wallet.DecrementNoteWitnesses(Params().GetConsensus(), &index2);
|
||||
auto anchors3 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors3 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) saplingWitnesses[0]);
|
||||
|
@ -1485,7 +1523,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
|||
|
||||
// Re-incrementing with the same block should give the same result
|
||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers, true);
|
||||
auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
EXPECT_NE(anchors4.first, anchors4.second);
|
||||
|
||||
EXPECT_TRUE((bool) sproutWitnesses[0]);
|
||||
|
@ -1498,7 +1536,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
|||
std::vector<std::optional<SproutWitness>> sproutWitnesses5;
|
||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses5;
|
||||
|
||||
auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses5, saplingWitnesses5);
|
||||
auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses5, saplingWitnesses5);
|
||||
EXPECT_NE(anchors5.first, anchors5.second);
|
||||
|
||||
EXPECT_EQ(sproutWitnesses, sproutWitnesses5);
|
||||
|
@ -1540,7 +1578,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
|||
std::vector<SaplingOutPoint> saplingNotes {outpts.second};
|
||||
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||
anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1561,7 +1599,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
|||
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||
|
||||
auto anchors3 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors3 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) saplingWitnesses[0]);
|
||||
|
@ -1570,7 +1608,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
|||
// should give us the previous anchor
|
||||
wallet.DecrementNoteWitnesses(Params().GetConsensus(), &index2);
|
||||
|
||||
auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) saplingWitnesses[0]);
|
||||
|
@ -1581,7 +1619,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
|||
// Re-incrementing with the same block should give the same result
|
||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers, true);
|
||||
|
||||
auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) saplingWitnesses[0]);
|
||||
|
@ -1623,7 +1661,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
|||
sproutNotes.push_back(outpts.first);
|
||||
saplingNotes.push_back(outpts.second);
|
||||
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
for (size_t j = 0; j <= i; j++) {
|
||||
EXPECT_TRUE((bool) sproutWitnesses[j]);
|
||||
EXPECT_TRUE((bool) saplingWitnesses[j]);
|
||||
|
@ -1638,7 +1676,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
|||
MerkleFrontiers riPrevFrontiers{riFrontiers};
|
||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &(indices[i]), &(blocks[i]), riFrontiers, true);
|
||||
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
for (size_t j = 0; j < numBlocks; j++) {
|
||||
EXPECT_TRUE((bool) sproutWitnesses[j]);
|
||||
EXPECT_TRUE((bool) saplingWitnesses[j]);
|
||||
|
@ -1652,7 +1690,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
|||
{
|
||||
wallet.DecrementNoteWitnesses(Params().GetConsensus(), &(indices[i]));
|
||||
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
for (size_t j = 0; j < numBlocks; j++) {
|
||||
EXPECT_TRUE((bool) sproutWitnesses[j]);
|
||||
EXPECT_TRUE((bool) saplingWitnesses[j]);
|
||||
|
@ -1664,7 +1702,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
|||
|
||||
{
|
||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &(indices[i]), &(blocks[i]), riPrevFrontiers, true);
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
for (size_t j = 0; j < numBlocks; j++) {
|
||||
EXPECT_TRUE((bool) sproutWitnesses[j]);
|
||||
EXPECT_TRUE((bool) saplingWitnesses[j]);
|
||||
|
@ -1724,7 +1762,7 @@ TEST(WalletTests, ClearNoteWitnessCache) {
|
|||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||
|
||||
// Before clearing, we should have a witness for one note
|
||||
GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
EXPECT_TRUE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) sproutWitnesses[1]);
|
||||
EXPECT_TRUE((bool) saplingWitnesses[0]);
|
||||
|
@ -1735,7 +1773,7 @@ TEST(WalletTests, ClearNoteWitnessCache) {
|
|||
|
||||
// After clearing, we should not have a witness for either note
|
||||
wallet.ClearNoteWitnessCache();
|
||||
auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||
auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, 1, sproutWitnesses, saplingWitnesses);
|
||||
EXPECT_FALSE((bool) sproutWitnesses[0]);
|
||||
EXPECT_FALSE((bool) sproutWitnesses[1]);
|
||||
EXPECT_FALSE((bool) saplingWitnesses[0]);
|
||||
|
|
|
@ -13,14 +13,16 @@ std::optional<libzcash::OrchardSpendingKey> OrchardWallet::GetSpendingKeyForAddr
|
|||
}
|
||||
|
||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> OrchardWallet::GetSpendInfo(
|
||||
const std::vector<OrchardNoteMetadata>& noteMetadata) const
|
||||
const std::vector<OrchardNoteMetadata>& noteMetadata,
|
||||
uint256 anchor) const
|
||||
{
|
||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> result;
|
||||
for (const auto& note : noteMetadata) {
|
||||
auto pSpendInfo = orchard_wallet_get_spend_info(
|
||||
inner.get(),
|
||||
note.GetOutPoint().hash.begin(),
|
||||
note.GetOutPoint().n);
|
||||
note.GetOutPoint().n,
|
||||
anchor.begin());
|
||||
if (pSpendInfo == nullptr) {
|
||||
throw std::logic_error("Called OrchardWallet::GetSpendInfo with unknown outpoint");
|
||||
} else {
|
||||
|
|
|
@ -442,7 +442,8 @@ public:
|
|||
}
|
||||
|
||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> GetSpendInfo(
|
||||
const std::vector<OrchardNoteMetadata>& noteMetadata) const;
|
||||
const std::vector<OrchardNoteMetadata>& noteMetadata,
|
||||
uint256 anchor) const;
|
||||
|
||||
void GarbageCollect() {
|
||||
orchard_wallet_gc_note_commitment_tree(inner.get());
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
@ -4942,7 +4943,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
" \"amount\":amount (numeric, required) The numeric amount in " + CURRENCY_UNIT + " is the value\n"
|
||||
" \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
|
||||
" }, ... ]\n"
|
||||
"3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
|
||||
"3. minconf (numeric, optional, default=" + strprintf("%u", DEFAULT_NOTE_CONFIRMATIONS) + ") Only use funds confirmed at least this many times.\n"
|
||||
"4. fee (numeric, optional, default=" + strprintf("%s", FormatMoney(DEFAULT_FEE)) + ") The fee amount to attach to this transaction.\n"
|
||||
"5. privacyPolicy (string, optional, default=\"LegacyCompat\") Policy for what information leakage is acceptable.\n"
|
||||
" One of the following strings:\n"
|
||||
|
@ -5154,7 +5155,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
}
|
||||
|
||||
// Minimum confirmations
|
||||
int nMinDepth = 1;
|
||||
int nMinDepth = DEFAULT_NOTE_CONFIRMATIONS;
|
||||
if (params.size() > 2) {
|
||||
nMinDepth = params[2].get_int();
|
||||
}
|
||||
|
@ -5199,12 +5200,12 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
UniValue contextInfo = o;
|
||||
|
||||
std::optional<uint256> orchardAnchor;
|
||||
if (!ztxoSelector.SelectsSprout()) {
|
||||
// Allow Orchard recipients by setting an Orchard anchor.
|
||||
// TODO: Add an orchardAnchorHeight field to ZTXOSelector so we can ensure the
|
||||
// same anchor is used for witnesses of any selected Orchard note.
|
||||
auto orchardAnchorHeight = nextBlockHeight - nOrchardAnchorConfirmations;
|
||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||
auto nAnchorDepth = std::min((unsigned int) nMinDepth, nAnchorConfirmations);
|
||||
if (!ztxoSelector.SelectsSprout() && nAnchorDepth > 0) {
|
||||
auto orchardAnchorHeight = nextBlockHeight - nAnchorDepth;
|
||||
if (chainparams.GetConsensus().NetworkUpgradeActive(orchardAnchorHeight, Consensus::UPGRADE_NU5)) {
|
||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||
}
|
||||
}
|
||||
TransactionBuilder builder(chainparams.GetConsensus(), nextBlockHeight, orchardAnchor, pwalletMain);
|
||||
|
||||
|
@ -5212,7 +5213,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
|
||||
std::shared_ptr<AsyncRPCOperation> operation(
|
||||
new AsyncRPCOperation_sendmany(
|
||||
std::move(builder), ztxoSelector, recipients, nMinDepth, strategy, nFee, contextInfo)
|
||||
std::move(builder), ztxoSelector, recipients, nMinDepth, nAnchorDepth, strategy, nFee, contextInfo)
|
||||
);
|
||||
q->addOperation(operation);
|
||||
AsyncRPCOperationId operationId = operation->getId();
|
||||
|
@ -5560,8 +5561,10 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
std::optional<uint256> orchardAnchor;
|
||||
if (canopyActive) {
|
||||
// Allow Orchard recipients by setting an Orchard anchor.
|
||||
auto orchardAnchorHeight = nextBlockHeight - nOrchardAnchorConfirmations;
|
||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||
auto orchardAnchorHeight = nextBlockHeight - nAnchorConfirmations;
|
||||
if (Params().GetConsensus().NetworkUpgradeActive(orchardAnchorHeight, Consensus::UPGRADE_NU5)) {
|
||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||
}
|
||||
}
|
||||
TransactionBuilder builder = TransactionBuilder(
|
||||
Params().GetConsensus(), nextBlockHeight, orchardAnchor, pwalletMain);
|
||||
|
@ -5895,7 +5898,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
useAnySprout || useAnySapling ?
|
||||
std::nullopt :
|
||||
std::optional(NoteFilter::ForPaymentAddresses(zaddrs));
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, orchardEntries, noteFilter);
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, orchardEntries, noteFilter, nAnchorConfirmations);
|
||||
|
||||
// If Sapling is not active, do not allow sending from a sapling addresses.
|
||||
if (!saplingActive && saplingEntries.size() > 0) {
|
||||
|
@ -6037,8 +6040,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
// Allow Orchard recipients by setting an Orchard anchor.
|
||||
// TODO: Add an orchardAnchorHeight field to ZTXOSelector so we can ensure the
|
||||
// same anchor is used for witnesses of any selected Orchard note.
|
||||
auto orchardAnchorHeight = nextBlockHeight - nOrchardAnchorConfirmations;
|
||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||
auto orchardAnchorHeight = nextBlockHeight - nAnchorConfirmations;
|
||||
if (Params().GetConsensus().NetworkUpgradeActive(orchardAnchorHeight, Consensus::UPGRADE_NU5)) {
|
||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||
}
|
||||
}
|
||||
builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, orchardAnchor, pwalletMain);
|
||||
}
|
||||
|
|
|
@ -1237,7 +1237,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
|
|||
TransactionBuilder builder(consensusParams, nHeight + 1, std::nullopt, pwalletMain);
|
||||
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, zaddr1, 100*COIN, "DEADBEEF") };
|
||||
TransactionStrategy strategy;
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy));
|
||||
operation->main();
|
||||
BOOST_CHECK(operation->isFailed());
|
||||
std::string msg = operation->getErrorMessage();
|
||||
|
@ -1250,7 +1250,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
|
|||
TransactionBuilder builder(consensusParams, nHeight + 1, std::nullopt, pwalletMain);
|
||||
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, taddr1, 100*COIN, "DEADBEEF") };
|
||||
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedRecipients);
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy));
|
||||
operation->main();
|
||||
BOOST_CHECK(operation->isFailed());
|
||||
std::string msg = operation->getErrorMessage();
|
||||
|
@ -1263,7 +1263,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
|
|||
TransactionBuilder builder(consensusParams, nHeight + 1, std::nullopt, pwalletMain);
|
||||
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, zaddr1, 100*COIN, "DEADBEEF") };
|
||||
TransactionStrategy strategy;
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
|
||||
TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
|||
bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE;
|
||||
bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS;
|
||||
bool fPayAtLeastCustomFee = true;
|
||||
unsigned int nOrchardAnchorConfirmations = DEFAULT_ORCHARD_ANCHOR_CONFIRMATIONS;
|
||||
unsigned int nAnchorConfirmations = DEFAULT_ANCHOR_CONFIRMATIONS;
|
||||
|
||||
const char * DEFAULT_WALLET_DAT = "wallet.dat";
|
||||
|
||||
|
@ -3529,9 +3529,10 @@ bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void CWallet::GetSproutNoteWitnesses(const std::vector<JSOutPoint>& notes,
|
||||
bool CWallet::GetSproutNoteWitnesses(const std::vector<JSOutPoint>& notes,
|
||||
unsigned int confirmations,
|
||||
std::vector<std::optional<SproutWitness>>& witnesses,
|
||||
uint256 &final_anchor)
|
||||
uint256 &final_anchor) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
witnesses.resize(notes.size());
|
||||
|
@ -3539,9 +3540,16 @@ void CWallet::GetSproutNoteWitnesses(const std::vector<JSOutPoint>& notes,
|
|||
int i = 0;
|
||||
for (JSOutPoint note : notes) {
|
||||
if (mapWallet.count(note.hash) &&
|
||||
mapWallet[note.hash].mapSproutNoteData.count(note) &&
|
||||
mapWallet[note.hash].mapSproutNoteData[note].witnesses.size() > 0) {
|
||||
witnesses[i] = mapWallet[note.hash].mapSproutNoteData[note].witnesses.front();
|
||||
mapWallet.at(note.hash).mapSproutNoteData.count(note) &&
|
||||
mapWallet.at(note.hash).mapSproutNoteData.at(note).witnesses.size() > 0) {
|
||||
auto noteWitnesses = mapWallet.at(note.hash).mapSproutNoteData.at(note).witnesses;
|
||||
auto it = noteWitnesses.cbegin(), end = noteWitnesses.cend();
|
||||
for (int i = 1; i < confirmations; i++) {
|
||||
if (it == end) return false;
|
||||
++it;
|
||||
}
|
||||
if (it == end) return false;
|
||||
witnesses[i] = *it;
|
||||
if (!rt) {
|
||||
rt = witnesses[i]->root();
|
||||
} else {
|
||||
|
@ -3554,11 +3562,13 @@ void CWallet::GetSproutNoteWitnesses(const std::vector<JSOutPoint>& notes,
|
|||
if (rt) {
|
||||
final_anchor = *rt;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
|
||||
bool CWallet::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
|
||||
unsigned int confirmations,
|
||||
std::vector<std::optional<SaplingWitness>>& witnesses,
|
||||
uint256 &final_anchor)
|
||||
uint256 &final_anchor) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
witnesses.resize(notes.size());
|
||||
|
@ -3566,9 +3576,16 @@ void CWallet::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
|
|||
int i = 0;
|
||||
for (SaplingOutPoint note : notes) {
|
||||
if (mapWallet.count(note.hash) &&
|
||||
mapWallet[note.hash].mapSaplingNoteData.count(note) &&
|
||||
mapWallet[note.hash].mapSaplingNoteData[note].witnesses.size() > 0) {
|
||||
witnesses[i] = mapWallet[note.hash].mapSaplingNoteData[note].witnesses.front();
|
||||
mapWallet.at(note.hash).mapSaplingNoteData.count(note) &&
|
||||
mapWallet.at(note.hash).mapSaplingNoteData.at(note).witnesses.size() > 0) {
|
||||
auto noteWitnesses = mapWallet.at(note.hash).mapSaplingNoteData.at(note).witnesses;
|
||||
auto it = noteWitnesses.cbegin(), end = noteWitnesses.cend();
|
||||
for (int i = 1; i < confirmations; i++) {
|
||||
if (it == end) return false;
|
||||
++it;
|
||||
}
|
||||
if (it == end) return false;
|
||||
witnesses[i] = *it;
|
||||
if (!rt) {
|
||||
rt = witnesses[i]->root();
|
||||
} else {
|
||||
|
@ -3581,13 +3598,15 @@ void CWallet::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
|
|||
if (rt) {
|
||||
final_anchor = *rt;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> CWallet::GetOrchardSpendInfo(
|
||||
const std::vector<OrchardNoteMetadata>& orchardNoteMetadata) const
|
||||
const std::vector<OrchardNoteMetadata>& orchardNoteMetadata,
|
||||
uint256 anchor) const
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
return orchardWallet.GetSpendInfo(orchardNoteMetadata);
|
||||
return orchardWallet.GetSpendInfo(orchardNoteMetadata, anchor);
|
||||
}
|
||||
|
||||
isminetype CWallet::IsMine(const CTxIn &txin) const
|
||||
|
@ -6574,12 +6593,15 @@ bool CWallet::ParameterInteraction(const CChainParams& params)
|
|||
return UIError(_("-migrationdestaddress must be a valid Sapling address."));
|
||||
}
|
||||
}
|
||||
if (mapArgs.count("-orchardanchorconfirmations")) {
|
||||
int64_t confirmations = atoi64(mapArgs["-orchardanchorconfirmations"]);
|
||||
if (mapArgs.count("-anchorconfirmations")) {
|
||||
int64_t confirmations = atoi64(mapArgs["-anchorconfirmations"]);
|
||||
if (confirmations < 1) {
|
||||
return UIError(strprintf(_("Invalid value for -orchardanchorconfirmations='%u' (must be least 1)"), confirmations));
|
||||
return UIError(strprintf(_("Invalid value for -anchorconfirmations='%u' (must be least 1)"), confirmations));
|
||||
}
|
||||
nOrchardAnchorConfirmations = confirmations;
|
||||
if (confirmations > 100) {
|
||||
return UIError(strprintf(_("Invalid value for -anchorconfirmations='%u' (must be at most 100)"), confirmations));
|
||||
}
|
||||
nAnchorConfirmations = confirmations;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -53,7 +53,7 @@ extern unsigned int nTxConfirmTarget;
|
|||
extern bool bSpendZeroConfChange;
|
||||
extern bool fSendFreeTransactions;
|
||||
extern bool fPayAtLeastCustomFee;
|
||||
extern unsigned int nOrchardAnchorConfirmations;
|
||||
extern unsigned int nAnchorConfirmations;
|
||||
|
||||
static const unsigned int DEFAULT_KEYPOOL_SIZE = 100;
|
||||
//! -paytxfee default
|
||||
|
@ -78,8 +78,10 @@ static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
|
|||
|
||||
//! Amount of entropy used in generation of the mnemonic seed, in bytes.
|
||||
static const size_t WALLET_MNEMONIC_ENTROPY_LENGTH = 32;
|
||||
//! -orchardanchorconfirmations default
|
||||
static const unsigned int DEFAULT_ORCHARD_ANCHOR_CONFIRMATIONS = 1;
|
||||
//! -anchorconfirmations default
|
||||
static const unsigned int DEFAULT_ANCHOR_CONFIRMATIONS = 3;
|
||||
// Default minimum number of confirmations for note selection
|
||||
static const unsigned int DEFAULT_NOTE_CONFIRMATIONS = 10;
|
||||
|
||||
extern const char * DEFAULT_WALLET_DAT;
|
||||
|
||||
|
@ -1778,16 +1780,19 @@ public:
|
|||
bool IsSproutNullifierFromMe(const uint256& nullifier) const;
|
||||
bool IsSaplingNullifierFromMe(const uint256& nullifier) const;
|
||||
|
||||
void GetSproutNoteWitnesses(
|
||||
bool GetSproutNoteWitnesses(
|
||||
const std::vector<JSOutPoint>& notes,
|
||||
unsigned int confirmations,
|
||||
std::vector<std::optional<SproutWitness>>& witnesses,
|
||||
uint256 &final_anchor);
|
||||
void GetSaplingNoteWitnesses(
|
||||
uint256 &final_anchor) const;
|
||||
bool GetSaplingNoteWitnesses(
|
||||
const std::vector<SaplingOutPoint>& notes,
|
||||
unsigned int confirmations,
|
||||
std::vector<std::optional<SaplingWitness>>& witnesses,
|
||||
uint256 &final_anchor);
|
||||
uint256 &final_anchor) const;
|
||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> GetOrchardSpendInfo(
|
||||
const std::vector<OrchardNoteMetadata>& orchardNoteMetadata) const;
|
||||
const std::vector<OrchardNoteMetadata>& orchardNoteMetadata,
|
||||
uint256 anchor) const;
|
||||
|
||||
isminetype IsMine(const CTxIn& txin) const;
|
||||
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
|
||||
|
@ -1966,7 +1971,7 @@ public:
|
|||
std::vector<SaplingNoteEntry>& saplingEntriesRet,
|
||||
std::vector<OrchardNoteMetadata>& orchardNotesRet,
|
||||
const std::optional<NoteFilter>& noteFilter,
|
||||
int minDepth=1,
|
||||
int minDepth,
|
||||
int maxDepth=INT_MAX,
|
||||
bool ignoreSpent=true,
|
||||
bool requireSpendingKey=true,
|
||||
|
|
Loading…
Reference in New Issue