Skip to content

Commit 9b0e841

Browse files
Merge pull request #12 from BitGo/BTC-2652.add-fixedscriptwallet-outputs.lint-fix
feat(wasm-utxo): improve code quality with idiomatic Rust patterns
2 parents a7de986 + 6d5051c commit 9b0e841

File tree

10 files changed

+96
-80
lines changed

10 files changed

+96
-80
lines changed

packages/wasm-utxo/src/address/cashaddr.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,9 @@ fn polymod(values: &[u8]) -> u64 {
265265
let c0 = (c >> 35) as u8;
266266
c = ((c & 0x07ffffffff) << 5) ^ (d as u64);
267267

268-
for i in 0..5 {
268+
for (i, &generator) in generators.iter().enumerate() {
269269
if (c0 & (1 << i)) != 0 {
270-
c ^= generators[i];
270+
c ^= generator;
271271
}
272272
}
273273
}
@@ -457,7 +457,6 @@ mod tests {
457457
///
458458
/// Using bech32 crate's `ByteIterExt::bytes_to_fes()` or checksum functions would fail these tests
459459
/// because they implement Bech32/Bech32m logic, not CashAddr logic.
460-
461460
// Test vector: 20-byte P2PKH payload
462461
const TEST_HASH_20: &str = "F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9";
463462

@@ -474,7 +473,7 @@ mod tests {
474473
// Test roundtrip
475474
let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "bitcoincash").unwrap();
476475
assert_eq!(decoded_hash, hash);
477-
assert_eq!(is_p2sh, false);
476+
assert!(!is_p2sh);
478477
}
479478

480479
#[test]
@@ -490,7 +489,7 @@ mod tests {
490489
// Test roundtrip
491490
let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "bchtest").unwrap();
492491
assert_eq!(decoded_hash, hash);
493-
assert_eq!(is_p2sh, true);
492+
assert!(is_p2sh);
494493
}
495494

496495
#[test]
@@ -503,7 +502,7 @@ mod tests {
503502
// Test roundtrip
504503
let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "pref").unwrap();
505504
assert_eq!(decoded_hash, hash);
506-
assert_eq!(is_p2sh, true);
505+
assert!(is_p2sh);
507506
}
508507

509508
#[test]
@@ -585,7 +584,7 @@ mod tests {
585584
let (hash, is_p2sh) = decode_cashaddr(uppercase, "bitcoincash").unwrap();
586585

587586
assert_eq!(hex::encode(hash).to_uppercase(), TEST_HASH_20);
588-
assert_eq!(is_p2sh, false);
587+
assert!(!is_p2sh);
589588
}
590589

591590
#[test]
@@ -628,7 +627,7 @@ mod tests {
628627
// Test roundtrip
629628
let (decoded_hash, is_p2sh) = decode_cashaddr(&address, "ecash").unwrap();
630629
assert_eq!(decoded_hash, hash);
631-
assert_eq!(is_p2sh, false);
630+
assert!(!is_p2sh);
632631
}
633632

634633
#[test]

packages/wasm-utxo/src/descriptor.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::error::WasmMiniscriptError;
22
use crate::try_into_js_value::TryIntoJsValue;
3-
use miniscript::bitcoin::secp256k1::{Context, Secp256k1, Signing};
3+
use miniscript::bitcoin::secp256k1::{Secp256k1, Signing};
44
use miniscript::bitcoin::ScriptBuf;
55
use miniscript::descriptor::KeyMap;
66
use miniscript::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
7+
use std::fmt;
78
use std::str::FromStr;
89
use wasm_bindgen::prelude::*;
910

@@ -27,12 +28,9 @@ impl WrapDescriptor {
2728
}
2829

2930
#[wasm_bindgen(js_name = toString)]
31+
#[allow(clippy::inherent_to_string_shadow_display)]
3032
pub fn to_string(&self) -> String {
31-
match &self.0 {
32-
WrapDescriptorEnum::Derivable(desc, _) => desc.to_string(),
33-
WrapDescriptorEnum::Definite(desc) => desc.to_string(),
34-
WrapDescriptorEnum::String(desc) => desc.to_string(),
35-
}
33+
format!("{}", self)
3634
}
3735

3836
#[wasm_bindgen(js_name = hasWildcard)]
@@ -115,7 +113,7 @@ impl WrapDescriptor {
115113
secp: &Secp256k1<C>,
116114
descriptor: &str,
117115
) -> Result<WrapDescriptor, WasmMiniscriptError> {
118-
let (desc, keys) = Descriptor::parse_descriptor(&secp, descriptor)?;
116+
let (desc, keys) = Descriptor::parse_descriptor(secp, descriptor)?;
119117
Ok(WrapDescriptor(WrapDescriptorEnum::Derivable(desc, keys)))
120118
}
121119

