What changed, and why it matters
This commit is a small code cleanup in the Zcash part of the Keystone hardware wallet firmware. It changes how the code checks for duplicate 'rk' values across Orchard and Ironwood shielded transaction actions. The old code used chained iterators and cloned them repeatedly; the new code collects the actions into a vector first and then uses nested loops. The behavior appears unchanged: it still rejects duplicate rk values with the same error message. There is no direct evidence in the commit that this fixes a security bug.
No immediate security action required. Treat as routine code-quality refactor. If auditing, verify that the new nested-loop logic is equivalent to the old iterator-based logic and that no action is skipped or compared twice.
Security signals we found
No security-relevant behavioral change visible in diff
Function still rejects duplicate Orchard/Ironwood action rk values
Refactoring from iterator-based duplicate detection to vector-based nested loops
No new input validation, no changed error conditions, no changed return values
Evidence from the diff
The function validate_distinct_orchard_protocol_rks in rust/apps/zcash/src/pczt/mod.rs is refactored. Previously it chained two iterators over orchard and ironwood actions and used .clone() plus .skip/.any to detect duplicate spend().rk() values. Now it collects the chained iterator into a Vec and uses explicit nested indexing loops. The logic and error return remain the same. The change is described as an optimization. No security relevance is stated, no CVE or attribution is present, and no advisory references are supplied.
Changed components
rust/apps/zcash/src/pczt/mod.rsvalidate_distinct_orchard_protocol_rks functionZcash PCZT (Partially Created Zcash Transaction) handlingInspect captured patch +11 / −12
diff --git a/rust/apps/zcash/src/pczt/mod.rs b/rust/apps/zcash/src/pczt/mod.rs
index 2ae0724..f96eaad 100644
--- a/rust/apps/zcash/src/pczt/mod.rs
+++ b/rust/apps/zcash/src/pczt/mod.rs
@@ -3,7 +3,7 @@ pub mod parse;
pub mod sign;
pub mod structs;
-use alloc::{format, string::ToString};
+use alloc::{format, string::ToString, vec::Vec};
use zcash_vendor::{
pczt::Pczt,
transparent,
@@ -59,17 +59,16 @@ fn validate_distinct_orchard_protocol_rks(pczt: &Pczt) -> Result<(), ZcashError>
.orchard()
.actions()
.iter()
- .chain(pczt.ironwood().actions().iter());
-
- for (index, action) in actions.clone().enumerate() {
- if actions
- .clone()
- .skip(index + 1)
- .any(|other| other.spend().rk() == action.spend().rk())
- {
- return Err(ZcashError::InvalidPczt(
- "duplicate Orchard or Ironwood action rk".to_string(),
- ));
+ .chain(pczt.ironwood().actions().iter())
+ .collect::<Vec<_>>();
+
+ for i in 0..actions.len() {
+ for j in (i + 1)..actions.len() {
+ if actions[i].spend().rk() == actions[j].spend().rk() {
+ return Err(ZcashError::InvalidPczt(
+ "duplicate Orchard or Ironwood action rk".to_string(),
+ ));
+ }
}
}
Why this scored 31/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.