The Bidirectional MAST Engine
The bidirectional MAST engine is a proposed extension of Skyhook’s lock-scripts that inverts how escrow is released. Today a lock-script request escrows funds and later releases them by executing a committed program on ESMASTe. In the proposed direction, funds are escrowed against a committed set of constraints, and anyone who makes a Zcash payment satisfying them can claim the escrow. The claim is checked by pure verification, with no virtual machine involved, and the lock can hold several alternative sets of terms in a Merkle tree while revealing only the one that is exercised. The rest of the lifecycle, and every existing claim path, stays unchanged.
The inversion
The proposed direction keeps the skeleton of a lock-script swap and replaces its ending. Funds are escrowed against committed constraints rather than a committed program; a ZEC holder builds a transaction that satisfies them; and the claim path verifies that transaction before paying out, replacing execution with verification at every step.
A constraint check compares fields of the Zcash action with what the leaf expects: the recipient key pk_d, the diversified base g_d, and the value. Exact equality covers fixed-price arrangements, in which a lock names precise recipient keys and an exact amount. Bounded ranges could cover floor and ceiling prices in a later revision, at the cost of more audit surface; version one restricts itself to exact equality on the three fields, because every generalization multiplies the review burden while the core mechanism is still unproven in production.
The MAST structure
MAST stands for Merklized Alternative Script Tree, a term taken from the vocabulary of Bitcoin’s Taproot. The lock commits to the Merkle root of a set of acceptable leaves, each encoding one complete claims package: the field constraints, the payout policy and the authentication parameters.
A claim reveals exactly one leaf, together with its Merkle proof into the committed root, and verification checks the path before examining the leaf’s contents. The other leaves stay hidden permanently: an observer of a settled claim learns which terms were satisfied but nothing about the alternatives the lock’s author considered. Arrangements with several possible recipients can therefore share one lock without advertising the full list to competitors or to surveillance. A lock with a single set of constraints is simply a tree with one leaf, checked by the same code.
The six gates
A claim in the inverted direction passes six checks in a fixed order, each assuming the ones before it:
- Inclusion. The transaction’s Merkle path folds to a finalized anchor root through the standard computation.
- Leaf membership. The revealed leaf hashes through its proof to the request’s MAST root, using the established proof pattern.
- Field constraints. The decoded action fields match the leaf exactly, with no tolerance or partial credit.
- Realness binding. The recomputed note commitment equals the claimed one, which ties the claimed randomness to the fields so that action contents can’t be invented independently of the commitment.
- Authentication. The claim’s ticket is confirmed before any state changes, as specified in Ticket Authentication.
- Nullifier marking. The note is recorded in the shared spent set, so it can’t settle twice through either direction.
Opaque consumption
Throughout the inverted path, verification consumes committed bytes exactly as stored. Ciphertext regions enter the checks without being decrypted, since plaintext is never needed where committed bytes suffice, and signature components enter recovery without normalization or canonicalization, preserving honest creator output byte for byte. The recovery identifier is treated as pseudorandom output over the committed bytes and is only range-checked. Each transformation left out is one that can’t introduce a divergence between independent implementations; since honest output is already pseudorandom, canonicalizing it would add checks without adding security.
Shared nullifier set
The inverted direction marks the same nullifier set as the existing one. A note spent through a constraint claim can never later settle a program execution, and vice versa, so neither direction can pay twice for any note, however many locks refer to it. The two directions interact only through this shared state, not through any awareness of each other: each verification path stays independently auditable, with no logic about the other beyond the common marking operation.
Cost and privacy
Inverted claims always cost less than program executions, because no virtual machine runs. The six gates have bounded costs: two Merkle paths for inclusion and membership, one hash recomputation for the commitment, one signature recovery for the ticket, and two storage writes recording the nullifier and completion. Because there is no program whose complexity could vary the cost, budgeting is exact for every shape of claim.
The privacy gain is asymmetric. The fields a leaf constrains, the recipient’s address and the value, are revealed to the contract when a claim is made, as in today’s swaps until Milestone 3. The lock’s unexercised alternatives, however, stay hidden behind unrevealed branches, so the design reveals exactly the terms that were exercised and nothing more.
Relationship to the current engine
The proposal changes no existing path. Program-execution claims continue through the runner with identical semantics, and the inverted direction adds a parallel claim entry that reuses the codebase’s proven patterns: escrow, digest binding at accept time, inclusion proofs, commitment recomputation and nullifier discipline. Because both directions share these patterns, a single audit can cover both, which keeps the marginal cost of the extension small.