Release 0.15.0#516
Draft
ebfull wants to merge 69 commits into
Draft
Conversation
Fix the `BuildError::OutputsDisabled` `Display` string, which described spends rather than outputs, and tighten related builder, PCZT signer, and tree doc comments. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename `enable_spends`/`enable_outputs` to `enable_spend`/`enable_output` throughout the circuit gate, witness assignments, and constraint comments, matching the per-action semantics of the flags. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a `Circuit::empty` constructor for shape-only uses (key generation, layout rendering) where witnesses are unknown. Move `configure` onto `Config` and split synthesis into a reusable `synthesize_base`, so the per-version constraints can build on a shared base. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the closure body of `bundle_for_version` into a `finish_unauthorized_bundle` helper that derives the binding signing key, builds the actions, checks bsk/bvk consistency, and assembles the unauthorized bundle. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `single_leaf_witness`, the `SHIELDING` bundle type, and an `output_only_builder` helper, and rewrite the existing tests to use them instead of repeating tree-construction and builder boilerplate. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`BatchValidator` now binds its verifying key at construction: `BatchValidator::new` takes a `&VerifyingKey` and `validate` no longer does. Removes the `Default` impl, since a verifying key is now required. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Circuit-building APIs (`ProvingKey`/`VerifyingKey::build`, `Circuit::from_action_context`) now take an explicit `OrchardCircuitVersion` instead of defaulting to `FixedPostNu6_2`. Removes the temporary `_for_version` key/circuit APIs and the `Default` impls for `Circuit` and `OrchardCircuitVersion`; callers must choose a version explicitly. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce `orchard::bundle::BundleProtocol`, the `(pool, era)` selector that bundle construction is chosen by. It currently projects to the Action circuit version via `circuit_version()`, with variants `OrchardPreNu6_2` and `OrchardPreNu6_3`. `orchard::builder::Builder::new` and `orchard::builder::bundle` take a `BundleProtocol` in place of the removed `Builder::new_for_version` / `bundle_for_version`, and `Builder::build` derives the circuit version from it. Proving and verifying keys still take an `OrchardCircuitVersion`, since a key is a circuit artifact, and the version is threaded that way through the builder internals. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `Flags::cross_address_enabled` to expose the cross-address bit while keeping the pre-NU6.3 wire encoding unchanged. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce the NU6.3 flag-byte format, where bit 2 is `enableCrossAddress`,
alongside the pre-NU6.3 format where it is reserved. The crate-private
`BundleFormat` captures this era distinction, and `BundleProtocol` gains the
`OrchardPostNu6_3` and `IronwoodPostNu6_3` variants, projecting to a
`BundleFormat` via `bundle_format()`.
`Flags::{to,from}_byte`, `Bundle::commitment`, and `pczt::Bundle::parse` now
take a `BundleProtocol` and interpret bit 2 according to its era; the same byte
parses as an unrestricted bundle before NU6.3 and a restricted one under NU6.3.
`Flags` gains `CROSS_ADDRESS_DISABLED` (representable only under NU6.3), and
`to_byte`/`commitment` refuse to encode it under a pre-NU6.3 protocol.
Co-authored-by: GPT 5.5 <codex@openai.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `disableCrossAddress` as a circuit public input and reject restricted bundles for keys that cannot enforce it. `BatchValidator::add_bundle` now returns `Result` to signal unsupported restricted bundles. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an `Address` helper that compares derived expanded receiver pairs, for use by the restricted cross-address checks added in later commits. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire the post-NU 6.3 circuit through key and circuit-version selection ahead of adding its constraints. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ircuit
Add the post-NU 6.3 constraints, the regenerated circuit description, and
proof fixtures for both unrestricted and restricted statements. Pre-NU 6.3
keys continue to reject restricted proof instances.
Surface the consensus constraint as
`BundleProtocol::requires_cross_address_restriction` (true only for
`OrchardPostNu6_3`), and restructure `BundleType::Transactional` to carry
`{ spends_enabled, outputs_enabled, bundle_required }`. The builder derives the
`enableCrossAddress` bit from the protocol — the least-restrictive value
consensus permits — via `BundleType::{flags, num_actions}`, which now take the
`BundleProtocol`.
Co-authored-by: GPT 5.5 <codex@openai.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reject restricted PCZTs with mismatched expanded receivers before signing, finalizing, or proving them. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pair spends and outputs by expanded receiver, fabricating zero-value counterparts as needed and rejecting impossible flag combinations. The fabricated zero-value output paired with each real spend is addressed to the spent note's own receiver, so its `enc_ciphertext` is randomized rather than encrypted to that address. A real ciphertext there would trial-decrypt under the receiver's incoming viewing key in the same action that carries the spend's nullifier, letting anyone who holds the ivk -- including a quantum adversary who recovered it from the published address, while nk stays secret -- detect the spend, collapsing the protocol's asymmetry that hides spends but not receives. `OutputInfo::fabricated_for_spend` sets a `randomized_ciphertext` flag; `build` then fills `enc_ciphertext` with random bytes (asserting the value is zero, so it can never stand in for a value-bearing note) while keeping the genuine epk and random out_ciphertext, leaving the note and its commitment unchanged so the circuit's same-expanded-receiver constraint and PCZT note-commitment checks still hold. Padding and `OutputInfo::dummy` outputs go to throwaway addresses and keep ordinary encryption. In a PCZT the output still carries its explicit recipient, value, and rseed with no user_address, so a signer reads the zero value and classifies it as a dummy it tolerates -- rather than reconstructing the expected ciphertext and rejecting the mismatch. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Support restricted builder and PCZT flows end to end, including fabricated spend signing, padding dummies, and coinbase handling. Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the CHANGELOG preamble summarizing the NU6.3 `enableCrossAddress` flag and the post-NU 6.3 Orchard Action circuit, and how existing callers preserve the current behavior by selecting `BundleProtocol::OrchardPreNu6_3` (and `OrchardCircuitVersion::FixedPostNu6_2` when building proving/verifying keys). Co-authored-by: GPT 5.5 <codex@openai.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iants Behaviour-preserving rename of the bundle pool restrictions enum, its arms, and the `protocol` field/parameters that carry it, to better reflect what the value actually pins (the information that affects pool-related restrictions on a bundle), with no logic changes: - BundleProtocol -> BundlePoolRestrictions - OrchardPreNu6_3 -> OrchardNu6_2Only - OrchardPostNu6_3 -> OrchardNu6_3Onward - IronwoodPostNu6_3 -> IronwoodNu6_3Onward - `protocol` field/parameters -> `pool_restrictions` Also reframes the closely-related doc comments (prose `protocol` -> pool restrictions / `BundlePoolRestrictions`). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Carry the underlying VerifyError inside ProverError::DisallowedCrossAddressTransfer rather than having a unit variant alongside a separate ProverError::CrossAddressRestriction(VerifyError); the prover now surfaces the cross-address verification failure through a single variant. Also reword the VerifyError cross-address Display message in terms of the bundle's pool restriction. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
… exceptional
Bit 2 of the Orchard flag byte (`enableCrossAddress`) is only representable
for the Ironwood pool post-NU6.3. It is rejected pre-NU6.3 (where bit 2 is
reserved) and for Orchard post-NU6.3 (where consensus mandates the
cross-address restriction). This is now keyed directly on
`BundlePoolRestrictions` in `Flags::{from_byte, to_byte}` rather than via an
intermediate era projection, so the now-redundant `BundleFormat` enum and
`BundlePoolRestrictions::bundle_format` are removed.
`Flags::from_parts` is consolidated to the 3-argument form taking the
cross-address bit; the 2-argument `from_parts_with_cross_address` wrapper is
removed.
Coinbase bundles are not exceptional with respect to the cross-address
restriction: they always disable spends and enable outputs, but set
`enableCrossAddress` exactly as a non-coinbase transaction would for the same
pool restrictions. The `BundleType::Coinbase` flags arm now uses
`default_cross_address_enabled(pool_restrictions)` accordingly.
Tests covering cross-address-enabled flag bytes move to the Ironwood pool
(the only pool that can represent them), and `arb_flags_nu6_3` is renamed to
`arb_flags_ironwood_post_nu6_3`.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
NU6.3 Circuit Implementation
Co-Authored-By: Tal Derei <talderei99@gmail.com>
Co-Authored-By: Tal Derei <talderei99@gmail.com>
Co-Authored-By: Tal Derei <talderei99@gmail.com>
Co-Authored-By: Tal Derei <talderei99@gmail.com>
Co-Authored-By: Tal Derei <talderei99@gmail.com>
Add QR note version support
Co-Authored-By: Dev Ojha <dojha@berkeley.edu>
Replace the internal AnchorCommitment enum with two boolean predicates (includes_anchor_in_txid_digest / includes_anchor_in_authorizing_digest) and reword the bundle commitment documentation for clarity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add in v6 and Ironwood TX-id / Auth-ID code
Ironwood: CHANGELOG.md reorganizations and improvements
Previously `commitment_format` ignored `tx_version` for the Ironwood pool, silently committing an Ironwood bundle under v6 personalization even when the caller requested `TxVersion::V5`. Add a `CommitmentError::InvalidTransactionVersion` variant and return it from the commitment APIs instead. This makes `authorizing_commitment` and the `hash_bundle_*_empty` helpers fallible, mirroring `commitment`, and threads `CommitmentError` through the internal `hash_bundle_*_data` helpers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reject Ironwood commitments for v5 transactions
Contributor
|
Converted to draft until we're through the pre-release phase. |
Replace `BundlePoolRestrictions` with `BundleVersion`, the `(ValuePool, ProtocolVersion)` of an Orchard bundle, built from the new top-level `ValuePool` and `ProtocolVersion` types via safe-by-construction `const fn` constructors (`orchard_insecure_v0`, `orchard_v1`, `orchard_v2`, `ironwood_v2`). Each `Bundle` now carries its `BundleVersion` as non-serialized context, so a bundle is encodable and committable by construction: - Construction (`Bundle::from_parts` / `try_from_parts`, the builder, and PCZT parsing/extraction) takes a `BundleVersion` and validates that the flags are representable under it, rejecting inconsistent combinations with the new `BundleError::UnrepresentableFlags`. `from_parts` is now fallible. - `commitment` / `authorizing_commitment` and the `decrypt_*` / `recover_*` helpers no longer take a version argument; they read it from the bundle. `Bundle::flag_byte` exposes the now-infallible flag-byte encoding and `Bundle::bundle_version` the carried version. - `CommitmentError::UnrepresentableFlags` is removed (flags are validated at construction); only `InvalidTransactionVersion` remains. Proof-size enforcement is derived from the bundle version rather than a separate `ProofSizeEnforcement` argument: it is enforced for every version except the historical pre-NU6.2 Orchard pool (`orchard_insecure_v0`), whose already-committed transactions may carry non-canonical proofs. `ProofSizeEnforcement` is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`BundleType` previously embedded part of a bundle's `Flags`
(`Transactional` carried `spends_enabled`/`outputs_enabled`, and
`BundleType::flags` derived the cross-address bit from the bundle
version). This conflated two independent concerns: the construction
discipline (how the builder pads and pairs actions) and the bundle's
flag set (which spend/output/cross-address capabilities it advertises).
It also meant the caller could not restrict cross-address transfers more
tightly than the bundle version's default chose to.
Make the two orthogonal. `BundleType` is now just the construction
policy — `Transactional { bundle_required }` or `Coinbase` — and the
bundle's `Flags` are supplied separately to the builder. The default
flag set moves to `BundleVersion::default_flags` (spends and outputs
enabled, cross-address transfers enabled unless the version mandates the
restriction); a caller may pass a more restricted set the version
permits.
Validate the flags when the builder is constructed: `Builder::new` (and
the free `bundle` function) now take `Flags` and are fallible, rejecting
a flag set that cannot be encoded under the bundle version with
`BuildError::UnrepresentableFlags`, and rejecting a `Coinbase` builder
whose flags enable spends with `BuildError::CoinbaseSpendsEnabled`.
Because the flags are validated up front, `build_bundle` can assume they
are encodable (a `debug_assert!` documents the invariant).
`BundleType::num_actions` now reads the spend/output/cross-address
policy from the supplied `Flags` rather than re-deriving it from the
bundle version.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The `try_from_parts` doc linked to the `pub(crate)` `BundleVersion::enforces_canonical_proof_size`, which trips `rustdoc::private_intra_doc_links` (an error under `-D warnings`). Point at the public `BundleVersion::orchard_insecure_v0` constructor instead: it builds the sole bundle version whose proof size is not enforced, so it is the more useful public reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename the `ProtocolVersion` variants and `BundleVersion` constructors from 0-based to 1-based version numbers, at the protocol developers' request: ProtocolVersion::InsecureV0 -> InsecureV1 ProtocolVersion::V1 -> V2 ProtocolVersion::V2 -> V3 BundleVersion::orchard_insecure_v0 -> orchard_insecure_v1 BundleVersion::orchard_v1 -> orchard_v2 BundleVersion::orchard_v2 -> orchard_v3 BundleVersion::ironwood_v2 -> ironwood_v3 This is a pure rename with no change in behavior; each version keeps the same mapping to consensus epochs, circuit versions, and note plaintext versions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reorder the free `bundle` function to take `bundle_type` immediately after `rng`, matching `Builder::new`'s `(bundle_type, bundle_version, flags, anchor)` order. Also note the removal of `BundleType::DISABLED` in the changelog. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Distinguish value pool, protocol version, and bundle version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
❗ Do not merge into
mainuntil0.15.0is released oncrates.ioand the commit is tagged as0.15.0.This is the release PR for
0.15.0, which features NU6.3-related changes including the new circuit and pool APIs for Ironwood. This tracks thefeat/ironwoodbranch, which is currently open for PRs.We are doing pre-release testing first. We'll be releasing
0.15.0-pre.Nfrom this branch until ZIPs, specs, audits and other internal reviews confirm we're ready for anorchardcrate release.