Skip to content

Commit 5d36f9b

Browse files
committed
Add Hash256 associated type
1 parent e22b081 commit 5d36f9b

20 files changed

+214
-90
lines changed

examples/taproot.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bitcoin::util::address::WitnessVersion;
66
use bitcoin::Network;
77
use miniscript::descriptor::DescriptorType;
88
use miniscript::policy::Concrete;
9-
use miniscript::{Descriptor, Miniscript, Tap, TranslatePk, Translator};
9+
use miniscript::{hash256, Descriptor, Miniscript, Tap, TranslatePk, Translator};
1010
use secp256k1::{rand, KeyPair};
1111

1212
// Refer to https://github.com/sanket1729/adv_btc_workshop/blob/master/workshop.md#creating-a-taproot-descriptor
@@ -28,6 +28,10 @@ impl Translator<String, bitcoin::XOnlyPublicKey, ()> for StrPkTranslator {
2828
fn sha256(&mut self, _sha256: &String) -> Result<sha256::Hash, ()> {
2929
unreachable!("Policy does not contain any sha256 fragment");
3030
}
31+
32+
fn hash256(&mut self, _sha256: &String) -> Result<hash256::Hash, ()> {
33+
unreachable!("Policy does not contain any hash256 fragment");
34+
}
3135
}
3236

