Skip to content

Draft/extensible tx format (local version) - #133

Draft
vivek-arte wants to merge 52 commits into
QED-it:mainfrom
zcash:draft/extensible_tx_format
Draft

Draft/extensible tx format (local version)#133
vivek-arte wants to merge 52 commits into
QED-it:mainfrom
zcash:draft/extensible_tx_format

Conversation

@vivek-arte

Copy link
Copy Markdown

No description provided.

@netlify

netlify Bot commented Feb 3, 2026

Copy link
Copy Markdown

Deploy Preview for zcash-zips-qedit ready!

Name Link
🔨 Latest commit 3d31529
🔍 Latest deploy log https://app.netlify.com/projects/zcash-zips-qedit/deploys/6a160662f748050008e67278
😎 Deploy Preview https://deploy-preview-133--zcash-zips-qedit.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@vivek-arte
vivek-arte marked this pull request as draft February 3, 2026 12:13
@nuttycom
nuttycom force-pushed the draft/extensible_tx_format branch 5 times, most recently from a0020fe to 986b087 Compare February 6, 2026 03:57
@nuttycom
nuttycom force-pushed the draft/extensible_tx_format branch from 986b087 to 346b40d Compare February 19, 2026 16:44
@nuttycom
nuttycom force-pushed the draft/extensible_tx_format branch from 346b40d to 68f3ef9 Compare March 6, 2026 02:19
@nuttycom
nuttycom force-pushed the draft/extensible_tx_format branch 3 times, most recently from bd6f621 to e325e71 Compare March 24, 2026 21:02
@nuttycom
nuttycom force-pushed the draft/extensible_tx_format branch from e325e71 to 1e02d2f Compare April 21, 2026 20:25
@nuttycom
nuttycom force-pushed the draft/extensible_tx_format branch from 1e02d2f to 5c49035 Compare May 13, 2026 18:44
daira and others added 16 commits August 12, 2026 16:06
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>
daira and others added 16 commits September 1, 2026 12:27
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
nuttycom force-pushed the draft/extensible_tx_format branch 2 times, most recently from 8a24b5a to a21e4b1 Compare September 1, 2026 21:08
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
nuttycom force-pushed the draft/extensible_tx_format branch 2 times, most recently from 4ad4038 to 873532a Compare September 1, 2026 23:57
nuttycom and others added 9 commits September 1, 2026 18:03
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants