Conversation
The front-door test set is named for the `packages/` directory it runs, so the plural is the faithful name. Hard-cut: `makers test package` now errors with `unknown set` rather than aliasing. Updates every reference site: Makefile.toml (default, case matcher, dispatch, descriptions, comment block), help.sh, docs/testing.md, README.md, and the live-tests/CONTEXT.md glossary term (now records the retired singular under _Avoid_). ADR-0004 gets a one-line supersession footer; its historical text is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat/ironwood_nu_6_3
…o_blockchainsource # Conflicts: # live-tests/e2e/tests/devtool.rs # live-tests/e2e/tests/test_vectors.rs # packages/zaino-state/src/backends.rs # packages/zaino-state/src/backends/state.rs # packages/zaino-state/src/chain_index.rs # packages/zaino-state/src/chain_index/source/validator_connector.rs # packages/zaino-state/src/indexer/node_backed_indexer.rs
Deduplicate zaino-common and delete its dead public API; net -247 lines of Rust, behavior preserved. logging.rs (386 -> 187 lines): - Collapse the six init_*/try_init_* bodies into one private try_install(LogConfig); init() panics if a global subscriber is already set, try_init() ignores that case. - Delete unused DisplayHash/DisplayHexStr and the unreachable programmatic config surface (LogConfig builder methods, show_span_events, the *_with_config entry points); LogConfig and LogFormat are now private. - The ZAINOLOG_FORMAT/ZAINOLOG_COLOR/RUST_LOG interface and all three output formats are unchanged. config/network.rs (371 -> 308 lines): - New activation_heights_mirror! macro records the NetworkUpgrade variant <-> ActivationHeights field correspondence once and expands to the two mirror From impls plus from_zebra_pairs (all-None init + upgrade-list walk). Exhaustive destructures and match keep full compile-time drift detection; a future network upgrade lands as a single (Variant, field) pair. - Delete Network::zaino_regtest_heights (no callers workspace-wide). CHANGELOG: breaking removals and internal refactors recorded under Unreleased; version bump deferred to release. Verified: cargo check --workspace, cargo clippy --all-targets, cargo fmt, cargo nextest run -p zaino-common (19/19 passed), doctests (8/8 passed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Compiler-verified sweep: each dependency in zaino-common's manifest was deleted one at a time and the crate re-checked with `cargo check -p zaino-common --all-targets`; a passing check kept the deletion, a failing one restored the dependency. Dropped (zero references, check passes without them): - thiserror — never used by this crate - nu-ansi-term — never used directly; tracing-tree pulls its own copy transitively - hex — last consumers were DisplayHash/DisplayHexStr, removed in the preceding DRY commit Kept (check fails without them): zebra-chain, serde, tracing, tracing-subscriber, tracing-tree, time. The root [workspace.dependencies] nu-ansi-term entry is now unused by every member but left in place; removing it is a separate root-manifest decision. Verified: cargo check --workspace --all-targets clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
zainod 0.5.0 panicked at startup when gRPC TLS was enabled: the zebra bump added a second rustls provider path (zebra-rpc -> zebra-node-services/rpc-client -> reqwest/rustls-tls -> ring) alongside zaino's own reqwest (aws-lc-rs), and rustls 0.23 refuses to auto-select a provider when both features are enabled. Reproduced and confirmed by a two-arm experiment recorded on the issue. Fixes #1360. - workspace reqwest: "rustls" -> "rustls-no-provider" (drops aws-lc-rs from the graph entirely) - zaino-serve: tonic gains "tls-ring" so zaino chooses ring itself - zaino-common: new crypto::ensure_default_crypto_provider(), a guarded first-install-wins ring install that respects an embedder's provider; this is the load-bearing fix (Arm B: dual-provider graph passes with it), the feature pinning is defense-in-depth and build hygiene - called at the two boundaries that build rustls configs: the outbound reqwest client factory in zaino-fetch (new build_rpc_client, DRYing three hand-rolled ClientBuilder chains) and the gRPC TLS acceptor in zaino-serve - regression test: TLS-enabled spawn + real handshake against a committed test-CA/leaf fixture (CI previously ran plaintext only); fails with the exact reported panic under the pre-fix feature graph Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The two functions zaino-common calls — CryptoProvider::install_default and get_default — have no-std implementations in rustls 0.23 (the process default falls back from std::sync::OnceLock to once_cell::race::OnceBox), so "std" is not required by our usage. It is also enabled in any full build regardless, because tokio-rustls hard-enables rustls/std. Minimum-necessary-scope: declare only "ring". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
continue-on-error makes the run succeed but still shows the failed job as a red X in the PR checks list, which reads as a blocking failure. Move the advisory decision into the step: on non-rc/non-stable contexts a failure emits a ::warning annotation and exits 0; rc/** and stable keep the hard failure. Also generalize the failure epilogue: same-name version divergence from crates.io (new cross-crate API or features, resolved by release-time bumps) is as common a cause as patch overrides. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ossary Record the decision reversing zaino's rustls provider from ring to aws-lc-rs, per Daira Emma's post-quantum argument: - aws-lc-rs is the preferred (first-install-wins, not mandated) provider - rustls prefer-post-quantum enabled: X25519MLKEM768 leads on the client leg; rustls servers follow client group preference, so inbound hybrid uptake is client-driven - classical key exchange accepted but deprecating, gated on wallet stacks (zingolib is ring-pinned; ZODL rides mobile platform TLS) - ring tolerated in Cargo.lock via the zebra-node-services reqwest path, fenced by an exact-snapshot CI lint, until the upstream zebra fix References: - https://crates.io/crates/rustls-post-quantum - https://www.reddit.com/r/rust/comments/1de13y6/comment/l89pbmc/ CONTEXT.md begins the project glossary: Preferred CryptoProvider, Hybrid key exchange, Classical key exchange. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Switch zaino's rustls provider from ring to aws-lc-rs and enable rustls's prefer-post-quantum feature, so the X25519MLKEM768 hybrid key exchange leads zaino's outbound handshakes (rustls servers follow the client's group preference, so inbound hybrid uptake is client-driven). Installation stays first-install-wins: an embedder that installs a provider before zaino keeps its choice. Full rationale in ADR-0006. - zaino-common: rustls features ring → aws_lc_rs + prefer-post-quantum; ensure_default_crypto_provider installs aws-lc-rs - zaino-serve: tonic tls-ring → tls-aws-lc - ring remains in Cargo.lock solely via zebra-rpc → zebra-node-services rpc-client → reqwest 0.12 "rustls-tls" (reqwest 0.12 offers no aws-lc alternative); it is compiled but dormant — reqwest consults the process-default provider first. Removal tracks an upstream zebra fix. - new workbench guard check-crypto-provider (makers lint-crypto-provider) pins the ring-selecting feature edges to exactly that tolerated path, failing loud on new edges and on ring's disappearance alike - classical key exchange (X25519, SECP256R1, SECP384R1) is deprecated: still accepted for wallet compatibility, slated for refusal once major wallet TLS stacks negotiate hybrids References: - https://crates.io/crates/rustls-post-quantum - https://www.reddit.com/r/rust/comments/1de13y6/comment/l89pbmc/ Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the matches! closure in check-crypto-provider's tree-prefix trimming with the char-array pattern clippy suggests. The lint escaped local verification because a chained `fmt --check && clippy` short- circuited on the fmt diff, so clippy never ran. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: install rustls CryptoProvider explicitly and pin provider to aws-lc-rs
…truth The Validator's configured activation heights are now the only source of truth for every component, enforced at compile time on both sides of the zcash_local_net seam (zaino#1076; infrastructure ADR 0003 and PR #278; the inbound spec is committed as zainod-heights-from-validator-spec.md). On the indexer side, zaino_common::Network is a payload-free kind, so a configuration value cannot carry heights and a pre-handshake height read does not typecheck. Both backends construct the runtime zebra_chain::parameters::Network in exactly one place: the spawn handshake, which uses zebra's compiled parameters for the public networks and adopts the validator's reported schedule from getblockchaininfo.upgrades for regtest. An upgrade absent from the validator's map is never-activated, nothing is backfilled from defaults, and a failed or unparseable handshake aborts startup with an error naming the validator endpoint. Every downstream consumer — the chain-index config, the connectors, the finalised state, and the subscribers via ServiceMetadata — receives that runtime network and can no longer manufacture its own; the conversions that let a config value impersonate chain truth (to_zebra_network and the From impls into zebra's type) are deleted, along with the dead accessors that invited a bypass. Test fixtures that are their own chain construct runtime networks explicitly through ActivationHeights::to_regtest_network. On the wallet side, the zcash_local_net pin moves to 78511f7, where the devtool client's network is a WalletNetwork whose regtest variant only WalletNetwork::from_validator can construct. The e2e client builder becomes build_clients(port, &validator) and derives the wallet schedule from the running validator, so: *wallet/validator height drift is unrepresentable* and a fixture's heights are typed exactly once, in the zebrad launch config. The harness no longer mirrors fixture heights into zainod: every custom-heights launch doubles as a regression test of the adoption path. The canonical launch set moves to zaino-testutils as ZEBRAD_DEFAULT_ACTIVATION_HEIGHTS, which is validator-launch vocabulary rather than anyone's schedule. The uniqueness regressions live in clientless/tests/validator_heights.rs: a kind-only-configured zainod must sync a NU6.3-at-6 schedule its configuration never saw, and a golden test pins the upgrades map a live zebrad reports. Three unit tests beside activation_heights_from_upgrades pin the mapping itself. The production workspace, all live-test crates, and the unit suites compile and pass clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…xture The ironwood_activation suite exercises the wallet-observable predicates across the Orchard-to-Ironwood boundary on ORCHARD_THEN_IRONWOOD_ACTIVATION_HEIGHTS, the hermetic replay of the public testnet's NU6.3 activation at height 4,134,000. The wallets derive their schedule from the running validator and zainod adopts the same schedule over getblockchaininfo, so the fixture heights are typed exactly once, in the zebrad launch config. unified_receipt_lands_in_orchard_before_boundary pins Orchard-era receipt semantics. orchard_note_spends_to_ironwood_across_boundary exercises the ZIP 318 migration shape: an Orchard note minted before the boundary, spent after activation to a freshly generated unified address, with the receipt asserted in the Ironwood pool. It also pins that the send actually exits the Orchard pool, which is sound under the cross-address restriction because change can return only to the spent note's own receiver. Both cells register on the fetch and state backends. The public testnet can never host the migration cell: its pre-NU6.3 epoch is closed and no pre-activation Orchard TAZ is obtainable, so this fixture is the only controlled venue. Renames apply the pool-naming convention (NU6_3_ACTIVE_* becomes IRONWOOD_ONLY_*: pool names pair with pool names, and NU6.3 names only the upgrade itself). CONTEXT.md gains the supporting glossary entries — testnet versus regtest nets, the era-naming convention, and the cross-address restriction with its normative constraint quoted verbatim. docs/notes/ironwood-activation-plan.md records the design decisions and their sources. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(zaino-fetch): deserialize verbosity-2 getblock transaction objects
refactor(state): apply ironwood-migration polish from review of #1379
The new rev (85502cd0) picks up the twelve commits on the bump_to_NU6.3 branch since the previous pin, including deterministic listener-port allocation with an Indexer-convergence barrier, the generic Wallet abstraction, and the front proxies published as the canonical endpoints. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DRY zaino-common
The interesting resolutions all follow from dev's unification of
FetchService/StateService into NodeBackedIndexerService meeting this
branch's rule that the validator is the sole source of activation-height
truth (zaino#1076):
The network-adoption logic that lived in the deleted backends module
moves into ValidatorConnector::{spawn_fetch,spawn_state}, which now
return the adopted runtime network alongside the connector, and
activation_heights_from_upgrades moves (with its tests) into
validator_connector.rs. source::State carries the adopted
zebra_chain::parameters::Network together with dev's new
chain_tip_change and sync_task_handle fields.
The v1.3.0 migration keeps dev's PoolActivationHeights::resolve shape,
resolved against the runtime network the config now carries directly.
Test-only construction sites replace the removed payload-carrying
Network::Regtest kind with ActivationHeights::to_regtest_network().
The generic live-test suites (ironwood_activation, validator_heights)
move from FetchService/StateService type parameters to the Rpc/Direct
ValidatorConnectionMarker types, matching dev's ported devtool suite.
dev's dry_zaino_common refactor (#1371) touched the payload-carrying Network type this branch deletes; the resolution keeps the branch's payload-free network kind in zaino-common.
The dev merge took the incoming Cargo.lock, which predates this branch keeping rustls in zaino-common (ADR-0006); cargo regenerates the entry on the first build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The NetworkUpgrade-variant ↔ ActivationHeights-field correspondence is recorded exactly once, in zaino-common's activation_heights_mirror! macro, but activation_heights_from_upgrades restated it as a hand-written thirteen-arm match and both it and its tests restated the all-None schedule as field-by-field literals. The macro now generates the two missing derived items — the NEVER_ACTIVATED schedule and the per-upgrade slot_mut accessor — and the adoption function collapses onto them. The generated match stays exhaustive, so a new zebra upgrade variant still fails the build until its pair is added to the mirror. Also remove the dead ChainIndexConfig::new: it had no callers and was the one constructor shape that invited supplying a network from somewhere other than validator adoption; from_backend_config is now the sole named production constructor (zaino#1076). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Public-network activation heights come only from checked-in, ecosystem-shared consensus code; regtest parameters are configured on the validator at scenario launch and every other component adopts them from it. adopt_network previously enforced the regtest half but took the compiled Mainnet/Testnet parameters on faith: a validator running a *configured* testnet (zebra supports custom testnet activation heights) would silently drift from the index — the exact bug class this branch exists to kill, on a different network kind. adopt_network now fetches getblockchaininfo on every network kind and, on Mainnet and Testnet, verifies each reported (upgrade, height) pair against the compiled parameters before trusting them, failing loud on the first disagreement. Only reported entries are checked, not report completeness: the upgrades map is branch-ID-keyed, so unconfigured upgrades are simply absent and an older validator may not know the newest ones. Also document two acceptance decisions the spec made but the code did not state: adoption happens exactly once at spawn (a validator restarted mid-session with a different schedule is out of scope), and before_overwinter is always None when adopted (BeforeOverwinter has no consensus branch ID, so it can never appear in the report; zebra's new_regtest supplies its handling). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The public shared-consensus test network and a hermetic regtest chain are categorically different things, and the bare word "testnet" has named both. Where the intention is the public network, the canonical vocabulary is now: "The Public Testnet" in prose, `the_pub_testnet` in identifiers, and `PubTestnet` in types. The CONTEXT.md glossary entry records the rule. The config kind renames to `Network::PubTestnet`. Its canonical config spelling becomes `"PubTestnet"`, with `#[serde(alias = "Testnet")]` keeping existing config files parsing; a zainod config test pins the legacy spelling. The Public-Testnet chain-cache static renames to ZEBRAD_THE_PUB_TESTNET_CACHE_DIR, and the boundary-walk suite renames to the_pub_testnet_ironwood_boundary (the Makefile ironwood filter follows). References to zebra's own types and config format (parameters::Network::Testnet, NetworkType::Testnet, zebrad.toml) are foreign vocabulary and keep their spelling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ChainWork::to_u256 takes self by value (the type is Copy, and clippy's wrong_self_convention expects to_* methods on Copy types to consume self), and the address-deltas test fixture uses i.is_multiple_of(2) in place of the manual modulo test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat!: enforce the Validator as the sole source of activation-height truth
An audit of every zebra* and zcash* dependency edge (cargo machete, the compiler's unused_crate_dependencies lint, and inspection of each remaining single-reference hit) found exactly one dead edge: zainod declared zebra-chain but never referenced it. Remove it. Every other declared edge is genuinely used; zebra-chain remains the type backbone of the workspace, with some 350 references in zaino-state alone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Advance ZEBRA_VERSION in .env.testing-artifacts from 6.0.0-rc.0 to the final 6.0.0 release. Zebrad 6.0.0 depends on zebra-chain ^11.1.0, the same crate generation the workspace now pins, so the zebrad binary the live tests run against and the zebra libraries zaino links are once again from a single release. The makers check-matching-zebras guard passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A workspace-wide unused-dependency audit (the compiler's unused_crate_dependencies lint analyzed per target, cross-checked with cargo machete and a text search of every candidate's package, including feature-gated code) found twelve dead edges. Remove them: prost, bs58, nonempty, derive_more, and once_cell from zaino-state; tracing-subscriber from zainod; and tracing, corez, serde_json, tempfile, tower, and zip32 from clientless. The bs58, nonempty, and zip32 entries in [workspace.dependencies] lost their last inheritors and are removed with them. One edge that looks dead is kept deliberately: clientless does not import zainod in any test source, but its transparent_address_history_experimental feature forwards to zainod/transparent_address_history_experimental, and cargo rejects a feature forward to a non-dependency. A comment in the manifest now records that. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The same audit that removed the dead edges found three dependencies that are real but used exclusively under #[cfg(test)]: primitive-types in zaino-state (the legacy_chainwork_reference round-trip tests), tempfile in zainod (the config tests), and tonic in zaino-testutils (the cfg(test)-gated build_client helper). Move each from [dependencies] to [dev-dependencies] so shipped builds stop linking them. The lockfile is unchanged: dependency kind does not affect resolution. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mary `makers test all` previously ran the packages set outside the summary runner, so the closing table covered only the two live partitions. The `all` branch now delegates to `live-summary --all`, which runs `makers container-test` first and prints its tallies as a `packages:` row above `clientless:`, `e2e:`, and `TOTAL:`, under a "test summary" header. `makers test live` is unchanged apart from the new column. The old contract is preserved: every set runs even when an earlier one fails, and the runner exits non-zero if any set did. Each row also gains a wall-clock time column, parsed from the nextest summary line's `[ 510.718s]` stamp. Durations are held as integer milliseconds in a u64 — whole seconds and a right-padded three-digit fraction parsed digit-by-digit, no floating point — and the TOTAL row sums them, which reads as true wall time because the suites run sequentially. Six new unit tests cover the parser (padding, short and absent fractions, and propagation through parse_summary), and the pre-existing `filter(..).last()` on a double-ended iterator is tightened to `rfind(..)` per clippy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The test-environment image rebuild (first since the ZEBRA_VERSION bump changed the image tag) failed because Debian trixie point updates replaced two pinned package versions, and the archive does not keep superseded versions: protobuf-compiler 3.21.12-11 -> 3.21.12-11+deb13u1 (all three build stages) and curl 8.14.1-2+deb13u3 -> 8.14.1-2+deb13u4 (both stages). Every other pin in the Containerfile still matches the archive; verified against qa.debian.org/madison and a live trixie-slim container. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ut parsing Replace the duration_millis parser (which scraped nextest's human-readable summary line) with Instant::now()/elapsed() around each run_partition call. The nextest display format is not a stable contract; the runner already owns the process lifecycle so it can time it directly. This also captures build time, which the nextest stamp did not include.
PRs that target rc/** or stable carry unbumped dev code by design — version bumps happen on the RC branch after merge. The blocking mode was failing these PRs for an expected, non-actionable condition. Only direct pushes to rc/** or stable are blocking now; PRs targeting them are advisory.
…for-prs fix(ci): publish dry-run advisory for PRs targeting rc/stable
nachog00
enabled auto-merge
July 13, 2026 18:24
zancas
approved these changes
Jul 13, 2026
zancas
left a comment
Member
There was a problem hiding this comment.
Already reviewed for merge into dev.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bring the
rc/0.6.0branch up to currentdevahead of the0.6.0-rc.3tag.The previous RC tags (
rc.1,rc.2) were cut from a divergentrelease_alphabranch. This PR starts fresh:rc/0.6.0was recreated from the0.6.0-rc.1tag (which is a clean ancestor ofdev), and this PR fast-forwards it todevHEAD.Includes all work since
rc.1:makers testsetpackage->packages#1355)Blocked on #1394 (
bump_deps) merging into dev first — that PR advances zebra deps to v6.0.0 stable and drops thezcash_*pre-release pins.Once merged, version bump +
0.6.0-rc.3tag follow on this branch.