From 2b17f2b6ef9cab669bf743b1b68d1f46257a869b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 29 May 2026 11:39:59 +0000 Subject: [PATCH 01/16] ci: fix issues found in upstream Zebra PR --- .github/workflows/ci-basic.yml | 39 ++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index ff00f174da2..8bbf3366dda 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -2,6 +2,9 @@ name: Basic checks on: [push] +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest @@ -19,7 +22,10 @@ jobs: SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Show system resource summary (before cleanup) run: | df -h @@ -35,6 +41,7 @@ jobs: - name: Install dependencies on Ubuntu run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev + - name: Install formatting & linting tools run: rustup component add rustfmt clippy @@ -47,16 +54,44 @@ jobs: sed -i 's|.*"--cfg", .feature="tx_v6".*|# &|' .cargo/config.toml sed -i 's|.*"--cfg", "zcash_unstable=\\"nu7\\"".*|# &|' .cargo/config.toml - - name: Run tests + - name: Run non-network tests + env: + SKIP_NETWORK_TESTS: "1" run: timeout --preserve-status 1h cargo test --verbose --locked + + - name: Run network-sensitive tests + run: | + for attempt in 1 2 3; do + echo "network-sensitive tests attempt ${attempt}" + + timeout --preserve-status 45m bash -c ' + set -euo pipefail + cargo test -p zebra-network --lib --verbose --locked -- --test-threads=1 + cargo test -p zebrad --test acceptance --verbose --locked -- --test-threads=1 + ' && exit 0 + + status=$? + echo "network-sensitive tests attempt ${attempt} failed with status ${status}" + + if [ "${attempt}" = "3" ]; then + exit "${status}" + fi + + sleep 30 + done + - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked + - name: Run format check run: cargo fmt -- --check + - name: Run clippy run: cargo clippy --workspace --all-targets --features "default-release-binaries proptest-impl lightwalletd-grpc-tests zebra-checkpoints" + - name: Restore cargo config run: git checkout -- .cargo/config.toml + - name: Verify working directory is clean run: git diff --exit-code From ba39b0a2de3a3f04ae96127e5a5d858886cf298f Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 1 Jun 2026 08:23:18 +0000 Subject: [PATCH 02/16] Update Orchard ZSA workflow block tests to use ExpectedTranscriptError instead of the is_valid flag --- zebra-consensus/src/orchard_zsa/tests.rs | 14 +++++--------- zebra-state/src/service/check/tests/issuance.rs | 4 ++-- .../src/vectors/orchard_zsa_workflow_blocks.rs | 16 +++++++++------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/zebra-consensus/src/orchard_zsa/tests.rs b/zebra-consensus/src/orchard_zsa/tests.rs index 04b0b355a39..8e27f08d1c9 100644 --- a/zebra-consensus/src/orchard_zsa/tests.rs +++ b/zebra-consensus/src/orchard_zsa/tests.rs @@ -176,25 +176,21 @@ fn create_transcript_data<'a, I: IntoIterator>( |OrchardWorkflowBlock { height: _, bytes, - is_valid, + expected_result, }| { ( Arc::new(Block::zcash_deserialize(&bytes[..]).expect("block should deserialize")), - *is_valid, + expected_result.clone(), ) }, ); - std::iter::once((regtest_genesis_block(), true)) + std::iter::once((regtest_genesis_block(), Ok(()))) .chain(workflow_blocks) - .map(|(block, is_valid)| { + .map(|(block, expected_result)| { ( Request::Commit(block.clone()), - if is_valid { - Ok(block.hash()) - } else { - Err(ExpectedTranscriptError::Any) - }, + expected_result.map(|_| block.hash()), ) }) } diff --git a/zebra-state/src/service/check/tests/issuance.rs b/zebra-state/src/service/check/tests/issuance.rs index b7a54a41944..eefd65cdbee 100644 --- a/zebra-state/src/service/check/tests/issuance.rs +++ b/zebra-state/src/service/check/tests/issuance.rs @@ -59,7 +59,7 @@ fn check_burns_and_issuance() { for OrchardWorkflowBlock { height, bytes, - is_valid, + expected_result, } in ORCHARD_ZSA_WORKFLOW_BLOCKS.iter() { let block = @@ -83,7 +83,7 @@ fn check_burns_and_issuance() { let commit_result = validate_and_commit_non_finalized(&finalized_state.db, &mut non_finalized_state, block); - if !is_valid { + if expected_result.is_err() { assert!( issued_asset_changes_result.is_err() || commit_result.is_err(), "invalid workflow block at height {height} should fail issued-asset validation or commit" diff --git a/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs b/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs index 8aa976208fb..f5b66e69a8c 100644 --- a/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs +++ b/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs @@ -5,14 +5,16 @@ use hex::FromHex; use lazy_static::lazy_static; +use crate::transcript::ExpectedTranscriptError; + /// Represents a serialized block and its validity status. pub struct OrchardWorkflowBlock { /// Block height. pub height: u32, /// Serialized byte data of the block. pub bytes: &'static [u8], - /// Indicates whether the block is valid. - pub is_valid: bool, + /// Expected result of transcript validation for this block. + pub expected_result: Result<(), ExpectedTranscriptError>, } fn decode_bytes(hex: &str) -> Vec { @@ -41,35 +43,35 @@ lazy_static! { OrchardWorkflowBlock { height: 1, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_1_BYTES.as_slice(), - is_valid: true + expected_result: Ok(()) }, // Transfer OrchardWorkflowBlock { height: 2, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_2_BYTES.as_slice(), - is_valid: true + expected_result: Ok(()) }, // Burn: 7, Burn: 2 OrchardWorkflowBlock { height: 3, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_3_BYTES.as_slice(), - is_valid: true + expected_result: Ok(()) }, // Issue: finalize OrchardWorkflowBlock { height: 4, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_4_BYTES.as_slice(), - is_valid: true + expected_result: Ok(()) }, // Try to issue: 2000 OrchardWorkflowBlock { height: 5, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_5_BYTES.as_slice(), - is_valid: false + expected_result: Err(ExpectedTranscriptError::Any) }, ]; } From 1f21ee2e4f2803e6a309163d6fae87447784610e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 4 Jun 2026 13:53:35 +0000 Subject: [PATCH 03/16] Revert "ci: fix issues found in upstream Zebra PR" This reverts commit 2b17f2b6ef9cab669bf743b1b68d1f46257a869b. --- .github/workflows/ci-basic.yml | 39 ++-------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 8bbf3366dda..ff00f174da2 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -2,9 +2,6 @@ name: Basic checks on: [push] -permissions: - contents: read - jobs: test: runs-on: ubuntu-latest @@ -22,10 +19,7 @@ jobs: SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - + - uses: actions/checkout@v4 - name: Show system resource summary (before cleanup) run: | df -h @@ -41,7 +35,6 @@ jobs: - name: Install dependencies on Ubuntu run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev - - name: Install formatting & linting tools run: rustup component add rustfmt clippy @@ -54,44 +47,16 @@ jobs: sed -i 's|.*"--cfg", .feature="tx_v6".*|# &|' .cargo/config.toml sed -i 's|.*"--cfg", "zcash_unstable=\\"nu7\\"".*|# &|' .cargo/config.toml - - name: Run non-network tests - env: - SKIP_NETWORK_TESTS: "1" + - name: Run tests run: timeout --preserve-status 1h cargo test --verbose --locked - - - name: Run network-sensitive tests - run: | - for attempt in 1 2 3; do - echo "network-sensitive tests attempt ${attempt}" - - timeout --preserve-status 45m bash -c ' - set -euo pipefail - cargo test -p zebra-network --lib --verbose --locked -- --test-threads=1 - cargo test -p zebrad --test acceptance --verbose --locked -- --test-threads=1 - ' && exit 0 - - status=$? - echo "network-sensitive tests attempt ${attempt} failed with status ${status}" - - if [ "${attempt}" = "3" ]; then - exit "${status}" - fi - - sleep 30 - done - - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked - - name: Run format check run: cargo fmt -- --check - - name: Run clippy run: cargo clippy --workspace --all-targets --features "default-release-binaries proptest-impl lightwalletd-grpc-tests zebra-checkpoints" - - name: Restore cargo config run: git checkout -- .cargo/config.toml - - name: Verify working directory is clean run: git diff --exit-code From a9a44dff6e33b5086a91df3864954cc7aafd484b Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:10:18 +0300 Subject: [PATCH 04/16] split run attempts --- .github/workflows/ci-basic.yml | 67 +++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index ff00f174da2..0867379c704 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -2,6 +2,9 @@ name: Basic checks on: [push] +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest @@ -19,7 +22,10 @@ jobs: SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Show system resource summary (before cleanup) run: | df -h @@ -35,6 +41,7 @@ jobs: - name: Install dependencies on Ubuntu run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev + - name: Install formatting & linting tools run: rustup component add rustfmt clippy @@ -47,16 +54,72 @@ jobs: sed -i 's|.*"--cfg", .feature="tx_v6".*|# &|' .cargo/config.toml sed -i 's|.*"--cfg", "zcash_unstable=\\"nu7\\"".*|# &|' .cargo/config.toml - - name: Run tests + - name: Run non-network tests + env: + SKIP_NETWORK_TESTS: "1" run: timeout --preserve-status 1h cargo test --verbose --locked + + # Build the network-sensitive test binaries outside the retry loops so + # compile failures fail once instead of being retried, and retry + # attempts below contain only test runtime. + - name: Build network-sensitive tests + run: | + cargo test -p zebra-network --lib --verbose --locked --no-run + cargo test -p zebrad --test acceptance --verbose --locked --no-run + + # The two network-sensitive suites are retried independently so a flaky + # failure in one does not re-run the other. Per-attempt timeouts are + # sized from measured serial test runtimes (~15m and ~19m) plus headroom. + - name: Run zebra-network tests + run: | + for attempt in 1 2 3; do + echo "zebra-network tests attempt ${attempt}" + + timeout --preserve-status 25m \ + cargo test -p zebra-network --lib --verbose --locked -- --test-threads=1 \ + && exit 0 + + status=$? + echo "zebra-network tests attempt ${attempt} failed with status ${status}" + + if [ "${attempt}" = "3" ]; then + exit "${status}" + fi + + sleep 30 + done + + - name: Run zebrad acceptance tests + run: | + for attempt in 1 2 3; do + echo "zebrad acceptance tests attempt ${attempt}" + + timeout --preserve-status 30m \ + cargo test -p zebrad --test acceptance --verbose --locked -- --test-threads=1 \ + && exit 0 + + status=$? + echo "zebrad acceptance tests attempt ${attempt} failed with status ${status}" + + if [ "${attempt}" = "3" ]; then + exit "${status}" + fi + + sleep 30 + done + - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked + - name: Run format check run: cargo fmt -- --check + - name: Run clippy run: cargo clippy --workspace --all-targets --features "default-release-binaries proptest-impl lightwalletd-grpc-tests zebra-checkpoints" + - name: Restore cargo config run: git checkout -- .cargo/config.toml + - name: Verify working directory is clean run: git diff --exit-code From 06e16f491738e4246da9d325900b83d6b469115c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 9 Jun 2026 07:38:51 +0000 Subject: [PATCH 05/16] Use ExpectedTranscriptError::Exact instead of ExpectedTranscriptError::Any --- zebra-consensus/src/orchard_zsa/tests.rs | 59 ++++++++++++++++--- .../src/service/check/tests/issuance.rs | 6 +- .../vectors/orchard_zsa_workflow_blocks.rs | 19 +++--- 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/zebra-consensus/src/orchard_zsa/tests.rs b/zebra-consensus/src/orchard_zsa/tests.rs index 8e27f08d1c9..edc8e7bf157 100644 --- a/zebra-consensus/src/orchard_zsa/tests.rs +++ b/zebra-consensus/src/orchard_zsa/tests.rs @@ -7,6 +7,7 @@ use std::{ collections::{hash_map, HashMap}, + error::Error, sync::Arc, }; @@ -17,7 +18,7 @@ use tower::ServiceExt; use orchard::{ issuance::{ auth::{IssueValidatingKey, ZSASchnorr}, - {AssetRecord, IssueAction}, + Error as IssuanceError, {AssetRecord, IssueAction}, }, note::{AssetBase, AssetId}, value::NoteValue, @@ -25,6 +26,7 @@ use orchard::{ use zebra_chain::{ block::{genesis::regtest_genesis_block, Block, Hash}, + orchard_zsa::AssetStateError, parameters::{testnet::ConfiguredActivationHeights, Network}, serialization::ZcashDeserialize, }; @@ -32,11 +34,14 @@ use zebra_chain::{ #[cfg(all(zcash_unstable = "nu7", feature = "tx_v6"))] use zebra_chain::orchard_zsa::{AssetState, BurnItem}; -use zebra_state::{ReadRequest, ReadResponse, ReadStateService}; +use zebra_state::{ + CommitSemanticallyVerifiedError, ReadRequest, ReadResponse, ReadStateService, + ValidateContextError, +}; use zebra_test::{ transcript::{ExpectedTranscriptError, Transcript}, - vectors::{OrchardWorkflowBlock, ORCHARD_ZSA_WORKFLOW_BLOCKS}, + vectors::{OrchardWorkflowBlock, OrchardWorkflowBlockResult, ORCHARD_ZSA_WORKFLOW_BLOCKS}, }; use crate::{block::Request, Config}; @@ -56,6 +61,39 @@ enum AssetRecordsError { ModifyFinalized, } +type BoxError = Box; + +fn has_finalized_asset_error(error: &(dyn Error + 'static)) -> bool { + let mut error = Some(error); + + while let Some(err) = error { + if matches!( + err.downcast_ref::(), + Some(ValidateContextError::InvalidIssuedAsset( + AssetStateError::Issue(IssuanceError::IssueActionPreviouslyFinalizedAssetBase,) + )) + ) { + return true; + } + + error = err.source(); + } + + false +} + +fn expect_finalized_asset_error(error: Option) -> Result<(), BoxError> { + let Some(error) = error else { + return Err(eyre!("expected finalized asset error").into()); + }; + + if has_finalized_asset_error(error.as_ref()) { + Ok(()) + } else { + Err(error) + } +} + /// Processes orchard burns, decreasing asset supply. fn process_burns<'a, I: IntoIterator>( asset_records: &mut AssetRecords, @@ -178,10 +216,17 @@ fn create_transcript_data<'a, I: IntoIterator>( bytes, expected_result, }| { - ( - Arc::new(Block::zcash_deserialize(&bytes[..]).expect("block should deserialize")), - expected_result.clone(), - ) + let block = + Arc::new(Block::zcash_deserialize(&bytes[..]).expect("block should deserialize")); + + let expected_result = match expected_result { + OrchardWorkflowBlockResult::Valid => Ok(()), + OrchardWorkflowBlockResult::IssueFinalizedAssetError => { + Err(ExpectedTranscriptError::exact(expect_finalized_asset_error)) + } + }; + + (block, expected_result) }, ); diff --git a/zebra-state/src/service/check/tests/issuance.rs b/zebra-state/src/service/check/tests/issuance.rs index eefd65cdbee..ab23de69c40 100644 --- a/zebra-state/src/service/check/tests/issuance.rs +++ b/zebra-state/src/service/check/tests/issuance.rs @@ -7,7 +7,9 @@ use zebra_chain::{ serialization::ZcashDeserialize, }; -use zebra_test::vectors::{OrchardWorkflowBlock, ORCHARD_ZSA_WORKFLOW_BLOCKS}; +use zebra_test::vectors::{ + OrchardWorkflowBlock, OrchardWorkflowBlockResult, ORCHARD_ZSA_WORKFLOW_BLOCKS, +}; use crate::{ check::Chain, @@ -83,7 +85,7 @@ fn check_burns_and_issuance() { let commit_result = validate_and_commit_non_finalized(&finalized_state.db, &mut non_finalized_state, block); - if expected_result.is_err() { + if matches!(expected_result, OrchardWorkflowBlockResult::Valid) { assert!( issued_asset_changes_result.is_err() || commit_result.is_err(), "invalid workflow block at height {height} should fail issued-asset validation or commit" diff --git a/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs b/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs index f5b66e69a8c..9e1f463fd5f 100644 --- a/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs +++ b/zebra-test/src/vectors/orchard_zsa_workflow_blocks.rs @@ -5,7 +5,12 @@ use hex::FromHex; use lazy_static::lazy_static; -use crate::transcript::ExpectedTranscriptError; +/// Expected consensus result for a block. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum OrchardWorkflowBlockResult { + Valid, + IssueFinalizedAssetError, +} /// Represents a serialized block and its validity status. pub struct OrchardWorkflowBlock { @@ -14,7 +19,7 @@ pub struct OrchardWorkflowBlock { /// Serialized byte data of the block. pub bytes: &'static [u8], /// Expected result of transcript validation for this block. - pub expected_result: Result<(), ExpectedTranscriptError>, + pub expected_result: OrchardWorkflowBlockResult, } fn decode_bytes(hex: &str) -> Vec { @@ -43,35 +48,35 @@ lazy_static! { OrchardWorkflowBlock { height: 1, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_1_BYTES.as_slice(), - expected_result: Ok(()) + expected_result: OrchardWorkflowBlockResult::Valid }, // Transfer OrchardWorkflowBlock { height: 2, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_2_BYTES.as_slice(), - expected_result: Ok(()) + expected_result: OrchardWorkflowBlockResult::Valid }, // Burn: 7, Burn: 2 OrchardWorkflowBlock { height: 3, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_3_BYTES.as_slice(), - expected_result: Ok(()) + expected_result: OrchardWorkflowBlockResult::Valid }, // Issue: finalize OrchardWorkflowBlock { height: 4, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_4_BYTES.as_slice(), - expected_result: Ok(()) + expected_result: OrchardWorkflowBlockResult::Valid }, // Try to issue: 2000 OrchardWorkflowBlock { height: 5, bytes: ORCHARD_ZSA_WORKFLOW_BLOCK_5_BYTES.as_slice(), - expected_result: Err(ExpectedTranscriptError::Any) + expected_result: OrchardWorkflowBlockResult::IssueFinalizedAssetError }, ]; } From f3a224bd3c0eaf23b481beea4be37248c540c4f2 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 9 Jun 2026 08:31:09 +0000 Subject: [PATCH 06/16] Add a comment to has_finalized_asset_error to explain why Debug output is used --- zebra-consensus/src/orchard_zsa/tests.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/zebra-consensus/src/orchard_zsa/tests.rs b/zebra-consensus/src/orchard_zsa/tests.rs index edc8e7bf157..71fcf502049 100644 --- a/zebra-consensus/src/orchard_zsa/tests.rs +++ b/zebra-consensus/src/orchard_zsa/tests.rs @@ -18,7 +18,7 @@ use tower::ServiceExt; use orchard::{ issuance::{ auth::{IssueValidatingKey, ZSASchnorr}, - Error as IssuanceError, {AssetRecord, IssueAction}, + AssetRecord, IssueAction, }, note::{AssetBase, AssetId}, value::NoteValue, @@ -26,7 +26,6 @@ use orchard::{ use zebra_chain::{ block::{genesis::regtest_genesis_block, Block, Hash}, - orchard_zsa::AssetStateError, parameters::{testnet::ConfiguredActivationHeights, Network}, serialization::ZcashDeserialize, }; @@ -34,10 +33,7 @@ use zebra_chain::{ #[cfg(all(zcash_unstable = "nu7", feature = "tx_v6"))] use zebra_chain::orchard_zsa::{AssetState, BurnItem}; -use zebra_state::{ - CommitSemanticallyVerifiedError, ReadRequest, ReadResponse, ReadStateService, - ValidateContextError, -}; +use zebra_state::{CommitSemanticallyVerifiedError, ReadRequest, ReadResponse, ReadStateService}; use zebra_test::{ transcript::{ExpectedTranscriptError, Transcript}, @@ -67,11 +63,14 @@ fn has_finalized_asset_error(error: &(dyn Error + 'static)) -> bool { let mut error = Some(error); while let Some(err) = error { + // The inner CommitBlockError is private, so this test can only type-check + // the wrapper and inspect the specific InvalidIssuedAsset error via Debug. if matches!( - err.downcast_ref::(), - Some(ValidateContextError::InvalidIssuedAsset( - AssetStateError::Issue(IssuanceError::IssueActionPreviouslyFinalizedAssetBase,) - )) + err.downcast_ref::(), + Some(commit_error) + if format!("{commit_error:?}").contains( + "InvalidIssuedAsset(Issue(IssueActionPreviouslyFinalizedAssetBase))" + ) ) { return true; } @@ -87,7 +86,7 @@ fn expect_finalized_asset_error(error: Option) -> Result<(), BoxError> return Err(eyre!("expected finalized asset error").into()); }; - if has_finalized_asset_error(error.as_ref()) { + if has_finalized_asset_error(&*error) { Ok(()) } else { Err(error) From 00ca0be631a2f81b1d6979d01119ee83d221466d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 9 Jun 2026 09:20:09 +0000 Subject: [PATCH 07/16] Fix error in check_burns_and_issuance test --- zebra-state/src/service/check/tests/issuance.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-state/src/service/check/tests/issuance.rs b/zebra-state/src/service/check/tests/issuance.rs index ab23de69c40..5f15e22f298 100644 --- a/zebra-state/src/service/check/tests/issuance.rs +++ b/zebra-state/src/service/check/tests/issuance.rs @@ -85,7 +85,7 @@ fn check_burns_and_issuance() { let commit_result = validate_and_commit_non_finalized(&finalized_state.db, &mut non_finalized_state, block); - if matches!(expected_result, OrchardWorkflowBlockResult::Valid) { + if !matches!(expected_result, OrchardWorkflowBlockResult::Valid) { assert!( issued_asset_changes_result.is_err() || commit_result.is_err(), "invalid workflow block at height {height} should fail issued-asset validation or commit" From c65c34e0d8a3a5c485d4f38395a3f0f9c04ee025 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Jun 2026 08:45:50 +0000 Subject: [PATCH 08/16] ci: try to run non-network tests only --- .github/workflows/ci-basic.yml | 51 +--------------------------------- 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 0867379c704..9f42703f7ba 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -57,56 +57,7 @@ jobs: - name: Run non-network tests env: SKIP_NETWORK_TESTS: "1" - run: timeout --preserve-status 1h cargo test --verbose --locked - - # Build the network-sensitive test binaries outside the retry loops so - # compile failures fail once instead of being retried, and retry - # attempts below contain only test runtime. - - name: Build network-sensitive tests - run: | - cargo test -p zebra-network --lib --verbose --locked --no-run - cargo test -p zebrad --test acceptance --verbose --locked --no-run - - # The two network-sensitive suites are retried independently so a flaky - # failure in one does not re-run the other. Per-attempt timeouts are - # sized from measured serial test runtimes (~15m and ~19m) plus headroom. - - name: Run zebra-network tests - run: | - for attempt in 1 2 3; do - echo "zebra-network tests attempt ${attempt}" - - timeout --preserve-status 25m \ - cargo test -p zebra-network --lib --verbose --locked -- --test-threads=1 \ - && exit 0 - - status=$? - echo "zebra-network tests attempt ${attempt} failed with status ${status}" - - if [ "${attempt}" = "3" ]; then - exit "${status}" - fi - - sleep 30 - done - - - name: Run zebrad acceptance tests - run: | - for attempt in 1 2 3; do - echo "zebrad acceptance tests attempt ${attempt}" - - timeout --preserve-status 30m \ - cargo test -p zebrad --test acceptance --verbose --locked -- --test-threads=1 \ - && exit 0 - - status=$? - echo "zebrad acceptance tests attempt ${attempt} failed with status ${status}" - - if [ "${attempt}" = "3" ]; then - exit "${status}" - fi - - sleep 30 - done + run: timeout --preserve-status 1h cargo test --verbose --locked --skip trusted_chain_sync_handles_forks_correctly - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked From 1353336c2047f3977ec0fc07ea2fd38efce71296 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Jun 2026 09:00:53 +0000 Subject: [PATCH 09/16] ci: fix an error in the previous commit --- .github/workflows/ci-basic.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 9f42703f7ba..947caddbbcd 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -57,7 +57,8 @@ jobs: - name: Run non-network tests env: SKIP_NETWORK_TESTS: "1" - run: timeout --preserve-status 1h cargo test --verbose --locked --skip trusted_chain_sync_handles_forks_correctly + run: timeout --preserve-status 1h cargo test --verbose --locked -- \ + --skip trusted_chain_sync_handles_forks_correctly - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked From 6f68d6ee6e1bc520e5ddb4111b17be4bc79f2582 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Jun 2026 13:14:05 +0000 Subject: [PATCH 10/16] ci: run zebra-network tests serially --- .github/workflows/ci-basic.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 947caddbbcd..845da99a1c1 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -60,6 +60,12 @@ jobs: run: timeout --preserve-status 1h cargo test --verbose --locked -- \ --skip trusted_chain_sync_handles_forks_correctly + - name: Run zebra-network tests serially + run: | + timeout --preserve-status 30m \ + cargo test -p zebra-network --verbose --locked -- \ + --test-threads=1 + - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked From b18ad52c1d46942f4ea892db9657c61bde5fbe4e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Jun 2026 14:06:28 +0000 Subject: [PATCH 11/16] ci: run network and acceptance tests separately with cargo-nextest --- .github/workflows/ci-basic.yml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 845da99a1c1..b6c491850bc 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -57,14 +57,32 @@ jobs: - name: Run non-network tests env: SKIP_NETWORK_TESTS: "1" - run: timeout --preserve-status 1h cargo test --verbose --locked -- \ - --skip trusted_chain_sync_handles_forks_correctly + run: | + timeout --preserve-status 1h cargo test --verbose --locked -- \ + --skip trusted_chain_sync_handles_forks_correctly + + - name: Install cargo-nextest + uses: taiki-e/install-action@nextest + + - name: Run regular tests + run: | + timeout --preserve-status 1h \ + cargo nextest run --workspace --locked \ + -E 'not package(zebra-network) and not binary(acceptance)' - - name: Run zebra-network tests serially + - name: Run zebra-network tests run: | timeout --preserve-status 30m \ - cargo test -p zebra-network --verbose --locked -- \ - --test-threads=1 + cargo nextest run -p zebra-network --locked \ + --retries 3 \ + --test-threads 1 + + - name: Run zebrad acceptance tests + run: | + timeout --preserve-status 1h \ + cargo nextest run -p zebrad --test acceptance --locked \ + --retries 3 \ + --test-threads 1 - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked From 654f7c43bc759a529ab896ae971fc260666f4c51 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Jun 2026 19:40:17 +0000 Subject: [PATCH 12/16] ci: increase the number of threads for zebra-network tests to 4 --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index b6c491850bc..cf871c3228a 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -75,7 +75,7 @@ jobs: timeout --preserve-status 30m \ cargo nextest run -p zebra-network --locked \ --retries 3 \ - --test-threads 1 + --test-threads 4 - name: Run zebrad acceptance tests run: | From 81cdac581c0fdc2f0d079df15ca64a2227816922 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 11 Jun 2026 08:35:11 +0000 Subject: [PATCH 13/16] ci: remove thread limit for network tests --- .github/workflows/ci-basic.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index cf871c3228a..9b1bf7f86c7 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -74,8 +74,7 @@ jobs: run: | timeout --preserve-status 30m \ cargo nextest run -p zebra-network --locked \ - --retries 3 \ - --test-threads 4 + --retries 3 - name: Run zebrad acceptance tests run: | From 520f7574f45a6a2ad6e57f6c67257573b19e985b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 11 Jun 2026 10:29:04 +0000 Subject: [PATCH 14/16] ci: try to increase the number of threads for acceptance tests --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 9b1bf7f86c7..a522a48c0ce 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -81,7 +81,7 @@ jobs: timeout --preserve-status 1h \ cargo nextest run -p zebrad --test acceptance --locked \ --retries 3 \ - --test-threads 1 + --test-threads 4 - name: Run doc check run: cargo doc --workspace --no-deps --all-features --document-private-items --locked From b3d1d3ae8937ef1c46293838675e71f91537bddc Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Fri, 12 Jun 2026 10:39:37 +0300 Subject: [PATCH 15/16] removed debug string (#143) --- zebra-consensus/src/orchard_zsa/tests.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/zebra-consensus/src/orchard_zsa/tests.rs b/zebra-consensus/src/orchard_zsa/tests.rs index 71fcf502049..7124e89eafc 100644 --- a/zebra-consensus/src/orchard_zsa/tests.rs +++ b/zebra-consensus/src/orchard_zsa/tests.rs @@ -26,6 +26,7 @@ use orchard::{ use zebra_chain::{ block::{genesis::regtest_genesis_block, Block, Hash}, + orchard_zsa::AssetStateError, parameters::{testnet::ConfiguredActivationHeights, Network}, serialization::ZcashDeserialize, }; @@ -33,7 +34,7 @@ use zebra_chain::{ #[cfg(all(zcash_unstable = "nu7", feature = "tx_v6"))] use zebra_chain::orchard_zsa::{AssetState, BurnItem}; -use zebra_state::{CommitSemanticallyVerifiedError, ReadRequest, ReadResponse, ReadStateService}; +use zebra_state::{ReadRequest, ReadResponse, ReadStateService}; use zebra_test::{ transcript::{ExpectedTranscriptError, Transcript}, @@ -63,14 +64,14 @@ fn has_finalized_asset_error(error: &(dyn Error + 'static)) -> bool { let mut error = Some(error); while let Some(err) = error { - // The inner CommitBlockError is private, so this test can only type-check - // the wrapper and inspect the specific InvalidIssuedAsset error via Debug. + // The commit-error wrapper hides its inner error, but every layer derives + // `Error::source()`, so we can walk the chain down to the public leaf + // `AssetStateError` and match the exact variant instead of its Debug output. if matches!( - err.downcast_ref::(), - Some(commit_error) - if format!("{commit_error:?}").contains( - "InvalidIssuedAsset(Issue(IssueActionPreviouslyFinalizedAssetBase))" - ) + err.downcast_ref::(), + Some(AssetStateError::Issue( + orchard::issuance::Error::IssueActionPreviouslyFinalizedAssetBase + )) ) { return true; } From d17e7f17a94ae26c6b3c116e44e16462be65211e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 15 Jun 2026 14:54:44 +0000 Subject: [PATCH 16/16] Remove explanatory review comment in orchard_zsa/tests.rs --- zebra-consensus/src/orchard_zsa/tests.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/zebra-consensus/src/orchard_zsa/tests.rs b/zebra-consensus/src/orchard_zsa/tests.rs index 7124e89eafc..50361099c36 100644 --- a/zebra-consensus/src/orchard_zsa/tests.rs +++ b/zebra-consensus/src/orchard_zsa/tests.rs @@ -64,9 +64,6 @@ fn has_finalized_asset_error(error: &(dyn Error + 'static)) -> bool { let mut error = Some(error); while let Some(err) = error { - // The commit-error wrapper hides its inner error, but every layer derives - // `Error::source()`, so we can walk the chain down to the public leaf - // `AssetStateError` and match the exact variant instead of its Debug output. if matches!( err.downcast_ref::(), Some(AssetStateError::Issue(