diff --git a/src/wallet/signer.rs b/src/wallet/signer.rs index 43cff45a..dde2e1a6 100644 --- a/src/wallet/signer.rs +++ b/src/wallet/signer.rs @@ -91,8 +91,9 @@ //! ``` use std::cmp::Ordering; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::fmt; +use std::ops::Bound::Included; use std::sync::Arc; use bitcoin::blockdata::opcodes; @@ -111,7 +112,7 @@ use crate::descriptor::XKeyUtils; /// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among /// multiple of them -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash)] pub enum SignerId { PkHash(hash160::Hash), Fingerprint(Fingerprint), @@ -295,7 +296,7 @@ impl Signer for PrivateKey { /// The default value is `100`. Signers with an ordering above that will be called later, /// and they will thus see the partial signatures added to the transaction once they get to sign /// themselves. -#[derive(Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)] +#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)] pub struct SignerOrdering(pub usize); impl std::default::Default for SignerOrdering { @@ -304,7 +305,7 @@ impl std::default::Default for SignerOrdering { } } -#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[derive(Debug, Clone)] struct SignersContainerKey { id: SignerId, ordering: SignerOrdering, @@ -321,7 +322,7 @@ impl From<(SignerId, SignerOrdering)> for SignersContainerKey { /// Container for multiple signers #[derive(Debug, Default, Clone)] -pub struct SignersContainer(HashMap>); +pub struct SignersContainer(BTreeMap>); impl SignersContainer { pub fn as_key_map(&self, secp: &SecpCtx) -> KeyMap { @@ -394,18 +395,19 @@ impl SignersContainer { /// Returns the list of signers in the container, sorted by lowest to highest `ordering` pub fn signers(&self) -> Vec<&Arc> { - let mut items = self.0.iter().collect::>(); - items.sort_unstable_by_key(|(key, _)| *key); - items.into_iter().map(|(_, v)| v).collect() + self.0.values().collect() } /// Finds the signer with lowest ordering for a given id in the container. pub fn find(&self, id: SignerId) -> Option<&Arc> { self.0 - .iter() - .filter(|(key, _)| key.id == id) - .min_by(|(k_a, _), (k_b, _)| k_a.cmp(k_b)) + .range(( + Included(&(id.clone(), SignerOrdering(0)).into()), + Included(&(id.clone(), SignerOrdering(usize::MAX)).into()), + )) + .filter(|(k, _)| k.id == id) .map(|(_, v)| v) + .next() } } @@ -521,10 +523,20 @@ impl PartialOrd for SignersContainerKey { impl Ord for SignersContainerKey { fn cmp(&self, other: &Self) -> Ordering { - self.ordering.cmp(&other.ordering) + self.ordering + .cmp(&other.ordering) + .then(self.id.cmp(&other.id)) } } +impl PartialEq for SignersContainerKey { + fn eq(&self, other: &Self) -> bool { + self.id == other.id && self.ordering == other.ordering + } +} + +impl Eq for SignersContainerKey {} + #[cfg(test)] mod signers_container_tests { use super::*;