diff --git a/packages/wasm-utxo/src/address/cashaddr.rs b/packages/wasm-utxo/src/address/cashaddr.rs index 4865339..5afa541 100644 --- a/packages/wasm-utxo/src/address/cashaddr.rs +++ b/packages/wasm-utxo/src/address/cashaddr.rs @@ -265,9 +265,9 @@ fn polymod(values: &[u8]) -> u64 { let c0 = (c >> 35) as u8; c = ((c & 0x07ffffffff) << 5) ^ (d as u64); - for i in 0..5 { + for (i, &generator) in generators.iter().enumerate() { if (c0 & (1 << i)) != 0 { - c ^= generators[i]; + c ^= generator; } } } @@ -457,7 +457,6 @@ mod tests { /// /// Using bech32 crate's `ByteIterExt::bytes_to_fes()` or checksum functions would fail these tests /// because they implement Bech32/Bech32m logic, not CashAddr logic. - // Test vector: 20-byte P2PKH payload const TEST_HASH_20: &str = "F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9"; @@ -474,7 +473,7 @@ mod tests { // Test roundtrip let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "bitcoincash").unwrap(); assert_eq!(decoded_hash, hash); - assert_eq!(is_p2sh, false); + assert!(!is_p2sh); } #[test] @@ -490,7 +489,7 @@ mod tests { // Test roundtrip let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "bchtest").unwrap(); assert_eq!(decoded_hash, hash); - assert_eq!(is_p2sh, true); + assert!(is_p2sh); } #[test] @@ -503,7 +502,7 @@ mod tests { // Test roundtrip let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "pref").unwrap(); assert_eq!(decoded_hash, hash); - assert_eq!(is_p2sh, true); + assert!(is_p2sh); } #[test] @@ -585,7 +584,7 @@ mod tests { let (hash, is_p2sh) = decode_cashaddr(uppercase, "bitcoincash").unwrap(); assert_eq!(hex::encode(hash).to_uppercase(), TEST_HASH_20); - assert_eq!(is_p2sh, false); + assert!(!is_p2sh); } #[test] @@ -628,7 +627,7 @@ mod tests { // Test roundtrip let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "ecash").unwrap(); assert_eq!(decoded_hash, hash); - assert_eq!(is_p2sh, false); + assert!(!is_p2sh); } #[test] diff --git a/packages/wasm-utxo/src/descriptor.rs b/packages/wasm-utxo/src/descriptor.rs index a08ab22..e1e9557 100644 --- a/packages/wasm-utxo/src/descriptor.rs +++ b/packages/wasm-utxo/src/descriptor.rs @@ -1,9 +1,10 @@ use crate::error::WasmMiniscriptError; use crate::try_into_js_value::TryIntoJsValue; -use miniscript::bitcoin::secp256k1::{Context, Secp256k1, Signing}; +use miniscript::bitcoin::secp256k1::{Secp256k1, Signing}; use miniscript::bitcoin::ScriptBuf; use miniscript::descriptor::KeyMap; use miniscript::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey}; +use std::fmt; use std::str::FromStr; use wasm_bindgen::prelude::*; @@ -27,12 +28,9 @@ impl WrapDescriptor { } #[wasm_bindgen(js_name = toString)] + #[allow(clippy::inherent_to_string_shadow_display)] pub fn to_string(&self) -> String { - match &self.0 { - WrapDescriptorEnum::Derivable(desc, _) => desc.to_string(), - WrapDescriptorEnum::Definite(desc) => desc.to_string(), - WrapDescriptorEnum::String(desc) => desc.to_string(), - } + format!("{}", self) } #[wasm_bindgen(js_name = hasWildcard)] @@ -115,7 +113,7 @@ impl WrapDescriptor { secp: &Secp256k1, descriptor: &str, ) -> Result { - let (desc, keys) = Descriptor::parse_descriptor(&secp, descriptor)?; + let (desc, keys) = Descriptor::parse_descriptor(secp, descriptor)?; Ok(WrapDescriptor(WrapDescriptorEnum::Derivable(desc, keys))) } @@ -199,6 +197,16 @@ impl WrapDescriptor { } } +impl fmt::Display for WrapDescriptor { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.0 { + WrapDescriptorEnum::Derivable(desc, _) => write!(f, "{}", desc), + WrapDescriptorEnum::Definite(desc) => write!(f, "{}", desc), + WrapDescriptorEnum::String(desc) => write!(f, "{}", desc), + } + } +} + impl FromStr for WrapDescriptor { type Err = WasmMiniscriptError; fn from_str(s: &str) -> Result { @@ -217,15 +225,12 @@ mod tests { ) .unwrap(); - assert_eq!(desc.has_wildcard(), false); - assert_eq!( - match desc { - WrapDescriptor { - 0: crate::descriptor::WrapDescriptorEnum::Definite(_), - } => true, - _ => false, - }, - true - ); + assert!(!desc.has_wildcard()); + assert!(matches!( + desc, + WrapDescriptor { + 0: crate::descriptor::WrapDescriptorEnum::Definite(_), + } + )); } } diff --git a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checkmultisig.rs b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checkmultisig.rs index e65aee8..1738d57 100644 --- a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checkmultisig.rs +++ b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checkmultisig.rs @@ -9,7 +9,7 @@ pub fn build_multisig_script_2_of_3(keys: &PubTriple) -> ScriptBuf { let total_count = 3; let mut builder = Builder::default().push_int(quorum as i64); for key in keys { - builder = builder.push_slice(&key.to_bytes()) + builder = builder.push_slice(key.to_bytes()) } builder .push_int(total_count as i64) @@ -51,13 +51,13 @@ pub fn parse_multisig_script_2_of_3(script: &ScriptBuf) -> Result { let key = CompressedPublicKey::from_slice(bytes.as_bytes()).map_err(|e| { format!( "Failed to parse compressed public key at position {}: {}", - i, e + idx, e ) })?; keys.push(key); @@ -65,7 +65,7 @@ pub fn parse_multisig_script_2_of_3(script: &ScriptBuf) -> Result { return Err(format!( "Instruction at position {} should be a push bytes instruction", - i + idx )); } } @@ -150,7 +150,7 @@ mod tests { // Test script with wrong number of instructions let script = Builder::new() .push_opcode(OP_PUSHNUM_2) - .push_slice(&[0x02; 33]) // Only one key instead of three + .push_slice([0x02; 33]) // Only one key instead of three .push_opcode(OP_PUSHNUM_3) .push_opcode(OP_CHECKMULTISIG) .into_script(); @@ -173,9 +173,9 @@ mod tests { // Build script with wrong quorum (OP_1 instead of OP_2) let script = Builder::new() .push_opcode(OP_PUSHNUM_1) - .push_slice(&pub_triple[0].to_bytes()) - .push_slice(&pub_triple[1].to_bytes()) - .push_slice(&pub_triple[2].to_bytes()) + .push_slice(pub_triple[0].to_bytes()) + .push_slice(pub_triple[1].to_bytes()) + .push_slice(pub_triple[2].to_bytes()) .push_opcode(OP_PUSHNUM_3) .push_opcode(OP_CHECKMULTISIG) .into_script(); @@ -198,9 +198,9 @@ mod tests { // Build script with wrong total (OP_4 instead of OP_3) let script = Builder::new() .push_opcode(OP_PUSHNUM_2) - .push_slice(&pub_triple[0].to_bytes()) - .push_slice(&pub_triple[1].to_bytes()) - .push_slice(&pub_triple[2].to_bytes()) + .push_slice(pub_triple[0].to_bytes()) + .push_slice(pub_triple[1].to_bytes()) + .push_slice(pub_triple[2].to_bytes()) .push_opcode(OP_PUSHNUM_4) .push_opcode(OP_CHECKMULTISIG) .into_script(); @@ -223,9 +223,9 @@ mod tests { // Build script without OP_CHECKMULTISIG let script = Builder::new() .push_opcode(OP_PUSHNUM_2) - .push_slice(&pub_triple[0].to_bytes()) - .push_slice(&pub_triple[1].to_bytes()) - .push_slice(&pub_triple[2].to_bytes()) + .push_slice(pub_triple[0].to_bytes()) + .push_slice(pub_triple[1].to_bytes()) + .push_slice(pub_triple[2].to_bytes()) .push_opcode(OP_PUSHNUM_3) .push_opcode(OP_PUSHNUM_1) // Wrong opcode instead of OP_CHECKMULTISIG .into_script(); @@ -242,9 +242,9 @@ mod tests { // Build script with invalid public key data let script = Builder::new() .push_opcode(OP_PUSHNUM_2) - .push_slice(&[0x00; 10]) // Invalid public key (too short) - .push_slice(&[0x02; 33]) // Valid compressed pubkey format - .push_slice(&[0x03; 33]) // Valid compressed pubkey format + .push_slice([0x00; 10]) // Invalid public key (too short) + .push_slice([0x02; 33]) // Valid compressed pubkey format + .push_slice([0x03; 33]) // Valid compressed pubkey format .push_opcode(OP_PUSHNUM_3) .push_opcode(OP_CHECKMULTISIG) .into_script(); @@ -262,8 +262,8 @@ mod tests { let script = Builder::new() .push_opcode(OP_PUSHNUM_2) .push_opcode(OP_PUSHNUM_1) // Wrong: should be pubkey bytes - .push_slice(&[0x02; 33]) - .push_slice(&[0x03; 33]) + .push_slice([0x02; 33]) + .push_slice([0x03; 33]) .push_opcode(OP_PUSHNUM_3) .push_opcode(OP_CHECKMULTISIG) .into_script(); diff --git a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checksigverify.rs b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checksigverify.rs index 3bf81cd..f9e03c5 100644 --- a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checksigverify.rs +++ b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checksigverify.rs @@ -20,7 +20,7 @@ pub fn build_p2tr_ns_script(keys: &[CompressedPublicKey]) -> ScriptBuf { for (i, key) in keys.iter().enumerate() { // convert to xonly key let key_bytes = to_xonly_pubkey(*key); - builder = builder.push_slice(&key_bytes); + builder = builder.push_slice(key_bytes); if i == keys.len() - 1 { builder = builder.push_opcode(OP_CHECKSIG); } else { @@ -89,11 +89,11 @@ impl ScriptP2tr { pub fn output_script(&self) -> ScriptBuf { let output_key = self.spend_info.output_key().to_inner(); - let output_script = Builder::new() + + Builder::new() .push_int(1) .push_slice(output_key.serialize()) - .into_script(); - output_script + .into_script() } } diff --git a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/mod.rs b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/mod.rs index af27b72..4841683 100644 --- a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/mod.rs +++ b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/mod.rs @@ -39,11 +39,11 @@ impl std::fmt::Display for WalletScripts { f, "{}", match self { - WalletScripts::P2sh(_) => format!("P2sh"), - WalletScripts::P2shP2wsh(_) => format!("P2shP2wsh"), - WalletScripts::P2wsh(_) => format!("P2wsh"), - WalletScripts::P2trLegacy(_) => format!("P2trLegacy"), - WalletScripts::P2trMusig2(_) => format!("P2trMusig2"), + WalletScripts::P2sh(_) => "P2sh".to_string(), + WalletScripts::P2shP2wsh(_) => "P2shP2wsh".to_string(), + WalletScripts::P2wsh(_) => "P2wsh".to_string(), + WalletScripts::P2trLegacy(_) => "P2trLegacy".to_string(), + WalletScripts::P2trMusig2(_) => "P2trMusig2".to_string(), } ) } @@ -165,7 +165,7 @@ pub fn derive_xpubs_with_path( ) -> XpubTriple { let derived = xpubs .iter() - .map(|k| k.derive_pub(&ctx, &p).unwrap()) + .map(|k| k.derive_pub(ctx, &p).unwrap()) .collect::>(); derived.try_into().expect("could not convert vec to array") } @@ -182,7 +182,7 @@ pub fn derive_xpubs( index: chain as u32, }) .child(ChildNumber::Normal { index }); - derive_xpubs_with_path(&xpubs, ctx, p) + derive_xpubs_with_path(xpubs, ctx, p) } #[cfg(test)] @@ -383,14 +383,14 @@ mod tests { .expect("Failed to find input with script type"); let (chain, index) = - parse_fixture_paths(&input_fixture).expect("Failed to parse fixture paths"); + parse_fixture_paths(input_fixture).expect("Failed to parse fixture paths"); let scripts = WalletScripts::from_xpubs(&xpubs, chain, index); // Use the new helper methods for validation match (scripts, input_fixture) { (WalletScripts::P2sh(scripts), fixtures::PsbtInputFixture::P2sh(fixture_input)) => { let vout = fixture.inputs[input_index].index as usize; - let output_script = get_output_script_from_non_witness_utxo(&fixture_input, vout); + let output_script = get_output_script_from_non_witness_utxo(fixture_input, vout); fixture_input .assert_matches_wallet_scripts(&scripts, &output_script) .expect("P2sh validation failed"); diff --git a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/singlesig.rs b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/singlesig.rs index 062e249..21b8f04 100644 --- a/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/singlesig.rs +++ b/packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/singlesig.rs @@ -7,7 +7,7 @@ use crate::bitcoin::{CompressedPublicKey, ScriptBuf}; /// Build bare p2pk script (used for p2sh-p2pk replay protection) pub fn build_p2pk_script(key: CompressedPublicKey) -> ScriptBuf { Builder::default() - .push_slice(&key.to_bytes()) + .push_slice(key.to_bytes()) .push_opcode(OP_CHECKSIG) .into_script() } @@ -58,7 +58,7 @@ mod tests { let expected_redeem_script = &p2shp2pk_input.redeem_script; let expected_pubkey = p2shp2pk_input .partial_sig - .get(0) + .first() .map(|sig| &sig.pubkey) .expect("No partial signature found"); diff --git a/packages/wasm-utxo/src/lib.rs b/packages/wasm-utxo/src/lib.rs index dd4d610..420309a 100644 --- a/packages/wasm-utxo/src/lib.rs +++ b/packages/wasm-utxo/src/lib.rs @@ -12,6 +12,7 @@ mod try_into_js_value; pub use ::miniscript::bitcoin; pub use address::utxolib_compat; +pub use address::*; pub use descriptor::WrapDescriptor; pub use miniscript::WrapMiniscript; pub use psbt::WrapPsbt; diff --git a/packages/wasm-utxo/src/miniscript.rs b/packages/wasm-utxo/src/miniscript.rs index f068cd1..cacc0b3 100644 --- a/packages/wasm-utxo/src/miniscript.rs +++ b/packages/wasm-utxo/src/miniscript.rs @@ -2,6 +2,7 @@ use crate::error::WasmMiniscriptError; use crate::try_into_js_value::TryIntoJsValue; use miniscript::bitcoin::{PublicKey, XOnlyPublicKey}; use miniscript::{bitcoin, Legacy, Miniscript, Segwitv0, Tap}; +use std::fmt; use std::str::FromStr; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; @@ -35,8 +36,9 @@ impl WrapMiniscript { } #[wasm_bindgen(js_name = toString)] + #[allow(clippy::inherent_to_string_shadow_display)] pub fn to_string(&self) -> String { - unwrap_apply!(&self.0, |ms| ms.to_string()) + format!("{}", self) } #[wasm_bindgen(js_name = encode)] @@ -112,3 +114,9 @@ impl From> for WrapMiniscript { WrapMiniscript(WrapMiniscriptEnum::Legacy(miniscript)) } } + +impl fmt::Display for WrapMiniscript { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unwrap_apply!(&self.0, |ms| write!(f, "{}", ms)) + } +} diff --git a/packages/wasm-utxo/src/psbt.rs b/packages/wasm-utxo/src/psbt.rs index 3cd0841..f2312ef 100644 --- a/packages/wasm-utxo/src/psbt.rs +++ b/packages/wasm-utxo/src/psbt.rs @@ -3,8 +3,8 @@ use crate::error::WasmMiniscriptError; use crate::try_into_js_value::TryIntoJsValue; use crate::WrapDescriptor; use miniscript::bitcoin::bip32::Fingerprint; -use miniscript::bitcoin::secp256k1::{Context, Secp256k1, Signing}; -use miniscript::bitcoin::{bip32, psbt, secp256k1, PublicKey, XOnlyPublicKey}; +use miniscript::bitcoin::secp256k1::{Secp256k1, Signing}; +use miniscript::bitcoin::{bip32, psbt, PublicKey, XOnlyPublicKey}; use miniscript::bitcoin::{PrivateKey, Psbt}; use miniscript::descriptor::{SinglePub, SinglePubKey}; use miniscript::psbt::PsbtExt; @@ -17,7 +17,7 @@ use wasm_bindgen::{JsError, JsValue}; struct SingleKeySigner { privkey: PrivateKey, pubkey: PublicKey, - pubkey_xonly: XOnlyPublicKey, + _pubkey_xonly: XOnlyPublicKey, fingerprint: Fingerprint, fingerprint_xonly: Fingerprint, } @@ -33,7 +33,7 @@ impl SingleKeySigner { SingleKeySigner { privkey, pubkey, - pubkey_xonly, + _pubkey_xonly: pubkey_xonly, fingerprint: SingleKeySigner::fingerprint(SinglePubKey::FullKey(pubkey)), fingerprint_xonly: SingleKeySigner::fingerprint(SinglePubKey::XOnly(pubkey_xonly)), } @@ -46,7 +46,7 @@ impl psbt::GetKey for SingleKeySigner { fn get_key( &self, key_request: psbt::KeyRequest, - secp: &Secp256k1, + _secp: &Secp256k1, ) -> Result, Self::Error> { match key_request { // NOTE: this KeyRequest does not occur for taproot signatures @@ -54,15 +54,15 @@ impl psbt::GetKey for SingleKeySigner { // instead based on `DescriptorPublicKey::Single(SinglePub { origin: None, key, })` psbt::KeyRequest::Pubkey(req_pubkey) => { if req_pubkey == self.pubkey { - Ok(Some(self.privkey.clone())) + Ok(Some(self.privkey)) } else { Ok(None) } } - psbt::KeyRequest::Bip32((fingerprint, path)) => { + psbt::KeyRequest::Bip32((fingerprint, _path)) => { if fingerprint.eq(&self.fingerprint) || fingerprint.eq(&self.fingerprint_xonly) { - Ok(Some(self.privkey.clone())) + Ok(Some(self.privkey)) } else { Ok(None) } @@ -86,8 +86,9 @@ impl WrapPsbt { self.0.serialize() } + #[allow(clippy::should_implement_trait)] pub fn clone(&self) -> WrapPsbt { - WrapPsbt(self.0.clone()) + Clone::clone(self) } #[wasm_bindgen(js_name = updateInputWithDescriptor)] @@ -99,7 +100,7 @@ impl WrapPsbt { match &descriptor.0 { WrapDescriptorEnum::Definite(d) => self .0 - .update_input_with_descriptor(input_index, &d) + .update_input_with_descriptor(input_index, d) .map_err(JsError::from), WrapDescriptorEnum::Derivable(_, _) => Err(JsError::new( "Cannot update input with a derivable descriptor", @@ -119,7 +120,7 @@ impl WrapPsbt { match &descriptor.0 { WrapDescriptorEnum::Definite(d) => self .0 - .update_output_with_descriptor(output_index, &d) + .update_output_with_descriptor(output_index, d) .map_err(JsError::from), WrapDescriptorEnum::Derivable(_, _) => Err(JsError::new( "Cannot update output with a derivable descriptor", @@ -149,7 +150,7 @@ impl WrapPsbt { let secp = Secp256k1::new(); self.0 .sign(&SingleKeySigner::from_privkey(privkey, &secp), &secp) - .map_err(|(r, errors)| { + .map_err(|(_r, errors)| { WasmMiniscriptError::new(&format!("{} errors: {:?}", errors.len(), errors)) }) .and_then(|r| r.try_to_js_value()) @@ -165,6 +166,12 @@ impl WrapPsbt { } } +impl Clone for WrapPsbt { + fn clone(&self) -> Self { + WrapPsbt(self.0.clone()) + } +} + #[cfg(test)] mod tests { use crate::psbt::SingleKeySigner; @@ -200,7 +207,7 @@ mod tests { .values() .for_each(|key_source| { let key_source_ref: KeySource = ( - Fingerprint::from_hex(&"aeee1e6a").unwrap(), + Fingerprint::from_hex("aeee1e6a").unwrap(), DerivationPath::from(vec![]), ); assert_eq!(key_source.1, key_source_ref); diff --git a/packages/wasm-utxo/src/try_into_js_value.rs b/packages/wasm-utxo/src/try_into_js_value.rs index d189a0a..fde3fdd 100644 --- a/packages/wasm-utxo/src/try_into_js_value.rs +++ b/packages/wasm-utxo/src/try_into_js_value.rs @@ -283,12 +283,8 @@ impl TryIntoJsValue for SigningKeysMap { fn try_to_js_value(&self) -> Result { let obj = js_sys::Object::new(); for (key, value) in self.iter() { - js_sys::Reflect::set( - &obj, - &key.to_string().into(), - &value.try_to_js_value()?.into(), - ) - .map_err(|_| WasmMiniscriptError::new("Failed to set object property"))?; + js_sys::Reflect::set(&obj, &key.to_string().into(), &value.try_to_js_value()?) + .map_err(|_| WasmMiniscriptError::new("Failed to set object property"))?; } Ok(obj.into()) }