Add client support#270
Merged
Merged
Conversation
Clients are the third kind of process zcash_local_net manages, alongside validators and indexers. Unlike both, a client binary is not a daemon: each wallet operation is a run-to-completion subprocess invocation against a persistent wallet directory owned by the client struct. This lets zaino's wallet integration tests replace their zingolib client stack (#269). - `client::Client` trait: launch (restore from mnemonic + birthday against a running indexer), sync, send(addr, zats) -> txid, shield -> txid, balance -> WalletBalance, default_address, rescan. All operations run to completion, so strictly sequential act -> mine -> wait -> assert test flows need no extra synchronization. - `client::ClientConfig::setup_indexer_connection` mirrors `IndexerConfig::setup_validator_connection`; launch order is validator -> indexer -> client. - `client::zcash_devtool::ZcashDevtool` drives the zcash-devtool CLI (built with `--features regtest_support`, resolved via TEST_BINARIES_DIR/PATH). `ZcashDevtoolConfig::faucet()` (abandon-art seed) and `::recipient()` (HOSPITAL_MUSEUM seed) provide the standard test wallets; `init` pipes the mnemonic on stdin, `send`/`balance` pass `--min-confirmations` (default 1 — devtool's own 3-trusted/10-untrusted default policy makes nothing rescan from scratch, and shielding self-sent transparent funds conserves totals exactly (the faucet is the miner, so fees return via coinbase). Requires zcash-devtool with non-interactive init and --min-confirmations support (paired changes in the zcash-devtool branch), and NU6.2-capable zebrad (5.1.0) / zainod (0.4.0) test binaries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wires the Client trait to the surface devtool added in 105a4af ("Add
machine-readable CLI surface for the zaino wallet-test client"). Until
now only the unified address was reachable and balance was scraped
from human-readable text; this unblocks the transparent/sapling half
of zaino's wallet matrix and removes the fragile parser.
- `client::AddressReceiver` (Unified | Transparent | Sapling | Orchard)
and `Client::address(receiver) -> String`. A dedicated enum, not
`zcash_protocol::PoolType` (which is Transparent | Shielded(..) and
has no Unified — the wrong shape here). `default_address()` becomes
a default trait method forwarding to `address(Unified)`, so existing
callers are unchanged.
- `ZcashDevtool::address` drives `list-addresses --receiver <pool>`
(reads the local wallet db, no server args) and parses the
`Receiver(<pool>): <addr>` lines; unified still parses the
`Default Address:` line.
- `ZcashDevtool::balance` switches to `balance --json`, whose keys map
field-for-field to `WalletBalance`. Deletes the text-scrape parser
that had to reverse-scan past a `{:#?}` WalletSummary debug dump
(`parse_balance_output` / `parse_zec_amount` and the ZEC-string
fixture) — sturdier across zcash_client_* upgrades. Parsed via
`serde_json::Value` rather than a derived `Deserialize` on
`WalletBalance`, keeping serde out of the public API
(cargo-check-external-types).
- Unit tests pin every new parser against recorded shapes
(`balance_json_parses`, `balance_json_rejects_bad_shapes`,
`receiver_lines_parse`). The faucet address integration test now
asserts all four receivers against the zingo_test_vectors constants:
unified == REG_O_ADDR_FROM_ABANDONART, transparent ==
REG_T_ADDR_FROM_ABANDONART, sapling == REG_Z_ADDR_FROM_ABANDONART,
orchard decodes as a regtest UA — proving the abandon-art wallet
owns the addresses the harness pays.
Requires zcash-devtool at branch add_regtest commit 105a4af or later.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wires the Client trait to the get-info surface the devtool added in
d820388, the do_info analogue used as a "can the wallet reach its
server" smoke check. Completes the machine-readable CLI consumption
begun with address()/balance --json.
- client::Client::get_info -> client::GetInfo { server_uri, chain_name,
chain_tip_height }. chain_tip_height is the server/node tip (a u64,
matching the wire LightdInfo.block_height), never the wallet's
locally-synced height. The field set is a frozen contract with the
binary; parsed via serde_json::Value to keep serde out of the public
API (cargo-check-external-types).
- ZcashDevtool::launch now writes the regtest --activation-heights TOML
from the configured heights and passes it to init. The pinned devtool
(d820388, via b1f9e6c) requires --activation-heights for `-n regtest`
(heights are configured at init, not baked in); without it nothing
launches. Schema mirrors devtool data.rs::ActivationHeights
(deny_unknown_fields, overwinter..nu6_2, no nu7).
- Unit test pins the parser against a real get-info line captured from
the d820388 binary: {"chain_name":"test","chain_tip_height":3,
"server_uri":"http://127.0.0.1:42739"}. Reality corrected two guesses
- zaino reports regtest as chain_name "test" (not "regtest"), and
server_uri has no trailing slash.
- connect_to_node_get_info integration test exercises get_info against
the live binary + indexer (asserts shape populated, server-tip
semantics via a poll).
- faucet_shields_transparent_funds: replace the brittle "exactly 2
rewards" assertions with a reward count derived from the snapshots'
own chain_tip_height delta. The faucet is the miner, so snapshot
capture heights race run-to-run; the delta captures the real
invariant (fees net out via coinbase) robustly.
Requires zcash-devtool at branch add_regtest commit d820388 or later.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The single source of truth (zcash_local_net::validator) was already on NU6.2 — regtest_test_activation_heights sets nu6_2=Some(5) and REGTEST_FIXTURE_HEIGHTS_CLI_STRING is "all=1,nu5=2,nu6=2,nu6_1=5,nu6_2=5, nu7=off" — but regtest-launcher trailed it (the stale "TODO: update regtest-launcher to nu6.2" marked the gap). The parser rejected the default string with "Unknown activation key 'nu6_2'", which panicked cli::tests::cli_default_matches_fixture_helper and made the binary exit at Cli::parse() before startup — also failing the e2e test. Close all three NU6.2 drop sites in the launcher: - cli.rs: add Nu6_2 to UpgradeKey and UPGRADE_ORDER (between Nu6_1 and Nu7, the correct cascade slot), recognise nu6_2|nu6.2|nu62 in parse_key, handle it in set_field, and add it to the "Valid keys" error text and doc comment. - main.rs: add .set_nu6_2(...) to the ConfiguredActivationHeights -> ActivationHeights conversion (without this the NU6.2 height was silently dropped even once parsing worked). - cli.rs test: mirror the field in cli_default_matches_fixture_helper. - README.md: refresh the example, Keys list, and stale default string. Also drop the mining bootstrap target_height from 101 to 5. Profiling showed getblocktemplate (~280ms/block, flat across the NU6.2 boundary — not a regression) dominated the 101-block bootstrap at ~30-60s, overrunning the e2e test's 45s deadline. Mining to height 5 still crosses every upgrade (nu6_1 and nu6_2 both activate at 5) and brings first-mine well inside the deadline; the e2e snapshot is unaffected (its normalizer rewrites mined heights to <HEIGHT>). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Factor three repeated patterns out of the integration tests: - regtest_heights_nu6_1_at(h): replaces three copies of the 11-line ActivationHeights::builder() block; encodes the "nu6_1 and nu6_2 co-activate" invariant in one place. - READINESS_RPCS + readiness_rpc_failures(): collapses the two duplicated four-endpoint RPC failure-collection loops; the endpoint list is now a single source of truth. - init_tracing(): unifies all 36 tracing_subscriber::fmt() init sites and standardizes on the panic-safe try_init() (was a mix of .init()/.try_init()). No behavior change; pure refactor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Planning doc for wiring the Client trait + ZcashDevtool impl to the machine-readable surface that zcash-devtool's add_regtest branch shipped (per-pool `wallet list-addresses --receiver`, `--json` balance/list-tx), so zaino's DevtoolClients adapter can stop panicking on per-pool addresses. Design only — no code change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zebrad::launch pre-mines a genesis-priming block, so the chain is deterministically at height 1 after launch_orchard_net (verified 25/25). faucet_sends_recipient_receives_and_rescans then mines 3 more (-> height 4) but asserted the height-3 balance (BLOCK_1 + 2*POST_NU6 = 1,862,500,000). The test only passed when sync_to_height(faucet, 3) happened to sample the wallet while the indexer still lagged at height 3; when the wallet reached the true tip 4 first it saw an extra coinbase (BLOCK_1 + 3*POST_NU6 = 2,481,250,000) and failed. That sampling race is why it flaked pass/fail by load (fast/light load failed, slow/loaded passed). Sync to the validator's actual tip and derive the expected balance from it, removing both the off-by-one and the race. The downstream sync_to_height targets are unaffected: they are `>=` waits the (off-by-one-higher) real heights already satisfy, and their asserts are on transferred amounts, not the tip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Orchard coinbase mining dominated these tests (~84% of wall-clock, ~4.5-9.5s per block of Halo2 coinbase proving, measured). Mine only the orchard blocks each send/confirm step actually needs, and derive every sync target from the validator's real tip so the smaller counts stay correct (also removes the height-sampling race from faucet_shields). ~-23s / -26s per test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dorianvp
approved these changes
Jun 30, 2026
dorianvp
left a comment
Member
There was a problem hiding this comment.
utACK. I think those md files should not go to dev, but we can remove them later.
zancas
added a commit
that referenced
this pull request
Jul 2, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Merged
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.
Add client support to zcash_local_net so that it can support running zcash_devtool