ZEC: improve reorg recovery, input selection and broadcast safety
Summary
Improve ZEC reorg recovery and transaction reservation handling, reduce avoidable input-selection differences between validators, and require signed transactions to be persisted successfully before Bifrost broadcasts them.
The latest extension is limited to two Bifrost production files and three test files. The complete MR also includes the earlier ZEC build/test updates and Radix simulation cleanup.
Changes
Reorg recovery and transaction expiry
- Walk backwards to the common ancestor within the configured maximum reorg rescan window.
- Reuse fetched block data when updating canonical block hashes.
- Use the configured chain identity for errata and preserve the distinction between confirmed, pending and unknown transaction status. Transient RPC failures must not become evidence for errata.
- Set transaction expiry to the local ZEC height plus 35 blocks.
- Align pending, spent and self-change cache pruning with that expiry horizon, while retaining block metadata according to the configured reorg window.
- Simplify reservation cleanup around the canonical
pending:<cacheHash>key.
Confirmed input selection
- Select confirmed live RPC inputs with valid heights, positive values and valid scripts.
- Normalize transaction IDs and scripts, deduplicate identical records, and reject conflicting metadata.
- Order inputs consistently by height, transaction ID and output index.
- For ordinary payments, select only the ordered prefix needed to cover the payment and existing gas allowance. Consolidation retains its configured input-count target.
- Check local pending and spent reservations after selection. If a selected input is unavailable locally, defer the attempt instead of substituting another input.
- Verify the provenance of small vault-change outputs so legitimate vault dust remains spendable without admitting arbitrary external dust.
- Respect global and ZEC-specific signing halts before attempting consolidation.
Persist before broadcast
- Persist the ZEC checkpoint together with signed bytes and observation data.
- Stop before broadcasting if that storage operation fails.
- Preserve the existing retry path that reuses stored signed bytes, including after a database restart.
Supporting changes
- Update the ZEC build helper, regtest address construction, Sapling/Orchard fixtures and NU6.3 branch-ID assertion.
- Remove Radix/XRD from simulation clients, startup, funding and routes, and derive simulation coverage from enabled chains. Production Radix support remains unchanged.
Rollout
The new input-selection policy activates at network version 1.133.0. Older network versions retain the existing selection policy. The gates include TODO comments identifying their eventual removal.
This assumes the upgraded signing policy is deployed before activation. Different builds already advertising the active version are not coordinated by the version gate alone.
Remaining limitations
Input selection still depends on live RPC state. Validators can disagree when necessary inputs appear or disappear between reads, or when their chain views differ. Waiting for confirmed change can also reduce throughput.
The existing expiry/rescheduling overlap remains. Live expiry -> retirement -> reschedule coverage is still outstanding.
THORNode parity and MAYA-specific adaptations
This MR mirrors selected THORNode behaviors in MAYA’s dedicated Zcash client.
Mirrored from THORNode
- Bounded reorg recovery: walk backwards within
MaxReorgRescanBlocks, stop at the common ancestor, and associate errata with the configured chain. - Confirmed-input selection: mirror the companion THORNode change on
zly/zec-confirmed-inputs, commit4c6eee48458d:- Use confirmed live inputs, normalize identifiers and deduplicate records.
- Order candidates by creation height, transaction ID and output index.
- Select only enough inputs to cover an ordinary payment and its fee; consolidation retains its configured input-count target.
- Defer when selected inputs conflict with local state instead of substituting different inputs.
- Validate the provenance of small vault-change outputs so legitimate dust remains spendable.
- Consolidation signing halts: apply the same protection against consolidation while signing is halted, using MAYA’s existing halt semantics.
- Regression coverage: mirror the corresponding input-ordering, differing-candidate-view, spent-input and vault-dust scenarios.
The confirmed-input reference is a separate THORNode follow-up, not the complete deterministic-expiry port from THORNode !5058.
MAYA-specific adaptations and hardening
- Integrate selection with MAYA’s pending/spent reservation storage and activate the new policy at network version
1.133.0. - Preserve MAYA’s 35-block expiry policy and existing Rust builder support for transparent and shielded recipient outputs.
- Keep inconclusive reorg RPC results from triggering errata.
- Strengthen signed-transaction persistence: save the successful ZEC checkpoint together with signed bytes and observation data, and prevent broadcast if that write fails. This extends the shared-signer persistence pattern; it is additional MAYA hardening rather than a direct copy of the THORNode fix.
- Add persistence-failure and database-restart tests proving that retries reuse the saved checkpoint and signed payload.
Expiry scope
This MR sets transaction expiry and aligns cache pruning with its lifetime. Historical shared signing heights, confirmation-aware terminal expiry handling, consolidation journaling and the additional Rust lifecycle APIs are implemented separately in !856 (merged).
Summary by CodeRabbit
-
Bug Fixes
- Improved reorg handling: reconfirmation now scans from the reorg height, emits errata with correct chain ID, and refreshes diverged blocks.
- Added explicit nil-signature error handling during signing.
-
Improvements
- Consolidated pruning paths and optimized cleanup logic.
- Transactions now tracked/queried by ID strings.
- Partial transactions gain a computed expiry height.
- Reservation logging/broadcast flow no longer includes transaction IDs.
-
Tests
- Added/updated tests for reorg reconfirmation and expiry-height behavior.