-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ZSA integration (step 3): Add initial Transaction V6 support to Zebra (currently copies V5 behavior) #16
base: zsa-integration-zsadeps
Are you sure you want to change the base?
Conversation
This commit introduces basic support for Transaction version 6 (Tx V6). This initial implementation treats Tx V6 as a simple copy of Tx V5, without yet integrating ZSA-specific features or the new transaction structure. - Added a new V6 variant to the Transaction enum in the zebra-chain crate. - Updated relevant code to handle the new V6 variant. Note: Tests and additional adjustments are still pending, and will be addressed in subsequent commits.
…py V5 behaviour for now)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added some comments
/// Orchard transactions must use transaction version 5 and this version | ||
/// group ID. | ||
// FIXME: use a proper value! | ||
pub const TX_V6_VERSION_GROUP_ID: u32 = 0x26A7_270B; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use a random number in the meanwhile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: It's 0x124A69F8
in zcash_primitives
, if that was random, let's use that so it won't need an update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Temporarily changed to 0x7777_7777 to align with the a new value used in librustzcash (zcash_primitives) and test vectors. Kept a FIXME comment to change it in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Temporarily changed to 0x124A_69F8 to align with the a value used in OLD version of librustzcash (zcash_primitives) and test vectors. Kept a FIXME comment to change it in the future.
@@ -142,6 +142,28 @@ pub enum Transaction { | |||
/// The orchard data for this transaction, if any. | |||
orchard_shielded_data: Option<orchard::ShieldedData>, | |||
}, | |||
// FIXME: implement V6 properly (now it's just a coipy of V5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a copy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the changed-files
and codespell
lint jobs from here may be trivial and help catch typos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
@@ -142,6 +142,28 @@ pub enum Transaction { | |||
/// The orchard data for this transaction, if any. | |||
orchard_shielded_data: Option<orchard::ShieldedData>, | |||
}, | |||
// FIXME: implement V6 properly (now it's just a coipy of V5) | |||
/// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanille, Sapling and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which supports OrchardZSA, Orchard, Sapling ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
// FIXME: implement V6 properly (now it's just a coipy of V5) | ||
/// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanille, Sapling and | ||
/// transparent, but not Sprout. | ||
V6 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we put this behind a feature flag?
(this and all subsequent V6 handling)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in #37.
} | ||
| Transaction::V6 { | ||
sapling_shielded_data: None, | ||
.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's simplify the entire function:
/// Access the deduplicated [`sapling::tree::Root`]s in this transaction,
/// regardless of version.
pub fn sapling_anchors(&self) -> Box<dyn Iterator<Item = sapling::tree::Root> + '_> {
// This function returns a boxed iterator because the different
// transaction variants end up having different iterator types
match self {
Transaction::V4 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
Transaction::V5 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
Transaction::V6 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
// No Spends (V1, V2, V3 and V4, V5, V6 without sapling shielded data)
_ => Box::new(iter::empty()),
}
}
(x4 for all sapling functions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arya2 what do you think about this simplification across the entire file?
This will significantly reduce boilerplate without affecting semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The simplification looks nice, I'd lean towards whatever's easiest since it all needs to be refactored to a new-type around the zcash_primitives
Transaction
type soon, and if there's no difference in difficulty, I'd go with:
use Transaction::*;
match self {
V4 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
V5 {
sapling_shielded_data: Some(sapling_shielded_data),
..
}
| V6 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
// No Spends
V1 { .. } | V2 { .. } | V3 { .. } | V4 { .. } | V5 { .. } | V6 { .. } => {
Box::new(std::iter::empty())
}
}
because it currently seems excessively explicit/verbose, but avoiding a catch-all arm makes it easier to see that it needs an update when a new variant is added. If only Rust supported enums in range patterns we could have the best of both here and elsewhere in Zebra (I think there's a crate for it but adding a crate seems worse than being verbose). Stable support for if let
guards would've been nice here and elsewhere in this file too 🤷.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such simplification would work here and in similar places. However, if we add a feature flag for the V6 feature as we discussed:
V5 { ... } |
#[cfg(feature = "tx-v6")]
V6 { ... } => { ... }
It wouldn't compile. Here's a playground example to illustrate the issue.
I introduced the "tx-v6"
feature flag in the next PR (#17, "Step 4"). However, it would definitely be better to include it in this PR ("Step 3") since I introduced V6 here (the absence of the "tx-v6"
feature flag in this PR makes the review process confusing).
Anyway, we can't afford to use the |
operator for such simplification during the transition period when the "tx-v6"
feature flag is needed. Although I'm not completely sure if Rust doesn't have workarounds to achieve that.
And it was one of the reasons why I added the tx_v5_and_v6
macro here – to avoid such code duplication. However, the macro itself can be confusing because its usage doesn't follow the existing style for processing transaction version matches. I might need to remove it, and we can discuss this further.
// auto-detects the transaction version by the first byte, so the same function | ||
// can be used here for both V5 and V6. | ||
// FIXME: fix spec refs below for V6 | ||
/// Compute the Transaction ID for a V5/V6 transaction in the given network upgrade. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Compute the Transaction ID for transactions V5 to V6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
// FIXME: it looks like the updated zcash_primitives in librustzcash | ||
// auto-detects the transaction version by the first byte, so the same function | ||
// can be used here for both V5 and V6. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove these 3 lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
txid_v5_v6()
's approach would work for all transactions, but it's an unnecessary memory/cache allocation when txid_v1_to_v4()
is so simple and already implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
@@ -63,6 +63,7 @@ pub fn transparent_spend( | |||
finalized_state, | |||
)?; | |||
|
|||
// FIXME: what about v6? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment and fix line 69
to be
// This is a particular issue for v5 and v6 transactions,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
&None, | ||
&None, | ||
sapling_shielded_data, | ||
orchard_shielded_data, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to deal with issue bundle here?
(x2)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is probably the best place to update the issued_assets
map for the non-finalized part of the chain, same for revert_chain_with()
when rolling back the chain for a fork.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
@@ -446,6 +446,7 @@ enum SpendConflictTestInput { | |||
|
|||
conflict: SpendConflictForTransactionV5, | |||
}, | |||
// FIXME: add and use V6? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// FIXME: add V6 test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
|
||
/// The version group ID for version 6 transactions. | ||
/// | ||
/// Orchard transactions must use transaction version 5 and this version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Orchard transactions must use transaction version 5 and this version | |
/// Orchard ZSA transactions must use transaction version 6 and this version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
@@ -142,6 +142,28 @@ pub enum Transaction { | |||
/// The orchard data for this transaction, if any. | |||
orchard_shielded_data: Option<orchard::ShieldedData>, | |||
}, | |||
// FIXME: implement V6 properly (now it's just a coipy of V5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the changed-files
and codespell
lint jobs from here may be trivial and help catch typos.
} | ||
| Transaction::V6 { | ||
sapling_shielded_data: None, | ||
.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The simplification looks nice, I'd lean towards whatever's easiest since it all needs to be refactored to a new-type around the zcash_primitives
Transaction
type soon, and if there's no difference in difficulty, I'd go with:
use Transaction::*;
match self {
V4 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
V5 {
sapling_shielded_data: Some(sapling_shielded_data),
..
}
| V6 {
sapling_shielded_data: Some(sapling_shielded_data),
..
} => Box::new(sapling_shielded_data.anchors()),
// No Spends
V1 { .. } | V2 { .. } | V3 { .. } | V4 { .. } | V5 { .. } | V6 { .. } => {
Box::new(std::iter::empty())
}
}
because it currently seems excessively explicit/verbose, but avoiding a catch-all arm makes it easier to see that it needs an update when a new variant is added. If only Rust supported enums in range patterns we could have the best of both here and elsewhere in Zebra (I think there's a crate for it but adding a crate seems worse than being verbose). Stable support for if let
guards would've been nice here and elsewhere in this file too 🤷.
Transaction::V6 { | ||
sapling_shielded_data: Some(sapling_shielded_data), | ||
.. | ||
} => Box::new(sapling_shielded_data.spends_per_anchor()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick/Optional: Transaction::V5 | Transaction::V6
would work here and for all of the sapling methods below too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be a good simplification, but it's probably not compatible with the "tx-v6" feature flag. I’ve provided more details in this response.
@@ -918,6 +918,22 @@ pub fn transaction_to_fake_v5( | |||
orchard_shielded_data: None, | |||
}, | |||
v5 @ V5 { .. } => v5.clone(), | |||
V6 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename the function to something like transaction_to_fake_min_v5()
instead of converting v6 transactions to v5 here, since there aren't any v6 transactions in the test blocks (zebra_test::vectors::{MAINNET_BLOCKS, TESTNET_BLOCKS}
, accessed via network.block_iter()
in some places), and if they're added later, it would improve test coverage to keep them as v6 transactions in the tests where this is used (a total of ~20 places counting indirect calls, and only v5_transaction_is_accepted_after_nu5_activation_for_network
looks like it would need an update other than a rename).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to this comment copied to #37.
} => { | ||
// Transaction V6 spec: | ||
// FIXME: specify a proper ref | ||
// https://zips.z.cash/protocol/protocol.pdf#txnencoding |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: Leave both so it can be referenced while it's only in the ZIP and won't need an update if the encoding is meant to eventually be added to the protocol specification, though I'm not sure if that's the intention, I asked here.
Update: I've only found the version group IDs for V5 in the protocol spec so far, I think we'll probably want to keep this reference here (or add it back later).
/// Orchard transactions must use transaction version 5 and this version | ||
/// group ID. | ||
// FIXME: use a proper value! | ||
pub const TX_V6_VERSION_GROUP_ID: u32 = 0x26A7_270B; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: It's 0x124A69F8
in zcash_primitives
, if that was random, let's use that so it won't need an update.
// FIXME: it looks like the updated zcash_primitives in librustzcash | ||
// auto-detects the transaction version by the first byte, so the same function | ||
// can be used here for both V5 and V6. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
txid_v5_v6()
's approach would work for all transactions, but it's an unnecessary memory/cache allocation when txid_v1_to_v4()
is so simple and already implemented.
&None, | ||
&None, | ||
sapling_shielded_data, | ||
orchard_shielded_data, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is probably the best place to update the issued_assets
map for the non-finalized part of the chain, same for revert_chain_with()
when rolling back the chain for a fork.
…to aling with the one used in librustzcash
…sh_primitives) interface (OrchardBundle enum etc.)" This reverts commit 998a2c7.
…h the one used in OLD librustzcash
This PR introduces initial support for Transaction version 6 (Tx V6) in the Zebra codebase as part of the broader effort to add ZSA (Zcash Shielded Assets) support.
Key changes
Transaction
enum in thezebra-chain
crate, currently replicating the behavior of V5.Notes
Next steps
FIXME
comments in the code.zebra-chain::orchard::ShieldedData
struct to be a generic that supports both V5 and V6./tx_v6_with_ser_1.8.0
branch can be utilized).