3337
fn main() {

src/descriptor/key.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use bitcoin::util::bip32;
1010
use bitcoin::{self, XOnlyPublicKey, XpubIdentifier};
1111

1212
use crate::prelude::*;
13-
use crate::{MiniscriptKey, ToPublicKey};
13+
use crate::{hash256, MiniscriptKey, ToPublicKey};
1414

1515
/// The descriptor pubkey, either a single pubkey or an xpub.
1616
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
@@ -737,7 +737,8 @@ impl<K: InnerXKey> DescriptorXKey<K> {
737737
impl MiniscriptKey for DescriptorPublicKey {
738738
// This allows us to be able to derive public keys even for PkH s
739739
type Hash = Self;
740-
type Sha256 = bitcoin::hashes::sha256::Hash;
740+
type Sha256 = sha256::Hash;
741+
type Hash256 = hash256::Hash;
741742

742743
fn is_uncompressed(&self) -> bool {
743744
match self {
@@ -803,7 +804,8 @@ impl fmt::Display for DerivedDescriptorKey {
803804
impl MiniscriptKey for DerivedDescriptorKey {
804805
// This allows us to be able to derive public keys even for PkH s
805806
type Hash = Self;
806-
type Sha256 = bitcoin::hashes::sha256::Hash;
807+
type Sha256 = sha256::Hash;
808+
type Hash256 = hash256::Hash;
807809

808810
fn is_uncompressed(&self) -> bool {
809811
self.key.is_uncompressed()
@@ -831,6 +833,10 @@ impl ToPublicKey for DerivedDescriptorKey {
831833
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
832834
*hash
833835
}
836+
837+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
838+
*hash
839+
}
834840
}
835841

836842
#[cfg(test)]

src/descriptor/mod.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ use self::checksum::verify_checksum;
3737
use crate::miniscript::{Legacy, Miniscript, Segwitv0};
3838
use crate::prelude::*;
3939
use crate::{
40-
expression, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, PkTranslator, Satisfier,
41-
ToPublicKey, TranslatePk, Translator,
40+
expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, PkTranslator,
41+
Satisfier, ToPublicKey, TranslatePk, Translator,
4242
};
4343

4444
mod bare;
@@ -646,6 +646,12 @@ impl Descriptor<DescriptorPublicKey> {
646646
sha256::Hash::from_str(sha256).map_err(|e| Error::Unexpected(e.to_string()))?;
647647
Ok(hash)
648648
}
649+
650+
fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, Error> {
651+
let hash = hash256::Hash::from_str(hash256)
652+
.map_err(|e| Error::Unexpected(e.to_string()))?;
653+
Ok(hash)
654+
}
649655
}
650656

651657
let descriptor = Descriptor::<String>::from_str(s)?;
@@ -672,6 +678,10 @@ impl Descriptor<DescriptorPublicKey> {
672678
fn sha256(&mut self, sha256: &sha256::Hash) -> Result<String, ()> {
673679
Ok(sha256.to_string())
674680
}
681+
682+
fn hash256(&mut self, hash256: &hash256::Hash) -> Result<String, ()> {
683+
Ok(hash256.to_string())
684+
}
675685
}
676686

677687
fn key_to_string(pk: &DescriptorPublicKey, key_map: &KeyMap) -> Result<String, ()> {

src/interpreter/mod.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ use core::fmt;
2323
use core::str::FromStr;
2424

2525
use bitcoin::blockdata::witness::Witness;
26-
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d};
26+
use bitcoin::hashes::{hash160, ripemd160, sha256};
2727
use bitcoin::util::{sighash, taproot};
2828
use bitcoin::{self, secp256k1, TxOut};
2929

3030
use crate::miniscript::context::NoChecks;
3131
use crate::miniscript::ScriptContext;
3232
use crate::prelude::*;
33-
use crate::{Descriptor, Miniscript, Terminal, ToPublicKey};
33+
use crate::{hash256, Descriptor, Miniscript, Terminal, ToPublicKey};
3434

3535
mod error;
3636
mod inner;
@@ -149,7 +149,8 @@ impl TypedHash160 {
149149

150150
impl MiniscriptKey for BitcoinKey {
151151
type Hash = TypedHash160;
152-
type Sha256 = bitcoin::hashes::sha256::Hash;
152+
type Sha256 = sha256::Hash;
153+
type Hash256 = hash256::Hash;
153154

154155
fn to_pubkeyhash(&self) -> Self::Hash {
155156
match self {
@@ -454,7 +455,7 @@ pub enum HashLockType {
454455
///SHA 256 hashlock
455456
Sha256(sha256::Hash),
456457
///Hash 256 hashlock
457-
Hash256(sha256d::Hash),
458+
Hash256(hash256::Hash),
458459
///Hash160 hashlock
459460
Hash160(hash160::Hash),
460461
///Ripemd160 hashlock
@@ -1040,7 +1041,7 @@ fn verify_sersig<'txin>(
10401041
mod tests {
10411042

10421043
use bitcoin;
1043-
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
1044+
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
10441045
use bitcoin::secp256k1::{self, Secp256k1};
10451046

10461047
use super::inner::ToNoChecks;
@@ -1156,11 +1157,8 @@ mod tests {
11561157
let preimage = [0xab as u8; 32];
11571158
let sha256_hash = sha256::Hash::hash(&preimage);
11581159
let sha256 = no_checks_ms(&format!("sha256({})", sha256_hash));
1159-
let sha256d_hash_rev = sha256d::Hash::hash(&preimage);
1160-
let mut sha256d_hash_bytes = sha256d_hash_rev.clone().into_inner();
1161-
sha256d_hash_bytes.reverse();
1162-
let sha256d_hash = sha256d::Hash::from_inner(sha256d_hash_bytes);
1163-
let hash256 = no_checks_ms(&format!("hash256({})", sha256d_hash));
1160+
let hash256_hash = hash256::Hash::hash(&preimage);
1161+
let hash256 = no_checks_ms(&format!("hash256({})", hash256_hash));
11641162
let hash160_hash = hash160::Hash::hash(&preimage);
11651163
let hash160 = no_checks_ms(&format!("hash160({})", hash160_hash));
11661164
let ripemd160_hash = ripemd160::Hash::hash(&preimage);
@@ -1242,7 +1240,7 @@ mod tests {
12421240
assert_eq!(
12431241
sha256d_satisfied.unwrap(),
12441242
vec![SatisfiedConstraint::HashLock {
1245-
hash: HashLockType::Hash256(sha256d_hash_rev),
1243+
hash: HashLockType::Hash256(hash256_hash),
12461244
preimage: preimage,
12471245
}]
12481246
);

src/interpreter/stack.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
1717
use bitcoin;
1818
use bitcoin::blockdata::{opcodes, script};
19-
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
19+
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
2020

2121
use super::error::PkEvalErrInner;
2222
use super::{
2323
verify_sersig, BitcoinKey, Error, HashLockType, KeySigPair, SatisfiedConstraint, TypedHash160,
2424
};
25+
use crate::hash256;
2526
use crate::prelude::*;
2627

2728
/// Definition of Stack Element of the Stack used for interpretation of Miniscript.
@@ -288,13 +289,13 @@ impl<'txin> Stack<'txin> {
288289
/// `SIZE 32 EQUALVERIFY HASH256 h EQUAL`
289290
pub(super) fn evaluate_hash256(
290291
&mut self,
291-
hash: &sha256d::Hash,
292+
hash: &hash256::Hash,
292293
) -> Option<Result<SatisfiedConstraint, Error>> {
293294
if let Some(Element::Push(preimage)) = self.pop() {
294295
if preimage.len() != 32 {
295296
return Some(Err(Error::HashPreimageLengthMismatch));
296297
}
297-
if sha256d::Hash::hash(preimage) == *hash {
298+
if hash256::Hash::hash(preimage) == *hash {
298299
self.push(Element::Satisfied);
299300
Some(Ok(SatisfiedConstraint::HashLock {
300301
hash: HashLockType::Hash256(*hash),

src/lib.rs

+70-7
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,26 @@ pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Ha
152152
false
153153
}
154154

155-
/// The associated [`Hash`] type for this pubkey.
155+
/// The associated PublicKey Hash for this [`MiniscriptKey`],
156+
/// used in the pkh fragment
156157
type Hash: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
157158

158-
/// The associated [`sha256::Hash`] type for this [`MiniscriptKey`] type.
159-
/// Used in the sha256 fragment
159+
/// The associated [`sha256::Hash`] for this [`MiniscriptKey`],
160+
/// used in the hash256 fragment.
160161
type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
161162

163+
/// The associated [`hash256::Hash`] for this [`MiniscriptKey`],
164+
/// used in the hash256 fragment.
165+
type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
166+
162167
/// Converts this key to the associated pubkey hash.
163168
fn to_pubkeyhash(&self) -> Self::Hash;
164169
}
165170

166171
impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
167172
type Hash = hash160::Hash;
168173
type Sha256 = sha256::Hash;
174+
type Hash256 = hash256::Hash;
169175

170176
fn to_pubkeyhash(&self) -> Self::Hash {
171177
hash160::Hash::hash(&self.serialize())
@@ -180,6 +186,7 @@ impl MiniscriptKey for bitcoin::PublicKey {
180186

181187
type Hash = hash160::Hash;
182188
type Sha256 = sha256::Hash;
189+
type Hash256 = hash256::Hash;
183190

184191
fn to_pubkeyhash(&self) -> Self::Hash {
185192
hash160::Hash::hash(&self.to_bytes())
@@ -189,6 +196,7 @@ impl MiniscriptKey for bitcoin::PublicKey {
189196
impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
190197
type Hash = hash160::Hash;
191198
type Sha256 = sha256::Hash;
199+
type Hash256 = hash256::Hash;
192200

193201
fn to_pubkeyhash(&self) -> Self::Hash {
194202
hash160::Hash::hash(&self.serialize())
@@ -202,6 +210,7 @@ impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
202210
impl MiniscriptKey for String {
203211
type Hash = String;
204212
type Sha256 = String; // specify hashes as string
213+
type Hash256 = String;
205214

206215
fn to_pubkeyhash(&self) -> Self::Hash {
207216
(&self).to_string()
@@ -229,6 +238,9 @@ pub trait ToPublicKey: MiniscriptKey {
229238

230239
/// Converts the generic associated [`MiniscriptKey::Sha256`] to [`sha256::Hash`]
231240
fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;
241+
242+
/// Converts the generic associated [`MiniscriptKey::Hash256`] to [`hash256::Hash`]
243+
fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;
232244
}
233245

234246
impl ToPublicKey for bitcoin::PublicKey {
@@ -243,6 +255,10 @@ impl ToPublicKey for bitcoin::PublicKey {
243255
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
244256
*hash
245257
}
258+
259+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
260+
*hash
261+
}
246262
}
247263

248264
impl ToPublicKey for bitcoin::secp256k1::PublicKey {
@@ -257,6 +273,10 @@ impl ToPublicKey for bitcoin::secp256k1::PublicKey {
257273
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
258274
*hash
259275
}
276+
277+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
278+
*hash
279+
}
260280
}
261281

262282
impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
@@ -280,6 +300,10 @@ impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
280300
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
281301
*hash
282302
}
303+
304+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
305+
*hash
306+
}
283307
}
284308

285309
/// Dummy key which de/serializes to the empty string; useful sometimes for testing
@@ -300,6 +324,7 @@ impl str::FromStr for DummyKey {
300324
impl MiniscriptKey for DummyKey {
301325
type Hash = DummyKeyHash;
302326
type Sha256 = DummySha256Hash;
327+
type Hash256 = DummyHash256;
303328

304329
fn to_pubkeyhash(&self) -> Self::Hash {
305330
DummyKeyHash
@@ -334,6 +359,11 @@ impl ToPublicKey for DummyKey {
334359
sha256::Hash::from_str("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352")
335360
.unwrap()
336361
}
362+
363+
fn to_hash256(_hash: &DummyHash256) -> hash256::Hash {
364+
hash256::Hash::from_str("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352")
365+
.unwrap()
366+
}
337367
}
338368

339369
/// Dummy keyhash which de/serializes to the empty string; useful sometimes for testing
@@ -390,8 +420,34 @@ impl hash::Hash for DummySha256Hash {
390420
}
391421
}
392422

393-
/// Describes an object that can translate various keys and hashes from one key to the type
394-
/// associated with the other key. Used by the [`TranslatePk`] trait to do the actual translations.
423+
/// Dummy keyhash which de/serializes to the empty string; useful for testing
424+
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
425+
pub struct DummyHash256;
426+
427+
impl str::FromStr for DummyHash256 {
428+
type Err = &'static str;
429+
fn from_str(x: &str) -> Result<DummyHash256, &'static str> {
430+
if x.is_empty() {
431+
Ok(DummyHash256)
432+
} else {
433+
Err("non empty dummy hash")
434+
}
435+
}
436+
}
437+
438+
impl fmt::Display for DummyHash256 {
439+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
440+
f.write_str("")
441+
}
442+
}
443+
444+
impl hash::Hash for DummyHash256 {
445+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
446+
"DummySha256Hash".hash(state);
447+
}
448+
}
449+
450+
/// Provides the conversion information required in [`TranslatePk`]
395451
pub trait Translator<P, Q, E>
396452
where
397453
P: MiniscriptKey,
@@ -403,8 +459,11 @@ where
403459
/// Translates public key hashes P::Hash -> Q::Hash.
404460
fn pkh(&mut self, pkh: &P::Hash) -> Result<Q::Hash, E>;
405461

406-
/// Translates sha256 hashes from P::Sha256 -> Q::Sha256
462+
/// Provides the translation from P::Sha256 -> Q::Sha256
407463
fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
464+
465+
/// Provides the translation from P::Hash256 -> Q::Hash256
466+
fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
408467
}
409468

410469
/// Provides the conversion information required in [`TranslatePk`].
@@ -426,7 +485,7 @@ impl<P, Q, E, T> Translator<P, Q, E> for T
426485
where
427486
T: PkTranslator<P, Q, E>,
428487
P: MiniscriptKey,
429-
Q: MiniscriptKey<Sha256 = P::Sha256>,
488+
Q: MiniscriptKey<Sha256 = P::Sha256, Hash256 = P::Hash256>,
430489
{
431490
fn pk(&mut self, pk: &P) -> Result<Q, E> {
432491
<Self as PkTranslator<P, Q, E>>::pk(self, pk)
@@ -439,6 +498,10 @@ where
439498
fn sha256(&mut self, sha256: &<P as MiniscriptKey>::Sha256) -> Result<<Q>::Sha256, E> {
440499
Ok(sha256.clone())
441500
}
501+
502+
fn hash256(&mut self, hash256: &<P as MiniscriptKey>::Hash256) -> Result<<Q>::Hash256, E> {
503+
Ok(hash256.clone())
504+
}
442505
}
443506

444507
/// Converts a descriptor using abstract keys to one using specific keys. Uses translator `t` to do

0 commit comments

Comments
 (0)