The Pipeline: Scan, Open, Witness, Fill, Broadcast
The Skyhook pipeline is the set of five programs that turn a shielded note into a verified payment: scan finds the notes a key owns, open derives a note’s full contents, witness proves the note’s membership in the commitment tree, fill builds and proves the spending transaction, and broadcast submits it and checks the result. This page follows a real execution, a 50 TAZ transfer on the Zcash test network with transaction ID 3fff0557, mined at height 4482776 and carrying the memo “Happy to help!”.
Scan
Scanning trial-decrypts recent compact blocks with a viewing key and lists the notes it owns, with their value, diversifier and rho, and the transaction IDs and heights where they appeared. It is entirely read-only: nothing is signed or moved. On a fast connection a full Ironwood sync takes under a minute. In the example, scanning turned up a 512 TAZ note received weeks earlier, which became the candidate to fund the transfer.
Open
Opening fetches the complete funding transaction, trial-decrypts the relevant action and derives the note’s full opening: its value, diversifier, g_d, pk_d, rho, psi, candidate values of rcm, cmx, the nullifier and the memo. For notes at non-default diversifiers, such as change outputs and fan-outs, the opener derives pk_d from the key itself, since the caller can’t know it in advance.
The nullifier is then checked against both the chain and the mempool. If the note has already been spent the attempt ends and a new candidate is sought; otherwise the pipeline continues. The example note was unspent on both checks.
Witness
Witnessing synchronizes the note commitment tree and produces the Merkle path from the note’s commitment to a recent anchor root. The path must refold cleanly to the root before it is accepted, or the pipeline stops. The anchor also has to be recent enough to remain valid at the claim height, many blocks later; a witness against a stale tip is useless as a proof. The example’s witness was fresh by construction.
Fill
Filling builds the spend from the funding note: a payment output to the recipient, a change output back to the sender, the fee, and an expiry set to the current tip plus a margin. The payment output carries the memo (in the example, the fourteen characters of “Happy to help!”), while change always carries an empty memo, since memos are addressed to recipients. Proving takes a fraction of a second on many-core hardware with a cached proving key.
Broadcast and verify
The transaction is submitted through lightwalletd, and three independent checks follow:
- the mined transaction is fetched back and compared byte for byte with the one that was built (in the example, all 9,166 bytes matched);
- the payment output is decrypted with the outgoing viewing key, and its value and memo are read back (5,000,000,000 zats and the expected text);
- confirmations accumulate over subsequent blocks.
The transfer counts as complete only after all three. The checks take minutes, while a missed failure could lose funds.
Architecture
Each stage is a separate binary, and the stages communicate through JSON. The demo interface, the liquidity bot and the test suite each drive the same code through their own entry point, which keeps caller-specific logic separate and the cryptography shared. The same portable core is the basis for the mobile bindings planned in Milestone 4.