Compare commits
14 Commits
eef788e949
...
e5b2d8ba35
Author | SHA1 | Date |
---|---|---|
ar | e5b2d8ba35 | |
Arya | e5d4d739b7 | |
Arya | e95a70de7a | |
Arya | ee9ab3162a | |
Alfredo Garcia | d869ec6fe4 | |
Alfredo Garcia | 5f69870235 | |
Arya | 275e99ec72 | |
Alfredo Garcia | 8cf0b7a36a | |
dependabot[bot] | 74319ec477 | |
Marek | 2ba837470e | |
dependabot[bot] | f1334a8378 | |
Arya | f8c153991b | |
Alfredo Garcia | 887d4a2457 | |
Alfredo Garcia | 2995ea087b |
|
@ -19,11 +19,21 @@ updates:
|
|||
ecc:
|
||||
patterns:
|
||||
# deliberately include zcash_script (even though it is maintained by ZF)
|
||||
- "zcash_*|orchard|halo2*|incrementalmerkletree|bridgetree|equihash"
|
||||
- "zcash_*
|
||||
- "orchard"
|
||||
- "halo2*"
|
||||
- "incrementalmerkletree"
|
||||
- "bridgetree"
|
||||
- "equihash"
|
||||
prod:
|
||||
dependency-type: "production"
|
||||
exclude-patterns:
|
||||
- "zcash_*|orchard|halo2*|incrementalmerkletree|bridgetree|equihash"
|
||||
- "zcash_*
|
||||
- "orchard"
|
||||
- "halo2*"
|
||||
- "incrementalmerkletree"
|
||||
- "bridgetree"
|
||||
- "equihash"
|
||||
dev:
|
||||
dependency-type: "development"
|
||||
# Devops section
|
||||
|
|
|
@ -151,7 +151,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4.1.2
|
||||
- name: actionlint
|
||||
uses: reviewdog/action-actionlint@v1.43.0
|
||||
uses: reviewdog/action-actionlint@v1.44.0
|
||||
with:
|
||||
level: warning
|
||||
fail_on_error: false
|
||||
|
|
|
@ -78,8 +78,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# TODO: Windows was removed for now, see https://github.com/ZcashFoundation/zebra/issues/3801
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
rust: [stable, beta]
|
||||
# TODO: When vars.EXPERIMENTAL_FEATURES has features in it, add it here.
|
||||
# Or work out a way to trim the space from the variable: GitHub doesn't allow empty variables.
|
||||
|
@ -281,7 +280,7 @@ jobs:
|
|||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal
|
||||
|
||||
- name: Install cargo-machete
|
||||
uses: baptiste0928/cargo-install@v3.0.1
|
||||
uses: baptiste0928/cargo-install@v3.1.0
|
||||
with:
|
||||
crate: cargo-machete
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ jobs:
|
|||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal
|
||||
|
||||
- name: Install cargo-release
|
||||
uses: baptiste0928/cargo-install@v3.0.1
|
||||
uses: baptiste0928/cargo-install@v3.1.0
|
||||
with:
|
||||
crate: cargo-release
|
||||
|
||||
|
|
126
Cargo.lock
126
Cargo.lock
|
@ -239,7 +239,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -250,7 +250,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -415,7 +415,7 @@ dependencies = [
|
|||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
"which",
|
||||
]
|
||||
|
||||
|
@ -705,9 +705,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.34"
|
||||
version = "0.4.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
|
||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
@ -811,7 +811,7 @@ dependencies = [
|
|||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1072,14 +1072,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.107"
|
||||
version = "1.0.113"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe98ba1789d56fb3db3bee5e032774d4f421b685de7ba703643584ba24effbe"
|
||||
checksum = "048948e14bc2c2652ec606c8e3bb913407f0187288fb351a0b2d972beaf12070"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
|
@ -1089,31 +1089,31 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx-gen"
|
||||
version = "0.7.117"
|
||||
version = "0.7.121"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54b629c0d006c7e44c1444dd17d18a458c9390d32276b758ac7abd21a75c99b0"
|
||||
checksum = "383ecb9f96a536a1c7a2a61c5786f583da84f9240da149d78d005a4413c9a71e"
|
||||
dependencies = [
|
||||
"codespan-reporting",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.107"
|
||||
version = "1.0.113"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20888d9e1d2298e2ff473cee30efe7d5036e437857ab68bbfea84c74dba91da2"
|
||||
checksum = "af40b0467c68d3d9fb7550ef984edc8ad47252f703ef0f1f2d1052e0e4af8793"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.107"
|
||||
version = "1.0.113"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fa16a70dd58129e4dfffdff535fb1bce66673f7bbeec4a5a1765a504e1ccd84"
|
||||
checksum = "7743446286141c9f6d4497c493c01234eb848e14d2e20866ae9811eae0630cb9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1161,7 +1161,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.10.0",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1183,7 +1183,7 @@ checksum = "c5a91391accf613803c2a9bf9abccdbaa07c54b4244a5b64883f9c3c137c86be"
|
|||
dependencies = [
|
||||
"darling_core 0.20.6",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1256,7 +1256,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1561,7 +1561,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2629,7 +2629,7 @@ checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3064,7 +3064,7 @@ dependencies = [
|
|||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3105,7 +3105,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3206,7 +3206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3329,7 +3329,7 @@ dependencies = [
|
|||
"prost",
|
||||
"prost-types",
|
||||
"regex",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
"tempfile",
|
||||
"which",
|
||||
]
|
||||
|
@ -3344,7 +3344,7 @@ dependencies = [
|
|||
"itertools 0.12.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3809,9 +3809,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.10"
|
||||
version = "0.21.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
|
||||
checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring 0.17.8",
|
||||
|
@ -4028,9 +4028,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
version = "1.0.198"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -4046,20 +4046,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
version = "1.0.198"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.115"
|
||||
version = "1.0.116"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
|
||||
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"itoa",
|
||||
|
@ -4137,7 +4137,7 @@ dependencies = [
|
|||
"darling 0.20.6",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4366,9 +4366,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.59"
|
||||
version = "2.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a"
|
||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4452,29 +4452,29 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.58"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
|
||||
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.58"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
||||
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread-priority"
|
||||
version = "0.16.0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a617e9eeeb20448b01a8e2427fb80dfbc9c49d79a1de3b11f25731edbf547e3c"
|
||||
checksum = "599e8e829c2314b750ecade9309ecc6cf9a48c2e62fe25680b6c1d2172463ca3"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"cfg-if 1.0.0",
|
||||
|
@ -4590,7 +4590,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4774,7 +4774,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"prost-build",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4787,7 +4787,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"prost-build",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4917,7 +4917,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5355,7 +5355,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -5389,7 +5389,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -5670,9 +5670,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_client_backend"
|
||||
version = "0.10.0-rc.4"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecc33f71747a93d509f7e1c047961e359a271bdf4869cc07f7f65ee1ba7df8c2"
|
||||
checksum = "d6a382af39be9ee5a3788157145c404b7cd19acc440903f6c34b09fb44f0e991"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bech32",
|
||||
|
@ -5737,9 +5737,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_primitives"
|
||||
version = "0.13.0-rc.1"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc4391d9325e0a51a7cbff02b5c4b5472d66087bd9c903ddb12dea7ec22f3e0"
|
||||
checksum = "d17e4c94ca8d69d2fcf2be97522da5732a580eb2125cda3b150761952f8df8e6"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bip0039",
|
||||
|
@ -5773,9 +5773,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_proofs"
|
||||
version = "0.13.0-rc.1"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48f22eff3bdc382327ef28f809024ddc89ec6d903ba71be629b2cbea34afdda2"
|
||||
checksum = "df0c99f65a840ff256c106b28d67d702d9759d206112473d4982c92003262406"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"blake2b_simd",
|
||||
|
@ -5804,9 +5804,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zcash_script"
|
||||
version = "0.1.14"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8deff8ea47cbe2a008abefedc1a2d9c0e48a87844379759ace270a0b53353c71"
|
||||
checksum = "9e3de6aece21108f502f724183955d244e02338613eaa4f9010386c63618a3a8"
|
||||
dependencies = [
|
||||
"bellman",
|
||||
"bindgen",
|
||||
|
@ -6187,7 +6187,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"serde_yaml",
|
||||
"structopt",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
"thiserror",
|
||||
"tinyvec",
|
||||
"tokio",
|
||||
|
@ -6288,7 +6288,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -6308,5 +6308,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.59",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
|
|
@ -68,7 +68,7 @@ Zebra is tested with the latest `stable` Rust version. Earlier versions are not
|
|||
supported or tested. Any Zebra release can start depending on new features in the
|
||||
latest stable Rust.
|
||||
|
||||
Every few weeks, we release a [new Zebra version](https://github.com/ZcashFoundation/zebra/releases).
|
||||
Around every 4 weeks, we release a [new Zebra version](https://github.com/ZcashFoundation/zebra/releases).
|
||||
|
||||
Below are quick summaries for installing the dependencies on your machine.
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ The pre-release version is denoted by appending a hyphen and a series of dot sep
|
|||
|
||||
### Supported Releases
|
||||
|
||||
Every Zebra version released by the Zcash Foundation is supported up to a specific height. Currently we support each version for about **16 weeks** but this can change from release to release.
|
||||
Every Zebra version released by the Zcash Foundation is supported up to a specific height. Currently we support each version for about **20 weeks** but this can change from release to release.
|
||||
|
||||
When the Zcash chain reaches this end of support height, `zebrad` will shut down and the binary will refuse to start.
|
||||
|
||||
|
@ -95,7 +95,7 @@ In general, expect the following release cycle:
|
|||
|
||||
* A major release for each network upgrade, whenever there are breaking changes to Zebra (by API, severe bugs or other kind of upgrades)
|
||||
* Minor releases for significant new Zebra features or severe bug fixes
|
||||
* A patch release every few weeks
|
||||
* A patch release around every 4 weeks
|
||||
|
||||
This cadence of releases gives eager developers access to new features as soon as they are fully developed and pass through our code review and integration testing processes, while maintaining the stability and reliability of the platform for production users that prefer to receive features after they have been validated by Zcash and other developers that use the pre-release builds.
|
||||
|
||||
|
|
|
@ -97,21 +97,21 @@ orchard = "0.6.0"
|
|||
zcash_encoding = "0.2.0"
|
||||
zcash_history = "0.4.0"
|
||||
zcash_note_encryption = "0.4.0"
|
||||
zcash_primitives = { version = "0.13.0-rc.1", features = ["transparent-inputs"] }
|
||||
zcash_primitives = { version = "0.13.0", features = ["transparent-inputs"] }
|
||||
|
||||
# Time
|
||||
chrono = { version = "0.4.34", default-features = false, features = ["clock", "std", "serde"] }
|
||||
chrono = { version = "0.4.38", default-features = false, features = ["clock", "std", "serde"] }
|
||||
humantime = "2.1.0"
|
||||
|
||||
# Error Handling & Formatting
|
||||
displaydoc = "0.2.4"
|
||||
static_assertions = "1.1.0"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
tracing = "0.1.39"
|
||||
|
||||
# Serialization
|
||||
hex = { version = "0.4.3", features = ["serde"] }
|
||||
serde = { version = "1.0.196", features = ["serde_derive", "rc"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive", "rc"] }
|
||||
serde_with = "3.7.0"
|
||||
serde-big-array = "0.5.1"
|
||||
|
||||
|
@ -126,7 +126,7 @@ redjubjub = "0.7.0"
|
|||
reddsa = "0.5.1"
|
||||
|
||||
# Production feature json-conversion
|
||||
serde_json = { version = "1.0.115", optional = true }
|
||||
serde_json = { version = "1.0.116", optional = true }
|
||||
|
||||
# Production feature async-error and testing feature proptest-impl
|
||||
tokio = { version = "1.37.0", optional = true }
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
//! Randomised property testing for [`Block`]s.
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use proptest::{
|
||||
arbitrary::{any, Arbitrary},
|
||||
prelude::*,
|
||||
};
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::{
|
||||
amount::NonNegative,
|
||||
block,
|
||||
fmt::{HexDebug, SummaryDebug},
|
||||
history_tree::HistoryTree,
|
||||
parameters::{
|
||||
Network,
|
||||
NetworkUpgrade::{self, *},
|
||||
GENESIS_PREVIOUS_BLOCK_HASH,
|
||||
},
|
||||
parameters::{NetworkUpgrade::*, GENESIS_PREVIOUS_BLOCK_HASH},
|
||||
serialization,
|
||||
transaction::arbitrary::MAX_ARBITRARY_ITEMS,
|
||||
transparent::{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Generate large transparent blocks and transactions for testing.
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use chrono::DateTime;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
|
@ -42,18 +42,6 @@ pub fn transaction() -> (Transaction, Vec<u8>) {
|
|||
(transaction, transaction_bytes)
|
||||
}
|
||||
|
||||
/// Returns a generated transparent lock time, and its canonical serialized bytes.
|
||||
pub fn lock_time() -> (LockTime, Vec<u8>) {
|
||||
let lock_time = LockTime::Time(DateTime::<Utc>::from_naive_utc_and_offset(
|
||||
NaiveDateTime::from_timestamp_opt(61, 0)
|
||||
.expect("in-range number of seconds and valid nanosecond"),
|
||||
Utc,
|
||||
));
|
||||
let lock_time_bytes = lock_time.zcash_serialize_to_vec().unwrap();
|
||||
|
||||
(lock_time, lock_time_bytes)
|
||||
}
|
||||
|
||||
/// Returns a generated transparent input, and its canonical serialized bytes.
|
||||
pub fn input() -> (transparent::Input, Vec<u8>) {
|
||||
// Some of the test vectors are in a non-canonical format,
|
||||
|
@ -182,8 +170,8 @@ fn single_transaction_block_many_inputs(oversized: bool) -> Block {
|
|||
// A block header
|
||||
let (block_header, block_header_bytes) = block_header();
|
||||
|
||||
// A LockTime
|
||||
let (lock_time, lock_time_bytes) = lock_time();
|
||||
let lock_time = LockTime::Time(DateTime::from_timestamp(61, 0).unwrap());
|
||||
let lock_time_bytes = lock_time.zcash_serialize_to_vec().unwrap();
|
||||
|
||||
// Calculate the number of inputs we need,
|
||||
// subtracting the bytes used to serialize the expected input count,
|
||||
|
@ -256,8 +244,8 @@ fn single_transaction_block_many_outputs(oversized: bool) -> Block {
|
|||
// A block header
|
||||
let (block_header, block_header_bytes) = block_header();
|
||||
|
||||
// A LockTime
|
||||
let (lock_time, lock_time_bytes) = lock_time();
|
||||
let lock_time = LockTime::Time(DateTime::from_timestamp(61, 0).unwrap());
|
||||
let lock_time_bytes = lock_time.zcash_serialize_to_vec().unwrap();
|
||||
|
||||
// Calculate the number of outputs we need,
|
||||
// subtracting the bytes used to serialize the expected output count,
|
||||
|
|
|
@ -2,21 +2,19 @@
|
|||
|
||||
use std::{env, io::ErrorKind};
|
||||
|
||||
use proptest::{arbitrary::any, prelude::*, test_runner::Config};
|
||||
use proptest::{prelude::*, test_runner::Config};
|
||||
|
||||
use hex::{FromHex, ToHex};
|
||||
|
||||
use zebra_test::prelude::*;
|
||||
|
||||
use crate::{
|
||||
parameters::{Network, GENESIS_PREVIOUS_BLOCK_HASH},
|
||||
parameters::GENESIS_PREVIOUS_BLOCK_HASH,
|
||||
serialization::{SerializationError, ZcashDeserializeInto, ZcashSerialize},
|
||||
LedgerState,
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
arbitrary::{allow_all_transparent_coinbase_spends, PREVOUTS_CHAIN_HEIGHT},
|
||||
serialize::MAX_BLOCK_BYTES,
|
||||
*,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{convert::TryFrom, io};
|
||||
use std::io;
|
||||
|
||||
use halo2::pasta::pallas;
|
||||
use reddsa::orchard::SpendAuth;
|
||||
|
|
|
@ -7,7 +7,7 @@ use group::{
|
|||
use halo2::pasta::pallas;
|
||||
use reddsa::{orchard::SpendAuth, Signature, SigningKey, VerificationKey, VerificationKeyBytes};
|
||||
|
||||
use proptest::{arbitrary::any, array, collection::vec, prelude::*};
|
||||
use proptest::{array, collection::vec, prelude::*};
|
||||
|
||||
use super::{
|
||||
keys::*, note, tree, Action, AuthorizedAction, Flags, NoteCommitment, ValueCommitment,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
use halo2::pasta::pallas;
|
||||
use reddsa::{self, orchard::Binding, orchard::SpendAuth, Signature};
|
||||
use reddsa::{orchard::Binding, orchard::SpendAuth, Signature};
|
||||
|
||||
use crate::{
|
||||
amount::{Amount, NegativeAllowed},
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::{
|
|||
};
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use bridgetree::{self, NonEmptyFrontier};
|
||||
use bridgetree::NonEmptyFrontier;
|
||||
use halo2::pasta::{group::ff::PrimeField, pallas};
|
||||
use hex::ToHex;
|
||||
use incrementalmerkletree::Hashable;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::NetworkUpgrade;
|
||||
use super::{Network, NetworkUpgrade};
|
||||
|
||||
impl NetworkUpgrade {
|
||||
/// Generates network upgrades.
|
||||
|
@ -32,3 +32,13 @@ impl NetworkUpgrade {
|
|||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for Network {
|
||||
type Parameters = ();
|
||||
|
||||
fn arbitrary_with(_args: ()) -> Self::Strategy {
|
||||
prop_oneof![Just(Self::Mainnet), Just(Self::new_default_testnet())].boxed()
|
||||
}
|
||||
|
||||
type Strategy = BoxedStrategy<Self>;
|
||||
}
|
||||
|
|
|
@ -4,17 +4,16 @@ use std::{fmt, str::FromStr, sync::Arc};
|
|||
|
||||
use thiserror::Error;
|
||||
|
||||
use zcash_primitives::constants;
|
||||
use zcash_primitives::{consensus as zp_consensus, constants as zp_constants};
|
||||
|
||||
use crate::{
|
||||
block::{self, Height, HeightDiff},
|
||||
parameters::NetworkUpgrade::Canopy,
|
||||
parameters::NetworkUpgrade,
|
||||
};
|
||||
|
||||
pub mod testnet;
|
||||
use self::testnet::ConfiguredActivationHeights;
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
pub mod testnet;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -81,7 +80,6 @@ impl From<Network> for NetworkKind {
|
|||
|
||||
/// An enum describing the possible network choices.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize)]
|
||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||
#[serde(into = "NetworkKind")]
|
||||
pub enum Network {
|
||||
/// The production mainnet.
|
||||
|
@ -98,8 +96,8 @@ impl NetworkKind {
|
|||
/// pay-to-public-key-hash payment addresses for the network.
|
||||
pub fn b58_pubkey_address_prefix(self) -> [u8; 2] {
|
||||
match self {
|
||||
Self::Mainnet => constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||
Self::Testnet | Self::Regtest => constants::testnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||
Self::Mainnet => zp_constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||
Self::Testnet | Self::Regtest => zp_constants::testnet::B58_PUBKEY_ADDRESS_PREFIX,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,8 +105,8 @@ impl NetworkKind {
|
|||
/// payment addresses for the network.
|
||||
pub fn b58_script_address_prefix(self) -> [u8; 2] {
|
||||
match self {
|
||||
Self::Mainnet => constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||
Self::Testnet | Self::Regtest => constants::testnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||
Self::Mainnet => zp_constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||
Self::Testnet | Self::Regtest => zp_constants::testnet::B58_SCRIPT_ADDRESS_PREFIX,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,15 +140,11 @@ impl fmt::Display for NetworkKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&Network> for &'static str {
|
||||
fn from(network: &Network) -> &'static str {
|
||||
impl<'a> From<&'a Network> for &'a str {
|
||||
fn from(network: &'a Network) -> &'a str {
|
||||
match network {
|
||||
Network::Mainnet => "Mainnet",
|
||||
// TODO:
|
||||
// - Add a `name` field to use here instead of checking `is_default_testnet()`
|
||||
// - zcashd calls the Regtest cache dir 'regtest' (#8327).
|
||||
Network::Testnet(params) if params.is_default_testnet() => "Testnet",
|
||||
Network::Testnet(_params) => "UnknownTestnet",
|
||||
Network::Testnet(params) => params.network_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +166,11 @@ impl Network {
|
|||
Self::Testnet(Arc::new(params))
|
||||
}
|
||||
|
||||
/// Creates a new [`Network::Testnet`] with `Regtest` parameters and the provided network upgrade activation heights.
|
||||
pub fn new_regtest(activation_heights: ConfiguredActivationHeights) -> Self {
|
||||
Self::new_configured_testnet(testnet::Parameters::new_regtest(activation_heights))
|
||||
}
|
||||
|
||||
/// Returns true if the network is the default Testnet, or false otherwise.
|
||||
pub fn is_default_testnet(&self) -> bool {
|
||||
if let Self::Testnet(params) = self {
|
||||
|
@ -181,6 +180,15 @@ impl Network {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the network is Regtest, or false otherwise.
|
||||
pub fn is_regtest(&self) -> bool {
|
||||
if let Self::Testnet(params) = self {
|
||||
params.is_regtest()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the [`NetworkKind`] for this network.
|
||||
pub fn kind(&self) -> NetworkKind {
|
||||
match self {
|
||||
|
@ -231,7 +239,7 @@ impl Network {
|
|||
//
|
||||
// See the `ZIP_212_GRACE_PERIOD_DURATION` documentation for more information.
|
||||
|
||||
let canopy_activation = Canopy
|
||||
let canopy_activation = NetworkUpgrade::Canopy
|
||||
.activation_height(self)
|
||||
.expect("Canopy activation height must be present for both networks");
|
||||
|
||||
|
@ -279,3 +287,70 @@ impl FromStr for Network {
|
|||
#[derive(Clone, Debug, Error)]
|
||||
#[error("Invalid network: {0}")]
|
||||
pub struct InvalidNetworkError(String);
|
||||
|
||||
impl zp_consensus::Parameters for Network {
|
||||
fn activation_height(
|
||||
&self,
|
||||
nu: zcash_primitives::consensus::NetworkUpgrade,
|
||||
) -> Option<zcash_primitives::consensus::BlockHeight> {
|
||||
let target_nu = match nu {
|
||||
zp_consensus::NetworkUpgrade::Overwinter => NetworkUpgrade::Overwinter,
|
||||
zp_consensus::NetworkUpgrade::Sapling => NetworkUpgrade::Sapling,
|
||||
zp_consensus::NetworkUpgrade::Blossom => NetworkUpgrade::Blossom,
|
||||
zp_consensus::NetworkUpgrade::Heartwood => NetworkUpgrade::Heartwood,
|
||||
zp_consensus::NetworkUpgrade::Canopy => NetworkUpgrade::Canopy,
|
||||
zp_consensus::NetworkUpgrade::Nu5 => NetworkUpgrade::Nu5,
|
||||
};
|
||||
|
||||
// Heights are hard-coded below Height::MAX or checked when the config is parsed.
|
||||
target_nu
|
||||
.activation_height(self)
|
||||
.map(|Height(h)| zp_consensus::BlockHeight::from_u32(h))
|
||||
}
|
||||
|
||||
fn coin_type(&self) -> u32 {
|
||||
match self {
|
||||
Network::Mainnet => zp_constants::mainnet::COIN_TYPE,
|
||||
// The regtest cointype reuses the testnet cointype,
|
||||
// See <https://github.com/satoshilabs/slips/blob/master/slip-0044.md>
|
||||
Network::Testnet(_) => zp_constants::testnet::COIN_TYPE,
|
||||
}
|
||||
}
|
||||
|
||||
fn address_network(&self) -> Option<zcash_address::Network> {
|
||||
match self {
|
||||
Network::Mainnet => Some(zcash_address::Network::Main),
|
||||
// TODO: Check if network is `Regtest` first, and if it is, return `zcash_address::Network::Regtest`
|
||||
Network::Testnet(_params) => Some(zcash_address::Network::Test),
|
||||
}
|
||||
}
|
||||
|
||||
fn hrp_sapling_extended_spending_key(&self) -> &str {
|
||||
match self {
|
||||
Network::Mainnet => zp_constants::mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||
Network::Testnet(params) => params.hrp_sapling_extended_spending_key(),
|
||||
}
|
||||
}
|
||||
|
||||
fn hrp_sapling_extended_full_viewing_key(&self) -> &str {
|
||||
match self {
|
||||
Network::Mainnet => zp_constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
Network::Testnet(params) => params.hrp_sapling_extended_full_viewing_key(),
|
||||
}
|
||||
}
|
||||
|
||||
fn hrp_sapling_payment_address(&self) -> &str {
|
||||
match self {
|
||||
Network::Mainnet => zp_constants::mainnet::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
Network::Testnet(params) => params.hrp_sapling_payment_address(),
|
||||
}
|
||||
}
|
||||
|
||||
fn b58_pubkey_address_prefix(&self) -> [u8; 2] {
|
||||
self.kind().b58_pubkey_address_prefix()
|
||||
}
|
||||
|
||||
fn b58_script_address_prefix(&self) -> [u8; 2] {
|
||||
self.kind().b58_script_address_prefix()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,334 @@
|
|||
//! Types and implementation for Testnet consensus parameters
|
||||
use std::{collections::BTreeMap, fmt};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
use zcash_primitives::constants as zp_constants;
|
||||
|
||||
use crate::{
|
||||
block::Height,
|
||||
parameters::{
|
||||
network_upgrade::TESTNET_ACTIVATION_HEIGHTS, Network, NetworkUpgrade,
|
||||
NETWORK_UPGRADES_IN_ORDER,
|
||||
},
|
||||
};
|
||||
|
||||
/// Reserved network names that should not be allowed for configured Testnets.
|
||||
pub const RESERVED_NETWORK_NAMES: [&str; 6] = [
|
||||
"Mainnet",
|
||||
"Testnet",
|
||||
"Regtest",
|
||||
"MainnetKind",
|
||||
"TestnetKind",
|
||||
"RegtestKind",
|
||||
];
|
||||
|
||||
/// Maximum length for a configured network name.
|
||||
pub const MAX_NETWORK_NAME_LENGTH: usize = 30;
|
||||
|
||||
/// Maximum length for a configured human-readable prefix.
|
||||
pub const MAX_HRP_LENGTH: usize = 30;
|
||||
|
||||
/// Configurable activation heights for Regtest and configured Testnets.
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct ConfiguredActivationHeights {
|
||||
/// Activation height for `BeforeOverwinter` network upgrade.
|
||||
pub before_overwinter: Option<u32>,
|
||||
/// Activation height for `Overwinter` network upgrade.
|
||||
pub overwinter: Option<u32>,
|
||||
/// Activation height for `Sapling` network upgrade.
|
||||
pub sapling: Option<u32>,
|
||||
/// Activation height for `Blossom` network upgrade.
|
||||
pub blossom: Option<u32>,
|
||||
/// Activation height for `Heartwood` network upgrade.
|
||||
pub heartwood: Option<u32>,
|
||||
/// Activation height for `Canopy` network upgrade.
|
||||
pub canopy: Option<u32>,
|
||||
/// Activation height for `NU5` network upgrade.
|
||||
#[serde(rename = "NU5")]
|
||||
pub nu5: Option<u32>,
|
||||
}
|
||||
|
||||
/// Builder for the [`Parameters`] struct.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
pub struct ParametersBuilder {
|
||||
/// The name of this network to be used by the `Display` trait impl.
|
||||
network_name: String,
|
||||
/// The network upgrade activation heights for this network, see [`Parameters::activation_heights`] for more details.
|
||||
activation_heights: BTreeMap<Height, NetworkUpgrade>,
|
||||
/// Sapling extended spending key human-readable prefix for this network
|
||||
hrp_sapling_extended_spending_key: String,
|
||||
/// Sapling extended full viewing key human-readable prefix for this network
|
||||
hrp_sapling_extended_full_viewing_key: String,
|
||||
/// Sapling payment address human-readable prefix for this network
|
||||
hrp_sapling_payment_address: String,
|
||||
}
|
||||
|
||||
impl Default for ParametersBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
network_name: "UnknownTestnet".to_string(),
|
||||
// # Correctness
|
||||
//
|
||||
// `Genesis` network upgrade activation height must always be 0
|
||||
activation_heights: TESTNET_ACTIVATION_HEIGHTS.iter().cloned().collect(),
|
||||
hrp_sapling_extended_spending_key:
|
||||
zp_constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY.to_string(),
|
||||
hrp_sapling_extended_full_viewing_key:
|
||||
zp_constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY.to_string(),
|
||||
hrp_sapling_payment_address: zp_constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS
|
||||
.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ParametersBuilder {
|
||||
/// Sets the network name to be used in the [`Parameters`] being built.
|
||||
pub fn with_network_name(mut self, network_name: impl fmt::Display) -> Self {
|
||||
self.network_name = network_name.to_string();
|
||||
|
||||
assert!(
|
||||
!RESERVED_NETWORK_NAMES.contains(&self.network_name.as_str()),
|
||||
"cannot use reserved network name '{network_name}' as configured Testnet name, reserved names: {RESERVED_NETWORK_NAMES:?}"
|
||||
);
|
||||
|
||||
assert!(
|
||||
self.network_name.len() <= MAX_NETWORK_NAME_LENGTH,
|
||||
"network name {network_name} is too long, must be {MAX_NETWORK_NAME_LENGTH} characters or less"
|
||||
);
|
||||
|
||||
assert!(
|
||||
self.network_name
|
||||
.chars()
|
||||
.all(|x| x.is_alphanumeric() || x == '_'),
|
||||
"network name must include only alphanumeric characters or '_'"
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that the provided Sapling human-readable prefixes (HRPs) are valid and unique, then
|
||||
/// sets the Sapling HRPs to be used in the [`Parameters`] being built.
|
||||
pub fn with_sapling_hrps(
|
||||
mut self,
|
||||
hrp_sapling_extended_spending_key: impl fmt::Display,
|
||||
hrp_sapling_extended_full_viewing_key: impl fmt::Display,
|
||||
hrp_sapling_payment_address: impl fmt::Display,
|
||||
) -> Self {
|
||||
self.hrp_sapling_extended_spending_key = hrp_sapling_extended_spending_key.to_string();
|
||||
self.hrp_sapling_extended_full_viewing_key =
|
||||
hrp_sapling_extended_full_viewing_key.to_string();
|
||||
self.hrp_sapling_payment_address = hrp_sapling_payment_address.to_string();
|
||||
|
||||
let sapling_hrps = [
|
||||
&self.hrp_sapling_extended_spending_key,
|
||||
&self.hrp_sapling_extended_full_viewing_key,
|
||||
&self.hrp_sapling_payment_address,
|
||||
];
|
||||
|
||||
for sapling_hrp in sapling_hrps {
|
||||
assert!(sapling_hrp.len() <= MAX_HRP_LENGTH, "Sapling human-readable prefix {sapling_hrp} is too long, must be {MAX_HRP_LENGTH} characters or less");
|
||||
assert!(
|
||||
sapling_hrp.chars().all(|c| c.is_ascii_lowercase() || c == '-'),
|
||||
"human-readable prefixes should contain only lowercase ASCII characters and dashes, hrp: {sapling_hrp}"
|
||||
);
|
||||
assert_eq!(
|
||||
sapling_hrps
|
||||
.iter()
|
||||
.filter(|&&hrp| hrp == sapling_hrp)
|
||||
.count(),
|
||||
1,
|
||||
"Sapling human-readable prefixes must be unique, repeated Sapling HRP: {sapling_hrp}"
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that the provided network upgrade activation heights are in the correct order, then
|
||||
/// sets them as the new network upgrade activation heights.
|
||||
pub fn with_activation_heights(
|
||||
mut self,
|
||||
ConfiguredActivationHeights {
|
||||
// TODO: Find out if `BeforeOverwinter` is required at Height(1), allow for
|
||||
// configuring its activation height if it's not required to be at Height(1)
|
||||
before_overwinter: _,
|
||||
overwinter,
|
||||
sapling,
|
||||
blossom,
|
||||
heartwood,
|
||||
canopy,
|
||||
nu5,
|
||||
}: ConfiguredActivationHeights,
|
||||
) -> Self {
|
||||
use NetworkUpgrade::*;
|
||||
|
||||
// # Correctness
|
||||
//
|
||||
// These must be in order so that later network upgrades overwrite prior ones
|
||||
// if multiple network upgrades are configured with the same activation height.
|
||||
let activation_heights: BTreeMap<_, _> = overwinter
|
||||
.into_iter()
|
||||
.map(|h| (h, Overwinter))
|
||||
.chain(sapling.into_iter().map(|h| (h, Sapling)))
|
||||
.chain(blossom.into_iter().map(|h| (h, Blossom)))
|
||||
.chain(heartwood.into_iter().map(|h| (h, Heartwood)))
|
||||
.chain(canopy.into_iter().map(|h| (h, Canopy)))
|
||||
.chain(nu5.into_iter().map(|h| (h, Nu5)))
|
||||
.map(|(h, nu)| (h.try_into().expect("activation height must be valid"), nu))
|
||||
.collect();
|
||||
|
||||
let network_upgrades: Vec<_> = activation_heights.iter().map(|(_h, &nu)| nu).collect();
|
||||
|
||||
// Check that the provided network upgrade activation heights are in the same order by height as the default testnet activation heights
|
||||
let mut activation_heights_iter = activation_heights.iter();
|
||||
for expected_network_upgrade in NETWORK_UPGRADES_IN_ORDER {
|
||||
if !network_upgrades.contains(&expected_network_upgrade) {
|
||||
continue;
|
||||
} else if let Some((&height, &network_upgrade)) = activation_heights_iter.next() {
|
||||
assert_ne!(
|
||||
height,
|
||||
Height(0),
|
||||
"Height(0) is reserved for the `Genesis` upgrade"
|
||||
);
|
||||
|
||||
assert!(
|
||||
network_upgrade == expected_network_upgrade,
|
||||
"network upgrades must be activated in order, the correct order is {NETWORK_UPGRADES_IN_ORDER:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// # Correctness
|
||||
//
|
||||
// Height(0) must be reserved for the `NetworkUpgrade::Genesis`.
|
||||
// TODO: Find out if `BeforeOverwinter` must always be active at Height(1), remove it here if it's not required.
|
||||
self.activation_heights.split_off(&Height(2));
|
||||
self.activation_heights.extend(activation_heights);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Converts the builder to a [`Parameters`] struct
|
||||
pub fn finish(self) -> Parameters {
|
||||
let Self {
|
||||
network_name,
|
||||
activation_heights,
|
||||
hrp_sapling_extended_spending_key,
|
||||
hrp_sapling_extended_full_viewing_key,
|
||||
hrp_sapling_payment_address,
|
||||
} = self;
|
||||
Parameters {
|
||||
network_name,
|
||||
activation_heights,
|
||||
hrp_sapling_extended_spending_key,
|
||||
hrp_sapling_extended_full_viewing_key,
|
||||
hrp_sapling_payment_address,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the builder to a configured [`Network::Testnet`]
|
||||
pub fn to_network(self) -> Network {
|
||||
Network::new_configured_testnet(self.finish())
|
||||
}
|
||||
}
|
||||
|
||||
/// Network consensus parameters for test networks such as Regtest and the default Testnet.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||
pub struct Parameters {}
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
pub struct Parameters {
|
||||
/// The name of this network to be used by the `Display` trait impl.
|
||||
network_name: String,
|
||||
/// The network upgrade activation heights for this network.
|
||||
///
|
||||
/// Note: This value is ignored by `Network::activation_list()` when `zebra-chain` is
|
||||
/// compiled with the `zebra-test` feature flag AND the `TEST_FAKE_ACTIVATION_HEIGHTS`
|
||||
/// environment variable is set.
|
||||
activation_heights: BTreeMap<Height, NetworkUpgrade>,
|
||||
/// Sapling extended spending key human-readable prefix for this network
|
||||
hrp_sapling_extended_spending_key: String,
|
||||
/// Sapling extended full viewing key human-readable prefix for this network
|
||||
hrp_sapling_extended_full_viewing_key: String,
|
||||
/// Sapling payment address human-readable prefix for this network
|
||||
hrp_sapling_payment_address: String,
|
||||
}
|
||||
|
||||
impl Default for Parameters {
|
||||
/// Returns an instance of the default public testnet [`Parameters`].
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
network_name: "Testnet".to_string(),
|
||||
..Self::build().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parameters {
|
||||
/// Creates a new [`ParametersBuilder`].
|
||||
pub fn build() -> ParametersBuilder {
|
||||
ParametersBuilder::default()
|
||||
}
|
||||
|
||||
/// Accepts a [`ConfiguredActivationHeights`].
|
||||
///
|
||||
/// Creates an instance of [`Parameters`] with `Regtest` values.
|
||||
pub fn new_regtest(activation_heights: ConfiguredActivationHeights) -> Self {
|
||||
Self {
|
||||
network_name: "Regtest".to_string(),
|
||||
..Self::build()
|
||||
.with_sapling_hrps(
|
||||
zp_constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||
zp_constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
zp_constants::regtest::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
)
|
||||
// Removes default Testnet activation heights if not configured,
|
||||
// most network upgrades are disabled by default for Regtest in zcashd
|
||||
.with_activation_heights(activation_heights)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the instance of [`Parameters`] represents the default public Testnet.
|
||||
pub fn is_default_testnet(&self) -> bool {
|
||||
self == &Self::default()
|
||||
}
|
||||
|
||||
/// Returns true if the instance of [`Parameters`] represents Regtest.
|
||||
pub fn is_regtest(&self) -> bool {
|
||||
let Self {
|
||||
network_name,
|
||||
hrp_sapling_extended_spending_key,
|
||||
hrp_sapling_extended_full_viewing_key,
|
||||
hrp_sapling_payment_address,
|
||||
..
|
||||
} = Self::new_regtest(ConfiguredActivationHeights::default());
|
||||
|
||||
self.network_name == network_name
|
||||
&& self.hrp_sapling_extended_spending_key == hrp_sapling_extended_spending_key
|
||||
&& self.hrp_sapling_extended_full_viewing_key == hrp_sapling_extended_full_viewing_key
|
||||
&& self.hrp_sapling_payment_address == hrp_sapling_payment_address
|
||||
}
|
||||
|
||||
/// Returns the network name
|
||||
pub fn network_name(&self) -> &str {
|
||||
&self.network_name
|
||||
}
|
||||
|
||||
/// Returns the network upgrade activation heights
|
||||
pub fn activation_heights(&self) -> &BTreeMap<Height, NetworkUpgrade> {
|
||||
&self.activation_heights
|
||||
}
|
||||
|
||||
/// Returns the `hrp_sapling_extended_spending_key` field
|
||||
pub fn hrp_sapling_extended_spending_key(&self) -> &str {
|
||||
&self.hrp_sapling_extended_spending_key
|
||||
}
|
||||
|
||||
/// Returns the `hrp_sapling_extended_full_viewing_key` field
|
||||
pub fn hrp_sapling_extended_full_viewing_key(&self) -> &str {
|
||||
&self.hrp_sapling_extended_full_viewing_key
|
||||
}
|
||||
|
||||
/// Returns the `hrp_sapling_payment_address` field
|
||||
pub fn hrp_sapling_payment_address(&self) -> &str {
|
||||
&self.hrp_sapling_payment_address
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
mod prop;
|
||||
mod vectors;
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
//! Fixed test vectors for the network consensus parameters.
|
||||
|
||||
use zcash_primitives::{
|
||||
consensus::{self as zp_consensus, Parameters},
|
||||
constants as zp_constants,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
block::Height,
|
||||
parameters::{
|
||||
testnet::{
|
||||
self, ConfiguredActivationHeights, MAX_HRP_LENGTH, MAX_NETWORK_NAME_LENGTH,
|
||||
RESERVED_NETWORK_NAMES,
|
||||
},
|
||||
Network, NetworkUpgrade, MAINNET_ACTIVATION_HEIGHTS, NETWORK_UPGRADES_IN_ORDER,
|
||||
TESTNET_ACTIVATION_HEIGHTS,
|
||||
},
|
||||
};
|
||||
|
||||
/// Checks that every method in the `Parameters` impl for `zebra_chain::Network` has the same output
|
||||
/// as the Parameters impl for `zcash_primitives::consensus::Network` on Mainnet and the default Testnet.
|
||||
#[test]
|
||||
fn check_parameters_impl() {
|
||||
let zp_network_upgrades = [
|
||||
zp_consensus::NetworkUpgrade::Overwinter,
|
||||
zp_consensus::NetworkUpgrade::Sapling,
|
||||
zp_consensus::NetworkUpgrade::Blossom,
|
||||
zp_consensus::NetworkUpgrade::Heartwood,
|
||||
zp_consensus::NetworkUpgrade::Canopy,
|
||||
zp_consensus::NetworkUpgrade::Nu5,
|
||||
];
|
||||
|
||||
for (network, zp_network) in [
|
||||
(Network::Mainnet, zp_consensus::Network::MainNetwork),
|
||||
(
|
||||
Network::new_default_testnet(),
|
||||
zp_consensus::Network::TestNetwork,
|
||||
),
|
||||
] {
|
||||
for nu in zp_network_upgrades {
|
||||
let activation_height = network
|
||||
.activation_height(nu)
|
||||
.expect("must have activation height for past network upgrades");
|
||||
|
||||
assert_eq!(
|
||||
activation_height,
|
||||
zp_network
|
||||
.activation_height(nu)
|
||||
.expect("must have activation height for past network upgrades"),
|
||||
"Parameters::activation_heights() outputs must match"
|
||||
);
|
||||
|
||||
let activation_height: u32 = activation_height.into();
|
||||
|
||||
for height in (activation_height - 1)..=(activation_height + 1) {
|
||||
for nu in zp_network_upgrades {
|
||||
let height = zp_consensus::BlockHeight::from_u32(height);
|
||||
assert_eq!(
|
||||
network.is_nu_active(nu, height),
|
||||
zp_network.is_nu_active(nu, height),
|
||||
"Parameters::is_nu_active() outputs must match",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
network.coin_type(),
|
||||
zp_network.coin_type(),
|
||||
"Parameters::coin_type() outputs must match"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_extended_spending_key(),
|
||||
zp_network.hrp_sapling_extended_spending_key(),
|
||||
"Parameters::hrp_sapling_extended_spending_key() outputs must match"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_extended_full_viewing_key(),
|
||||
zp_network.hrp_sapling_extended_full_viewing_key(),
|
||||
"Parameters::hrp_sapling_extended_full_viewing_key() outputs must match"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_payment_address(),
|
||||
zp_network.hrp_sapling_payment_address(),
|
||||
"Parameters::hrp_sapling_payment_address() outputs must match"
|
||||
);
|
||||
assert_eq!(
|
||||
network.b58_pubkey_address_prefix(),
|
||||
zp_network.b58_pubkey_address_prefix(),
|
||||
"Parameters::b58_pubkey_address_prefix() outputs must match"
|
||||
);
|
||||
assert_eq!(
|
||||
network.b58_script_address_prefix(),
|
||||
zp_network.b58_script_address_prefix(),
|
||||
"Parameters::b58_script_address_prefix() outputs must match"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that `NetworkUpgrade::activation_height()` returns the activation height of the next
|
||||
/// network upgrade if it doesn't find an activation height for a prior network upgrade, that the
|
||||
/// `Genesis` upgrade is always at `Height(0)`, and that the default Mainnet/Testnet/Regtest activation
|
||||
/// heights are what's expected.
|
||||
#[test]
|
||||
fn activates_network_upgrades_correctly() {
|
||||
let expected_activation_height = 1;
|
||||
let network = testnet::Parameters::build()
|
||||
.with_activation_heights(ConfiguredActivationHeights {
|
||||
nu5: Some(expected_activation_height),
|
||||
..Default::default()
|
||||
})
|
||||
.to_network();
|
||||
|
||||
let genesis_activation_height = NetworkUpgrade::Genesis
|
||||
.activation_height(&network)
|
||||
.expect("must return an activation height");
|
||||
|
||||
assert_eq!(
|
||||
genesis_activation_height,
|
||||
Height(0),
|
||||
"activation height for all networks after Genesis and BeforeOverwinter should match NU5 activation height"
|
||||
);
|
||||
|
||||
for nu in NETWORK_UPGRADES_IN_ORDER.into_iter().skip(1) {
|
||||
let activation_height = nu
|
||||
.activation_height(&network)
|
||||
.expect("must return an activation height");
|
||||
|
||||
assert_eq!(
|
||||
activation_height, Height(expected_activation_height),
|
||||
"activation height for all networks after Genesis and BeforeOverwinter \
|
||||
should match NU5 activation height, network_upgrade: {nu}, activation_height: {activation_height:?}"
|
||||
);
|
||||
}
|
||||
|
||||
let expected_default_regtest_activation_heights = &[
|
||||
(Height(0), NetworkUpgrade::Genesis),
|
||||
(Height(1), NetworkUpgrade::BeforeOverwinter),
|
||||
];
|
||||
|
||||
for (network, expected_activation_heights) in [
|
||||
(Network::Mainnet, MAINNET_ACTIVATION_HEIGHTS),
|
||||
(Network::new_default_testnet(), TESTNET_ACTIVATION_HEIGHTS),
|
||||
(
|
||||
Network::new_regtest(Default::default()),
|
||||
expected_default_regtest_activation_heights,
|
||||
),
|
||||
] {
|
||||
assert_eq!(
|
||||
network.activation_list(),
|
||||
expected_activation_heights.iter().cloned().collect(),
|
||||
"network activation list should match expected activation heights"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that configured testnet names are validated and used correctly.
|
||||
#[test]
|
||||
fn check_configured_network_name() {
|
||||
// Sets a no-op panic hook to avoid long output.
|
||||
std::panic::set_hook(Box::new(|_| {}));
|
||||
|
||||
// Checks that reserved network names cannot be used for configured testnets.
|
||||
for reserved_network_name in RESERVED_NETWORK_NAMES {
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_network_name(reserved_network_name)
|
||||
})
|
||||
.expect_err("should panic when attempting to set network name as a reserved name");
|
||||
}
|
||||
|
||||
// Check that max length is enforced, and that network names may only contain alphanumeric characters and '_'.
|
||||
for invalid_network_name in [
|
||||
"a".repeat(MAX_NETWORK_NAME_LENGTH + 1),
|
||||
"!!!!non-alphanumeric-name".to_string(),
|
||||
] {
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_network_name(invalid_network_name)
|
||||
})
|
||||
.expect_err("should panic when setting network name that's too long or contains non-alphanumeric characters (except '_')");
|
||||
}
|
||||
|
||||
drop(std::panic::take_hook());
|
||||
|
||||
// Checks that network names are displayed correctly
|
||||
assert_eq!(
|
||||
Network::new_default_testnet().to_string(),
|
||||
"Testnet",
|
||||
"default testnet should be displayed as 'Testnet'"
|
||||
);
|
||||
assert_eq!(
|
||||
Network::Mainnet.to_string(),
|
||||
"Mainnet",
|
||||
"Mainnet should be displayed as 'Mainnet'"
|
||||
);
|
||||
assert_eq!(
|
||||
Network::new_regtest(Default::default()).to_string(),
|
||||
"Regtest",
|
||||
"Regtest should be displayed as 'Regtest'"
|
||||
);
|
||||
|
||||
// Check that network name can contain alphanumeric characters and '_'.
|
||||
let expected_name = "ConfiguredTestnet_1";
|
||||
let network = testnet::Parameters::build()
|
||||
// Check that network name can contain `MAX_NETWORK_NAME_LENGTH` characters
|
||||
.with_network_name("a".repeat(MAX_NETWORK_NAME_LENGTH))
|
||||
.with_network_name(expected_name)
|
||||
.to_network();
|
||||
|
||||
// Check that configured network name is displayed
|
||||
assert_eq!(
|
||||
network.to_string(),
|
||||
expected_name,
|
||||
"network must be displayed as configured network name"
|
||||
);
|
||||
}
|
||||
|
||||
/// Checks that configured Sapling human-readable prefixes (HRPs) are validated and used correctly.
|
||||
#[test]
|
||||
fn check_configured_sapling_hrps() {
|
||||
// Sets a no-op panic hook to avoid long output.
|
||||
std::panic::set_hook(Box::new(|_| {}));
|
||||
|
||||
// Check that configured Sapling HRPs must be unique.
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_sapling_hrps("", "", "");
|
||||
})
|
||||
.expect_err("should panic when setting non-unique Sapling HRPs");
|
||||
|
||||
// Check that max length is enforced, and that network names may only contain lowecase ASCII characters and dashes.
|
||||
for invalid_hrp in [
|
||||
"a".repeat(MAX_NETWORK_NAME_LENGTH + 1),
|
||||
"!!!!non-alphabetical-name".to_string(),
|
||||
"A".to_string(),
|
||||
] {
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_sapling_hrps(invalid_hrp, "dummy-hrp-a", "dummy-hrp-b");
|
||||
})
|
||||
.expect_err("should panic when setting Sapling HRPs that are too long or contain non-alphanumeric characters (except '-')");
|
||||
}
|
||||
|
||||
drop(std::panic::take_hook());
|
||||
|
||||
// Check that Sapling HRPs can contain lowercase ascii characters and dashes.
|
||||
let expected_hrp_sapling_extended_spending_key = "sapling-hrp-a";
|
||||
let expected_hrp_sapling_extended_full_viewing_key = "sapling-hrp-b";
|
||||
let expected_hrp_sapling_payment_address = "sapling-hrp-c";
|
||||
|
||||
let network = testnet::Parameters::build()
|
||||
// Check that Sapling HRPs can contain `MAX_HRP_LENGTH` characters
|
||||
.with_sapling_hrps("a".repeat(MAX_HRP_LENGTH), "dummy-hrp-a", "dummy-hrp-b")
|
||||
.with_sapling_hrps(
|
||||
expected_hrp_sapling_extended_spending_key,
|
||||
expected_hrp_sapling_extended_full_viewing_key,
|
||||
expected_hrp_sapling_payment_address,
|
||||
)
|
||||
.to_network();
|
||||
|
||||
// Check that configured Sapling HRPs are returned by `Parameters` trait methods
|
||||
assert_eq!(
|
||||
network.hrp_sapling_extended_spending_key(),
|
||||
expected_hrp_sapling_extended_spending_key,
|
||||
"should return expected Sapling extended spending key HRP"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_extended_full_viewing_key(),
|
||||
expected_hrp_sapling_extended_full_viewing_key,
|
||||
"should return expected Sapling EFVK HRP"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_payment_address(),
|
||||
expected_hrp_sapling_payment_address,
|
||||
"should return expected Sapling payment address HRP"
|
||||
);
|
||||
|
||||
// Check that default Mainnet, Testnet, and Regtest HRPs are valid, these calls will panic
|
||||
// if any of the values fail validation.
|
||||
testnet::Parameters::build()
|
||||
.with_sapling_hrps(
|
||||
zp_constants::mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||
zp_constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
zp_constants::mainnet::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
)
|
||||
.with_sapling_hrps(
|
||||
zp_constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||
zp_constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
zp_constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
)
|
||||
.with_sapling_hrps(
|
||||
zp_constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||
zp_constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
zp_constants::regtest::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
);
|
||||
}
|
||||
|
||||
/// Checks that configured testnet names are validated and used correctly.
|
||||
#[test]
|
||||
fn check_network_name() {
|
||||
// Sets a no-op panic hook to avoid long output.
|
||||
std::panic::set_hook(Box::new(|_| {}));
|
||||
|
||||
// Checks that reserved network names cannot be used for configured testnets.
|
||||
for reserved_network_name in RESERVED_NETWORK_NAMES {
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_network_name(reserved_network_name)
|
||||
})
|
||||
.expect_err("should panic when attempting to set network name as a reserved name");
|
||||
}
|
||||
|
||||
// Check that max length is enforced, and that network names may only contain alphanumeric characters and '_'.
|
||||
for invalid_network_name in [
|
||||
"a".repeat(MAX_NETWORK_NAME_LENGTH + 1),
|
||||
"!!!!non-alphanumeric-name".to_string(),
|
||||
] {
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_network_name(invalid_network_name)
|
||||
})
|
||||
.expect_err("should panic when setting network name that's too long or contains non-alphanumeric characters (except '_')");
|
||||
}
|
||||
|
||||
drop(std::panic::take_hook());
|
||||
|
||||
// Checks that network names are displayed correctly
|
||||
assert_eq!(
|
||||
Network::new_default_testnet().to_string(),
|
||||
"Testnet",
|
||||
"default testnet should be displayed as 'Testnet'"
|
||||
);
|
||||
assert_eq!(
|
||||
Network::Mainnet.to_string(),
|
||||
"Mainnet",
|
||||
"Mainnet should be displayed as 'Mainnet'"
|
||||
);
|
||||
|
||||
// TODO: Check Regtest
|
||||
|
||||
// Check that network name can contain alphanumeric characters and '_'.
|
||||
let expected_name = "ConfiguredTestnet_1";
|
||||
let network = testnet::Parameters::build()
|
||||
// Check that network name can contain `MAX_NETWORK_NAME_LENGTH` characters
|
||||
.with_network_name("a".repeat(MAX_NETWORK_NAME_LENGTH))
|
||||
.with_network_name(expected_name)
|
||||
.to_network();
|
||||
|
||||
// Check that configured network name is displayed
|
||||
assert_eq!(
|
||||
network.to_string(),
|
||||
expected_name,
|
||||
"network must be displayed as configured network name"
|
||||
);
|
||||
}
|
|
@ -7,7 +7,6 @@ use crate::parameters::{Network, Network::*};
|
|||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::fmt;
|
||||
use std::ops::Bound::*;
|
||||
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use hex::{FromHex, ToHex};
|
||||
|
@ -15,6 +14,18 @@ use hex::{FromHex, ToHex};
|
|||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
|
||||
/// A list of network upgrades in the order that they must be activated.
|
||||
pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 8] = [
|
||||
Genesis,
|
||||
BeforeOverwinter,
|
||||
Overwinter,
|
||||
Sapling,
|
||||
Blossom,
|
||||
Heartwood,
|
||||
Canopy,
|
||||
Nu5,
|
||||
];
|
||||
|
||||
/// A Zcash network upgrade.
|
||||
///
|
||||
/// Network upgrades can change the Zcash network protocol or consensus rules in
|
||||
|
@ -242,12 +253,7 @@ impl Network {
|
|||
/// and it's a test build, this returns a list of fake activation heights
|
||||
/// used by some tests.
|
||||
pub fn activation_list(&self) -> BTreeMap<block::Height, NetworkUpgrade> {
|
||||
let (mainnet_heights, testnet_heights) = {
|
||||
#[cfg(not(feature = "zebra-test"))]
|
||||
{
|
||||
(MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS)
|
||||
}
|
||||
|
||||
match self {
|
||||
// To prevent accidentally setting this somehow, only check the env var
|
||||
// when being compiled for tests. We can't use cfg(test) since the
|
||||
// test that uses this is in zebra-state, and cfg(test) is not
|
||||
|
@ -260,25 +266,19 @@ impl Network {
|
|||
// feature should only be enabled for tests:
|
||||
// https://doc.rust-lang.org/cargo/reference/features.html#resolver-version-2-command-line-flags
|
||||
#[cfg(feature = "zebra-test")]
|
||||
if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() {
|
||||
(
|
||||
FAKE_MAINNET_ACTIVATION_HEIGHTS,
|
||||
FAKE_TESTNET_ACTIVATION_HEIGHTS,
|
||||
)
|
||||
} else {
|
||||
(MAINNET_ACTIVATION_HEIGHTS, TESTNET_ACTIVATION_HEIGHTS)
|
||||
Mainnet if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() => {
|
||||
FAKE_MAINNET_ACTIVATION_HEIGHTS.iter().cloned().collect()
|
||||
}
|
||||
};
|
||||
match self {
|
||||
Mainnet => mainnet_heights,
|
||||
// TODO: Add an `activation_heights` field to `testnet::Parameters` to return here. (#7970)
|
||||
Testnet(_params) => testnet_heights,
|
||||
#[cfg(feature = "zebra-test")]
|
||||
Testnet(_) if std::env::var_os("TEST_FAKE_ACTIVATION_HEIGHTS").is_some() => {
|
||||
FAKE_TESTNET_ACTIVATION_HEIGHTS.iter().cloned().collect()
|
||||
}
|
||||
Mainnet => MAINNET_ACTIVATION_HEIGHTS.iter().cloned().collect(),
|
||||
Testnet(params) => params.activation_heights().clone(),
|
||||
}
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkUpgrade {
|
||||
/// Returns the current network upgrade for `network` and `height`.
|
||||
pub fn current(network: &Network, height: block::Height) -> NetworkUpgrade {
|
||||
|
@ -290,11 +290,28 @@ impl NetworkUpgrade {
|
|||
.expect("every height has a current network upgrade")
|
||||
}
|
||||
|
||||
/// Returns the next expected network upgrade after this network upgrade
|
||||
pub fn next_upgrade(self) -> Option<Self> {
|
||||
match self {
|
||||
Genesis => Some(BeforeOverwinter),
|
||||
BeforeOverwinter => Some(Overwinter),
|
||||
Overwinter => Some(Sapling),
|
||||
Sapling => Some(Blossom),
|
||||
Blossom => Some(Heartwood),
|
||||
Heartwood => Some(Canopy),
|
||||
Canopy => Some(Nu5),
|
||||
Nu5 => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the next network upgrade for `network` and `height`.
|
||||
///
|
||||
/// Returns None if the next upgrade has not been implemented in Zebra
|
||||
/// yet.
|
||||
#[cfg(test)]
|
||||
pub fn next(network: &Network, height: block::Height) -> Option<NetworkUpgrade> {
|
||||
use std::ops::Bound::*;
|
||||
|
||||
network
|
||||
.activation_list()
|
||||
.range((Excluded(height), Unbounded))
|
||||
|
@ -302,17 +319,27 @@ impl NetworkUpgrade {
|
|||
.next()
|
||||
}
|
||||
|
||||
/// Returns the activation height for this network upgrade on `network`.
|
||||
/// Returns the activation height for this network upgrade on `network`, or
|
||||
///
|
||||
/// Returns the activation height of the first network upgrade that follows
|
||||
/// this network upgrade if there is no activation height for this network upgrade
|
||||
/// such as on Regtest or a configured Testnet where multiple network upgrades have the
|
||||
/// same activation height, or if one is omitted when others that follow it are included.
|
||||
///
|
||||
/// Returns None if this network upgrade is a future upgrade, and its
|
||||
/// activation height has not been set yet.
|
||||
///
|
||||
/// Returns None if this network upgrade has not been configured on a Testnet or Regtest.
|
||||
pub fn activation_height(&self, network: &Network) -> Option<block::Height> {
|
||||
network
|
||||
.activation_list()
|
||||
.iter()
|
||||
.filter(|(_, nu)| nu == &self)
|
||||
.find(|(_, nu)| nu == &self)
|
||||
.map(|(height, _)| *height)
|
||||
.next()
|
||||
.or_else(|| {
|
||||
self.next_upgrade()
|
||||
.and_then(|next_nu| next_nu.activation_height(network))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if `height` is the activation height of any network upgrade
|
||||
|
|
|
@ -53,7 +53,7 @@ impl ZcashDeserialize for Bctv14Proof {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Arbitrary for Bctv14Proof {
|
||||
|
|
|
@ -65,7 +65,7 @@ impl ZcashDeserialize for Groth16Proof {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Arbitrary for Groth16Proof {
|
||||
|
|
|
@ -36,7 +36,7 @@ impl ZcashDeserialize for Halo2Proof {
|
|||
}
|
||||
}
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest::{arbitrary::Arbitrary, prelude::*};
|
||||
use proptest::prelude::*;
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Arbitrary for Halo2Proof {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
mod tests;
|
||||
|
||||
use std::{collections::BTreeMap, convert::TryInto, io, sync::Arc};
|
||||
use std::{collections::BTreeMap, io, sync::Arc};
|
||||
|
||||
use serde_big_array::BigArray;
|
||||
pub use zcash_history::{V1, V2};
|
||||
|
|
|
@ -22,29 +22,11 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh
|
|||
|
||||
let alt_height = height.0.into();
|
||||
let null_sapling_ovk = zcash_primitives::keys::OutgoingViewingKey([0u8; 32]);
|
||||
let network = match network {
|
||||
Network::Mainnet => zcash_primitives::consensus::Network::MainNetwork,
|
||||
Network::Testnet(params) => {
|
||||
// # Correctness:
|
||||
//
|
||||
// There are differences between the `TestNetwork` parameters and those returned by
|
||||
// `CRegTestParams()` in zcashd, so this function can't return `TestNetwork` unless
|
||||
// Zebra is using the default public Testnet.
|
||||
//
|
||||
// TODO: Remove this conversion by implementing `zcash_primitives::consensus::Parameters`
|
||||
// for `Network` (#8365).
|
||||
assert!(
|
||||
params.is_default_testnet(),
|
||||
"could not convert configured testnet to zcash_primitives::consensus::Network"
|
||||
);
|
||||
zcash_primitives::consensus::Network::TestNetwork
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(bundle) = alt_tx.sapling_bundle() {
|
||||
for output in bundle.shielded_outputs().iter() {
|
||||
let recovery = zcash_primitives::sapling::note_encryption::try_sapling_output_recovery(
|
||||
&network,
|
||||
network,
|
||||
alt_height,
|
||||
&null_sapling_ovk,
|
||||
output,
|
||||
|
|
|
@ -5,7 +5,7 @@ use jubjub::{AffinePoint, ExtendedPoint};
|
|||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaChaRng;
|
||||
|
||||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use crate::primitives::Groth16Proof;
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//! Note and value commitments.
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt, io,
|
||||
};
|
||||
use std::{fmt, io};
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use jubjub::ExtendedPoint;
|
||||
|
|
|
@ -16,7 +16,7 @@ use rand_core::{CryptoRng, RngCore};
|
|||
|
||||
use crate::{
|
||||
error::{AddressError, RandError},
|
||||
primitives::redjubjub::{self, SpendAuth},
|
||||
primitives::redjubjub::SpendAuth,
|
||||
serialization::{
|
||||
serde_helpers, ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize,
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -3,14 +3,11 @@
|
|||
//! Zebra uses a generic spend type for `V4` and `V5` transactions.
|
||||
//! The anchor change is handled using the `AnchorVariant` type trait.
|
||||
|
||||
use std::{convert::TryInto, fmt, io};
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::{
|
||||
block::MAX_BLOCK_BYTES,
|
||||
primitives::{
|
||||
redjubjub::{self, SpendAuth},
|
||||
Groth16Proof,
|
||||
},
|
||||
primitives::{redjubjub::SpendAuth, Groth16Proof},
|
||||
serialization::{
|
||||
ReadZcashExt, SerializationError, TrustedPreallocate, WriteZcashExt, ZcashDeserialize,
|
||||
ZcashDeserializeInto, ZcashSerialize,
|
||||
|
|
|
@ -8,7 +8,6 @@ use crate::{
|
|||
serialization::{ZcashDeserializeInto, ZcashSerialize},
|
||||
transaction::{LockTime, Transaction},
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
proptest! {
|
||||
/// Serialize and deserialize `Spend<PerSpendAnchor>`
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::{
|
|||
};
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use bridgetree::{self, NonEmptyFrontier};
|
||||
use bridgetree::NonEmptyFrontier;
|
||||
use hex::ToHex;
|
||||
use incrementalmerkletree::{frontier::Frontier, Hashable};
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
//! Arbitrary data generation for serialization proptests
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use proptest::{arbitrary::any, prelude::*};
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::{
|
||||
CompactSizeMessage, DateTime32, TrustedPreallocate, ZcashSerialize, MAX_PROTOCOL_MESSAGE_LEN,
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
//! - [`CompactSizeMessage`] for sizes that must be less than the network message limit, and
|
||||
//! - [`CompactSize64`] for flags, arbitrary counts, and sizes that span multiple blocks.
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use crate::serialization::{
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//! Serialization constraint helpers.
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
ops::Deref,
|
||||
};
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::serialization::SerializationError;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use proptest::{collection::size_range, prelude::*};
|
||||
|
||||
use std::{convert::TryInto, matches};
|
||||
use std::matches;
|
||||
|
||||
use crate::serialization::{
|
||||
arbitrary::max_allocation_is_big_enough, zcash_deserialize::MAX_U8_ALLOCATION,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, array, prelude::*};
|
||||
use proptest::{array, prelude::*};
|
||||
|
||||
use crate::{
|
||||
amount::{Amount, NonNegative},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
impl Arbitrary for super::EncryptedNote {
|
||||
type Parameters = ();
|
||||
|
|
|
@ -30,7 +30,9 @@ impl Network {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns blocks indexed by height in a [`BTreeMap`].
|
||||
///
|
||||
/// Returns Mainnet blocks if `self` is set to Mainnet, and Testnet blocks otherwise.
|
||||
pub fn block_map(&self) -> BTreeMap<u32, &'static [u8]> {
|
||||
if self.is_mainnet() {
|
||||
zebra_test::vectors::MAINNET_BLOCKS.clone()
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
//! Arbitrary data generation for transaction proptests
|
||||
|
||||
use std::{
|
||||
cmp::max,
|
||||
collections::HashMap,
|
||||
convert::{TryFrom, TryInto},
|
||||
ops::Neg,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{cmp::max, collections::HashMap, ops::Neg, sync::Arc};
|
||||
|
||||
use chrono::{TimeZone, Utc};
|
||||
use proptest::{
|
||||
arbitrary::any, array, collection::vec, option, prelude::*, test_runner::TestRunner,
|
||||
};
|
||||
use proptest::{array, collection::vec, option, prelude::*, test_runner::TestRunner};
|
||||
use reddsa::{orchard::Binding, Signature};
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -28,11 +28,7 @@
|
|||
//!
|
||||
//! [1]: crate::transaction::UnminedTx
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{fmt, sync::Arc};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use proptest_derive::Arbitrary;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{cmp, convert::TryFrom, fmt};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
/// A 512-byte (plaintext) memo associated with a note, as described in
|
||||
/// [protocol specification §5.5][ps].
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! Contains impls of `ZcashSerialize`, `ZcashDeserialize` for all of the
|
||||
//! transaction types, so that all of the serialization logic is in one place.
|
||||
|
||||
use std::{borrow::Borrow, convert::TryInto, io, sync::Arc};
|
||||
use std::{borrow::Borrow, io, sync::Arc};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use halo2::pasta::{group::ff::PrimeField, pallas};
|
||||
use halo2::pasta::group::ff::PrimeField;
|
||||
use hex::FromHex;
|
||||
use reddsa::{orchard::Binding, orchard::SpendAuth, Signature};
|
||||
|
||||
|
@ -12,13 +12,12 @@ use crate::{
|
|||
amount,
|
||||
block::MAX_BLOCK_BYTES,
|
||||
parameters::{OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID},
|
||||
primitives::{Groth16Proof, Halo2Proof, ZkSnarkProof},
|
||||
primitives::{Halo2Proof, ZkSnarkProof},
|
||||
serialization::{
|
||||
zcash_deserialize_external_count, zcash_serialize_empty_list,
|
||||
zcash_serialize_external_count, AtLeastOne, ReadZcashExt, SerializationError,
|
||||
TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize,
|
||||
},
|
||||
sprout,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
//! Fixed test vectors for transactions.
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use chrono::DateTime;
|
||||
use color_eyre::eyre::Result;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::{
|
||||
amount::Amount,
|
||||
block::{Block, Height, MAX_BLOCK_BYTES},
|
||||
parameters::{Network, NetworkUpgrade},
|
||||
parameters::Network,
|
||||
serialization::{SerializationError, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize},
|
||||
transaction::{hash::WtxId, sighash::SigHasher, txid::TxIdBuilder, Transaction},
|
||||
transaction::{sighash::SigHasher, txid::TxIdBuilder},
|
||||
transparent::Script,
|
||||
};
|
||||
|
||||
|
@ -221,13 +220,6 @@ fn deserialize_large_transaction() {
|
|||
let output =
|
||||
transparent::Output::zcash_deserialize(&zebra_test::vectors::DUMMY_OUTPUT1[..]).unwrap();
|
||||
|
||||
// Create a lock time.
|
||||
let lock_time = LockTime::Time(DateTime::<Utc>::from_naive_utc_and_offset(
|
||||
NaiveDateTime::from_timestamp_opt(61, 0)
|
||||
.expect("in-range number of seconds and valid nanosecond"),
|
||||
Utc,
|
||||
));
|
||||
|
||||
// Serialize the input so that we can determine its serialized size.
|
||||
let mut input_data = Vec::new();
|
||||
input
|
||||
|
@ -242,14 +234,12 @@ fn deserialize_large_transaction() {
|
|||
.take(tx_inputs_num)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let outputs = vec![output];
|
||||
|
||||
// Create an oversized transaction. Adding the output and lock time causes
|
||||
// the transaction to overflow the threshold.
|
||||
let oversized_tx = Transaction::V1 {
|
||||
inputs,
|
||||
outputs,
|
||||
lock_time,
|
||||
outputs: vec![output],
|
||||
lock_time: LockTime::Time(DateTime::from_timestamp(61, 0).unwrap()),
|
||||
};
|
||||
|
||||
// Serialize the transaction.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Transaction ID computation. Contains code for generating the Transaction ID
|
||||
//! from the transaction.
|
||||
use std::{convert::TryInto, io};
|
||||
use std::io;
|
||||
|
||||
use super::{Hash, Transaction};
|
||||
use crate::serialization::{sha256d, ZcashSerialize};
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
use std::{fmt, io};
|
||||
|
||||
use ripemd::{Digest, Ripemd160};
|
||||
use secp256k1::PublicKey;
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::{
|
||||
parameters::NetworkKind,
|
||||
serialization::{SerializationError, ZcashDeserialize, ZcashSerialize},
|
||||
|
@ -154,29 +150,6 @@ impl ZcashDeserialize for Address {
|
|||
}
|
||||
}
|
||||
|
||||
trait ToAddressWithNetwork {
|
||||
/// Convert `self` to an `Address`, given the current `network`.
|
||||
fn to_address(&self, network: NetworkKind) -> Address;
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for Script {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToScriptHash {
|
||||
network_kind,
|
||||
script_hash: Address::hash_payload(self.as_raw_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for PublicKey {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToPublicKeyHash {
|
||||
network_kind,
|
||||
pub_key_hash: Address::hash_payload(&self.serialize()[..]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Address {
|
||||
/// Create an address for the given public key hash and network.
|
||||
pub fn from_pub_key_hash(network_kind: NetworkKind, pub_key_hash: [u8; 20]) -> Self {
|
||||
|
@ -219,21 +192,6 @@ impl Address {
|
|||
}
|
||||
}
|
||||
|
||||
/// A hash of a transparent address payload, as used in
|
||||
/// transparent pay-to-script-hash and pay-to-publickey-hash
|
||||
/// addresses.
|
||||
///
|
||||
/// The resulting hash in both of these cases is always exactly 20
|
||||
/// bytes.
|
||||
/// <https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address>
|
||||
fn hash_payload(bytes: &[u8]) -> [u8; 20] {
|
||||
let sha_hash = Sha256::digest(bytes);
|
||||
let ripe_hash = Ripemd160::digest(sha_hash);
|
||||
let mut payload = [0u8; 20];
|
||||
payload[..].copy_from_slice(&ripe_hash[..]);
|
||||
payload
|
||||
}
|
||||
|
||||
/// Given a transparent address (P2SH or a P2PKH), create a script that can be used in a coinbase
|
||||
/// transaction output.
|
||||
pub fn create_script_from_address(&self) -> Script {
|
||||
|
@ -264,11 +222,53 @@ impl Address {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use ripemd::{Digest, Ripemd160};
|
||||
use secp256k1::PublicKey;
|
||||
use sha2::Sha256;
|
||||
|
||||
use super::*;
|
||||
|
||||
trait ToAddressWithNetwork {
|
||||
/// Convert `self` to an `Address`, given the current `network`.
|
||||
fn to_address(&self, network: NetworkKind) -> Address;
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for Script {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToScriptHash {
|
||||
network_kind,
|
||||
script_hash: Address::hash_payload(self.as_raw_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAddressWithNetwork for PublicKey {
|
||||
fn to_address(&self, network_kind: NetworkKind) -> Address {
|
||||
Address::PayToPublicKeyHash {
|
||||
network_kind,
|
||||
pub_key_hash: Address::hash_payload(&self.serialize()[..]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Address {
|
||||
/// A hash of a transparent address payload, as used in
|
||||
/// transparent pay-to-script-hash and pay-to-publickey-hash
|
||||
/// addresses.
|
||||
///
|
||||
/// The resulting hash in both of these cases is always exactly 20
|
||||
/// bytes.
|
||||
/// <https://en.bitcoin.it/Base58Check_encoding#Encoding_a_Bitcoin_address>
|
||||
#[allow(dead_code)]
|
||||
fn hash_payload(bytes: &[u8]) -> [u8; 20] {
|
||||
let sha_hash = Sha256::digest(bytes);
|
||||
let ripe_hash = Ripemd160::digest(sha_hash);
|
||||
let mut payload = [0u8; 20];
|
||||
payload[..].copy_from_slice(&ripe_hash[..]);
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pubkey_mainnet() {
|
||||
let _init_guard = zebra_test::init();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use crate::{block, parameters::NetworkKind, LedgerState};
|
||||
|
||||
|
|
|
@ -95,7 +95,6 @@ mod proptests {
|
|||
use proptest::prelude::*;
|
||||
|
||||
use super::*;
|
||||
use crate::serialization::{ZcashDeserialize, ZcashSerialize};
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Unspent transparent output data structures and functions.
|
||||
|
||||
use std::{collections::HashMap, convert::TryInto};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
block::{self, Block, Height},
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
transparent,
|
||||
};
|
||||
|
||||
use std::{borrow::Borrow, collections::HashMap, convert::TryInto};
|
||||
use std::{borrow::Borrow, collections::HashMap};
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
use crate::{amount::MAX_MONEY, transaction::Transaction};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
impl Arbitrary for equihash::Solution {
|
||||
type Parameters = ();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
use crate::block;
|
||||
|
||||
use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
impl Arbitrary for CompactDifficulty {
|
||||
type Parameters = ();
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use proptest::{arbitrary::any, prelude::*};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::block;
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
use proptest::{arbitrary::any, prelude::*, test_runner::Config};
|
||||
use proptest::{prelude::*, test_runner::Config};
|
||||
|
||||
use crate::{
|
||||
block::{self, Block},
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use crate::{
|
||||
block::{Block, MAX_BLOCK_BYTES},
|
||||
serialization::{CompactSizeMessage, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize},
|
||||
|
|
|
@ -43,16 +43,16 @@ jubjub = "0.10.0"
|
|||
rand = "0.8.5"
|
||||
rayon = "1.10.0"
|
||||
|
||||
chrono = { version = "0.4.34", default-features = false, features = ["clock", "std"] }
|
||||
chrono = { version = "0.4.38", default-features = false, features = ["clock", "std"] }
|
||||
displaydoc = "0.2.4"
|
||||
lazy_static = "1.4.0"
|
||||
once_cell = "1.18.0"
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
|
||||
futures = "0.3.30"
|
||||
futures-util = "0.3.28"
|
||||
metrics = "0.22.3"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
tokio = { version = "1.37.0", features = ["time", "sync", "tracing", "rt-multi-thread"] }
|
||||
tower = { version = "0.4.13", features = ["timeout", "util", "buffer"] }
|
||||
tracing = "0.1.39"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
|
||||
|
||||
use std::{collections::HashSet, convert::TryFrom};
|
||||
use std::collections::HashSet;
|
||||
|
||||
use zebra_chain::{
|
||||
amount::{Amount, Error, NonNegative},
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
//! Tests for block verification
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
use color_eyre::eyre::{eyre, Report};
|
||||
use once_cell::sync::Lazy;
|
||||
use tower::{buffer::Buffer, util::BoxService};
|
||||
|
||||
use zebra_chain::{
|
||||
amount::{Amount, MAX_MONEY},
|
||||
amount::MAX_MONEY,
|
||||
block::{
|
||||
self,
|
||||
tests::generate::{
|
||||
large_multi_transaction_block, large_single_transaction_block_many_inputs,
|
||||
},
|
||||
Block, Height,
|
||||
},
|
||||
parameters::{Network, NetworkUpgrade},
|
||||
parameters::NetworkUpgrade,
|
||||
serialization::{ZcashDeserialize, ZcashDeserializeInto},
|
||||
transaction::{arbitrary::transaction_to_fake_v5, LockTime, Transaction},
|
||||
work::difficulty::{ParameterDifficulty as _, INVALID_COMPACT_DIFFICULTY},
|
||||
|
|
|
@ -5,8 +5,8 @@ use std::sync::Arc;
|
|||
use num_integer::div_ceil;
|
||||
|
||||
use zebra_chain::{
|
||||
block::{self, Block, HeightDiff, MAX_BLOCK_BYTES},
|
||||
parameters::{Network, Network::*},
|
||||
block::{Block, HeightDiff, MAX_BLOCK_BYTES},
|
||||
parameters::Network::*,
|
||||
serialization::ZcashDeserialize,
|
||||
};
|
||||
use zebra_node_services::constants::{MAX_CHECKPOINT_BYTE_COUNT, MAX_CHECKPOINT_HEIGHT_GAP};
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
//! Tests for checkpoint-based block verification
|
||||
|
||||
use std::{cmp::min, mem::drop, time::Duration};
|
||||
use std::{cmp::min, time::Duration};
|
||||
|
||||
use color_eyre::eyre::{eyre, Report};
|
||||
use futures::{
|
||||
future::TryFutureExt,
|
||||
stream::{FuturesUnordered, StreamExt},
|
||||
};
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use tokio::time::timeout;
|
||||
use tower::{Service, ServiceExt};
|
||||
use tracing_futures::Instrument;
|
||||
|
||||
use zebra_chain::{parameters::Network::*, serialization::ZcashDeserialize};
|
||||
|
|
|
@ -15,7 +15,7 @@ use tokio::sync::watch;
|
|||
use tower::{util::ServiceFn, Service};
|
||||
use tower_batch_control::{Batch, BatchControl};
|
||||
use tower_fallback::Fallback;
|
||||
use zebra_chain::primitives::ed25519::{batch, *};
|
||||
use zebra_chain::primitives::ed25519::*;
|
||||
|
||||
use crate::BoxError;
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::time::Duration;
|
|||
use color_eyre::eyre::{eyre, Report, Result};
|
||||
use futures::stream::{FuturesOrdered, StreamExt};
|
||||
use tower::ServiceExt;
|
||||
use tower_batch_control::Batch;
|
||||
|
||||
use crate::primitives::ed25519::*;
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use crate::groth16::h_sig;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -16,7 +16,7 @@ use tower::{util::ServiceFn, Service};
|
|||
use tower_batch_control::{Batch, BatchControl};
|
||||
use tower_fallback::Fallback;
|
||||
|
||||
use zebra_chain::primitives::redjubjub::{batch, *};
|
||||
use zebra_chain::primitives::redjubjub::*;
|
||||
|
||||
use crate::BoxError;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ use std::time::Duration;
|
|||
use color_eyre::eyre::{eyre, Result};
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use tower::ServiceExt;
|
||||
use tower_batch_control::Batch;
|
||||
|
||||
async fn sign_and_verify<V>(mut verifier: V, n: usize) -> Result<(), V::Error>
|
||||
where
|
||||
|
|
|
@ -7,7 +7,6 @@ use std::time::Duration;
|
|||
use color_eyre::eyre::{eyre, Result};
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use tower::ServiceExt;
|
||||
use tower_batch_control::Batch;
|
||||
|
||||
use zebra_chain::primitives::reddsa::{
|
||||
orchard::{Binding, SpendAuth},
|
||||
|
|
|
@ -4,18 +4,15 @@ use std::{sync::Arc, time::Duration};
|
|||
|
||||
use color_eyre::eyre::Report;
|
||||
use once_cell::sync::Lazy;
|
||||
use tower::{layer::Layer, timeout::TimeoutLayer, Service};
|
||||
use tower::{layer::Layer, timeout::TimeoutLayer};
|
||||
|
||||
use zebra_chain::{
|
||||
block::{self, Block},
|
||||
parameters::Network,
|
||||
block::Block,
|
||||
serialization::{ZcashDeserialize, ZcashDeserializeInto},
|
||||
};
|
||||
use zebra_state as zs;
|
||||
use zebra_test::transcript::{ExpectedTranscriptError, Transcript};
|
||||
|
||||
use crate::Config;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// The timeout we apply to each verify future during testing.
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
future::Future,
|
||||
iter::FromIterator,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
|
|
|
@ -20,13 +20,13 @@ futures-util = "0.3.28"
|
|||
tonic = "0.11.0"
|
||||
tonic-reflection = "0.11.0"
|
||||
prost = "0.12.4"
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] }
|
||||
tokio-stream = "0.1.15"
|
||||
tower = { version = "0.4.13", features = ["util", "buffer"] }
|
||||
color-eyre = "0.6.3"
|
||||
|
||||
zcash_primitives = { version = "0.13.0-rc.1" }
|
||||
zcash_primitives = { version = "0.13.0" }
|
||||
|
||||
zebra-node-services = { path = "../zebra-node-services", version = "1.0.0-beta.36", features = ["shielded-scan"] }
|
||||
zebra-chain = { path = "../zebra-chain" , version = "1.0.0-beta.36" }
|
||||
|
|
|
@ -43,7 +43,7 @@ proptest-impl = ["proptest", "proptest-derive", "zebra-chain/proptest-impl"]
|
|||
bitflags = "2.5.0"
|
||||
byteorder = "1.5.0"
|
||||
bytes = "1.6.0"
|
||||
chrono = { version = "0.4.34", default-features = false, features = ["clock", "std"] }
|
||||
chrono = { version = "0.4.38", default-features = false, features = ["clock", "std"] }
|
||||
dirs = "5.0.1"
|
||||
hex = "0.4.3"
|
||||
humantime-serde = "1.1.1"
|
||||
|
@ -56,9 +56,9 @@ pin-project = "1.1.5"
|
|||
rand = "0.8.5"
|
||||
rayon = "1.10.0"
|
||||
regex = "1.10.4"
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
tempfile = "3.10.1"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
|
||||
futures = "0.3.30"
|
||||
tokio = { version = "1.37.0", features = ["fs", "io-util", "net", "time", "tracing", "macros", "rt-multi-thread"] }
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
use std::{
|
||||
cmp::Reverse,
|
||||
collections::HashMap,
|
||||
iter::Extend,
|
||||
net::{IpAddr, SocketAddr},
|
||||
sync::{Arc, Mutex},
|
||||
time::Instant,
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::{
|
|||
ffi::OsString,
|
||||
io::{self, ErrorKind},
|
||||
net::{IpAddr, SocketAddr},
|
||||
string::String,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
|
@ -15,7 +14,10 @@ use tempfile::NamedTempFile;
|
|||
use tokio::{fs, io::AsyncWriteExt};
|
||||
use tracing::Span;
|
||||
|
||||
use zebra_chain::parameters::{testnet, Network, NetworkKind};
|
||||
use zebra_chain::parameters::{
|
||||
testnet::{self, ConfiguredActivationHeights},
|
||||
Network, NetworkKind,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
constants::{
|
||||
|
@ -625,12 +627,19 @@ impl<'de> Deserialize<'de> for Config {
|
|||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct DTestnetParameters {
|
||||
network_name: Option<String>,
|
||||
activation_heights: Option<ConfiguredActivationHeights>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields, default)]
|
||||
struct DConfig {
|
||||
listen_addr: String,
|
||||
network: NetworkKind,
|
||||
testnet_parameters: Option<testnet::Parameters>,
|
||||
testnet_parameters: Option<DTestnetParameters>,
|
||||
regtest_activation_heights: ConfiguredActivationHeights,
|
||||
initial_mainnet_peers: IndexSet<String>,
|
||||
initial_testnet_peers: IndexSet<String>,
|
||||
cache_dir: CacheDir,
|
||||
|
@ -647,6 +656,7 @@ impl<'de> Deserialize<'de> for Config {
|
|||
listen_addr: "0.0.0.0".to_string(),
|
||||
network: Default::default(),
|
||||
testnet_parameters: None,
|
||||
regtest_activation_heights: ConfiguredActivationHeights::default(),
|
||||
initial_mainnet_peers: config.initial_mainnet_peers,
|
||||
initial_testnet_peers: config.initial_testnet_peers,
|
||||
cache_dir: config.cache_dir,
|
||||
|
@ -661,6 +671,7 @@ impl<'de> Deserialize<'de> for Config {
|
|||
listen_addr,
|
||||
network: network_kind,
|
||||
testnet_parameters,
|
||||
regtest_activation_heights,
|
||||
initial_mainnet_peers,
|
||||
initial_testnet_peers,
|
||||
cache_dir,
|
||||
|
@ -669,21 +680,55 @@ impl<'de> Deserialize<'de> for Config {
|
|||
max_connections_per_ip,
|
||||
} = DConfig::deserialize(deserializer)?;
|
||||
|
||||
let network = if let Some(network_params) = testnet_parameters {
|
||||
// TODO: Panic here if the initial testnet peers are the default initial testnet peers.
|
||||
assert_eq!(
|
||||
network_kind,
|
||||
NetworkKind::Testnet,
|
||||
"set network to 'Testnet' to use configured testnet parameters"
|
||||
);
|
||||
/// Accepts an [`IndexSet`] of initial peers,
|
||||
///
|
||||
/// Returns true if any of them are the default Testnet or Mainnet initial peers.
|
||||
fn contains_default_initial_peers(initial_peers: &IndexSet<String>) -> bool {
|
||||
let Config {
|
||||
initial_mainnet_peers: mut default_initial_peers,
|
||||
initial_testnet_peers: default_initial_testnet_peers,
|
||||
..
|
||||
} = Config::default();
|
||||
default_initial_peers.extend(default_initial_testnet_peers);
|
||||
|
||||
Network::new_configured_testnet(network_params)
|
||||
} else {
|
||||
// Convert to default `Network` for a `NetworkKind` if there are no testnet parameters.
|
||||
match network_kind {
|
||||
NetworkKind::Mainnet => Network::Mainnet,
|
||||
NetworkKind::Testnet => Network::new_default_testnet(),
|
||||
NetworkKind::Regtest => unimplemented!("Regtest is not yet implemented in Zebra"),
|
||||
initial_peers
|
||||
.intersection(&default_initial_peers)
|
||||
.next()
|
||||
.is_some()
|
||||
}
|
||||
|
||||
let network = match (network_kind, testnet_parameters) {
|
||||
(NetworkKind::Mainnet, _) => Network::Mainnet,
|
||||
(NetworkKind::Testnet, None) => Network::new_default_testnet(),
|
||||
(NetworkKind::Regtest, _) => Network::new_regtest(regtest_activation_heights),
|
||||
(
|
||||
NetworkKind::Testnet,
|
||||
Some(DTestnetParameters {
|
||||
network_name,
|
||||
activation_heights,
|
||||
}),
|
||||
) => {
|
||||
let mut params_builder = testnet::Parameters::build();
|
||||
|
||||
if let Some(network_name) = network_name {
|
||||
params_builder = params_builder.with_network_name(network_name)
|
||||
}
|
||||
|
||||
// Retain default Testnet activation heights unless there's an empty [testnet_parameters.activation_heights] section.
|
||||
if let Some(activation_heights) = activation_heights {
|
||||
// Return an error if the initial testnet peers includes any of the default initial Mainnet or Testnet
|
||||
// peers while activation heights are configured.
|
||||
// TODO: Check that the network magic is different from the default Mainnet/Testnet network magic too?
|
||||
if contains_default_initial_peers(&initial_testnet_peers) {
|
||||
return Err(de::Error::custom(
|
||||
"cannot use default initial testnet peers with configured activation heights",
|
||||
));
|
||||
}
|
||||
|
||||
params_builder = params_builder.with_activation_heights(activation_heights)
|
||||
}
|
||||
|
||||
params_builder.to_network()
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! An address-with-metadata type used in Bitcoin networking.
|
||||
|
||||
use std::{
|
||||
cmp::{max, Ord, Ordering},
|
||||
cmp::{max, Ordering},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::net::IpAddr;
|
||||
|
||||
use proptest::{arbitrary::any, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use zebra_chain::{parameters::Network::*, serialization::DateTime32};
|
||||
|
||||
|
|
|
@ -9,11 +9,7 @@
|
|||
|
||||
use std::{borrow::Cow, collections::HashSet, fmt, pin::Pin, sync::Arc, time::Instant};
|
||||
|
||||
use futures::{
|
||||
future::{self, Either},
|
||||
prelude::*,
|
||||
stream::Stream,
|
||||
};
|
||||
use futures::{future::Either, prelude::*};
|
||||
use rand::{seq::SliceRandom, thread_rng, Rng};
|
||||
use tokio::time::{sleep, Sleep};
|
||||
use tower::{Service, ServiceExt};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Wrapper around handshake logic that also opens a TCP connection.
|
||||
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
|
|
@ -106,7 +106,7 @@ use std::{
|
|||
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
future::{Future, FutureExt, TryFutureExt},
|
||||
future::{FutureExt, TryFutureExt},
|
||||
prelude::*,
|
||||
stream::FuturesUnordered,
|
||||
task::noop_waker,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use proptest::{arbitrary::any, arbitrary::Arbitrary, collection::vec, prelude::*};
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
|
||||
use zebra_chain::{block, transaction};
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Randomised property tests for Zebra's Zcash network protocol types.
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use bytes::BytesMut;
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Fixed test vectors for external protocol messages.
|
||||
|
||||
use std::{convert::TryInto, io::Write};
|
||||
use std::io::Write;
|
||||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ color-eyre = { version = "0.6.3", optional = true }
|
|||
jsonrpc-core = { version = "18.0.0", optional = true }
|
||||
# Security: avoid default dependency on openssl
|
||||
reqwest = { version = "0.11.26", default-features = false, features = ["rustls-tls"], optional = true }
|
||||
serde = { version = "1.0.196", optional = true }
|
||||
serde_json = { version = "1.0.115", optional = true }
|
||||
serde = { version = "1.0.198", optional = true }
|
||||
serde_json = { version = "1.0.116", optional = true }
|
||||
tokio = { version = "1.37.0", features = ["time"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -55,5 +55,5 @@ tokio = { version = "1.37.0", features = ["time"], optional = true }
|
|||
color-eyre = "0.6.3"
|
||||
jsonrpc-core = "18.0.0"
|
||||
reqwest = { version = "0.11.26", default-features = false, features = ["rustls-tls"] }
|
||||
serde = "1.0.196"
|
||||
serde_json = "1.0.115"
|
||||
serde = "1.0.198"
|
||||
serde_json = "1.0.116"
|
||||
|
|
|
@ -42,7 +42,7 @@ proptest-impl = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
chrono = { version = "0.4.34", default-features = false, features = ["clock", "std"] }
|
||||
chrono = { version = "0.4.38", default-features = false, features = ["clock", "std"] }
|
||||
futures = "0.3.30"
|
||||
|
||||
# lightwalletd sends JSON-RPC requests over HTTP 1.1
|
||||
|
@ -53,7 +53,7 @@ jsonrpc-derive = "18.0.0"
|
|||
jsonrpc-http-server = "18.0.0"
|
||||
|
||||
# zebra-rpc needs the preserve_order feature in serde_json, which is a dependency of jsonrpc-core
|
||||
serde_json = { version = "1.0.115", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0.116", features = ["preserve_order"] }
|
||||
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||
|
||||
tokio = { version = "1.37.0", features = ["time", "rt-multi-thread", "macros", "tracing"] }
|
||||
|
@ -62,7 +62,7 @@ tower = "0.4.13"
|
|||
tracing = "0.1.39"
|
||||
|
||||
hex = { version = "0.4.3", features = ["serde"] }
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
|
||||
# Experimental feature getblocktemplate-rpcs
|
||||
rand = { version = "0.8.5", optional = true }
|
||||
|
@ -84,7 +84,7 @@ insta = { version = "1.38.0", features = ["redactions", "json", "ron"] }
|
|||
|
||||
proptest = "1.4.0"
|
||||
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
tokio = { version = "1.37.0", features = ["full", "tracing", "test-util"] }
|
||||
|
||||
zebra-chain = { path = "../zebra-chain", version = "1.0.0-beta.36", features = ["proptest-impl"] }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! Some parts of the `zcashd` RPC documentation are outdated.
|
||||
//! So this implementation follows the `zcashd` server and `lightwalletd` client implementations.
|
||||
|
||||
use std::{collections::HashSet, default::Default, fmt::Debug, sync::Arc};
|
||||
use std::{collections::HashSet, fmt::Debug, sync::Arc};
|
||||
|
||||
use chrono::Utc;
|
||||
use futures::{stream::FuturesOrdered, FutureExt, StreamExt, TryFutureExt};
|
||||
|
@ -1098,6 +1098,11 @@ where
|
|||
data: None,
|
||||
})?;
|
||||
|
||||
// # Concurrency
|
||||
//
|
||||
// For consistency, this lookup must be performed first, then all the other
|
||||
// lookups must be based on the hash.
|
||||
|
||||
// Fetch the block referenced by [`hash_or_height`] from the state.
|
||||
// TODO: If this RPC is called a lot, just get the block header,
|
||||
// rather than the whole block.
|
||||
|
@ -1128,6 +1133,9 @@ where
|
|||
_ => unreachable!("unmatched response to a block request"),
|
||||
};
|
||||
|
||||
let hash = hash_or_height.hash().unwrap_or_else(|| block.hash());
|
||||
let hash_or_height = hash.into();
|
||||
|
||||
// Fetch the Sapling & Orchard treestates referenced by
|
||||
// [`hash_or_height`] from the state.
|
||||
|
||||
|
@ -1156,8 +1164,6 @@ where
|
|||
// We've got all the data we need for the RPC response, so we
|
||||
// assemble the response.
|
||||
|
||||
let hash = block.hash();
|
||||
|
||||
let height = block
|
||||
.coinbase_height()
|
||||
.expect("verified blocks have a valid height");
|
||||
|
|
|
@ -7,14 +7,14 @@ use jsonrpc_core::{self, BoxFuture, Error, ErrorCode, Result};
|
|||
use jsonrpc_derive::rpc;
|
||||
use tower::{Service, ServiceExt};
|
||||
|
||||
use zcash_address::{self, unified::Encoding, TryFromAddress};
|
||||
use zcash_address::{unified::Encoding, TryFromAddress};
|
||||
|
||||
use zebra_chain::{
|
||||
amount::Amount,
|
||||
block::{self, Block, Height, TryIntoHeight},
|
||||
chain_sync_status::ChainSyncStatus,
|
||||
chain_tip::ChainTip,
|
||||
parameters::{Network, POW_AVERAGING_WINDOW},
|
||||
parameters::{Network, NetworkKind, POW_AVERAGING_WINDOW},
|
||||
primitives,
|
||||
serialization::ZcashDeserializeInto,
|
||||
transparent::{
|
||||
|
@ -449,13 +449,25 @@ where
|
|||
) -> Self {
|
||||
// Prevent loss of miner funds due to an unsupported or incorrect address type.
|
||||
if let Some(miner_address) = mining_config.miner_address.clone() {
|
||||
assert_eq!(
|
||||
miner_address.network_kind(),
|
||||
network.kind(),
|
||||
"incorrect miner address config: {miner_address} \
|
||||
network.network {network} and miner address network {} must match",
|
||||
miner_address.network_kind(),
|
||||
);
|
||||
match network.kind() {
|
||||
NetworkKind::Mainnet => assert_eq!(
|
||||
miner_address.network_kind(),
|
||||
NetworkKind::Mainnet,
|
||||
"Incorrect config: Zebra is configured to run on a Mainnet network, \
|
||||
which implies the configured mining address needs to be for Mainnet, \
|
||||
but the provided address is for {}.",
|
||||
miner_address.network_kind(),
|
||||
),
|
||||
// `Regtest` uses `Testnet` transparent addresses.
|
||||
network_kind @ (NetworkKind::Testnet | NetworkKind::Regtest) => assert_eq!(
|
||||
miner_address.network_kind(),
|
||||
NetworkKind::Testnet,
|
||||
"Incorrect config: Zebra is configured to run on a {network_kind} network, \
|
||||
which implies the configured mining address needs to be for Testnet, \
|
||||
but the provided address is for {}.",
|
||||
miner_address.network_kind(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// A limit on the configured extra coinbase data, regardless of the current block height.
|
||||
|
|
|
@ -227,9 +227,8 @@ fn update_checksum(checksum: &mut u32, item: [u8; 32]) {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToString for LongPollId {
|
||||
/// Exact conversion from LongPollId to a string.
|
||||
fn to_string(&self) -> String {
|
||||
impl std::fmt::Display for LongPollId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let LongPollId {
|
||||
tip_height,
|
||||
tip_hash_checksum,
|
||||
|
@ -240,7 +239,8 @@ impl ToString for LongPollId {
|
|||
|
||||
// We can't do this using `serde`, because it names each field,
|
||||
// but we want a single string containing all the fields.
|
||||
format!(
|
||||
write!(
|
||||
f,
|
||||
// Height as decimal, padded with zeroes to the width of Height::MAX
|
||||
// Checksums as hex, padded with zeroes to the width of u32::MAX
|
||||
// Timestamp as decimal, padded with zeroes to the width of u32::MAX
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! cargo insta test --review -p zebra-rpc --lib -- test_rpc_response_data
|
||||
//! ```
|
||||
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use insta::dynamic_redaction;
|
||||
use tower::buffer::Buffer;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
//! Fixed test vectors for RPC methods.
|
||||
|
||||
use std::{ops::RangeInclusive, sync::Arc};
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use jsonrpc_core::ErrorCode;
|
||||
use tower::buffer::Buffer;
|
||||
|
||||
use zebra_chain::{
|
||||
|
@ -11,8 +10,7 @@ use zebra_chain::{
|
|||
chain_tip::{mock::MockChainTip, NoChainTip},
|
||||
parameters::Network::*,
|
||||
serialization::{ZcashDeserializeInto, ZcashSerialize},
|
||||
transaction::{UnminedTx, UnminedTxId},
|
||||
transparent,
|
||||
transaction::UnminedTxId,
|
||||
};
|
||||
use zebra_node_services::BoxError;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use jsonrpc_core::{Compatibility, MetaIoHandler};
|
|||
use jsonrpc_http_server::{CloseHandle, ServerBuilder};
|
||||
use tokio::task::JoinHandle;
|
||||
use tower::Service;
|
||||
use tracing::{Instrument, *};
|
||||
use tracing::*;
|
||||
|
||||
use zebra_chain::{
|
||||
block, chain_sync_status::ChainSyncStatus, chain_tip::ChainTip, parameters::Network,
|
||||
|
|
|
@ -23,13 +23,14 @@ use super::super::*;
|
|||
|
||||
/// Test that the JSON-RPC server spawns when configured with a single thread.
|
||||
#[test]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn rpc_server_spawn_single_thread() {
|
||||
rpc_server_spawn(false)
|
||||
}
|
||||
|
||||
/// Test that the JSON-RPC server spawns when configured with multiple threads.
|
||||
#[test]
|
||||
fn rpc_sever_spawn_parallel_threads() {
|
||||
fn rpc_server_spawn_parallel_threads() {
|
||||
rpc_server_spawn(true)
|
||||
}
|
||||
|
||||
|
|
|
@ -45,21 +45,21 @@ color-eyre = "0.6.3"
|
|||
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||
itertools = "0.12.1"
|
||||
semver = "1.0.22"
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
tokio = { version = "1.37.0", features = ["time"] }
|
||||
tower = "0.4.13"
|
||||
tracing = "0.1.39"
|
||||
futures = "0.3.30"
|
||||
|
||||
zcash_client_backend = "0.10.0-rc.1"
|
||||
zcash_primitives = "0.13.0-rc.1"
|
||||
zcash_primitives = "0.13.0"
|
||||
|
||||
zebra-chain = { path = "../zebra-chain", version = "1.0.0-beta.36", features = ["shielded-scan"] }
|
||||
zebra-state = { path = "../zebra-state", version = "1.0.0-beta.36", features = ["shielded-scan"] }
|
||||
zebra-node-services = { path = "../zebra-node-services", version = "1.0.0-beta.36", features = ["shielded-scan"] }
|
||||
zebra-grpc = { path = "../zebra-grpc", version = "0.1.0-alpha.3" }
|
||||
|
||||
chrono = { version = "0.4.34", default-features = false, features = ["clock", "std", "serde"] }
|
||||
chrono = { version = "0.4.38", default-features = false, features = ["clock", "std", "serde"] }
|
||||
|
||||
# test feature proptest-impl
|
||||
proptest = { version = "1.4.0", optional = true }
|
||||
|
|
|
@ -384,25 +384,6 @@ pub fn scan_block<K: ScanningKey>(
|
|||
// TODO: Implement a check that returns early when the block height is below the Sapling
|
||||
// activation height.
|
||||
|
||||
let network = match network {
|
||||
Network::Mainnet => zcash_primitives::consensus::Network::MainNetwork,
|
||||
Network::Testnet(params) => {
|
||||
// # Correctness:
|
||||
//
|
||||
// There are differences between the `TestNetwork` parameters and those returned by
|
||||
// `CRegTestParams()` in zcashd, so this function can't return `TestNetwork` unless
|
||||
// Zebra is using the default public Testnet.
|
||||
//
|
||||
// TODO: Remove this conversion by implementing `zcash_primitives::consensus::Parameters`
|
||||
// for `Network` (#8365).
|
||||
assert!(
|
||||
params.is_default_testnet(),
|
||||
"could not convert configured testnet to zcash_primitives::consensus::Network"
|
||||
);
|
||||
zcash_primitives::consensus::Network::TestNetwork
|
||||
}
|
||||
};
|
||||
|
||||
let chain_metadata = ChainMetadata {
|
||||
sapling_commitment_tree_size: sapling_tree_size,
|
||||
// Orchard is not supported at the moment so the tree size can be 0.
|
||||
|
@ -417,7 +398,7 @@ pub fn scan_block<K: ScanningKey>(
|
|||
.collect();
|
||||
|
||||
zcash_client_backend::scanning::scan_block(
|
||||
&network,
|
||||
network,
|
||||
block_to_compact(block, chain_metadata),
|
||||
scanning_keys.as_slice(),
|
||||
// Ignore whether notes are change from a viewer's own spends for now.
|
||||
|
|
|
@ -15,11 +15,11 @@ keywords = ["zebra", "zcash"]
|
|||
categories = ["api-bindings", "cryptography::cryptocurrencies"]
|
||||
|
||||
[dependencies]
|
||||
zcash_script = "0.1.14"
|
||||
zcash_script = "0.1.15"
|
||||
|
||||
zebra-chain = { path = "../zebra-chain", version = "1.0.0-beta.36" }
|
||||
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
displaydoc = "0.2.4"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -277,7 +277,6 @@ impl Drop for CachedFfiTransaction {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex::FromHex;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use zebra_chain::{
|
||||
parameters::{ConsensusBranchId, NetworkUpgrade::*},
|
||||
|
|
|
@ -47,7 +47,7 @@ elasticsearch = [
|
|||
|
||||
[dependencies]
|
||||
bincode = "1.3.3"
|
||||
chrono = { version = "0.4.34", default-features = false, features = ["clock", "std"] }
|
||||
chrono = { version = "0.4.38", default-features = false, features = ["clock", "std"] }
|
||||
dirs = "5.0.1"
|
||||
futures = "0.3.30"
|
||||
hex = "0.4.3"
|
||||
|
@ -63,9 +63,9 @@ regex = "1.10.4"
|
|||
rlimit = "0.10.1"
|
||||
rocksdb = { version = "0.22.0", default-features = false, features = ["lz4"] }
|
||||
semver = "1.0.22"
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
tempfile = "3.10.1"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
|
||||
rayon = "1.10.0"
|
||||
tokio = { version = "1.37.0", features = ["rt-multi-thread", "sync", "tracing"] }
|
||||
|
@ -75,7 +75,7 @@ tracing = "0.1.39"
|
|||
# elasticsearch specific dependencies.
|
||||
# Security: avoid default dependency on openssl
|
||||
elasticsearch = { version = "8.5.0-alpha.1", default-features = false, features = ["rustls-tls"], optional = true }
|
||||
serde_json = { version = "1.0.115", package = "serde_json", optional = true }
|
||||
serde_json = { version = "1.0.116", package = "serde_json", optional = true }
|
||||
|
||||
zebra-chain = { path = "../zebra-chain", version = "1.0.0-beta.36", features = ["async-error"] }
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! * the Testnet minimum difficulty adjustment from ZIPs 205 and 208, and
|
||||
//! * `median-time-past`.
|
||||
|
||||
use std::{cmp::max, cmp::min, convert::TryInto};
|
||||
use std::{cmp::max, cmp::min};
|
||||
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Randomised property tests for nullifier contextual validation
|
||||
|
||||
use std::{convert::TryInto, env, sync::Arc};
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
use itertools::Itertools;
|
||||
use proptest::prelude::*;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Fixed test vectors for state contextual validation checks.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use zebra_chain::serialization::ZcashDeserializeInto;
|
||||
|
||||
use super::super::*;
|
||||
|
|
|
@ -502,6 +502,12 @@ impl FinalizedState {
|
|||
let network = self.network();
|
||||
|
||||
rt.block_on(async move {
|
||||
// Send a ping to the server to check if it is available before inserting.
|
||||
if client.ping().send().await.is_err() {
|
||||
tracing::error!("Elasticsearch is not available, skipping block indexing");
|
||||
return;
|
||||
}
|
||||
|
||||
let response = client
|
||||
.bulk(elasticsearch::BulkParts::Index(
|
||||
format!("zcash_{}", network.to_string().to_lowercase()).as_str(),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue