Draft/extensible tx format (local version) - #133
Draft
vivek-arte wants to merge 52 commits into
Draft
Conversation
✅ Deploy Preview for zcash-zips-qedit ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
vivek-arte
marked this pull request as draft
February 3, 2026 12:13
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
5 times, most recently
from
February 6, 2026 03:57
a0020fe to
986b087
Compare
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
from
February 19, 2026 16:44
986b087 to
346b40d
Compare
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
from
March 6, 2026 02:19
346b40d to
68f3ef9
Compare
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
3 times, most recently
from
March 24, 2026 21:02
bd6f621 to
e325e71
Compare
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
from
April 21, 2026 20:25
e325e71 to
1e02d2f
Compare
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
from
May 13, 2026 18:44
1e02d2f to
5c49035
Compare
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
ZIPs 209 and 213: add missing references
… and Orchard. Specifies the effecting and authorizing data structures for each bundle type, with value balance moved to mValuePoolDeltas as per the extensible tx format design. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ment. Specifies the V6 transaction digest algorithms: - TxId digest with separate value_pool_deltas_digest and dynamic effects_bundles_digest - Signature digest for transparent input signing with hash_type support - Authorizing data commitment for witness data Key design decisions: - Value balances committed via top-level value_pool_deltas_digest (not per-bundle) - effects_bundles_digest uses tagged concatenation (bundle_type_id || root_hash) - Unknown bundle types supported by accepting their root hash externally Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tion process. Restructure the specification to begin with a comprehensive introduction to protocol bundles, explaining effecting data, authorizing data, and the transparent transaction value pool concepts. Define the bundle type registration process that ZIPs must follow when introducing new bundle types. Move the bundle type registry to appear before the transaction format specification for better readability. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update PR URL to 1156 and fix email addresses - Use conformance language (MAY/MUST NOT) for registry column descriptions - Add constraint that map keys must be in increasing order - Change "ordered by" to "in increasing order of" throughout - Fix "transparent transaction value pool" terminology - Change AssetUuid subscript notation to function notation - Add registry update mechanism language - Add "Defining ZIP" column to bundle type registry table - Rephrase consensus rules section to clarify modifications to protocol spec - Add clarifying text for fee bundle semantics (coinbase collects, others pay) - Add mutual exclusion consensus rule for Sapling/Orchard bundle variants Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Register bundle type 4 (Transaction fee) in the V6 bundle registry - Update consensus rules to use mValuePoolDeltas terminology - Replace header_digest modification with value_pool_deltas_digest reference - Add reference to extensible transaction format ZIP Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
A "Parsing Rules" section, ahead of the per-bundle format definitions and "Consensus Rules", lists the parser-level invariants that any v6 parser must enforce regardless of which bundle types it understands. This makes it explicit that parsing the format is safe even for parsers that don't recognize every bundle type, and gives wallets a single place to look for the constraints they need to check before they can compute the txid or enumerate transparent value flows. Move the cross-map "all entries for the same bundleType across the three maps must encode the same bundleVariant" rule, the per-element 1:1 correspondences in the Sapling authorizing-data section, and the analogous rules in the Orchard authorizing-data section into the new section. Their previous locations are replaced with one-line forward references. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ndle subsections.
The bundle-local rules ("assetClass = 0 for fee bundle entries", and
"coinbase transactions must have enableSpendsOrchard = 0") only need
to be enforced by parties that understand the bundle type they apply
to, while the cross-bundle / chain-context rules (per-block fee sum,
coinbase ZEC subsidy sum, non-coinbase per-asset value pool delta
sum) require full validators with block context.
The "coinbase transactions must have enableSpendsOrchard = 0" rule
was previously stated in passing in the prose under the Orchard
flagsOrchard field; lift it into the new bundle-local subsection so
all consensus rules are in one place.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ng = 0. The wire format for v6 Sapling effecting data omits anchorSapling when there are no Sapling spends, but T.3.2c lists anchorSapling as an unconditional 32-byte component of sapling_effects_digest. State explicitly that the value hashed at T.3.2c is 32 zero bytes in that case, so the digest structure remains fixed for any non-empty Sapling bundle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… 16 characters. Every other personalization string in the digest tree is exactly 16 characters, but ZTxIdEffBndHash (15) and ZTxAuthBndHash (14) were shorter, leaving the padding for the trailing bytes ambiguous. Rename them to ZTxIdEffBnd_Hash (1 underscore) and ZTxAuthBnd__Hash (2 underscores), matching the existing underscore-padding convention used elsewhere in this ZIP (e.g. ZTxIdSOutC__Hash) and in ZIP 244. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use "'" instead of "." for the sub-headings, so they're level 4 (matching the rest of the document) instead of level 5. The previous underline triggered a docutils "Title level inconsistent" SEVERE error and the document failed to render. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix "wouild" → "would", "advertizing" → "advertising", "inaccessiblity" → "inaccessibility", "i.e," → "i.e.,", and "[^BCP14]" (Markdown footnote) → "[#BCP14]_" (RST). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… section. Consensus Rules and Transaction Format prose use lowercase "must" for requirements that are normative. Per BCP 14, these carry conformance meaning only when in ALL CAPS in the Specification section. Requirements section left as-is per ZIP 0 (must not contain conformance requirements). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rsing Rules. The uniqueness, ordering, and cross-map consistency constraints on mValuePoolDeltas, mEffectBundles, and mAuthBundles were stated in three places: the prose after the Transaction Format table, the prose after the ValuePoolDelta table, and the Parsing Rules section. Keep Parsing Rules as the single normative source and replace the earlier prose with descriptive text and a cross-reference. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Parsing Rules required entries in strictly increasing key order but did not specify the comparison operation for the 64-byte assetUuid field. State explicitly that the key tuple (bundleType, assetClass, assetUuid) is compared lexicographically, with assetUuid compared as a byte string. Also fix a circular cross-reference: Parsing Rules said "as defined in Transaction Format" but Transaction Format now cross-references Parsing Rules. Make the Parsing Rules bullet self-contained instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The transparent bundle has no cryptographic binding between its contents and its mValuePoolDeltas entry (unlike Sapling/Orchard where value commitments and binding signatures enforce the relationship). Specify the consensus rule that full validators MUST verify the transparent delta equals total input value minus total output value, for both non-coinbase and coinbase transactions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This ZIP proposes its format as transaction version 7; version 6 is taken by ZIP 229. The formats that precede it are referred to as pre-V7. ZIP 248 defines "V7 transaction format", "V7 transaction", and "pre-V7 transaction format" in its Terminology section; ZIPs 231 and 2002 adopt those terms by reference. ZIP 231 additionally uses "V7-onward" and "pre-V7" to qualify note plaintexts and ciphertexts. ZIP 2002's Deployment section and ZIP 233's reference list also drop their remaining citations of ZIP 230, which the ZIP 248 registry supersedes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The citation of ZIP 230 for the explicit note plaintext encodings used a footnote label that was never defined, so it rendered as literal text. Point it at this ZIP's own Changes to the Zcash Protocol Specification section, which gives those encodings. Also remove the uncited ZIP 230 note plaintexts reference definition, and the duplicate ZIP 248 reference definition that pointed at a pull request URL. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Registers bundle type 1 variant 0 as the coinbase bundle, which the registry previously held as reserved. The block subsidy previously entered the transparent transaction value pool implicitly, which made the coinbase transaction the sole exception to the value pool delta balance rule: its deltas summed to the negation of the subsidy rather than to zero. The coinbase bundle carries the subsidy as its value pool delta, so the balance rule now holds for every transaction in every asset. The bundle's effecting data is the height of the block in which the transaction is mined, followed by a compactSize-prefixed field of at most 94 bytes for miner-chosen data. Both replace content that was previously encoded as the scriptSig of a transparent input whose previous output reference identified no output. The presence of the coinbase bundle now identifies a coinbase transaction, so that input is gone entirely, along with its sequence number. Also state the value of a lookup for a key absent from mValuePoolDeltas, which the balance rule requires in order to be well defined when the block subsidy is zero, and cross-reference the balance rule from the AssetUuid definition that supplies its grouping. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… data. The coinbase bundle's value pool delta is the block subsidy: the new issuance that consensus awards to the miner of the block, as distinct from the fees, which the fee bundle carries. That subsidy is now also stated as a blockSubsidy field of the coinbase bundle's own effecting data, and so committed to the transaction identifier along with the rest of that data. Deriving it instead is not open to every client, because the subsidy is not a function of the block height alone once issuance depends on accumulated chain state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Ironwood bundle takes bundle type 4, and the fee, NSM, key rotation, and lockbox disbursement bundles shift up by one to 5, 6, 7, and 8. ZIPs 2002 and 233 follow. The *Orchard pool* and the *Ironwood pool* are two pools of the same shielded protocol, so the section that specified the Orchard bundle now specifies the encoding of an Orchard protocol bundle, which the Orchard and Ironwood bundle types share. The anchor is described relative to the bundle's own pool, and the restriction on enableSpendsOrchard in a coinbase transaction applies to every Orchard protocol bundle rather than to the Orchard bundle alone. The pools need separate bundle types rather than variants of one type: a variant must affect the same value pool as the type it varies, so that a client that does not recognize the variant still knows which pools are touched. The Ironwood digests are the same shape as the Orchard ones over the same fields, with distinct personalization strings so that the digest of a bundle acting on one pool cannot be reused as the digest of a bundle acting on the other. Personalizations follow the stems ZIP 229 uses for the equivalent v6 digests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bit 2 of flagsOrchard is the enableCrossAddress bit specified by ZIP 2006, and bits 3..7 are the reserved ones. The bit MUST be 0 in an Orchard bundle, which is what restricts transfers into the Orchard pool to the protocol-level address of the action's spend; it is unrestricted in an Ironwood bundle. The other two bits lose their Orchard suffix, becoming enableSpends and enableOutputs, because they mean the same thing for both pools. ZIP 229 renamed them for that reason when it gave the Ironwood pool its own flags field. ZIP 231 now registers its Orchard variant against every bundle type that uses the Orchard protocol bundle encoding, rather than against the Orchard pool alone, and its copy of the encoding follows the flags field. The terms taken from ZIP 229 are declared in both Terminology sections. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
2 times, most recently
from
September 1, 2026 21:08
8a24b5a to
a21e4b1
Compare
The registry now lists only the (bundleType, bundleVariant) pairs this upgrade allocates, and runs 0 to 6 without a gap. Everything whose identifier is still open moves to the potential future bundle types section: key rotation, lockbox disbursement, memos, and ZSA issuance, none of which has a bundle type; and the post-ZIP 231 and OrchardZSA variants, which have a bundle type but no variant identifier. That section gains the Defining ZIP column, so the entries that name a ZIP keep it, and its lead-in no longer describes every entry as illustrative. The Orchard variant that ZIP 231 defines is also renamed to match that ZIP and registered against the Ironwood bundle as well as the Orchard bundle, which is what ZIP 231 asks for now that both use the Orchard protocol bundle encoding. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nuttycom
force-pushed
the
draft/extensible_tx_format
branch
2 times, most recently
from
September 1, 2026 23:57
4ad4038 to
873532a
Compare
…ation. Addresses str4d's review comment on PR 1156. Everything a reader needs in order to parse, identify, and digest a transaction without knowing any bundle type now comes first: the registry, the transaction format, the parsing rules, the consensus rules, sighash versioning, and the bundle-agnostic parts of the digest trees. A new Bundle Definitions section at the end then defines the four bundle types this ZIP registers, in the shape that another ZIP would use to register one of its own. Each bundle's effecting data, authorizing data, sighash algorithms, and digest contributions are now given together, so T.3.x, S.3.0, and A.1.x sit beside the structures they hash rather than in a separate digest section. The table of associatedData per protocol is replaced by a per-bundle statement of the sighash algorithm versions available at variant 0, which is where a ZIP registering a bundle type would state them. Sighash Versioning keeps the versioning mechanism and the per-signature structures. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…box. Addresses str4d's review comments on PR 1156. The block subsidy is the whole of the new issuance for a block, which consensus splits between the miner, the funding streams that pay to an address, and the funding streams that deposit into the deferred pool. Describing it as what the miner is awarded was wrong, and so was equating it with the coinbase bundle's value pool delta: the part deposited into the lockbox is never paid out by the transaction. The coinbase bundle's effecting data now carries lockboxValue alongside blockSubsidy, and the value pool delta is their difference. Both components are stated because the delta alone shows what the coinbase pays out, not what was issued or what the lockbox received. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses the review comments on PR 1156, following ZIP 229. An anchor selects the note commitment tree state that a bundle's proofs are verified against, which is a property of how the spends are authorized rather than of what the transaction does. Carrying it as authorizing data lets a bundle be re-anchored to a more recent root without changing the transaction identifier, while the proofs still bind to the anchor actually used. anchorSapling and anchorOrchard move to the end of their bundles' authorizing data, and to the auth digests after the existing fields. Each is present only when its bundle has a spend or action referencing it, so a Sapling bundle with outputs but no spends now references no anchor at all, rather than hashing 32 zero bytes in its place. The personalizations of the four digests whose directly hashed content changes are distinguished as ZIP 229 distinguishes its own: ZTxIdSaplingH_v7, ZTxAuthSapliH_v7, ZTxIdOrchardH_v7, and ZTxAuthOrchaH_v7. The Ironwood digests keep theirs, which this ZIP already introduced. ZIP 231's copies of the Sapling and Orchard encodings follow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
daira: correct Jack Grigg's address in the Owners field; drop REQUIRED from the BCP 14 key words, which the document does not use, and with it the template instruction that was still sitting above them; in ZIP 233, MUST BE -> MUST be. nuttycom: register the two Orchard protocol variants in ZIP 231 under their own names, Orchard post-ZIP 231 and Ironwood post-ZIP 231, rather than one name listed twice; and fix the wrapping of the ZIP 231 Motivation paragraph. Two more wrapping defects of my own are fixed alongside: the same paragraph shape in the deferred memo decryption rationale, and a note about the anchor that had been placed inside the flagsOrchard bullet list rather than after it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses the review comments on PR 1156. The downgrade attack that the KDF domain separation prevents is one against the partial-ciphertext optimization, which v5 and v6 have; it is not a property of every earlier ciphertext format. Both places that described the target now say v5 or v6. The domain separation itself is still from every pre-V7 note ciphertext, so that statement is unchanged. The note that the memo bundle changes must be merged with the addition of an asset_base field to Orchard note plaintexts is removed; that work is not part of this PR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses str4d's review comments on PR 1156. The anchor precedes the proofs and signatures it constrains, in the encoding and in the auth digests alike. This is symmetric with other descriptions of the Sapling and Orchard protocols, and it follows the direction in which the data depends: changing an anchor forces the proofs to be recomputed, while the proofs can be recomputed against an unchanged anchor. Note this orders the auth digests differently from ZIP 229, which appends each anchor after the existing fields. ZIP 231's copies of both encodings follow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ion. Addresses str4d's review comments on PR 1156. TransparentSighashInfo, SaplingSignature, and OrchardSignature move from the shared Per-Signature Structures subsection into the authorizing data of the bundles that carry them, replacing the cross-references that stood in their place. Sighash Versioning keeps only the versioning mechanism, which is what is bundle-agnostic about it. The Signature Digest section is renamed v0 Signature Digest, since it is the digest that sighash version 0 selects rather than the only one a signer can ever commit to. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses str4d's and nuttycom's review comments on PR 1156. Conformance to the bundle type registry moves from the parsing rules to the bundle-local consensus rules. A parser cannot check it for a bundle type it does not know, because the registry grows with each network upgrade, whereas a full validator always knows the registry in force for the block it is validating. The coinbase restriction on shielded spends was stated for the Orchard protocol bundles but not for Sapling; nSpendsSapling MUST now be 0 in a coinbase transaction as well. blockSubsidy and lockboxValue become uint64, which consensus already requires of them, so blockSubsidy no longer needs a separate nonnegativity rule. The example in Privacy Implications is stated against NU8 and a hypothetical NU9. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Jack Grigg <thestr4d@gmail.com>
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.
No description provided.