Compare commits
15 Commits
52555159dc
...
649738d66f
Author | SHA1 | Date |
---|---|---|
Gustavo Valverde | 649738d66f | |
Arya | d84d7356dd | |
Arya | c28e37bf23 | |
Arya | e5d4d739b7 | |
Arya | e95a70de7a | |
Arya | ee9ab3162a | |
Alfredo Garcia | d869ec6fe4 | |
Alfredo Garcia | 5f69870235 | |
Arya | 275e99ec72 | |
Alfredo Garcia | 8cf0b7a36a | |
dependabot[bot] | 74319ec477 | |
Gustavo Valverde | 5f835a19e0 | |
Gustavo Valverde | 5aa1a8091c | |
Gustavo Valverde | 773b0b531f | |
Gustavo Valverde | 9dbdfe28c5 |
|
@ -136,6 +136,8 @@ jobs:
|
|||
image_name: zebrad
|
||||
no_cache: ${{ inputs.no_cache || false }}
|
||||
rust_log: info
|
||||
# This step needs access to Docker Hub secrets to run successfully
|
||||
secrets: inherit
|
||||
|
||||
# Test that Zebra works using the default config with the latest Zebra version.
|
||||
test-configuration-file:
|
||||
|
|
|
@ -149,6 +149,9 @@ jobs:
|
|||
rust_backtrace: full
|
||||
rust_lib_backtrace: full
|
||||
rust_log: info
|
||||
# This step needs access to Docker Hub secrets to run successfully
|
||||
secrets: inherit
|
||||
|
||||
|
||||
# zebrad cached checkpoint state tests
|
||||
|
||||
|
|
|
@ -111,6 +111,8 @@ jobs:
|
|||
rust_backtrace: full
|
||||
rust_lib_backtrace: full
|
||||
rust_log: info
|
||||
# This step needs access to Docker Hub secrets to run successfully
|
||||
secrets: inherit
|
||||
|
||||
# Run all the zebra tests, including tests that are ignored by default.
|
||||
#
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
build:
|
||||
name: Build images
|
||||
timeout-minutes: 210
|
||||
runs-on: ubuntu-latest-xl
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
image_digest: ${{ steps.docker_build.outputs.digest }}
|
||||
image_name: ${{ fromJSON(steps.docker_build.outputs.metadata)['image.name'] }}
|
||||
|
@ -92,6 +92,8 @@ jobs:
|
|||
uses: docker/metadata-action@v5.5.1
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
# We only publish images to DockerHub if a release is not a pre-release
|
||||
# Ref: https://github.com/orgs/community/discussions/26281#discussioncomment-3251177
|
||||
images: |
|
||||
us-docker.pkg.dev/${{ vars.GCP_PROJECT }}/zebra/${{ inputs.image_name }}
|
||||
zfnd/${{ inputs.image_name }},enable=${{ github.event_name == 'release' && !github.event.release.prerelease }}
|
||||
|
@ -118,11 +120,6 @@ jobs:
|
|||
type=edge,enable={{is_default_branch}}
|
||||
type=schedule
|
||||
|
||||
# Setup Docker Buildx to allow use of docker cache layers from GH
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Authenticate to Google Cloud
|
||||
id: auth
|
||||
uses: google-github-actions/auth@v2.1.2
|
||||
|
@ -144,14 +141,20 @@ jobs:
|
|||
password: ${{ steps.auth.outputs.access_token }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
# We only publish images to DockerHub if a release is not a pre-release
|
||||
# Ref: https://github.com/orgs/community/discussions/26281#discussioncomment-3251177
|
||||
if: ${{ github.event_name == 'release' && !github.event.release.prerelease }}
|
||||
uses: docker/login-action@v3.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Setup Docker Buildx to use Docker Build Cloud
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: "lab:latest"
|
||||
driver: cloud
|
||||
endpoint: "zfnd/zebra"
|
||||
|
||||
# Build and push image to Google Artifact Registry, and possibly DockerHub
|
||||
- name: Build & push
|
||||
id: docker_build
|
||||
|
@ -171,17 +174,3 @@ jobs:
|
|||
# Don't read from the cache if the caller disabled it.
|
||||
# https://docs.docker.com/engine/reference/commandline/buildx_build/#options
|
||||
no-cache: ${{ inputs.no_cache }}
|
||||
# To improve build speeds, for each branch we push an additional image to the registry,
|
||||
# to be used as the caching layer, using the `max` caching mode.
|
||||
#
|
||||
# We use multiple cache sources to confirm a cache hit, starting from a per-branch cache.
|
||||
# If there's no hit, we continue with a `main` branch cache, which helps us avoid
|
||||
# rebuilding cargo-chef, most dependencies, and possibly some Zebra crates.
|
||||
#
|
||||
# The caches are tried in top-down order, the first available cache is used:
|
||||
# https://github.com/moby/moby/pull/26839#issuecomment-277383550
|
||||
cache-from: |
|
||||
type=registry,ref=us-docker.pkg.dev/${{ vars.GCP_PROJECT }}/zebra-caching/${{ inputs.image_name }}${{ inputs.tag_suffix }}:${{ env.GITHUB_REF_SLUG_URL }}-cache
|
||||
type=registry,ref=us-docker.pkg.dev/${{ vars.GCP_PROJECT }}/zebra-caching/${{ inputs.image_name }}${{ inputs.tag_suffix }}:main-cache
|
||||
cache-to: |
|
||||
type=registry,ref=us-docker.pkg.dev/${{ vars.GCP_PROJECT }}/zebra-caching/${{ inputs.image_name }}${{ inputs.tag_suffix }}:${{ env.GITHUB_REF_SLUG_URL }}-cache,mode=max
|
||||
|
|
122
Cargo.lock
122
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",
|
||||
]
|
||||
|
||||
|
@ -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,7 +97,7 @@ 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.38", default-features = false, features = ["clock", "std", "serde"] }
|
||||
|
@ -106,12 +106,12 @@ 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 }
|
||||
|
|
|
@ -25,6 +25,7 @@ mod header;
|
|||
mod height;
|
||||
mod serialize;
|
||||
|
||||
pub mod genesis;
|
||||
pub mod merkle;
|
||||
|
||||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//! Regtest genesis block
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use hex::FromHex;
|
||||
|
||||
use crate::{block::Block, serialization::ZcashDeserializeInto};
|
||||
|
||||
/// Genesis block for Regtest, copied from zcashd via `getblock 0 0` RPC method
|
||||
pub fn regtest_genesis_block() -> Arc<Block> {
|
||||
let regtest_genesis_block_bytes =
|
||||
<Vec<u8>>::from_hex(include_str!("genesis/block-regtest-0-000-000.txt").trim())
|
||||
.expect("Block bytes are in valid hex representation");
|
||||
|
||||
regtest_genesis_block_bytes
|
||||
.zcash_deserialize_into()
|
||||
.map(Arc::new)
|
||||
.expect("hard-coded Regtest genesis block data must deserialize successfully")
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
040000000000000000000000000000000000000000000000000000000000000000000000db4d7a85b768123f1dff1d4c4cece70083b2d27e117b4ac2e31d087988a5eac40000000000000000000000000000000000000000000000000000000000000000dae5494d0f0f0f2009000000000000000000000000000000000000000000000000000000000000002401936b7db1eb4ac39f151b8704642d0a8bda13ec547d54cd5e43ba142fc6d8877cab07b30101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff071f0104455a6361736830623963346565663862376363343137656535303031653335303039383462366665613335363833613763616331343161303433633432303634383335643334ffffffff010000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000
|
|
@ -455,9 +455,15 @@ impl HistoryTree {
|
|||
sapling_root: &sapling::tree::Root,
|
||||
orchard_root: &orchard::tree::Root,
|
||||
) -> Result<(), HistoryTreeError> {
|
||||
let heartwood_height = NetworkUpgrade::Heartwood
|
||||
.activation_height(network)
|
||||
.expect("Heartwood height is known");
|
||||
let Some(heartwood_height) = NetworkUpgrade::Heartwood.activation_height(network) else {
|
||||
assert!(
|
||||
self.0.is_none(),
|
||||
"history tree must not exist pre-Heartwood"
|
||||
);
|
||||
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
match block
|
||||
.coinbase_height()
|
||||
.expect("must have height")
|
||||
|
|
|
@ -11,6 +11,8 @@ use crate::{
|
|||
parameters::NetworkUpgrade,
|
||||
};
|
||||
|
||||
use self::testnet::ConfiguredActivationHeights;
|
||||
|
||||
pub mod testnet;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -138,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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,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 {
|
||||
|
@ -177,6 +180,23 @@ 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 true if proof-of-work validation should be disabled for this network
|
||||
pub fn disable_pow(&self) -> bool {
|
||||
if let Self::Testnet(params) = self {
|
||||
params.disable_pow()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
/// Returns the [`NetworkKind`] for this network.
|
||||
pub fn kind(&self) -> NetworkKind {
|
||||
match self {
|
||||
|
|
|
@ -1,16 +1,40 @@
|
|||
//! Types and implementation for Testnet consensus parameters
|
||||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, fmt};
|
||||
|
||||
use zcash_primitives::constants as zp_constants;
|
||||
|
||||
use crate::{
|
||||
block::Height,
|
||||
block::{self, 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;
|
||||
|
||||
/// The block hash of the Regtest genesis block, `zcash-cli -regtest getblockhash 0`
|
||||
const REGTEST_GENESIS_HASH: &str =
|
||||
"029f11d80ef9765602235e1bc9727e3eb6ba20839319f761fee920d63401e327";
|
||||
|
||||
/// The block hash of the Testnet genesis block, `zcash-cli -testnet getblockhash 0`
|
||||
const TESTNET_GENESIS_HASH: &str =
|
||||
"05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38";
|
||||
|
||||
/// Configurable activation heights for Regtest and configured Testnets.
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
|
@ -35,6 +59,10 @@ pub struct ConfiguredActivationHeights {
|
|||
/// 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 genesis block hash
|
||||
genesis_hash: block::Hash,
|
||||
/// 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
|
||||
|
@ -43,35 +71,108 @@ pub struct ParametersBuilder {
|
|||
hrp_sapling_extended_full_viewing_key: String,
|
||||
/// Sapling payment address human-readable prefix for this network
|
||||
hrp_sapling_payment_address: String,
|
||||
/// A flag for disabling proof-of-work checks when Zebra is validating blocks
|
||||
disable_pow: bool,
|
||||
}
|
||||
|
||||
impl Default for ParametersBuilder {
|
||||
/// Creates a [`ParametersBuilder`] with all of the default Testnet parameters except `network_name`.
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
network_name: "UnknownTestnet".to_string(),
|
||||
// # Correctness
|
||||
//
|
||||
// `Genesis` network upgrade activation height must always be 0
|
||||
activation_heights: [
|
||||
(Height(0), NetworkUpgrade::Genesis),
|
||||
// TODO: Find out if `BeforeOverwinter` must always be active at Height(1), remove it here if it's not required.
|
||||
(Height(1), NetworkUpgrade::BeforeOverwinter),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
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(),
|
||||
genesis_hash: TESTNET_GENESIS_HASH
|
||||
.parse()
|
||||
.expect("hard-coded hash parses"),
|
||||
disable_pow: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/// Parses the hex-encoded block hash and sets it as the genesis hash in the [`Parameters`] being built.
|
||||
pub fn with_genesis_hash(mut self, genesis_hash: impl fmt::Display) -> Self {
|
||||
self.genesis_hash = genesis_hash
|
||||
.to_string()
|
||||
.parse()
|
||||
.expect("configured genesis hash must parse");
|
||||
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 activation_heights(
|
||||
pub fn with_activation_heights(
|
||||
mut self,
|
||||
ConfiguredActivationHeights {
|
||||
// TODO: Find out if `BeforeOverwinter` is required at Height(1), allow for
|
||||
|
@ -99,7 +200,6 @@ impl ParametersBuilder {
|
|||
.chain(heartwood.into_iter().map(|h| (h, Heartwood)))
|
||||
.chain(canopy.into_iter().map(|h| (h, Canopy)))
|
||||
.chain(nu5.into_iter().map(|h| (h, Nu5)))
|
||||
.filter(|&(_, nu)| nu != NetworkUpgrade::BeforeOverwinter)
|
||||
.map(|(h, nu)| (h.try_into().expect("activation height must be valid"), nu))
|
||||
.collect();
|
||||
|
||||
|
@ -127,25 +227,38 @@ impl ParametersBuilder {
|
|||
// # 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
|
||||
}
|
||||
|
||||
/// Sets the `disable_pow` flag to be used in the [`Parameters`] being built.
|
||||
pub fn with_disable_pow(mut self, disable_pow: bool) -> Self {
|
||||
self.disable_pow = disable_pow;
|
||||
self
|
||||
}
|
||||
|
||||
/// Converts the builder to a [`Parameters`] struct
|
||||
pub fn finish(self) -> Parameters {
|
||||
let Self {
|
||||
network_name,
|
||||
genesis_hash,
|
||||
activation_heights,
|
||||
hrp_sapling_extended_spending_key,
|
||||
hrp_sapling_extended_full_viewing_key,
|
||||
hrp_sapling_payment_address,
|
||||
disable_pow,
|
||||
} = self;
|
||||
Parameters {
|
||||
network_name,
|
||||
genesis_hash,
|
||||
activation_heights,
|
||||
hrp_sapling_extended_spending_key,
|
||||
hrp_sapling_extended_full_viewing_key,
|
||||
hrp_sapling_payment_address,
|
||||
disable_pow,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,6 +271,10 @@ impl ParametersBuilder {
|
|||
/// Network consensus parameters for test networks such as Regtest and the default Testnet.
|
||||
#[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 genesis block hash
|
||||
genesis_hash: block::Hash,
|
||||
/// The network upgrade activation heights for this network.
|
||||
///
|
||||
/// Note: This value is ignored by `Network::activation_list()` when `zebra-chain` is
|
||||
|
@ -170,19 +287,16 @@ pub struct Parameters {
|
|||
hrp_sapling_extended_full_viewing_key: String,
|
||||
/// Sapling payment address human-readable prefix for this network
|
||||
hrp_sapling_payment_address: String,
|
||||
/// A flag for disabling proof-of-work checks when Zebra is validating blocks
|
||||
disable_pow: bool,
|
||||
}
|
||||
|
||||
impl Default for Parameters {
|
||||
/// Returns an instance of the default public testnet [`Parameters`].
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
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(),
|
||||
network_name: "Testnet".to_string(),
|
||||
..Self::build().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,11 +307,63 @@ impl Parameters {
|
|||
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_genesis_hash(REGTEST_GENESIS_HASH)
|
||||
.with_disable_pow(true)
|
||||
.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,
|
||||
genesis_hash,
|
||||
// Activation heights are configurable on Regtest
|
||||
activation_heights: _,
|
||||
hrp_sapling_extended_spending_key,
|
||||
hrp_sapling_extended_full_viewing_key,
|
||||
hrp_sapling_payment_address,
|
||||
disable_pow,
|
||||
} = Self::new_regtest(ConfiguredActivationHeights::default());
|
||||
|
||||
self.network_name == network_name
|
||||
&& self.genesis_hash == genesis_hash
|
||||
&& 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
|
||||
&& self.disable_pow == disable_pow
|
||||
}
|
||||
|
||||
/// Returns the network name
|
||||
pub fn network_name(&self) -> &str {
|
||||
&self.network_name
|
||||
}
|
||||
|
||||
/// Returns the genesis hash
|
||||
pub fn genesis_hash(&self) -> block::Hash {
|
||||
self.genesis_hash
|
||||
}
|
||||
|
||||
/// Returns the network upgrade activation heights
|
||||
pub fn activation_heights(&self) -> &BTreeMap<Height, NetworkUpgrade> {
|
||||
&self.activation_heights
|
||||
|
@ -217,4 +383,9 @@ impl Parameters {
|
|||
pub fn hrp_sapling_payment_address(&self) -> &str {
|
||||
&self.hrp_sapling_payment_address
|
||||
}
|
||||
|
||||
/// Returns true if proof-of-work validation should be disabled for this network
|
||||
pub fn disable_pow(&self) -> bool {
|
||||
self.disable_pow
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
//! Fixed test vectors for the network consensus parameters.
|
||||
|
||||
use zcash_primitives::consensus::{self as zp_consensus, Parameters};
|
||||
use zcash_primitives::{
|
||||
consensus::{self as zp_consensus, Parameters},
|
||||
constants as zp_constants,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
block::Height,
|
||||
parameters::{
|
||||
testnet::{self, ConfiguredActivationHeights},
|
||||
Network, NetworkUpgrade, NETWORK_UPGRADES_IN_ORDER,
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -91,13 +98,14 @@ fn check_parameters_impl() {
|
|||
}
|
||||
|
||||
/// 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, and that the
|
||||
/// `Genesis` upgrade is always at `Height(0)`.
|
||||
/// 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()
|
||||
.activation_heights(ConfiguredActivationHeights {
|
||||
.with_activation_heights(ConfiguredActivationHeights {
|
||||
nu5: Some(expected_activation_height),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -124,4 +132,219 @@ fn activates_network_upgrades_correctly() {
|
|||
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"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ impl Arbitrary for equihash::Solution {
|
|||
.prop_map(|v| {
|
||||
let mut bytes = [0; equihash::SOLUTION_SIZE];
|
||||
bytes.copy_from_slice(v.as_slice());
|
||||
Self(bytes)
|
||||
Self::Common(bytes)
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
|
|
|
@ -29,16 +29,26 @@ pub struct SolverCancelled;
|
|||
/// The size of an Equihash solution in bytes (always 1344).
|
||||
pub(crate) const SOLUTION_SIZE: usize = 1344;
|
||||
|
||||
/// The size of an Equihash solution in bytes on Regtest (always 36).
|
||||
pub(crate) const REGTEST_SOLUTION_SIZE: usize = 36;
|
||||
|
||||
/// Equihash Solution in compressed format.
|
||||
///
|
||||
/// A wrapper around [u8; 1344] because Rust doesn't implement common
|
||||
/// traits like `Debug`, `Clone`, etc for collections like array
|
||||
/// beyond lengths 0 to 32.
|
||||
/// A wrapper around `[u8; n]` where `n` is the solution size because
|
||||
/// Rust doesn't implement common traits like `Debug`, `Clone`, etc.
|
||||
/// for collections like arrays beyond lengths 0 to 32.
|
||||
///
|
||||
/// The size of an Equihash solution in bytes is always 1344 so the
|
||||
/// length of this type is fixed.
|
||||
/// The size of an Equihash solution in bytes is always 1344 on Mainnet and Testnet, and
|
||||
/// is always 36 on Regtest so the length of this type is fixed.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Solution(#[serde(with = "BigArray")] pub [u8; SOLUTION_SIZE]);
|
||||
// It's okay to use the extra space on Regtest
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Solution {
|
||||
/// Equihash solution on Mainnet or Testnet
|
||||
Common(#[serde(with = "BigArray")] [u8; SOLUTION_SIZE]),
|
||||
/// Equihash solution on Regtest
|
||||
Regtest(#[serde(with = "BigArray")] [u8; REGTEST_SOLUTION_SIZE]),
|
||||
}
|
||||
|
||||
impl Solution {
|
||||
/// The length of the portion of the header used as input when verifying
|
||||
|
@ -48,15 +58,24 @@ impl Solution {
|
|||
/// to the verification function.
|
||||
pub const INPUT_LENGTH: usize = 4 + 32 * 3 + 4 * 2;
|
||||
|
||||
/// Returns the inner value of the [`Solution`] as a byte slice.
|
||||
fn value(&self) -> &[u8] {
|
||||
match self {
|
||||
Solution::Common(solution) => solution.as_slice(),
|
||||
Solution::Regtest(solution) => solution.as_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Ok(())` if `EquihashSolution` is valid for `header`
|
||||
#[allow(clippy::unwrap_in_result)]
|
||||
pub fn check(&self, header: &Header) -> Result<(), Error> {
|
||||
let n = 200;
|
||||
let k = 9;
|
||||
let nonce = &header.nonce;
|
||||
let solution = &self.0;
|
||||
let mut input = Vec::new();
|
||||
let (solution, n, k) = match self {
|
||||
Solution::Common(solution) => (solution.as_slice(), 200, 9),
|
||||
Solution::Regtest(solution) => (solution.as_slice(), 48, 5),
|
||||
};
|
||||
|
||||
let mut input = Vec::new();
|
||||
header
|
||||
.zcash_serialize(&mut input)
|
||||
.expect("serialization into a vec can't fail");
|
||||
|
@ -73,23 +92,29 @@ impl Solution {
|
|||
/// Returns a [`Solution`] containing the bytes from `solution`.
|
||||
/// Returns an error if `solution` is the wrong length.
|
||||
pub fn from_bytes(solution: &[u8]) -> Result<Self, SerializationError> {
|
||||
if solution.len() != SOLUTION_SIZE {
|
||||
return Err(SerializationError::Parse(
|
||||
match solution.len() {
|
||||
// Won't panic, because we just checked the length.
|
||||
SOLUTION_SIZE => {
|
||||
let mut bytes = [0; SOLUTION_SIZE];
|
||||
bytes.copy_from_slice(solution);
|
||||
Ok(Self::Common(bytes))
|
||||
}
|
||||
REGTEST_SOLUTION_SIZE => {
|
||||
let mut bytes = [0; REGTEST_SOLUTION_SIZE];
|
||||
bytes.copy_from_slice(solution);
|
||||
Ok(Self::Regtest(bytes))
|
||||
}
|
||||
_unexpected_len => Err(SerializationError::Parse(
|
||||
"incorrect equihash solution size",
|
||||
));
|
||||
)),
|
||||
}
|
||||
|
||||
let mut bytes = [0; SOLUTION_SIZE];
|
||||
// Won't panic, because we just checked the length.
|
||||
bytes.copy_from_slice(solution);
|
||||
|
||||
Ok(Self(bytes))
|
||||
}
|
||||
|
||||
/// Returns a [`Solution`] of `[0; SOLUTION_SIZE]` to be used in block proposals.
|
||||
#[cfg(feature = "getblocktemplate-rpcs")]
|
||||
pub fn for_proposal() -> Self {
|
||||
Self([0; SOLUTION_SIZE])
|
||||
// TODO: Accept network as an argument, and if it's Regtest, return the shorter null solution.
|
||||
Self::Common([0; SOLUTION_SIZE])
|
||||
}
|
||||
|
||||
/// Mines and returns one or more [`Solution`]s based on a template `header`.
|
||||
|
@ -126,14 +151,14 @@ impl Solution {
|
|||
|
||||
impl PartialEq<Solution> for Solution {
|
||||
fn eq(&self, other: &Solution) -> bool {
|
||||
self.0.as_ref() == other.0.as_ref()
|
||||
self.value() == other.value()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Solution {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("EquihashSolution")
|
||||
.field(&hex::encode(&self.0[..]))
|
||||
.field(&hex::encode(self.value()))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -153,13 +178,13 @@ impl Eq for Solution {}
|
|||
#[cfg(any(test, feature = "proptest-impl"))]
|
||||
impl Default for Solution {
|
||||
fn default() -> Self {
|
||||
Self([0; SOLUTION_SIZE])
|
||||
Self::Common([0; SOLUTION_SIZE])
|
||||
}
|
||||
}
|
||||
|
||||
impl ZcashSerialize for Solution {
|
||||
fn zcash_serialize<W: io::Write>(&self, writer: W) -> Result<(), io::Error> {
|
||||
zcash_serialize_bytes(&self.0.to_vec(), writer)
|
||||
zcash_serialize_bytes(&self.value().to_vec(), writer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,12 +47,12 @@ chrono = { version = "0.4.38", default-features = false, features = ["clock", "s
|
|||
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"
|
||||
|
|
|
@ -176,16 +176,18 @@ where
|
|||
Err(BlockError::MaxHeight(height, hash, block::Height::MAX))?;
|
||||
}
|
||||
|
||||
// > The block data MUST be validated and checked against the server's usual
|
||||
// > acceptance rules (excluding the check for a valid proof-of-work).
|
||||
// <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
|
||||
if request.is_proposal() {
|
||||
check::difficulty_threshold_is_valid(&block.header, &network, &height, &hash)?;
|
||||
} else {
|
||||
// Do the difficulty checks first, to raise the threshold for
|
||||
// attacks that use any other fields.
|
||||
check::difficulty_is_valid(&block.header, &network, &height, &hash)?;
|
||||
check::equihash_solution_is_valid(&block.header)?;
|
||||
if !network.disable_pow() {
|
||||
// > The block data MUST be validated and checked against the server's usual
|
||||
// > acceptance rules (excluding the check for a valid proof-of-work).
|
||||
// <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
|
||||
if request.is_proposal() {
|
||||
check::difficulty_threshold_is_valid(&block.header, &network, &height, &hash)?;
|
||||
} else {
|
||||
// Do the difficulty checks first, to raise the threshold for
|
||||
// attacks that use any other fields.
|
||||
check::difficulty_is_valid(&block.header, &network, &height, &hash)?;
|
||||
check::equihash_solution_is_valid(&block.header)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, check the Merkle root validity, to ensure that
|
||||
|
|
|
@ -595,8 +595,10 @@ where
|
|||
.ok_or(VerifyCheckpointError::CoinbaseHeight { hash })?;
|
||||
self.check_height(height)?;
|
||||
|
||||
crate::block::check::difficulty_is_valid(&block.header, &self.network, &height, &hash)?;
|
||||
crate::block::check::equihash_solution_is_valid(&block.header)?;
|
||||
if !self.network.disable_pow() {
|
||||
crate::block::check::difficulty_is_valid(&block.header, &self.network, &height, &hash)?;
|
||||
crate::block::check::equihash_solution_is_valid(&block.header)?;
|
||||
}
|
||||
|
||||
// don't do precalculation until the block passes basic difficulty checks
|
||||
let block = CheckpointVerifiedBlock::with_hash(block, hash);
|
||||
|
|
|
@ -55,41 +55,60 @@ impl ParameterCheckpoint for Network {
|
|||
fn genesis_hash(&self) -> zebra_chain::block::Hash {
|
||||
match self {
|
||||
// zcash-cli getblockhash 0
|
||||
Network::Mainnet => "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08",
|
||||
// zcash-cli -testnet getblockhash 0
|
||||
// TODO: Add a `genesis_hash` field to `testnet::Parameters` and return it here (#8366)
|
||||
Network::Testnet(_params) => {
|
||||
"05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38"
|
||||
}
|
||||
Network::Mainnet => "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08"
|
||||
.parse()
|
||||
.expect("hard-coded hash parses"),
|
||||
// See `zebra_chain::parameters::network::testnet` for more details.
|
||||
Network::Testnet(params) => params.genesis_hash(),
|
||||
}
|
||||
.parse()
|
||||
.expect("hard-coded hash parses")
|
||||
}
|
||||
|
||||
fn checkpoint_list(&self) -> CheckpointList {
|
||||
// parse calls CheckpointList::from_list
|
||||
// TODO:
|
||||
// - Add a `genesis_hash` field to `testnet::Parameters` and return it here (#8366)
|
||||
// - Try to disable checkpoints entirely for regtest and custom testnets
|
||||
let checkpoint_list: CheckpointList = match self {
|
||||
Network::Mainnet => MAINNET_CHECKPOINTS
|
||||
.parse()
|
||||
.expect("Hard-coded Mainnet checkpoint list parses and validates"),
|
||||
Network::Testnet(_params) => TESTNET_CHECKPOINTS
|
||||
.parse()
|
||||
.expect("Hard-coded Testnet checkpoint list parses and validates"),
|
||||
let (checkpoints_for_network, should_fallback_to_genesis_hash_as_checkpoint) = match self {
|
||||
Network::Mainnet => (MAINNET_CHECKPOINTS, false),
|
||||
Network::Testnet(params) if params.is_default_testnet() => (TESTNET_CHECKPOINTS, false),
|
||||
Network::Testnet(_params) => (TESTNET_CHECKPOINTS, true),
|
||||
};
|
||||
|
||||
match checkpoint_list.hash(block::Height(0)) {
|
||||
Some(hash) if hash == self.genesis_hash() => checkpoint_list,
|
||||
Some(_) => {
|
||||
panic!("The hard-coded genesis checkpoint does not match the network genesis hash")
|
||||
// Check that the list starts with the correct genesis block and parses checkpoint list.
|
||||
let first_checkpoint_height = checkpoints_for_network
|
||||
.lines()
|
||||
.next()
|
||||
.map(checkpoint_height_and_hash);
|
||||
|
||||
match first_checkpoint_height {
|
||||
// parse calls CheckpointList::from_list
|
||||
Some(Ok((block::Height(0), hash))) if hash == self.genesis_hash() => {
|
||||
checkpoints_for_network
|
||||
.parse()
|
||||
.expect("hard-coded checkpoint list parses and validates")
|
||||
}
|
||||
None => unreachable!("Parser should have checked for a missing genesis checkpoint"),
|
||||
_ if should_fallback_to_genesis_hash_as_checkpoint => {
|
||||
CheckpointList::from_list([(block::Height(0), self.genesis_hash())])
|
||||
.expect("hard-coded checkpoint list parses and validates")
|
||||
}
|
||||
Some(Ok((block::Height(0), _))) => {
|
||||
panic!("the genesis checkpoint does not match the {self} genesis hash")
|
||||
}
|
||||
Some(Ok(_)) => panic!("checkpoints must start at the genesis block height 0"),
|
||||
Some(Err(err)) => panic!("{err}"),
|
||||
None => panic!(
|
||||
"there must be at least one checkpoint on default networks, for the genesis block"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a checkpoint to a [`block::Height`] and [`block::Hash`].
|
||||
fn checkpoint_height_and_hash(checkpoint: &str) -> Result<(block::Height, block::Hash), BoxError> {
|
||||
let fields = checkpoint.split(' ').collect::<Vec<_>>();
|
||||
if let [height, hash] = fields[..] {
|
||||
Ok((height.parse()?, hash.parse()?))
|
||||
} else {
|
||||
Err(format!("Invalid checkpoint format: expected 2 space-separated fields but found {}: '{checkpoint}'", fields.len()).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of block height and hash checkpoints.
|
||||
///
|
||||
/// Checkpoints should be chosen to avoid forks or chain reorganizations,
|
||||
|
@ -115,12 +134,7 @@ impl FromStr for CheckpointList {
|
|||
let mut checkpoint_list: Vec<(block::Height, block::Hash)> = Vec::new();
|
||||
|
||||
for checkpoint in s.lines() {
|
||||
let fields = checkpoint.split(' ').collect::<Vec<_>>();
|
||||
if let [height, hash] = fields[..] {
|
||||
checkpoint_list.push((height.parse()?, hash.parse()?));
|
||||
} else {
|
||||
Err(format!("Invalid checkpoint format: expected 2 space-separated fields but found {}: '{checkpoint}'", fields.len()))?;
|
||||
};
|
||||
checkpoint_list.push(checkpoint_height_and_hash(checkpoint)?);
|
||||
}
|
||||
|
||||
CheckpointList::from_list(checkpoint_list)
|
||||
|
@ -146,17 +160,9 @@ impl CheckpointList {
|
|||
let checkpoints: BTreeMap<block::Height, block::Hash> =
|
||||
original_checkpoints.into_iter().collect();
|
||||
|
||||
// Check that the list starts with the correct genesis block
|
||||
// Check that the list starts with _some_ genesis block
|
||||
match checkpoints.iter().next() {
|
||||
// TODO: If required (we may not need checkpoints at all in Regtest or custom testnets):
|
||||
// move this check to `<Network as ParameterCheckpoint>::checkpoint_list(&network)` method above (#8366),
|
||||
// See <https://github.com/ZcashFoundation/zebra/pull/7924#discussion_r1385865347>
|
||||
Some((block::Height(0), hash))
|
||||
if (hash == &Network::Mainnet.genesis_hash()
|
||||
|| hash == &Network::new_default_testnet().genesis_hash()) => {}
|
||||
Some((block::Height(0), _)) => {
|
||||
Err("the genesis checkpoint does not match the Mainnet or Testnet genesis hash")?
|
||||
}
|
||||
Some((block::Height(0), _hash)) => {}
|
||||
Some(_) => Err("checkpoints must start at the genesis block height 0")?,
|
||||
None => Err("there must be at least one checkpoint, for the genesis block")?,
|
||||
};
|
||||
|
|
|
@ -237,6 +237,7 @@ fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> {
|
|||
|
||||
let _ = Mainnet.checkpoint_list();
|
||||
let _ = Network::new_default_testnet().checkpoint_list();
|
||||
let _ = Network::new_regtest(Default::default()).checkpoint_list();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -629,8 +629,8 @@ impl<'de> Deserialize<'de> for Config {
|
|||
{
|
||||
#[derive(Deserialize)]
|
||||
struct DTestnetParameters {
|
||||
#[serde(default)]
|
||||
pub(super) activation_heights: ConfiguredActivationHeights,
|
||||
network_name: Option<String>,
|
||||
activation_heights: Option<ConfiguredActivationHeights>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -639,6 +639,7 @@ impl<'de> Deserialize<'de> for Config {
|
|||
listen_addr: String,
|
||||
network: NetworkKind,
|
||||
testnet_parameters: Option<DTestnetParameters>,
|
||||
regtest_activation_heights: ConfiguredActivationHeights,
|
||||
initial_mainnet_peers: IndexSet<String>,
|
||||
initial_testnet_peers: IndexSet<String>,
|
||||
cache_dir: CacheDir,
|
||||
|
@ -655,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,
|
||||
|
@ -669,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,
|
||||
|
@ -677,23 +680,55 @@ impl<'de> Deserialize<'de> for Config {
|
|||
max_connections_per_ip,
|
||||
} = DConfig::deserialize(deserializer)?;
|
||||
|
||||
// TODO: Panic here if the initial testnet peers are the default initial testnet peers.
|
||||
let network = if let Some(DTestnetParameters { activation_heights }) = testnet_parameters {
|
||||
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);
|
||||
|
||||
testnet::Parameters::build()
|
||||
.activation_heights(activation_heights)
|
||||
.to_network()
|
||||
} 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()
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,14 +45,14 @@ 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"] }
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"] }
|
||||
|
||||
|
|
|
@ -451,6 +451,7 @@ fn finalized_equals_pushed_history_tree() -> Result<()> {
|
|||
/// Check that rejected blocks do not change the internal state of a genesis chain
|
||||
/// in a non-finalized state.
|
||||
#[test]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn rejection_restores_internal_state_genesis() -> Result<()> {
|
||||
let _init_guard = zebra_test::init();
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ tinyvec = { version = "1.6.0", features = ["rustc_1_55"] }
|
|||
humantime = "2.1.0"
|
||||
owo-colors = "4.0.0"
|
||||
spandoc = "0.2.2"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
tracing-error = "0.2.0"
|
||||
|
|
|
@ -95,10 +95,10 @@ tinyvec = { version = "1.6.0", features = ["rustc_1_55"] }
|
|||
|
||||
structopt = "0.3.26"
|
||||
hex = "0.4.3"
|
||||
serde_json = "1.0.115"
|
||||
serde_json = "1.0.116"
|
||||
tracing-error = "0.2.0"
|
||||
tracing-subscriber = "0.3.18"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
|
||||
zebra-node-services = { path = "../zebra-node-services", version = "1.0.0-beta.36" }
|
||||
zebra-chain = { path = "../zebra-chain", version = "1.0.0-beta.36" }
|
||||
|
@ -120,11 +120,11 @@ tokio = { version = "1.37.0", features = ["full"], optional = true }
|
|||
|
||||
jsonrpc = { version = "0.18.0", optional = true }
|
||||
|
||||
zcash_primitives = { version = "0.13.0-rc.1", optional = true }
|
||||
zcash_primitives = { version = "0.13.0", optional = true }
|
||||
zcash_client_backend = {version = "0.10.0-rc.1", optional = true}
|
||||
|
||||
# For the openapi generator
|
||||
syn = { version = "2.0.58", features = ["full"], optional = true }
|
||||
syn = { version = "2.0.60", features = ["full"], optional = true }
|
||||
quote = { version = "1.0.36", optional = true }
|
||||
serde_yaml = { version = "0.9.34+deprecated", optional = true }
|
||||
serde = { version = "1.0.196", features = ["serde_derive"], optional = true }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"], optional = true }
|
||||
|
|
|
@ -178,7 +178,7 @@ humantime-serde = "1.1.1"
|
|||
indexmap = "2.2.6"
|
||||
lazy_static = "1.4.0"
|
||||
semver = "1.0.22"
|
||||
serde = { version = "1.0.196", features = ["serde_derive"] }
|
||||
serde = { version = "1.0.198", features = ["serde_derive"] }
|
||||
toml = "0.8.11"
|
||||
|
||||
futures = "0.3.30"
|
||||
|
@ -193,7 +193,7 @@ color-eyre = { version = "0.6.3", default-features = false, features = ["issue-u
|
|||
# Enable a feature that makes tinyvec compile much faster.
|
||||
tinyvec = { version = "1.6.0", features = ["rustc_1_55"] }
|
||||
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.59"
|
||||
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
tracing-appender = "0.2.3"
|
||||
|
@ -210,7 +210,7 @@ num-integer = "0.1.46"
|
|||
rand = "0.8.5"
|
||||
|
||||
# prod feature internal-miner
|
||||
thread-priority = { version = "0.16.0", optional = true }
|
||||
thread-priority = { version = "1.0.0", optional = true }
|
||||
|
||||
# prod feature sentry
|
||||
sentry = { version = "0.32.2", default-features = false, features = ["backtrace", "contexts", "reqwest", "rustls", "tracing"], optional = true }
|
||||
|
@ -261,7 +261,7 @@ regex = "1.10.4"
|
|||
insta = { version = "1.38.0", features = ["json"] }
|
||||
|
||||
# zebra-rpc needs the preserve_order feature, it also makes test results more stable
|
||||
serde_json = { version = "1.0.115", features = ["preserve_order"] }
|
||||
serde_json = { version = "1.0.116", features = ["preserve_order"] }
|
||||
tempfile = "3.10.1"
|
||||
|
||||
hyper = { version = "0.14.28", features = ["http1", "http2", "server"]}
|
||||
|
|
|
@ -22,7 +22,8 @@ pub const ESTIMATED_RELEASE_HEIGHT: u32 = 2_471_000;
|
|||
///
|
||||
/// - Zebra will exit with a panic if the current tip height is bigger than the `ESTIMATED_RELEASE_HEIGHT`
|
||||
/// plus this number of days.
|
||||
pub const EOS_PANIC_AFTER: u32 = 112;
|
||||
/// - Currently set to 20 weeks.
|
||||
pub const EOS_PANIC_AFTER: u32 = 140;
|
||||
|
||||
/// The number of days before the end of support where Zebra will display warnings.
|
||||
pub const EOS_WARN_AFTER: u32 = EOS_PANIC_AFTER - 14;
|
||||
|
|
|
@ -161,10 +161,12 @@ use color_eyre::{
|
|||
use semver::Version;
|
||||
use serde_json::Value;
|
||||
|
||||
use tower::ServiceExt;
|
||||
use zebra_chain::{
|
||||
block::{self, Height},
|
||||
block::{self, genesis::regtest_genesis_block, Height},
|
||||
parameters::Network::{self, *},
|
||||
};
|
||||
use zebra_consensus::ParameterCheckpoint;
|
||||
use zebra_network::constants::PORT_IN_USE_ERROR;
|
||||
use zebra_node_services::rpc_client::RpcRequestClient;
|
||||
use zebra_state::{constants::LOCK_FILE_ERROR, state_database_format_version_in_code};
|
||||
|
@ -622,6 +624,7 @@ fn config_tests() -> Result<()> {
|
|||
invalid_generated_config()?;
|
||||
|
||||
// Check that we have a current version of the config stored
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
last_config_is_stored()?;
|
||||
|
||||
// Check that Zebra's previous configurations still work
|
||||
|
@ -1756,7 +1759,7 @@ fn non_blocking_logger() -> Result<()> {
|
|||
});
|
||||
|
||||
// Wait until the spawned task finishes up to 45 seconds before shutting down tokio runtime
|
||||
if done_rx.recv_timeout(Duration::from_secs(45)).is_ok() {
|
||||
if done_rx.recv_timeout(Duration::from_secs(90)).is_ok() {
|
||||
rt.shutdown_timeout(Duration::from_secs(3));
|
||||
}
|
||||
|
||||
|
@ -3098,3 +3101,29 @@ fn scan_start_where_left() -> Result<()> {
|
|||
async fn scan_task_commands() -> Result<()> {
|
||||
common::shielded_scan::scan_task_commands::run().await
|
||||
}
|
||||
|
||||
/// Checks that the Regtest genesis block can be validated.
|
||||
#[tokio::test]
|
||||
async fn validate_regtest_genesis_block() {
|
||||
let _init_guard = zebra_test::init();
|
||||
|
||||
let network = Network::new_regtest(Default::default());
|
||||
let state = zebra_state::init_test(&network);
|
||||
let (
|
||||
block_verifier_router,
|
||||
_transaction_verifier,
|
||||
_parameter_download_task_handle,
|
||||
_max_checkpoint_height,
|
||||
) = zebra_consensus::router::init(zebra_consensus::Config::default(), &network, state).await;
|
||||
|
||||
let genesis_hash = block_verifier_router
|
||||
.oneshot(zebra_consensus::Request::Commit(regtest_genesis_block()))
|
||||
.await
|
||||
.expect("should validate Regtest genesis block");
|
||||
|
||||
assert_eq!(
|
||||
genesis_hash,
|
||||
network.genesis_hash(),
|
||||
"validated block hash should match network genesis hash"
|
||||
)
|
||||
}
|
||||
|
|
|
@ -57,9 +57,12 @@ initial_testnet_peers = [
|
|||
]
|
||||
listen_addr = "0.0.0.0:8233"
|
||||
max_connections_per_ip = 1
|
||||
network = "Testnet"
|
||||
network = "Regtest"
|
||||
peerset_initial_target_size = 25
|
||||
|
||||
[network.testnet_parameters]
|
||||
network_name = "ConfiguredTestnet_1"
|
||||
|
||||
[network.testnet_parameters.activation_heights]
|
||||
BeforeOverwinter = 1
|
||||
Overwinter = 207_500
|
||||
|
@ -69,6 +72,15 @@ Heartwood = 903_800
|
|||
Canopy = 1_028_500
|
||||
NU5 = 1_842_420
|
||||
|
||||
[network.regtest_activation_heights]
|
||||
BeforeOverwinter = 1
|
||||
Overwinter = 207_500
|
||||
Sapling = 280_000
|
||||
Blossom = 584_000
|
||||
Heartwood = 903_800
|
||||
Canopy = 1_028_500
|
||||
NU5 = 1_842_420
|
||||
|
||||
[rpc]
|
||||
debug_force_finished_sync = false
|
||||
parallel_cpu_threads = 0
|
||||
|
|
Loading…
Reference in New Issue