From 798267c60255915e680a19a55ffb44b16fc1502f Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 26 Jun 2025 12:27:42 +0200 Subject: [PATCH 01/22] Quote variables in push-deploy.yaml to pass upstream actionlint checks The actionlint job in the ZcashFoundation/zebra repository CI reported multiple SC2086 errors. This commit quotes shell variables in push-deploy.yaml to fix the linter failures. --- .github/workflows/push-deploy.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/push-deploy.yaml b/.github/workflows/push-deploy.yaml index 12d1bed16ea..ce918790975 100644 --- a/.github/workflows/push-deploy.yaml +++ b/.github/workflows/push-deploy.yaml @@ -37,7 +37,7 @@ jobs: - name: Get short commit hash id: vars - run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" - name: Build, tag, and push image to Amazon ECR id: build-image @@ -47,12 +47,12 @@ jobs: IMAGE_TAG_COMMIT: ${{ env.SHORT_SHA }} run: | # Build a docker container - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_LATEST -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_COMMIT -f testnet-single-node-deploy/dockerfile . + docker build -t "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_LATEST" -t "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_COMMIT" -f testnet-single-node-deploy/dockerfile . # Push both tags to ECR - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_LATEST - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_COMMIT + docker push "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_LATEST" + docker push "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_COMMIT" # Output the image URIs - echo "image_latest=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_LATEST" >> $GITHUB_OUTPUT - echo "image_commit=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_COMMIT" >> $GITHUB_OUTPUT + echo "image_latest=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_LATEST" >> "$GITHUB_OUTPUT" + echo "image_commit=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG_COMMIT" >> "$GITHUB_OUTPUT" From 81054edaf23678c47cb01c7f8e8dc95a98396e32 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 6 Jul 2025 22:05:24 +0200 Subject: [PATCH 02/22] Rename tx-v6 feature flag to tx_v6 to match with the upstream (ZF) changes --- .cargo/config.toml | 8 +++---- zebra-chain/Cargo.toml | 2 +- zebra-chain/src/lib.rs | 2 +- zebra-chain/src/orchard.rs | 2 +- zebra-chain/src/orchard/commitment.rs | 10 ++++---- zebra-chain/src/orchard/note/ciphertexts.rs | 4 ++-- zebra-chain/src/orchard/shielded_data.rs | 12 +++++----- .../src/orchard/shielded_data_flavor.rs | 10 ++++---- zebra-chain/src/parameters/transaction.rs | 2 +- zebra-chain/src/transaction.rs | 24 +++++++++---------- zebra-chain/src/transaction/arbitrary.rs | 22 ++++++++--------- zebra-chain/src/transaction/serialize.rs | 12 +++++----- zebra-consensus/Cargo.toml | 6 ++--- zebra-consensus/src/primitives/halo2.rs | 8 +++---- zebra-consensus/src/primitives/halo2/tests.rs | 6 ++--- zebra-consensus/src/transaction.rs | 6 ++--- zebra-state/Cargo.toml | 4 ++-- .../src/service/non_finalized_state/chain.rs | 14 +++++------ zebra-state/src/tests.rs | 2 +- zebra-test/Cargo.toml | 2 +- zebra-test/src/vectors.rs | 8 +++---- zebrad/Cargo.toml | 8 +++---- .../components/mempool/storage/tests/prop.rs | 16 ++++++------- 23 files changed, 95 insertions(+), 95 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index ec87157c946..4e11b230936 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,8 +3,8 @@ # Flags that apply to all Zebra crates and configurations [target.'cfg(all())'] rustflags = [ - # Enable tx-v6 everywhere by default - "--cfg", 'feature="tx-v6"', + # Enable tx_v6 everywhere by default + "--cfg", 'feature="tx_v6"', # TODO: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) "--cfg", "zcash_unstable=\"nu6\"", @@ -88,8 +88,8 @@ rustflags = [ [build] rustdocflags = [ - # Enable tx-v6 everywhere by default - "--cfg", 'feature="tx-v6"', + # Enable tx_v6 everywhere by default + "--cfg", 'feature="tx_v6"', # TODO: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) "--cfg", "zcash_unstable=\"nu6\"", diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 358b556f105..f7babbe91d3 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -62,7 +62,7 @@ proptest-impl = [ bench = ["zebra-test"] # Support for transaction version 6 -tx-v6 = [ +tx_v6 = [ "nonempty" ] diff --git a/zebra-chain/src/lib.rs b/zebra-chain/src/lib.rs index dd6fa1a1abf..917f8aeab39 100644 --- a/zebra-chain/src/lib.rs +++ b/zebra-chain/src/lib.rs @@ -41,7 +41,7 @@ pub mod transparent; pub mod value_balance; pub mod work; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub mod orchard_zsa; #[cfg(any(test, feature = "proptest-impl"))] diff --git a/zebra-chain/src/orchard.rs b/zebra-chain/src/orchard.rs index 290ddb4931a..e5a6cbee01f 100644 --- a/zebra-chain/src/orchard.rs +++ b/zebra-chain/src/orchard.rs @@ -28,5 +28,5 @@ pub use shielded_data_flavor::{OrchardVanilla, ShieldedDataFlavor}; pub(crate) use shielded_data::ActionCommon; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub use shielded_data_flavor::OrchardZSA; diff --git a/zebra-chain/src/orchard/commitment.rs b/zebra-chain/src/orchard/commitment.rs index 2b809bdbd27..c97e5053f20 100644 --- a/zebra-chain/src/orchard/commitment.rs +++ b/zebra-chain/src/orchard/commitment.rs @@ -14,7 +14,7 @@ use halo2::{ use lazy_static::lazy_static; use rand_core::{CryptoRng, RngCore}; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use orchard::{ note::AssetBase, value::{ValueCommitTrapdoor, ValueSum}, @@ -243,7 +243,7 @@ impl ValueCommitment { { let rcv = generate_trapdoor(csprng)?; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] let vc = Self::new( rcv, // TODO: Make the `ValueSum::from_raw` function public in the `orchard` crate @@ -253,7 +253,7 @@ impl ValueCommitment { AssetBase::native(), ); - #[cfg(not(feature = "tx-v6"))] + #[cfg(not(feature = "tx_v6"))] let vc = Self::new(rcv, value); Ok(vc) @@ -264,14 +264,14 @@ impl ValueCommitment { /// ValueCommit^Orchard(v) := /// /// - #[cfg(not(feature = "tx-v6"))] + #[cfg(not(feature = "tx_v6"))] pub fn new(rcv: pallas::Scalar, value: Amount) -> Self { let v = pallas::Scalar::from(value); Self::from(*V * v + *R * rcv) } /// Generate a new `ValueCommitment` from an existing `rcv on a `value` (ZSA version). - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] pub fn new(rcv: pallas::Scalar, value: ValueSum, asset: AssetBase) -> Self { // TODO: Add `pub` methods to `ValueCommitTrapdoor` and `ValueCommitment` in `orchard` // to simplify type conversions when calling `orchard::value::ValueCommitment::derive`. diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 9b676ffd96b..644baa0ccd2 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -113,7 +113,7 @@ mod tests { serialization::{ZcashDeserialize, ZcashSerialize}, }; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] use crate::orchard::OrchardZSA; use proptest::prelude::*; @@ -138,7 +138,7 @@ mod tests { } - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] #[test] fn encrypted_ciphertext_roundtrip_orchard_zsa(ec in any::<::EncryptedNote>()) { let _init_guard = zebra_test::init(); diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index 37e84fa9a3b..df77a131672 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -20,7 +20,7 @@ use crate::{ }, }; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use orchard::{note::AssetBase, value::ValueSum}; use super::{OrchardVanilla, ShieldedDataFlavor}; @@ -28,11 +28,11 @@ use super::{OrchardVanilla, ShieldedDataFlavor}; /// A bundle of [`Action`] descriptions and signature data. #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] #[cfg_attr( - not(feature = "tx-v6"), + not(feature = "tx_v6"), serde(bound(serialize = "Flavor::EncryptedNote: serde::Serialize")) )] #[cfg_attr( - feature = "tx-v6", + feature = "tx_v6", serde(bound( serialize = "Flavor::EncryptedNote: serde::Serialize, Flavor::BurnType: serde::Serialize", deserialize = "Flavor::BurnType: serde::Deserialize<'de>" @@ -58,7 +58,7 @@ pub struct ShieldedData { /// Denoted as `bindingSigOrchard` in the spec. pub binding_sig: Signature, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] /// Assets intended for burning /// Denoted as `vAssetBurn` in the spec (ZIP 230). pub burn: Flavor::BurnType, @@ -126,13 +126,13 @@ impl ShieldedData { pub fn binding_verification_key(&self) -> reddsa::VerificationKeyBytes { let cv: ValueCommitment = self.actions().map(|action| action.cv).sum(); - #[cfg(not(feature = "tx-v6"))] + #[cfg(not(feature = "tx_v6"))] let key = { let cv_balance = ValueCommitment::new(pallas::Scalar::zero(), self.value_balance); cv - cv_balance }; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] let key = { let cv_balance = ValueCommitment::new( pallas::Scalar::zero(), diff --git a/zebra-chain/src/orchard/shielded_data_flavor.rs b/zebra-chain/src/orchard/shielded_data_flavor.rs index 7535305b636..1a791477652 100644 --- a/zebra-chain/src/orchard/shielded_data_flavor.rs +++ b/zebra-chain/src/orchard/shielded_data_flavor.rs @@ -8,12 +8,12 @@ use orchard::{domain::OrchardDomainCommon, orchard_flavor::OrchardFlavor}; pub use orchard::orchard_flavor::OrchardVanilla; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub use orchard::{note::AssetBase, orchard_flavor::OrchardZSA, value::NoteValue}; use crate::serialization::{ZcashDeserialize, ZcashSerialize}; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use crate::{ orchard::ValueCommitment, orchard_zsa::{Burn, BurnItem, NoBurn}, @@ -53,7 +53,7 @@ pub trait ShieldedDataFlavor: OrchardFlavor { + test_arbitrary::TestArbitrary; /// A type representing a burn field for this protocol version. - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] // FIXME: try to get rid type BurnType: Clone + Debug @@ -68,11 +68,11 @@ pub trait ShieldedDataFlavor: OrchardFlavor { impl ShieldedDataFlavor for OrchardVanilla { type EncryptedNote = note::EncryptedNote<{ OrchardVanilla::ENC_CIPHERTEXT_SIZE }>; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] type BurnType = NoBurn; } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] impl ShieldedDataFlavor for OrchardZSA { type EncryptedNote = note::EncryptedNote<{ OrchardZSA::ENC_CIPHERTEXT_SIZE }>; type BurnType = Burn; diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index bcc44cb4f6e..309b18ab31b 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -17,5 +17,5 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// OrchardZSA transactions must use transaction version 6 and this version /// group ID. // TODO: FIXME: use a proper value! -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub const TX_V6_VERSION_GROUP_ID: u32 = 0x7777_7777; diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 9b01316cfc3..0331237c4e9 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -53,7 +53,7 @@ use crate::{ value_balance::{ValueBalance, ValueBalanceError}, }; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use crate::orchard_zsa; /// A Zcash transaction. @@ -146,7 +146,7 @@ pub enum Transaction { orchard_shielded_data: Option>, }, /// A `version = 6` transaction , OrchardZSA, Orchard, Sapling and transparent, but not Sprout. - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] V6 { /// The Network Upgrade for this transaction. /// @@ -202,8 +202,8 @@ impl fmt::Display for Transaction { } // Define the macro to include the V6 variant. -// Needed only with the `tx-v6` feature to avoid duplicating code. -#[cfg(feature = "tx-v6")] +// Needed only with the `tx_v6` feature to avoid duplicating code. +#[cfg(feature = "tx_v6")] macro_rules! tx_v5_and_v6 { { $($fields:tt)* } => { Transaction::V5 { $($fields)* } | Transaction::V6 { $($fields)* } @@ -211,7 +211,7 @@ macro_rules! tx_v5_and_v6 { } /// Same as above, without the V6 arm. -#[cfg(not(feature = "tx-v6"))] +#[cfg(not(feature = "tx_v6"))] macro_rules! tx_v5_and_v6 { { $($fields:tt)* } => { Transaction::V5 { $($fields)* } @@ -237,7 +237,7 @@ macro_rules! orchard_shielded_data_field { .. } => orchard_shielded_data.as_ref().map(|data| data.$field), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data, .. @@ -403,7 +403,7 @@ impl Transaction { Transaction::V3 { .. } => 3, Transaction::V4 { .. } => 4, Transaction::V5 { .. } => 5, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { .. } => 6, } } @@ -1015,7 +1015,7 @@ impl Transaction { .flat_map(orchard::ShieldedData::action_commons), ), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data, .. @@ -1044,7 +1044,7 @@ impl Transaction { .flat_map(orchard::ShieldedData::nullifiers), ), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data, .. @@ -1073,7 +1073,7 @@ impl Transaction { .flat_map(orchard::ShieldedData::note_commitments) .cloned(), ), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data, orchard_zsa_issue_data, @@ -1499,7 +1499,7 @@ impl Transaction { .. } => Some(&mut orchard_shielded_data.value_balance), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data: Some(orchard_shielded_data), .. @@ -1514,7 +1514,7 @@ impl Transaction { .. } => None, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data: None, .. diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 8e71b63f9e9..a2995ed97a0 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -20,7 +20,7 @@ use crate::{ LedgerState, }; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use crate::orchard_zsa::IssueData; use itertools::Itertools; @@ -229,7 +229,7 @@ impl Transaction { } /// Generate a proptest strategy for V6 Transactions - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] pub fn v6_strategy(ledger_state: LedgerState) -> BoxedStrategy { Self::v5_v6_strategy_common::(ledger_state) .prop_flat_map(|common_fields| { @@ -795,14 +795,14 @@ impl Arbitrary for orchard::Shiel 1..MAX_ARBITRARY_ITEMS, ), any::(), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] any::(), ) .prop_map(|props| { - #[cfg(not(feature = "tx-v6"))] + #[cfg(not(feature = "tx_v6"))] let (flags, value_balance, shared_anchor, proof, actions, binding_sig) = props; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] let (flags, value_balance, shared_anchor, proof, actions, binding_sig, burn) = props; @@ -815,7 +815,7 @@ impl Arbitrary for orchard::Shiel .try_into() .expect("arbitrary vector size range produces at least one action"), binding_sig: binding_sig.0, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] burn, } }) @@ -860,7 +860,7 @@ impl Arbitrary for Transaction { Some(3) => return Self::v3_strategy(ledger_state), Some(4) => return Self::v4_strategy(ledger_state), Some(5) => return Self::v5_strategy(ledger_state), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Some(6) => return Self::v6_strategy(ledger_state), Some(_) => unreachable!("invalid transaction version in override"), None => {} @@ -881,7 +881,7 @@ impl Arbitrary for Transaction { ] .boxed(), NetworkUpgrade::Nu7 => { - #[cfg(not(feature = "tx-v6"))] + #[cfg(not(feature = "tx_v6"))] { prop_oneof![ Self::v4_strategy(ledger_state.clone()), @@ -889,7 +889,7 @@ impl Arbitrary for Transaction { ] .boxed() } - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] { prop_oneof![ Self::v4_strategy(ledger_state.clone()), @@ -1034,7 +1034,7 @@ pub fn transaction_to_fake_v5( orchard_shielded_data: None, }, v5 @ V5 { .. } => v5.clone(), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] _ => panic!(" other transaction versions are not supported"), } } @@ -1175,7 +1175,7 @@ pub fn insert_fake_orchard_shielded_data( proof: Halo2Proof(vec![]), actions: at_least_one![dummy_authorized_action], binding_sig: Signature::from([0u8; 64]), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] burn: Default::default(), }; diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 31f3f5a70f1..2a7df60c30d 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -20,7 +20,7 @@ use crate::{ }, }; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use crate::{ orchard::OrchardZSA, orchard_zsa::NoBurn, parameters::TX_V6_VERSION_GROUP_ID, serialization::CompactSizeMessage, @@ -391,7 +391,7 @@ impl ZcashSerialize for orchard::ShieldedData { } } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] #[allow(clippy::unwrap_in_result)] impl ZcashSerialize for orchard::ShieldedData { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { @@ -504,7 +504,7 @@ impl ZcashDeserialize for Option> { Ok(Some(orchard::ShieldedData:: { flags, value_balance, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] burn: NoBurn, shared_anchor, proof, @@ -517,7 +517,7 @@ impl ZcashDeserialize for Option> { // FIXME: Try to avoid duplication with OrchardVanilla version // we can't split ShieldedData out of Option deserialization, // because the counts are read along with the arrays. -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] impl ZcashDeserialize for Option> { fn zcash_deserialize(mut reader: R) -> Result { // Denoted as `nActionGroupsOrchard` in the spec (ZIP 230) (must be one for V6/NU7). @@ -817,7 +817,7 @@ impl ZcashSerialize for Transaction { orchard_shielded_data.zcash_serialize(&mut writer)?; } - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { network_upgrade, lock_time, @@ -1121,7 +1121,7 @@ impl ZcashDeserialize for Transaction { orchard_shielded_data, }) } - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] (6, true) => { // Transaction V6 spec: // https://zips.z.cash/zip-0230#transaction-format diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index 3fa5de04d05..56495ba0526 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -35,9 +35,9 @@ getblocktemplate-rpcs = [ proptest-impl = ["proptest", "proptest-derive", "zebra-chain/proptest-impl", "zebra-state/proptest-impl"] # Support for transaction version 6 -tx-v6 = [ - "zebra-state/tx-v6", - "zebra-chain/tx-v6" +tx_v6 = [ + "zebra-state/tx_v6", + "zebra-chain/tx_v6" ] [dependencies] diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index b5f665bc5ca..691bfaede62 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -21,7 +21,7 @@ use tower_fallback::Fallback; use zebra_chain::orchard::{OrchardVanilla, ShieldedData, ShieldedDataFlavor}; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] use zebra_chain::orchard::OrchardZSA; use crate::BoxError; @@ -83,7 +83,7 @@ lazy_static::lazy_static! { pub static ref VERIFYING_KEY_VANILLA: ItemVerifyingKey = ItemVerifyingKey::build::(); } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] lazy_static::lazy_static! { /// The halo2 proof verifying key for OrchardZSA pub static ref VERIFYING_KEY_ZSA: ItemVerifyingKey = ItemVerifyingKey::build::(); @@ -247,7 +247,7 @@ pub static VERIFIER_VANILLA: Lazy = Lazy::new(create_verification_context::); /// FIXME: copy a doc from VERIFIER_VANILLA or just refer to its doc? -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub static VERIFIER_ZSA: Lazy = Lazy::new(create_verification_context::); @@ -263,7 +263,7 @@ impl OrchardVerifier for OrchardVanilla { } } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] impl OrchardVerifier for OrchardZSA { const ZSA_ENABLED: bool = true; diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index e0fe52527b1..aa694dbe2e1 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -109,7 +109,7 @@ where .try_into() .unwrap(), binding_sig: <[u8; 64]>::from(bundle.authorization().binding_signature()).into(), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] burn: bundle.burn().as_slice().into(), } }) @@ -196,7 +196,7 @@ async fn verify_generated_halo2_proofs_vanilla() { .await } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] #[tokio::test(flavor = "multi_thread")] async fn verify_generated_halo2_proofs_zsa() { verify_generated_halo2_proofs::(&zebra_test::vectors::ORCHARD_SHIELDED_DATA_ZSA) @@ -287,7 +287,7 @@ async fn correctly_err_on_invalid_halo2_proofs_vanilla() { .await } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] #[tokio::test(flavor = "multi_thread")] async fn correctly_err_on_invalid_halo2_proofs_zsa() { correctly_err_on_invalid_halo2_proofs::( diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 6283da8830c..51de9007b78 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -414,7 +414,7 @@ where sapling_shielded_data, orchard_shielded_data, )?, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { sapling_shielded_data, orchard_shielded_data, @@ -512,12 +512,12 @@ impl OrchardTransaction for orchard::OrchardVanilla { const SUPPORTED_NETWORK_UPGRADES: &'static [NetworkUpgrade] = &[ NetworkUpgrade::Nu5, NetworkUpgrade::Nu6, - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] NetworkUpgrade::Nu7, ]; } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] impl OrchardTransaction for orchard::OrchardZSA { const SUPPORTED_NETWORK_UPGRADES: &'static [NetworkUpgrade] = &[NetworkUpgrade::Nu7]; } diff --git a/zebra-state/Cargo.toml b/zebra-state/Cargo.toml index 2a0eec9b2ca..f341e26cde3 100644 --- a/zebra-state/Cargo.toml +++ b/zebra-state/Cargo.toml @@ -47,8 +47,8 @@ elasticsearch = [ ] # Support for transaction version 6 -tx-v6 = [ - "zebra-chain/tx-v6" +tx_v6 = [ + "zebra-chain/tx_v6" ] [dependencies] diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index 0bb9d52929a..a002c301766 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -1506,7 +1506,7 @@ impl Chain { sapling_shielded_data, &None, &None, - #[cfg(feature ="tx-v6")] + #[cfg(feature ="tx_v6")] &None ), V5 { @@ -1522,10 +1522,10 @@ impl Chain { &None, sapling_shielded_data, orchard_shielded_data, - #[cfg(feature ="tx-v6")] + #[cfg(feature ="tx_v6")] &None, ), - #[cfg(feature ="tx-v6")] + #[cfg(feature ="tx_v6")] V6 { inputs, outputs, @@ -1546,7 +1546,7 @@ impl Chain { ), }; - #[cfg(not(feature = "tx-v6"))] + #[cfg(not(feature = "tx_v6"))] let ( inputs, outputs, @@ -1556,7 +1556,7 @@ impl Chain { orchard_shielded_data_vanilla, ) = transaction_data; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] let ( inputs, outputs, @@ -1587,7 +1587,7 @@ impl Chain { self.update_chain_tip_with(sapling_shielded_data_per_spend_anchor)?; self.update_chain_tip_with(sapling_shielded_data_shared_anchor)?; self.update_chain_tip_with(orchard_shielded_data_vanilla)?; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] self.update_chain_tip_with(orchard_shielded_data_zsa)?; } @@ -1725,7 +1725,7 @@ impl UpdateWith for Chain { sapling_shielded_data, orchard_shielded_data, ), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] V6 { inputs, outputs, diff --git a/zebra-state/src/tests.rs b/zebra-state/src/tests.rs index d01a871f142..2a229c0ebb0 100644 --- a/zebra-state/src/tests.rs +++ b/zebra-state/src/tests.rs @@ -34,7 +34,7 @@ impl FakeChainHelper for Arc { Transaction::V3 { inputs, .. } => &mut inputs[0], Transaction::V4 { inputs, .. } => &mut inputs[0], Transaction::V5 { inputs, .. } => &mut inputs[0], - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { inputs, .. } => &mut inputs[0], }; diff --git a/zebra-test/Cargo.toml b/zebra-test/Cargo.toml index f937eb8315f..1f8cabed08a 100644 --- a/zebra-test/Cargo.toml +++ b/zebra-test/Cargo.toml @@ -18,7 +18,7 @@ categories = ["command-line-utilities", "cryptography::cryptocurrencies"] default = [] # Support for transaction version 6 -tx-v6 = [] +tx_v6 = [] [dependencies] hex = "0.4.3" diff --git a/zebra-test/src/vectors.rs b/zebra-test/src/vectors.rs index f6983c95661..c62d43e7677 100644 --- a/zebra-test/src/vectors.rs +++ b/zebra-test/src/vectors.rs @@ -7,20 +7,20 @@ mod block; mod orchard_note_encryption; mod orchard_shielded_data; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] mod orchard_shielded_data_zsa; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] mod orchard_workflow_blocks_zsa; pub use block::*; pub use orchard_note_encryption::*; pub use orchard_shielded_data::*; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub use orchard_shielded_data_zsa::*; -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] pub use orchard_workflow_blocks_zsa::*; /// A testnet transaction test vector diff --git a/zebrad/Cargo.toml b/zebrad/Cargo.toml index 72a8afd7dc0..0691a2367be 100644 --- a/zebrad/Cargo.toml +++ b/zebrad/Cargo.toml @@ -157,10 +157,10 @@ test_sync_past_mandatory_checkpoint_mainnet = [] test_sync_past_mandatory_checkpoint_testnet = [] # Support for transaction version 6 -tx-v6 = [ - "zebra-consensus/tx-v6", - "zebra-state/tx-v6", - "zebra-chain/tx-v6" +tx_v6 = [ + "zebra-consensus/tx_v6", + "zebra-state/tx_v6", + "zebra-chain/tx_v6" ] [dependencies] diff --git a/zebrad/src/components/mempool/storage/tests/prop.rs b/zebrad/src/components/mempool/storage/tests/prop.rs index eaf99bb8ad9..ef0da69d2d1 100644 --- a/zebrad/src/components/mempool/storage/tests/prop.rs +++ b/zebrad/src/components/mempool/storage/tests/prop.rs @@ -448,7 +448,7 @@ enum SpendConflictTestInput { }, /// Test V6 transactions to include OrchardZSA nullifier conflicts. - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] V6 { #[proptest( strategy = "Transaction::v6_strategy(LedgerState::default()).prop_map(DisplayToDebug)" @@ -488,7 +488,7 @@ impl SpendConflictTestInput { (first, second) } - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] SpendConflictTestInput::V6 { mut first, mut second, @@ -524,7 +524,7 @@ impl SpendConflictTestInput { let (mut first, mut second) = match self { SpendConflictTestInput::V4 { first, second, .. } => (first, second), SpendConflictTestInput::V5 { first, second, .. } => (first, second), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] SpendConflictTestInput::V6 { first, second, .. } => (first, second), }; @@ -599,7 +599,7 @@ impl SpendConflictTestInput { Transaction::V1 { .. } | Transaction::V5 { .. } => {} // No JoinSplits - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { .. } => {} } } @@ -671,7 +671,7 @@ impl SpendConflictTestInput { Self::remove_sapling_transfers_with_conflicts(sapling_shielded_data, &conflicts) } - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { sapling_shielded_data, .. @@ -750,7 +750,7 @@ impl SpendConflictTestInput { .. } => Self::remove_orchard_actions_with_conflicts(orchard_shielded_data, &conflicts), - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] Transaction::V6 { orchard_shielded_data, .. @@ -808,7 +808,7 @@ enum SpendConflictForTransactionV5 { } /// A spend conflict valid for V6 transactions. -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] #[derive(Arbitrary, Clone, Debug)] enum SpendConflictForTransactionV6 { Transparent(Box), @@ -891,7 +891,7 @@ impl SpendConflictForTransactionV5 { } } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] impl SpendConflictForTransactionV6 { /// Apply a spend conflict to a V6 transaction. /// From d8ac7f5690bdc8f3c1625c31eae838945db40866 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 6 Jul 2025 22:41:32 +0200 Subject: [PATCH 03/22] Expand and remove tx_v5_and_v6 macro --- .../src/primitives/zcash_primitives.rs | 8 +- zebra-chain/src/transaction.rs | 230 +++++++++++++----- zebra-chain/src/transaction/tests/vectors.rs | 23 +- zebra-chain/src/transaction/txid.rs | 6 +- zebra-chain/src/transaction/unmined.rs | 6 +- zebra-consensus/src/transaction.rs | 1 - 6 files changed, 210 insertions(+), 64 deletions(-) diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 2260412cdc4..e13035b96fc 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -10,7 +10,7 @@ use crate::{ amount::{Amount, NonNegative}, parameters::{ConsensusBranchId, Network}, serialization::ZcashSerialize, - transaction::{tx_v5_and_v6, AuthDigest, HashType, SigHash, Transaction}, + transaction::{AuthDigest, HashType, SigHash, Transaction}, transparent::{self, Script}, }; @@ -174,7 +174,11 @@ impl TryFrom<&Transaction> for zp_tx::Transaction { #[allow(clippy::unwrap_in_result)] fn try_from(trans: &Transaction) -> Result { let network_upgrade = match trans { - tx_v5_and_v6! { + Transaction::V5 { + network_upgrade, .. + } => network_upgrade, + #[cfg(feature = "tx_v6")] + Transaction::V6 { network_upgrade, .. } => network_upgrade, Transaction::V1 { .. } diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 0331237c4e9..ed9576a0c12 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -201,25 +201,6 @@ impl fmt::Display for Transaction { } } -// Define the macro to include the V6 variant. -// Needed only with the `tx_v6` feature to avoid duplicating code. -#[cfg(feature = "tx_v6")] -macro_rules! tx_v5_and_v6 { - { $($fields:tt)* } => { - Transaction::V5 { $($fields)* } | Transaction::V6 { $($fields)* } - }; -} - -/// Same as above, without the V6 arm. -#[cfg(not(feature = "tx_v6"))] -macro_rules! tx_v5_and_v6 { - { $($fields:tt)* } => { - Transaction::V5 { $($fields)* } - }; -} - -pub(crate) use tx_v5_and_v6; - // Macro to get a specific field from an Orchard shielded data struct. // Returns `None` for transaction versions that don't support Orchard (V1-V4). // This avoids repeating the same match block pattern across multiple accessor methods. @@ -318,7 +299,9 @@ impl Transaction { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => None, - tx_v5_and_v6! { .. } => Some(AuthDigest::from(self)), + Transaction::V5 { .. } => Some(AuthDigest::from(self)), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Some(AuthDigest::from(self)), } } @@ -391,7 +374,9 @@ impl Transaction { pub fn is_overwintered(&self) -> bool { match self { Transaction::V1 { .. } | Transaction::V2 { .. } => false, - Transaction::V3 { .. } | Transaction::V4 { .. } | tx_v5_and_v6! { .. } => true, + Transaction::V3 { .. } | Transaction::V4 { .. } | Transaction::V5 { .. } => true, + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => true, } } @@ -415,7 +400,9 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | tx_v5_and_v6! { lock_time, .. } => *lock_time, + | Transaction::V5 { lock_time, .. } => *lock_time, + #[cfg(feature = "tx_v6")] + Transaction::V6 { lock_time, .. } => *lock_time, }; // `zcashd` checks that the block height is greater than the lock height. @@ -462,7 +449,9 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | tx_v5_and_v6! { lock_time, .. } => *lock_time, + | Transaction::V5 { lock_time, .. } => *lock_time, + #[cfg(feature = "tx_v6")] + Transaction::V6 { lock_time, .. } => *lock_time, }; let mut lock_time_bytes = Vec::new(); lock_time @@ -492,7 +481,15 @@ impl Transaction { Transaction::V1 { .. } | Transaction::V2 { .. } => None, Transaction::V3 { expiry_height, .. } | Transaction::V4 { expiry_height, .. } - | tx_v5_and_v6! { expiry_height, .. } => match expiry_height { + | Transaction::V5 { expiry_height, .. } => match expiry_height { + // Consensus rule: + // > No limit: To set no limit on transactions (so that they do not expire), nExpiryHeight should be set to 0. + // https://zips.z.cash/zip-0203#specification + block::Height(0) => None, + block::Height(expiry_height) => Some(block::Height(*expiry_height)), + }, + #[cfg(feature = "tx_v6")] + Transaction::V6 { expiry_height, .. } => match expiry_height { // Consensus rule: // > No limit: To set no limit on transactions (so that they do not expire), nExpiryHeight should be set to 0. // https://zips.z.cash/zip-0203#specification @@ -521,7 +518,12 @@ impl Transaction { ref mut expiry_height, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + ref mut expiry_height, + .. + } => expiry_height, + #[cfg(feature = "tx_v6")] + Transaction::V6 { ref mut expiry_height, .. } => expiry_height, @@ -538,7 +540,11 @@ impl Transaction { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => None, - tx_v5_and_v6! { + Transaction::V5 { + network_upgrade, .. + } => Some(*network_upgrade), + #[cfg(feature = "tx_v6")] + Transaction::V6 { network_upgrade, .. } => Some(*network_upgrade), } @@ -553,7 +559,9 @@ impl Transaction { Transaction::V2 { ref inputs, .. } => inputs, Transaction::V3 { ref inputs, .. } => inputs, Transaction::V4 { ref inputs, .. } => inputs, - tx_v5_and_v6! { ref inputs, .. } => inputs, + Transaction::V5 { ref inputs, .. } => inputs, + #[cfg(feature = "tx_v6")] + Transaction::V6 { ref inputs, .. } => inputs, } } @@ -565,7 +573,9 @@ impl Transaction { Transaction::V2 { ref mut inputs, .. } => inputs, Transaction::V3 { ref mut inputs, .. } => inputs, Transaction::V4 { ref mut inputs, .. } => inputs, - tx_v5_and_v6! { ref mut inputs, .. } => inputs, + Transaction::V5 { ref mut inputs, .. } => inputs, + #[cfg(feature = "tx_v6")] + Transaction::V6 { ref mut inputs, .. } => inputs, } } @@ -583,7 +593,9 @@ impl Transaction { Transaction::V2 { ref outputs, .. } => outputs, Transaction::V3 { ref outputs, .. } => outputs, Transaction::V4 { ref outputs, .. } => outputs, - tx_v5_and_v6! { ref outputs, .. } => outputs, + Transaction::V5 { ref outputs, .. } => outputs, + #[cfg(feature = "tx_v6")] + Transaction::V6 { ref outputs, .. } => outputs, } } @@ -603,7 +615,11 @@ impl Transaction { Transaction::V4 { ref mut outputs, .. } => outputs, - tx_v5_and_v6! { + Transaction::V5 { + ref mut outputs, .. + } => outputs, + #[cfg(feature = "tx_v6")] + Transaction::V6 { ref mut outputs, .. } => outputs, } @@ -653,7 +669,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -688,7 +706,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => 0, + | Transaction::V5 { .. } => 0, + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => 0, } } @@ -727,7 +747,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -763,7 +785,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => None, + | Transaction::V5 { .. } => None, + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => None, } } @@ -771,7 +795,10 @@ impl Transaction { pub fn has_sprout_joinsplit_data(&self) -> bool { match self { // No JoinSplits - Transaction::V1 { .. } | tx_v5_and_v6! { .. } => false, + Transaction::V1 { .. } | Transaction::V5 { .. } => false, + + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => false, // JoinSplits-on-BCTV14 Transaction::V2 { joinsplit_data, .. } | Transaction::V3 { joinsplit_data, .. } => { @@ -818,7 +845,9 @@ impl Transaction { .. } | Transaction::V1 { .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -835,7 +864,13 @@ impl Transaction { .. } => Box::new(sapling_shielded_data.anchors()), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.anchors()), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.anchors()), @@ -848,7 +883,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -873,7 +913,13 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.spends_per_anchor()), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.spends_per_anchor()), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.spends_per_anchor()), @@ -886,7 +932,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -901,7 +952,12 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.outputs()), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.outputs()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.outputs()), @@ -914,7 +970,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -931,7 +992,13 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.nullifiers()), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.nullifiers()), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.nullifiers()), @@ -944,7 +1011,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -961,7 +1033,13 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.note_commitments()), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.note_commitments()), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.note_commitments()), @@ -974,7 +1052,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -989,7 +1072,12 @@ impl Transaction { sapling_shielded_data, .. } => sapling_shielded_data.is_some(), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data, + .. + } => sapling_shielded_data.is_some(), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data, .. } => sapling_shielded_data.is_some(), @@ -1195,7 +1283,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1244,7 +1334,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1291,7 +1383,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1340,7 +1434,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1381,7 +1477,9 @@ impl Transaction { joinsplit_data: None, .. } - | tx_v5_and_v6! { .. } => Box::new(iter::empty()), + | Transaction::V5 { .. } => Box::new(iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(iter::empty()), }; joinsplit_value_balances.map(ValueBalance::from_sprout_amount) @@ -1419,7 +1517,12 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => sapling_shielded_data.value_balance, - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => sapling_shielded_data.value_balance, + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => sapling_shielded_data.value_balance, @@ -1431,7 +1534,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => Amount::zero(), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => Amount::zero(), @@ -1451,7 +1559,12 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Some(&mut sapling_shielded_data.value_balance), - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Some(&mut sapling_shielded_data.value_balance), + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: Some(sapling_shielded_data), .. } => Some(&mut sapling_shielded_data.value_balance), @@ -1462,7 +1575,12 @@ impl Transaction { sapling_shielded_data: None, .. } - | tx_v5_and_v6! { + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => None, + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data: None, .. } => None, diff --git a/zebra-chain/src/transaction/tests/vectors.rs b/zebra-chain/src/transaction/tests/vectors.rs index 9e0af8adf63..063d6401ef8 100644 --- a/zebra-chain/src/transaction/tests/vectors.rs +++ b/zebra-chain/src/transaction/tests/vectors.rs @@ -988,7 +988,28 @@ fn binding_signatures_for_network(network: Network) { .expect("must pass verification"); } } - tx_v5_and_v6! { + Transaction::V5 { + sapling_shielded_data, + .. + } => { + if let Some(sapling_shielded_data) = sapling_shielded_data { + let shielded_sighash = + tx.sighash(upgrade.branch_id().unwrap(), HashType::ALL, &[], None); + + let bvk = redjubjub::VerificationKey::try_from( + sapling_shielded_data.binding_verification_key(), + ) + .expect("a valid redjubjub::VerificationKey"); + + bvk.verify( + shielded_sighash.as_ref(), + &sapling_shielded_data.binding_sig, + ) + .expect("must pass verification"); + } + } + #[cfg(feature = "tx_v6")] + Transaction::V6 { sapling_shielded_data, .. } => { diff --git a/zebra-chain/src/transaction/txid.rs b/zebra-chain/src/transaction/txid.rs index 2b1f9d5b050..da506f952c4 100644 --- a/zebra-chain/src/transaction/txid.rs +++ b/zebra-chain/src/transaction/txid.rs @@ -2,7 +2,7 @@ //! from the transaction. use std::io; -use super::{tx_v5_and_v6, Hash, Transaction}; +use super::{Hash, Transaction}; use crate::serialization::{sha256d, ZcashSerialize}; /// A Transaction ID builder. It computes the transaction ID by hashing @@ -28,7 +28,9 @@ impl<'a> TxIdBuilder<'a> { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => self.txid_v1_to_v4(), - tx_v5_and_v6! { .. } => self.txid_v5_to_v6(), + Transaction::V5 { .. } => self.txid_v5_to_v6(), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => self.txid_v5_to_v6(), } } diff --git a/zebra-chain/src/transaction/unmined.rs b/zebra-chain/src/transaction/unmined.rs index ce327ae9f76..af79a460c85 100644 --- a/zebra-chain/src/transaction/unmined.rs +++ b/zebra-chain/src/transaction/unmined.rs @@ -21,7 +21,7 @@ use crate::{ amount::{Amount, NonNegative}, serialization::ZcashSerialize, transaction::{ - tx_v5_and_v6, AuthDigest, Hash, + AuthDigest, Hash, Transaction::{self, *}, WtxId, }, @@ -140,7 +140,9 @@ impl From<&Transaction> for UnminedTxId { fn from(transaction: &Transaction) -> Self { match transaction { V1 { .. } | V2 { .. } | V3 { .. } | V4 { .. } => Legacy(transaction.into()), - tx_v5_and_v6! { .. } => Witnessed(transaction.into()), + V5 { .. } => Witnessed(transaction.into()), + #[cfg(feature = "tx_v6")] + V6 { .. } => Witnessed(transaction.into()), } } } diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 51de9007b78..5949bb39b13 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -427,7 +427,6 @@ where sapling_shielded_data, orchard_shielded_data, )?, - }; if let Some(unmined_tx) = req.mempool_transaction() { From a088325cea74c2260d58d7b7f9e07824c254ceba Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 28 Jul 2025 10:35:34 +0200 Subject: [PATCH 04/22] Reorder transaction methods to match the upstream --- zebra-chain/src/transaction.rs | 511 ++++++++++++++++----------------- 1 file changed, 253 insertions(+), 258 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index ed9576a0c12..d6e29c101f4 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -325,11 +325,6 @@ impl Transaction { .contains(orchard::Flags::ENABLE_SPENDS)) } - /// Does this transaction have transparent or shielded outputs? - pub fn has_transparent_or_shielded_outputs(&self) -> bool { - !self.outputs().is_empty() || self.has_shielded_outputs() - } - /// Does this transaction have shielded outputs? /// /// See [`Self::has_transparent_or_shielded_outputs`] for details. @@ -343,6 +338,11 @@ impl Transaction { .contains(orchard::Flags::ENABLE_OUTPUTS)) } + /// Does this transaction have transparent or shielded outputs? + pub fn has_transparent_or_shielded_outputs(&self) -> bool { + !self.outputs().is_empty() || self.has_shielded_outputs() + } + /// Does this transaction has at least one flag when we have at least one orchard action? pub fn has_enough_orchard_flags(&self) -> bool { if self.version() < 5 || self.orchard_actions().count() == 0 { @@ -499,37 +499,6 @@ impl Transaction { } } - /// Modify the expiry height of this transaction. - /// - /// # Panics - /// - /// - if called on a v1 or v2 transaction - #[cfg(any(test, feature = "proptest-impl"))] - pub fn expiry_height_mut(&mut self) -> &mut block::Height { - match self { - Transaction::V1 { .. } | Transaction::V2 { .. } => { - panic!("v1 and v2 transactions are not supported") - } - Transaction::V3 { - ref mut expiry_height, - .. - } - | Transaction::V4 { - ref mut expiry_height, - .. - } - | Transaction::V5 { - ref mut expiry_height, - .. - } => expiry_height, - #[cfg(feature = "tx_v6")] - Transaction::V6 { - ref mut expiry_height, - .. - } => expiry_height, - } - } - /// Get this transaction's network upgrade field, if any. /// This field is serialized as `nConsensusBranchId` ([7.1]). /// @@ -565,20 +534,6 @@ impl Transaction { } } - /// Modify the transparent inputs of this transaction, regardless of version. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn inputs_mut(&mut self) -> &mut Vec { - match self { - Transaction::V1 { ref mut inputs, .. } => inputs, - Transaction::V2 { ref mut inputs, .. } => inputs, - Transaction::V3 { ref mut inputs, .. } => inputs, - Transaction::V4 { ref mut inputs, .. } => inputs, - Transaction::V5 { ref mut inputs, .. } => inputs, - #[cfg(feature = "tx_v6")] - Transaction::V6 { ref mut inputs, .. } => inputs, - } - } - /// Access the [`transparent::OutPoint`]s spent by this transaction's [`transparent::Input`]s. pub fn spent_outpoints(&self) -> impl Iterator + '_ { self.inputs() @@ -599,32 +554,6 @@ impl Transaction { } } - /// Modify the transparent outputs of this transaction, regardless of version. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn outputs_mut(&mut self) -> &mut Vec { - match self { - Transaction::V1 { - ref mut outputs, .. - } => outputs, - Transaction::V2 { - ref mut outputs, .. - } => outputs, - Transaction::V3 { - ref mut outputs, .. - } => outputs, - Transaction::V4 { - ref mut outputs, .. - } => outputs, - Transaction::V5 { - ref mut outputs, .. - } => outputs, - #[cfg(feature = "tx_v6")] - Transaction::V6 { - ref mut outputs, .. - } => outputs, - } - } - /// Returns `true` if this transaction has valid inputs for a coinbase /// transaction, that is, has a single input and it is a coinbase input /// (null prevout). @@ -1232,14 +1161,6 @@ impl Transaction { .map_err(ValueBalanceError::Transparent) } - /// Modify the transparent output values of this transaction, regardless of version. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn output_values_mut(&mut self) -> impl Iterator> { - self.outputs_mut() - .iter_mut() - .map(|output| &mut output.value) - } - /// Returns the `vpub_old` fields from `JoinSplit`s in this transaction, /// regardless of version, in the order they appear in the transaction. /// @@ -1289,57 +1210,6 @@ impl Transaction { } } - /// Modify the `vpub_old` fields from `JoinSplit`s in this transaction, - /// regardless of version, in the order they appear in the transaction. - /// - /// See `output_values_to_sprout` for details. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn output_values_to_sprout_mut( - &mut self, - ) -> Box> + '_> { - match self { - // JoinSplits with Bctv14 Proofs - Transaction::V2 { - joinsplit_data: Some(joinsplit_data), - .. - } - | Transaction::V3 { - joinsplit_data: Some(joinsplit_data), - .. - } => Box::new( - joinsplit_data - .joinsplits_mut() - .map(|joinsplit| &mut joinsplit.vpub_old), - ), - // JoinSplits with Groth16 Proofs - Transaction::V4 { - joinsplit_data: Some(joinsplit_data), - .. - } => Box::new( - joinsplit_data - .joinsplits_mut() - .map(|joinsplit| &mut joinsplit.vpub_old), - ), - // No JoinSplits - Transaction::V1 { .. } - | Transaction::V2 { - joinsplit_data: None, - .. - } - | Transaction::V3 { - joinsplit_data: None, - .. - } - | Transaction::V4 { - joinsplit_data: None, - .. - } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), - #[cfg(feature = "tx_v6")] - Transaction::V6 { .. } => Box::new(std::iter::empty()), - } - } - /// Returns the `vpub_new` fields from `JoinSplit`s in this transaction, /// regardless of version, in the order they appear in the transaction. /// @@ -1389,57 +1259,6 @@ impl Transaction { } } - /// Modify the `vpub_new` fields from `JoinSplit`s in this transaction, - /// regardless of version, in the order they appear in the transaction. - /// - /// See `input_values_from_sprout` for details. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn input_values_from_sprout_mut( - &mut self, - ) -> Box> + '_> { - match self { - // JoinSplits with Bctv14 Proofs - Transaction::V2 { - joinsplit_data: Some(joinsplit_data), - .. - } - | Transaction::V3 { - joinsplit_data: Some(joinsplit_data), - .. - } => Box::new( - joinsplit_data - .joinsplits_mut() - .map(|joinsplit| &mut joinsplit.vpub_new), - ), - // JoinSplits with Groth Proofs - Transaction::V4 { - joinsplit_data: Some(joinsplit_data), - .. - } => Box::new( - joinsplit_data - .joinsplits_mut() - .map(|joinsplit| &mut joinsplit.vpub_new), - ), - // No JoinSplits - Transaction::V1 { .. } - | Transaction::V2 { - joinsplit_data: None, - .. - } - | Transaction::V3 { - joinsplit_data: None, - .. - } - | Transaction::V4 { - joinsplit_data: None, - .. - } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), - #[cfg(feature = "tx_v6")] - Transaction::V6 { .. } => Box::new(std::iter::empty()), - } - } - /// Return a list of sprout value balances, /// the changes in the transaction value pool due to each sprout `JoinSplit`. /// @@ -1548,45 +1367,6 @@ impl Transaction { ValueBalance::from_sapling_amount(sapling_value_balance) } - /// Modify the `value_balance` field from the `sapling::ShieldedData` in this transaction, - /// regardless of version. - /// - /// See `sapling_value_balance` for details. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn sapling_value_balance_mut(&mut self) -> Option<&mut Amount> { - match self { - Transaction::V4 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Some(&mut sapling_shielded_data.value_balance), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Some(&mut sapling_shielded_data.value_balance), - #[cfg(feature = "tx_v6")] - Transaction::V6 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Some(&mut sapling_shielded_data.value_balance), - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { - sapling_shielded_data: None, - .. - } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } => None, - #[cfg(feature = "tx_v6")] - Transaction::V6 { - sapling_shielded_data: None, - .. - } => None, - } - } - /// Return the orchard value balance, the change in the transaction value /// pool due to [`orchard::Action`]s. /// @@ -1605,11 +1385,94 @@ impl Transaction { ValueBalance::from_orchard_amount(orchard_value_balance) } + /// Returns the value balances for this transaction using the provided transparent outputs. + pub(crate) fn value_balance_from_outputs( + &self, + outputs: &HashMap, + ) -> Result, ValueBalanceError> { + self.transparent_value_balance_from_outputs(outputs)? + + self.sprout_value_balance()? + + self.sapling_value_balance() + + self.orchard_value_balance() + } + + /// Returns the value balances for this transaction. + /// + /// These are the changes in the transaction value pool, split up into transparent, Sprout, + /// Sapling, and Orchard values. + /// + /// Calculated as the sum of the inputs and outputs from each pool, or the sum of the value + /// balances from each pool. + /// + /// Positive values are added to this transaction's value pool, and removed from the + /// corresponding chain value pool. Negative values are removed from this transaction, and added + /// to the corresponding pool. + /// + /// + /// + /// `utxos` must contain the utxos of every input in the transaction, including UTXOs created by + /// earlier transactions in this block. + /// + /// ## Note + /// + /// The chain value pool has the opposite sign to the transaction value pool. + pub fn value_balance( + &self, + utxos: &HashMap, + ) -> Result, ValueBalanceError> { + self.value_balance_from_outputs(&outputs_from_utxos(utxos.clone())) + } +} + +#[cfg(any(test, feature = "proptest-impl"))] +impl Transaction { + /// Modify the expiry height of this transaction. + /// + /// # Panics + /// + /// - if called on a v1 or v2 transaction + pub fn expiry_height_mut(&mut self) -> &mut block::Height { + match self { + Transaction::V1 { .. } | Transaction::V2 { .. } => { + panic!("v1 and v2 transactions are not supported") + } + Transaction::V3 { + ref mut expiry_height, + .. + } + | Transaction::V4 { + ref mut expiry_height, + .. + } + | Transaction::V5 { + ref mut expiry_height, + .. + } => expiry_height, + #[cfg(feature = "tx_v6")] + Transaction::V6 { + ref mut expiry_height, + .. + } => expiry_height, + } + } + + /// Modify the transparent inputs of this transaction, regardless of version. + pub fn inputs_mut(&mut self) -> &mut Vec { + match self { + Transaction::V1 { ref mut inputs, .. } => inputs, + Transaction::V2 { ref mut inputs, .. } => inputs, + Transaction::V3 { ref mut inputs, .. } => inputs, + Transaction::V4 { ref mut inputs, .. } => inputs, + Transaction::V5 { ref mut inputs, .. } => inputs, + #[cfg(feature = "tx_v6")] + Transaction::V6 { ref mut inputs, .. } => inputs, + } + } + /// Modify the `value_balance` field from the `orchard::ShieldedData` in this transaction, /// regardless of version. /// /// See `orchard_value_balance` for details. - #[cfg(any(test, feature = "proptest-impl"))] pub fn orchard_value_balance_mut(&mut self) -> Option<&mut Amount> { match self { Transaction::V5 { @@ -1640,41 +1503,173 @@ impl Transaction { } } - /// Returns the value balances for this transaction using the provided transparent outputs. - pub(crate) fn value_balance_from_outputs( - &self, - outputs: &HashMap, - ) -> Result, ValueBalanceError> { - self.transparent_value_balance_from_outputs(outputs)? - + self.sprout_value_balance()? - + self.sapling_value_balance() - + self.orchard_value_balance() + /// Modify the `value_balance` field from the `sapling::ShieldedData` in this transaction, + /// regardless of version. + /// + /// See `sapling_value_balance` for details. + pub fn sapling_value_balance_mut(&mut self) -> Option<&mut Amount> { + match self { + Transaction::V4 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Some(&mut sapling_shielded_data.value_balance), + Transaction::V5 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Some(&mut sapling_shielded_data.value_balance), + #[cfg(feature = "tx_v6")] + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Some(&mut sapling_shielded_data.value_balance), + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { + sapling_shielded_data: None, + .. + } + | Transaction::V5 { + sapling_shielded_data: None, + .. + } => None, + #[cfg(feature = "tx_v6")] + Transaction::V6 { + sapling_shielded_data: None, + .. + } => None, + } } - /// Returns the value balances for this transaction. - /// - /// These are the changes in the transaction value pool, split up into transparent, Sprout, - /// Sapling, and Orchard values. - /// - /// Calculated as the sum of the inputs and outputs from each pool, or the sum of the value - /// balances from each pool. - /// - /// Positive values are added to this transaction's value pool, and removed from the - /// corresponding chain value pool. Negative values are removed from this transaction, and added - /// to the corresponding pool. - /// - /// - /// - /// `utxos` must contain the utxos of every input in the transaction, including UTXOs created by - /// earlier transactions in this block. + /// Modify the `vpub_new` fields from `JoinSplit`s in this transaction, + /// regardless of version, in the order they appear in the transaction. /// - /// ## Note + /// See `input_values_from_sprout` for details. + pub fn input_values_from_sprout_mut( + &mut self, + ) -> Box> + '_> { + match self { + // JoinSplits with Bctv14 Proofs + Transaction::V2 { + joinsplit_data: Some(joinsplit_data), + .. + } + | Transaction::V3 { + joinsplit_data: Some(joinsplit_data), + .. + } => Box::new( + joinsplit_data + .joinsplits_mut() + .map(|joinsplit| &mut joinsplit.vpub_new), + ), + // JoinSplits with Groth Proofs + Transaction::V4 { + joinsplit_data: Some(joinsplit_data), + .. + } => Box::new( + joinsplit_data + .joinsplits_mut() + .map(|joinsplit| &mut joinsplit.vpub_new), + ), + // No JoinSplits + Transaction::V1 { .. } + | Transaction::V2 { + joinsplit_data: None, + .. + } + | Transaction::V3 { + joinsplit_data: None, + .. + } + | Transaction::V4 { + joinsplit_data: None, + .. + } + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), + } + } + + /// Modify the `vpub_old` fields from `JoinSplit`s in this transaction, + /// regardless of version, in the order they appear in the transaction. /// - /// The chain value pool has the opposite sign to the transaction value pool. - pub fn value_balance( - &self, - utxos: &HashMap, - ) -> Result, ValueBalanceError> { - self.value_balance_from_outputs(&outputs_from_utxos(utxos.clone())) + /// See `output_values_to_sprout` for details. + pub fn output_values_to_sprout_mut( + &mut self, + ) -> Box> + '_> { + match self { + // JoinSplits with Bctv14 Proofs + Transaction::V2 { + joinsplit_data: Some(joinsplit_data), + .. + } + | Transaction::V3 { + joinsplit_data: Some(joinsplit_data), + .. + } => Box::new( + joinsplit_data + .joinsplits_mut() + .map(|joinsplit| &mut joinsplit.vpub_old), + ), + // JoinSplits with Groth16 Proofs + Transaction::V4 { + joinsplit_data: Some(joinsplit_data), + .. + } => Box::new( + joinsplit_data + .joinsplits_mut() + .map(|joinsplit| &mut joinsplit.vpub_old), + ), + // No JoinSplits + Transaction::V1 { .. } + | Transaction::V2 { + joinsplit_data: None, + .. + } + | Transaction::V3 { + joinsplit_data: None, + .. + } + | Transaction::V4 { + joinsplit_data: None, + .. + } + | Transaction::V5 { .. } => Box::new(std::iter::empty()), + #[cfg(feature = "tx_v6")] + Transaction::V6 { .. } => Box::new(std::iter::empty()), + } + } + + /// Modify the transparent output values of this transaction, regardless of version. + pub fn output_values_mut(&mut self) -> impl Iterator> { + self.outputs_mut() + .iter_mut() + .map(|output| &mut output.value) + } + + /// Modify the transparent outputs of this transaction, regardless of version. + pub fn outputs_mut(&mut self) -> &mut Vec { + match self { + Transaction::V1 { + ref mut outputs, .. + } => outputs, + Transaction::V2 { + ref mut outputs, .. + } => outputs, + Transaction::V3 { + ref mut outputs, .. + } => outputs, + Transaction::V4 { + ref mut outputs, .. + } => outputs, + Transaction::V5 { + ref mut outputs, .. + } => outputs, + #[cfg(feature = "tx_v6")] + Transaction::V6 { + ref mut outputs, .. + } => outputs, + } } } From 55aa6ee7a37a9b2fda958888df32d74cb4448f52 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 15 Aug 2025 12:49:26 +0200 Subject: [PATCH 05/22] Fix feature tx_v6 flag names missed in the previous merge --- zebra-chain/src/transaction/tests/vectors.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zebra-chain/src/transaction/tests/vectors.rs b/zebra-chain/src/transaction/tests/vectors.rs index 613abb42545..636813236c6 100644 --- a/zebra-chain/src/transaction/tests/vectors.rs +++ b/zebra-chain/src/transaction/tests/vectors.rs @@ -31,7 +31,7 @@ lazy_static! { orchard_shielded_data: None, }; - #[cfg(feature = "tx-v6")] + #[cfg(feature = "tx_v6")] pub static ref EMPTY_V6_TX: Transaction = Transaction::V6 { network_upgrade: NetworkUpgrade::Nu7, lock_time: LockTime::min_lock_time_timestamp(), @@ -326,7 +326,7 @@ fn empty_v5_round_trip() { tx_round_trip(&EMPTY_V5_TX) } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] /// An empty transaction v6, with no Orchard/OrchardZSA, Sapling, or Transparent data /// /// empty transaction are invalid, but Zebra only checks this rule in @@ -351,7 +351,7 @@ fn empty_v5_librustzcash_round_trip() { tx_librustzcash_round_trip(&EMPTY_V5_TX); } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] /// Check if an empty V6 transaction can be deserialized by librustzcash too. #[test] fn empty_v6_librustzcash_round_trip() { @@ -482,7 +482,7 @@ fn fake_v5_round_trip_for_network(network: Network) { } } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] /// Do a serialization round-trip on OrchardZSA workflow blocks and their V6 /// transactions. #[test] @@ -629,7 +629,7 @@ fn fake_v5_librustzcash_round_trip_for_network(network: Network) { } } -#[cfg(feature = "tx-v6")] +#[cfg(feature = "tx_v6")] /// Confirms each V6 transaction in the OrchardZSA test blocks converts to librustzcash’s /// transaction type without error. #[test] From e6932a22cf2c4da225aa86c48c330cb53b789e2a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 25 Aug 2025 12:25:25 +0200 Subject: [PATCH 06/22] Add initial support of polymorphic Orchard action in zebra-rpc/TransactionObject - need to be fixed - see FIXME comments --- zebra-chain/src/orchard.rs | 2 +- .../src/orchard/shielded_data_flavor.rs | 4 +- zebra-chain/src/transaction.rs | 37 +++++- zebra-rpc/Cargo.toml | 2 + zebra-rpc/src/methods/types/transaction.rs | 107 +++++++++++------- zebra-rpc/tests/serialization_tests.rs | 2 +- 6 files changed, 109 insertions(+), 45 deletions(-) diff --git a/zebra-chain/src/orchard.rs b/zebra-chain/src/orchard.rs index 4d7bbe0df5a..19d70bdf767 100644 --- a/zebra-chain/src/orchard.rs +++ b/zebra-chain/src/orchard.rs @@ -24,7 +24,7 @@ pub use commitment::{CommitmentRandomness, NoteCommitment, ValueCommitment}; pub use keys::Diversifier; pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey}; pub use shielded_data::{AuthorizedAction, Flags, ShieldedData}; -pub use shielded_data_flavor::{OrchardVanilla, ShieldedDataFlavor}; +pub use shielded_data_flavor::{OrchardDomainCommon, OrchardVanilla, ShieldedDataFlavor}; #[cfg(feature = "tx_v6")] pub use shielded_data_flavor::OrchardZSA; diff --git a/zebra-chain/src/orchard/shielded_data_flavor.rs b/zebra-chain/src/orchard/shielded_data_flavor.rs index 02440f83d2f..0fe94143420 100644 --- a/zebra-chain/src/orchard/shielded_data_flavor.rs +++ b/zebra-chain/src/orchard/shielded_data_flavor.rs @@ -4,9 +4,9 @@ use std::fmt::Debug; use serde::{de::DeserializeOwned, Serialize}; -use orchard::{domain::OrchardDomainCommon, orchard_flavor::OrchardFlavor}; +use orchard::orchard_flavor::OrchardFlavor; -pub use orchard::orchard_flavor::OrchardVanilla; +pub use orchard::{domain::OrchardDomainCommon, orchard_flavor::OrchardVanilla}; #[cfg(feature = "tx_v6")] pub use orchard::{note::AssetBase, orchard_flavor::OrchardZSA, value::NoteValue}; diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 5788e434d5b..98500bc2aa9 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -1048,7 +1048,42 @@ impl Transaction { // orchard - /// Iterate over the [`orchard::Action`]s in this transaction. + /// Iterate over the [`orchard::AuthorizedAction`]s in V5 transaction. + pub fn orchard_vanilla_actions( + &self, + ) -> Option>> { + if let Transaction::V5 { + orchard_shielded_data, + .. + } = self + { + orchard_shielded_data + .as_ref() + .map(|shielded_data| shielded_data.actions.iter()) + } else { + None + } + } + + /// Iterate over the [`orchard::AuthorizedAction`]s in V6 transaction. + #[cfg(feature = "tx_v6")] + pub fn orchard_zsa_actions( + &self, + ) -> Option>> { + if let Transaction::V6 { + orchard_shielded_data, + .. + } = self + { + orchard_shielded_data + .as_ref() + .map(|shielded_data| shielded_data.actions.iter()) + } else { + None + } + } + + /// Return the number of Orchard actions in this transaction. pub fn orchard_action_count(&self) -> usize { match self { Transaction::V1 { .. } diff --git a/zebra-rpc/Cargo.toml b/zebra-rpc/Cargo.toml index 4a3d09b0400..622bbadc3a0 100644 --- a/zebra-rpc/Cargo.toml +++ b/zebra-rpc/Cargo.toml @@ -36,6 +36,8 @@ proptest-impl = [ "zebra-chain/proptest-impl", ] +tx_v6 = [] + [dependencies] chrono = { workspace = true, features = ["clock", "std"] } futures = { workspace = true } diff --git a/zebra-rpc/src/methods/types/transaction.rs b/zebra-rpc/src/methods/types/transaction.rs index 70d38b7a002..83e25edd48f 100644 --- a/zebra-rpc/src/methods/types/transaction.rs +++ b/zebra-rpc/src/methods/types/transaction.rs @@ -11,12 +11,17 @@ use hex::ToHex; use zebra_chain::{ amount::{self, Amount, NegativeOrZero, NonNegative}, block::{self, merkle::AUTH_DIGEST_PLACEHOLDER, Height}, + orchard::{self, OrchardDomainCommon, OrchardVanilla, ShieldedDataFlavor}, parameters::Network, primitives::ed25519, sapling::NotSmallOrderValueCommitment, transaction::{self, SerializedTransaction, Transaction, UnminedTx, VerifiedUnminedTx}, transparent::Script, }; + +#[cfg(feature = "tx_v6")] +use zebra_chain::orchard::OrchardZSA; + use zebra_consensus::groth16::Description; use zebra_state::IntoDisk; @@ -220,6 +225,12 @@ pub struct TransactionObject { #[serde(rename = "orchard", skip_serializing_if = "Option::is_none")] pub(crate) orchard: Option, + // FIXME: Do we need to include this into TransactionObject? All IssueData fields or actions only? + // What names should we use here? + /// The OrchardZSA issuance of the transaction. + //#[serde(rename = "orchardZSAIssue", skip_serializing_if = "Option::is_none")] + //pub(crate) orchard_zsa_issue: Option From<&'a orchard::AuthorizedAction> for OrchardAction { + fn from(authorized_action: &'a orchard::AuthorizedAction) -> Self { + let action = &authorized_action.action; + + // FIXME: implement thsi correctly + let enc_ciphertext = EncCiphertextHex::V5([0u8; 580]); + //let enc_ciphertext = EncCiphertextHex::from_bytes(action.enc_ciphertext.as_ref()) + // .expect("valid Orchard encCiphertext length"); + + let cv: [u8; 32] = action.cv.into(); + let nullifier: [u8; 32] = action.nullifier.into(); + let rk: [u8; 32] = action.rk.into(); + let cm_x: [u8; 32] = action.cm_x.into(); + let ephemeral_key: [u8; 32] = action.ephemeral_key.into(); + //let enc_ciphertext: [u8; 580] = action.enc_ciphertext.into(); + let spend_auth_sig: [u8; 64] = authorized_action.spend_auth_sig.into(); + let out_ciphertext: [u8; 80] = action.out_ciphertext.into(); + + OrchardAction { + cv, + nullifier, + rk, + cm_x, + ephemeral_key, + enc_ciphertext, + spend_auth_sig, + out_ciphertext, + } + } +} + impl Default for TransactionObject { fn default() -> Self { Self { @@ -491,6 +547,8 @@ impl Default for TransactionObject { shielded_spends: Vec::new(), shielded_outputs: Vec::new(), orchard: None, + // FIXME: Do we need to add this? + //orchard_zsa_issue: None, binding_sig: None, joinsplit_pub_key: None, joinsplit_sig: None, @@ -637,45 +695,14 @@ impl TransactionObject { None } else { Some(Orchard { + // FIXME: add support of processing of orchard_zsa_actions + // FIXME: orchard_vanilla_actions/orchard_zsa_actions should return already + // flattened iteratior, i.e. no Option wrapper and an empty iterator instead of None? actions: tx - .orchard_actions() - .collect::>() - .iter() - .map(|action| { - let spend_auth_sig: [u8; 64] = tx - .orchard_shielded_data() - .and_then(|shielded_data| { - shielded_data - .actions - .iter() - .find(|authorized_action| { - authorized_action.action == **action - }) - .map(|authorized_action| { - authorized_action.spend_auth_sig.into() - }) - }) - .unwrap_or([0; 64]); - - let cv: [u8; 32] = action.cv.into(); - let nullifier: [u8; 32] = action.nullifier.into(); - let rk: [u8; 32] = action.rk.into(); - let cm_x: [u8; 32] = action.cm_x.into(); - let ephemeral_key: [u8; 32] = action.ephemeral_key.into(); - let enc_ciphertext: [u8; 580] = action.enc_ciphertext.into(); - let out_ciphertext: [u8; 80] = action.out_ciphertext.into(); - - OrchardAction { - cv, - nullifier, - rk, - cm_x, - ephemeral_key, - enc_ciphertext, - spend_auth_sig, - out_ciphertext, - } - }) + .orchard_vanilla_actions() + .into_iter() + .flatten() + .map(|authorized_action| authorized_action.into()) .collect(), value_balance: Zec::from(tx.orchard_value_balance().orchard_amount()) .lossy_zec(), diff --git a/zebra-rpc/tests/serialization_tests.rs b/zebra-rpc/tests/serialization_tests.rs index eae2cfb985a..ccc9d5e4324 100644 --- a/zebra-rpc/tests/serialization_tests.rs +++ b/zebra-rpc/tests/serialization_tests.rs @@ -730,7 +730,7 @@ fn test_get_raw_transaction_true() -> Result<(), Box> { let rk = action.rk(); let cm_x = action.cm_x(); let ephemeral_key = action.ephemeral_key(); - let enc_ciphertext = action.enc_ciphertext(); + let enc_ciphertext = action.enc_ciphertext().clone(); let spend_auth_sig = action.spend_auth_sig(); let out_ciphertext = action.out_ciphertext(); OrchardAction::new( From b9e8168b654fe144353923884d3eec8558018971 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 25 Aug 2025 13:23:44 +0200 Subject: [PATCH 07/22] Fix compilation error in zebra-consensus/src/orchard_zsa/tests.rs (because of a new interface of new_regtest method) --- zebra-consensus/src/orchard_zsa/tests.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zebra-consensus/src/orchard_zsa/tests.rs b/zebra-consensus/src/orchard_zsa/tests.rs index 237e73b2983..92611b8c161 100644 --- a/zebra-consensus/src/orchard_zsa/tests.rs +++ b/zebra-consensus/src/orchard_zsa/tests.rs @@ -18,6 +18,7 @@ use color_eyre::eyre::Report; use zebra_chain::{ block::{genesis::regtest_genesis_block, Block, Hash}, + parameters::testnet::ConfiguredActivationHeights, parameters::Network, serialization::ZcashDeserialize, }; @@ -44,7 +45,12 @@ fn create_transcript_data() -> impl Iterator Result<(), Report> { let _init_guard = zebra_test::init(); - let network = Network::new_regtest(Some(1), Some(1), Some(1)); + let network = Network::new_regtest(ConfiguredActivationHeights { + nu5: Some(1), + nu6: Some(1), + nu7: Some(1), + ..Default::default() + }); let state_service = zebra_state::init_test(&network); @@ -53,7 +59,7 @@ async fn check_zsa_workflow() -> Result<(), Report> { _transaction_verifier, _groth16_download_handle, _max_checkpoint_height, - ) = crate::router::init(Config::default(), &network, state_service.clone()).await; + ) = crate::router::init_test(Config::default(), &network, state_service.clone()).await; Transcript::from(create_transcript_data()) .check(block_verifier_router.clone()) From 54ffabe7531cf4a40fa776be8d7921645d5bf7f6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 25 Aug 2025 13:25:19 +0200 Subject: [PATCH 08/22] Fix compilation error in zebra-rpc/src/methods/types/get_block_template/zip317/tests.rs (because Address::try_from_raw_transparent_p2pkh was removed in librustzcash) --- .../types/get_block_template/zip317/tests.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/zebra-rpc/src/methods/types/get_block_template/zip317/tests.rs b/zebra-rpc/src/methods/types/get_block_template/zip317/tests.rs index e96b6a32d34..afab0921ca1 100644 --- a/zebra-rpc/src/methods/types/get_block_template/zip317/tests.rs +++ b/zebra-rpc/src/methods/types/get_block_template/zip317/tests.rs @@ -1,8 +1,14 @@ //! Tests for ZIP-317 transaction selection for block template production +use zcash_address::TryFromAddress; use zcash_keys::address::Address; -use zebra_chain::{block::Height, parameters::Network, transaction, transparent::OutPoint}; +use zebra_chain::{ + block::Height, + parameters::{Network, NetworkKind}, + transaction, + transparent::OutPoint, +}; use zebra_node_services::mempool::TransactionDependencies; use super::select_mempool_transactions; @@ -13,8 +19,10 @@ fn excludes_tx_with_unselected_dependencies() { let next_block_height = Height(1_000_000); let extra_coinbase_data = Vec::new(); let mut mempool_tx_deps = TransactionDependencies::default(); + // FIXME: is this a correct change (try_from_raw_transparent_p2pkh to try_from_transparent_p2pkh)? let miner_address = - Address::try_from_raw_transparent_p2pkh([0x7e; 20]).expect("should be a valid address"); + Address::try_from_transparent_p2pkh(NetworkKind::from(network.clone()).into(), [0x7e; 20]) + .expect("should be a valid address"); let unmined_tx = network .unmined_transactions_in_blocks(..) .next() @@ -44,8 +52,10 @@ fn includes_tx_with_selected_dependencies() { let network = Network::Mainnet; let next_block_height = Height(1_000_000); let unmined_txs: Vec<_> = network.unmined_transactions_in_blocks(..).take(3).collect(); + // FIXME: is this a correct change (try_from_raw_transparent_p2pkh to try_from_transparent_p2pkh)? let miner_address = - Address::try_from_raw_transparent_p2pkh([0x7e; 20]).expect("should be a valid address"); + Address::try_from_transparent_p2pkh(NetworkKind::from(network.clone()).into(), [0x7e; 20]) + .expect("should be a valid address"); let dependent_tx1 = unmined_txs.first().expect("should have 3 txns"); let dependent_tx2 = unmined_txs.get(1).expect("should have 3 txns"); From bd332e304df3460d2f1bee022de383d1ff282c14 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 25 Aug 2025 13:46:38 +0200 Subject: [PATCH 09/22] Sync Zebra with orchard and librustzcash synced to upstream (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Quote variables in push-deploy.yaml to pass upstream actionlint checks The actionlint job in the ZcashFoundation/zebra repository CI reported multiple SC2086 errors. This commit quotes shell variables in push-deploy.yaml to fix the linter failures. * Rename nu6 zcash_unstabl flag to nu7, update orchard and librustzcash revisions in Cargo.toml, other small changes * Replace deprecated librustzcash types with updated protocol equivalents * Fix compilation errors occured after the previous commit * Additionally rename nu6 zcash_unstable flag to nu7 in rustdocflags section of .cargo/config.toml * Fix cargo clippy issue * zebra-chain: port TryFrom→SighashType from upstream Zebra v2.4.2 (to sync with librustzcash changes) * Removed resolved FIXME * Switch to the latest zsa1 rev of librustzcash --- .cargo/config.toml | 4 +- Cargo.lock | 701 ++++++++++-------- Cargo.toml | 45 +- zebra-chain/Cargo.toml | 8 +- zebra-chain/src/parameters/network.rs | 10 +- .../src/parameters/network/tests/vectors.rs | 3 +- zebra-chain/src/parameters/network_upgrade.rs | 8 +- zebra-chain/src/primitives/address.rs | 28 +- .../src/primitives/viewing_key/sapling.rs | 2 +- .../src/primitives/zcash_primitives.rs | 42 +- zebra-chain/src/transaction/sighash.rs | 28 + zebra-chain/src/transparent/address.rs | 8 +- zebra-consensus/src/primitives/halo2/tests.rs | 4 +- zebra-network/Cargo.toml | 2 +- zebra-network/src/constants.rs | 4 +- zebra-network/src/protocol/external/types.rs | 4 +- zebra-rpc/Cargo.toml | 1 + .../src/methods/get_block_template_rpcs.rs | 2 +- zebra-scan/Cargo.toml | 1 + .../src/bin/scanning-results-reader/main.rs | 4 +- zebra-scan/src/service/scan_task/scan.rs | 6 +- zebra-scan/src/tests.rs | 4 +- zebra-scan/src/tests/vectors.rs | 2 +- 23 files changed, 540 insertions(+), 381 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index ec87157c946..4175fa37571 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -7,7 +7,7 @@ rustflags = [ "--cfg", 'feature="tx-v6"', # TODO: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) - "--cfg", "zcash_unstable=\"nu6\"", + "--cfg", "zcash_unstable=\"nu7\"", # Zebra standard lints for Rust 1.65+ @@ -92,7 +92,7 @@ rustdocflags = [ "--cfg", 'feature="tx-v6"', # TODO: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) - "--cfg", "zcash_unstable=\"nu6\"", + "--cfg", "zcash_unstable=\"nu7\"", # The -A and -W settings must be the same as the `RUSTDOCFLAGS` in: # https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/docs-deploy-firebase.yml#L68 diff --git a/Cargo.lock b/Cargo.lock index a55b28eb2a4..6ef93e20732 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,7 +62,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "generic-array", ] @@ -377,9 +377,9 @@ checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" [[package]] name = "bech32" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" [[package]] name = "bellman" @@ -431,20 +431,22 @@ dependencies = [ "rustc-hash", "shlex", "syn 2.0.85", - "which", + "which 4.4.2", ] [[package]] -name = "bip0039" -version = "0.10.1" +name = "bip32" +version = "0.6.0-pre.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef0f0152ec5cf17f49a5866afaa3439816207fd4f0a224c0211ffaf5e278426" +checksum = "143f5327f23168716be068f8e1014ba2ea16a6c91e8777bc8927da7b51e1df1f" dependencies = [ + "bs58", "hmac", - "pbkdf2", - "rand 0.8.5", - "sha2", - "unicode-normalization", + "rand_core 0.6.4", + "ripemd 0.2.0-pre.4", + "secp256k1 0.29.1", + "sha2 0.11.0-pre.4", + "subtle", "zeroize", ] @@ -528,6 +530,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd016a0ddc7cb13661bf5576073ce07330a693f8608a1320b4e20561cc12cdc" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bls12_381" version = "0.8.0" @@ -543,9 +554,9 @@ dependencies = [ [[package]] name = "bridgetree" -version = "0.4.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbfcb6c5a091e80cb3d3b0c1a7f126af4631cd5065b1f9929b139f1be8f3fb62" +checksum = "3990cc973c3b9c41c4dbb66cde22e3af77c4c7b133008d81f292ad12c27ed794" dependencies = [ "incrementalmerkletree", ] @@ -556,7 +567,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "sha2", + "sha2 0.10.8", "tinyvec", ] @@ -771,7 +782,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "inout", "zeroize", ] @@ -896,8 +907,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86ed14aa9c9f927213c6e4f3ef75faaad3406134efe84ba2cb7983431d5f0931" dependencies = [ "futures-core", - "prost 0.13.3", - "prost-types 0.13.1", + "prost", + "prost-types", "tonic", "tracing-core", ] @@ -915,8 +926,8 @@ dependencies = [ "hdrhistogram", "humantime", "hyper-util", - "prost 0.13.3", - "prost-types 0.13.1", + "prost", + "prost-types", "serde", "serde_json", "thread_local", @@ -956,6 +967,15 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.12" @@ -1072,6 +1092,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1081,7 +1110,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", "rustc_version 0.4.0", "serde", @@ -1206,9 +1235,19 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.6", +] + +[[package]] +name = "digest" +version = "0.11.0-pre.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379" +dependencies = [ + "block-buffer 0.11.0-rc.3", + "crypto-common 0.2.0-rc.1", "subtle", ] @@ -1255,11 +1294,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", - "rfc6979", "signature", - "spki", ] [[package]] @@ -1285,7 +1322,7 @@ dependencies = [ "hex", "rand_core 0.6.4", "serde", - "sha2", + "sha2 0.10.8", "zeroize", ] @@ -1323,11 +1360,10 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", - "pkcs8", "rand_core 0.6.4", "sec1", "subtle", @@ -1349,6 +1385,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "env_logger" version = "0.7.1" @@ -1361,21 +1403,12 @@ dependencies = [ [[package]] name = "equihash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" -dependencies = [ - "blake2b_simd", - "byteorder", -] - -[[package]] -name = "equihash" -version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.2.2" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ "blake2b_simd", - "byteorder", + "core2", + "document-features", ] [[package]] @@ -1386,12 +1419,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1406,8 +1439,8 @@ dependencies = [ [[package]] name = "f4jumble" -version = "0.1.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.1.1" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ "blake2b_simd", ] @@ -1473,7 +1506,7 @@ dependencies = [ "futures-sink", "nanorand", "pin-project", - "spin 0.9.8", + "spin", ] [[package]] @@ -1650,6 +1683,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getset" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "gimli" version = "0.28.1" @@ -1749,17 +1794,19 @@ dependencies = [ [[package]] name = "halo2_gadgets" -version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?branch=zsa1#90bc56539022c7b47d3da6201958ae2d5a694207" +version = "0.3.1" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#bcf4877772e24618f970908583a39331d4ae0e4b" dependencies = [ "arrayvec", "bitvec", "ff", "group", + "halo2_poseidon", "halo2_proofs", "lazy_static", "pasta_curves", "rand 0.8.5", + "sinsemilla 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "subtle", "uint 0.9.5", ] @@ -1770,10 +1817,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" +[[package]] +name = "halo2_poseidon" +version = "0.1.0" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#bcf4877772e24618f970908583a39331d4ae0e4b" +dependencies = [ + "bitvec", + "ff", + "group", + "pasta_curves", +] + [[package]] name = "halo2_proofs" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#bcf4877772e24618f970908583a39331d4ae0e4b" dependencies = [ "blake2b_simd", "ff", @@ -1823,19 +1881,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "hdwallet" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a03ba7d4c9ea41552cd4351965ff96883e629693ae85005c501bb4b9e1c48a7" -dependencies = [ - "lazy_static", - "rand_core 0.6.4", - "ring 0.16.20", - "secp256k1 0.26.0", - "thiserror", -] - [[package]] name = "heck" version = "0.3.3" @@ -1883,11 +1928,11 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0-pre.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "e4b1fb14e4df79f9406b434b60acef9f45c26c50062cccf1346c6103b8c47d58" dependencies = [ - "digest", + "digest 0.11.0-pre.9", ] [[package]] @@ -2011,6 +2056,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hybrid-array" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d35805454dc9f8662a98d6d61886ffe26bd465f5960e0e55345c70d5c0d2a9" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "0.14.30" @@ -2163,9 +2217,9 @@ dependencies = [ [[package]] name = "incrementalmerkletree" -version = "0.5.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1872810fb725b06b8c153dde9e86f3ec26747b9b60096da7a869883b549cbe" +checksum = "30821f91f0fa8660edca547918dc59812893b497d07c1144f326f07fdd94aba9" dependencies = [ "either", ] @@ -2431,8 +2485,7 @@ dependencies = [ "cfg-if 1.0.0", "ecdsa", "elliptic-curve", - "once_cell", - "sha2", + "sha2 0.10.8", "signature", ] @@ -2451,7 +2504,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -2462,9 +2515,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libgit2-sys" @@ -2553,6 +2606,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "litrs" version = "0.4.1" @@ -2618,12 +2677,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memuse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" -dependencies = [ - "nonempty", -] +checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" [[package]] name = "metrics" @@ -2762,6 +2818,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" +[[package]] +name = "nonempty" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "549e471b99ccaf2f89101bec68f4d244457d5a95a9c3d0672e9564124397741d" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2877,31 +2939,36 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" -version = "0.8.0" -source = "git+https://github.com/QED-it/orchard?rev=831ca109705a409bc3d3b82e76245e45dd0f0812#831ca109705a409bc3d3b82e76245e45dd0f0812" +version = "0.11.0" +source = "git+https://github.com/QED-it/orchard?rev=806878c75e491ec7815af86ee08d761c7ed527b5#806878c75e491ec7815af86ee08d761c7ed527b5" dependencies = [ "aes", "bitvec", "blake2b_simd", + "core2", "ff", "fpe", + "getset", "group", - "half", "halo2_gadgets", + "halo2_poseidon", "halo2_proofs", "hex", "incrementalmerkletree", "k256", "lazy_static", "memuse", - "nonempty", + "nonempty 0.11.0", "pasta_curves", "proptest", "rand 0.8.5", + "rand_core 0.6.4", "reddsa", "serde", + "sinsemilla 0.1.0 (git+https://github.com/zcash/sinsemilla?rev=aabb707e862bc3d7b803c77d14e5a771bcee3e8c)", "subtle", "tracing", + "visibility", "zcash_note_encryption", "zcash_spec", "zip32", @@ -3029,17 +3096,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "password-hash" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "pasta_curves" version = "0.5.1" @@ -3055,16 +3111,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "pbkdf2" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" -dependencies = [ - "digest", - "password-hash", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3113,7 +3159,7 @@ checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -3297,6 +3343,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -3337,16 +3405,6 @@ dependencies = [ "syn 2.0.85", ] -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", - "prost-derive 0.12.6", -] - [[package]] name = "prost" version = "0.13.3" @@ -3354,28 +3412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.13.3", -] - -[[package]] -name = "prost-build" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" -dependencies = [ - "bytes", - "heck 0.5.0", - "itertools 0.12.1", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost 0.12.6", - "prost-types 0.12.6", - "regex", - "syn 2.0.85", - "tempfile", + "prost-derive", ] [[package]] @@ -3392,26 +3429,13 @@ dependencies = [ "once_cell", "petgraph", "prettyplease", - "prost 0.13.3", - "prost-types 0.13.1", + "prost", + "prost-types", "regex", "syn 2.0.85", "tempfile", ] -[[package]] -name = "prost-derive" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" -dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.85", -] - [[package]] name = "prost-derive" version = "0.13.3" @@ -3425,22 +3449,13 @@ dependencies = [ "syn 2.0.85", ] -[[package]] -name = "prost-types" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" -dependencies = [ - "prost 0.12.6", -] - [[package]] name = "prost-types" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" dependencies = [ - "prost 0.13.3", + "prost", ] [[package]] @@ -3651,6 +3666,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "redjubjub" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b0ac1bc6bb3696d2c6f52cff8fba57238b81da8c0214ee6cd146eb8fde364e" +dependencies = [ + "rand_core 0.6.4", + "reddsa", + "thiserror", + "zeroize", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -3767,16 +3794,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - [[package]] name = "rgb" version = "0.8.47" @@ -3786,21 +3803,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -3811,8 +3813,8 @@ dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.15", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] @@ -3822,7 +3824,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest", + "digest 0.10.7", +] + +[[package]] +name = "ripemd" +version = "0.2.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48cf93482ea998ad1302c42739bc73ab3adc574890c373ec89710e219357579" +dependencies = [ + "digest 0.11.0-pre.9", ] [[package]] @@ -3900,10 +3911,23 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + [[package]] name = "rustls" version = "0.21.12" @@ -3911,7 +3935,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-webpki", "sct", ] @@ -3931,8 +3955,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3970,8 +3994,8 @@ dependencies = [ [[package]] name = "sapling-crypto" -version = "0.1.3" -source = "git+https://github.com/QED-it/sapling-crypto?branch=zsa1#99ad0a5f0bdef332bdc91d577086abd3aca59553" +version = "0.5.0" +source = "git+https://github.com/QED-it/sapling-crypto?branch=zsa1#b0d2e4c1139f23fb7e9e410f2e5d986d5662ee03" dependencies = [ "aes", "bellman", @@ -3979,10 +4003,11 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "bls12_381", - "byteorder", + "core2", "document-features", "ff", "fpe", + "getset", "group", "hex", "incrementalmerkletree", @@ -3991,7 +4016,7 @@ dependencies = [ "memuse", "rand 0.8.5", "rand_core 0.6.4", - "redjubjub", + "redjubjub 0.8.0", "subtle", "tracing", "zcash_note_encryption", @@ -4011,8 +4036,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -4024,28 +4049,27 @@ dependencies = [ "base16ct", "der", "generic-array", - "pkcs8", "subtle", "zeroize", ] [[package]] name = "secp256k1" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.8.1", + "serde", ] [[package]] name = "secp256k1" -version = "0.27.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "secp256k1-sys", - "serde", + "secp256k1-sys 0.10.1", ] [[package]] @@ -4057,6 +4081,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -4315,7 +4348,18 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540c0893cce56cdbcfebcec191ec8e0f470dd1889b6e7a0b503e310a94a168f5" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.11.0-pre.9", ] [[package]] @@ -4329,9 +4373,9 @@ dependencies = [ [[package]] name = "shardtree" -version = "0.3.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cdd24424ce0b381646737fedddc33c4dcf7dcd2d545056b53f7982097bef5" +checksum = "637e95dcd06bc1bb3f86ed9db1e1832a70125f32daae071ef37dcb7701b7d4fe" dependencies = [ "bitflags 2.6.0", "either", @@ -4360,7 +4404,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -4370,6 +4414,27 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +[[package]] +name = "sinsemilla" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d268ae0ea06faafe1662e9967cd4f9022014f5eeb798e0c302c876df8b7af9c" +dependencies = [ + "group", + "pasta_curves", + "subtle", +] + +[[package]] +name = "sinsemilla" +version = "0.1.0" +source = "git+https://github.com/zcash/sinsemilla?rev=aabb707e862bc3d7b803c77d14e5a771bcee3e8c#aabb707e862bc3d7b803c77d14e5a771bcee3e8c" +dependencies = [ + "group", + "pasta_curves", + "subtle", +] + [[package]] name = "sketches-ddsketch" version = "0.3.0" @@ -4423,12 +4488,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -4504,9 +4563,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -4590,7 +4649,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "once_cell", - "rustix", + "rustix 0.38.37", "windows-sys 0.59.0", ] @@ -4880,7 +4939,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.3", + "prost", "socket2", "tokio", "tokio-stream", @@ -4892,27 +4951,28 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.10.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2", - "prost-build 0.12.6", + "prost-build", + "prost-types", "quote", "syn 2.0.85", ] [[package]] name = "tonic-build" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" +checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" dependencies = [ "prettyplease", "proc-macro2", - "prost-build 0.13.1", - "prost-types 0.13.1", + "prost-build", + "prost-types", "quote", "syn 2.0.85", ] @@ -4923,8 +4983,8 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "878d81f52e7fcfd80026b7fdb6a9b578b3c3653ba987f87f0dce4b64043cba27" dependencies = [ - "prost 0.13.3", - "prost-types 0.13.1", + "prost", + "prost-types", "tokio", "tokio-stream", "tonic", @@ -5271,16 +5331,10 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.6", "subtle", ] -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -5369,6 +5423,17 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "visibility" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "void" version = "1.0.2" @@ -5556,7 +5621,19 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.37", +] + +[[package]] +name = "which" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +dependencies = [ + "either", + "env_home", + "rustix 1.0.8", + "winsafe", ] [[package]] @@ -5785,6 +5862,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "wyz" version = "0.5.1" @@ -5814,11 +5897,12 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" -version = "0.3.2" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.8.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ "bech32", "bs58", + "core2", "f4jumble", "zcash_encoding", "zcash_protocol", @@ -5826,10 +5910,10 @@ dependencies = [ [[package]] name = "zcash_client_backend" -version = "0.12.1" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.19.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bech32", "bls12_381", "bs58", @@ -5839,10 +5923,9 @@ dependencies = [ "hex", "incrementalmerkletree", "memuse", - "nom", - "nonempty", + "nonempty 0.11.0", "percent-encoding", - "prost 0.12.6", + "prost", "rand_core 0.6.4", "rayon", "sapling-crypto", @@ -5850,32 +5933,34 @@ dependencies = [ "shardtree", "subtle", "time", - "tonic-build 0.10.2", + "time-core", + "tonic-build 0.13.1", "tracing", - "which", + "which 7.0.3", "zcash_address", "zcash_encoding", "zcash_keys", "zcash_note_encryption", "zcash_primitives", "zcash_protocol", + "zcash_transparent", "zip32", "zip321", ] [[package]] name = "zcash_encoding" -version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.3.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ - "byteorder", - "nonempty", + "core2", + "nonempty 0.11.0", ] [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ "blake2b_simd", "byteorder", @@ -5884,17 +5969,18 @@ dependencies = [ [[package]] name = "zcash_keys" -version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.9.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ "bech32", "blake2b_simd", "bls12_381", "bs58", + "core2", "document-features", "group", "memuse", - "nonempty", + "nonempty 0.11.0", "rand_core 0.6.4", "sapling-crypto", "secrecy", @@ -5902,15 +5988,15 @@ dependencies = [ "tracing", "zcash_address", "zcash_encoding", - "zcash_primitives", "zcash_protocol", + "zcash_transparent", "zip32", ] [[package]] name = "zcash_note_encryption" -version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#76745f00551d4442dee11ad64a8400b75132d18f" +version = "0.4.1" +source = "git+https://github.com/zcash/zcash_note_encryption?branch=main#668ea44cf59a226715a5f3cb1bf88710a8c188a3" dependencies = [ "chacha20", "chacha20poly1305", @@ -5921,32 +6007,34 @@ dependencies = [ [[package]] name = "zcash_primitives" -version = "0.15.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.23.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ - "aes", - "bip0039", + "bip32", "blake2b_simd", - "byteorder", + "block-buffer 0.11.0-rc.3", + "bs58", + "core2", + "crypto-common 0.2.0-rc.1", "document-features", - "equihash 0.2.0 (git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4)", + "equihash", "ff", "fpe", + "getset", "group", - "hdwallet", "hex", "incrementalmerkletree", "jubjub", "memuse", - "nonempty", + "nonempty 0.11.0", "orchard", "rand 0.8.5", "rand_core 0.6.4", - "redjubjub", - "ripemd", + "redjubjub 0.8.0", + "ripemd 0.1.3", "sapling-crypto", - "secp256k1 0.26.0", - "sha2", + "secp256k1 0.29.1", + "sha2 0.10.8", "subtle", "tracing", "zcash_address", @@ -5954,14 +6042,14 @@ dependencies = [ "zcash_note_encryption", "zcash_protocol", "zcash_spec", + "zcash_transparent", "zip32", ] [[package]] name = "zcash_proofs" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5163a1110f4265cc5f2fdf87ac4497fd1e014b6ce0760ca8d16d8e3853a5c0f7" +version = "0.23.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ "bellman", "blake2b_simd", @@ -5973,7 +6061,7 @@ dependencies = [ "known-folders", "lazy_static", "rand_core 0.6.4", - "redjubjub", + "redjubjub 0.8.0", "sapling-crypto", "tracing", "xdg", @@ -5982,10 +6070,12 @@ dependencies = [ [[package]] name = "zcash_protocol" -version = "0.1.1" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.5.3" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ + "core2", "document-features", + "hex", "memuse", ] @@ -6001,13 +6091,36 @@ dependencies = [ [[package]] name = "zcash_spec" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b" +checksum = "ded3f58b93486aa79b85acba1001f5298f27a46489859934954d262533ee2915" dependencies = [ "blake2b_simd", ] +[[package]] +name = "zcash_transparent" +version = "0.3.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" +dependencies = [ + "bip32", + "blake2b_simd", + "bs58", + "core2", + "document-features", + "getset", + "hex", + "ripemd 0.1.3", + "secp256k1 0.29.1", + "sha2 0.10.8", + "subtle", + "zcash_address", + "zcash_encoding", + "zcash_protocol", + "zcash_spec", + "zip32", +] + [[package]] name = "zebra-chain" version = "1.0.0-beta.41" @@ -6025,7 +6138,7 @@ dependencies = [ "criterion", "dirs", "ed25519-zebra", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "equihash", "futures", "group", "halo2_proofs", @@ -6035,7 +6148,7 @@ dependencies = [ "itertools 0.13.0", "jubjub", "lazy_static", - "nonempty", + "nonempty 0.7.0", "num-integer", "orchard", "primitive-types", @@ -6046,15 +6159,15 @@ dependencies = [ "rand_core 0.6.4", "rayon", "reddsa", - "redjubjub", - "ripemd", + "redjubjub 0.7.0", + "ripemd 0.1.3", "sapling-crypto", "secp256k1 0.27.0", "serde", "serde-big-array", "serde_json", "serde_with 3.11.0", - "sha2", + "sha2 0.10.8", "spandoc", "static_assertions", "tempfile", @@ -6071,6 +6184,7 @@ dependencies = [ "zcash_note_encryption", "zcash_primitives", "zcash_protocol", + "zcash_transparent", "zebra-test", ] @@ -6127,7 +6241,7 @@ dependencies = [ "color-eyre", "futures-util", "insta", - "prost 0.13.3", + "prost", "serde", "tokio", "tokio-stream", @@ -6212,7 +6326,7 @@ dependencies = [ "jsonrpc-http-server", "nix", "proptest", - "prost 0.13.3", + "prost", "rand 0.8.5", "serde", "serde_json", @@ -6226,6 +6340,7 @@ dependencies = [ "tracing", "zcash_address", "zcash_primitives", + "zcash_protocol", "zebra-chain", "zebra-consensus", "zebra-network", @@ -6272,6 +6387,7 @@ dependencies = [ "zcash_keys", "zcash_note_encryption", "zcash_primitives", + "zcash_protocol", "zebra-chain", "zebra-grpc", "zebra-node-services", @@ -6431,7 +6547,7 @@ dependencies = [ "pin-project", "proptest", "proptest-derive", - "prost 0.13.3", + "prost", "rand 0.8.5", "rayon", "regex", @@ -6512,21 +6628,22 @@ dependencies = [ [[package]] name = "zip32" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e" +checksum = "13ff9ea444cdbce820211f91e6aa3d3a56bde7202d3c0961b7c38f793abf5637" dependencies = [ "blake2b_simd", "memuse", "subtle", + "zcash_spec", ] [[package]] name = "zip321" -version = "0.0.0" -source = "git+https://github.com/QED-it/librustzcash?rev=e88964e248c9038e757771b8225c47ac8772abc4#e88964e248c9038e757771b8225c47ac8772abc4" +version = "0.4.0" +source = "git+https://github.com/QED-it/librustzcash?rev=a996e53e7a561a4723be6a712e44c8eb5fad4a6c#a996e53e7a561a4723be6a712e44c8eb5fad4a6c" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "nom", "percent-encoding", "zcash_address", diff --git a/Cargo.toml b/Cargo.toml index 4af9a635ce4..78c2e69381c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,18 +22,19 @@ resolver = "2" # `cargo release` settings [workspace.dependencies] -incrementalmerkletree = "0.5.1" -orchard = "0.8.0" -sapling-crypto = "0.1.3" +incrementalmerkletree = "0.8.2" +orchard = "0.11.0" +sapling-crypto = "0.5" # The dependency versions below are in accordance with the currently used orchard version. zcash_history = "0.4.0" -zcash_address = "0.3.2" -zcash_client_backend = "0.12.1" -zcash_encoding = "0.2.0" -zcash_keys = "0.2.0" -zcash_primitives = "0.15.0" -zcash_proofs = "0.15.0" -zcash_protocol = "0.1.1" +zcash_address = "0.8.0" +zcash_client_backend = "0.19.0" +zcash_encoding = "0.3.0" +zcash_keys = "0.9.0" +zcash_primitives = "0.23.0" +zcash_proofs = "0.23.0" +zcash_protocol = "0.5.3" +zcash_transparent = "0.3.0" [workspace.metadata.release] @@ -107,13 +108,17 @@ lto = "thin" [patch.crates-io] halo2_proofs = { version = "0.3.0", git = "https://github.com/QED-it/halo2", branch = "zsa1" } halo2_gadgets = { version = "0.3.0", git = "https://github.com/QED-it/halo2", branch = "zsa1" } -zcash_note_encryption = { version = "0.4.0", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" } -sapling-crypto = { version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "zsa1" } -orchard = { version = "0.8.0", git = "https://github.com/QED-it/orchard", rev = "831ca109705a409bc3d3b82e76245e45dd0f0812" } -zcash_primitives = { version = "0.15.0", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } -zcash_protocol = { version = "0.1.1", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } -zcash_address = { version = "0.3.2", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } -zcash_encoding = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } -zcash_history = { version = "0.4.0", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } -zcash_client_backend = { version = "0.12.1", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } -zcash_keys = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", rev = "e88964e248c9038e757771b8225c47ac8772abc4" } +halo2_poseidon = { version = "0.1.0", git = "https://github.com/QED-it/halo2", branch = "zsa1" } +zcash_note_encryption = { version = "0.4.1", git = "https://github.com/zcash/zcash_note_encryption", branch = "main" } +sapling-crypto = { package = "sapling-crypto", version = "0.5", git = "https://github.com/QED-it/sapling-crypto", branch = "zsa1" } +orchard = { version = "0.11.0", git = "https://github.com/QED-it/orchard", rev = "806878c75e491ec7815af86ee08d761c7ed527b5" } +zcash_primitives = { version = "0.23.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_protocol = { version = "0.5.3", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_address = { version = "0.8.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_encoding = { version = "0.3.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_history = { version = "0.4.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_client_backend = { version = "0.19.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_keys = { version = "0.9.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_transparent = { version = "0.3.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +zcash_proofs = { version = "0.23.0", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } +equihash = { version = "0.2.2", git = "https://github.com/QED-it/librustzcash", rev = "a996e53e7a561a4723be6a712e44c8eb5fad4a6c" } diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 358b556f105..55c9e5ecb1c 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -74,15 +74,14 @@ bitflags = "2.5.0" bitflags-serde-legacy = "0.1.1" blake2b_simd = "1.0.2" blake2s_simd = "1.0.2" -# TODO: Revert to "0.6.0" (or appropriate version) when the ZSA orchard fork is updated. -bridgetree = "0.4.0" +bridgetree = "0.7.0" bs58 = { version = "0.5.1", features = ["check"] } byteorder = "1.5.0" # TODO: Internal miner feature functionality was removed at https://github.com/ZcashFoundation/zebra/issues/8180 # See what was removed at https://github.com/ZcashFoundation/zebra/blob/v1.5.1/zebra-chain/Cargo.toml#L73-L85 # Restore support when conditions are met. https://github.com/ZcashFoundation/zebra/issues/8183 -equihash = "0.2.0" +equihash = "0.2.2" group = "0.13.0" incrementalmerkletree.workspace = true @@ -110,6 +109,7 @@ zcash_primitives = { workspace = true, features = ["transparent-inputs"] } sapling-crypto.workspace = true zcash_protocol.workspace = true zcash_address.workspace = true +zcash_transparent.workspace = true # Used for orchard serialization nonempty = { version = "0.7", optional = true } @@ -192,4 +192,4 @@ name = "redpallas" harness = false [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu7"))'] } diff --git a/zebra-chain/src/parameters/network.rs b/zebra-chain/src/parameters/network.rs index d119c087dd9..ec4d26301bb 100644 --- a/zebra-chain/src/parameters/network.rs +++ b/zebra-chain/src/parameters/network.rs @@ -58,9 +58,9 @@ impl NetworkKind { /// pay-to-public-key-hash payment addresses for the network. pub fn b58_pubkey_address_prefix(self) -> [u8; 2] { match self { - Self::Mainnet => zcash_primitives::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX, + Self::Mainnet => zcash_protocol::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX, Self::Testnet | Self::Regtest => { - zcash_primitives::constants::testnet::B58_PUBKEY_ADDRESS_PREFIX + zcash_protocol::constants::testnet::B58_PUBKEY_ADDRESS_PREFIX } } } @@ -69,9 +69,9 @@ impl NetworkKind { /// payment addresses for the network. pub fn b58_script_address_prefix(self) -> [u8; 2] { match self { - Self::Mainnet => zcash_primitives::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX, + Self::Mainnet => zcash_protocol::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX, Self::Testnet | Self::Regtest => { - zcash_primitives::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX + zcash_protocol::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX } } } @@ -279,7 +279,7 @@ impl FromStr for Network { pub struct InvalidNetworkError(String); impl zcash_protocol::consensus::Parameters for Network { - fn network_type(&self) -> zcash_address::Network { + fn network_type(&self) -> zcash_protocol::consensus::NetworkType { self.kind().into() } diff --git a/zebra-chain/src/parameters/network/tests/vectors.rs b/zebra-chain/src/parameters/network/tests/vectors.rs index 6c1426e4e0e..f15b3f6388e 100644 --- a/zebra-chain/src/parameters/network/tests/vectors.rs +++ b/zebra-chain/src/parameters/network/tests/vectors.rs @@ -1,7 +1,6 @@ //! Fixed test vectors for the network consensus parameters. -use zcash_primitives::consensus::{self as zp_consensus, Parameters}; -use zcash_protocol::consensus::NetworkConstants as _; +use zcash_protocol::consensus::{self as zp_consensus, NetworkConstants as _, Parameters}; use crate::{ block::Height, diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 3cc62abecf4..b79e4e0007e 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -95,7 +95,7 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_687_104), Nu5), (block::Height(2_726_400), Nu6), // FIXME: TODO: Use a proper value below. - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] (block::Height(3_111_000), Nu7), ]; @@ -135,7 +135,7 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_842_420), Nu5), (block::Height(2_976_000), Nu6), // FIXME: TODO: Use a proper value below. - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] (block::Height(3_222_000), Nu7), ]; @@ -229,7 +229,7 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), // FIXME: TODO: Use a proper value below. - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] (Nu7, ConsensusBranchId(0x77190ad8)), ]; @@ -550,7 +550,7 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, // TODO: Use a proper value below. - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu7, } } diff --git a/zebra-chain/src/primitives/address.rs b/zebra-chain/src/primitives/address.rs index 32ffa69b94a..42ab577216b 100644 --- a/zebra-chain/src/primitives/address.rs +++ b/zebra-chain/src/primitives/address.rs @@ -44,7 +44,7 @@ impl zcash_address::TryFromAddress for Address { type Error = BoxError; fn try_from_transparent_p2pkh( - network: zcash_address::Network, + network: zcash_protocol::consensus::NetworkType, data: [u8; 20], ) -> Result> { Ok(Self::Transparent(transparent::Address::from_pub_key_hash( @@ -54,7 +54,7 @@ impl zcash_address::TryFromAddress for Address { } fn try_from_transparent_p2sh( - network: zcash_address::Network, + network: zcash_protocol::consensus::NetworkType, data: [u8; 20], ) -> Result> { Ok(Self::Transparent(transparent::Address::from_script_hash( @@ -64,7 +64,7 @@ impl zcash_address::TryFromAddress for Address { } fn try_from_sapling( - network: zcash_address::Network, + network: zcash_protocol::consensus::NetworkType, data: [u8; 43], ) -> Result> { let network = network.into(); @@ -74,7 +74,7 @@ impl zcash_address::TryFromAddress for Address { } fn try_from_unified( - network: zcash_address::Network, + network: zcash_protocol::consensus::NetworkType, unified_address: zcash_address::unified::Address, ) -> Result> { let network = network.into(); @@ -170,27 +170,27 @@ impl Address { } } -impl From for NetworkKind { - fn from(network: zcash_address::Network) -> Self { +impl From for NetworkKind { + fn from(network: zcash_protocol::consensus::NetworkType) -> Self { match network { - zcash_address::Network::Main => NetworkKind::Mainnet, - zcash_address::Network::Test => NetworkKind::Testnet, - zcash_address::Network::Regtest => NetworkKind::Regtest, + zcash_protocol::consensus::NetworkType::Main => NetworkKind::Mainnet, + zcash_protocol::consensus::NetworkType::Test => NetworkKind::Testnet, + zcash_protocol::consensus::NetworkType::Regtest => NetworkKind::Regtest, } } } -impl From for zcash_address::Network { +impl From for zcash_protocol::consensus::NetworkType { fn from(network: NetworkKind) -> Self { match network { - NetworkKind::Mainnet => zcash_address::Network::Main, - NetworkKind::Testnet => zcash_address::Network::Test, - NetworkKind::Regtest => zcash_address::Network::Regtest, + NetworkKind::Mainnet => zcash_protocol::consensus::NetworkType::Main, + NetworkKind::Testnet => zcash_protocol::consensus::NetworkType::Test, + NetworkKind::Regtest => zcash_protocol::consensus::NetworkType::Regtest, } } } -impl From<&NetworkKind> for zcash_address::Network { +impl From<&NetworkKind> for zcash_protocol::consensus::NetworkType { fn from(network: &NetworkKind) -> Self { (*network).into() } diff --git a/zebra-chain/src/primitives/viewing_key/sapling.rs b/zebra-chain/src/primitives/viewing_key/sapling.rs index 846b9835fa9..85c0d0d2da9 100644 --- a/zebra-chain/src/primitives/viewing_key/sapling.rs +++ b/zebra-chain/src/primitives/viewing_key/sapling.rs @@ -5,7 +5,7 @@ use zcash_client_backend::{ encoding::decode_extended_full_viewing_key, keys::sapling::DiversifiableFullViewingKey as SaplingDfvk, }; -use zcash_primitives::constants::*; +use zcash_protocol::constants::*; use crate::parameters::Network; diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 90ea70324d7..f8286661c31 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -29,8 +29,8 @@ impl zp_tx::components::transparent::Authorization for TransparentAuth<'_> { // In this block we convert our Output to a librustzcash to TxOut. // (We could do the serialize/deserialize route but it's simple enough to convert manually) -impl zp_tx::sighash::TransparentAuthorizingContext for TransparentAuth<'_> { - fn input_amounts(&self) -> Vec { +impl zcash_transparent::sighash::TransparentAuthorizingContext for TransparentAuth<'_> { + fn input_amounts(&self) -> Vec { self.all_prev_outputs .iter() .map(|prevout| { @@ -137,7 +137,7 @@ impl zp_tx::components::orchard::MapAuth for IdentityMap { @@ -156,7 +156,7 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] type IssueAuth = orchard::issuance::Signed; } @@ -209,7 +209,7 @@ pub(crate) fn convert_tx_to_librustzcash( } /// Convert a Zebra transparent::Output into a librustzcash one. -impl TryFrom<&transparent::Output> for zp_tx::components::TxOut { +impl TryFrom<&transparent::Output> for zcash_transparent::bundle::TxOut { type Error = io::Error; #[allow(clippy::unwrap_in_result)] @@ -218,12 +218,12 @@ impl TryFrom<&transparent::Output> for zp_tx::components::TxOut { .zcash_serialize_to_vec() .expect("zcash_primitives and Zebra transparent output formats must be compatible"); - zp_tx::components::TxOut::read(&mut serialized_output_bytes.as_slice()) + zcash_transparent::bundle::TxOut::read(&mut serialized_output_bytes.as_slice()) } } /// Convert a Zebra transparent::Output into a librustzcash one. -impl TryFrom for zp_tx::components::TxOut { +impl TryFrom for zcash_transparent::bundle::TxOut { type Error = io::Error; // The borrow is actually needed to use TryFrom<&transparent::Output> @@ -234,11 +234,11 @@ impl TryFrom for zp_tx::components::TxOut { } /// Convert a Zebra non-negative Amount into a librustzcash one. -impl TryFrom> for zp_tx::components::amount::NonNegativeAmount { +impl TryFrom> for zcash_protocol::value::Zatoshis { type Error = BalanceError; fn try_from(amount: Amount) -> Result { - zp_tx::components::amount::NonNegativeAmount::from_nonnegative_i64(amount.into()) + zcash_protocol::value::Zatoshis::from_nonnegative_i64(amount.into()) } } @@ -323,16 +323,18 @@ pub(crate) fn sighash( let output = &precomputed_tx_data.all_previous_outputs[input_index]; lock_script = output.lock_script.clone().into(); unlock_script = zcash_primitives::legacy::Script(script_code); - zp_tx::sighash::SignableInput::Transparent { - hash_type: hash_type.bits() as _, - index: input_index, - script_code: &unlock_script, - script_pubkey: &lock_script, - value: output - .value - .try_into() - .expect("amount was previously validated"), - } + zp_tx::sighash::SignableInput::Transparent( + zcash_transparent::sighash::SignableInput::from_parts( + hash_type.try_into().expect("hash type should be ALL"), + input_index, + &unlock_script, + &lock_script, + output + .value + .try_into() + .expect("amount was previously validated"), + ), + ) } None => zp_tx::sighash::SignableInput::Shielded, }; @@ -376,7 +378,7 @@ pub(crate) fn transparent_output_address( output: &transparent::Output, network: &Network, ) -> Option { - let tx_out = zp_tx::components::TxOut::try_from(output) + let tx_out = zcash_transparent::bundle::TxOut::try_from(output) .expect("zcash_primitives and Zebra transparent output formats must be compatible"); let alt_addr = tx_out.recipient_address(); diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index 24d58a77b38..4fc1eed5b04 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -1,5 +1,7 @@ //! Signature hashes for Zcash transactions +use zcash_transparent::sighash::SighashType; + use super::Transaction; use crate::parameters::ConsensusBranchId; @@ -19,6 +21,32 @@ bitflags::bitflags! { const SINGLE = Self::ALL.bits() | Self::NONE.bits(); /// Anyone can add inputs to this transaction const ANYONECANPAY = 0b1000_0000; + + /// Sign all the outputs and Anyone can add inputs to this transaction + const ALL_ANYONECANPAY = Self::ALL.bits() | Self::ANYONECANPAY.bits(); + /// Sign none of the outputs and Anyone can add inputs to this transaction + const NONE_ANYONECANPAY = Self::NONE.bits() | Self::ANYONECANPAY.bits(); + /// Sign one of the outputs and Anyone can add inputs to this transaction + const SINGLE_ANYONECANPAY = Self::SINGLE.bits() | Self::ANYONECANPAY.bits(); + } +} + +// FIXME (for future reviewers): Copied from upstream Zebra v2.4.2 to fix a librustzcash +// breaking change. Keep the code (or update it accordingly) and remove this note when we +// merge with upstream Zebra. +impl TryFrom for SighashType { + type Error = (); + + fn try_from(hash_type: HashType) -> Result { + Ok(match hash_type { + HashType::ALL => Self::ALL, + HashType::NONE => Self::NONE, + HashType::SINGLE => Self::SINGLE, + HashType::ALL_ANYONECANPAY => Self::ALL_ANYONECANPAY, + HashType::NONE_ANYONECANPAY => Self::NONE_ANYONECANPAY, + HashType::SINGLE_ANYONECANPAY => Self::SINGLE_ANYONECANPAY, + _other => return Err(()), + }) } } diff --git a/zebra-chain/src/transparent/address.rs b/zebra-chain/src/transparent/address.rs index 1b933af2ef0..3855b7e9600 100644 --- a/zebra-chain/src/transparent/address.rs +++ b/zebra-chain/src/transparent/address.rs @@ -121,25 +121,25 @@ impl ZcashDeserialize for Address { reader.read_exact(&mut hash_bytes)?; match version_bytes { - zcash_primitives::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX => { + zcash_protocol::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX => { Ok(Address::PayToScriptHash { network_kind: NetworkKind::Mainnet, script_hash: hash_bytes, }) } - zcash_primitives::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX => { + zcash_protocol::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX => { Ok(Address::PayToScriptHash { network_kind: NetworkKind::Testnet, script_hash: hash_bytes, }) } - zcash_primitives::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX => { + zcash_protocol::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX => { Ok(Address::PayToPublicKeyHash { network_kind: NetworkKind::Mainnet, pub_key_hash: hash_bytes, }) } - zcash_primitives::constants::testnet::B58_PUBKEY_ADDRESS_PREFIX => { + zcash_protocol::constants::testnet::B58_PUBKEY_ADDRESS_PREFIX => { Ok(Address::PayToPublicKeyHash { network_kind: NetworkKind::Testnet, pub_key_hash: hash_bytes, diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index beb644a0c1f..a149fa1a39e 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -54,6 +54,8 @@ where ); for _ in 0..num_recipients { + let mut memo: [u8; 512] = [0; 512]; + memo[0] = 0xF6; builder .add_output( None, @@ -61,7 +63,7 @@ where NoteValue::from_raw(note_value), // FIXME: Use another AssetBase for OrchardZSA? AssetBase::native(), - None, + memo, ) .unwrap(); } diff --git a/zebra-network/Cargo.toml b/zebra-network/Cargo.toml index aca4b02bd6c..f1f8d1ad3f0 100644 --- a/zebra-network/Cargo.toml +++ b/zebra-network/Cargo.toml @@ -97,4 +97,4 @@ zebra-chain = { path = "../zebra-chain", features = ["proptest-impl"] } zebra-test = { path = "../zebra-test/" } [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu7"))'] } diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index d9615131542..23b1a0a5ef0 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -341,11 +341,11 @@ pub const TIMESTAMP_TRUNCATION_SECONDS: u32 = 30 * 60; /// This version of Zebra draws the current network protocol version from /// [ZIP-253](https://zips.z.cash/zip-0253). pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = { - #[cfg(not(zcash_unstable = "nu6" /* TODO nu7 */))] + #[cfg(not(zcash_unstable = "nu7"))] { Version(170_120) } - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */)] + #[cfg(zcash_unstable = "nu7")] { Version(170_140) } diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 91a1874c024..ea37e562d3c 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -106,9 +106,9 @@ impl Version { (Mainnet, Nu5) => 170_100, (Testnet(params), Nu6) if params.is_default_testnet() => 170_110, (Mainnet, Nu6) => 170_120, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] (Testnet(params), Nu7) if params.is_default_testnet() => 170_130, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] (Mainnet, Nu7) => 170_140, // It should be fine to reject peers with earlier network protocol versions on custom testnets for now. diff --git a/zebra-rpc/Cargo.toml b/zebra-rpc/Cargo.toml index 1562a77677e..bebd8e3ed60 100644 --- a/zebra-rpc/Cargo.toml +++ b/zebra-rpc/Cargo.toml @@ -97,6 +97,7 @@ serde = { version = "1.0.211", features = ["serde_derive"] } nix = { version = "0.29.0", features = ["signal"] } zcash_primitives = { workspace = true, features = ["transparent-inputs"] } +zcash_protocol.workspace = true # ECC deps used by getblocktemplate-rpcs feature zcash_address = { workspace = true, optional = true} diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index 2d50552cfec..1e72eb83900 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -1353,7 +1353,7 @@ where async move { let (network, unified_address): ( - zcash_address::Network, + zcash_protocol::consensus::NetworkType, zcash_address::unified::Address, ) = zcash_address::unified::Encoding::decode(address.clone().as_str()).map_err( |error| Error { diff --git a/zebra-scan/Cargo.toml b/zebra-scan/Cargo.toml index 4c13ed02050..22164f2e0f8 100644 --- a/zebra-scan/Cargo.toml +++ b/zebra-scan/Cargo.toml @@ -74,6 +74,7 @@ futures = "0.3.31" zcash_client_backend.workspace = true zcash_keys = { workspace = true, features = ["sapling"] } zcash_primitives.workspace = true +zcash_protocol.workspace = true zcash_address.workspace = true sapling-crypto.workspace = true diff --git a/zebra-scan/src/bin/scanning-results-reader/main.rs b/zebra-scan/src/bin/scanning-results-reader/main.rs index 88ae9549b54..bc6168b4fe0 100644 --- a/zebra-scan/src/bin/scanning-results-reader/main.rs +++ b/zebra-scan/src/bin/scanning-results-reader/main.rs @@ -62,8 +62,8 @@ pub fn main() { ) .expect("TX fetched via RPC should be deserializable from raw bytes"); - for output in - decrypt_transaction(&zp_network, height, &tx, &ufvks).sapling_outputs() + for output in decrypt_transaction(&zp_network, Some(height), None, &tx, &ufvks) + .sapling_outputs() { let memo = memo_bytes_to_string(output.memo().as_array()); diff --git a/zebra-scan/src/service/scan_task/scan.rs b/zebra-scan/src/service/scan_task/scan.rs index fd662f55560..080732a5ec6 100644 --- a/zebra-scan/src/service/scan_task/scan.rs +++ b/zebra-scan/src/service/scan_task/scan.rs @@ -542,7 +542,11 @@ pub fn scanning_keys<'a>( dfvks .into_iter() .enumerate() - .map(|(i, dfvk)| Ok((AccountId::try_from(u32::try_from(i)?)?, dfvk_to_ufvk(dfvk)?))) + .map(|(i, dfvk)| { + let account = AccountId::try_from(u32::try_from(i)?) + .map_err(|e| eyre!("Invalid AccountId: {:?}", e))?; + Ok((account, dfvk_to_ufvk(dfvk)?)) + }) .try_collect::<(_, _), Vec<(_, _)>, _>() .map(ScanningKeys::from_account_ufvks) } diff --git a/zebra-scan/src/tests.rs b/zebra-scan/src/tests.rs index ab2e9ea7ea9..92e9d4d45c2 100644 --- a/zebra-scan/src/tests.rs +++ b/zebra-scan/src/tests.rs @@ -20,7 +20,7 @@ use zcash_client_backend::{ use zcash_note_encryption::Domain; use zcash_primitives::{block::BlockHash, consensus::BlockHeight, memo::MemoBytes}; -use ::sapling_crypto::{ +use sapling_crypto::{ constants::SPENDING_KEY_GENERATOR, note_encryption::{sapling_note_encryption, SaplingDomain}, util::generate_random_rseed, @@ -250,7 +250,7 @@ pub fn random_compact_tx(mut rng: impl RngCore) -> CompactTx { }; let fake_cmu = { let fake_cmu = bls12_381::Scalar::random(&mut rng); - fake_cmu.to_repr().as_ref().to_owned() + fake_cmu.to_repr().to_vec() }; let fake_epk = { let mut buffer = [0; 64]; diff --git a/zebra-scan/src/tests/vectors.rs b/zebra-scan/src/tests/vectors.rs index 11671c289f6..5789701bc14 100644 --- a/zebra-scan/src/tests/vectors.rs +++ b/zebra-scan/src/tests/vectors.rs @@ -12,7 +12,7 @@ use zcash_client_backend::{ encoding::{decode_extended_full_viewing_key, encode_extended_full_viewing_key}, proto::compact_formats::ChainMetadata, }; -use zcash_primitives::constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY; +use zcash_protocol::constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY; use zebra_chain::{ block::{Block, Height}, From e36bf8755dc4cf9fbba6b212f98e95e625fb8c44 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 31 Aug 2025 22:41:46 +0200 Subject: [PATCH 10/22] Add orchard_flags_mut transaction method, use it in zebra-consensus/src/transaction/tests.rs, refactor those tests to support V5 and V6 in action duplication test --- zebra-chain/src/transaction.rs | 26 ++++++++- zebra-consensus/src/transaction/tests.rs | 67 ++++++++++++++++-------- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 98500bc2aa9..23034f66e8f 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -208,6 +208,7 @@ impl fmt::Display for Transaction { } } +// FIXME: get rid of this macro (unroll)? // Macro to get a specific field from an Orchard shielded data struct. // Returns `None` for transaction versions that don't support Orchard (V1-V4). // This avoids repeating the same match block pattern across multiple accessor methods. @@ -1048,7 +1049,7 @@ impl Transaction { // orchard - /// Iterate over the [`orchard::AuthorizedAction`]s in V5 transaction. + /// Iterate over the OrchardVanilla authorized actions in this transaction. pub fn orchard_vanilla_actions( &self, ) -> Option>> { @@ -1065,7 +1066,7 @@ impl Transaction { } } - /// Iterate over the [`orchard::AuthorizedAction`]s in V6 transaction. + /// Iterate over the OrchardZSA authorized actions in this transaction. #[cfg(feature = "tx_v6")] pub fn orchard_zsa_actions( &self, @@ -1892,4 +1893,25 @@ impl Transaction { } => outputs, } } + + /// Modify the orchard flags in this transaction, regardless of version. + pub fn orchard_flags_mut(&mut self) -> Option<&mut orchard::shielded_data::Flags> { + match self { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_mut().map(|data| &mut data.flags), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_mut().map(|data| &mut data.flags), + } + } } diff --git a/zebra-consensus/src/transaction/tests.rs b/zebra-consensus/src/transaction/tests.rs index 99ef0dec448..b9a098fff9c 100644 --- a/zebra-consensus/src/transaction/tests.rs +++ b/zebra-consensus/src/transaction/tests.rs @@ -76,7 +76,7 @@ fn v5_transaction_with_orchard_actions_has_inputs_and_outputs() { }) .expect("V5 tx with only Orchard shielded data"); - tx.orchard_shielded_data_mut().unwrap().flags = Flags::empty(); + *tx.orchard_flags_mut().unwrap() = Flags::empty(); // The check will fail if the transaction has no flags assert_eq!( @@ -85,7 +85,7 @@ fn v5_transaction_with_orchard_actions_has_inputs_and_outputs() { ); // If we add ENABLE_SPENDS flag it will pass the inputs check but fails with the outputs - tx.orchard_shielded_data_mut().unwrap().flags = Flags::ENABLE_SPENDS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_SPENDS; assert_eq!( check::has_inputs_and_outputs(&tx), @@ -93,7 +93,7 @@ fn v5_transaction_with_orchard_actions_has_inputs_and_outputs() { ); // If we add ENABLE_OUTPUTS flag it will pass the outputs check but fails with the inputs - tx.orchard_shielded_data_mut().unwrap().flags = Flags::ENABLE_OUTPUTS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_OUTPUTS; assert_eq!( check::has_inputs_and_outputs(&tx), @@ -101,8 +101,7 @@ fn v5_transaction_with_orchard_actions_has_inputs_and_outputs() { ); // Finally make it valid by adding both required flags - tx.orchard_shielded_data_mut().unwrap().flags = - Flags::ENABLE_SPENDS | Flags::ENABLE_OUTPUTS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_SPENDS | Flags::ENABLE_OUTPUTS; assert!(check::has_inputs_and_outputs(&tx).is_ok()); } @@ -121,7 +120,7 @@ fn v5_transaction_with_orchard_actions_has_flags() { }) .expect("V5 tx with only Orchard actions"); - tx.orchard_shielded_data_mut().unwrap().flags = Flags::empty(); + *tx.orchard_flags_mut().unwrap() = Flags::empty(); // The check will fail if the transaction has no flags assert_eq!( @@ -130,20 +129,19 @@ fn v5_transaction_with_orchard_actions_has_flags() { ); // If we add ENABLE_SPENDS flag it will pass. - tx.orchard_shielded_data_mut().unwrap().flags = Flags::ENABLE_SPENDS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_SPENDS; assert!(check::has_enough_orchard_flags(&tx).is_ok()); - tx.orchard_shielded_data_mut().unwrap().flags = Flags::empty(); + *tx.orchard_flags_mut().unwrap() = Flags::empty(); // If we add ENABLE_OUTPUTS flag instead, it will pass. - tx.orchard_shielded_data_mut().unwrap().flags = Flags::ENABLE_OUTPUTS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_OUTPUTS; assert!(check::has_enough_orchard_flags(&tx).is_ok()); - tx.orchard_shielded_data_mut().unwrap().flags = Flags::empty(); + *tx.orchard_flags_mut().unwrap() = Flags::empty(); // If we add BOTH ENABLE_SPENDS and ENABLE_OUTPUTS flags it will pass. - tx.orchard_shielded_data_mut().unwrap().flags = - Flags::ENABLE_SPENDS | Flags::ENABLE_OUTPUTS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_SPENDS | Flags::ENABLE_OUTPUTS; assert!(check::has_enough_orchard_flags(&tx).is_ok()); } } @@ -2791,18 +2789,45 @@ async fn v5_with_duplicate_orchard_action() { let height = tx.expiry_height().expect("expiry height"); - let orchard_shielded_data = tx - .orchard_shielded_data_mut() - .expect("tx without transparent, Sprout, or Sapling outputs must have Orchard actions"); - // Enable spends - orchard_shielded_data.flags = Flags::ENABLE_SPENDS | Flags::ENABLE_OUTPUTS; + *tx.orchard_flags_mut().unwrap() = Flags::ENABLE_SPENDS | Flags::ENABLE_OUTPUTS; + + // Duplicate the first action and get its nullifier + let duplicate_nullifier = match &mut tx { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => unimplemented!("Transaction version is not supported"), + + Transaction::V5 { + orchard_shielded_data, + .. + } => { + let orchard_shielded_data = orchard_shielded_data + .as_mut() + .expect("Transaction has orchard_shielded_data"); + let duplicate_action = orchard_shielded_data.actions.first().clone(); + let duplicate_nullifier = duplicate_action.action.nullifier; + orchard_shielded_data.actions.push(duplicate_action); - let duplicate_action = orchard_shielded_data.actions.first().clone(); - let duplicate_nullifier = duplicate_action.action.nullifier; + duplicate_nullifier + } - // Duplicate the first action - orchard_shielded_data.actions.push(duplicate_action); + #[cfg(feature = "tx_v6")] + Transaction::V6 { + orchard_shielded_data, + .. + } => { + let orchard_shielded_data = orchard_shielded_data + .as_mut() + .expect("Transaction has orchard_shielded_data"); + let duplicate_action = orchard_shielded_data.actions.first().clone(); + let duplicate_nullifier = duplicate_action.action.nullifier; + orchard_shielded_data.actions.push(duplicate_action); + + duplicate_nullifier + } + }; let verifier = Verifier::new_for_tests( &net, From 156bfb5bdb2573aee5295b1cbe672eda9c4a30e7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 31 Aug 2025 22:49:11 +0200 Subject: [PATCH 11/22] Remove orchard_shielded_data_field macro for style consistency Unrolled the orchard_shielded_data_field! macro into explicit code to match the style used elsewhere in Orchard transaction handling and in upstream ZcashFoundation, which avoids macros there entirely. --- zebra-chain/src/transaction.rs | 95 ++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 23034f66e8f..2cd15fe2eae 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -208,33 +208,6 @@ impl fmt::Display for Transaction { } } -// FIXME: get rid of this macro (unroll)? -// Macro to get a specific field from an Orchard shielded data struct. -// Returns `None` for transaction versions that don't support Orchard (V1-V4). -// This avoids repeating the same match block pattern across multiple accessor methods. -macro_rules! orchard_shielded_data_field { - ($self:expr, $field:ident) => { - match $self { - // No Orchard shielded data - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } => None, - - Transaction::V5 { - orchard_shielded_data, - .. - } => orchard_shielded_data.as_ref().map(|data| data.$field), - - #[cfg(feature = "tx_v6")] - Transaction::V6 { - orchard_shielded_data, - .. - } => orchard_shielded_data.as_ref().map(|data| data.$field), - } - }; -} - impl Transaction { // identifiers and hashes @@ -1180,13 +1153,51 @@ impl Transaction { /// Access the [`orchard::Flags`] in this transaction, if there is any, /// regardless of version. pub fn orchard_flags(&self) -> Option { - orchard_shielded_data_field!(self, flags) + match self { + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref().map(|data| data.flags), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref().map(|data| data.flags), + } } /// Access the [`orchard::tree::Root`] in this transaction, if there is any, /// regardless of version. pub fn orchard_shared_anchor(&self) -> Option { - orchard_shielded_data_field!(self, shared_anchor) + match self { + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data + .as_ref() + .map(|data| data.shared_anchor), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data + .as_ref() + .map(|data| data.shared_anchor), + } } /// Return if the transaction has any Orchard shielded data, @@ -1520,10 +1531,30 @@ impl Transaction { /// /// pub fn orchard_value_balance(&self) -> ValueBalance { - let orchard_value_balance = - orchard_shielded_data_field!(self, value_balance).unwrap_or_else(Amount::zero); + let orchard_value_balance = match self { + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data + .as_ref() + .map(|data| data.value_balance), + + #[cfg(feature = "tx_v6")] + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data + .as_ref() + .map(|data| data.value_balance), + }; - ValueBalance::from_orchard_amount(orchard_value_balance) + ValueBalance::from_orchard_amount(orchard_value_balance.unwrap_or_else(Amount::zero)) } /// Returns the value balances for this transaction using the provided transparent outputs. From 403047a411ceacee578709d0deb856c1db742688 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 1 Sep 2025 13:02:47 +0200 Subject: [PATCH 12/22] Use Vec for enc_ciphertext in zebra-rpc/src/methods/types/transaction.rs to store either Vanilla and ZSA data --- zebra-chain/src/orchard/note/ciphertexts.rs | 6 ++ .../src/orchard/shielded_data_flavor.rs | 1 + zebra-chain/src/transaction.rs | 35 --------- zebra-rpc/src/methods/types/transaction.rs | 77 ++++++++----------- 4 files changed, 41 insertions(+), 78 deletions(-) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 087d89a80ff..1057cc63f45 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -32,6 +32,12 @@ impl TryFrom<&[u8]> for EncryptedNote { } } +impl AsRef<[u8]> for EncryptedNote { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + impl ZcashSerialize for EncryptedNote { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { writer.write_all(&self.0[..])?; diff --git a/zebra-chain/src/orchard/shielded_data_flavor.rs b/zebra-chain/src/orchard/shielded_data_flavor.rs index 0fe94143420..14e7f366be8 100644 --- a/zebra-chain/src/orchard/shielded_data_flavor.rs +++ b/zebra-chain/src/orchard/shielded_data_flavor.rs @@ -46,6 +46,7 @@ pub trait ShieldedDataFlavor: OrchardFlavor { + Serialize + ZcashDeserialize + ZcashSerialize + + AsRef<[u8]> + for<'a> TryFrom<&'a [u8], Error = std::array::TryFromSliceError> + test_arbitrary::TestArbitrary; diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 2cd15fe2eae..47d25b39c49 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -1022,41 +1022,6 @@ impl Transaction { // orchard - /// Iterate over the OrchardVanilla authorized actions in this transaction. - pub fn orchard_vanilla_actions( - &self, - ) -> Option>> { - if let Transaction::V5 { - orchard_shielded_data, - .. - } = self - { - orchard_shielded_data - .as_ref() - .map(|shielded_data| shielded_data.actions.iter()) - } else { - None - } - } - - /// Iterate over the OrchardZSA authorized actions in this transaction. - #[cfg(feature = "tx_v6")] - pub fn orchard_zsa_actions( - &self, - ) -> Option>> { - if let Transaction::V6 { - orchard_shielded_data, - .. - } = self - { - orchard_shielded_data - .as_ref() - .map(|shielded_data| shielded_data.actions.iter()) - } else { - None - } - } - /// Return the number of Orchard actions in this transaction. pub fn orchard_action_count(&self) -> usize { match self { diff --git a/zebra-rpc/src/methods/types/transaction.rs b/zebra-rpc/src/methods/types/transaction.rs index 83e25edd48f..69b7f15b661 100644 --- a/zebra-rpc/src/methods/types/transaction.rs +++ b/zebra-rpc/src/methods/types/transaction.rs @@ -11,17 +11,13 @@ use hex::ToHex; use zebra_chain::{ amount::{self, Amount, NegativeOrZero, NonNegative}, block::{self, merkle::AUTH_DIGEST_PLACEHOLDER, Height}, - orchard::{self, OrchardDomainCommon, OrchardVanilla, ShieldedDataFlavor}, + orchard::{self, ShieldedDataFlavor}, parameters::Network, primitives::ed25519, sapling::NotSmallOrderValueCommitment, transaction::{self, SerializedTransaction, Transaction, UnminedTx, VerifiedUnminedTx}, transparent::Script, }; - -#[cfg(feature = "tx_v6")] -use zebra_chain::orchard::OrchardZSA; - use zebra_consensus::groth16::Description; use zebra_state::IntoDisk; @@ -221,16 +217,11 @@ pub struct TransactionObject { #[getter(copy)] pub(crate) joinsplit_sig: Option<[u8; ed25519::Signature::BYTE_SIZE]>, + // TODO: Consider also adding pub(crate) orchard_zsa_issue: Option /// Orchard actions of the transaction. #[serde(rename = "orchard", skip_serializing_if = "Option::is_none")] pub(crate) orchard: Option, - // FIXME: Do we need to include this into TransactionObject? All IssueData fields or actions only? - // What names should we use here? - /// The OrchardZSA issuance of the transaction. - //#[serde(rename = "orchardZSAIssue", skip_serializing_if = "Option::is_none")] - //pub(crate) orchard_zsa_issue: Option, /// A ciphertext enabling the sender to recover the output note. #[serde(rename = "spendAuthSig", with = "hex")] spend_auth_sig: [u8; 64], @@ -507,17 +484,12 @@ impl<'a, Flavor: ShieldedDataFlavor> From<&'a orchard::AuthorizedAction> fn from(authorized_action: &'a orchard::AuthorizedAction) -> Self { let action = &authorized_action.action; - // FIXME: implement thsi correctly - let enc_ciphertext = EncCiphertextHex::V5([0u8; 580]); - //let enc_ciphertext = EncCiphertextHex::from_bytes(action.enc_ciphertext.as_ref()) - // .expect("valid Orchard encCiphertext length"); - let cv: [u8; 32] = action.cv.into(); let nullifier: [u8; 32] = action.nullifier.into(); let rk: [u8; 32] = action.rk.into(); let cm_x: [u8; 32] = action.cm_x.into(); let ephemeral_key: [u8; 32] = action.ephemeral_key.into(); - //let enc_ciphertext: [u8; 580] = action.enc_ciphertext.into(); + let enc_ciphertext = action.enc_ciphertext.as_ref().to_vec(); let spend_auth_sig: [u8; 64] = authorized_action.spend_auth_sig.into(); let out_ciphertext: [u8; 80] = action.out_ciphertext.into(); @@ -547,8 +519,6 @@ impl Default for TransactionObject { shielded_spends: Vec::new(), shielded_outputs: Vec::new(), orchard: None, - // FIXME: Do we need to add this? - //orchard_zsa_issue: None, binding_sig: None, joinsplit_pub_key: None, joinsplit_sig: None, @@ -694,16 +664,37 @@ impl TransactionObject { orchard: if !tx.has_orchard_shielded_data() { None } else { + let mut actions = Vec::new(); + + match &*tx { + // Do nothing for non V5/V6 transactions as they don't contain orchard actions + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => {} + + Transaction::V5 { + orchard_shielded_data, + .. + } => actions.extend( + orchard_shielded_data + .iter() + .flat_map(|shielded_data| shielded_data.actions.iter()) + .map(|action| action.into()), + ), + Transaction::V6 { + orchard_shielded_data, + .. + } => actions.extend( + orchard_shielded_data + .iter() + .flat_map(|shielded_data| shielded_data.actions.iter()) + .map(|action| action.into()), + ), + } + Some(Orchard { - // FIXME: add support of processing of orchard_zsa_actions - // FIXME: orchard_vanilla_actions/orchard_zsa_actions should return already - // flattened iteratior, i.e. no Option wrapper and an empty iterator instead of None? - actions: tx - .orchard_vanilla_actions() - .into_iter() - .flatten() - .map(|authorized_action| authorized_action.into()) - .collect(), + actions, value_balance: Zec::from(tx.orchard_value_balance().orchard_amount()) .lossy_zec(), value_balance_zat: tx.orchard_value_balance().orchard_amount().zatoshis(), From fe0c0819d8806c889f6c93ed1db0d8a06b0eb9e9 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 7 Sep 2025 23:13:39 +0200 Subject: [PATCH 13/22] Temporarily comment out Nu7 activation heights, and use 0x7777_7777 as TX_V6_VERSION_GROUP_ID to align with librustzcash --- zebra-chain/src/parameters/network_upgrade.rs | 20 +++++++++++++------ zebra-chain/src/parameters/transaction.rs | 6 +++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index c381dde58ee..639e41c0e0d 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -115,9 +115,13 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_046_400), Canopy), (block::Height(1_687_104), Nu5), (block::Height(2_726_400), Nu6), - // FIXME: TODO: Use a proper value below. - #[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] - (block::Height(3_111_000), Nu7), + // FIXME: TODO: Uncomment the lines below and use the correct value + // once a height for Nu6_1 is defined. Having Nu7 without Nu6_1 + // causes several tests to fail, because they assume the Nu7 height + // applies to Nu6_1. + // + //#[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] + //(block::Height(3_111_000), Nu7), ]; /// Fake mainnet network upgrade activation heights, used in tests. @@ -156,9 +160,13 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_028_500), Canopy), (block::Height(1_842_420), Nu5), (block::Height(2_976_000), Nu6), - // FIXME: TODO: Use a proper value below. - #[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] - (block::Height(3_222_000), Nu7), + // FIXME: TODO: Uncomment the lines below and use the correct value + // once a height for Nu6_1 is defined. Having Nu7 without Nu6_1 + // causes several tests to fail, because they assume the Nu7 height + // applies to Nu6_1. + // + //#[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] + //(block::Height(3_222_000), Nu7), ]; /// Fake testnet network upgrade activation heights, used in tests. diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index 621355abb04..85f91d083e8 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -14,4 +14,8 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// The version group ID for version 6 transactions. /// TODO: update this after it's chosen -pub const TX_V6_VERSION_GROUP_ID: u32 = 0xFFFF_FFFF; +// FIXME: The upstream version uses 0xFFFF_FFFF for TX_V6_VERSION_GROUP_ID, +// but it was changed here to 0x7777_7777 for compatibility with the value of +// V6_VERSION_GROUP_ID in the ZSA version of librustzcash/zcash_protocol. +// Update to the proper value once it's fixed in librustzcash. +pub const TX_V6_VERSION_GROUP_ID: u32 = 0x7777_7777; From 2a3f1c4bb34cc4cb062ce13b5c567ed2ee377b59 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 8 Sep 2025 10:30:59 +0200 Subject: [PATCH 14/22] Add Cargo.lock --- Cargo.lock | 77 ++++++------------------------------------------------ 1 file changed, 8 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ef8ced2bf5..4482153d3ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2590,12 +2590,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - [[package]] name = "litrs" version = "0.4.1" @@ -2806,12 +2800,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549e471b99ccaf2f89101bec68f4d244457d5a95a9c3d0672e9564124397741d" -[[package]] -name = "nonempty" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549e471b99ccaf2f89101bec68f4d244457d5a95a9c3d0672e9564124397741d" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2954,7 +2942,7 @@ dependencies = [ "k256", "lazy_static", "memuse", - "nonempty 0.11.0", + "nonempty", "pasta_curves", "proptest", "rand 0.8.5", @@ -3718,18 +3706,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "redjubjub" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b0ac1bc6bb3696d2c6f52cff8fba57238b81da8c0214ee6cd146eb8fde364e" -dependencies = [ - "rand_core 0.6.4", - "reddsa", - "thiserror", - "zeroize", -] - [[package]] name = "redox_syscall" version = "0.5.3" @@ -3983,19 +3959,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustix" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", -] - [[package]] name = "rustls" version = "0.23.31" @@ -4098,7 +4061,7 @@ dependencies = [ "memuse", "rand 0.8.5", "rand_core 0.6.4", - "redjubjub 0.8.0", + "redjubjub", "subtle", "tracing", "zcash_note_encryption", @@ -4155,28 +4118,10 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "secp256k1-sys 0.8.1", + "secp256k1-sys", "serde", ] -[[package]] -name = "secp256k1" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" -dependencies = [ - "secp256k1-sys 0.10.1", -] - -[[package]] -name = "secp256k1-sys" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" -dependencies = [ - "cc", -] - [[package]] name = "secp256k1-sys" version = "0.10.1" @@ -4731,7 +4676,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 0.38.37", + "rustix", "windows-sys 0.59.0", ] @@ -5987,12 +5932,6 @@ dependencies = [ "bitflags 2.9.2", ] -[[package]] -name = "winsafe" -version = "0.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" - [[package]] name = "wyz" version = "0.5.1" @@ -6061,7 +6000,7 @@ dependencies = [ "time-core", "tonic-build 0.13.1", "tracing", - "which 7.0.3", + "which", "zcash_address", "zcash_encoding", "zcash_keys", @@ -6105,7 +6044,7 @@ dependencies = [ "document-features", "group", "memuse", - "nonempty 0.11.0", + "nonempty", "rand_core 0.6.4", "sapling-crypto", "secrecy", @@ -6151,7 +6090,7 @@ dependencies = [ "incrementalmerkletree", "jubjub", "memuse", - "nonempty 0.11.0", + "nonempty", "orchard", "rand 0.8.5", "rand_core 0.6.4", @@ -6186,7 +6125,7 @@ dependencies = [ "known-folders", "lazy_static", "rand_core 0.6.4", - "redjubjub 0.8.0", + "redjubjub", "sapling-crypto", "tracing", "xdg", From 362943e78d3541c583e2c803c60e947678693b49 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Sep 2025 16:41:23 +0200 Subject: [PATCH 15/22] Add nu7 cfg flag in a couple of places along with the existing zebra-test flag --- zebra-chain/src/parameters/network_upgrade.rs | 12 ++++++------ zebra-chain/src/primitives/zcash_primitives.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 639e41c0e0d..2609b814664 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -28,9 +28,9 @@ const NETWORK_UPGRADES_IN_ORDER: &[NetworkUpgrade] = &[ // FIXME: unify zebra-test/zcash_unstable nu7 usages, // check if the code is covered of those flags properly, // try to build with and without those flags - #[cfg(any(test, feature = "zebra-test"))] + #[cfg(any(test, feature = "zebra-test", zcash_unstable = "nu7"))] Nu6_1, - #[cfg(any(test, feature = "zebra-test"))] + #[cfg(any(test, feature = "zebra-test", zcash_unstable = "nu7"))] Nu7, ]; @@ -120,7 +120,7 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] // causes several tests to fail, because they assume the Nu7 height // applies to Nu6_1. // - //#[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] + //#[cfg(zcash_unstable = "nu7")] //(block::Height(3_111_000), Nu7), ]; @@ -165,7 +165,7 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] // causes several tests to fail, because they assume the Nu7 height // applies to Nu6_1. // - //#[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] + //#[cfg(zcash_unstable = "nu7")] //(block::Height(3_222_000), Nu7), ]; @@ -274,9 +274,9 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Canopy, ConsensusBranchId(0xe9ff75a6)), (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), - #[cfg(any(test, feature = "zebra-test"))] + #[cfg(any(test, feature = "zebra-test", zcash_unstable = "nu7"))] (Nu6_1, ConsensusBranchId(0x4dec4df0)), - #[cfg(any(test, feature = "zebra-test"))] + #[cfg(any(test, feature = "zebra-test", zcash_unstable = "nu7"))] (Nu7, ConsensusBranchId(0x77190ad8)), ]; diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 3d271c2de44..02ae8ab58b9 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -132,7 +132,7 @@ impl zp_tx::components::orchard::MapAuth for IdentityMap { @@ -149,7 +149,7 @@ impl zp_tx::Authorization for PrecomputedAuth { type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu7" /* TODO nu7 */ )] + #[cfg(zcash_unstable = "nu7")] type IssueAuth = orchard::issuance::Signed; } From 3ccd96eaf5ed8a6d15bbf5d0ace05a69ab9a680f Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 Sep 2025 18:01:54 +0200 Subject: [PATCH 16/22] Add --locked to cargo test run in CI config --- .github/workflows/ci-basic.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 064f28efdc5..521fb71475c 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -25,7 +25,9 @@ jobs: - name: Install formatting & linting tools run: rustup component add rustfmt clippy - name: Run tests - run: cargo test --verbose + env: + RUST_BACKTRACE: 1 + run: cargo test --locked --verbose - name: Verify working directory is clean run: git diff --exit-code - name: Run doc check From 231ae2ab0ce7d8581bcbad1e31dc12678c7c3258 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 11 Sep 2025 08:47:39 +0200 Subject: [PATCH 17/22] Skip intermittently failing Sapling spend tests in main run; execute separately with reduced concurrency pending flake fix --- .github/workflows/ci-basic.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 521fb71475c..766fceb7184 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -27,7 +27,17 @@ jobs: - name: Run tests env: RUST_BACKTRACE: 1 - run: cargo test --locked --verbose + # Skip two tests that intermittently fail on CI (likely a race/ordering issue). + # FIXME: investigate and fix the underlying flake; remove these skips once resolved. + run: cargo test --locked --verbose -- --skip v4_with_sapling_spends --skip v5_with_sapling_spends + # Run the skipped tests separately with constrained parallelism + - name: Run Sapling spend tests (serial) + env: + RUST_TEST_THREADS: 1 + TOKIO_WORKER_THREADS: 2 + run: | + cargo test -p zebra-consensus v4_with_sapling_spends -- --nocapture + cargo test -p zebra-consensus v5_with_sapling_spends -- --nocapture - name: Verify working directory is clean run: git diff --exit-code - name: Run doc check From cc3b7271839beacb3b6c4e248996cea19dbdd3ca Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 11 Sep 2025 09:45:22 +0200 Subject: [PATCH 18/22] Remove env set for separate sapling spend tests from CI config --- .github/workflows/ci-basic.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 766fceb7184..0c2f9d15a7a 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -31,10 +31,7 @@ jobs: # FIXME: investigate and fix the underlying flake; remove these skips once resolved. run: cargo test --locked --verbose -- --skip v4_with_sapling_spends --skip v5_with_sapling_spends # Run the skipped tests separately with constrained parallelism - - name: Run Sapling spend tests (serial) - env: - RUST_TEST_THREADS: 1 - TOKIO_WORKER_THREADS: 2 + - name: Run Sapling spend tests run: | cargo test -p zebra-consensus v4_with_sapling_spends -- --nocapture cargo test -p zebra-consensus v5_with_sapling_spends -- --nocapture From b9b06558a5f27e578f549f84c54099ad513afce2 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 14 Sep 2025 22:39:59 +0200 Subject: [PATCH 19/22] Update get_blockchain_info snapshots in zebra-rpc tests (remove Nu7 item) --- .../tests/snapshots/get_blockchain_info@mainnet_10.snap | 7 +------ .../tests/snapshots/get_blockchain_info@testnet_10.snap | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap index 5140c1d30db..54b0a2c2860 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap @@ -1,6 +1,6 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs -assertion_line: 562 +assertion_line: 689 expression: info --- { @@ -87,11 +87,6 @@ expression: info "name": "NU6", "activationheight": 2726400, "status": "pending" - }, - "77190ad8": { - "name": "NU7", - "activationheight": 3111000, - "status": "pending" } }, "consensus": { diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index e3039e52d82..b3d4d7c3207 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -1,6 +1,6 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs -assertion_line: 562 +assertion_line: 689 expression: info --- { @@ -87,11 +87,6 @@ expression: info "name": "NU6", "activationheight": 2976000, "status": "pending" - }, - "77190ad8": { - "name": "NU7", - "activationheight": 3222000, - "status": "pending" } }, "consensus": { From 70a8ba49e4ab1e186c5da08fbb780e1f7fcdd456 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 15 Sep 2025 11:10:03 +0200 Subject: [PATCH 20/22] Fix cargo clippy error --- zebra-chain/src/orchard_zsa/burn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs index bc738c2a7ef..8ba4696e82c 100644 --- a/zebra-chain/src/orchard_zsa/burn.rs +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -22,7 +22,7 @@ impl ZcashSerialize for AssetBase { impl ZcashDeserialize for AssetBase { fn zcash_deserialize(mut reader: R) -> Result { Option::from(AssetBase::from_bytes(&reader.read_32_bytes()?)) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa AssetBase!")) + .ok_or(SerializationError::Parse("Invalid orchard_zsa AssetBase!")) } } From f3a730c77cea5aa18660bb210c3efb4a21ff1188 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 15 Sep 2025 11:11:06 +0200 Subject: [PATCH 21/22] zebrad tests: increase BETWEEN_NODES_DELAY to fix zebra_rpc_conflict test failure --- zebrad/tests/common/launch.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zebrad/tests/common/launch.rs b/zebrad/tests/common/launch.rs index d4ee17f323e..4161fddc03d 100644 --- a/zebrad/tests/common/launch.rs +++ b/zebrad/tests/common/launch.rs @@ -47,11 +47,13 @@ pub const EXTENDED_LAUNCH_DELAY: Duration = Duration::from_secs(45); /// it is using for its RPCs. pub const LIGHTWALLETD_DELAY: Duration = Duration::from_secs(60); +// FIXME: This value has been increased from 20 to 50 to fix zebra_rpc_conflict test failure in zebrad, +// - should we consider other ways to resolve it? /// The amount of time we wait between launching two conflicting nodes. /// /// We use a longer time to make sure the first node has launched before the second starts, /// even if CI is under load. -pub const BETWEEN_NODES_DELAY: Duration = Duration::from_secs(20); +pub const BETWEEN_NODES_DELAY: Duration = Duration::from_secs(50); /// The amount of time we wait for lightwalletd to update to the tip. /// From 4446d4a1bda88f4746fe4c1b519d08cc587c868e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 16 Sep 2025 11:22:20 +0200 Subject: [PATCH 22/22] Trigger CI