Select Orchard anchors at `-orchardanchorconfirmations` depth.
This changes anchor selection and Orchard authentication path generation to default to select anchors at a the depth specified by the `-orchardanchorconfirmations` CLI argument, with a default anchor selection depth of 10 blocks. If the value of `minconf` used for a particular call to `z_sendmany` is less than the the set number of Orchard anchor confirmations, `minconf` will be used instead for the Orchard anchor confirmations depth, so that the selected anchor will be certain to contain any notes selected to be spent. Fixes #5644
This commit is contained in:
parent
b7d6120b20
commit
63e4addd9a
|
@ -4,9 +4,24 @@ linker = "aarch64-linux-gnu-gcc"
|
||||||
[source.crates-io]
|
[source.crates-io]
|
||||||
replace-with = "vendored-sources"
|
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"]
|
[source."https://github.com/zcash/librustzcash.git"]
|
||||||
git = "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"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."https://github.com/nuttycom/hdwallet.git"]
|
[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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0944d18a9a37691b87733b39c9360c9950af9aa5f97e2455bc108d8eb64fc1c1"
|
checksum = "0944d18a9a37691b87733b39c9360c9950af9aa5f97e2455bc108d8eb64fc1c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec 0.22.3",
|
||||||
"blake2s_simd 0.5.11",
|
"blake2s_simd 0.5.11",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
@ -154,16 +154,6 @@ dependencies = [
|
||||||
"subtle",
|
"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]]
|
[[package]]
|
||||||
name = "bip0039"
|
name = "bip0039"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -190,10 +180,22 @@ version = "0.22.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
|
checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"funty",
|
"funty 1.2.0",
|
||||||
"radium",
|
"radium 0.6.2",
|
||||||
"tap",
|
"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]]
|
[[package]]
|
||||||
|
@ -291,6 +293,12 @@ version = "3.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byte-slice-cast"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
|
@ -428,12 +436,6 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crunchy"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -562,7 +564,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equihash"
|
name = "equihash"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
@ -571,7 +573,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "f4jumble"
|
name = "f4jumble"
|
||||||
version = "0.0.0"
|
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 = [
|
dependencies = [
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
]
|
]
|
||||||
|
@ -582,11 +584,23 @@ version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e"
|
checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec 0.22.3",
|
||||||
"rand_core 0.6.3",
|
"rand_core 0.6.3",
|
||||||
"subtle",
|
"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]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -613,6 +627,12 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
|
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.21"
|
version = "0.3.21"
|
||||||
|
@ -719,11 +739,10 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "halo2_gadgets"
|
name = "halo2_gadgets"
|
||||||
version = "0.1.0-beta.3"
|
version = "0.1.0-beta.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/zcash/halo2.git?rev=0c33fa4e6e41464884765c8fb4cefebafd300ca2#0c33fa4e6e41464884765c8fb4cefebafd300ca2"
|
||||||
checksum = "7524b798b8b3689a198cd87ee1d22fe3ca007a51d35c4093f32d75c0efc30abe"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.7.2",
|
"arrayvec 0.7.2",
|
||||||
"bitvec",
|
"bitvec 0.22.3",
|
||||||
"ff",
|
"ff",
|
||||||
"group",
|
"group",
|
||||||
"halo2_proofs",
|
"halo2_proofs",
|
||||||
|
@ -737,11 +756,9 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "halo2_proofs"
|
name = "halo2_proofs"
|
||||||
version = "0.1.0-beta.4"
|
version = "0.1.0-beta.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/zcash/halo2.git?rev=0c33fa4e6e41464884765c8fb4cefebafd300ca2#0c33fa4e6e41464884765c8fb4cefebafd300ca2"
|
||||||
checksum = "e0240b05b791cccfd6451b010b19711280e63b87f495bd84df0103f35c9139e7"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"bumpalo",
|
|
||||||
"ff",
|
"ff",
|
||||||
"group",
|
"group",
|
||||||
"pasta_curves",
|
"pasta_curves",
|
||||||
|
@ -851,11 +868,30 @@ dependencies = [
|
||||||
"want",
|
"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]]
|
[[package]]
|
||||||
name = "incrementalmerkletree"
|
name = "incrementalmerkletree"
|
||||||
version = "0.3.0-beta.2"
|
version = "0.3.0-beta.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/zcash/incrementalmerkletree.git?rev=f23e3d89507849a24543121839eea6f40b141aff#f23e3d89507849a24543121839eea6f40b141aff"
|
||||||
checksum = "5812f2cfa06a7694b842402e9a100529d80fdc3022ead65ad98ce0af0bcd3311"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -906,7 +942,7 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2e7baec19d4e83f9145d4891178101a604565edff9645770fc979804138b04c"
|
checksum = "e2e7baec19d4e83f9145d4891178101a604565edff9645770fc979804138b04c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec 0.22.3",
|
||||||
"bls12_381",
|
"bls12_381",
|
||||||
"ff",
|
"ff",
|
||||||
"group",
|
"group",
|
||||||
|
@ -1252,11 +1288,10 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orchard"
|
name = "orchard"
|
||||||
version = "0.1.0-beta.3"
|
version = "0.1.0-beta.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/zcash/orchard.git?rev=a30caec124aa6c6e7818b5100293204425c49de3#a30caec124aa6c6e7818b5100293204425c49de3"
|
||||||
checksum = "c3bb8c5f5a0977683b5071650f1e7d91f296e344a796fda585086d5b4b0a74ea"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"bitvec",
|
"bitvec 0.22.3",
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"ff",
|
"ff",
|
||||||
"fpe",
|
"fpe",
|
||||||
|
@ -1294,6 +1329,32 @@ dependencies = [
|
||||||
"group",
|
"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]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
|
@ -1422,6 +1483,27 @@ version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
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]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.37"
|
version = "1.0.37"
|
||||||
|
@ -1462,6 +1544,12 @@ version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
|
checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "radix_trie"
|
name = "radix_trie"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -1680,6 +1768,12 @@ version = "0.1.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hex"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -1930,6 +2024,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -2011,12 +2114,12 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uint"
|
name = "uint"
|
||||||
version = "0.9.1"
|
version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f"
|
checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"crunchy 0.2.2",
|
"crunchy",
|
||||||
"hex",
|
"hex",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
@ -2198,10 +2301,19 @@ dependencies = [
|
||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
|
||||||
|
dependencies = [
|
||||||
|
"tap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_address"
|
name = "zcash_address"
|
||||||
version = "0.0.0"
|
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 = [
|
dependencies = [
|
||||||
"bech32",
|
"bech32",
|
||||||
"bs58",
|
"bs58",
|
||||||
|
@ -2212,7 +2324,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_encoding"
|
name = "zcash_encoding"
|
||||||
version = "0.0.0"
|
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 = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"nonempty",
|
"nonempty",
|
||||||
|
@ -2221,17 +2333,17 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_history"
|
name = "zcash_history"
|
||||||
version = "0.2.0"
|
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 = [
|
dependencies = [
|
||||||
"bigint",
|
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"primitive-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_note_encryption"
|
name = "zcash_note_encryption"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"chacha20",
|
"chacha20",
|
||||||
"chacha20poly1305",
|
"chacha20poly1305",
|
||||||
|
@ -2242,11 +2354,11 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_primitives"
|
name = "zcash_primitives"
|
||||||
version = "0.5.0"
|
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 = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"bip0039",
|
"bip0039",
|
||||||
"bitvec",
|
"bitvec 0.22.3",
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"blake2s_simd 1.0.0",
|
"blake2s_simd 1.0.0",
|
||||||
"bls12_381",
|
"bls12_381",
|
||||||
|
@ -2278,7 +2390,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zcash_proofs"
|
name = "zcash_proofs"
|
||||||
version = "0.5.0"
|
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 = [
|
dependencies = [
|
||||||
"bellman",
|
"bellman",
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
|
|
16
Cargo.toml
16
Cargo.toml
|
@ -84,10 +84,14 @@ panic = 'abort'
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[patch.crates-io]
|
[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" }
|
hdwallet = { git = "https://github.com/nuttycom/hdwallet.git", rev = "9b4c1bdbe0517e3a7a8f285d6048a37d472ba3bc" }
|
||||||
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "f23e3d89507849a24543121839eea6f40b141aff" }
|
||||||
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
orchard = { git = "https://github.com/zcash/orchard.git", rev = "a30caec124aa6c6e7818b5100293204425c49de3" }
|
||||||
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||||
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||||
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "68cbc2bb17b8967c7fb2f6034ac3d6174fc8f19b" }
|
||||||
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "d14e7a707ce01cefcbc82651dad48f002185dded" }
|
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" }
|
||||||
|
|
|
@ -11,6 +11,15 @@ Option handling
|
||||||
(provided that the wallet is enabled and pruning is disabled, and unless
|
(provided that the wallet is enabled and pruning is disabled, and unless
|
||||||
`-rescan=0` is specified explicitly).
|
`-rescan=0` is specified explicitly).
|
||||||
|
|
||||||
|
RPC Interface
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- The default `minconf` value for `z_sendmany` is now 10 confirmations instead
|
||||||
|
of 1.
|
||||||
|
- When spending notes using `z_sendmany`, Orchard anchors are now selected at
|
||||||
|
a depth of 10 blocks instead of at the chain tip. If the `minconf` value is
|
||||||
|
less than 10, `minconf` is used for the anchor selection depth instead.
|
||||||
|
|
||||||
Build system
|
Build system
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
|
@ -89,9 +89,9 @@ class MempoolLimit(BitcoinTestFramework):
|
||||||
print("Checking mempool size reset after block mined...")
|
print("Checking mempool size reset after block mined...")
|
||||||
self.check_mempool_sizes(0)
|
self.check_mempool_sizes(0)
|
||||||
zaddr4 = self.nodes[0].z_getnewaddress('sapling')
|
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)
|
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)
|
wait_and_assert_operationid_status(self.nodes[0], opid5)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ class MempoolTxExpiryTest(BitcoinTestFramework):
|
||||||
zsendamount = Decimal('1.0') - DEFAULT_FEE
|
zsendamount = Decimal('1.0') - DEFAULT_FEE
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address": z_bob, "amount": zsendamount})
|
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_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||||
persist_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
persist_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||||
# Verify transparent transaction is version 4 intended for Sapling branch
|
# Verify transparent transaction is version 4 intended for Sapling branch
|
||||||
|
@ -157,7 +157,7 @@ class MempoolTxExpiryTest(BitcoinTestFramework):
|
||||||
self.split_network()
|
self.split_network()
|
||||||
|
|
||||||
print("\nBlockheight advances to equal expiry block height. After reorg, txs should persist in mempool")
|
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_shielded_2 = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||||
persist_transparent_2 = self.nodes[0].sendtoaddress(bob, 0.01)
|
persist_transparent_2 = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||||
rawtx_trans = self.nodes[0].getrawtransaction(persist_transparent_2, 1)
|
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("\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())
|
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_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||||
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||||
print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks'])
|
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("\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())
|
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_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||||
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
expire_transparent = self.nodes[0].sendtoaddress(bob, 0.01)
|
||||||
print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks'])
|
print("Blockheight node 0 at expire_transparent creation:", self.nodes[0].getblockchaininfo()['blocks'])
|
||||||
|
|
|
@ -20,8 +20,7 @@ class RegtestSignrawtransactionTest (BitcoinTestFramework):
|
||||||
|
|
||||||
# Create and sign Sapling transaction.
|
# Create and sign Sapling transaction.
|
||||||
# If the incorrect consensus branch id is selected, there will be a signing error.
|
# If the incorrect consensus branch id is selected, there will be a signing error.
|
||||||
opid = self.nodes[1].z_sendmany(taddr,
|
opid = self.nodes[1].z_sendmany(taddr, [{'address': zaddr1, 'amount': 1}], 1)
|
||||||
[{'address': zaddr1, 'amount': 1}])
|
|
||||||
wait_and_assert_operationid_status(self.nodes[1], opid)
|
wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -142,7 +142,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
||||||
|
|
||||||
taddr = self.nodes[1].getnewaddress()
|
taddr = self.nodes[1].getnewaddress()
|
||||||
# Generate some change by sending part of zaddr1 back to taddr
|
# 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)
|
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||||
|
|
||||||
self.generate_and_sync(height+4)
|
self.generate_and_sync(height+4)
|
||||||
|
@ -220,7 +220,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
||||||
opid = self.nodes[1].z_sendmany(taddr, [
|
opid = self.nodes[1].z_sendmany(taddr, [
|
||||||
{'address': zaddr1, 'amount': 1, 'memo': my_memo},
|
{'address': zaddr1, 'amount': 1, 'memo': my_memo},
|
||||||
{'address': zaddrExt, 'amount': 2},
|
{'address': zaddrExt, 'amount': 2},
|
||||||
])
|
], 1)
|
||||||
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
@ -287,8 +287,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
||||||
# Generate some change by sending part of zaddr1 to zaddr2
|
# Generate some change by sending part of zaddr1 to zaddr2
|
||||||
txidPrev = txid
|
txidPrev = txid
|
||||||
zaddr2 = self.nodes[1].z_getnewaddress('sapling')
|
zaddr2 = self.nodes[1].z_getnewaddress('sapling')
|
||||||
opid = self.nodes[1].z_sendmany(zaddr1,
|
opid = self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6}], 1)
|
||||||
[{'address': zaddr2, 'amount': 0.6}])
|
|
||||||
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
txid = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.generate_and_sync(height+4)
|
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")
|
assert_equal(len(r), 0, "unified_addr should have received zero notes")
|
||||||
|
|
||||||
# Create a note in this UA on node1
|
# 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)
|
txid_sapling = wait_and_assert_operationid_status(node, opid)
|
||||||
self.generate_and_sync(height+5)
|
self.generate_and_sync(height+5)
|
||||||
|
|
||||||
|
@ -499,7 +498,7 @@ class ListReceivedTest (BitcoinTestFramework):
|
||||||
opid = self.nodes[1].z_sendmany(uao, [
|
opid = self.nodes[1].z_sendmany(uao, [
|
||||||
{'address': uaso, 'amount': Decimal('0.3')},
|
{'address': uaso, 'amount': Decimal('0.3')},
|
||||||
{'address': ua_node0, 'amount': Decimal('0.2')}
|
{'address': ua_node0, 'amount': Decimal('0.2')}
|
||||||
])
|
], 1)
|
||||||
txid1 = wait_and_assert_operationid_status(self.nodes[1], opid)
|
txid1 = wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ class WalletNullifiersTest (BitcoinTestFramework):
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address":myzaddr, "amount":7.0})
|
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.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
@ -71,7 +71,7 @@ class WalletNullifiersTest (BitcoinTestFramework):
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address":myzaddr3, "amount":2.0})
|
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.sync_all()
|
||||||
self.nodes[2].generate(1)
|
self.nodes[2].generate(1)
|
||||||
|
@ -93,7 +93,7 @@ class WalletNullifiersTest (BitcoinTestFramework):
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address":mytaddr1, "amount":1.0})
|
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.sync_all()
|
||||||
self.nodes[1].generate(1)
|
self.nodes[1].generate(1)
|
||||||
|
|
|
@ -53,6 +53,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
||||||
{'address': node3taddr1, 'amount': 60},
|
{'address': node3taddr1, 'amount': 60},
|
||||||
{'address': node3taddr2, 'amount': 75},
|
{'address': node3taddr2, 'amount': 75},
|
||||||
],
|
],
|
||||||
|
1
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
@ -67,7 +68,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
||||||
# We should be able to spend multiple UTXOs at once
|
# We should be able to spend multiple UTXOs at once
|
||||||
wait_and_assert_operationid_status(
|
wait_and_assert_operationid_status(
|
||||||
self.nodes[3],
|
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()
|
self.sync_all()
|
||||||
|
@ -84,7 +85,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
||||||
# Send from a change t-address.
|
# Send from a change t-address.
|
||||||
wait_and_assert_operationid_status(
|
wait_and_assert_operationid_status(
|
||||||
self.nodes[3],
|
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()
|
self.sync_all()
|
||||||
|
@ -95,7 +96,7 @@ class WalletSendManyAnyTaddr(BitcoinTestFramework):
|
||||||
assert_equal(self.nodes[1].z_getbalance(recipient), 120)
|
assert_equal(self.nodes[1].z_getbalance(recipient), 120)
|
||||||
|
|
||||||
# Check that ANY_TADDR note selection doesn't attempt a double-spend
|
# 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")
|
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.
|
# Create an expired transaction on node 3.
|
||||||
|
|
|
@ -107,7 +107,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
||||||
assert_equal(error_result["method"], "z_sendmany")
|
assert_equal(error_result["method"], "z_sendmany")
|
||||||
params = error_result["params"]
|
params = error_result["params"]
|
||||||
assert_equal(params["fee"], DEFAULT_FEE) # default
|
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["fromaddress"], mytaddr)
|
||||||
assert_equal(params["amounts"][0]["address"], myzaddr)
|
assert_equal(params["amounts"][0]["address"], myzaddr)
|
||||||
assert_equal(params["amounts"][0]["amount"], Decimal('1.23456789'))
|
assert_equal(params["amounts"][0]["amount"], Decimal('1.23456789'))
|
||||||
|
@ -198,7 +198,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
||||||
unshieldvalue = Decimal('10.0')
|
unshieldvalue = Decimal('10.0')
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address":mytaddr, "amount": unshieldvalue})
|
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)
|
mytxid = wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||||
assert(mytxid is not None)
|
assert(mytxid is not None)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
@ -224,7 +224,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
||||||
recipients = []
|
recipients = []
|
||||||
amount = Decimal('10.0') - DEFAULT_FEE - Decimal('0.00000001') # this leaves change at 1 zatoshi less than dust threshold
|
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 })
|
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)")
|
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
|
# 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
|
# z_sendmany will fail because of insufficient funds
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')})
|
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.")
|
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.")
|
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
|
# Send will fail because of insufficient funds unless sender uses coinbase utxos
|
||||||
|
@ -276,7 +276,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
||||||
self.nodes[0].getinfo()
|
self.nodes[0].getinfo()
|
||||||
# Issue #2263 Workaround END
|
# Issue #2263 Workaround END
|
||||||
|
|
||||||
myopid = self.nodes[0].z_sendmany(myzaddr, recipients)
|
myopid = self.nodes[0].z_sendmany(myzaddr, recipients, 1)
|
||||||
try:
|
try:
|
||||||
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||||
except JSONRPCException as e:
|
except JSONRPCException as e:
|
||||||
|
|
|
@ -75,7 +75,7 @@ class WalletTreeStateTest (BitcoinTestFramework):
|
||||||
recipients = []
|
recipients = []
|
||||||
recipients.append({"address": self.nodes[2].z_getnewaddress(), "amount": Decimal('18.0')})
|
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})
|
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...
|
# Wait for Tx 2 to begin executing...
|
||||||
for x in range(1, 60):
|
for x in range(1, 60):
|
||||||
|
|
|
@ -23,7 +23,7 @@ from decimal import Decimal
|
||||||
class WalletZSendmanyTest(BitcoinTestFramework):
|
class WalletZSendmanyTest(BitcoinTestFramework):
|
||||||
def setup_network(self, split=False):
|
def setup_network(self, split=False):
|
||||||
self.nodes = start_nodes(3, self.options.tmpdir, [[
|
self.nodes = start_nodes(3, self.options.tmpdir, [[
|
||||||
nuparams(NU5_BRANCH_ID, 220),
|
nuparams(NU5_BRANCH_ID, 240),
|
||||||
]] * self.num_nodes)
|
]] * self.num_nodes)
|
||||||
connect_nodes_bi(self.nodes,0,1)
|
connect_nodes_bi(self.nodes,0,1)
|
||||||
connect_nodes_bi(self.nodes,1,2)
|
connect_nodes_bi(self.nodes,1,2)
|
||||||
|
@ -91,7 +91,7 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
||||||
# send from node 0 to node 2 taddr
|
# send from node 0 to node 2 taddr
|
||||||
mytxid = self.nodes[0].sendtoaddress(mytaddr, 10.0)
|
mytxid = self.nodes[0].sendtoaddress(mytaddr, 10.0)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(10)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# send node 2 taddr to zaddr
|
# 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_unconfirmed_balance"]), zsendmanynotevalue)
|
||||||
assert_equal(Decimal(wallet_info["shielded_balance"]), Decimal('0.0'))
|
assert_equal(Decimal(wallet_info["shielded_balance"]), Decimal('0.0'))
|
||||||
|
|
||||||
self.nodes[2].generate(1)
|
self.nodes[2].generate(10)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
assert_equal(self.nodes[2].getbalance(), node2utxobalance)
|
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(
|
OrchardSpendInfoPtr* orchard_wallet_get_spend_info(
|
||||||
const OrchardWalletPtr* wallet,
|
const OrchardWalletPtr* wallet,
|
||||||
const unsigned char txid[32],
|
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
|
* Run the garbage collection operation on the wallet's note commitment
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
use incrementalmerkletree::{
|
use incrementalmerkletree::{
|
||||||
bridgetree::{BridgeTree, Checkpoint},
|
bridgetree::{BridgeTree, Checkpoint},
|
||||||
Hashable,
|
Hashable, Position,
|
||||||
};
|
};
|
||||||
use zcash_encoding::{Optional, Vector};
|
use zcash_encoding::{Optional, Vector};
|
||||||
use zcash_primitives::merkle_tree::{
|
use zcash_primitives::merkle_tree::{
|
||||||
incremental::{
|
incremental::{
|
||||||
read_bridge_v1, read_leu64_usize, read_position, write_bridge_v1, write_position,
|
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,
|
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())?;
|
write_usize_leu64(&mut writer, checkpoint.bridges_len())?;
|
||||||
writer.write_u8(if checkpoint.is_witnessed() { 1 } else { 0 })?;
|
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(
|
Vector::write_sized(
|
||||||
&mut writer,
|
&mut writer,
|
||||||
checkpoint.forgotten().iter(),
|
checkpoint.forgotten().iter(),
|
||||||
|
@ -29,25 +33,54 @@ pub fn write_checkpoint_v1<W: Write>(mut writer: W, checkpoint: &Checkpoint) ->
|
||||||
Ok(())
|
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(
|
Ok(Checkpoint::from_parts(
|
||||||
read_leu64_usize(&mut reader)?,
|
read_leu64_usize(&mut reader)?,
|
||||||
reader.read_u8()? == 1,
|
reader.read_u8()? == 1,
|
||||||
|
Vector::read_collected(&mut reader, |r| read_position(r))?,
|
||||||
Vector::read_collected(&mut reader, |mut r| {
|
Vector::read_collected(&mut reader, |mut r| {
|
||||||
Ok((read_position(&mut r)?, read_leu64_usize(&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,
|
mut writer: W,
|
||||||
tree: &BridgeTree<H, 32>,
|
tree: &BridgeTree<H, 32>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
Vector::write(&mut writer, tree.prior_bridges(), |w, b| {
|
writer.write_u8(SER_V2)?;
|
||||||
write_bridge_v1(w, b)
|
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| {
|
Optional::write(&mut writer, tree.current_bridge().as_ref(), |mut w, b| {
|
||||||
write_bridge_v1(w, b)
|
write_bridge_v1(&mut w, b)
|
||||||
})?;
|
})?;
|
||||||
Vector::write_sized(
|
Vector::write_sized(
|
||||||
&mut writer,
|
&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| {
|
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())?;
|
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)]
|
#[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,
|
mut reader: R,
|
||||||
) -> io::Result<BridgeTree<H, 32>> {
|
) -> 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(
|
BridgeTree::from_parts(
|
||||||
Vector::read(&mut reader, |r| read_bridge_v1(r))?,
|
prior_bridges,
|
||||||
Optional::read(&mut reader, |r| read_bridge_v1(r))?,
|
current_bridge,
|
||||||
Vector::read_collected(&mut reader, |mut r| {
|
saved,
|
||||||
Ok((read_position(&mut r)?, read_leu64_usize(&mut r)?))
|
checkpoints,
|
||||||
})?,
|
max_checkpoints,
|
||||||
Vector::read(&mut reader, |r| read_checkpoint_v1(r))?,
|
|
||||||
read_leu64_usize(&mut reader)?,
|
|
||||||
)
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
io::Error::new(
|
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 byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use incrementalmerkletree::{bridgetree, bridgetree::BridgeTree, Frontier, Position, Tree};
|
use incrementalmerkletree::{bridgetree, bridgetree::BridgeTree, Position, Tree};
|
||||||
use libc::c_uchar;
|
use libc::c_uchar;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
@ -201,6 +201,8 @@ pub enum SpendRetrievalError {
|
||||||
NoIvkForRecipient(Address),
|
NoIvkForRecipient(Address),
|
||||||
FvkNotFound(IncomingViewingKey),
|
FvkNotFound(IncomingViewingKey),
|
||||||
NoteNotPositioned(OutPoint),
|
NoteNotPositioned(OutPoint),
|
||||||
|
InvalidMerkleRoot,
|
||||||
|
WitnessNotAvailableAtRoot(MerkleHashOrchard),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct used to return metadata about how a bundle was determined
|
/// A struct used to return metadata about how a bundle was determined
|
||||||
|
@ -686,12 +688,12 @@ impl Wallet {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn note_commitment_tree_root(&self) -> MerkleHashOrchard {
|
pub fn note_commitment_tree_root(&self, checkpoint_depth: usize) -> Option<MerkleHashOrchard> {
|
||||||
self.witness_tree.root()
|
self.witness_tree.root(checkpoint_depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches the information necessary to spend the note at the given `OutPoint`,
|
/// 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
|
/// 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 has not been passed to `Wallet::append_bundle_commitments`.
|
||||||
|
@ -699,6 +701,7 @@ impl Wallet {
|
||||||
pub fn get_spend_info(
|
pub fn get_spend_info(
|
||||||
&self,
|
&self,
|
||||||
outpoint: OutPoint,
|
outpoint: OutPoint,
|
||||||
|
as_of_root: MerkleHashOrchard,
|
||||||
) -> Result<OrchardSpendInfo, SpendRetrievalError> {
|
) -> Result<OrchardSpendInfo, SpendRetrievalError> {
|
||||||
// TODO: Take `confirmations` parameter and obtain the Merkle path to the root at
|
// TODO: Take `confirmations` parameter and obtain the Merkle path to the root at
|
||||||
// that checkpoint, not the latest root.
|
// that checkpoint, not the latest root.
|
||||||
|
@ -738,8 +741,8 @@ impl Wallet {
|
||||||
|
|
||||||
let path = self
|
let path = self
|
||||||
.witness_tree
|
.witness_tree
|
||||||
.authentication_path(*position)
|
.authentication_path(*position, &as_of_root)
|
||||||
.expect("wallet always has paths to positioned notes");
|
.ok_or(SpendRetrievalError::WitnessNotAvailableAtRoot(as_of_root))?;
|
||||||
|
|
||||||
Ok(OrchardSpendInfo::from_parts(
|
Ok(OrchardSpendInfo::from_parts(
|
||||||
fvk.clone(),
|
fvk.clone(),
|
||||||
|
@ -939,7 +942,9 @@ pub extern "C" fn orchard_wallet_commitment_tree_root(
|
||||||
let wallet = unsafe { wallet.as_ref() }.expect("Wallet pointer may not be null");
|
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.");
|
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]
|
#[no_mangle]
|
||||||
|
@ -1213,13 +1218,23 @@ pub extern "C" fn orchard_wallet_get_spend_info(
|
||||||
wallet: *const Wallet,
|
wallet: *const Wallet,
|
||||||
txid: *const [c_uchar; 32],
|
txid: *const [c_uchar; 32],
|
||||||
action_idx: usize,
|
action_idx: usize,
|
||||||
|
as_of_root: *const [c_uchar; 32],
|
||||||
) -> *mut OrchardSpendInfo {
|
) -> *mut OrchardSpendInfo {
|
||||||
let wallet = unsafe { wallet.as_ref() }.expect("Wallet pointer may not be null.");
|
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 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 };
|
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)),
|
Ok(ret) => Box::into_raw(Box::new(ret)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
|
|
|
@ -259,7 +259,8 @@ TransactionBuilder::TransactionBuilder(
|
||||||
nHeight(nHeight),
|
nHeight(nHeight),
|
||||||
keystore(keystore),
|
keystore(keystore),
|
||||||
coinsView(coinsView),
|
coinsView(coinsView),
|
||||||
cs_coinsView(cs_coinsView)
|
cs_coinsView(cs_coinsView),
|
||||||
|
orchardAnchor(orchardAnchor)
|
||||||
{
|
{
|
||||||
mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
|
mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
|
||||||
|
|
||||||
|
@ -292,6 +293,11 @@ bool TransactionBuilder::SupportsOrchard() const {
|
||||||
return orchardBuilder.has_value();
|
return orchardBuilder.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<uint256> TransactionBuilder::GetOrchardAnchor() const {
|
||||||
|
return orchardAnchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TransactionBuilder::AddOrchardSpend(
|
bool TransactionBuilder::AddOrchardSpend(
|
||||||
libzcash::OrchardSpendingKey sk,
|
libzcash::OrchardSpendingKey sk,
|
||||||
orchard::SpendInfo spendInfo)
|
orchard::SpendInfo spendInfo)
|
||||||
|
|
|
@ -260,6 +260,7 @@ private:
|
||||||
CCriticalSection* cs_coinsView;
|
CCriticalSection* cs_coinsView;
|
||||||
CMutableTransaction mtx;
|
CMutableTransaction mtx;
|
||||||
CAmount fee = 10000;
|
CAmount fee = 10000;
|
||||||
|
std::optional<uint256> orchardAnchor;
|
||||||
std::optional<orchard::Builder> orchardBuilder;
|
std::optional<orchard::Builder> orchardBuilder;
|
||||||
CAmount valueBalanceOrchard = 0;
|
CAmount valueBalanceOrchard = 0;
|
||||||
|
|
||||||
|
@ -297,6 +298,7 @@ public:
|
||||||
cs_coinsView(std::move(builder.cs_coinsView)),
|
cs_coinsView(std::move(builder.cs_coinsView)),
|
||||||
mtx(std::move(builder.mtx)),
|
mtx(std::move(builder.mtx)),
|
||||||
fee(std::move(builder.fee)),
|
fee(std::move(builder.fee)),
|
||||||
|
orchardAnchor(std::move(builder.orchardAnchor)),
|
||||||
orchardBuilder(std::move(builder.orchardBuilder)),
|
orchardBuilder(std::move(builder.orchardBuilder)),
|
||||||
valueBalanceOrchard(std::move(builder.valueBalanceOrchard)),
|
valueBalanceOrchard(std::move(builder.valueBalanceOrchard)),
|
||||||
spends(std::move(builder.spends)),
|
spends(std::move(builder.spends)),
|
||||||
|
@ -337,6 +339,8 @@ public:
|
||||||
|
|
||||||
bool SupportsOrchard() const;
|
bool SupportsOrchard() const;
|
||||||
|
|
||||||
|
std::optional<uint256> GetOrchardAnchor() const;
|
||||||
|
|
||||||
bool AddOrchardSpend(
|
bool AddOrchardSpend(
|
||||||
libzcash::OrchardSpendingKey sk,
|
libzcash::OrchardSpendingKey sk,
|
||||||
orchard::SpendInfo spendInfo);
|
orchard::SpendInfo spendInfo);
|
||||||
|
|
|
@ -497,7 +497,9 @@ uint256 AsyncRPCOperation_sendmany::main_impl() {
|
||||||
{
|
{
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
pwalletMain->GetSaplingNoteWitnesses(saplingOutPoints, witnesses, anchor);
|
pwalletMain->GetSaplingNoteWitnesses(saplingOutPoints, witnesses, anchor);
|
||||||
orchardSpendInfo = pwalletMain->GetOrchardSpendInfo(spendable.orchardNoteMetadata);
|
if (builder_.GetOrchardAnchor().has_value()) {
|
||||||
|
orchardSpendInfo = pwalletMain->GetOrchardSpendInfo(spendable.orchardNoteMetadata, builder_.GetOrchardAnchor().value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Orchard spends
|
// Add Orchard spends
|
||||||
|
|
|
@ -110,7 +110,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
|
||||||
|
|
||||||
// If we attempt to get spend info now, it will fail because the note hasn't
|
// If we attempt to get spend info now, it will fail because the note hasn't
|
||||||
// been witnessed in the Orchard commitment tree.
|
// 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.
|
// Append the bundle to the wallet's commitment tree.
|
||||||
CBlock fakeBlock;
|
CBlock fakeBlock;
|
||||||
|
@ -119,7 +119,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
|
||||||
ASSERT_TRUE(wallet.AppendNoteCommitments(2, fakeBlock));
|
ASSERT_TRUE(wallet.AppendNoteCommitments(2, fakeBlock));
|
||||||
|
|
||||||
// Now we can get spend info for the note.
|
// 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);
|
EXPECT_EQ(spendInfo[0].second.Value(), 40000);
|
||||||
|
|
||||||
// Get the root of the commitment tree.
|
// Get the root of the commitment tree.
|
||||||
|
|
|
@ -884,8 +884,8 @@ TEST(WalletTests, GetConflictedOrchardNotes) {
|
||||||
auto recipient2 = ivk.Address(j2);
|
auto recipient2 = ivk.Address(j2);
|
||||||
|
|
||||||
// Generate tx to spend note A
|
// Generate tx to spend note A
|
||||||
auto noteToSpend = std::move(wallet.GetOrchardSpendInfo(orchardEntries)[0]);
|
|
||||||
auto builder2 = TransactionBuilder(consensusParams, 2, orchardTree.root());
|
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));
|
builder2.AddOrchardSpend(std::move(noteToSpend.first), std::move(noteToSpend.second));
|
||||||
auto maybeTx2 = builder2.Build();
|
auto maybeTx2 = builder2.Build();
|
||||||
EXPECT_TRUE(maybeTx2.IsTx());
|
EXPECT_TRUE(maybeTx2.IsTx());
|
||||||
|
@ -897,7 +897,7 @@ TEST(WalletTests, GetConflictedOrchardNotes) {
|
||||||
CWalletTx wtx2 {&wallet, tx2};
|
CWalletTx wtx2 {&wallet, tx2};
|
||||||
|
|
||||||
// Generate conflicting tx to spend note A
|
// 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());
|
auto builder3 = TransactionBuilder(consensusParams, 2, orchardTree.root());
|
||||||
builder3.AddOrchardSpend(std::move(noteToSpend2.first), std::move(noteToSpend2.second));
|
builder3.AddOrchardSpend(std::move(noteToSpend2.first), std::move(noteToSpend2.second));
|
||||||
auto maybeTx3 = builder3.Build();
|
auto maybeTx3 = builder3.Build();
|
||||||
|
|
|
@ -13,14 +13,16 @@ std::optional<libzcash::OrchardSpendingKey> OrchardWallet::GetSpendingKeyForAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> OrchardWallet::GetSpendInfo(
|
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;
|
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> result;
|
||||||
for (const auto& note : noteMetadata) {
|
for (const auto& note : noteMetadata) {
|
||||||
auto pSpendInfo = orchard_wallet_get_spend_info(
|
auto pSpendInfo = orchard_wallet_get_spend_info(
|
||||||
inner.get(),
|
inner.get(),
|
||||||
note.GetOutPoint().hash.begin(),
|
note.GetOutPoint().hash.begin(),
|
||||||
note.GetOutPoint().n);
|
note.GetOutPoint().n,
|
||||||
|
anchor.begin());
|
||||||
if (pSpendInfo == nullptr) {
|
if (pSpendInfo == nullptr) {
|
||||||
throw std::logic_error("Called OrchardWallet::GetSpendInfo with unknown outpoint");
|
throw std::logic_error("Called OrchardWallet::GetSpendInfo with unknown outpoint");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -442,7 +442,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> GetSpendInfo(
|
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() {
|
void GarbageCollect() {
|
||||||
orchard_wallet_gc_note_commitment_tree(inner.get());
|
orchard_wallet_gc_note_commitment_tree(inner.get());
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
@ -1042,7 +1043,7 @@ UniValue sendmany(const UniValue& params, bool fHelp)
|
||||||
" \"address\":amount (numeric) The Zcash address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n"
|
" \"address\":amount (numeric) The Zcash address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n"
|
||||||
" ,...\n"
|
" ,...\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
|
"3. minconf (numeric, optional, default=10) Only use the balance confirmed at least this many times.\n"
|
||||||
"4. \"comment\" (string, optional) A comment\n"
|
"4. \"comment\" (string, optional) A comment\n"
|
||||||
"5. subtractfeefromamount (string, optional) A json array with addresses.\n"
|
"5. subtractfeefromamount (string, optional) A json array with addresses.\n"
|
||||||
" The fee will be equally deducted from the amount of each selected address.\n"
|
" The fee will be equally deducted from the amount of each selected address.\n"
|
||||||
|
@ -4857,6 +4858,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
||||||
|
|
||||||
if (fHelp || params.size() < 2 || params.size() > 5)
|
if (fHelp || params.size() < 2 || params.size() > 5)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
|
strprintf(
|
||||||
"z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee ) ( privacyPolicy )\n"
|
"z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee ) ( privacyPolicy )\n"
|
||||||
"\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
|
"\nSend multiple times. Amounts are decimal numbers with at most 8 digits of precision."
|
||||||
"\nChange generated from one or more transparent addresses flows to a new transparent"
|
"\nChange generated from one or more transparent addresses flows to a new transparent"
|
||||||
|
@ -4877,7 +4879,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
||||||
" \"amount\":amount (numeric, required) The numeric amount in " + CURRENCY_UNIT + " is the value\n"
|
" \"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"
|
" \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
|
||||||
" }, ... ]\n"
|
" }, ... ]\n"
|
||||||
"3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
|
"3. minconf (numeric, optional, default=%u) 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"
|
"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"
|
"5. privacyPolicy (string, optional, default=\"LegacyCompat\") Policy for what information leakage is acceptable.\n"
|
||||||
" One of the following strings:\n"
|
" One of the following strings:\n"
|
||||||
|
@ -4905,6 +4907,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
||||||
+ HelpExampleCli("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\", \"amount\": 5.0}]'")
|
+ HelpExampleCli("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" '[{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\", \"amount\": 5.0}]'")
|
||||||
+ HelpExampleCli("z_sendmany", "\"ANY_TADDR\" '[{\"address\": \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", \"amount\": 2.0}]'")
|
+ HelpExampleCli("z_sendmany", "\"ANY_TADDR\" '[{\"address\": \"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", \"amount\": 2.0}]'")
|
||||||
+ HelpExampleRpc("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\", \"amount\": 5.0}]")
|
+ HelpExampleRpc("z_sendmany", "\"t1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", [{\"address\": \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\", \"amount\": 5.0}]")
|
||||||
|
, nOrchardAnchorConfirmations)
|
||||||
);
|
);
|
||||||
|
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
@ -5089,7 +5092,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Minimum confirmations
|
// Minimum confirmations
|
||||||
int nMinDepth = 1;
|
int nMinDepth = nOrchardAnchorConfirmations;
|
||||||
if (params.size() > 2) {
|
if (params.size() > 2) {
|
||||||
nMinDepth = params[2].get_int();
|
nMinDepth = params[2].get_int();
|
||||||
}
|
}
|
||||||
|
@ -5134,11 +5137,11 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
||||||
UniValue contextInfo = o;
|
UniValue contextInfo = o;
|
||||||
|
|
||||||
std::optional<uint256> orchardAnchor;
|
std::optional<uint256> orchardAnchor;
|
||||||
if (!ztxoSelector.SelectsSprout()) {
|
if (!ztxoSelector.SelectsSprout() && nMinDepth > 0) {
|
||||||
// Allow Orchard recipients by setting an Orchard anchor.
|
// Allow Orchard recipients by setting an Orchard anchor.
|
||||||
// TODO: Add an orchardAnchorHeight field to ZTXOSelector so we can ensure the
|
// TODO: Add an orchardAnchorHeight field to ZTXOSelector so we can ensure the
|
||||||
// same anchor is used for witnesses of any selected Orchard note.
|
// same anchor is used for witnesses of any selected Orchard note.
|
||||||
auto orchardAnchorHeight = nextBlockHeight - nOrchardAnchorConfirmations;
|
auto orchardAnchorHeight = nextBlockHeight - std::min((unsigned int) nMinDepth, nOrchardAnchorConfirmations);
|
||||||
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
orchardAnchor = chainActive[orchardAnchorHeight]->hashFinalOrchardRoot;
|
||||||
}
|
}
|
||||||
TransactionBuilder builder(chainparams.GetConsensus(), nextBlockHeight, orchardAnchor, pwalletMain);
|
TransactionBuilder builder(chainparams.GetConsensus(), nextBlockHeight, orchardAnchor, pwalletMain);
|
||||||
|
|
|
@ -3584,10 +3584,11 @@ void CWallet::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> CWallet::GetOrchardSpendInfo(
|
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);
|
AssertLockHeld(cs_wallet);
|
||||||
return orchardWallet.GetSpendInfo(orchardNoteMetadata);
|
return orchardWallet.GetSpendInfo(orchardNoteMetadata, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
isminetype CWallet::IsMine(const CTxIn &txin) const
|
isminetype CWallet::IsMine(const CTxIn &txin) const
|
||||||
|
|
|
@ -79,7 +79,7 @@ static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
|
||||||
//! Amount of entropy used in generation of the mnemonic seed, in bytes.
|
//! Amount of entropy used in generation of the mnemonic seed, in bytes.
|
||||||
static const size_t WALLET_MNEMONIC_ENTROPY_LENGTH = 32;
|
static const size_t WALLET_MNEMONIC_ENTROPY_LENGTH = 32;
|
||||||
//! -orchardanchorconfirmations default
|
//! -orchardanchorconfirmations default
|
||||||
static const unsigned int DEFAULT_ORCHARD_ANCHOR_CONFIRMATIONS = 1;
|
static const unsigned int DEFAULT_ORCHARD_ANCHOR_CONFIRMATIONS = 10;
|
||||||
|
|
||||||
extern const char * DEFAULT_WALLET_DAT;
|
extern const char * DEFAULT_WALLET_DAT;
|
||||||
|
|
||||||
|
@ -1787,7 +1787,8 @@ public:
|
||||||
std::vector<std::optional<SaplingWitness>>& witnesses,
|
std::vector<std::optional<SaplingWitness>>& witnesses,
|
||||||
uint256 &final_anchor);
|
uint256 &final_anchor);
|
||||||
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> GetOrchardSpendInfo(
|
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;
|
isminetype IsMine(const CTxIn& txin) const;
|
||||||
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
|
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
|
||||||
|
|
Loading…
Reference in New Issue