diff --git a/examples/compiler.rs b/examples/compiler.rs index 3b62147c..284aa12e 100644 --- a/examples/compiler.rs +++ b/examples/compiler.rs @@ -97,7 +97,7 @@ fn main() -> Result<(), Box> { let network = matches .value_of("network") - .and_then(|n| Some(Network::from_str(n))) + .map(|n| Network::from_str(n)) .transpose() .unwrap() .unwrap_or(Network::Testnet); diff --git a/scripts/cargo-check.sh b/scripts/cargo-check.sh new file mode 100755 index 00000000..01b94411 --- /dev/null +++ b/scripts/cargo-check.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Run various invocations of cargo check + +features=( "default" "compiler" "electrum" "esplora" "compact_filters" "key-value-db" "async-interface" "all-keys" "keys-bip39" ) +toolchains=( "+stable" "+1.45" "+nightly" ) + +main() { + check_src + check_all_targets +} + +# Check with all features, with various toolchains. +check_src() { + for toolchain in "${toolchains[@]}"; do + cmd="cargo $toolchain clippy --all-targets --no-default-features" + + for feature in "${features[@]}"; do + touch_files + $cmd --features "$feature" + done + done +} + +# Touch files to prevent cached warnings from not showing up. +touch_files() { + touch $(find . -name *.rs) +} + +main +exit 0 diff --git a/src/blockchain/compact_filters/mod.rs b/src/blockchain/compact_filters/mod.rs index 38c4d180..05aa25de 100644 --- a/src/blockchain/compact_filters/mod.rs +++ b/src/blockchain/compact_filters/mod.rs @@ -239,6 +239,7 @@ impl Blockchain for CompactFiltersBlockchain { vec![Capability::FullHistory].into_iter().collect() } + #[allow(clippy::mutex_atomic)] // Mutex is easier to understand than a CAS loop. fn setup( &self, _stop_gap: Option, // TODO: move to electrum and esplora only diff --git a/src/blockchain/compact_filters/store.rs b/src/blockchain/compact_filters/store.rs index 5e278f24..bc81f066 100644 --- a/src/blockchain/compact_filters/store.rs +++ b/src/blockchain/compact_filters/store.rs @@ -46,6 +46,8 @@ use bitcoin::BlockHash; use bitcoin::BlockHeader; use bitcoin::Network; +use lazy_static::lazy_static; + use super::CompactFiltersError; lazy_static! { @@ -119,7 +121,7 @@ where } fn deserialize(data: &[u8]) -> Result { - Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?) + deserialize(data).map_err(|_| CompactFiltersError::DataCorruption) } } @@ -436,15 +438,14 @@ impl ChainStore { let key = StoreEntry::BlockHeaderIndex(Some(*block_hash)).get_key(); let data = read_store.get_pinned_cf(cf_handle, key)?; - Ok(data - .map(|data| { - Ok::<_, CompactFiltersError>(usize::from_be_bytes( - data.as_ref() - .try_into() - .map_err(|_| CompactFiltersError::DataCorruption)?, - )) - }) - .transpose()?) + data.map(|data| { + Ok::<_, CompactFiltersError>(usize::from_be_bytes( + data.as_ref() + .try_into() + .map_err(|_| CompactFiltersError::DataCorruption)?, + )) + }) + .transpose() } pub fn get_block_hash(&self, height: usize) -> Result, CompactFiltersError> { @@ -453,13 +454,12 @@ impl ChainStore { let key = StoreEntry::BlockHeader(Some(height)).get_key(); let data = read_store.get_pinned_cf(cf_handle, key)?; - Ok(data - .map(|data| { - let (header, _): (BlockHeader, Uint256) = - deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?; - Ok::<_, CompactFiltersError>(header.block_hash()) - }) - .transpose()?) + data.map(|data| { + let (header, _): (BlockHeader, Uint256) = + deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?; + Ok::<_, CompactFiltersError>(header.block_hash()) + }) + .transpose() } pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> { @@ -475,10 +475,10 @@ impl ChainStore { let key = StoreEntry::Block(Some(height)).get_key(); let opt_block = read_store.get_pinned(key)?; - Ok(opt_block + opt_block .map(|data| deserialize(&data)) .transpose() - .map_err(|_| CompactFiltersError::DataCorruption)?) + .map_err(|_| CompactFiltersError::DataCorruption) } pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> { @@ -565,14 +565,14 @@ impl ChainStore { let prefix = StoreEntry::BlockHeader(None).get_key(); let iterator = read_store.prefix_iterator_cf(cf_handle, prefix); - Ok(iterator + iterator .last() .map(|(_, v)| -> Result<_, CompactFiltersError> { let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?; Ok(header.block_hash()) }) - .transpose()?) + .transpose() } pub fn apply( @@ -716,11 +716,11 @@ impl CFStore { // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't // have the right prefix - Ok(iterator + iterator .filter(|(k, _)| k.starts_with(&prefix)) .skip(1) .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1)) - .collect::>()?) + .collect::>() } pub fn replace_checkpoints( diff --git a/src/database/any.rs b/src/database/any.rs index a332b8d5..c3e0942f 100644 --- a/src/database/any.rs +++ b/src/database/any.rs @@ -312,24 +312,17 @@ impl BatchDatabase for AnyDatabase { } } fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> { - // TODO: refactor once `move_ref_pattern` is stable - #[allow(irrefutable_let_patterns)] match self { - AnyDatabase::Memory(db) => { - if let AnyBatch::Memory(batch) = batch { - db.commit_batch(batch) - } else { - unimplemented!() - } - } + AnyDatabase::Memory(db) => match batch { + AnyBatch::Memory(batch) => db.commit_batch(batch), + #[cfg(feature = "key-value-db")] + _ => unimplemented!("Sled batch shouldn't be used with Memory db."), + }, #[cfg(feature = "key-value-db")] - AnyDatabase::Sled(db) => { - if let AnyBatch::Sled(batch) = batch { - db.commit_batch(batch) - } else { - unimplemented!() - } - } + AnyDatabase::Sled(db) => match batch { + AnyBatch::Sled(batch) => db.commit_batch(batch), + _ => unimplemented!("Memory batch shouldn't be used with Sled db."), + }, } } } diff --git a/src/database/mod.rs b/src/database/mod.rs index e8face1e..250da587 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -227,7 +227,7 @@ pub mod test { ); assert_eq!( tree.get_path_from_script_pubkey(&script).unwrap(), - Some((keychain, path.clone())) + Some((keychain, path)) ); } @@ -256,7 +256,7 @@ pub mod test { ); assert_eq!( tree.get_path_from_script_pubkey(&script).unwrap(), - Some((keychain, path.clone())) + Some((keychain, path)) ); } diff --git a/src/descriptor/dsl.rs b/src/descriptor/dsl.rs index 37e9a1a4..405be39f 100644 --- a/src/descriptor/dsl.rs +++ b/src/descriptor/dsl.rs @@ -228,10 +228,11 @@ macro_rules! impl_sortedmulti { use $crate::keys::IntoDescriptorKey; let secp = $crate::bitcoin::secp256k1::Secp256k1::new(); - let mut keys = vec![]; - $( - keys.push($key.into_descriptor_key()); - )* + let keys = vec![ + $( + $key.into_descriptor_key(), + )* + ]; keys.into_iter().collect::, _>>() .map_err($crate::descriptor::DescriptorError::Key) @@ -656,10 +657,11 @@ macro_rules! fragment { use $crate::keys::IntoDescriptorKey; let secp = $crate::bitcoin::secp256k1::Secp256k1::new(); - let mut keys = vec![]; - $( - keys.push($key.into_descriptor_key()); - )* + let keys = vec![ + $( + $key.into_descriptor_key(), + )* + ]; keys.into_iter().collect::, _>>() .map_err($crate::descriptor::DescriptorError::Key) @@ -968,7 +970,7 @@ mod test { fn test_valid_networks() { let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap(); - let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap(); + let desc_key = (xprv, path).into_descriptor_key().unwrap(); let (_desc, _key_map, valid_networks) = descriptor!(pkh(desc_key)).unwrap(); assert_eq!( @@ -978,7 +980,7 @@ mod test { let xprv = bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap(); let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap(); - let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap(); + let desc_key = (xprv, path).into_descriptor_key().unwrap(); let (_desc, _key_map, valid_networks) = descriptor!(wpkh(desc_key)).unwrap(); assert_eq!(valid_networks, [Bitcoin].iter().cloned().collect()); @@ -1005,12 +1007,9 @@ mod test { descriptor!(sh(wsh(multi(2, desc_key1, desc_key2, desc_key3)))).unwrap(); assert_eq!(key_map.len(), 3); - let desc_key1: DescriptorKey = - (xprv1, path1.clone()).into_descriptor_key().unwrap(); - let desc_key2: DescriptorKey = - (xprv2, path2.clone()).into_descriptor_key().unwrap(); - let desc_key3: DescriptorKey = - (xprv3, path3.clone()).into_descriptor_key().unwrap(); + let desc_key1: DescriptorKey = (xprv1, path1).into_descriptor_key().unwrap(); + let desc_key2: DescriptorKey = (xprv2, path2).into_descriptor_key().unwrap(); + let desc_key3: DescriptorKey = (xprv3, path3).into_descriptor_key().unwrap(); let (key1, _key_map, _valid_networks) = desc_key1.extract(&secp).unwrap(); let (key2, _key_map, _valid_networks) = desc_key2.extract(&secp).unwrap(); @@ -1026,7 +1025,7 @@ mod test { // this compiles let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let path = bip32::DerivationPath::from_str("m/0").unwrap(); - let desc_key: DescriptorKey = (xprv, path.clone()).into_descriptor_key().unwrap(); + let desc_key: DescriptorKey = (xprv, path).into_descriptor_key().unwrap(); let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap(); assert_eq!(desc.to_string(), "pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)#yrnz9pp2"); diff --git a/src/descriptor/policy.rs b/src/descriptor/policy.rs index 8929e085..7dbfda60 100644 --- a/src/descriptor/policy.rs +++ b/src/descriptor/policy.rs @@ -938,7 +938,7 @@ mod test { .unwrap(); assert!( - matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint) + matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint) ); assert!(matches!(&policy.contribution, Satisfaction::None)); @@ -953,7 +953,7 @@ mod test { .unwrap(); assert!( - matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint) + matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint) ); assert!( matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None) @@ -1039,8 +1039,8 @@ mod test { assert!( matches!(&policy.item, Multisig { keys, threshold } if threshold == &1 - && &keys[0].fingerprint.unwrap() == &fingerprint0 - && &keys[1].fingerprint.unwrap() == &fingerprint1) + && keys[0].fingerprint.unwrap() == fingerprint0 + && keys[1].fingerprint.unwrap() == fingerprint1) ); assert!( matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2 @@ -1071,8 +1071,8 @@ mod test { assert!( matches!(&policy.item, Multisig { keys, threshold } if threshold == &2 - && &keys[0].fingerprint.unwrap() == &fingerprint0 - && &keys[1].fingerprint.unwrap() == &fingerprint1) + && keys[0].fingerprint.unwrap() == fingerprint0 + && keys[1].fingerprint.unwrap() == fingerprint1) ); assert!( @@ -1103,7 +1103,7 @@ mod test { .unwrap(); assert!( - matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint) + matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint) ); assert!(matches!(&policy.contribution, Satisfaction::None)); @@ -1119,7 +1119,7 @@ mod test { .unwrap(); assert!( - matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint) + matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint) ); assert!( matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None) @@ -1147,8 +1147,8 @@ mod test { assert!( matches!(&policy.item, Multisig { keys, threshold } if threshold == &1 - && &keys[0].fingerprint.unwrap() == &fingerprint0 - && &keys[1].fingerprint.unwrap() == &fingerprint1) + && keys[0].fingerprint.unwrap() == fingerprint0 + && keys[1].fingerprint.unwrap() == fingerprint1) ); assert!( matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2 diff --git a/src/descriptor/template.rs b/src/descriptor/template.rs index 14c3aef7..3fdbec89 100644 --- a/src/descriptor/template.rs +++ b/src/descriptor/template.rs @@ -75,7 +75,7 @@ impl IntoWalletDescriptor for T { secp: &SecpCtx, network: Network, ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> { - Ok(self.build()?.into_wallet_descriptor(secp, network)?) + self.build()?.into_wallet_descriptor(secp, network) } } @@ -108,7 +108,7 @@ pub struct P2PKH>(pub K); impl> DescriptorTemplate for P2PKH { fn build(self) -> Result { - Ok(descriptor!(pkh(self.0))?) + descriptor!(pkh(self.0)) } } @@ -142,7 +142,7 @@ pub struct P2WPKH_P2SH>(pub K); impl> DescriptorTemplate for P2WPKH_P2SH { fn build(self) -> Result { - Ok(descriptor!(sh(wpkh(self.0)))?) + descriptor!(sh(wpkh(self.0))) } } @@ -175,7 +175,7 @@ pub struct P2WPKH>(pub K); impl> DescriptorTemplate for P2WPKH { fn build(self) -> Result { - Ok(descriptor!(wpkh(self.0))?) + descriptor!(wpkh(self.0)) } } @@ -210,7 +210,7 @@ pub struct BIP44>(pub K, pub KeychainKind); impl> DescriptorTemplate for BIP44 { fn build(self) -> Result { - Ok(P2PKH(legacy::make_bipxx_private(44, self.0, self.1)?).build()?) + P2PKH(legacy::make_bipxx_private(44, self.0, self.1)?).build() } } @@ -249,7 +249,7 @@ pub struct BIP44Public>(pub K, pub bip32::Fingerprint, p impl> DescriptorTemplate for BIP44Public { fn build(self) -> Result { - Ok(P2PKH(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()?) + P2PKH(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build() } } @@ -284,7 +284,7 @@ pub struct BIP49>(pub K, pub KeychainKind); impl> DescriptorTemplate for BIP49 { fn build(self) -> Result { - Ok(P2WPKH_P2SH(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()?) + P2WPKH_P2SH(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build() } } @@ -323,7 +323,7 @@ pub struct BIP49Public>(pub K, pub bip32::Fingerprint, impl> DescriptorTemplate for BIP49Public { fn build(self) -> Result { - Ok(P2WPKH_P2SH(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()?) + P2WPKH_P2SH(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build() } } @@ -358,7 +358,7 @@ pub struct BIP84>(pub K, pub KeychainKind); impl> DescriptorTemplate for BIP84 { fn build(self) -> Result { - Ok(P2WPKH(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()?) + P2WPKH(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build() } } @@ -397,7 +397,7 @@ pub struct BIP84Public>(pub K, pub bip32::Fingerprint, impl> DescriptorTemplate for BIP84Public { fn build(self) -> Result { - Ok(P2WPKH(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()?) + P2WPKH(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build() } } @@ -440,11 +440,11 @@ macro_rules! expand_make_bipxx { KeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(), }; - let mut source_path = Vec::with_capacity(3); - source_path.push(bip32::ChildNumber::from_hardened_idx(bip)?); - source_path.push(bip32::ChildNumber::from_hardened_idx(0)?); - source_path.push(bip32::ChildNumber::from_hardened_idx(0)?); - let source_path: bip32::DerivationPath = source_path.into(); + let source_path = bip32::DerivationPath::from(vec![ + bip32::ChildNumber::from_hardened_idx(bip)?, + bip32::ChildNumber::from_hardened_idx(0)?, + bip32::ChildNumber::from_hardened_idx(0)?, + ]); Ok((key, (parent_fingerprint, source_path), derivation_path)) } diff --git a/src/keys/mod.rs b/src/keys/mod.rs index 0ce5d128..6edb419c 100644 --- a/src/keys/mod.rs +++ b/src/keys/mod.rs @@ -733,7 +733,7 @@ fn expand_multi_keys, Ctx: ScriptContext>( ) -> Result<(Vec, KeyMap, ValidNetworks), KeyError> { let (pks, key_maps_networks): (Vec<_>, Vec<_>) = pks .into_iter() - .map(|key| Ok::<_, KeyError>(key.into_descriptor_key()?.extract(secp)?)) + .map(|key| key.into_descriptor_key()?.extract(secp)) .collect::, _>>()? .into_iter() .map(|(a, b, c)| (a, (b, c))) diff --git a/src/lib.rs b/src/lib.rs index df6cf7c6..c8af648e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -225,7 +225,6 @@ extern crate async_trait; extern crate bdk_macros; #[cfg(feature = "compact_filters")] -#[macro_use] extern crate lazy_static; #[cfg(feature = "electrum")] diff --git a/src/wallet/coin_selection.rs b/src/wallet/coin_selection.rs index f0b0bb7a..3e16eaa2 100644 --- a/src/wallet/coin_selection.rs +++ b/src/wallet/coin_selection.rs @@ -815,7 +815,7 @@ mod test { .coin_select( &database, vec![], - utxos.clone(), + utxos, FeeRate::from_sat_per_vb(1.0), 99932, // first utxo's effective value 0.0, diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 58a706d1..07a98b81 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -1970,7 +1970,7 @@ mod test { assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1); assert_eq!( - psbt.inputs[0].bip32_derivation.values().nth(0).unwrap(), + psbt.inputs[0].bip32_derivation.values().next().unwrap(), &( Fingerprint::from_str("d34db33f").unwrap(), DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap() @@ -1996,7 +1996,7 @@ mod test { assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1); assert_eq!( - psbt.outputs[0].bip32_derivation.values().nth(0).unwrap(), + psbt.outputs[0].bip32_derivation.values().next().unwrap(), &( Fingerprint::from_str("d34db33f").unwrap(), DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap() @@ -3429,15 +3429,18 @@ mod test { let (mut psbt, _) = builder.finish().unwrap(); // add another input to the psbt that is at least passable. - let mut dud_input = bitcoin::util::psbt::Input::default(); - dud_input.witness_utxo = Some(TxOut { - value: 100_000, - script_pubkey: miniscript::Descriptor::::from_str( - "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)", - ) - .unwrap() - .script_pubkey(), - }); + let dud_input = bitcoin::util::psbt::Input { + witness_utxo: Some(TxOut { + value: 100_000, + script_pubkey: miniscript::Descriptor::::from_str( + "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)", + ) + .unwrap() + .script_pubkey(), + }), + ..Default::default() + }; + psbt.inputs.push(dud_input); psbt.global.unsigned_tx.input.push(bitcoin::TxIn::default()); let (psbt, is_final) = wallet.sign(psbt, None).unwrap(); diff --git a/src/wallet/signer.rs b/src/wallet/signer.rs index 83888f50..eebafa58 100644 --- a/src/wallet/signer.rs +++ b/src/wallet/signer.rs @@ -569,6 +569,11 @@ mod signers_container_tests { use miniscript::ScriptContext; use std::str::FromStr; + fn is_equal(this: &Arc, that: &Arc) -> bool { + let secp = Secp256k1::new(); + this.id(&secp) == that.id(&secp) + } + // Signers added with the same ordering (like `Ordering::default`) created from `KeyMap` // should be preserved and not overwritten. // This happens usually when a set of signers is created from a descriptor with private keys. @@ -593,73 +598,58 @@ mod signers_container_tests { #[test] fn signers_sorted_by_ordering() { let mut signers = SignersContainer::new(); - let signer1 = Arc::new(DummySigner); - let signer2 = Arc::new(DummySigner); - let signer3 = Arc::new(DummySigner); + let signer1 = Arc::new(DummySigner { number: 1 }); + let signer2 = Arc::new(DummySigner { number: 2 }); + let signer3 = Arc::new(DummySigner { number: 3 }); - signers.add_external( - SignerId::Fingerprint(b"cafe"[..].into()), - SignerOrdering(1), - signer1.clone(), - ); - signers.add_external( - SignerId::Fingerprint(b"babe"[..].into()), - SignerOrdering(2), - signer2.clone(), - ); - signers.add_external( - SignerId::Fingerprint(b"feed"[..].into()), - SignerOrdering(3), - signer3.clone(), - ); + // Mixed order insertions verifies we are not inserting at head or tail. + signers.add_external(SignerId::Dummy(2), SignerOrdering(2), signer2.clone()); + signers.add_external(SignerId::Dummy(1), SignerOrdering(1), signer1.clone()); + signers.add_external(SignerId::Dummy(3), SignerOrdering(3), signer3.clone()); // Check that signers are sorted from lowest to highest ordering let signers = signers.signers(); - assert_eq!(Arc::as_ptr(signers[0]), Arc::as_ptr(&signer1)); - assert_eq!(Arc::as_ptr(signers[1]), Arc::as_ptr(&signer2)); - assert_eq!(Arc::as_ptr(signers[2]), Arc::as_ptr(&signer3)); + + assert!(is_equal(signers[0], &signer1)); + assert!(is_equal(signers[1], &signer2)); + assert!(is_equal(signers[2], &signer3)); } #[test] fn find_signer_by_id() { let mut signers = SignersContainer::new(); - let signer1: Arc = Arc::new(DummySigner); - let signer2: Arc = Arc::new(DummySigner); - let signer3: Arc = Arc::new(DummySigner); - let signer4: Arc = Arc::new(DummySigner); + let signer1 = Arc::new(DummySigner { number: 1 }); + let signer2 = Arc::new(DummySigner { number: 2 }); + let signer3 = Arc::new(DummySigner { number: 3 }); + let signer4 = Arc::new(DummySigner { number: 3 }); // Same ID as `signer3` but will use lower ordering. - let id1 = SignerId::Fingerprint(b"cafe"[..].into()); - let id2 = SignerId::Fingerprint(b"babe"[..].into()); - let id3 = SignerId::Fingerprint(b"feed"[..].into()); - let id_nonexistent = SignerId::Fingerprint(b"fefe"[..].into()); + let id1 = SignerId::Dummy(1); + let id2 = SignerId::Dummy(2); + let id3 = SignerId::Dummy(3); + let id_nonexistent = SignerId::Dummy(999); signers.add_external(id1.clone(), SignerOrdering(1), signer1.clone()); signers.add_external(id2.clone(), SignerOrdering(2), signer2.clone()); signers.add_external(id3.clone(), SignerOrdering(3), signer3.clone()); - assert!( - matches!(signers.find(id1), Some(signer) if Arc::as_ptr(&signer1) == Arc::as_ptr(signer)) - ); - assert!( - matches!(signers.find(id2), Some(signer) if Arc::as_ptr(&signer2) == Arc::as_ptr(signer)) - ); - assert!( - matches!(signers.find(id3.clone()), Some(signer) if Arc::as_ptr(&signer3) == Arc::as_ptr(signer)) - ); + assert!(matches!(signers.find(id1), Some(signer) if is_equal(signer, &signer1))); + assert!(matches!(signers.find(id2), Some(signer) if is_equal(signer, &signer2))); + assert!(matches!(signers.find(id3.clone()), Some(signer) if is_equal(signer, &signer3))); // The `signer4` has the same ID as `signer3` but lower ordering. // It should be found by `id3` instead of `signer3`. signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone()); - assert!( - matches!(signers.find(id3), Some(signer) if Arc::as_ptr(&signer4) == Arc::as_ptr(signer)) - ); + assert!(matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4))); // Can't find anything with ID that doesn't exist assert!(matches!(signers.find(id_nonexistent), None)); } - #[derive(Debug)] - struct DummySigner; + #[derive(Debug, Clone, Copy)] + struct DummySigner { + number: u64, + } + impl Signer for DummySigner { fn sign( &self, @@ -671,7 +661,7 @@ mod signers_container_tests { } fn id(&self, _secp: &SecpCtx) -> SignerId { - SignerId::Dummy(42) + SignerId::Dummy(self.number) } fn sign_whole_tx(&self) -> bool { diff --git a/src/wallet/tx_builder.rs b/src/wallet/tx_builder.rs index 04f11139..5560f5d1 100644 --- a/src/wallet/tx_builder.rs +++ b/src/wallet/tx_builder.rs @@ -721,12 +721,12 @@ impl ChangeSpendPolicy { #[cfg(test)] mod test { - const ORDERING_TEST_TX: &'static str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\ - 85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\ - 79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\ - dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\ - 03e80300000000000002aaeee80300000000000001aa200300000000000001ff\ - 00000000"; + const ORDERING_TEST_TX: &str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\ + 85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\ + 79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\ + dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\ + 03e80300000000000002aaeee80300000000000001aa200300000000000001ff\ + 00000000"; macro_rules! ordering_test_tx { () => { deserialize::(&Vec::::from_hex(ORDERING_TEST_TX).unwrap()) @@ -770,7 +770,7 @@ mod test { use std::str::FromStr; let original_tx = ordering_test_tx!(); - let mut tx = original_tx.clone(); + let mut tx = original_tx; TxOrdering::BIP69Lexicographic.sort_tx(&mut tx); @@ -828,9 +828,9 @@ mod test { let filtered = get_test_utxos() .into_iter() .filter(|u| change_spend_policy.is_satisfied_by(u)) - .collect::>(); + .count(); - assert_eq!(filtered.len(), 2); + assert_eq!(filtered, 2); } #[test] diff --git a/src/wallet/utils.rs b/src/wallet/utils.rs index a71d09c1..d0065d0e 100644 --- a/src/wallet/utils.rs +++ b/src/wallet/utils.rs @@ -156,8 +156,8 @@ pub struct ChunksIterator { size: usize, } +#[cfg(any(feature = "electrum", feature = "esplora"))] impl ChunksIterator { - #[allow(dead_code)] pub fn new(iter: I, size: usize) -> Self { ChunksIterator { iter, size } } diff --git a/testutils/src/lib.rs b/testutils/src/lib.rs index 15b920c8..3a0e5b63 100644 --- a/testutils/src/lib.rs +++ b/testutils/src/lib.rs @@ -60,13 +60,13 @@ fn get_auth() -> Auth { ), _ => Auth::CookieFile(PathBuf::from( env::var("BDK_RPC_COOKIEFILE") - .unwrap_or("/home/user/.bitcoin/regtest/.cookie".to_string()), + .unwrap_or_else(|_| "/home/user/.bitcoin/regtest/.cookie".to_string()), )), } } pub fn get_electrum_url() -> String { - env::var("BDK_ELECTRUM_URL").unwrap_or("tcp://127.0.0.1:50001".to_string()) + env::var("BDK_ELECTRUM_URL").unwrap_or_else(|_| "tcp://127.0.0.1:50001".to_string()) } pub struct TestClient { @@ -311,8 +311,8 @@ where impl TestClient { pub fn new() -> Self { - let url = env::var("BDK_RPC_URL").unwrap_or("127.0.0.1:18443".to_string()); - let wallet = env::var("BDK_RPC_WALLET").unwrap_or("bdk-test".to_string()); + let url = env::var("BDK_RPC_URL").unwrap_or_else(|_| "127.0.0.1:18443".to_string()); + let wallet = env::var("BDK_RPC_WALLET").unwrap_or_else(|_| "bdk-test".to_string()); let client = RpcClient::new(format!("http://{}/wallet/{}", url, wallet), get_auth()).unwrap(); let electrum = ElectrumClient::new(&get_electrum_url()).unwrap(); @@ -349,7 +349,7 @@ impl TestClient { pub fn receive(&mut self, meta_tx: TestIncomingTx) -> Txid { assert!( - meta_tx.output.len() > 0, + !meta_tx.output.is_empty(), "can't create a transaction with no outputs" );