Skip to content

test framework: cover the zallet#644 mining-pool payout gather scenario#176

Open
pacu wants to merge 1 commit into
dw/sendfromaccountfrom
test-644-fragmented-change-gather
Open

test framework: cover the zallet#644 mining-pool payout gather scenario#176
pacu wants to merge 1 commit into
dw/sendfromaccountfrom
test-644-fragmented-change-gather

Conversation

@pacu

@pacu pacu commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Closes #175. (The underlying wallet issue is zcash/zallet#644, resolved by zcash/zallet#531 — this scenario locks the fix in.)

Targets dw/sendfromaccount (the integration-test side of zcash/zallet#531) — meant to merge into that branch so the scenario ships with the z_sendfromaccount coverage.

What this adds

One scenario in wallet_z_send_scenarios.py, scenario_mining_pool_payout_gathers_fragmented_funds, reproducing zcash/zallet#644 end to end on a fresh account and showing that the any_transparent fund source resolves it:

  1. The miner's pipeline: coinbase → z_shieldcoinbase → de-shield 2.0 + 2.0 onto the pool's own payout t-addrs.
  2. The wallet fragments its own funds: a t→t payout of 0.5 from one address strands ~1.5 of change on a wallet-chosen internal change address — asserted to be none of the addresses the operator picked, and asserted still owned by the account.
  3. The reported failure mode as a precondition: a 3-miner round totaling 3.0 exceeds every single address (2.0 / ~1.5, read on-chain) while the account's reported transparent balance covers it. Naming a single address fails with insufficient funds; any_transparent under AllowFullyTransparent is refused (gathering forces ≥2 input addresses, which with transparent recipients requires NoPrivacy) and moves nothing.
  4. The fix: one z_sendfromaccount(pool, "any_transparent", …, "NoPrivacy") pays all three miners exactly; the transaction is asserted to gather ≥2 inputs from >1 distinct address including the internal change fragment, and to spend zero shielded notes while the account still holds Orchard — the exchange-compatibility guarantee transparent payouts need.

Also adds a transparent_input_addresses helper to util.py (resolves each transparent input's funding address from the node, mirroring transparent_output_addresses) and a qa/CHANGELOG.md entry.

Verification

Ran the full wallet_z_send_scenarios.py against the Z3 stack — zebrad + zainod test binaries, zallet + zallet-zaino built (release) from zcash/zallet branch dw/sendfromaccount:

wallet_z_send_scenarios.py | True   | 441 s

All pre-existing scenarios still pass with the new one wired in between reserve consolidation and the Sapling payout.

🤖 Generated with Claude Code

https://claude.ai/code/session_017WB1TU6tyLmMa1n4SQ9XgK

zcash/zallet#644 reports that a wallet created from scratch fragments its
transparent funds onto internal change addresses on every t->t send, after
which the account reports a spendable total that no single-address source
can pay in one transaction. The z_sendfromaccount `any_transparent` fund
source is the capability that closes this gap.

Add a scenario that reproduces the miner's pipeline end to end on a fresh
account: coinbase -> shield -> de-shield onto the pool's own payout
addresses, a t->t send whose change lands on a wallet-chosen internal
address (asserted), a payout round that exceeds every single address while
the account balance covers it (asserted), the two refusals (a single-address
source reports insufficient funds; any_transparent under
AllowFullyTransparent is an under-acknowledgement, since gathering links
addresses), and finally one any_transparent + NoPrivacy transaction paying
all three miners by gathering the change fragment -- with zero shielded
inputs while the account still holds Orchard notes, the guarantee
exchange-bound payouts need.

Adds a transparent_input_addresses helper to util.py that resolves each
transparent input's funding address from the node, mirroring
transparent_output_addresses.

Verified against the Z3 stack (zebrad + zainod + zallet built from
zcash/zallet branch dw/sendfromaccount): wallet_z_send_scenarios.py passes
in 441s with the new scenario included.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017WB1TU6tyLmMa1n4SQ9XgK
@pacu
pacu marked this pull request as ready for review July 17, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant