Skip to content

Commit b9896ec

Browse files
tchardingoleonardolima
authored andcommitted
refactor(keymap): create KeyMap type
- creates a new `key_map` module, and `KeyMap` type to replace the existing `BTreeMap` alias. - it's a commit extracted from superseded PR rust-bitcoin#765.
1 parent 2ca5a35 commit b9896ec

File tree

3 files changed

+97
-28
lines changed

3 files changed

+97
-28
lines changed

src/descriptor/key_map.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-License-Identifier: CC0-1.0
2+
3+
//! A map of public key to secret key.
4+
5+
use core::iter;
6+
7+
use bitcoin::secp256k1::{Secp256k1, Signing};
8+
9+
#[cfg(doc)]
10+
use super::Descriptor;
11+
use super::{DescriptorKeyParseError, DescriptorPublicKey, DescriptorSecretKey};
12+
use crate::prelude::{btree_map, BTreeMap};
13+
14+
/// Alias type for a map of public key to secret key.
15+
///
16+
/// This map is returned whenever a descriptor that contains secrets is parsed using
17+
/// [`Descriptor::parse_descriptor`], since the descriptor will always only contain
18+
/// public keys. This map allows looking up the corresponding secret key given a
19+
/// public key from the descriptor.
20+
#[derive(Debug, Clone, Eq, PartialEq)]
21+
pub struct KeyMap {
22+
map: BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
23+
}
24+
25+
impl KeyMap {
26+
/// Creates a new empty `KeyMap`.
27+
#[inline]
28+
pub fn new() -> Self { Self { map: BTreeMap::new() } }
29+
30+
/// Inserts secret key into key map returning the associated public key.
31+
#[inline]
32+
pub fn insert<C: Signing>(
33+
&mut self,
34+
secp: &Secp256k1<C>,
35+
sk: DescriptorSecretKey,
36+
) -> Result<DescriptorPublicKey, DescriptorKeyParseError> {
37+
let pk = sk.to_public(secp)?;
38+
if !self.map.contains_key(&pk) {
39+
self.map.insert(pk.clone(), sk);
40+
}
41+
Ok(pk)
42+
}
43+
44+
/// Gets the secret key associated with `pk` if `pk` is in the map.
45+
#[inline]
46+
pub fn get(&self, pk: &DescriptorPublicKey) -> Option<&DescriptorSecretKey> { self.map.get(pk) }
47+
48+
/// Returns the number of items in this map.
49+
#[inline]
50+
pub fn len(&self) -> usize { self.map.len() }
51+
52+
/// Returns true if the map is empty.
53+
#[inline]
54+
pub fn is_empty(&self) -> bool { self.map.is_empty() }
55+
}
56+
57+
impl Default for KeyMap {
58+
fn default() -> Self { Self::new() }
59+
}
60+
61+
impl IntoIterator for KeyMap {
62+
type Item = (DescriptorPublicKey, DescriptorSecretKey);
63+
type IntoIter = btree_map::IntoIter<DescriptorPublicKey, DescriptorSecretKey>;
64+
65+
#[inline]
66+
fn into_iter(self) -> Self::IntoIter { self.map.into_iter() }
67+
}
68+
69+
impl iter::Extend<(DescriptorPublicKey, DescriptorSecretKey)> for KeyMap {
70+
#[inline]
71+
fn extend<T>(&mut self, iter: T)
72+
where
73+
T: IntoIterator<Item = (DescriptorPublicKey, DescriptorSecretKey)>,
74+
{
75+
self.map.extend(iter)
76+
}
77+
}

src/descriptor/mod.rs

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,14 @@ pub use self::tr::{
5151

5252
pub mod checksum;
5353
mod key;
54+
mod key_map;
5455

5556
pub use self::key::{
5657
DefiniteDescriptorKey, DerivPaths, DescriptorKeyParseError, DescriptorMultiXKey,
5758
DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, InnerXKey, MalformedKeyDataKind,
5859
NonDefiniteKeyError, SinglePriv, SinglePub, SinglePubKey, Wildcard, XKeyNetwork,
5960
};
60-
61-
/// Alias type for a map of public key to secret key
62-
///
63-
/// This map is returned whenever a descriptor that contains secrets is parsed using
64-
/// [`Descriptor::parse_descriptor`], since the descriptor will always only contain
65-
/// public keys. This map allows looking up the corresponding secret key given a
66-
/// public key from the descriptor.
67-
pub type KeyMap = BTreeMap<DescriptorPublicKey, DescriptorSecretKey>;
61+
pub use self::key_map::KeyMap;
6862

6963
/// Script descriptor
7064
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -725,28 +719,24 @@ impl Descriptor<DescriptorPublicKey> {
725719
key_map: &mut KeyMap,
726720
secp: &secp256k1::Secp256k1<C>,
727721
) -> Result<DescriptorPublicKey, Error> {
728-
let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
729-
Ok(sk) => (
730-
sk.to_public(secp)
731-
.map_err(|e| Error::Unexpected(e.to_string()))?,
732-
Some(sk),
733-
),
734-
Err(_) => (
722+
match DescriptorSecretKey::from_str(s) {
723+
Ok(sk) => {
724+
let pk = key_map
725+
.insert(secp, sk)
726+
.map_err(|e| Error::Unexpected(e.to_string()))?;
727+
Ok(pk)
728+
}
729+
Err(_) => {
735730
// try to parse as a public key if parsing as a secret key failed
736-
s.parse()
737-
.map_err(|e| Error::Parse(ParseError::box_from_str(e)))?,
738-
None,
739-
),
740-
};
741-
742-
if let Some(secret_key) = secret_key {
743-
key_map.insert(public_key.clone(), secret_key);
731+
let pk = s
732+
.parse()
733+
.map_err(|e| Error::Parse(ParseError::box_from_str(e)))?;
734+
Ok(pk)
735+
}
744736
}
745-
746-
Ok(public_key)
747737
}
748738

749-
let mut keymap_pk = KeyMapWrapper(BTreeMap::new(), secp);
739+
let mut keymap_pk = KeyMapWrapper(KeyMap::new(), secp);
750740

751741
struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
752742

src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ mod prelude {
777777
pub use alloc::{
778778
borrow::{Borrow, Cow, ToOwned},
779779
boxed::Box,
780-
collections::{vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap},
780+
collections::{btree_map, vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap},
781781
rc, slice,
782782
string::{String, ToString},
783783
sync,
@@ -787,7 +787,9 @@ mod prelude {
787787
pub use std::{
788788
borrow::{Borrow, Cow, ToOwned},
789789
boxed::Box,
790-
collections::{vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet},
790+
collections::{
791+
btree_map, vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet,
792+
},
791793
rc, slice,
792794
string::{String, ToString},
793795
sync,

0 commit comments

Comments
 (0)