refactor(zcash): use shielded pool display directly
What changed, and why it matters
This commit is a minor code cleanup in the Zcash shielded-transaction handling code. It removes temporary variables named `pool_label` and instead uses the existing `pool` value directly when building error messages. There is no change to security logic, transaction validation, or cryptographic operations.
No security action required. Treat as a normal refactoring review.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff removes intermediate let pool_label = pool; bindings across check.rs, mod.rs, parse.rs, and sign.rs in the Zcash PCZT (Partially Created Zcash Transaction) module. Error-message format strings are updated to interpolate pool directly. The ShieldedPool type already implements Display, so the behavior is functionally identical. No control flow, validation rules, or signing semantics are altered.
Changed components
rust/apps/zcash/src/pczt/check.rsrust/apps/zcash/src/pczt/mod.rsrust/apps/zcash/src/pczt/parse.rsrust/apps/zcash/src/pczt/sign.rsInspect captured patch +22 / −33
diff --git a/rust/apps/zcash/src/pczt/check.rs b/rust/apps/zcash/src/pczt/check.rs
index b67aa4d..f3873fd 100644
--- a/rust/apps/zcash/src/pczt/check.rs
+++ b/rust/apps/zcash/src/pczt/check.rs
@@ -396,7 +396,6 @@ fn check_shielded_bundle<P: consensus::Parameters>(
bundle: &orchard::pczt::Bundle,
pool: ShieldedPool,
) -> Result<(), ZcashError> {
- let pool_label = pool;
let fvk = ufvk.orchard().ok_or(ZcashError::InvalidDataError(
"orchard fvk is not present".to_string(),
))?;
@@ -427,7 +426,7 @@ fn check_shielded_bundle<P: consensus::Parameters>(
match calculated_value_balance {
Ok(value_balance) if &value_balance == bundle.value_sum() => Ok(()),
_ => Err(ZcashError::InvalidPczt(format!(
- "invalid {pool_label} bundle value balance"
+ "invalid {pool} bundle value balance"
))),
}
}
@@ -446,7 +445,6 @@ fn check_and_parse_shielded_bundle<P: consensus::Parameters>(
pool: ShieldedPool,
checked_actions: &mut alloc::vec::Vec<ShieldedAction>,
) -> Result<Option<ParsedOrchard>, ZcashError> {
- let pool_label = pool;
let fvk = ufvk.orchard().ok_or(ZcashError::InvalidDataError(
"orchard fvk is not present".to_string(),
))?;
@@ -520,7 +518,7 @@ fn check_and_parse_shielded_bundle<P: consensus::Parameters>(
}
}
_ => Err(ZcashError::InvalidPczt(format!(
- "invalid {pool_label} bundle value balance"
+ "invalid {pool} bundle value balance"
))),
}
}
@@ -537,12 +535,11 @@ fn check_action<P: consensus::Parameters>(
flags: &orchard::bundle::Flags,
pool: ShieldedPool,
) -> Result<ParsedTo, ZcashError> {
- let pool_label = pool;
// Check `cv_net` first so we know that the `value` fields for both the spend and the
// output are present and correct.
- action.verify_cv_net().map_err(|e| {
- ZcashError::InvalidPczt(format!("invalid cv_net in {pool_label} action: {e:?}"))
- })?;
+ action
+ .verify_cv_net()
+ .map_err(|e| ZcashError::InvalidPczt(format!("invalid cv_net in {pool} action: {e:?}")))?;
check_action_spend(
params,
@@ -565,7 +562,6 @@ fn check_action_spend<P: consensus::Parameters>(
spend: &orchard::pczt::Spend,
pool: ShieldedPool,
) -> Result<(), ZcashError> {
- let pool_label = pool;
if let (Some(value), Some(zip32_derivation)) = (spend.value(), spend.zip32_derivation()) {
if value.inner() != 0 && zip32_derivation.seed_fingerprint() == seed_fingerprint {
let matched_account = super::matching_seed_supported_orchard_account(
@@ -604,11 +600,11 @@ fn check_action_spend<P: consensus::Parameters>(
if let Some(expected_fvk) = can_verify_nf_rk {
spend.verify_nullifier(expected_fvk).map_err(|e| {
- ZcashError::InvalidPczt(format!("invalid {pool_label} action nullifier: {e:?}"))
- })?;
- spend.verify_rk(expected_fvk).map_err(|e| {
- ZcashError::InvalidPczt(format!("invalid {pool_label} action rk: {e:?}"))
+ ZcashError::InvalidPczt(format!("invalid {pool} action nullifier: {e:?}"))
})?;
+ spend
+ .verify_rk(expected_fvk)
+ .map_err(|e| ZcashError::InvalidPczt(format!("invalid {pool} action rk: {e:?}")))?;
}
Ok(())
@@ -622,11 +618,10 @@ fn check_action_output<P: consensus::Parameters>(
flags: &orchard::bundle::Flags,
pool: ShieldedPool,
) -> Result<ParsedTo, ZcashError> {
- let pool_label = pool;
action
.output()
.verify_note_commitment(action.spend())
- .map_err(|e| ZcashError::InvalidPczt(format!("invalid {pool_label} action cmx: {e:?}")))?;
+ .map_err(|e| ZcashError::InvalidPczt(format!("invalid {pool} action cmx: {e:?}")))?;
// Decode and validate the recipient, rejecting non-zero outputs the device cannot review.
let parsed_to = super::parse::parse_orchard_output(params, keys, action, pool)?;
diff --git a/rust/apps/zcash/src/pczt/mod.rs b/rust/apps/zcash/src/pczt/mod.rs
index 6a1db8f..1bc27f7 100644
--- a/rust/apps/zcash/src/pczt/mod.rs
+++ b/rust/apps/zcash/src/pczt/mod.rs
@@ -202,7 +202,6 @@ pub(crate) fn matching_seed_supported_orchard_account_parts(
coin_type: u32,
pool: ShieldedPool,
) -> Result<Option<zcash_vendor::zip32::AccountId>, crate::errors::ZcashError> {
- let pool_label = pool;
let Some((derivation_seed_fingerprint, derivation_path)) = derivation else {
return Ok(None);
};
@@ -212,7 +211,7 @@ pub(crate) fn matching_seed_supported_orchard_account_parts(
let unsupported_path = || {
crate::errors::ZcashError::InvalidPczt(alloc::format!(
- "unsupported {pool_label} spend ZIP 32 derivation path"
+ "unsupported {pool} spend ZIP 32 derivation path"
))
};
diff --git a/rust/apps/zcash/src/pczt/parse.rs b/rust/apps/zcash/src/pczt/parse.rs
index 2a24259..0f218d7 100644
--- a/rust/apps/zcash/src/pczt/parse.rs
+++ b/rust/apps/zcash/src/pczt/parse.rs
@@ -191,21 +191,19 @@ pub(crate) fn decode_output_enc_ciphertext(
})
} else {
// If we reached here, none of our OVKs matched; recover directly as the fallback.
- let pool_label = pool;
-
let recipient = action.output().recipient().ok_or_else(|| {
- ZcashError::InvalidPczt(format!("Missing recipient field for {pool_label} action"))
+ ZcashError::InvalidPczt(format!("Missing recipient field for {pool} action"))
})?;
let value = action.output().value().ok_or_else(|| {
- ZcashError::InvalidPczt(format!("Missing value field for {pool_label} action"))
+ ZcashError::InvalidPczt(format!("Missing value field for {pool} action"))
})?;
let rho = orchard::note::Rho::from_bytes(&action.spend().nullifier().to_bytes())
.into_option()
.ok_or_else(|| {
- ZcashError::InvalidPczt(format!("Missing rho field for {pool_label} action"))
+ ZcashError::InvalidPczt(format!("Missing rho field for {pool} action"))
})?;
let rseed = action.output().rseed().ok_or_else(|| {
- ZcashError::InvalidPczt(format!("Missing rseed field for {pool_label} action"))
+ ZcashError::InvalidPczt(format!("Missing rseed field for {pool} action"))
})?;
let note = orchard::Note::from_parts(
@@ -216,9 +214,7 @@ pub(crate) fn decode_output_enc_ciphertext(
(*action.output().note_version()).into(),
)
.into_option()
- .ok_or_else(|| {
- ZcashError::InvalidPczt(format!("{pool_label} action contains invalid note"))
- })?;
+ .ok_or_else(|| ZcashError::InvalidPczt(format!("{pool} action contains invalid note")))?;
Ok(match pool {
ShieldedPool::Orchard => {
@@ -705,7 +701,6 @@ pub(crate) fn parse_orchard_output<P: consensus::Parameters>(
action: &orchard::pczt::Action,
pool: ShieldedPool,
) -> Result<ParsedTo, ZcashError> {
- let pool_label = pool;
let output = action.output();
// we should verify the cv_net in checking phrase, the transaction checking should failed if the net value is not correct
@@ -745,7 +740,7 @@ pub(crate) fn parse_orchard_output<P: consensus::Parameters>(
let belongs_to_wallet = is_external || is_internal;
if is_internal_ovk && !belongs_to_wallet {
return Err(ZcashError::InvalidPczt(alloc::format!(
- "{pool_label} output was recoverable with an internal OVK but does not belong to this wallet"
+ "{pool} output was recoverable with an internal OVK but does not belong to this wallet"
)));
}
let is_dummy = match vk {
@@ -774,7 +769,7 @@ pub(crate) fn parse_orchard_output<P: consensus::Parameters>(
// `vk.is_none()` as a fallback. We require that non-trivial outputs are
// visible to the Keystone device.
(None, Some(value)) if value.inner() != 0 => Err(ZcashError::InvalidPczt(
- alloc::format!("enc_ciphertext field for {pool_label} action is undecryptable"),
+ alloc::format!("enc_ciphertext field for {pool} action is undecryptable"),
)),
// We couldn't directly decrypt a zero-valued note. This is okay because
// it is checked elsewhere that the direct details in the PCZT are valid,
@@ -829,7 +824,7 @@ pub(crate) fn parse_orchard_output<P: consensus::Parameters>(
}
(None, 0) => Ok(("Dummy output".into(), true)),
(None, _) => Err(ZcashError::InvalidPczt(alloc::format!(
- "missing user address for {pool_label} output"
+ "missing user address for {pool} output"
))),
}?;
Ok(ParsedTo::new(
diff --git a/rust/apps/zcash/src/pczt/sign.rs b/rust/apps/zcash/src/pczt/sign.rs
index 1d49260..5ed0e79 100644
--- a/rust/apps/zcash/src/pczt/sign.rs
+++ b/rust/apps/zcash/src/pczt/sign.rs
@@ -324,7 +324,6 @@ impl PcztSigner for SeedSigner<'_> {
// Strict per-action validation, ported verbatim from the previous
// collect_orchard_bundle_signing_keys so the lean signer keeps identical
// skip/reject semantics to the RoleSigner path.
- let pool_label = self.pool;
if action.spend().spend_auth_sig().is_some() {
return Ok(());
}
@@ -333,7 +332,8 @@ impl PcztSigner for SeedSigner<'_> {
Some(0) | None => return Ok(()),
Some(_) => {
return Err(ZcashError::InvalidPczt(format!(
- "{pool_label} spend dummy_sk is only valid for dummy spends"
+ "{} spend dummy_sk is only valid for dummy spends",
+ self.pool
)));
}
}
@@ -375,7 +375,7 @@ impl PcztSigner for SeedSigner<'_> {
OsRng,
)
.map_err(|e| {
- ZcashError::SigningError(format!("failed to sign {pool_label} action: {e:?}"))
+ ZcashError::SigningError(format!("failed to sign {} action: {e:?}", self.pool))
})
})?;
self.signed.set(self.signed.get() + 1);
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.