diff --git a/README.rst b/README.rst
index 1a92f05b..b5630906 100644
--- a/README.rst
+++ b/README.rst
@@ -181,6 +181,7 @@ written.
| 235 | Remove 60% of Transaction Fees From Circulation | Draft | zips#924 |
| 245 | Transaction Identifier Digests & Signature Validation for Transparent Zcash Extensions | Draft | zips#384 |
| 246 | Digests for the Version 6 Transaction Format | Draft | |
+
| 248 | Extensible Transaction Format | Draft | zips/pull/1163 |
| 270 | Key Rotation for Tracked Signing Keys | Reserved | zips#1047 |
| 302 | Standardized Memo Field Format | Draft | zips#366 |
| 303 | Sprout Payment Disclosure | Reserved | |
@@ -320,6 +321,7 @@ Index of ZIPs
| 244 | Transaction Identifier Non-Malleability | Final |
| 245 | Transaction Identifier Digests & Signature Validation for Transparent Zcash Extensions | Draft |
| 246 | Digests for the Version 6 Transaction Format | Draft |
+
| 248 | Extensible Transaction Format | Draft |
| 250 | Deployment of the Heartwood Network Upgrade | Final |
| 251 | Deployment of the Canopy Network Upgrade | Final |
| 252 | Deployment of the NU5 Network Upgrade | Final |
diff --git a/zips/zip-0226.rst b/zips/zip-0226.rst
index b2d3bf95..ac76147b 100644
--- a/zips/zip-0226.rst
+++ b/zips/zip-0226.rst
@@ -363,11 +363,190 @@ The transaction format for v6 transactions is described in ZIP 230 [#zip-0230]_.
The ZSA-related changes in v6 include:
* updates to the transaction structure [#zip-0230-transaction-format]_ and the
- sighash digest computation [#zip-0246]_;
+ sighash digest computation [#zip-0248]_;
* new note plaintext formats for both Sapling and Orchard outputs [#zip-0230-note-plaintexts]_,
with corresponding changes to the note decryption algorithms for incoming and
outgoing viewing keys [#zip-2005]_.
+Changes to ZIP 248
+``````````````````
+
+This ZIP proposes to register the OrchardZSA bundle type in the V6 transaction
+bundle type registry defined in ZIP 248 [#zip-0248]_:
+
++------------+----------------------+--------------------+------------------+-------------+
+| BundleType | ``mValuePoolDeltas`` | ``mEffectBundles`` | ``mAuthBundles`` | Bundle kind |
++============+======================+====================+==================+=============+
+| TBD |✅ |✅ |✅ | OrchardZSA |
++------------+----------------------+--------------------+------------------+-------------+
+
+OrchardZSA Effecting Data
+'''''''''''''''''''''''''
+
++-----------------------------+----------------------------------+------------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==================================+======================================================+=====================================================================+
+| varies |``nActionGroupsOrchard`` |``compactSize`` |The number of Action Group descriptions in |
+| | | |``vActionGroupsOrchard``. |
++-----------------------------+----------------------------------+------------------------------------------------------+---------------------------------------------------------------------+
+| varies |``vActionGroupsOrchard`` |``ActionGroupOrchardEffecting[nActionGroupsOrchard]`` |A sequence of ActionGroupOrchardEffecting descriptions, encoded as |
+| | | |per `ActionGroupOrchardEffecting`_. |
++-----------------------------+----------------------------------+------------------------------------------------------+---------------------------------------------------------------------+
+
+ActionGroupOrchardEffecting
+'''''''''''''''''''''''''''
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| varies |``nActionsOrchard`` |``compactSize`` |The number of Action descriptions in ``vActionsOrchard``. |
+| | | |This MUST have a value strictly greater than ``0``. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 372 × ``nActionsOrchard`` |``vActionsOrchard`` |``OrchardZSAEffecting[nActionsOrchard]`` |A sequence of OrchardZSA Action descriptions in the Action Group. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 1 |``flagsOrchard`` |``byte`` |As defined in §7.1 ‘Transaction Encoding and Consensus’ |
+| | | |[#protocol-txnencoding]_. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 32 |``anchorOrchard`` |``byte[32]`` |As defined in §7.1 ‘Transaction Encoding and Consensus’ |
+| | | |[#protocol-txnencoding]_. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 4 |``nAGExpiryHeight`` |``uint32`` |A block height in the range {1 .. 499999999} after which any |
+| | | |transaction including this Action Group cannot be mined, or 0 if |
+| | | |this Action Group places no constraint on transaction expiry. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies | ``nAssetBurn`` | ``compactSize`` |The number of Assets burnt. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 40 × ``nAssetBurn`` | ``vAssetBurn`` | ``AssetBurn[nAssetBurn]`` |A sequence of Asset Burn descriptions, encoded per |
+| | | |`OrchardZSA Asset Burn Description`_. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+The encodings of ``OrchardZSAEffecting`` and ``AssetBurn`` are described below.
+
+* If the value of ``nAGExpiryHeight`` is nonzero, it MUST be consistent with
+ the ``nExpiryHeight`` of the overall transaction.
+* In NU7, ``nExpiryHeight`` MUST be set to ``0``; this restriction is expected
+ to be lifted in a future network upgrade.
+
+Rationale for nAGExpiryHeight
+'''''''''''''''''''''''''''''
+
+We introduce the ``nAGExpiryHeight`` field in this transaction format in order
+to be forward compatible with Swaps over ZSAs, as proposed in ZIP 228
+[#zip-0228]_. For the OrchardZSA protocol, which does not make use of an
+additional expiry height for transactions, we set the value of
+``nAGExpiryHeight`` to be ``0`` by consensus. This serves as a default value to
+represent the situation where there is no expiry, analogous to the convention
+adopted for ``nExpiryHeight`` in ZIP 203 [#zip-0203].
+
+Rationale for including Burn fields inside OrchardZSA Action Groups
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+Note that the bundle format includes the burn fields of the transaction inside
+the OrchardZSA Action Group rather than at the transaction level. This is a
+design choice that considers the future scenario where Action Groups may be
+generated by different parties before being bundled together into a
+transaction. In such a scenario, the individual parties can burn Assets of
+their choice in their corresponding Action Groups. Maintaining the burn fields
+at the transaction level would provide the ability to burn Assets only to the
+party performing the bundling of the Action Groups.
+
+OrchardZSAEffecting
+'''''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the input note minus the |
+| | | |output note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``nullifier`` |``byte[32]`` |The nullifier of the input note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``rk`` |``byte[32]`` |The randomized validating key for this Action. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``cmx`` |``byte[32]`` |The :math:`x\!`-coordinate of the note commitment for the output |
+| | | |note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Pallas public key. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``132`` |``encCiphertext`` |``byte[132]`` |The encrypted contents of the note plaintext. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by concatenation |
+| | | |of the transmission key with the ephemeral secret key. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+.. _`OrchardZSA Asset Burn Description`:
+
+OrchardZSA Asset Burn Description
+'''''''''''''''''''''''''''''''''
+
+An OrchardZSA Asset Burn description is encoded as an instance of an
+``AssetBurn`` type:
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| 32 |``AssetBase`` |``byte[32]`` |For the OrchardZSA protocol, this is the encoding of the Asset Base |
+| | | |:math:`\mathsf{AssetBase^{Orchard}}\!`. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 8 |``valueBurn`` |``uint64`` |The amount being burnt. The value is checked by consensus to be |
+| | | |non-zero. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+OrchardZSA Authorizing Data
+'''''''''''''''''''''''''''
+
+The authorizing data for the OrchardZSA bundle contains the proofs and
+signatures that authorize the actions. The per-action-group data parallels the
+structure of the effecting data.
+
++-----------------------------+----------------------------------+------------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==================================+======================================================+=====================================================================+
+| varies |``vActionGroupsOrchardAuth`` |``ActionGroupOrchardAuthorizing[nActionGroupsOrchard]``|Authorizing data for each Action Group, in the same order as |
+| | | |``vActionGroupsOrchard`` in the effecting data. |
++-----------------------------+----------------------------------+------------------------------------------------------+---------------------------------------------------------------------+
+|``64`` |``bindingSigOrchard`` |``byte[64]`` |An Orchard binding signature on the SIGHASH transaction hash. |
++-----------------------------+----------------------------------+------------------------------------------------------+---------------------------------------------------------------------+
+
+* The value of ``nActionGroupsOrchard`` is not re-encoded in the authorizing
+ data; it is taken from the corresponding effecting data.
+
+* The field ``bindingSigOrchard`` is present if and only if
+ $\mathtt{nActionGroupsOrchard} > 0$.
+
+ActionGroupOrchardAuthorizing
+'''''''''''''''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``varies`` |``sizeProofsOrchard`` |``compactSize`` |Length in bytes of ``proofsOrchard``. Value is |
+| | | |:math:`2720 + 2272 \cdot \mathtt{nActionsOrchard}\!`. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``sizeProofsOrchard`` |``proofsOrchard`` |``byte[sizeProofsOrchard]`` |Encoding of aggregated zk-SNARK proofs for OrchardZSA Actions |
+| | | |in this Action Group. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``64 * nActionsOrchard`` |``vSpendAuthSigsOrchard`` |``byte[64 * nActionsOrchard]`` |Authorizing signatures for each OrchardZSA Action in this |
+| | | |Action Group. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+* The value of ``nActionsOrchard`` is not re-encoded in the authorizing data; it
+ is taken from the corresponding ``ActionGroupOrchardEffecting``.
+
+* The proofs aggregated in ``proofsOrchard``, and the elements of
+ ``vSpendAuthSigsOrchard``, each have a 1:1 correspondence to the elements of
+ ``vActionsOrchard`` in the corresponding ``ActionGroupOrchardEffecting`` and
+ MUST be ordered such that the proof or signature at a given index corresponds
+ to the ``OrchardZSAEffecting`` at the same index.
+
+The OrchardZSA bundle has value pool deltas (transfers move value in and out of
+the transparent transaction value pool), effecting data (the OrchardZSA actions
+and burn information), and authorizing data (the proofs and binding signature).
+
+A transaction MUST NOT contain both an Orchard bundle (type 3) and an OrchardZSA
+bundle. The OrchardZSA bundle replaces the Orchard bundle for transactions that
+transfer Custom Assets.
+
Implications for Wallets
````````````````````````
@@ -387,13 +566,18 @@ The following requirements on wallets are specified and motivated in ZIP 230
temporarily inaccessible, until the wallet is upgraded to fully support v6 and to
rescan outputs since v6 activation.
-Sighash modifications relative to ZIP 244 [#zip-0244]_
-------------------------------------------------------
+Modifications to Digest Algorithms
+----------------------------------
+
+The OrchardZSA bundle contributes to the transaction identifier and signature
+digest via the ``effects_bundles_digest`` and ``auth_bundles_digest`` defined
+in ZIP 248 [#zip-0248]_.
-Relative to the sighash algorithm defined in ZIP 244 [#zip-0244]_, the sighash algorithm
-that applies to v6 transactions differs by altering the Orchard bundle within
-the tree hash to match the corresponding OrchardZSA changes. See ZIP 246 [#zip-0246]_
-for details.
+The OrchardZSA bundle's value pool deltas (for both ZEC and Custom Assets) are
+committed via ``value_pool_deltas_digest``. The OrchardZSA effecting data
+(actions and burn information) is committed via ``effects_bundles_digest``.
+The OrchardZSA authorizing data (proofs and binding signature) is committed
+via ``auth_bundles_digest``.
Transaction Fees
----------------
@@ -435,7 +619,9 @@ References
.. [#BCP14] `Information on BCP 14 — "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels" and "RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words" `_
.. [#zip-0200] `ZIP 200: Network Upgrade Mechanism `_
.. [#zip-0209] `ZIP 209: Prohibit Negative Shielded Chain Value Pool Balances `_
+.. [#zip-0203] `ZIP 203: Transaction Expiry `_
.. [#zip-0224] `ZIP 224: Orchard `_
+.. [#zip-0228] `ZIP 228: Asset Swaps for Zcash Shielded Assets `_
.. [#zip-0227] `ZIP 227: Issuance of Zcash Shielded Assets `_
.. [#zip-0227-specification-global-issuance-state] `ZIP 227: Issuance of Zcash Shielded Assets — Specification: Global Issuance State `_
.. [#zip-0227-assetidentifier] `ZIP 227: Issuance of Zcash Shielded Assets — Specification: Asset Identifier `_
@@ -449,8 +635,7 @@ References
.. [#zip-0230-note-plaintexts] `ZIP 230: Version 6 Transaction Format — Note Plaintexts `_
.. [#zip-0230-orchard-note-plaintext] `ZIP 230: Version 6 Transaction Format — Orchard Note Plaintext `_
.. [#zip-0230-implications-for-wallets] `ZIP 230: Version 6 Transaction Format — Implications for Wallets `_
-.. [#zip-0244] `ZIP 244: Transaction Identifier Non-Malleability `_
-.. [#zip-0246] `ZIP 246: Digests for the Version 6 Transaction Format `_
+.. [#zip-0248] `ZIP 248: Extensible Transaction Format `_
.. [#zip-0307] `ZIP 307: Light Client Protocol for Payment Detection `_
.. [#zip-2005] `ZIP 2005: Quantum Recoverability `_
.. [#protocol] `Zcash Protocol Specification, Version 2025.6.2 [NU6.1] or later. `_
diff --git a/zips/zip-0227.rst b/zips/zip-0227.rst
index 7a58b4e3..4eabc32e 100644
--- a/zips/zip-0227.rst
+++ b/zips/zip-0227.rst
@@ -325,9 +325,9 @@ An Issue Note is a tuple $(\mathsf{d}, \mathsf{pk_d}, \mathsf{v}, \mathsf{AssetB
- $\text{ρ}: \mathbb{F}_{q_{\mathbb{P}}}$ is used to derive the nullifier of the note, and is computed as in `Computation of ρ`_.
- $\mathsf{rseed}: \mathbb{B}^{[\mathbb{Y}^{32}]}$ MUST be sampled uniformly at random by the issuer.
-ZIP 230 [#zip-0230-issue-note]_ defines, in ``IssueNoteDescription``, field encodings which together with
-$\mathsf{issuer}$ from the parent `Issuance Bundle`_ and $\mathsf{AssetDescHash}$ from the parent
-`Issuance Action`_, specify an Issue Note.
+The `IssueNoteDescription`_ encoding, together with
+$\mathsf{issuer}$ from the parent `Issuance Bundle`_ and $\mathsf{assetDescHash}$ from the parent
+`Issuance Action`_, specifies an Issue Note.
Let $\mathsf{Note^{Issue}}$ be the type of an Issue Note, i.e.
@@ -352,7 +352,8 @@ An issuance action, ``IssueAction``, is the instance of issuing a specific Custo
The $\mathsf{finalize}$ boolean is set by the Issuer to signal that there will be no further issuance of the specific Custom Asset.
As we will see in `Specification: Consensus Rule Changes`_, transactions that attempt to issue further amounts of a Custom Asset that has previously been finalized will be rejected.
-The complete encoding of these fields into an ``IssueAction`` is defined in ZIP 230 [#zip-0230-issuance-action-description]_.
+The complete encoding of these fields into an ``IssueAction`` is defined
+in `Issuance Action Description`_ below.
Issuance Bundle
@@ -366,8 +367,129 @@ It contains the following fields:
- ``vIssueActions``: an array of issuance actions, of type ``IssueAction``.
- ``issueAuthSig``: the encoding of a signature of the transaction SIGHASH, signed by the issuance authorizing key, $\mathsf{isk}$, that validates the issuance.
-The issuance bundle is added within the transaction format as a new bundle.
-The detailed encoding of the issuance bundle as a part of the V6 transaction format is defined in ZIP 230 [#zip-0230-transaction-format]_.
+The issuance bundle is added within the transaction format as a new bundle.
+The encoding of the issuance bundle's effecting and authorizing data is
+defined in `Changes to ZIP 248`_ below.
+
+This ZIP proposes to register the ZSA Issuance bundle type in the V6
+transaction bundle type registry defined in ZIP 248 [#zip-0248]_:
+
+Changes to ZIP 248
+``````````````````
+
++------------+----------------------+--------------------+------------------+--------------+
+| BundleType | ``mValuePoolDeltas`` | ``mEffectBundles`` | ``mAuthBundles`` | Bundle kind |
++============+======================+====================+==================+==============+
+| TBD |✅ |✅ |✅ | ZSA Issuance |
++------------+----------------------+--------------------+------------------+--------------+
+
+The ZSA Issuance bundle has value pool deltas (issuance adds value to the
+transparent transaction value pool for Custom Assets), effecting data (the
+issuance actions and issue notes), and authorizing data (the issuance
+authorization signature).
+
+.. _`Issuance Effecting Data`:
+
+Issuance Effecting Data
+'''''''''''''''''''''''
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| varies |``issuerLength`` |``compactSize`` |The length of the issuer identifier. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| ``issuerLength`` |``issuer`` |``byte[issuerLength]`` |The issuer identifier as defined in `Issuer Identifier`_. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``nIssueActions`` |``compactSize`` |The number of issuance actions in the bundle. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``vIssueActions`` |``IssueAction[nIssueActions]`` |A sequence of issuance action descriptions, encoded per |
+| | | |`Issuance Action Description`_. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+* The fields ``issuerLength``, ``issuer``, ``nIssueActions``, and
+ ``vIssueActions`` are always present.
+* If $\mathtt{nIssueActions} = 0$ then ``issuerLength`` MUST be set to $0$
+ (``issuer`` and ``vIssueActions`` will be empty in this case).
+
+.. _`Issuance Action Description`:
+
+Issuance Action Description (``IssueAction``)
+''''''''''''''''''''''''''''''''''''''''''''''
+
+An issuance action, ``IssueAction``, is the instance of issuing a specific
+Custom Asset, and contains the following fields:
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| 32 |``assetDescHash`` |``byte[32]`` |A hash of the description of the Custom Asset. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``nNotes`` |``compactSize`` |The number of notes in the Issuance Action. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 115 × ``nNotes`` |``vNotes`` |``IssueNoteDescription[nNotes]`` |A sequence of issue note descriptions within the Issuance Action. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 1 |``flagsIssuance`` |``byte`` |An 8-bit value representing a set of flags. Ordered from LSB to MSB: |
+| | | | |
+| | | |* :math:`\mathsf{finalize}` |
+| | | |* The remaining bits are set to :math:`0\!`. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+The encoding of ``IssueNoteDescription`` is described below.
+Note that we allow the number of notes (represented by ``nNotes``) to be zero.
+This allows for issuers to create Issuance Actions to only finalize an issued
+Asset, without needing them to simultaneously issue more of that Asset.
+
+.. _`IssueNoteDescription`:
+
+Issue Note Description (``IssueNoteDescription``)
+''''''''''''''''''''''''''''''''''''''''''''''''''
+
+An issuance note description, ``IssueNoteDescription``, contains the following
+fields:
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| 43 |``recipient`` |``byte[43]`` |The encoding of a recipient's diversified payment address, as |
+| | | |:math:`\mathsf{LEBS2OSP}_{88}(\mathsf{d})\| |
+| | | |\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_{\mathbb{P}} |
+| | | |(\mathsf{pk}_\mathsf{d}))\!`, where :math:`\mathsf{d}` is the |
+| | | |diversifier and :math:`\mathsf{pk_d}` is the diversified |
+| | | |transmission key. **Non Normative Note**: This is the same as the |
+| | | |encoding of an Orchard Raw Payment Address, as defined in |
+| | | |§5.6.4.2 'Orchard Raw Payment Addresses'. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 8 |``value`` |``uint64`` |The amount being issued in this note. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 32 |``rho`` |``byte[32]`` |This is defined and encoded in the same manner as for Orchard notes |
+| | | |in §3.2.1 'Note Plaintexts and Memo Fields'. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 32 |``rseed`` |``byte[32]`` |The ``rseed`` field of the note, encoded as for Orchard notes in |
+| | | |§3.2.1 'Note Plaintexts and Memo Fields'. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+.. _`Issuance Authorizing Data`:
+
+Issuance Authorizing Data
+'''''''''''''''''''''''''
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| varies |``sizeSighashInfo`` |``compactSize`` |The size in bytes of ``sighashInfo``. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| ``sizeSighashInfo`` |``sighashInfo`` |``byte[sizeSighashInfo]`` |The sighash version and associated information. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``sizeSignature`` |``compactSize`` |The size in bytes of ``signature``. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``signature`` |``byte[sizeSignature]`` |The signature of the transaction SIGHASH, signed by the issuer, |
+| | | |preceded by a ``0x00`` byte indicating a BIP 340 signature. It is |
+| | | |validated as specified in |
+| | | |`Issuance Authorization Signing and Validation`_. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+* The issuance authorizing data is present if and only if
+ $\mathtt{nIssueActions} > 0$.
Computation of ρ
----------------
@@ -409,7 +531,7 @@ For all actions ``IssueAction``:
- encode the ``IssueAction`` into the vector ``vIssueActions`` of the bundle.
-For the ``IssueBundle`` (see “ZSA Issuance Bundle Fields” in [#zip-0230-transaction-format]_):
+For the ``IssueBundle`` (see `Issuance Effecting Data`_):
- encode the ``vIssueActions`` vector.
- fill the ``issuerLength`` and ``issuer`` fields using $\mathsf{issuer}$.
@@ -487,7 +609,7 @@ If the transaction contains an issuance bundle:
- The issuance authorization signature, $\mathsf{issueAuthSig}$, MUST be a valid $\mathsf{IssueAuthSig}$ signature over $\mathsf{SigHash}$, i.e. $\mathsf{IssueAuthSig}.\!\mathsf{Validate}(\mathsf{ik}, \mathsf{SigHash}, \mathsf{issueAuthSig}) = 1$.
- For every issuance action description ($\mathsf{IssueAction}_\mathsf{i},\ 1 \leq i \leq \mathtt{nIssueActions}$) in the issuance bundle:
- - Every ``IssueNoteDescription`` in the ``IssueAction`` MUST be a valid field encoding as defined in ZIP 230 [#zip-0230-issue-note]_.
+ - Every ``IssueNoteDescription`` in the ``IssueAction`` MUST be a valid field encoding as defined in `IssueNoteDescription`_.
- Let an Issue Note (with type $\mathsf{Note^{Issue}}$) be constructed from the fields of each ``IssueNoteDescription``, with the $\mathsf{AssetBase}$ derived from the ``assetDescHash`` field of the ``IssueAction`` and the ``issuer`` field of the issuance bundle, as described in the `Specification: Asset Identifier, Asset Digest, and Asset Base`_ section.
- It MUST be the case that $\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{final} \neq 1$.
- If $\mathsf{issued\_assets}_{\mathsf{OUT}}(\mathsf{AssetBase}).\mathsf{note_{ref}} = \bot$, then let $\mathsf{new\_note_{ref}}$ be the first Issue Note in the Issuance Action.
@@ -593,12 +715,17 @@ Concrete Applications
-Modifications relative to ZIP 244 [#zip-0244]_
-==============================================
+Modifications to Digest Algorithms
+==================================
-Relative to the sighash algorithm defined in ZIP 244, the sighash algorithm
-that applies to v6 transactions differs by including the issuance bundle
-components within the tree hash. See ZIP 246 [#zip-0246]_ for details.
+The ZSA Issuance bundle contributes to the transaction identifier and signature
+digest via the ``effects_bundles_digest`` and ``auth_bundles_digest`` defined
+in ZIP 248 [#zip-0248]_.
+
+The issuance bundle's value pool deltas are committed via
+``value_pool_deltas_digest``. The issuance effecting data (issuance actions and
+issue notes) is committed via ``effects_bundles_digest``. The issuance
+authorization signature is committed via ``auth_bundles_digest``.
Changes to ZIP 317 [#zip-0317]_
@@ -692,11 +819,7 @@ References
.. [#zip-0226-assetburn] `ZIP 226: Transfer and Burn of Zcash Shielded Assets — Additional Consensus Rules for the assetBurn set `_
.. [#zip-0226-txiddigest] `ZIP 226: Transfer and Burn of Zcash Shielded Assets — TxId Digest `_
.. [#zip-0226-authcommitment] `ZIP 226: Transfer and Burn of Zcash Shielded Assets — Authorizing Data Commitment `_
-.. [#zip-0230-issuance-action-description] `ZIP 230: Version 6 Transaction Format — Issuance Action Description (IssueAction) `_
-.. [#zip-0230-issue-note] `ZIP 230: Version 6 Transaction Format — Issue Note Description (IssueNoteDescription) `_
-.. [#zip-0230-transaction-format] `ZIP 230: Version 6 Transaction Format — Transaction Format `_
-.. [#zip-0244] `ZIP 244: Transaction Identifier Non-Malleability `_
-.. [#zip-0246] `ZIP 246: Digests for the Version 6 Transaction Format `_
+.. [#zip-0248] `ZIP 248: Extensible Transaction Format `_
.. [#zip-0317] `ZIP 317: Proportional Transfer Fee Mechanism `_
.. [#zip-0317-fee-calculation] `ZIP 317: Proportional Transfer Fee Mechanism — Fee calculation `_
.. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_
diff --git a/zips/zip-0231.md b/zips/zip-0231.md
index 909ce8a4..43f1dbff 100644
--- a/zips/zip-0231.md
+++ b/zips/zip-0231.md
@@ -143,6 +143,149 @@ Since this proposal is defined only for v6 and later transactions, it is not
necessary to consider Sprout JoinSplit outputs. The following sections apply
to both Sapling and Orchard outputs.
+## Changes to ZIP 248
+
+This ZIP proposes to register the following bundle types in the V6 transaction
+bundle type registry defined in ZIP 248 [^zip-0248]:
+
+| BundleType | `mValuePoolDeltas` | `mEffectBundles` | `mAuthBundles` | Bundle kind |
+|------------|--------------------| -----------------|----------------|----------------------|
+| TBD |❌ |✅ |❌ | Memos |
+| TBD |✅ |✅ |✅ | Sapling-post-ZIP 231 |
+| TBD |✅ |✅ |✅ | Orchard-post-ZIP 231 |
+
+The Memos bundle has no value pool deltas (memo data does not involve value
+transfers) and no authorizing data. The effecting data consists of the encoded
+memo bundle as defined in [Encoding in transactions].
+
+If this ZIP is activated in the same network upgrade as ZIP 248, the encoding
+of the Sapling and Orchard bundles described in this ZIP will be used for
+bundle types 2 and 3, respectively, and ZIP 248's definition of the Sapling and
+Orchard bundles must be updated accordingly. If this ZIP is activated in a
+network upgrade AFTER the network upgrade in which ZIP 248 is activated, the
+encodings it describes will be assigned distinct bundle identifiers. In this
+latter case, a transaction MUST NOT contain both a Sapling-pre-ZIP 231 bundle
+and a Sapling-post-ZIP 231 bundle, or both an Orchard-pre-ZIP 231 bundle and an
+Orchard-post-ZIP 231 bundle.
+
+## Sapling-post-ZIP 231 Bundle
+
+The Sapling-post-ZIP 231 bundle replaces the Sapling bundle defined in
+ZIP 248 [^zip-0248]. The only change is that the note plaintext in each
+Sapling output is shortened: the 512-byte memo field is replaced by a
+32-byte $\mathsf{K^{memo}}$, reducing `encCiphertext` from 580 bytes to
+100 bytes.
+
+### Sapling-post-ZIP 231 Effecting Data
+
+The effecting data for the Sapling-post-ZIP 231 bundle describes the Sapling
+spends and outputs.
+
+| Bytes | Name | Data Type | Description |
+|--------------------------|--------------------|---------------------------------------------|------------------------------------------------------------------------------|
+| varies | `nSpendsSapling` | `compactSize` | Number of Sapling Spend descriptions. |
+| 96 \* nSpendsSapling | `vSpendsSapling` | `SaplingSpendEffecting[nSpendsSapling]` | Effecting data for each Sapling Spend. |
+| varies | `nOutputsSapling` | `compactSize` | Number of Sapling Output descriptions. |
+| 276 \* nOutputsSapling | `vOutputsSapling` | `SaplingOutputPostZIP231[nOutputsSapling]` | Sapling Output descriptions. |
+| 32 | `anchorSapling` | `byte[32]` | A root of the Sapling note commitment tree at some block height in the past. |
+
+* The field `anchorSapling` is present if and only if $\mathtt{nSpendsSapling} > 0$.
+
+`SaplingSpendEffecting` is unchanged from ZIP 248 [^zip-0248].
+
+#### SaplingOutputPostZIP231
+
+| Bytes | Name | Data Type | Description |
+|-------|-----------------|-------------|---------------------------------------------------------------------------------------------------------------------------|
+| 32 | `cv` | `byte[32]` | A value commitment to the net value of the output note. |
+| 32 | `cmu` | `byte[32]` | The $u$-coordinate of the note commitment for the output note. |
+| 32 | `ephemeralKey` | `byte[32]` | An encoding of an ephemeral Jubjub public key. |
+| 100 | `encCiphertext` | `byte[100]` | The encrypted contents of the note plaintext, which contains $\mathsf{K^{memo}}$ in place of the 512-byte memo field. |
+| 80 | `outCiphertext` | `byte[80]` | The encrypted contents of the byte string created by concatenation of the transmission key with the ephemeral secret key. |
+
+### Sapling-post-ZIP 231 Authorizing Data
+
+The authorizing data is unchanged from the Sapling bundle defined in
+ZIP 248 [^zip-0248].
+
+| Bytes | Name | Data Type | Description |
+|--------------------------|--------------------------|-----------------------------------|--------------------------------------------------------------|
+| 192 \* nSpendsSapling | `vSpendProofsSapling` | `byte[192 * nSpendsSapling]` | Encodings of the zk-SNARK proofs for each Sapling Spend. |
+| 64 \* nSpendsSapling | `vSpendAuthSigsSapling` | `byte[64 * nSpendsSapling]` | Authorizing signatures for each Sapling Spend. |
+| 192 \* nOutputsSapling | `vOutputProofsSapling` | `byte[192 * nOutputsSapling]` | Encodings of the zk-SNARK proofs for each Sapling Output. |
+| 64 | `bindingSigSapling` | `byte[64]` | A Sapling binding signature on the SIGHASH transaction hash. |
+
+* The values of `nSpendsSapling` and `nOutputsSapling` are not re-encoded in
+ the authorizing data; they are taken from the corresponding effecting data.
+* The field `bindingSigSapling` is present if and only if
+ $\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0$.
+* The elements of `vSpendProofsSapling` and `vSpendAuthSigsSapling` have a
+ 1:1 correspondence to the elements of `vSpendsSapling` in the effecting data
+ and MUST be ordered such that the element at a given index corresponds to the
+ `SaplingSpendEffecting` at the same index.
+* The elements of `vOutputProofsSapling` have a 1:1 correspondence to the
+ elements of `vOutputsSapling` in the effecting data and MUST be ordered such
+ that the proof at a given index corresponds to the `SaplingOutputPostZIP231`
+ at the same index.
+
+## Orchard-post-ZIP 231 Bundle
+
+The Orchard-post-ZIP 231 bundle replaces the Orchard bundle defined in
+ZIP 248 [^zip-0248]. As with Sapling, the only change is that the note
+plaintext in each Orchard action is shortened: the 512-byte memo field is
+replaced by a 32-byte $\mathsf{K^{memo}}$, reducing `encCiphertext` from
+580 bytes to 100 bytes.
+
+### Orchard-post-ZIP 231 Effecting Data
+
+The effecting data for the Orchard-post-ZIP 231 bundle describes the Orchard
+actions.
+
+| Bytes | Name | Data Type | Description |
+|--------------------------|--------------------|-------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
+| varies | `nActionsOrchard` | `compactSize` | The number of Orchard Action descriptions. |
+| 340 \* nActionsOrchard | `vActionsOrchard` | `OrchardActionPostZIP231[nActionsOrchard]` | Effecting data for each Orchard Action. |
+| 1 | `flagsOrchard` | `byte` | An 8-bit value representing a set of flags. Ordered from LSB to MSB: `enableSpendsOrchard`, `enableOutputsOrchard`. The remaining bits are set to $0$. |
+| 32 | `anchorOrchard` | `byte[32]` | A root of the Orchard note commitment tree at some block height in the past. |
+
+* The fields `flagsOrchard` and `anchorOrchard` are present if and only if
+ $\mathtt{nActionsOrchard} > 0$.
+* For coinbase transactions, the `enableSpendsOrchard` bit MUST be set to $0$.
+
+#### OrchardActionPostZIP231
+
+| Bytes | Name | Data Type | Description |
+|-------|-----------------|-------------|---------------------------------------------------------------------------------------------------------------------------|
+| 32 | `cv` | `byte[32]` | A value commitment to the net value of the input note minus the output note. |
+| 32 | `nullifier` | `byte[32]` | The nullifier of the input note. |
+| 32 | `rk` | `byte[32]` | The randomized validating key for this Action. |
+| 32 | `cmx` | `byte[32]` | The $x$-coordinate of the note commitment for the output note. |
+| 32 | `ephemeralKey` | `byte[32]` | An encoding of an ephemeral Pallas public key. |
+| 100 | `encCiphertext` | `byte[100]` | The encrypted contents of the note plaintext, which contains $\mathsf{K^{memo}}$ in place of the 512-byte memo field. |
+| 80 | `outCiphertext` | `byte[80]` | The encrypted contents of the byte string created by concatenation of the transmission key with the ephemeral secret key. |
+
+### Orchard-post-ZIP 231 Authorizing Data
+
+The authorizing data is unchanged from the Orchard bundle defined in
+ZIP 248 [^zip-0248].
+
+| Bytes | Name | Data Type | Description |
+|--------------------------|--------------------------|-----------------------------------|--------------------------------------------------------------------------------------------|
+| varies | `sizeProofsOrchard` | `compactSize` | Length in bytes of `proofsOrchard`. Value is $2720 + 2272 \cdot \mathtt{nActionsOrchard}$. |
+| sizeProofsOrchard | `proofsOrchard` | `byte[sizeProofsOrchard]` | Encoding of aggregated zk-SNARK proofs for Orchard Actions. |
+| 64 \* nActionsOrchard | `vSpendAuthSigsOrchard` | `byte[64 * nActionsOrchard]` | Authorizing signatures for each Orchard Action. |
+| 64 | `bindingSigOrchard` | `byte[64]` | An Orchard binding signature on the SIGHASH transaction hash. |
+
+* The value of `nActionsOrchard` is not re-encoded in the authorizing data; it
+ is taken from the corresponding effecting data.
+* The fields `sizeProofsOrchard`, `proofsOrchard`, and `bindingSigOrchard` are
+ present if and only if $\mathtt{nActionsOrchard} > 0$.
+* The proofs aggregated in `proofsOrchard`, and the elements of
+ `vSpendAuthSigsOrchard`, each have a 1:1 correspondence to the elements of
+ `vActionsOrchard` in the effecting data and MUST be ordered such that the
+ proof or signature at a given index corresponds to the
+ `OrchardActionPostZIP231` at the same index.
+
## Memo bundle
A memo bundle consists of a sequence of 272-byte memo chunks, each encrypting
@@ -254,6 +397,9 @@ followed by $\mathtt{0x01}$), ensuring that a malformed memo is not returned.
## Encoding in transactions
+The following describes the effecting data for the memo bundle. This data
+appears in `mEffectBundles` with the memo bundle type identifier.
+
| Bytes | Name | Data Type | Description |
|----------|------------------------|-----------------------------------------------------------|-----------------------------------------------------------------------|
| 1 | $\mathtt{fAllPruned}$ | $\mathtt{uint8}$ | 1 if all chunks have been pruned, otherwise 0. |
@@ -276,19 +422,28 @@ If $\mathtt{fAllPruned} = 0$, then:
If $\mathtt{fAllPruned} = 1$, then:
- $\mathtt{nonceOrHash}$ represents the overall hash for the memo bundle as defined in
- [Transaction sighash].
+ [Transaction Digest].
- The $\mathtt{nMemoChunks}$, $\mathtt{pruned}$, and $\mathtt{vMemoChunks}$ fields will be absent.
-## Transaction sighash
+## Transaction Digest
+
+The memo bundle contributes to the transaction identifier via the
+`effects_bundles_digest` defined in ZIP 248 [^zip-0248].
-$\mathsf{memo\_chunk\_digest}[i] = H(\mathtt{vMemoChunks}[i]) \\$
-$\mathsf{memo\_bundle\_digest} = H(\mathsf{concat}(\mathsf{memo\_chunk\_digests}))$
+The memo bundle's effect digest is computed as follows:
+
+$\mathsf{memo\_chunk\_digest}[i] = \mathsf{BLAKE2b\text{-}256}(\texttt{"ZTxIdMemoChunkHs"}, \mathtt{vMemoChunks}[i]) \\$
+$\mathsf{memo\_bundle\_digest} = \mathsf{BLAKE2b\text{-}256}(\texttt{"ZTxIdMemoBundHsh"}, \mathsf{concat}(\mathsf{memo\_chunk\_digests}))$
+
+For pruned chunks, the $\mathsf{memo\_chunk\_digest}$ stored in the transaction
+encoding is used directly.
The memo bundle digest structure is a performance optimization for the case
-where all memo chunks in a transaction have been pruned.
+where all memo chunks in a transaction have been pruned. When $\mathtt{fAllPruned} = 1$,
+the $\mathtt{nonceOrHash}$ field contains the pre-computed $\mathsf{memo\_bundle\_digest}$.
-TODO: finish this to be a modification to the equivalent of ZIP 244 for
-transaction v6.
+Since the memo bundle has no authorizing data, it does not contribute to the
+`auth_bundles_digest`.
## Changes to ZIP 317 [^zip-0317]
@@ -581,9 +736,11 @@ TBD
[^zip-0200]: [ZIP 200: Network Upgrade Mechanism](zip-0200.rst)
+[^zip-0248]: [ZIP 248: Extensible Transaction Format](zip-0248.rst)
+
[^draft-arya-deploy-nu7]: [draft-arya-deploy-nu7: Deployment of the NU7 Network Upgrade](draft-arya-deploy-nu7.md)
-[^zip-0230-orchard-note-plaintext]: [ZIP 230: Version 6 Transaction Format — Orchard Note Plaintext](zip-0230.rst#orchard-note-plaintext)
+[^zip-0230-note-plaintexts]: [ZIP 230: Version 6 Transaction Format — Note Plaintexts](zip-0230.rst#note-plaintexts)
[^zip-0302]: [ZIP 302: Standardized Memo Field Format](zip-0302.rst)
diff --git a/zips/zip-0233.md b/zips/zip-0233.md
index bca2ef1f..759e24ea 100644
--- a/zips/zip-0233.md
+++ b/zips/zip-0233.md
@@ -75,82 +75,83 @@ design shared by Bitcoin-like systems:
# Privacy Implications
-ZIP 233 adds a new type of transparent transaction event that is fully visible to chain
-observers, and linked to other events performed in the transaction. The removal of
-funds from circulation does not affect shielded outputs, and therefore does not alter
-the privacy properties of shielded funds.
+ZIP 233 adds a new type of transparent transaction event that is fully visible
+to chain observers, and linked to other events performed in the transaction.
+The removal of funds from circulation does represent a potential distinguisher;
+transactions that intentionally remove funds from circulation are likely to
+represent a small fraction of Zcash transactions, and so this will provide
+another tool that adversaries may use to be able to segment users of the
+network.
# Requirements
-- The mechanism enables users to remove funds from the circulating supply, and each removal event is explicitly specified in the corresponding transaction.
-- The process is publicly auditable, allowing network participants to verify the amount and occurrence of funds removed from circulation.
+- The mechanism enables users to remove funds from the circulating supply, and
+ each removal event is explicitly specified in the corresponding transaction.
+- The process is publicly auditable, allowing network participants to verify
+ the amount and occurrence of funds removed from circulation.
# Specification
-## Transaction Field
+## Changes to ZIP 248
-Each transaction gains a $\mathsf{zip233\_amount}$ property, specifying the
-value in zatoshis that is removed from circulation when the transaction is
-mined. The value removed from circulation subtracts from the remaining value in
-the "transparent transaction value pool" as described in § 3.4 ‘Transactions and
-Treestates’ [^protocol-transactions].
+This ZIP proposes to register bundle type 5 ("ZIP 233 NSM field") in the V6
+transaction bundle type registry defined in ZIP 248 [^zip-0248].
-$\mathsf{zip233\_amount}$ does not result in an output being produced in any
-chain value pool, and therefore from the point at which the transaction is
-applied to the global chain state, $\mathsf{zip233\_amount}$ is subtracted from
-the issued supply. It is unavailable for circulation on the network at least
-through to the end of the block in which the transaction is mined. ZIP 234
-[^zip-0234] specifies a potential mechanism by which the funds removed from
-circulation would again become available.
+| BundleType | `mValuePoolDeltas` | `mEffectBundles` | `mAuthBundles` |
+|------------|--------------------| -----------------|----------------|
+| 5 |✅ |❌ |❌ |
-## Changes to ZIP 230 [^zip-0230]
+The NSM bundle has no effecting data and no authorizing data. The amount to be
+removed from circulation is represented solely as an entry in `mValuePoolDeltas`
+with `bundleType = 5` and `assetClass = 0` (ZEC).
-The following field is appended to the Common Transaction Fields of the v6
-transaction format after `nExpiryHeight` [^zip-0230-transaction-format]:
+## NSM Amount
-| Bytes | Name | Data Type | Description |
-|-------|----------------|-----------|----------------------------------------------------------------------------|
-| 8 | `zip233Amount` | `uint64` | The value to be removed from circulation in this transaction, in zatoshis. |
+When the `mValuePoolDeltas` map contains an entry with `bundleType = 5`, the
+transaction removes funds from circulation. The entry's `value` field MUST BE
+nonpositive; its negation is denoted $\mathsf{zip233\_amount}$ and represents
+the value in zatoshis removed from circulation when the transaction is mined.
+If no such entry is present, $\mathsf{zip233\_amount}$ is defined to be 0.
-The $\mathsf{zip233\_amount}$ of a transaction is defined to be the value of the
-`zip233Amount` field if present, and otherwise 0.
-
-Notes:
-
-* If both this ZIP and ZIP 2002 are selected for inclusion in the same Network
- Upgrade, then the ordering of fields in the transaction format will be ``fee``
- and then ``zip233Amount``.
-* Older transaction versions can continue to be supported after a network
- upgrade, but removing funds from circulation is not possible for these
- transactions. For example, NU5 supports both v4 and v5 transaction formats,
- for both coinbase and non-coinbase transactions.
+The NSM bundle's effect on the transparent transaction value pool does not
+reflect an output being produced in any chain value pool. At the point at which
+the transaction is applied to the global chain state, $\mathsf{zip233\_amount}$
+is subtracted from the issued supply. It is unavailable for circulation on the
+network at least through to the end of the block in which the transaction is
+mined. ZIP 234 [^zip-0234] specifies a potential mechanism by which the funds
+removed from circulation would become available for reintroduction into the
+issued supply in subsequent blocks.
## Changes to the Zcash Protocol Specification
-Make a change to § 3.4 ‘Transactions and Treestates’ [^protocol-transactions]
-implementing the specification in [ZIP-233 Amount].
+Let $\mathsf{NSMBundleId} = 5.$
-In § 7.1 ‘Transaction Encoding and Consensus’ [^protocol-txnconsensus], add:
-
-> [NU7 onward] $\mathsf{zip233\_amount}$ MUST be in the range $\{ 0 .. \mathsf{MAX\_MONEY} \}$.
+Let $\mathsf{Zec}$ be the asset UUID for ZEC as defined in ZIP 248 [^zip-0248].
-In § 7.1.2 ‘Transaction Consensus Rules’ [^protocol-txnconsensus], add a note:
+Make a change to § 3.4 'Transactions and Treestates' [^protocol-transactions]
+adding the following consensus rules:
-> [NU7 onward] $\mathsf{zip233\_amount}$ does not result in an output being produced in any
-chain value pool.
+> * [NU7 onward] The `assetClass` for any entry in `mValuePoolDeltas` having
+> `bundleType` $= \mathsf{NSMBundleId}$ MUST be 0. That is, amounts to remove
+> from circulation MUST be denominated in ZEC.
+>
+> * [NU7 onward] The value of $\mathsf{mValuePoolDeltas}[(\mathsf{NSMBundleId}, \mathsf{Zec})]$,
+> if present, MUST be nonpositive. Its absolute value is $\mathsf{zip233\_amount}$.
+>
+> * [NU7 onward] $\mathsf{zip233\_amount}$ does not result in an output being
+> produced in any chain value pool.
-## Modifications relative to ZIP 244 [^zip-0244]
+In § 7.1 'Transaction Encoding and Consensus' [^protocol-txnconsensus], add:
-Relative to the sighash algorithm defined in ZIP 244, the sighash algorithm
-that applies to v6 transactions differs by appending the encoding of
-$\mathsf{zip233\_amount}$ to the Common Transaction Fields that are the input
-to the digest in T.1: `header_digest` [^zip-0244-t-1-header-digest]:
+> [NU7 onward] $\mathsf{zip233\_amount}$ MUST be in the range $\{ 0 .. \mathsf{MAX\_MONEY} \}$.
-> T.1f: zip233_amount (8-byte little-endian amount to remove from circulation)
+## Modifications to Digest Algorithms
-Note: If both this ZIP and ZIP 2002 are selected for inclusion in the same
-Network Upgrade, then the ambiguity in ordering of the fields added by these
-ZIPs would need to be resolved.
+The $\mathsf{zip233\_amount}$ is committed to the transaction identifier and
+signature digest via the `value_pool_deltas_digest` defined in ZIP 248 [^zip-0248].
+Since the NSM bundle (bundle type 5) has no effecting data and no authorizing
+data, its only contribution to the transaction digest is through its entry
+in `mValuePoolDeltas`.
## Applicability
@@ -192,14 +193,10 @@ This ZIP is proposed to activate with Network Upgrade 7. [^draft-arya-deploy-nu7
[^zip-0230]: [ZIP 230: Version 6 Transaction Format](zip-0230.rst)
-[^zip-0230-transaction-format]: [ZIP 230: Version 6 Transaction Format. Section 'Transaction Format'](zip-0230.rst#transaction-format)
-
[^zip-0234]: [ZIP 234: Network Sustainability Mechanism: Issuance Smoothing](zip-0234.rst)
[^zip-0235]: [ZIP 235: Remove 60% of Transaction Fees From Circulation](zip-0235.rst)
-[^zip-0244]: [ZIP 244: Transaction Identifier Non-Malleability](zip-0244.rst)
-
-[^zip-0244-t-1-header-digest]: [ZIP 244: Transaction Identifier Non-Malleability. Section T.1: header_digest](zip-0244.rst#t-1-header-digest)
+[^zip-0248]: [ZIP 248: Extensible Transaction Format](zip-0248.rst)
[^draft-arya-deploy-nu7]: [draft-arya-deploy-nu7: Deployment of the NU7 Network Upgrade](draft-arya-deploy-nu7.md)
diff --git a/zips/zip-0248.rst b/zips/zip-0248.rst
new file mode 100644
index 00000000..593a4ed4
--- /dev/null
+++ b/zips/zip-0248.rst
@@ -0,0 +1,1661 @@
+::
+
+ ZIP: 248
+ Title: Extensible Transaction Format
+ Owners: Jack Grigg
+ Kris Nuttycombe
+ Daira-Emma Hopwood
+ Schell Scivally
+ Status: Draft
+ Category: Consensus / Wallet
+ Created: 2025-12-17
+ License: MIT
+ Discussions-To:
+ Pull-Request:
+
+Terminology
+===========
+
+{Edit this to reflect the key words that are actually used.}
+The key words "MUST", "REQUIRED", "MUST NOT", "SHOULD", and "MAY" in this
+document are to be interpreted as described in BCP 14 [^BCP14] when, and only
+when, they appear in all capitals.
+
+The character § is used when referring to sections of the Zcash Protocol
+Specification. [#protocol]_
+
+The terms "Mainnet" and "Testnet" are to be interpreted as described in § 3.12
+‘Mainnet and Testnet’. [#protocol-networks]_
+
+The term "full validator" in this document is to be interpreted as defined in §
+3.3 ‘The Block Chain’. [#protocol-blockchain]_
+
+The terms below are to be interpreted as follows:
+
+transparent transaction value pool
+ An ephemeral value for the balance of an asset within the scope of a single
+ transaction, which is modified by additions and subtractions in the
+ processing of the effects of transaction bundles. When all of the effects of
+ a transaction are accounted for, each such balance is zero; i.e, the total of
+ additions to the balance equals the total of subtractions from it.
+
+
+Abstract
+========
+
+This ZIP proposes an encoding for V6 Zcash transactions that is intended to
+reduce the impact of future changes to the Zcash transaction format on the
+Zcash ecosystem. It defines a new typecode-length-value encoding for a sequence
+of protocol bundles, and a "value balance" map that describes the effect of
+each bundle on the transparent transaction value pool for each asset. The
+entries of this map serve the same purpose as the Sapling and Orchard value
+balance fields have done in the past.
+
+
+Motivation
+==========
+
+In the past, Zcash network upgrades that changed the transaction format have
+resulted in substantial disruption for wallets and other third-party clients in
+the Zcash ecosystem. In order to continue functioning after a network upgrade,
+clients were required to upgrade their Zcash transaction parsers to read the
+new format, even if the context in which those parsers were being used didn't
+need or couldn't make use of newly added transaction data. An example of this
+is that transparent-only wallets were forced to update their parsers to
+understand the Sapling and Orchard parts of transactions, even if they would
+never read or act upon those parts. This has led on occasion to significant
+problems in the Zcash ecosystem, including situations where funds have been
+locked and rendered unspendable from transparent-only wallets.
+
+For some kinds of changes to consensus features, it's imperative that every
+wallet be aware of and be adapted to those changes, and in those cases making a
+major (breaking) transaction version update as we've done in the past is
+appropriate. For many new features, however, it is possible for a wallet to
+continue functioning correctly without having to fully understand a transaction
+using that feature.
+
+For example, if TZEs were to be added to the protocol, it wouild be possible
+for wallets to continue operating with transparent/Sapling/Orchard
+functionality, ignoring TZE parts. There is substantial precedent for this sort
+of behavior; transparent-only hardware wallets are currently still important in
+the Zcash ecosystem, and many wallets didn't begin interacting with Orchard
+transaction parts until quite a while after Orchard activation.
+
+After this change to transaction encoding, wallets and other third parties will
+not be required to update their transaction parsers in advance of a network
+upgrade for the introduction of many (and perhaps most) types of new protocol
+features. This will enable the Zcash ecosystem to make smaller and more
+incremental network upgrades without breaking existing wallets.
+
+
+Privacy Implications
+====================
+
+This change alters the encoding of transactions, but does not alter the
+information content of the transaction. As such, the only implication of this
+change is that the use of this transaction format acts as a 1-bit distinguisher
+that reveals that the wallet that generated the transaction has been updated to
+be aware of the new format. This information leakage is unavoidable for any
+transaction format change.
+
+In the future, this change may reduce the amount of information leakage, since
+transactions created using the proposed TLV format will include bundles only
+for those protocols for which the transaction modifies chain state. For example,
+if this transaction format change is deployed in NU7 and NU8 defines a bundle
+type for TZE components, it will not be possible for a chain observer to
+distinguish whether or not the wallet that produced an Orchard-only transaction
+is one that has been updated to understand the TZE component. Under prior
+practices for changing the transaction format, this would have been
+distinguishable.
+
+In summary, this proposal provides a net improvement in user privacy in
+addition to its other benefits.
+
+
+Requirements
+============
+
+* The transaction format can be parsed without any knowledge of any Zcash
+ payment protocols.
+* Movement of value into and out of the transparent value pools (the ZEC
+ transparent value pool, plus the transparent value pool for each ZSA asset)
+ can be understood with only partial knowledge of the Zcash payment protocols.
+* The information content of transactions should not change as part of
+ this ZIP. Other ZIPs activated along with this ZIP may however make
+ use of it in introducing such changes.
+* It must be possible for wallets to parse any transaction that is valid within
+ a version group that it understands, even if it doesn't have handling for or
+ understand all of the bundle types that are valid for that version group. In
+ such a situation, however, such a wallet must still be able to accurately
+ describe any transparent movement of funds effected by the transaction, and
+ alert the user if the transaction contains bundles that it does not
+ understand.
+* It must be possible for a wallet to correctly construct and sign transactions
+ for a given transaction version group that it understands, even if it doesn't
+ have handling for or understand all of the bundle types that are valid for
+ transactions in that version group.
+
+
+Non-requirements
+================
+
+
+Specification
+=============
+
+Protocol Bundles
+----------------
+
+This ZIP refines and codifies the concept of "protocol bundles" that emerged
+from the implementation of the ZIP 225 [#zip-0225]_ transaction format. It
+makes bundles first-class objects and defines a registry of bundle type
+identifiers. Within the period that a given transaction format version is used
+on the Zcash network, the semantics of the bundle associated with a given
+bundle type identifier are fixed.
+
+A **protocol bundle** is a self-contained component of a transaction that
+implements a specific piece of protocol functionality. Each bundle type
+defines:
+
+* What **effecting data** the bundle contains — the data that determines what
+ state changes the bundle produces (e.g., which notes are spent, which outputs
+ are created, which transparent UTXOs are consumed or produced).
+
+* What **authorizing data** the bundle contains — the proofs and signatures
+ that authorize the state changes specified by the effecting data.
+
+* How the bundle affects the **transparent transaction value pool** — whether
+ the bundle adds value to, removes value from, or has no effect on this
+ ephemeral pool that balances value flows within a transaction.
+
+Rationale for Effecting Data and Authorizing Data
+`````````````````````````````````````````````````
+
+.. raw:: html
+
+
+ Click to show/hide
+
+The separation of effecting data from authorizing data serves several purposes:
+
+1. **Transaction identifier stability**: The transaction identifier (txid) is
+ computed only from the effecting data. This means that the txid is
+ determined by *what* the transaction does, not by *how* it is authorized.
+ Third parties cannot change a transaction's identifier by modifying
+ signatures or proofs.
+
+2. **Efficient pruning**: Full nodes that have validated a transaction may
+ prune the authorizing data while retaining the effecting data. Since
+ authorizing data appears at the end of the encoded transaction, pruning
+ is simply truncation.
+
+3. **Partial validation**: A wallet that does not understand a particular
+ bundle type can still compute the transaction identifier by hashing the
+ effecting data opaquely, without needing to parse its internal structure.
+
+.. raw:: html
+
+
+
+The Transparent Transaction Value Pool
+``````````````````````````````````````
+
+The transparent transaction value pool is an ephemeral concept that exists only
+within the scope of processing a single transaction. It serves as a balancing
+mechanism through which value flows between bundles.
+
+Each bundle may contribute a **value pool delta** — a signed value indicating
+how much the bundle adds to or removes from the transparent transaction value
+pool for a given asset. A positive delta means the bundle is adding value to
+the pool (e.g., a shielded spend releasing value), while a negative delta means
+the bundle is consuming value from the pool (e.g., a shielded output absorbing
+value, or a transaction fee).
+
+For a valid non-coinbase transaction, the sum of all value pool deltas for each
+asset MUST equal zero. This ensures that value is neither created nor destroyed
+— it is only transferred between bundles within the transaction.
+
+For a coinbase transaction, the sum of value pool deltas for ZEC equals the
+negative of the block subsidy, reflecting that the block subsidy implicitly
+adds value to the transparent transaction value pool.
+
+Bundle Type Registration
+````````````````````````
+
+When a ZIP introduces a new bundle type, it MUST:
+
+1. Request allocation of a bundle type identifier in the registry defined
+ below. The identifier must be a non-negative integer.
+
+2. Specify whether entries for this bundle type are permitted in
+ ``mValuePoolDeltas`` (the value pool delta map).
+
+3. Specify whether entries for this bundle type are permitted in
+ ``mEffectBundles`` (the effecting data map).
+
+4. Specify whether entries for this bundle type are permitted in
+ ``mAuthBundles`` (the authorizing data map).
+
+5. If effecting data is permitted, define the encoding of that data.
+
+6. If authorizing data is permitted, define the encoding of that data.
+
+7. Define the digest algorithm for the bundle's contribution to the transaction
+ identifier, if effecting data is present.
+
+8. Define the digest algorithm for the bundle's contribution to the authorizing
+ data commitment, if authorizing data is present.
+
+A bundle type MUST NOT permit entries in ``mAuthBundles`` unless it also permits
+entries in ``mEffectBundles``. That is, authorizing data cannot exist without
+corresponding effecting data for a given bundle type.
+
+Once a bundle type identifier is assigned for a given transaction version, its
+semantics are fixed for the lifetime of that transaction version. A subsequent
+network upgrade may define a new transaction version that reassigns identifiers
+or changes bundle semantics, but within a single transaction version, bundle
+type identifiers have stable, unchanging meanings.
+
+V6 Transaction Bundle Type Registry
+```````````````````````````````````
+
+The following integers are registered as bundle type identifiers for the V6
+transaction format. All currently-defined IDs are encoded as single-byte
+``compactSize`` values where they appear in the transaction format.
+
+The ``mValuePoolDeltas`` column indicates whether or not an entry for this
+bundle type MAY appear in ``mValuePoolDeltas``. For rows where an ❌
+is present, the value pool delta for every pool is guaranteed to be zero, and
+so entries in ``mValuePoolDeltas`` MUST NOT be present.
+
+The ``mEffectBundles`` column indicates whether or not an entry for this bundle
+type MAY appear in ``mEffectBundles``. For rows where an ❌ is present, the
+bundle has no effecting data, and so an entry in ``mEffectBundles`` MUST NOT
+be present.
+
+The ``mAuthBundles`` column indicates whether or not an entry for this bundle
+type MAY appear in ``mAuthBundles``. For rows where an ❌ is present, the
+bundle has no authorizing data, and so an entry in ``mAuthBundles`` MUST NOT
+be present.
+
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| BundleType | ``mValuePoolDeltas`` | ``mEffectBundles`` | ``mAuthBundles`` | Defining ZIP | Bundle kind |
++============+======================+====================+==================+==============+==============================================+
+| 0 |✅ |✅ |✅ | This ZIP | Transparent |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 1 | | | | | Reserved |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 2 |✅ |✅ |✅ | This ZIP | Sapling |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 3 |✅ |✅ |✅ | This ZIP | Orchard |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 4 |✅ |❌ |❌ | ZIP 2002 | Transaction fee |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 5 |✅ |❌ |❌ | ZIP 233 | ZIP 233 NSM field |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 6 |❌ |✅ |✅ | ZIP 270 | Key rotation |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| 7 |✅ |✅ |✅ | TBD | Lockbox disbursement |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| |❌ |✅ |❌ | ZIP 231 | Memos |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| |✅ |✅ |✅ | ZIP 231 | Sapling-post-ZIP 231 |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| |✅ |✅ |✅ | ZIP 231 | Orchard-post-ZIP 231 |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| |✅ |✅ |✅ | ZIP 227 | ZSA Issuance |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+| |✅ |✅ |✅ | ZIP 226 | OrchardZSA |
++------------+----------------------+--------------------+------------------+--------------+----------------------------------------------+
+
+Additional bundle types MAY be added to this registry via modifications to this
+ZIP specified in other ZIPs. Such modifications MUST specify all of the
+information required by the `Bundle Type Registration`_ section above.
+
+Potential Future Bundle Types
+`````````````````````````````
+
+.. raw:: html
+
+
+ Click to show/hide
+
+The following entries are provided to illustrate how potential future upgrades
+might affect the bundle registry:
+
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+| BundleType | ``mValuePoolDeltas`` | ``mEffectBundles`` | ``mAuthBundles`` | Bundle kind |
++============+======================+====================+==================+=============================================================+
+| |✅ |✅ |✅ | TZEs |
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+| |✅ |✅ |✅ | Pool that only has a long-term storage protocol (PQ, very |
+| | | | | simple thus insulated from counterfeiting fears, can be |
+| | | | | used for payments but higher latency for that purpose) |
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+| |✅ |✅ |✅ | Tachyon |
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+| |✅ |✅ |❌ | Staking |
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+| |✅ |✅ |✅ | Unstaking (if it can't be combined with the Staking bundle) |
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+| |✅ |✅ |✅ | Post-quantum fast payment protocol |
++------------+----------------------+--------------------+------------------+-------------------------------------------------------------+
+
+.. raw:: html
+
+
+
+Transaction Format
+------------------
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| **Common Transaction Fields** |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 4 |``header`` |``uint32`` |Contains: |
+| | | | |
+| | | |* ``fOverwintered`` flag (bit 31, always set) |
+| | | |* ``version`` (bits 30 .. 0) – transaction version. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 4 |``nVersionGroupId`` |``uint32`` |Version group ID (nonzero). |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 4 |``nConsensusBranchId`` |``uint32`` |Consensus branch ID (nonzero). |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 4 |``lock_time`` |``uint32`` |Unix-epoch UTC time or block height, encoded as in Bitcoin. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 4 |``nExpiryHeight`` |``uint32`` |A block height in the range {1 .. 499999999} after which |
+| | | |the transaction will expire, or 0 to disable expiry. [#zip-0203]_ |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| **Transaction transparent value pool balance map** |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``nValuePoolDeltas`` |``compactSize`` |Number of entries in the ``mValuePoolDeltas`` map. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``mValuePoolDeltas`` |``ValuePoolDelta[nValuePoolDeltas]`` |A map describing the change to the transparent value pool produced by|
+| | | |each bundle. Only bundles that produces changes to the transparent |
+| | | |value balance will have corresponding entries in this map. For |
+| | | |bundles that have no data except for a value, such as the ZIP 233 |
+| | | |amount, no additional bundle data will be present in the ``Bundles`` |
+| | | |section. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| **Bundles** |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``nEffectBundles`` |``compactSize`` |Number of bundles in the transaction that have per-bundle data. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``mEffectBundles`` |``BundleData[nEffectBundles]`` |A map from bundle identifier to the effecting data of a bundle. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``nAuthBundles`` |``compactSize`` |Number of bundles in the transaction that have per-bundle data. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``mAuthBundles`` |``BundleData[nAuthBundles]`` |A map from bundle identifier to the authorizing data of a bundle. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+``mEffectBundles`` and ``mAuthBundles`` are interpreted as maps keyed by
+bundle type. The entries in each map MUST be in increasing order of key.
+Each map MUST NOT contain more than a single entry for a given key. For each
+key that exists in ``mAuthBundles``, a corresponding entry must exist in
+``mEffectBundles``.
+
+ValuePoolDelta
+--------------
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| varies |``bundleType`` |``compactSize`` |An encoding of the bundle type identifier. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 1 |``assetClass`` |``uint8`` |An asset class identifier. 0x00 for the ZEC asset, 0x01 for other |
+| | | |assets. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| one of {0, 64} |``assetUuid`` |``byte[0] or byte[64]`` |If `assetClass == 0`, the zero-length byte array, otherwise a byte |
+| | | |array containing a universally unique 64-byte identifier for the |
+| | | |asset. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| 8 |``value`` |``nonzero int64`` |The net change to the transparent transaction value pool for the |
+| | | |given asset, produced by the bundle with this bundle type identifier.|
+| | | |This value MUST be nonzero; if a ``ValuePoolDelta`` record would |
+| | | |have zero value, it MUST be elided from the encoding |
+| | | |of ``mValuePoolDeltas`` instead. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+``mValuePoolDeltas`` is interpreted as a map keyed by the tuple
+$(\mathsf{BundleType}, \mathsf{AssetUuid}).$ The map MUST NOT contain more than
+a single entry for a given key. Lookups in this map are denoted with the
+syntax $\mathsf{mValuePoolDeltas}[(\mathsf{BundleType}, \mathsf{AssetUuid})].$
+
+Let $\mathsf{Zec}$ be a distinguished value representing the ZEC asset. It is
+used as the asset identifier when $\mathsf{assetClass} = 0$.
+
+Let $\mathsf{AssetUuid}(\mathsf{d})$ be the asset indicated by the ``mValuePoolDeltas`` entry $\mathsf{d}.$
+
+.. math::
+
+ \mathsf{AssetUuid}(\mathsf{d}) =
+ \begin{cases}
+ \mathsf{Zec} & \text{if } \mathsf{d}.\mathsf{assetClass} = 0 \\
+ \mathsf{d}.\mathsf{assetUuid} & \text{if } \mathsf{d}.\mathsf{assetClass} = 1 \\
+ \bot & \text{otherwise}
+ \end{cases}
+
+BundleData
+----------
+
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==============================+================================================+=====================================================================+
+| varies |``bundleType`` |``compactSize`` |An encoding of the bundle type identifier. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``nBundleDataLen`` |``compactSize`` |The length of the ``vBundleData`` byte array. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+| varies |``vBundleData`` |``byte[nBundleDataLen]`` |The effecting or authorizing data for the bundle, dependent upon |
+| | | |whether the ``BundleData`` occurs in ``mEffectBundles`` or |
+| | | |``mAuthBundles``. |
++-----------------------------+------------------------------+------------------------------------------------+---------------------------------------------------------------------+
+
+
+Transparent Bundle
+------------------
+
+Transparent Effecting Data
+``````````````````````````
+
+The effecting data for the transparent bundle describes the transparent inputs
+being spent and the transparent outputs being created.
+
++-----------------------------+--------------------------+------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+==========================================+=====================================================================+
+|``varies`` |``tx_in_count`` |``compactSize`` |Number of transparent inputs. |
++-----------------------------+--------------------------+------------------------------------------+---------------------------------------------------------------------+
+|``varies`` |``tx_in_effecting`` |``TransparentInputEffecting[tx_in_count]``|Effecting data for each transparent input. |
++-----------------------------+--------------------------+------------------------------------------+---------------------------------------------------------------------+
+|``varies`` |``tx_out_count`` |``compactSize`` |Number of transparent outputs. |
++-----------------------------+--------------------------+------------------------------------------+---------------------------------------------------------------------+
+|``varies`` |``tx_out`` |``TransparentOutput[tx_out_count]`` |Transparent outputs. |
++-----------------------------+--------------------------+------------------------------------------+---------------------------------------------------------------------+
+
+TransparentInputEffecting
+'''''''''''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``32`` |``prevout_hash`` |``byte[32]`` |The transaction ID of the output being spent. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``4`` |``prevout_index`` |``uint32`` |The index of the output being spent within that transaction. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``4`` |``nSequence`` |``uint32`` |Sequence number, encoded as in Bitcoin. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+TransparentOutput
+'''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``8`` |``value`` |``int64`` |The value of the output in zatoshi. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``varies`` |``scriptPubKeyLen`` |``compactSize`` |Length of the scriptPubKey. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``scriptPubKeyLen`` |``scriptPubKey`` |``byte[scriptPubKeyLen]`` |The script that must be satisfied to spend this output. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+Transparent Authorizing Data
+````````````````````````````
+
+The authorizing data for the transparent bundle contains the scripts that
+authorize spending of the referenced transparent inputs.
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``varies`` |``tx_in_auth`` |``TransparentInputAuth[tx_in_count]`` |Authorizing data for each transparent input. The number of entries |
+| | | |MUST equal ``tx_in_count`` from the effecting data. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+TransparentInputAuth
+''''''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``varies`` |``scriptSigLen`` |``compactSize`` |Length of the scriptSig. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``scriptSigLen`` |``scriptSig`` |``byte[scriptSigLen]`` |The script satisfying the conditions of the referenced output's |
+| | | |scriptPubKey. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+
+Sapling Bundle
+--------------
+
+Sapling Effecting Data
+``````````````````````
+
+The effecting data for the Sapling bundle describes the Sapling spends and
+outputs. Unlike the V5 transaction format defined in ZIP 225 [#zip-0225]_,
+the value balance is not included here; it appears in ``mValuePoolDeltas``
+instead.
+
++-----------------------------+--------------------------+-----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+=========================================+=====================================================================+
+|``varies`` |``nSpendsSapling`` |``compactSize`` |Number of Sapling Spend descriptions. |
++-----------------------------+--------------------------+-----------------------------------------+---------------------------------------------------------------------+
+|``96 * nSpendsSapling`` |``vSpendsSapling`` |``SaplingSpendEffecting[nSpendsSapling]``|Effecting data for each Sapling Spend. |
++-----------------------------+--------------------------+-----------------------------------------+---------------------------------------------------------------------+
+|``varies`` |``nOutputsSapling`` |``compactSize`` |Number of Sapling Output descriptions. |
++-----------------------------+--------------------------+-----------------------------------------+---------------------------------------------------------------------+
+|``756 * nOutputsSapling`` |``vOutputsSapling`` |``SaplingOutput[nOutputsSapling]`` |Sapling Output descriptions. |
++-----------------------------+--------------------------+-----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``anchorSapling`` |``byte[32]`` |A root of the Sapling note commitment tree at some block height |
+| | | |in the past. |
++-----------------------------+--------------------------+-----------------------------------------+---------------------------------------------------------------------+
+
+* The field ``anchorSapling`` is present if and only if $\mathtt{nSpendsSapling} > 0$.
+
+SaplingSpendEffecting
+'''''''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the input note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``nullifier`` |``byte[32]`` |The nullifier of the input note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``rk`` |``byte[32]`` |The randomized validating key for this Spend. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+SaplingOutput
+'''''''''''''
+
+This is identical to ``OutputDescriptionV5`` as defined in ZIP 225 [#zip-0225]_.
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the output note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``cmu`` |``byte[32]`` |The :math:`u\!`-coordinate of the note commitment for the output |
+| | | |note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Jubjub public key. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``580`` |``encCiphertext`` |``byte[580]`` |The encrypted contents of the note plaintext. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by concatenation |
+| | | |of the transmission key with the ephemeral secret key. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+Sapling Authorizing Data
+````````````````````````
+
+The authorizing data for the Sapling bundle contains the proofs and signatures
+that authorize the spends and validate the outputs.
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``192 * nSpendsSapling`` |``vSpendProofsSapling`` |``byte[192 * nSpendsSapling]`` |Encodings of the zk-SNARK proofs for each Sapling Spend. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``64 * nSpendsSapling`` |``vSpendAuthSigsSapling`` |``byte[64 * nSpendsSapling]`` |Authorizing signatures for each Sapling Spend. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``192 * nOutputsSapling`` |``vOutputProofsSapling`` |``byte[192 * nOutputsSapling]`` |Encodings of the zk-SNARK proofs for each Sapling Output. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``64`` |``bindingSigSapling`` |``byte[64]`` |A Sapling binding signature on the SIGHASH transaction hash. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+* The values of ``nSpendsSapling`` and ``nOutputsSapling`` are not re-encoded in
+ the authorizing data; they are taken from the corresponding effecting data.
+
+* The field ``bindingSigSapling`` is present if and only if
+ $\mathtt{nSpendsSapling} + \mathtt{nOutputsSapling} > 0$.
+
+* The elements of ``vSpendProofsSapling`` and ``vSpendAuthSigsSapling`` have a
+ 1:1 correspondence to the elements of ``vSpendsSapling`` in the effecting data
+ and MUST be ordered such that the element at a given index corresponds to the
+ ``SaplingSpendEffecting`` at the same index.
+
+* The elements of ``vOutputProofsSapling`` have a 1:1 correspondence to the
+ elements of ``vOutputsSapling`` in the effecting data and MUST be ordered such
+ that the proof at a given index corresponds to the ``SaplingOutput`` at the
+ same index.
+
+
+Orchard Bundle
+--------------
+
+Orchard Effecting Data
+``````````````````````
+
+The effecting data for the Orchard bundle describes the Orchard actions. Unlike
+the V5 transaction format defined in ZIP 225 [#zip-0225]_, the value balance is
+not included here; it appears in ``mValuePoolDeltas`` instead.
+
++-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+===========================================+=====================================================================+
+|``varies`` |``nActionsOrchard`` |``compactSize`` |The number of Orchard Action descriptions. |
++-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
+|``820 * nActionsOrchard`` |``vActionsOrchard`` |``OrchardActionEffecting[nActionsOrchard]``|Effecting data for each Orchard Action. |
++-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
+|``1`` |``flagsOrchard`` |``byte`` |An 8-bit value representing a set of flags. Ordered from LSB to MSB: |
+| | | | |
+| | | |* ``enableSpendsOrchard`` |
+| | | |* ``enableOutputsOrchard`` |
+| | | |* The remaining bits are set to :math:`0\!`. |
++-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
+|``32`` |``anchorOrchard`` |``byte[32]`` |A root of the Orchard note commitment tree at some block height |
+| | | |in the past. |
++-----------------------------+--------------------------+-------------------------------------------+---------------------------------------------------------------------+
+
+* The fields ``flagsOrchard`` and ``anchorOrchard`` are present if and only if
+ $\mathtt{nActionsOrchard} > 0$.
+
+* For coinbase transactions, the ``enableSpendsOrchard`` bit MUST be set to $0$.
+
+OrchardActionEffecting
+''''''''''''''''''''''
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``32`` |``cv`` |``byte[32]`` |A value commitment to the net value of the input note minus the |
+| | | |output note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``nullifier`` |``byte[32]`` |The nullifier of the input note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``rk`` |``byte[32]`` |The randomized validating key for this Action. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``cmx`` |``byte[32]`` |The :math:`x\!`-coordinate of the note commitment for the output |
+| | | |note. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``32`` |``ephemeralKey`` |``byte[32]`` |An encoding of an ephemeral Pallas public key. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``580`` |``encCiphertext`` |``byte[580]`` |The encrypted contents of the note plaintext. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``80`` |``outCiphertext`` |``byte[80]`` |The encrypted contents of the byte string created by concatenation |
+| | | |of the transmission key with the ephemeral secret key. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+Orchard Authorizing Data
+````````````````````````
+
+The authorizing data for the Orchard bundle contains the proofs and signatures
+that authorize the actions.
+
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+| Bytes | Name | Data Type | Description |
++=============================+==========================+========================================+=====================================================================+
+|``varies`` |``sizeProofsOrchard`` |``compactSize`` |Length in bytes of ``proofsOrchard``. Value is |
+| | | |:math:`2720 + 2272 \cdot \mathtt{nActionsOrchard}\!`. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``sizeProofsOrchard`` |``proofsOrchard`` |``byte[sizeProofsOrchard]`` |Encoding of aggregated zk-SNARK proofs for Orchard Actions. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``64 * nActionsOrchard`` |``vSpendAuthSigsOrchard`` |``byte[64 * nActionsOrchard]`` |Authorizing signatures for each Orchard Action. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+|``64`` |``bindingSigOrchard`` |``byte[64]`` |An Orchard binding signature on the SIGHASH transaction hash. |
++-----------------------------+--------------------------+----------------------------------------+---------------------------------------------------------------------+
+
+* The value of ``nActionsOrchard`` is not re-encoded in the authorizing data; it
+ is taken from the corresponding effecting data.
+
+* The fields ``sizeProofsOrchard``, ``proofsOrchard``, and ``bindingSigOrchard``
+ are present if and only if $\mathtt{nActionsOrchard} > 0$.
+
+* The proofs aggregated in ``proofsOrchard``, and the elements of
+ ``vSpendAuthSigsOrchard``, each have a 1:1 correspondence to the elements of
+ ``vActionsOrchard`` in the effecting data and MUST be ordered such that the
+ proof or signature at a given index corresponds to the
+ ``OrchardActionEffecting`` at the same index.
+
+
+Consensus Rules
+---------------
+
+This ZIP requires the following modifications to the consensus rules in the
+Zcash Protocol Specification.
+
+Let ``FeeBundleId`` be the identifier of the fee bundle. In V6 transactions,
+$\mathsf{FeeBundleId} = 4$ as defined in the table above.
+
+The following transaction validity rules are added:
+
+* The ``assetClass`` value for any entry in ``mValuePoolDeltas`` having
+ ``bundleType = FeeBundleId`` is 0 (fee amounts are denominated in ZEC
+ and no other asset.)
+
+* For coinbase transactions, the value of $\mathsf{mValuePoolDeltas}[(\mathsf{FeeBundleId}, \mathsf{Zec})]$
+ must be nonnegative. This represents the total transaction fees collected from
+ all other transactions in the block.
+
+* For non-coinbase transactions, the value of $\mathsf{mValuePoolDeltas}[(\mathsf{FeeBundleId}, \mathsf{Zec})]$
+ must be nonpositive. This represents the transaction fee paid by the
+ transaction (expressed as a negative value, since it is removed from the
+ transparent transaction value pool).
+
+* Within the scope of a block, the sum of the fee bundle values must equal 0.
+ That is, the fees collected by the coinbase transaction must equal the sum of
+ fees paid by all other transactions in the block.
+
+* Certain bundle types are mutually exclusive: a transaction MUST NOT contain
+ more than one bundle from each of the following sets:
+
+ * {Sapling, Sapling-post-ZIP-231}
+ * {Orchard, Orchard-post-ZIP-231, OrchardZSA}
+
+* For the coinbase transaction, the sum of value pool deltas in the ZEC asset
+ is equal to the negative of the block subsidy for that block; the block
+ subsidy adds an implicit input value to the transparent transaction value
+ pool that the coinbase outputs consume.
+
+ .. math::
+
+ \sum_{\mathsf{d} \in \mathsf{mValuePoolDeltas} | \mathsf{AssetUuid}(\mathsf{d}) = \mathsf{Zec}} \mathsf{d.value} = -\mathsf{BlockSubsidy}(\mathsf{height})
+
+ where $\mathsf{BlockSubsidy}$ is defined in § 7.8 'Block Subsidy and
+ Founders' Reward'. [#protocol-subsidies]_
+
+* For all non-coinbase transactions, the sum of value pool delta values in each
+ asset equals 0.
+
+ .. math::
+
+ \forall \mathsf{a}. \sum_{\mathsf{d} \in \mathsf{mValuePoolDeltas} | \mathsf{AssetUuid}(\mathsf{d}) = \mathsf{a}} \mathsf{d.value} = 0
+
+Digest Algorithms
+-----------------
+
+All digests are personalized BLAKE2b-256 hashes. In cases where no elements are
+available for hashing (for example, if there are no transparent transaction
+inputs), a personalized hash of the empty byte array will be used. The
+personalization string therefore provides domain separation for the hashes of
+even empty data fields.
+
+The notation ``BLAKE2b-256(personalization_string, [])`` is used to refer to
+hashes constructed in this manner.
+
+TxId Digest
+```````````
+
+A new transaction digest algorithm is defined that constructs the identifier for
+a V6 transaction from a tree of hashes. The overall structure of the hash is as
+follows::
+
+ txid_digest
+ ├── header_digest
+ ├── value_pool_deltas_digest
+ └── effects_bundles_digest
+ ├─ (bundle_type_id || transparent_effects_digest)
+ ├─ (bundle_type_id || sapling_effects_digest)
+ │ ├── sapling_spends_digest
+ │ │ ├── sapling_spends_compact_digest
+ │ │ └── sapling_spends_noncompact_digest
+ │ └── sapling_outputs_digest
+ │ ├── sapling_outputs_compact_digest
+ │ ├── sapling_outputs_memos_digest
+ │ └── sapling_outputs_noncompact_digest
+ ├─ (bundle_type_id || orchard_effects_digest)
+ │ ├── orchard_actions_compact_digest
+ │ ├── orchard_actions_memos_digest
+ │ └── orchard_actions_noncompact_digest
+ └─ (bundle_type_id || unknown_bundle_effects_digest) ...
+
+Each node written as ``snake_case`` in this tree is a BLAKE2b-256 hash of its
+children, initialized with a personalization string specific to that branch
+of the tree. Nodes that are not themselves digests are written in ``camelCase``.
+In the specification below, nodes of the tree are presented in depth-first order.
+
+txid_digest
+'''''''''''
+
+A BLAKE2b-256 hash of the following values::
+
+ T.1: header_digest (32-byte hash output)
+ T.2: value_pool_deltas_digest (32-byte hash output)
+ T.3: effects_bundles_digest (32-byte hash output)
+
+The personalization field of this hash is set to::
+
+ "ZcashTxHash_" || CONSENSUS_BRANCH_ID
+
+``ZcashTxHash_`` has 1 underscore character.
+
+As in ZIP 143 [#zip-0143]_, CONSENSUS_BRANCH_ID is the 4-byte little-endian
+encoding of the consensus branch ID for the epoch of the block containing the
+transaction.
+
+T.1: header_digest
+''''''''''''''''''
+
+A BLAKE2b-256 hash of the following values::
+
+ T.1a: version (4-byte little-endian version identifier including overwintered flag)
+ T.1b: version_group_id (4-byte little-endian version group identifier)
+ T.1c: consensus_branch_id (4-byte little-endian consensus branch id)
+ T.1d: lock_time (4-byte little-endian nLockTime value)
+ T.1e: expiry_height (4-byte little-endian block height)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdHeadersHash"
+
+T.2: value_pool_deltas_digest
+'''''''''''''''''''''''''''''
+
+A BLAKE2b-256 hash of the concatenated encodings of all entries in
+``mValuePoolDeltas``, in increasing order of ``(bundleType, assetClass, assetUuid)``.
+For each entry, the following values are concatenated::
+
+ T.2a: bundleType (compactSize encoding)
+ T.2b: assetClass (1 byte)
+ T.2c: assetUuid (0 or 64 bytes, depending on assetClass)
+ T.2d: value (8-byte signed little-endian)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdVPDeltaHash"
+
+In the case that the transaction has no value pool delta entries (which would
+only occur for transactions that have no effect on any value pool),
+``value_pool_deltas_digest`` is::
+
+ BLAKE2b-256("ZTxIdVPDeltaHash", [])
+
+T.3: effects_bundles_digest
+'''''''''''''''''''''''''''
+
+A BLAKE2b-256 hash of the concatenated tagged bundle effect digests for all
+bundles present in ``mEffectBundles``, in increasing order of ``bundleType``. For each
+bundle, the following values are concatenated::
+
+ T.3a: bundleType (compactSize encoding)
+ T.3b: bundle_effects_digest (32-byte hash output)
+
+where ``bundle_effects_digest`` is the root hash of the bundle's effecting data
+tree, as defined below for each known bundle type.
+
+The personalization field of this hash is set to::
+
+ "ZTxIdEffBndHash"
+
+In the case that the transaction has no effect bundles, ``effects_bundles_digest``
+is::
+
+ BLAKE2b-256("ZTxIdEffBndHash", [])
+
+For bundle types not recognized by a wallet, the wallet MUST be provided with the
+32-byte ``bundle_effects_digest`` value in order to compute the transaction
+identifier. This enables partial verification of transactions containing unknown
+bundle types.
+
+T.3.0: transparent_effects_digest
+.................................
+
+In the case that transparent inputs or outputs are present, the transparent
+effects digest is a BLAKE2b-256 hash of the following values::
+
+ T.3.0a: prevouts_digest (32-byte hash)
+ T.3.0b: sequence_digest (32-byte hash)
+ T.3.0c: outputs_digest (32-byte hash)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdTranspaHash"
+
+In the case that the transaction has no transparent components,
+``transparent_effects_digest`` is::
+
+ BLAKE2b-256("ZTxIdTranspaHash", [])
+
+T.3.0a: prevouts_digest
+~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the field encoding of all ``(prevout_hash, prevout_index)``
+pairs from the transparent effecting data.
+
+The personalization field of this hash is set to::
+
+ "ZTxIdPrevoutHash"
+
+In the case that the transaction has transparent outputs but no transparent
+inputs, ``prevouts_digest`` is::
+
+ BLAKE2b-256("ZTxIdPrevoutHash", [])
+
+T.3.0b: sequence_digest
+~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the 32-bit little-endian representation of all ``nSequence``
+field values from the transparent effecting data.
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSequencHash"
+
+In the case that the transaction has transparent outputs but no transparent
+inputs, ``sequence_digest`` is::
+
+ BLAKE2b-256("ZTxIdSequencHash", [])
+
+T.3.0c: outputs_digest
+~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the concatenated field encodings of all transparent
+outputs. The field encoding of each output consists of the encoded output
+``value`` (8-byte little endian) followed by the ``scriptPubKey`` byte array
+(with leading ``compactSize`` length).
+
+The personalization field of this hash is set to::
+
+ "ZTxIdOutputsHash"
+
+In the case that the transaction has transparent inputs but no transparent
+outputs, ``outputs_digest`` is::
+
+ BLAKE2b-256("ZTxIdOutputsHash", [])
+
+T.3.2: sapling_effects_digest
+.............................
+
+In the case that Sapling spends or outputs are present, the Sapling effects
+digest is a BLAKE2b-256 hash of the following values::
+
+ T.3.2a: sapling_spends_digest (32-byte hash)
+ T.3.2b: sapling_outputs_digest (32-byte hash)
+ T.3.2c: anchorSapling (32 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSaplingHash"
+
+Note that unlike ZIP 244, the value balance is not included here; it is committed
+via ``value_pool_deltas_digest`` instead.
+
+In the case that the transaction has no Sapling spends or outputs,
+``sapling_effects_digest`` is::
+
+ BLAKE2b-256("ZTxIdSaplingHash", [])
+
+T.3.2a: sapling_spends_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the case that Sapling spends are present, this digest is a BLAKE2b-256 hash
+of the following values::
+
+ T.3.2a.i: sapling_spends_compact_digest (32-byte hash)
+ T.3.2a.ii: sapling_spends_noncompact_digest (32-byte hash)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSSpendsHash"
+
+In the case that the transaction has Sapling outputs but no Sapling spends,
+``sapling_spends_digest`` is::
+
+ BLAKE2b-256("ZTxIdSSpendsHash", [])
+
+T.3.2a.i: sapling_spends_compact_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the field encoding of all ``nullifier`` field values
+of Sapling spends belonging to the transaction.
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSSpendCHash"
+
+T.3.2a.ii: sapling_spends_noncompact_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the non-nullifier information for all Sapling spends
+belonging to the transaction. For each spend, the following elements are
+included in the hash::
+
+ T.3.2a.ii.1: cv (32 bytes)
+ T.3.2a.ii.2: anchor (32 bytes)
+ T.3.2a.ii.3: rk (32 bytes)
+
+The anchor is hashed for *each* spend (even though it is shared in the encoding).
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSSpendNHash"
+
+T.3.2b: sapling_outputs_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the case that Sapling outputs are present, this digest is a BLAKE2b-256 hash
+of the following values::
+
+ T.3.2b.i: sapling_outputs_compact_digest (32-byte hash)
+ T.3.2b.ii: sapling_outputs_memos_digest (32-byte hash)
+ T.3.2b.iii: sapling_outputs_noncompact_digest (32-byte hash)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSOutputHash"
+
+In the case that the transaction has Sapling spends but no Sapling outputs,
+``sapling_outputs_digest`` is::
+
+ BLAKE2b-256("ZTxIdSOutputHash", [])
+
+T.3.2b.i: sapling_outputs_compact_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the subset of Sapling output information included in the
+ZIP 307 [#zip-0307]_ ``CompactBlock`` format for all Sapling outputs belonging
+to the transaction. For each output, the following elements are included::
+
+ T.3.2b.i.1: cmu (32 bytes)
+ T.3.2b.i.2: ephemeralKey (32 bytes)
+ T.3.2b.i.3: encCiphertext[..52] (first 52 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSOutC__Hash" (2 underscore characters)
+
+T.3.2b.ii: sapling_outputs_memos_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the memo field data for all Sapling outputs belonging to
+the transaction. For each output::
+
+ T.3.2b.ii.1: encCiphertext[52..564] (512 bytes, encrypted memo)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSOutM__Hash" (2 underscore characters)
+
+T.3.2b.iii: sapling_outputs_noncompact_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the remaining Sapling output information not included in
+the ``CompactBlock`` format. For each output::
+
+ T.3.2b.iii.1: cv (32 bytes)
+ T.3.2b.iii.2: encCiphertext[564..] (post-memo AEAD tag, 16 bytes)
+ T.3.2b.iii.3: outCiphertext (80 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdSOutN__Hash" (2 underscore characters)
+
+T.3.3: orchard_effects_digest
+.............................
+
+In the case that Orchard actions are present, the Orchard effects digest is a
+BLAKE2b-256 hash of the following values::
+
+ T.3.3a: orchard_actions_compact_digest (32-byte hash)
+ T.3.3b: orchard_actions_memos_digest (32-byte hash)
+ T.3.3c: orchard_actions_noncompact_digest (32-byte hash)
+ T.3.3d: flagsOrchard (1 byte)
+ T.3.3e: anchorOrchard (32 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdOrchardHash"
+
+Note that unlike ZIP 244, the value balance is not included here; it is committed
+via ``value_pool_deltas_digest`` instead.
+
+In the case that the transaction has no Orchard actions, ``orchard_effects_digest``
+is::
+
+ BLAKE2b-256("ZTxIdOrchardHash", [])
+
+T.3.3a: orchard_actions_compact_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the subset of Orchard action information intended for
+inclusion in the ``CompactBlock`` format. For each action::
+
+ T.3.3a.i: nullifier (32 bytes)
+ T.3.3a.ii: cmx (32 bytes)
+ T.3.3a.iii: ephemeralKey (32 bytes)
+ T.3.3a.iv: encCiphertext[..52] (first 52 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdOrcActCHash"
+
+T.3.3b: orchard_actions_memos_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the memo field data for all Orchard actions. For each
+action::
+
+ T.3.3b.i: encCiphertext[52..564] (512 bytes, encrypted memo)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdOrcActMHash"
+
+T.3.3c: orchard_actions_noncompact_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A BLAKE2b-256 hash of the remaining Orchard action information not intended for
+inclusion in the ``CompactBlock`` format. For each action::
+
+ T.3.3c.i: cv (32 bytes)
+ T.3.3c.ii: rk (32 bytes)
+ T.3.3c.iii: encCiphertext[564..] (post-memo AEAD tag, 16 bytes)
+ T.3.3c.iv: outCiphertext (80 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdOrcActNHash"
+
+Signature Digest
+````````````````
+
+A new per-input transaction digest algorithm is defined that constructs a hash
+that may be signed by a transaction creator to commit to the effects of the
+transaction. This follows closely the algorithm from ZIP 244 [#zip-0244]_.
+
+For transactions that have no transparent inputs, the signature digest is
+identical to the transaction identifier digest.
+
+For transactions with transparent inputs, the signature digest replaces
+``effects_bundles_digest`` with a ``signature_bundles_digest`` that incorporates
+``hash_type``-dependent transparent signing data::
+
+ signature_digest
+ ├── header_digest
+ ├── value_pool_deltas_digest
+ └── signature_bundles_digest
+
+signature_digest
+''''''''''''''''
+
+A BLAKE2b-256 hash of the following values::
+
+ S.1: header_digest (32-byte hash output)
+ S.2: value_pool_deltas_digest (32-byte hash output)
+ S.3: signature_bundles_digest (32-byte hash output)
+
+The personalization field of this hash is set to::
+
+ "ZcashTxHash_" || CONSENSUS_BRANCH_ID
+
+This value has the same personalization as the transaction identifier digest,
+so that what is being signed in the case that there are no transparent inputs
+is exactly the transaction id.
+
+S.3: signature_bundles_digest
+'''''''''''''''''''''''''''''
+
+If the transaction has no transparent inputs, ``signature_bundles_digest`` is
+identical to ``effects_bundles_digest``.
+
+Otherwise, ``signature_bundles_digest`` is constructed the same as
+``effects_bundles_digest``, except that ``transparent_effects_digest`` is
+replaced with ``transparent_sig_digest``.
+
+S.3.0: transparent_sig_digest
+.............................
+
+This digest is a BLAKE2b-256 hash of the following values::
+
+ S.3.0a: hash_type (1 byte)
+ S.3.0b: prevouts_sig_digest (32-byte hash)
+ S.3.0c: amounts_sig_digest (32-byte hash)
+ S.3.0d: scriptpubkeys_sig_digest (32-byte hash)
+ S.3.0e: sequence_sig_digest (32-byte hash)
+ S.3.0f: outputs_sig_digest (32-byte hash)
+ S.3.0g: txin_sig_digest (32-byte hash)
+
+The personalization field of this hash is set to::
+
+ "ZTxIdTranspaHash"
+
+S.3.0a: hash_type
+~~~~~~~~~~~~~~~~~
+
+An 8-bit unsigned value. The ``SIGHASH`` encodings from the legacy script system
+are used: one of ``SIGHASH_ALL`` (0x01), ``SIGHASH_NONE`` (0x02), or
+``SIGHASH_SINGLE`` (0x03), optionally combined with ``SIGHASH_ANYONECANPAY`` (0x80).
+
+The following restrictions apply:
+
+- Using any undefined ``hash_type`` (not 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83)
+ causes validation failure.
+- Using ``SIGHASH_SINGLE`` without a corresponding output at the same index
+ causes validation failure.
+
+For signatures over Sapling Spends or Orchard Actions, ``hash_type`` is set to
+``SIGHASH_ALL`` (0x01).
+
+S.3.0b: prevouts_sig_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the ``SIGHASH_ANYONECANPAY`` flag is not set, identical to ``prevouts_digest``
+(T.3.0a).
+
+Otherwise::
+
+ BLAKE2b-256("ZTxIdPrevoutHash", [])
+
+S.3.0c: amounts_sig_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the ``SIGHASH_ANYONECANPAY`` flag is not set, a BLAKE2b-256 hash of the
+concatenation of the 8-byte signed little-endian representations of all ``value``
+fields for the coins spent by the transparent inputs to the transaction.
+
+The personalization field of this hash is set to::
+
+ "ZTxTrAmountsHash"
+
+If the ``SIGHASH_ANYONECANPAY`` flag is set::
+
+ BLAKE2b-256("ZTxTrAmountsHash", [])
+
+S.3.0d: scriptpubkeys_sig_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the ``SIGHASH_ANYONECANPAY`` flag is not set, a BLAKE2b-256 hash of the
+concatenation of the field encodings (each including a leading ``compactSize``)
+of all ``scriptPubKey`` fields for the coins spent by the transparent inputs.
+
+The personalization field of this hash is set to::
+
+ "ZTxTrScriptsHash"
+
+If the ``SIGHASH_ANYONECANPAY`` flag is set::
+
+ BLAKE2b-256("ZTxTrScriptsHash", [])
+
+S.3.0e: sequence_sig_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Identical to ``sequence_digest`` (T.3.0b) regardless of ``hash_type``.
+
+S.3.0f: outputs_sig_digest
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the sighash type is neither ``SIGHASH_SINGLE`` nor ``SIGHASH_NONE``, identical
+to ``outputs_digest`` (T.3.0c).
+
+If the sighash type is ``SIGHASH_SINGLE`` and a transparent output exists at the
+same index as the input being signed, a hash of that output's encoding.
+
+Otherwise::
+
+ BLAKE2b-256("ZTxIdOutputsHash", [])
+
+S.3.0g: txin_sig_digest
+~~~~~~~~~~~~~~~~~~~~~~~
+
+For signatures over a transparent input, a BLAKE2b-256 hash of::
+
+ S.3.0g.i: prevout (36 bytes: 32-byte hash + 4-byte index)
+ S.3.0g.ii: value (8-byte signed little-endian)
+ S.3.0g.iii: scriptPubKey (with compactSize length prefix)
+ S.3.0g.iv: nSequence (4-byte unsigned little-endian)
+
+The personalization field of this hash is set to::
+
+ "Zcash___TxInHash" (3 underscores)
+
+For signatures over a Sapling Spend or Orchard Action::
+
+ BLAKE2b-256("Zcash___TxInHash", [])
+
+Authorizing Data Commitment
+```````````````````````````
+
+A transaction digest algorithm is defined that constructs a digest committing to
+the authorizing data of a transaction. The overall structure is::
+
+ auth_digest
+ └── auth_bundles_digest
+ ├─ (bundle_type_id || transparent_auth_digest)
+ ├─ (bundle_type_id || sapling_auth_digest)
+ ├─ (bundle_type_id || orchard_auth_digest)
+ └─ (bundle_type_id || unknown_bundle_auth_digest) ...
+
+auth_digest
+'''''''''''
+
+A BLAKE2b-256 hash of the following value::
+
+ A.1: auth_bundles_digest (32-byte hash output)
+
+The personalization field of this hash is set to::
+
+ "ZTxAuthHash_" || CONSENSUS_BRANCH_ID
+
+For transaction versions before V6, a placeholder value consisting of 32 bytes
+of ``0xFF`` is used in place of the authorizing data commitment.
+
+A.1: auth_bundles_digest
+''''''''''''''''''''''''
+
+A BLAKE2b-256 hash of the concatenated tagged bundle auth digests for all
+bundles present in ``mAuthBundles``, in increasing order of ``bundleType``. For each
+bundle, the following values are concatenated::
+
+ A.1a: bundleType (compactSize encoding)
+ A.1b: bundle_auth_digest (32-byte hash output)
+
+The personalization field of this hash is set to::
+
+ "ZTxAuthBndHash"
+
+In the case that the transaction has no auth bundles, ``auth_bundles_digest`` is::
+
+ BLAKE2b-256("ZTxAuthBndHash", [])
+
+A.1.0: transparent_auth_digest
+..............................
+
+In the case that the transaction contains transparent inputs, this is a
+BLAKE2b-256 hash of the concatenated ``scriptSig`` values (each with leading
+``compactSize`` length) for all transparent inputs.
+
+The personalization field of this hash is set to::
+
+ "ZTxAuthTransHash"
+
+In the case that the transaction has no transparent inputs::
+
+ BLAKE2b-256("ZTxAuthTransHash", [])
+
+A.1.2: sapling_auth_digest
+..........................
+
+In the case that Sapling spends or outputs are present, this is a BLAKE2b-256
+hash of the following concatenated values::
+
+ A.1.2a: vSpendProofsSapling (192 bytes per spend)
+ A.1.2b: vSpendAuthSigsSapling (64 bytes per spend)
+ A.1.2c: vOutputProofsSapling (192 bytes per output)
+ A.1.2d: bindingSigSapling (64 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxAuthSapliHash"
+
+In the case that the transaction has no Sapling spends or outputs::
+
+ BLAKE2b-256("ZTxAuthSapliHash", [])
+
+A.1.3: orchard_auth_digest
+..........................
+
+In the case that Orchard actions are present, this is a BLAKE2b-256 hash of the
+following concatenated values::
+
+ A.1.3a: proofsOrchard (aggregated proofs)
+ A.1.3b: vSpendAuthSigsOrchard (64 bytes per action)
+ A.1.3c: bindingSigOrchard (64 bytes)
+
+The personalization field of this hash is set to::
+
+ "ZTxAuthOrchaHash"
+
+In the case that the transaction has no Orchard actions::
+
+ BLAKE2b-256("ZTxAuthOrchaHash", [])
+
+
+Rationale
+=========
+
+TODO: Document why we take the specific approach we do on what the format
+constrains vs what wallets are expected (required?) to notify users of (once we
+decide on the approach).
+
+Effecting data bundles and authorizing data bundles are stored separately in
+the transaction format so that the authorizing data may be pruned by
+straightforward truncation of the encoded representation of the transaction.
+
+
+Deployment
+==========
+
+
+Reference implementation
+========================
+
+
+Open issues
+===========
+
+Notes from design sessions
+==========================
+
+This section should be removed as soon as all the considerations described here
+are accounted for in ZIP.
+
+Wallets or consensus-dependent applications that send transactions, might do
+something wrong that compromises user funds or privacy if they do not take into
+account consensus changes in an upgrade; therefore, only a subset of consensus
+changes can be safely adapted to using this mechanism.
+
+In particular, consensus rules may change in such a way that a wallet doing
+what it has done in the past causes risk of loss of funds.
+
+An example of this was ZIP 212 [#zip-0212]_. In that case
+the existing mechanisms failed to prevent loss of funds because in practice,
+wallets updated the consensus branch ID without updating note encryption. We
+made the mistake of requiring wallets to change their behaviour for an existing
+transaction version. Except for certain cases involving severe security flaws,
+we should avoid doing that again.
+
+If a wallet needs to actively do something differently (for example,
+advertizing addresses in a new format or creating an output with a TZE
+precondition) in order to be affected by a new feature, then it is reasonably
+safe for it to ignore the feature as long as it can still parse transactions
+and, and create and sign transactions that don't make use of those features.
+
+It is okay that such a wallet might not be able to see funds that depend on new
+features, as long as they do not create such funds themselves.
+
+Loss of funds is unacceptable. Temporary inaccessibility of funds in certain
+circumstances can be okay -- provided that this potential inaccessiblity and
+the circumstances where it can occur is documented and an explicit design
+decision.
+
+Strawman
+--------
+
+Modify how we approach transaction format evolution, such that (after one more
+change to transaction encoding) it is possible for a wallet that has not
+adopted a parser for a given transaction format to continue to function after
+an *additive* change to the transaction format. Another way to state this is
+that we should make it possible to make "semver-compatible" transaction format
+changes.
+
+* @str4d: We could use a TLV approach where each "bundle" has a value balance.
+ The NSM burn amount field could be its own bundle, the explicit fee data
+ could be its own bundle and the consensus rule could be that all value
+ balances sum to zero.
+
+ * generically, you want a value balance vector, where you have zero or more
+ value balances moving between bundles in other assets.
+
+* @nuttycom: You could have pre-ZSA and post-ZSA Orchard bundles.
+
+Strawman II
+-----------
+
+Treat bundles as individually versioned.
+
+* Each bundle is registered with an ID relative to a tx version group ID.
+* The bundle ID encoding also has some flag bits indicating how it interacts
+ with the tx as a whole.
+* Transactions then have two "bundle maps":
+
+ * The first encodes how value moves between the different bundles.
+ * The second encodes data specific to a bundle (e.g. how value moves within a bundle)
+ * Bundles that don't have any data would just appear in the first map, and
+ bundles that don't produce or consume value would just appear in the
+ second map.
+* We can re-interpret various other facets of transactions as "bundles"
+
+ * Explicit fees are a bundle that never produces value
+ * NSM field similarly never produces value
+ * ZSA burns would be split into "value balance out of Orchard pool" and
+ "value balance being removed from ZSA issuance"
+ * See also the conversation we had about refactoring coinbase transactions.
+ TODO: Figure out how to integrate the two.
+* Privacy effect is minimal
+
+ * We already follow a bundle approach with a transparent transaction value
+ pool, for the turnstiles. This leans into it, while preserving the bundle
+ boundary within which we implement each privacy protocol.
+ * Some combinations of bundles would be permitted by the tx format that
+ were not previously permitted.
+
+ * However, we can still restrict which combinations of bundles can be
+ mined in the consensus rules.
+
+Sketch of the format:
+
+* Transaction version (like now)
+
+ * Version
+ * Version group ID
+
+* Transaction header
+
+ * Expiry height etc
+ * Likely need some kind of key-value map here to allow additional fields to
+ be added, or maybe version the header to allow evolution?
+
+* Transparent transaction value pool "traffic map"
+
+ * Option 1: BundleVersionID -> (valueBalance, AssetId -> valueBalance)
+
+ * Key: Bundle version ID
+ * Value:
+
+ * ZEC `valueBalance`
+ * CompactSize len(generalizedValueBalances)
+ * Zero or more generalized value balances
+
+ * `AssetId` (not `AssetBase` because those are
+ protocol-specific, and we want generalized value balances to
+ be understandable independently of protocol changes)
+ * `valueBalance`
+
+ * Option 2: (BundleVersionID, Option[AssetId]) -> valueBalance
+
+ * Key: Bundle version ID encoded as u8 || { Option[AssetId] }
+ * Value: `valueBalance`
+
+ * Option 3: BundleVersionID -> Option[AssetId] -> valueBalance
+
+ * Key: Bundle version ID
+ * Value:
+
+ * Map containing one or more generalized value balances
+
+ * { Option[AssetId] }
+ * `valueBalance`
+* Sequence of bundles (maybe with a length prefix?)
+
+ * Bundle version ID
+
+ * Maybe flag bits, either in the version ID or next to it, that
+ indicate how an opaquely-parsing wallet should interpret the bundle,
+ e.g.:
+
+ * A bit that says whether or not the bundle interacts with the
+ transparent transaction value pool (which memo bundles would not
+ have).
+
+ * Counterpoint: The traffic map already specifies whether a
+ given bundle *does* have an interaction with the transparent
+ tx value pool for this tx. This is different from whether
+ that kind of bundle *can* interact with the transparent tx
+ value pool, but it the latter needed?
+
+ * A bit that says whether the bundle has any other effect than what
+ is specified in the traffic map.
+
+ * Counterpoint: We should split apart effecting and authorizing
+ data in the encoding, and then a bundle must be assumed
+ effecting iff it has non-null effecting data.
+
+ * CompactSize len(effectingData)
+
+ * effectingData
+
+ * CompactSize len(authorizingData)
+
+ * authorizingData
+
+ * effectingData and authorizingData would be opaque to the initial
+ parser.
+ * Parsers that support parsing (tx_version, bundle_version) know how to
+ interpret its internals
+
+Questions
+---------
+
+* Is it okay for fee calculations to be opaque to wallet parsers, as long as
+ the fee amounts can be calculated in consensus?
+
+ * Yes:
+
+ * When receiving, all you care about is knowing the actual fee amount;
+ you see that in the fee bundle's value balance.
+ * When sending, you need to understand all bundles you are including,
+ and then you can calculate the fee.
+
+* Can wallets still compute the txid and wtxid of an arbitrary transaction?
+
+ * Yes, provided that effecting and authorizing data is separated. Then they
+ can hash the effecting data even without understanding it to compute the
+ txid, and they can hash the authorizing data even without understanding
+ it to compute the authorizing data commitment part of the wtxid (ZIP
+ 239 [#zip-0239]_).
+ * *However*, this reintroduces a more direct linkage between the [w]txid
+ computation and the transaction encoding. It's arguably fine, and
+ potentially simpler -- since the [w]txid computation need not change at
+ all for most protocol changes.
+ * If the hashing uses flat hashes over the effectingData and
+ authorizingData of each bundle (which it has to because the internal
+ structure is not known), then it might be more difficult to do Merkle
+ proofs over subsets of the data within a bundle. We haven't used that so
+ far; is it really needed?
+
+ * Should the authorizing data be entirely separate from the effecting data,
+ and encoded at the end of the transaction in a batch, so that pruning is
+ simply truncation?
+
+* The light wallet protocol will be updated to allow the client to specify the
+ set of bundle types that the client understands. In the case that this
+ information is provided, the light client server will then send the root
+ hashes for each bundle type that the client **does not** understand when
+ returning raw transaction data, so that the light client can correctly
+ recompute and validate the txid; also, the compact transactions can be pruned
+ to exclude bundles of bundle types. that the client will not understand.
+
+TODO
+====
+
+Rename ``assetDigest`` to ``assetUuid`` in ZIP 227
+
+
+References
+==========
+
+.. [#BCP14] `Information on BCP 14 — "RFC 2119: Key words for use in RFCs to Indicate Requirement Levels" and "RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words `_
+.. [#protocol] `Zcash Protocol Specification, Version 2025.6.3 [NU6.1] or later `_
+.. [#protocol-blockchain] `Zcash Protocol Specification, Version 2025.6.3 [NU6.1]. Section 3.3: The Block Chain `_
+.. [#protocol-networks] `Zcash Protocol Specification, Version 2025.6.3 [NU6.1]. Section 3.12: Mainnet and Testnet `_
+.. [#protocol-subsidies] `Zcash Protocol Specification, Version 2025.6.3 [NU6.1]. Section 7.8: Block Subsidy and Founders' Reward `_
+.. [#zip-0143] `ZIP 143: Transaction Signature Validation for Overwinter `_
+.. [#zip-0203] `ZIP 203: Transaction Expiry `_
+.. [#zip-0212] `ZIP 212: Allow Recipient to Derive Ephemeral Secret from Note Plaintext `_
+.. [#zip-0225] `ZIP 225: Version 5 Transaction Format `_
+.. [#zip-0239] `ZIP 239: Relay of Version 5 Transactions `_
+.. [#zip-0244] `ZIP 244: Transaction Identifier Non-Malleability `_
+.. [#zip-0307] `ZIP 307: Light Client Protocol for Payment Detection `_
+
diff --git a/zips/zip-2002.rst b/zips/zip-2002.rst
index 803454e5..67e6a98d 100644
--- a/zips/zip-2002.rst
+++ b/zips/zip-2002.rst
@@ -32,10 +32,12 @@ The terms "Mainnet" and "Testnet" are to be interpreted as described in
Abstract
========
-This proposal adds an explicit ``fee`` field to the v6 transaction format.
-Instead of fees being implicit in the difference between the input value and
-output value of the transaction, all value transfers, including fee transfers to
-miners, will be explicit and committed to via the txid.
+This proposal makes the transaction fee explicit in the v6 transaction format,
+as an entry in the transparent transaction value pool balance map defined in
+ZIP 248 [#zip-0248]_. Instead of fees being implicit in the difference between
+the input value and output value of the transaction, all value transfers,
+including fee transfers to miners, will be explicit and committed to via the
+txid.
Motivation
@@ -68,53 +70,65 @@ needed to compute it.
Specification
=============
-Changes to ZIP 230 [#zip-0230]_
--------------------------------
+Changes to ZIP 248
+------------------
-The following field is appended to the Common Transaction Fields of the v6
-transaction format after ``nExpiryHeight`` [#zip-0230-transaction-format]_:
+This ZIP proposes to register bundle type 4 ("Transaction fee") in the V6
+transaction bundle type registry defined in ZIP 248 [#zip-0248]_.
-+-------+---------+------------+------------------------------------------------------+
-| Bytes | Name | Data Type | Description |
-+=======+=========+============+======================================================+
-| 8 | ``fee`` | ``uint64`` | The fee to be paid by this transaction, in zatoshis. |
-+-------+---------+------------+------------------------------------------------------+
++------------+----------------------+--------------------+------------------+
+| BundleType | ``mValuePoolDeltas`` | ``mEffectBundles`` | ``mAuthBundles`` |
++============+======================+====================+==================+
+| 4 |✅ |❌ |❌ |
++------------+----------------------+--------------------+------------------+
-Note: If both this ZIP and ZIP 233 are selected for inclusion in the same
-Network Upgrade, then the ordering of fields in the transaction format will
-be ``fee`` and then ``zip233Amount``.
+The fee bundle has no effecting data and no authorizing data. The transaction
+fee is represented solely as an entry in ``mValuePoolDeltas`` with
+``bundleType = 4`` and ``assetClass = 0`` (ZEC).
+
+For non-coinbase transactions, the ``value`` field of this entry MUST be
+nonpositive, representing the fee being removed from the transparent
+transaction value pool. For coinbase transactions, the ``value`` field MUST be
+nonnegative, representing the total fees collected from other transactions in
+the block being added to the ZEC transparent transaction value pool.
Changes to the Zcash Protocol Specification
-------------------------------------------
-In § 3.4 ‘Transactions and Treestates’ [#protocol-transactions]_ (last modified by
-ZIP 236 [#zip-0236]_), add the following consensus rule and note:
+Let $\mathsf{FeeBundleId} = 4.$
+
+Let $\mathsf{Zec}$ be the asset UUID for ZEC as defined in ZIP 248 [#zip-0248]_.
+
+In § 3.4 'Transactions and Treestates' [#protocol-transactions]_ (last modified by
+ZIP 236 [#zip-0236]_), add the following consensus rules:
- * [NU7 onward] For v6 and later transactions, the remaining value in the
- transparent transaction value pool, in zatoshis, MUST be equal to the value
- of the transaction’s ``fee`` field.
-
- Non-normative note: The effect of these rules is that the ``fee`` field of
- v6 and later coinbase transactions will always be zero.
+ * [NU7 onward] The ``assetClass`` for any entry in ``mValuePoolDeltas`` having
+ ``bundleType`` $= \mathsf{FeeBundleId}$ MUST be 0. That is, fee amounts MUST
+ be denominated in ZEC.
-In § 7.1 ‘Transaction Encoding and Consensus’ [#protocol-txnconsensus]_, add:
+ * [NU7 onward] For v6 and later non-coinbase transactions, the value of
+ $\mathsf{mValuePoolDeltas}[(\mathsf{FeeBundleId}, \mathsf{Zec})]$ MUST be
+ nonpositive. Its absolute value represents the transaction fee in zatoshis.
- [NU7 onward] ``fee`` MUST be in the range $\{ 0 .. \mathsf{MAX\_MONEY} \}$.
+ * [NU7 onward] For v6 and later coinbase transactions, the value of
+ $\mathsf{mValuePoolDeltas}[(\mathsf{FeeBundleId}, \mathsf{Zec})]$ MUST be
+ nonnegative. It represents the total transaction fees collected from all
+ other transactions in the block.
+In § 7.1 'Transaction Encoding and Consensus' [#protocol-txnconsensus]_, add:
-Modifications relative to ZIP 244 [#zip-0244]_
-----------------------------------------------
+ [NU7 onward] The absolute value of the fee bundle's value pool delta MUST
+ be in the range $\{ 0 .. \mathsf{MAX\_MONEY} \}$.
-Relative to the sighash algorithm defined in ZIP 244, the sighash algorithm
-that applies to v6 transactions differs by appending the ``fee`` field to
-the Common Transaction Fields that are the input to the digest in
-T.1: header_digest [#zip-0244-header-digest]_::
- T.1f: fee (8-byte little-endian fee amount)
+Modifications to Digest Algorithms
+----------------------------------
-Note: If both this ZIP and ZIP 233 are selected for inclusion in the same
-Network Upgrade, then the ambiguity in ordering of the fields added by these
-ZIPs would need to be resolved.
+The fee amount is committed to the transaction identifier and signature
+digest via the ``value_pool_deltas_digest`` defined in ZIP 248 [#zip-0248]_.
+Since the fee bundle (bundle type 4) has no effecting data and no authorizing
+data, its only contribution to the transaction digest is through its entry
+in ``mValuePoolDeltas``.
Applicability
@@ -147,8 +161,5 @@ References
.. [#bitcointalk-fee-error] `Bitcoin Forum post by @Voiceeeeee, March 8, 2017. "PLEASE HELP.. I sent a transaction with a 2.5 BTC transaction fee" `_
.. [#zip-0200] `ZIP 200: Network Upgrade Mechanism `_
.. [#zip-0230] `ZIP 230: Version 6 Transaction Format `_
-.. [#zip-0230-transaction-format] `ZIP 230: Version 6 Transaction Format — Specification: Transaction Format `_
.. [#zip-0236] `ZIP 236: Blocks should balance exactly `_
-.. [#zip-0244] `ZIP 244: Transaction Identifier Non-Malleability `_
-.. [#zip-0244-header-digest] `ZIP 244: Transaction Identifier Non-Malleability. Section T.1: Header Digest `_
-.. [#zip-0246] `ZIP 246: Digests for the Version 6 Transaction Format `_
+.. [#zip-0248] `ZIP 248: Extensible Transaction Format `_