@@ -116,7 +116,6 @@ pub mod psbt;
116
116
117
117
mod util;
118
118
119
- use std:: io:: Write ;
120
119
use std:: str:: FromStr ;
121
120
use std:: { error, fmt, hash, str} ;
122
121
@@ -134,58 +133,43 @@ pub use descriptor::pretaproot::{traits::PreTaprootDescriptorTrait, PreTaprootDe
134
133
135
134
///Public key trait which can be converted to Hash type
136
135
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`.
139
137
fn is_uncompressed ( & self ) -> bool {
140
138
false
141
139
}
142
140
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`.
146
142
// This is required to know what in DescriptorPublicKey to know whether the inner
147
143
// key in allowed in descriptor context
148
144
fn is_x_only_key ( & self ) -> bool {
149
145
false
150
146
}
151
147
152
- /// The associated Hash type with the publicKey
148
+ /// The associated [` Hash`] type for this pubkey.
153
149
type Hash : Clone + Eq + Ord + fmt:: Display + fmt:: Debug + hash:: Hash ;
154
150
155
- /// Converts an object to PublicHash
151
+ /// Converts this key to the associated pubkey hash.
156
152
fn to_pubkeyhash ( & self ) -> Self :: Hash ;
157
153
}
158
154
159
155
impl MiniscriptKey for bitcoin:: secp256k1:: PublicKey {
160
- /// `is_uncompressed` always returns `false`
161
- fn is_uncompressed ( & self ) -> bool {
162
- false
163
- }
164
-
165
156
type Hash = hash160:: Hash ;
166
157
167
158
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 ( ) )
173
160
}
174
161
}
175
162
176
163
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.
179
165
fn is_uncompressed ( & self ) -> bool {
180
166
!self . compressed
181
167
}
182
168
183
169
type Hash = hash160:: Hash ;
184
170
185
171
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 ( ) )
189
173
}
190
174
}
191
175
@@ -794,3 +778,58 @@ fn hex_script(s: &str) -> bitcoin::Script {
794
778
let v: Vec < u8 > = bitcoin:: hashes:: hex:: FromHex :: from_hex ( s) . unwrap ( ) ;
795
779
bitcoin:: Script :: from ( v)
796
780
}
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