What changed, and why it matters
This commit is a routine Zcash update and test-coverage improvement. It renames a misspelled function, splits a large signing routine into transparent-only and orchard-only variants, and adds unit tests for wallet integrations. There is no direct evidence in the commit that this fixes an active security vulnerability, but the change to Zcash shielded signing logic is security-adjacent and should be reviewed carefully.
Treat as a normal code-quality and feature-update commit, but perform a focused review of the new sign_orchard path to ensure orchard signatures are produced over the correct sighash and that transparent inputs are still signed exactly once by the caller. Verify that the cypherpunk feature gating does not accidentally disable signing for non-cypherpunk builds.
Security signals we found
Zcash shielded transaction signing logic changed
Function renamed from sign_full to sign_orchard, removing duplicated transparent signing path
Typo fix in shielded_sig_commitment (previously sheilded_sig_commitment)
cypherpunk feature gating tightened for orchard tests
No explicit security claim or CVE reference in commit message or diff
Evidence from the diff
The commit updates the Zcash PCZT (Partially Created Zcash Transaction) signing flow. The main functional changes are in rust/zcash_vendor/src/pczt_ext.rs and rust/apps/zcash/src/pczt/sign.rs: the previous sign_full helper is replaced by sign_orchard, which only signs orchard shielded inputs and no longer re-implements transparent signing. A typo ‘sheilded_sig_commitment’ is corrected to ‘shielded_sig_commitment’. The cypherpunk feature gate is applied more consistently, and the keystore’s trivial-seed rejection test is moved out of the orchard-only test module. The remaining changes add unit tests to metamask.rs, okx.rs, thor_wallet.rs, and zcash.rs, and raise code-coverage thresholds in CI.
Changed components
rust/apps/zcash/src/pczt/sign.rsrust/zcash_vendor/src/pczt_ext.rsrust/keystore/src/algorithms/zcash/mod.rsrust/apps/zcash/Cargo.tomlrust/apps/wallets/src/metamask.rsrust/apps/wallets/src/okx.rsrust/apps/wallets/src/thor_wallet.rsrust/apps/wallets/src/zcash.rs.github/workflows/rust-wallets-checks.ymlInspect captured patch +237 / −56
diff --git a/.github/workflows/rust-wallets-checks.yml b/.github/workflows/rust-wallets-checks.yml
index ce0bba6..12fa43f 100644
--- a/.github/workflows/rust-wallets-checks.yml
+++ b/.github/workflows/rust-wallets-checks.yml
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/wallets
- run: cd rust/apps/wallets && cargo +nightly-2025-05-01 llvm-cov --fail-under-regions 51 --fail-under-functions 54 --fail-under-lines 70 --ignore-filename-regex 'keystore/*|xrp/*'
+ run: cd rust/apps/wallets && cargo +nightly-2025-05-01 llvm-cov --fail-under-regions 71 --fail-under-functions 71 --fail-under-lines 88 --ignore-filename-regex 'keystore/*|xrp/*|utils/*'
diff --git a/rust/apps/wallets/src/metamask.rs b/rust/apps/wallets/src/metamask.rs
index 63d72e9..62a8e53 100644
--- a/rust/apps/wallets/src/metamask.rs
+++ b/rust/apps/wallets/src/metamask.rs
@@ -155,7 +155,7 @@ fn get_path_component(index: Option<u32>, hardened: bool) -> URResult<PathCompon
mod tests {
extern crate std;
- use crate::metamask::generate_ledger_live_account;
+ use crate::metamask::{generate_ledger_live_account, generate_standard_legacy_hd_key, ETHAccountTypeApp};
use alloc::string::ToString;
use alloc::vec;
use alloc::vec::Vec;
@@ -190,4 +190,29 @@ mod tests {
assert_eq!(hex::encode(cbor).to_lowercase(),
"a2011a757e6fc9028ad9012fa502f40358210326bd25d39a5eeb0217c4508bc5c50d28087121372daa5d2e48b30a8f3345998606d90130a3018a182cf5183cf500f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f4035821030b235be63214e20961295fb82ff3fe365c21e3c5c203bc7a995b5f31fa10a86506d90130a3018a182cf5183cf501f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f4035821020a48e423f5991eba82dc251aa4b7191bb4bf72838ff61e761fe1e08f374968e706d90130a3018a182cf5183cf502f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f403582103c2d7cb8f289f4211064258c63c86a57d22eb4e2565fa1c9b203797251a1fad9d06d90130a3018a182cf5183cf503f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f403582103435a76cc11055f740187fbfe68a7a1f0180fe43f6835bd52797bb50c6e567a2506d90130a3018a182cf5183cf504f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f403582102f41789edb56ce2786392d4fb040565ac767be3e43355610a91853e65212a02a106d90130a3018a182cf5183cf505f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f4035821038f4e60d5035d28a76d1b9a64dd7867b11fb652a56605a0e51923b4f49e23522a06d90130a3018a182cf5183cf506f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f403582102765303723f047bac13ff1a9617c0891fd23ebcf7c7053d4c2d1dc49f24c9e0d906d90130a3018a182cf5183cf507f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f403582103ac7982290292097e2d072b5520911a4c94af713ae49cdd8ab6fcd1895c194ef306d90130a3018a182cf5183cf508f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665d9012fa502f4035821039fcc0a270027ee3d8ad2b41f172d03aa8f5353a9876301e0799f845bda6f1f3506d90130a3018a182cf5183cf509f500f400f4021a757e6fc9030309684b657973746f6e650a736163636f756e742e6c65646765725f6c697665");
}
+
+ #[test]
+ fn test_eth_account_type_app_to_i32() {
+ assert_eq!(ETHAccountTypeApp::Bip44Standard.to_i32(), 0);
+ assert_eq!(ETHAccountTypeApp::LedgerLive.to_i32(), 1);
+ assert_eq!(ETHAccountTypeApp::LedgerLegacy.to_i32(), 2);
+ }
+
+ #[test]
+ fn test_generate_standard_legacy_hd_key() {
+ let mfp = "757E6FC9";
+ let mfp = Vec::from_hex(mfp).unwrap();
+ let mfp: [u8; 4] = mfp.try_into().unwrap();
+ let x_pub = "xpub6C8zKiZZ8V75XynjThhvdjy7hbnJHAFkhW7jL9EvBCsRFSRov4sXUJATU6CqUF9BxAbryiU3eghdHDLbwgF8ASE4AwHTzkLHaHsbwiCnkHc";
+
+ // Test Bip44Standard
+ let result = generate_standard_legacy_hd_key(&mfp, x_pub, ETHAccountTypeApp::Bip44Standard, None).unwrap();
+ let cbor: Vec<u8> = result.try_into().unwrap();
+ assert!(!cbor.is_empty());
+
+ // Test LedgerLegacy
+ let result = generate_standard_legacy_hd_key(&mfp, x_pub, ETHAccountTypeApp::LedgerLegacy, None).unwrap();
+ let cbor: Vec<u8> = result.try_into().unwrap();
+ assert!(!cbor.is_empty());
+ }
}
diff --git a/rust/apps/wallets/src/okx.rs b/rust/apps/wallets/src/okx.rs
index 6c6b1b9..4086db6 100644
--- a/rust/apps/wallets/src/okx.rs
+++ b/rust/apps/wallets/src/okx.rs
@@ -173,3 +173,72 @@ fn generate_eth_ledger_live_key(
note,
))
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use alloc::vec;
+ use bitcoin::bip32::{DerivationPath, Xpub};
+ use core::str::FromStr;
+
+ fn serialize_xpub(xpub: &Xpub) -> Vec<u8> {
+ let mut bytes = Vec::new();
+ // Version: xpub (Mainnet) = 0x0488B21E
+ bytes.extend_from_slice(&[0x04, 0x88, 0xB2, 0x1E]);
+ bytes.push(xpub.depth);
+ bytes.extend_from_slice(xpub.parent_fingerprint.as_bytes());
+ // ChildNumber to u32
+ let child_num: u32 = xpub.child_number.into();
+ bytes.extend_from_slice(&child_num.to_be_bytes());
+ bytes.extend_from_slice(xpub.chain_code.as_bytes());
+ bytes.extend_from_slice(&xpub.public_key.serialize());
+ bytes
+ }
+
+ #[test]
+ fn test_generate_crypto_multi_accounts() {
+ let mfp = [0x75, 0x7e, 0x6f, 0xc9];
+ let serial = "123456";
+ let device_type = "Keystone 3 Pro";
+ let device_version = "1.0.0";
+
+ // ETH Standard xpub
+ let eth_xpub_str = "xpub6C8zKiZZ8V75XynjThhvdjy7hbnJHAFkhW7jL9EvBCsRFSRov4sXUJATU6CqUF9BxAbryiU3eghdHDLbwgF8ASE4AwHTzkLHaHsbwiCnkHc";
+ let eth_xpub = Xpub::from_str(eth_xpub_str).unwrap();
+ let eth_xpub_bytes = serialize_xpub(ð_xpub);
+
+ let eth_path = DerivationPath::from_str("m/44'/60'/0'").unwrap();
+ let eth_key = ExtendedPublicKey {
+ path: eth_path,
+ key: eth_xpub_bytes,
+ };
+
+ // BTC Native Segwit xpub
+ let btc_xpub_str = "xpub6C8zKiZZ8V75aXTgYAswqCgYUHeBYg1663a4Ri6zdJ4GW58r67Kmj4Fr8pbBK9usq45o8iQ8dBM75o67ct1M38yeb6RhFTWBxiYeq8Kg84Z";
+ let btc_xpub = Xpub::from_str(btc_xpub_str).unwrap();
+ let btc_xpub_bytes = serialize_xpub(&btc_xpub);
+
+ let btc_path = DerivationPath::from_str("m/84'/0'/0'").unwrap();
+ let btc_key = ExtendedPublicKey {
+ path: btc_path,
+ key: btc_xpub_bytes,
+ };
+
+ let keys = vec![eth_key, btc_key];
+
+ let result = generate_crypto_multi_accounts(mfp, serial, keys, device_type, device_version);
+ assert!(result.is_ok());
+
+ let multi_accounts = result.unwrap();
+ let cbor: Vec<u8> = multi_accounts.clone().try_into().unwrap();
+ assert!(!cbor.is_empty());
+
+ // Verify device info
+ assert_eq!(multi_accounts.get_device(), Some(device_type.to_string()));
+ assert_eq!(multi_accounts.get_device_version(), Some(device_version.to_string()));
+
+ // Verify keys count
+ // ETH generates 2 keys (standard + ledger live), BTC generates 1 key. Total 3.
+ assert_eq!(multi_accounts.get_keys().len(), 3);
+ }
+}
diff --git a/rust/apps/wallets/src/thor_wallet.rs b/rust/apps/wallets/src/thor_wallet.rs
index cd98228..33b0ea1 100644
--- a/rust/apps/wallets/src/thor_wallet.rs
+++ b/rust/apps/wallets/src/thor_wallet.rs
@@ -165,3 +165,83 @@ fn generate_eth_ledger_live_key(
note,
))
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use alloc::vec;
+ use bitcoin::bip32::{DerivationPath, Xpub};
+ use core::str::FromStr;
+
+ fn serialize_xpub(xpub: &Xpub) -> Vec<u8> {
+ let mut bytes = Vec::new();
+ // Version: xpub (Mainnet) = 0x0488B21E
+ bytes.extend_from_slice(&[0x04, 0x88, 0xB2, 0x1E]);
+ bytes.push(xpub.depth);
+ bytes.extend_from_slice(xpub.parent_fingerprint.as_bytes());
+ // ChildNumber to u32
+ let child_num: u32 = xpub.child_number.into();
+ bytes.extend_from_slice(&child_num.to_be_bytes());
+ bytes.extend_from_slice(xpub.chain_code.as_bytes());
+ bytes.extend_from_slice(&xpub.public_key.serialize());
+ bytes
+ }
+
+ #[test]
+ fn test_generate_crypto_multi_accounts() {
+ let mfp = [0x75, 0x7e, 0x6f, 0xc9];
+ let serial = "123456";
+ let device_type = "Keystone 3 Pro";
+ let device_version = "1.0.0";
+
+ // ETH Standard xpub
+ let eth_xpub_str = "xpub6C8zKiZZ8V75XynjThhvdjy7hbnJHAFkhW7jL9EvBCsRFSRov4sXUJATU6CqUF9BxAbryiU3eghdHDLbwgF8ASE4AwHTzkLHaHsbwiCnkHc";
+ let eth_xpub = Xpub::from_str(eth_xpub_str).unwrap();
+ let eth_xpub_bytes = serialize_xpub(ð_xpub);
+
+ let eth_path = DerivationPath::from_str("m/44'/60'/0'").unwrap();
+ let eth_key = ExtendedPublicKey {
+ path: eth_path,
+ key: eth_xpub_bytes,
+ };
+
+ // BTC Native Segwit xpub
+ let btc_xpub_str = "xpub6C8zKiZZ8V75aXTgYAswqCgYUHeBYg1663a4Ri6zdJ4GW58r67Kmj4Fr8pbBK9usq45o8iQ8dBM75o67ct1M38yeb6RhFTWBxiYeq8Kg84Z";
+ let btc_xpub = Xpub::from_str(btc_xpub_str).unwrap();
+ let btc_xpub_bytes = serialize_xpub(&btc_xpub);
+
+ let btc_path = DerivationPath::from_str("m/84'/0'/0'").unwrap();
+ let btc_key = ExtendedPublicKey {
+ path: btc_path,
+ key: btc_xpub_bytes,
+ };
+
+ // Thorchain xpub
+ let thor_xpub_str = "xpub6C8zKiZZ8V75tgxbNbnWfAbC63k1s6tQvfpYLNLaEzq3aUhhZu798JUyMJVL3fNK2CcF2vKauyBdF73TxjLyfU9Cfb4SLKxLDr3SUVVSAQL";
+ let thor_xpub = Xpub::from_str(thor_xpub_str).unwrap();
+ let thor_xpub_bytes = serialize_xpub(&thor_xpub);
+
+ let thor_path = DerivationPath::from_str("m/44'/931'/0'").unwrap();
+ let thor_key = ExtendedPublicKey {
+ path: thor_path,
+ key: thor_xpub_bytes,
+ };
+
+ let keys = vec![eth_key, btc_key, thor_key];
+
+ let result = generate_crypto_multi_accounts(mfp, serial, keys, device_type, device_version);
+ assert!(result.is_ok());
+
+ let multi_accounts = result.unwrap();
+ let cbor: Vec<u8> = multi_accounts.clone().try_into().unwrap();
+ assert!(!cbor.is_empty());
+
+ // Verify device info
+ assert_eq!(multi_accounts.get_device(), Some(device_type.to_string()));
+ assert_eq!(multi_accounts.get_device_version(), Some(device_version.to_string()));
+
+ // Verify keys count
+ // ETH generates 2 keys (standard + ledger live), BTC generates 1 key, Thorchain generates 1 key. Total 4.
+ assert_eq!(multi_accounts.get_keys().len(), 4);
+ }
+}
diff --git a/rust/apps/wallets/src/zcash.rs b/rust/apps/wallets/src/zcash.rs
index 93b6dcc..8a774da 100644
--- a/rust/apps/wallets/src/zcash.rs
+++ b/rust/apps/wallets/src/zcash.rs
@@ -33,3 +33,35 @@ pub fn generate_sync_ur(
let accounts = ZcashAccounts::new(seed_fingerprint.to_vec(), keys);
Ok(accounts)
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use alloc::vec;
+ use alloc::string::ToString;
+
+ #[test]
+ fn test_generate_sync_ur() {
+ let seed_fingerprint = [1u8; 32];
+ let key_infos = vec![
+ UFVKInfo {
+ key_text: "uview1vmle95235860km865468566554".to_string(),
+ key_name: "Account 0".to_string(),
+ index: 0,
+ },
+ UFVKInfo {
+ key_text: "uview1vmle95235860km865468566555".to_string(),
+ key_name: "Account 1".to_string(),
+ index: 1,
+ },
+ ];
+
+ let result = generate_sync_ur(key_infos, seed_fingerprint);
+ assert!(result.is_ok());
+
+ let accounts = result.unwrap();
+ let cbor: Vec<u8> = accounts.try_into().unwrap();
+ assert!(!cbor.is_empty());
+ }
+}
+
diff --git a/rust/apps/zcash/Cargo.toml b/rust/apps/zcash/Cargo.toml
index 4250768..403c924 100644
--- a/rust/apps/zcash/Cargo.toml
+++ b/rust/apps/zcash/Cargo.toml
@@ -11,7 +11,7 @@ rust_tools = { workspace = true }
app_utils = { workspace = true }
bitcoin = { workspace = true }
thiserror = { workspace = true }
-zcash_vendor = { workspace = true }
+zcash_vendor = { workspace = true, default-features = false}
hex = { workspace = true }
bitvec = { version = "1.0.1", default-features = false, features = ["alloc"] }
blake2b_simd = { workspace = true }
diff --git a/rust/apps/zcash/src/pczt/sign.rs b/rust/apps/zcash/src/pczt/sign.rs
index 1865add..3ea000a 100644
--- a/rust/apps/zcash/src/pczt/sign.rs
+++ b/rust/apps/zcash/src/pczt/sign.rs
@@ -109,7 +109,7 @@ pub fn sign_pczt(pczt: Pczt, seed: &[u8]) -> crate::Result<Vec<u8>> {
let signer = pczt_ext::sign_transparent(signer, &SeedSigner { seed })
.map_err(|e| ZcashError::SigningError(e.to_string()))?;
#[cfg(feature = "cypherpunk")]
- let signer = pczt_ext::sign_full(signer, &SeedSigner { seed })
+ let signer = pczt_ext::sign_orchard(signer, &SeedSigner { seed })
.map_err(|e| ZcashError::SigningError(e.to_string()))?;
// Now that we've created the signature, remove the other optional fields from the
diff --git a/rust/keystore/src/algorithms/zcash/mod.rs b/rust/keystore/src/algorithms/zcash/mod.rs
index feb747d..3742811 100644
--- a/rust/keystore/src/algorithms/zcash/mod.rs
+++ b/rust/keystore/src/algorithms/zcash/mod.rs
@@ -103,8 +103,9 @@ pub fn sign_message_orchard<R: RngCore + CryptoRng>(
}
}
+#[cfg(feature = "cypherpunk")]
#[cfg(test)]
-mod tests {
+mod orchard_tests {
use super::*;
use zcash_vendor::{
pasta_curves::Fq,
@@ -164,21 +165,6 @@ mod tests {
);
}
- #[test]
- fn test_reject_trivial_seed() {
- // all-zero seed should be rejected
- let zero_seed = vec![0u8; 32];
- let result = calculate_seed_fingerprint(&zero_seed);
- assert!(result.is_err());
- assert!(matches!(result, Err(KeystoreError::SeedError(_))));
-
- // all-0xFF seed should also be rejected
- let ff_seed = vec![0xffu8; 32];
- let result = calculate_seed_fingerprint(&ff_seed);
- assert!(result.is_err());
- assert!(matches!(result, Err(KeystoreError::SeedError(_))));
- }
-
#[test]
fn test_orchard_signing() {
let rng_seed = [0u8; 32];
@@ -206,3 +192,22 @@ mod tests {
assert_eq!(hex::encode(bytes), "065ef82c33af0ed487e8932112e3359e93c5955d3eac6c3a1f9cb6dd24e19d8a2bba454a4274154dd4ad0c6bdb2022a646950ed521f3de18e99015f4821cbb10");
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[test]
+ fn test_reject_trivial_seed() {
+ // all-zero seed should be rejected
+ let zero_seed = vec![0u8; 32];
+ let result = calculate_seed_fingerprint(&zero_seed);
+ assert!(result.is_err());
+ assert!(matches!(result, Err(KeystoreError::SeedError(_))));
+
+ // all-0xFF seed should also be rejected
+ let ff_seed = vec![0xffu8; 32];
+ let result = calculate_seed_fingerprint(&ff_seed);
+ assert!(result.is_err());
+ assert!(matches!(result, Err(KeystoreError::SeedError(_))));
+ }
+}
diff --git a/rust/zcash_vendor/src/pczt_ext.rs b/rust/zcash_vendor/src/pczt_ext.rs
index 67e15cd..f8ddf33 100644
--- a/rust/zcash_vendor/src/pczt_ext.rs
+++ b/rust/zcash_vendor/src/pczt_ext.rs
@@ -101,6 +101,7 @@ pub trait PcztSigner {
) -> Result<(), Self::Error>
where
F: FnOnce(SignableInput) -> [u8; 32];
+
#[cfg(feature = "cypherpunk")]
fn sign_orchard(
&self,
@@ -293,7 +294,7 @@ fn hash_orchard_txid_empty() -> Hash {
hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION).finalize()
}
-fn sheilded_sig_commitment(pczt: &Pczt, lock_time: u32, input_info: Option<SignableInput>) -> Hash {
+fn shielded_sig_commitment(pczt: &Pczt, lock_time: u32, input_info: Option<SignableInput>) -> Hash {
let mut personal = [0; 16];
personal[..12].copy_from_slice(ZCASH_TX_PERSONALIZATION_PREFIX);
personal[12..].copy_from_slice(&pczt.global().consensus_branch_id().to_le_bytes());
@@ -404,7 +405,7 @@ where
.enumerate()
.try_for_each(|(i, input)| {
signer.sign_transparent(i, input, |signable_input| {
- sheilded_sig_commitment(pczt, lock_time, Some(signable_input))
+ shielded_sig_commitment(pczt, lock_time, Some(signable_input))
.as_bytes()
.try_into()
.expect("correct length")
@@ -429,43 +430,12 @@ where
}
#[cfg(feature = "cypherpunk")]
-pub fn sign_full<T>(llsigner: Signer, signer: &T) -> Result<Signer, T::Error>
+pub fn sign_orchard<T>(llsigner: Signer, signer: &T) -> Result<Signer, T::Error>
where
T: PcztSigner,
- T::Error: From<transparent::pczt::ParseError>,
+ T::Error: From<orchard::pczt::ParseError>,
{
llsigner
- .sign_transparent_with::<T::Error, _>(|pczt, signable, tx_modifiable| {
- let lock_time = determine_lock_time(pczt.global(), pczt.transparent().inputs())
- .ok_or(transparent::pczt::ParseError::InvalidRequiredHeightLocktime)?;
- signable
- .inputs_mut()
- .iter_mut()
- .enumerate()
- .try_for_each(|(i, input)| {
- signer.sign_transparent(i, input, |signable_input| {
- sheilded_sig_commitment(pczt, lock_time, Some(signable_input))
- .as_bytes()
- .try_into()
- .expect("correct length")
- })?;
-
- if input.sighash_type().encode() & SIGHASH_ANYONECANPAY == 0 {
- *tx_modifiable &= !FLAG_TRANSPARENT_INPUTS_MODIFIABLE;
- }
-
- if (input.sighash_type().encode() & !SIGHASH_ANYONECANPAY) != SIGHASH_NONE {
- *tx_modifiable &= !FLAG_TRANSPARENT_OUTPUTS_MODIFIABLE;
- }
-
- if (input.sighash_type().encode() & !SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE {
- *tx_modifiable |= FLAG_HAS_SIGHASH_SINGLE;
- }
-
- *tx_modifiable &= !FLAG_SHIELDED_MODIFIABLE;
- Ok(())
- })
- })?
.sign_orchard_with::<T::Error, _>(|pczt, signable, tx_modifiable| {
let lock_time = determine_lock_time(pczt.global(), pczt.transparent().inputs())
.ok_or(transparent::pczt::ParseError::InvalidRequiredHeightLocktime)?;
@@ -477,7 +447,7 @@ where
}
Some(_) => {
signer
- .sign_orchard(action, sheilded_sig_commitment(pczt, lock_time, None))?;
+ .sign_orchard(action, shielded_sig_commitment(pczt, lock_time, None))?;
*tx_modifiable &= !(FLAG_TRANSPARENT_INPUTS_MODIFIABLE
| FLAG_TRANSPARENT_OUTPUTS_MODIFIABLE
| FLAG_SHIELDED_MODIFIABLE);
Why this scored 26/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.