Skip to main content

The Bundle and the Builder

1. Why This Chapter Exists

src/builder.rs and src/bundle.rs are the most likely files for a contributor to touch when adding wallet-side behaviour. Together they own the randomness, the dummy-action padding, the typestate transitions, and the batch verification entry point. After this chapter the reader can predict in what order each randomiser is sampled and at which typestate each signature is attached.

2. Definitions

Definition 2.1 (Action)

An Action AA contains the public Action statement of Chapter 5 plus the encrypted ciphertext data (cvnet,nf,rk,cm,epk,Cenc,Cout,enableSpends,enableOutputs)(\mathsf{cv^{\mathsf{net}}}, \mathsf{nf}, \mathsf{rk}, \mathsf{cm}^\star, \mathsf{epk}, C^{\mathsf{enc}}, C^{\mathsf{out}}, \mathsf{enableSpends}, \mathsf{enableOutputs}).

Definition 2.2 (Bundle)

B=({Ai}i=1N,π,σbind,{σiauth}i=1N,value_balance),B = \big(\{A_i\}_{i=1}^N,\, \pi,\, \sigma^{\mathsf{bind}},\, \{\sigma_i^{\mathsf{auth}}\}_{i=1}^N,\, \mathsf{value\_balance}\big),

where π\pi is the single Halo 2 proof asserting the conjunction of all AiA_i.

Definition 2.3 (Typestate)

The bundle progresses InProgressUnauthorizedAuthorized\texttt{InProgress} \to \texttt{Unauthorized} \to \texttt{Authorized} through the Authorization trait. Each transition adds the proof or the signatures.

Definition 2.4 (Padding)

The builder pads the Action list with dummy Actions until NN matches a target. Dummies prevent the size of the bundle from leaking the count of real spends and outputs.

3. The Code

3.1 The Bundle Type

src/bundle.rs
loading...

Bundle<T, V> is generic over the authorisation typestate T (which implements the Authorization trait declared just above this block) and the user-defined valueBalanceOrchard type V. The public methods are gated on T; only the Authorized typestate exposes the proof bytes and the per-Action signatures.

3.2 The Builder

src/builder.rs
loading...

Builder::new(bundle_type, anchor) opens an empty builder parameterised by a BundleType (transactional or coinbase, with spends/outputs enablement flags) and the Merkle root every spend must commit under. add_spend and add_output queue inputs and outputs; build(rng) shuffles, pads with dummies, and produces an Unauthorized Bundle ready for proving.

3.3 The Signing Flow

  1. Bundle::<InProgress, V>::create_proof(rng, &pk) runs the prover and returns Bundle<Unauthorized<...>, V>.
  2. Bundle::<Unauthorized<...>, V>::prepare(rng, sighash) derives the SIGHASH-bound signing material.
  3. Per-Action apply_signatures(&[ask]) produces Authorized<V>.

3.4 Batch Verification

src/bundle/batch.rs batches Halo 2 proof checks and RedPallas signature checks across many bundles. Open issue #497 tracks returning a structured error from add_bundle.

3.5 SIGHASH

src/bundle/commitments.rs implements the per-Bundle digests used by the binding signature and the spend authorising signatures (per ZIP 244).

4. Failure Modes

  • Order-dependent randomness. The builder shuffles the Action list before sampling per-Action randomisers. A change that samples before shuffling exposes the order of inputs.
  • Mis-paired flags. enableSpends and enableOutputs must cover both the witness and the public flag values. Setting only one side produces a valid-looking proof that is rejected.
  • Premature signature access. The typestate prevents reading signatures from an Unauthorized bundle. PRs that introduce a public accessor must enforce the same gate.
  • Power-of-two regression. The padding count must be a power of two (see code comments). A change that bumps to a non-power-of-two breaks the assumption used by some verifiers' batch sizing.

5. Spec Pointers

6. Exercises

  1. Read Builder::build. List, in order, every randomness sampled per Action and which field (base or scalar) it inhabits.
  2. The padding count is a power of two. Find the constant and the calling site. Why a power of two specifically?
  3. Code task. In a unit test, build a Bundle with one spend and zero outputs, then assert that the produced bundle has exactly two Actions (one real, one dummy). Run cargo test --lib builder::.

7. Further Reading