Skip to content

Commit 1a2a49a

Browse files
committed
Merge #371: Clean up trait MiniscriptKey
3092830 Simplify to_pubkeyhash (Tobin C. Harding) d495945 Improve docs on is_uncompressed (Tobin C. Harding) 47fc2c6 Remove re-implementation of default method (Tobin C. Harding) d1da214 Add regression tests for MiniscriptKey impls (Tobin C. Harding) 0e3635f Improve docs on trait MiniscriptKey (Tobin C. Harding) Pull request description: Improve the code around trait `MiniscriptKey` by doing - Improve docs - Add regression tests - Refactor the trait ACKs for top commit: sanket1729: ACK 3092830. Thank you again for the clean changes Tree-SHA512: a449544f16459b21f368dcd7e1cefaf7e4e2794347c66e486ecb3b73fc4e3b26fc44c86311a9dbc2bc8185fb3fae31e1c82a214b41bfb3d1c5bb4c4a9fea09f9
2 parents 43075d8 + 3092830 commit 1a2a49a

File tree

1 file changed

+62
-23
lines changed

1 file changed

+62
-23
lines changed

src/lib.rs

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ pub mod psbt;
116116

117117
mod util;
118118

119-
use std::io::Write;
120119
use std::str::FromStr;
121120
use std::{error, fmt, hash, str};
122121

@@ -134,58 +133,43 @@ pub use descriptor::pretaproot::{traits::PreTaprootDescriptorTrait, PreTaprootDe
134133

135134
///Public key trait which can be converted to Hash type
136135
pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
137-
/// Check if the publicKey is uncompressed. The default
138-
/// implementation returns false
136+
/// Returns true if the pubkey is uncompressed. Defaults to `false`.
139137
fn is_uncompressed(&self) -> bool {
140138
false
141139
}
142140

143-
/// Check if the publicKey is x-only. The default
144-
/// implementation returns false
145-
//
141+
/// Returns true if the pubkey is an x-only pubkey. Defaults to `false`.
146142
// This is required to know what in DescriptorPublicKey to know whether the inner
147143
// key in allowed in descriptor context
148144
fn is_x_only_key(&self) -> bool {
149145
false
150146
}
151147

152-
/// The associated Hash type with the publicKey
148+
/// The associated [`Hash`] type for this pubkey.
153149
type Hash: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
154150

155-
/// Converts an object to PublicHash
151+
/// Converts this key to the associated pubkey hash.
156152
fn to_pubkeyhash(&self) -> Self::Hash;
157153
}
158154

159155
impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
160-
/// `is_uncompressed` always returns `false`
161-
fn is_uncompressed(&self) -> bool {
162-
false
163-
}
164-
165156
type Hash = hash160::Hash;
166157

167158
fn to_pubkeyhash(&self) -> Self::Hash {
168-
let mut engine = hash160::Hash::engine();
169-
engine
170-
.write_all(&self.serialize())
171-
.expect("engines don't error");
172-
hash160::Hash::from_engine(engine)
159+
hash160::Hash::hash(&self.serialize())
173160
}
174161
}
175162

176163
impl MiniscriptKey for bitcoin::PublicKey {
177-
/// `is_uncompressed` returns true only for
178-
/// bitcoin::Publickey type if the underlying key is uncompressed.
164+
/// Returns the compressed-ness of the underlying secp256k1 key.
179165
fn is_uncompressed(&self) -> bool {
180166
!self.compressed
181167
}
182168

183169
type Hash = hash160::Hash;
184170

185171
fn to_pubkeyhash(&self) -> Self::Hash {
186-
let mut engine = hash160::Hash::engine();
187-
self.write_into(&mut engine).expect("engines don't error");
188-
hash160::Hash::from_engine(engine)
172+
hash160::Hash::hash(&self.to_bytes())
189173
}
190174
}
191175

@@ -794,3 +778,58 @@ fn hex_script(s: &str) -> bitcoin::Script {
794778
let v: Vec<u8> = bitcoin::hashes::hex::FromHex::from_hex(s).unwrap();
795779
bitcoin::Script::from(v)
796780
}
781+
782+
#[cfg(test)]
783+
mod tests {
784+
use super::*;
785+
786+
#[test]
787+
fn regression_bitcoin_key_hash() {
788+
use bitcoin::PublicKey;
789+
790+
// Uncompressed key.
791+
let pk = PublicKey::from_str(
792+
"042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"
793+
).unwrap();
794+
795+
let want = hash160::Hash::from_str("ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a").unwrap();
796+
let got = pk.to_pubkeyhash();
797+
assert_eq!(got, want)
798+
}
799+
800+
#[test]
801+
fn regression_secp256k1_key_hash() {
802+
use bitcoin::secp256k1::PublicKey;
803+
804+
// Compressed key.
805+
let pk = PublicKey::from_str(
806+
"032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
807+
)
808+
.unwrap();
809+
810+
let want = hash160::Hash::from_str("9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4").unwrap();
811+
let got = pk.to_pubkeyhash();
812+
assert_eq!(got, want)
813+
}
814+
815+
#[test]
816+
fn regression_xonly_key_hash() {
817+
use bitcoin::secp256k1::XOnlyPublicKey;
818+
819+
let pk = XOnlyPublicKey::from_str(
820+
"cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
821+
)
822+
.unwrap();
823+
824+
let want = hash160::Hash::from_str("eb8ac65f971ae688a94aeabf223506865e7e08f2").unwrap();
825+
let got = pk.to_pubkeyhash();
826+
assert_eq!(got, want)
827+
}
828+
829+
#[test]
830+
fn regression_string_key_hash() {
831+
let pk = String::from("some-key-hash-string");
832+
let hash = pk.to_pubkeyhash();
833+
assert_eq!(hash, pk)
834+
}
835+
}

0 commit comments

Comments
 (0)