@@ -199,6 +197,16 @@ impl WrapDescriptor {
199197
}
200198
}
201199

200+
impl fmt::Display for WrapDescriptor {
201+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202+
match &self.0 {
203+
WrapDescriptorEnum::Derivable(desc, _) => write!(f, "{}", desc),
204+
WrapDescriptorEnum::Definite(desc) => write!(f, "{}", desc),
205+
WrapDescriptorEnum::String(desc) => write!(f, "{}", desc),
206+
}
207+
}
208+
}
209+
202210
impl FromStr for WrapDescriptor {
203211
type Err = WasmMiniscriptError;
204212
fn from_str(s: &str) -> Result<Self, Self::Err> {
@@ -217,15 +225,12 @@ mod tests {
217225
)
218226
.unwrap();
219227

220-
assert_eq!(desc.has_wildcard(), false);
221-
assert_eq!(
222-
match desc {
223-
WrapDescriptor {
224-
0: crate::descriptor::WrapDescriptorEnum::Definite(_),
225-
} => true,
226-
_ => false,
227-
},
228-
true
229-
);
228+
assert!(!desc.has_wildcard());
229+
assert!(matches!(
230+
desc,
231+
WrapDescriptor {
232+
0: crate::descriptor::WrapDescriptorEnum::Definite(_),
233+
}
234+
));
230235
}
231236
}

packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checkmultisig.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub fn build_multisig_script_2_of_3(keys: &PubTriple) -> ScriptBuf {
99
let total_count = 3;
1010
let mut builder = Builder::default().push_int(quorum as i64);
1111
for key in keys {
12-
builder = builder.push_slice(&key.to_bytes())
12+
builder = builder.push_slice(key.to_bytes())
1313
}
1414
builder
1515
.push_int(total_count as i64)
@@ -51,21 +51,21 @@ pub fn parse_multisig_script_2_of_3(script: &ScriptBuf) -> Result<PubTriple, Str
5151

5252
// Extract the three public keys
5353
let mut keys = Vec::new();
54-
for i in 1..4 {
55-
match &instructions[i] {
54+
for (idx, instruction) in instructions.iter().enumerate().skip(1).take(3) {
55+
match instruction {
5656
Instruction::PushBytes(bytes) => {
5757
let key = CompressedPublicKey::from_slice(bytes.as_bytes()).map_err(|e| {
5858
format!(
5959
"Failed to parse compressed public key at position {}: {}",
60-
i, e
60+
idx, e
6161
)
6262
})?;
6363
keys.push(key);
6464
}
6565
_ => {
6666
return Err(format!(
6767
"Instruction at position {} should be a push bytes instruction",
68-
i
68+
idx
6969
));
7070
}
7171
}
@@ -150,7 +150,7 @@ mod tests {
150150
// Test script with wrong number of instructions
151151
let script = Builder::new()
152152
.push_opcode(OP_PUSHNUM_2)
153-
.push_slice(&[0x02; 33]) // Only one key instead of three
153+
.push_slice([0x02; 33]) // Only one key instead of three
154154
.push_opcode(OP_PUSHNUM_3)
155155
.push_opcode(OP_CHECKMULTISIG)
156156
.into_script();
@@ -173,9 +173,9 @@ mod tests {
173173
// Build script with wrong quorum (OP_1 instead of OP_2)
174174
let script = Builder::new()
175175
.push_opcode(OP_PUSHNUM_1)
176-
.push_slice(&pub_triple[0].to_bytes())
177-
.push_slice(&pub_triple[1].to_bytes())
178-
.push_slice(&pub_triple[2].to_bytes())
176+
.push_slice(pub_triple[0].to_bytes())
177+
.push_slice(pub_triple[1].to_bytes())
178+
.push_slice(pub_triple[2].to_bytes())
179179
.push_opcode(OP_PUSHNUM_3)
180180
.push_opcode(OP_CHECKMULTISIG)
181181
.into_script();
@@ -198,9 +198,9 @@ mod tests {
198198
// Build script with wrong total (OP_4 instead of OP_3)
199199
let script = Builder::new()
200200
.push_opcode(OP_PUSHNUM_2)
201-
.push_slice(&pub_triple[0].to_bytes())
202-
.push_slice(&pub_triple[1].to_bytes())
203-
.push_slice(&pub_triple[2].to_bytes())
201+
.push_slice(pub_triple[0].to_bytes())
202+
.push_slice(pub_triple[1].to_bytes())
203+
.push_slice(pub_triple[2].to_bytes())
204204
.push_opcode(OP_PUSHNUM_4)
205205
.push_opcode(OP_CHECKMULTISIG)
206206
.into_script();
@@ -223,9 +223,9 @@ mod tests {
223223
// Build script without OP_CHECKMULTISIG
224224
let script = Builder::new()
225225
.push_opcode(OP_PUSHNUM_2)
226-
.push_slice(&pub_triple[0].to_bytes())
227-
.push_slice(&pub_triple[1].to_bytes())
228-
.push_slice(&pub_triple[2].to_bytes())
226+
.push_slice(pub_triple[0].to_bytes())
227+
.push_slice(pub_triple[1].to_bytes())
228+
.push_slice(pub_triple[2].to_bytes())
229229
.push_opcode(OP_PUSHNUM_3)
230230
.push_opcode(OP_PUSHNUM_1) // Wrong opcode instead of OP_CHECKMULTISIG
231231
.into_script();
@@ -242,9 +242,9 @@ mod tests {
242242
// Build script with invalid public key data
243243
let script = Builder::new()
244244
.push_opcode(OP_PUSHNUM_2)
245-
.push_slice(&[0x00; 10]) // Invalid public key (too short)
246-
.push_slice(&[0x02; 33]) // Valid compressed pubkey format
247-
.push_slice(&[0x03; 33]) // Valid compressed pubkey format
245+
.push_slice([0x00; 10]) // Invalid public key (too short)
246+
.push_slice([0x02; 33]) // Valid compressed pubkey format
247+
.push_slice([0x03; 33]) // Valid compressed pubkey format
248248
.push_opcode(OP_PUSHNUM_3)
249249
.push_opcode(OP_CHECKMULTISIG)
250250
.into_script();
@@ -262,8 +262,8 @@ mod tests {
262262
let script = Builder::new()
263263
.push_opcode(OP_PUSHNUM_2)
264264
.push_opcode(OP_PUSHNUM_1) // Wrong: should be pubkey bytes
265-
.push_slice(&[0x02; 33])
266-
.push_slice(&[0x03; 33])
265+
.push_slice([0x02; 33])
266+
.push_slice([0x03; 33])
267267
.push_opcode(OP_PUSHNUM_3)
268268
.push_opcode(OP_CHECKMULTISIG)
269269
.into_script();

packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/checksigverify.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn build_p2tr_ns_script(keys: &[CompressedPublicKey]) -> ScriptBuf {
2020
for (i, key) in keys.iter().enumerate() {
2121
// convert to xonly key
2222
let key_bytes = to_xonly_pubkey(*key);
23-
builder = builder.push_slice(&key_bytes);
23+
builder = builder.push_slice(key_bytes);
2424
if i == keys.len() - 1 {
2525
builder = builder.push_opcode(OP_CHECKSIG);
2626
} else {
@@ -89,11 +89,11 @@ impl ScriptP2tr {
8989

9090
pub fn output_script(&self) -> ScriptBuf {
9191
let output_key = self.spend_info.output_key().to_inner();
92-
let output_script = Builder::new()
92+
93+
Builder::new()
9394
.push_int(1)
9495
.push_slice(output_key.serialize())
95-
.into_script();
96-
output_script
96+
.into_script()
9797
}
9898
}
9999

packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ impl std::fmt::Display for WalletScripts {
3939
f,
4040
"{}",
4141
match self {
42-
WalletScripts::P2sh(_) => format!("P2sh"),
43-
WalletScripts::P2shP2wsh(_) => format!("P2shP2wsh"),
44-
WalletScripts::P2wsh(_) => format!("P2wsh"),
45-
WalletScripts::P2trLegacy(_) => format!("P2trLegacy"),
46-
WalletScripts::P2trMusig2(_) => format!("P2trMusig2"),
42+
WalletScripts::P2sh(_) => "P2sh".to_string(),
43+
WalletScripts::P2shP2wsh(_) => "P2shP2wsh".to_string(),
44+
WalletScripts::P2wsh(_) => "P2wsh".to_string(),
45+
WalletScripts::P2trLegacy(_) => "P2trLegacy".to_string(),
46+
WalletScripts::P2trMusig2(_) => "P2trMusig2".to_string(),
4747
}
4848
)
4949
}
@@ -165,7 +165,7 @@ pub fn derive_xpubs_with_path(
165165
) -> XpubTriple {
166166
let derived = xpubs
167167
.iter()
168-
.map(|k| k.derive_pub(&ctx, &p).unwrap())
168+
.map(|k| k.derive_pub(ctx, &p).unwrap())
169169
.collect::<Vec<_>>();
170170
derived.try_into().expect("could not convert vec to array")
171171
}
@@ -182,7 +182,7 @@ pub fn derive_xpubs(
182182
index: chain as u32,
183183
})
184184
.child(ChildNumber::Normal { index });
185-
derive_xpubs_with_path(&xpubs, ctx, p)
185+
derive_xpubs_with_path(xpubs, ctx, p)
186186
}
187187

188188
#[cfg(test)]
@@ -383,14 +383,14 @@ mod tests {
383383
.expect("Failed to find input with script type");
384384

385385
let (chain, index) =
386-
parse_fixture_paths(&input_fixture).expect("Failed to parse fixture paths");
386+
parse_fixture_paths(input_fixture).expect("Failed to parse fixture paths");
387387
let scripts = WalletScripts::from_xpubs(&xpubs, chain, index);
388388

389389
// Use the new helper methods for validation
390390
match (scripts, input_fixture) {
391391
(WalletScripts::P2sh(scripts), fixtures::PsbtInputFixture::P2sh(fixture_input)) => {
392392
let vout = fixture.inputs[input_index].index as usize;
393-
let output_script = get_output_script_from_non_witness_utxo(&fixture_input, vout);
393+
let output_script = get_output_script_from_non_witness_utxo(fixture_input, vout);
394394
fixture_input
395395
.assert_matches_wallet_scripts(&scripts, &output_script)
396396
.expect("P2sh validation failed");

packages/wasm-utxo/src/fixed_script_wallet/wallet_scripts/singlesig.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::bitcoin::{CompressedPublicKey, ScriptBuf};
77
/// Build bare p2pk script (used for p2sh-p2pk replay protection)
88
pub fn build_p2pk_script(key: CompressedPublicKey) -> ScriptBuf {
99
Builder::default()
10-
.push_slice(&key.to_bytes())
10+
.push_slice(key.to_bytes())
1111
.push_opcode(OP_CHECKSIG)
1212
.into_script()
1313
}
@@ -58,7 +58,7 @@ mod tests {
5858
let expected_redeem_script = &p2shp2pk_input.redeem_script;
5959
let expected_pubkey = p2shp2pk_input
6060
.partial_sig
61-
.get(0)
61+
.first()
6262
.map(|sig| &sig.pubkey)
6363
.expect("No partial signature found");
6464

packages/wasm-utxo/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod try_into_js_value;
1212
pub use ::miniscript::bitcoin;
1313

1414
pub use address::utxolib_compat;
15+
pub use address::*;
1516
pub use descriptor::WrapDescriptor;
1617
pub use miniscript::WrapMiniscript;
1718
pub use psbt::WrapPsbt;

packages/wasm-utxo/src/miniscript.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::error::WasmMiniscriptError;
22
use crate::try_into_js_value::TryIntoJsValue;
33
use miniscript::bitcoin::{PublicKey, XOnlyPublicKey};
44
use miniscript::{bitcoin, Legacy, Miniscript, Segwitv0, Tap};
5+
use std::fmt;
56
use std::str::FromStr;
67
use wasm_bindgen::prelude::wasm_bindgen;
78
use wasm_bindgen::JsValue;
@@ -35,8 +36,9 @@ impl WrapMiniscript {
3536
}
3637

3738
#[wasm_bindgen(js_name = toString)]
39+
#[allow(clippy::inherent_to_string_shadow_display)]
3840
pub fn to_string(&self) -> String {
39-
unwrap_apply!(&self.0, |ms| ms.to_string())
41+
format!("{}", self)
4042
}
4143

4244
#[wasm_bindgen(js_name = encode)]
@@ -112,3 +114,9 @@ impl From<Miniscript<PublicKey, Legacy>> for WrapMiniscript {
112114
WrapMiniscript(WrapMiniscriptEnum::Legacy(miniscript))
113115
}
114116
}
117+
118+
impl fmt::Display for WrapMiniscript {
119+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120+
unwrap_apply!(&self.0, |ms| write!(f, "{}", ms))
121+
}
122+
}

0 commit comments

Comments
 (0)