Skip to content

Commit b9f7a63

Browse files
committed
Add Hash256 associated type
1 parent be1ec04 commit b9f7a63

File tree

19 files changed

+205
-86
lines changed

19 files changed

+205
-86
lines changed

src/descriptor/key.rs

Lines changed: 9 additions & 3 deletions
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

Lines changed: 12 additions & 2 deletions
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, ForEach, ForEachKey, MiniscriptKey, PkTranslator,
41-
Satisfier, ToPublicKey, TranslatePk, Translator,
40+
expression, hash256, miniscript, BareCtx, Error, ForEach, ForEachKey, MiniscriptKey,
41+
PkTranslator, 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

Lines changed: 9 additions & 11 deletions
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
@@ -1030,7 +1031,7 @@ fn verify_sersig<'txin>(
10301031
mod tests {
10311032

10321033
use bitcoin;
1033-
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
1034+
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
10341035
use bitcoin::secp256k1::{self, Secp256k1};
10351036

10361037
use super::inner::ToNoChecks;
@@ -1146,11 +1147,8 @@ mod tests {
11461147
let preimage = [0xab as u8; 32];
11471148
let sha256_hash = sha256::Hash::hash(&preimage);
11481149
let sha256 = no_checks_ms(&format!("sha256({})", sha256_hash));
1149-
let sha256d_hash_rev = sha256d::Hash::hash(&preimage);
1150-
let mut sha256d_hash_bytes = sha256d_hash_rev.clone().into_inner();
1151-
sha256d_hash_bytes.reverse();
1152-
let sha256d_hash = sha256d::Hash::from_inner(sha256d_hash_bytes);
1153-
let hash256 = no_checks_ms(&format!("hash256({})", sha256d_hash));
1150+
let hash256_hash = hash256::Hash::hash(&preimage);
1151+
let hash256 = no_checks_ms(&format!("hash256({})", hash256_hash));
11541152
let hash160_hash = hash160::Hash::hash(&preimage);
11551153
let hash160 = no_checks_ms(&format!("hash160({})", hash160_hash));
11561154
let ripemd160_hash = ripemd160::Hash::hash(&preimage);
@@ -1232,7 +1230,7 @@ mod tests {
12321230
assert_eq!(
12331231
sha256d_satisfied.unwrap(),
12341232
vec![SatisfiedConstraint::HashLock {
1235-
hash: HashLockType::Hash256(sha256d_hash_rev),
1233+
hash: HashLockType::Hash256(hash256_hash),
12361234
preimage: preimage,
12371235
}]
12381236
);

src/interpreter/stack.rs

Lines changed: 4 additions & 3 deletions
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.
@@ -290,13 +291,13 @@ impl<'txin> Stack<'txin> {
290291
/// `SIZE 32 EQUALVERIFY HASH256 h EQUAL`
291292
pub(super) fn evaluate_hash256(
292293
&mut self,
293-
hash: &sha256d::Hash,
294+
hash: &hash256::Hash,
294295
) -> Option<Result<SatisfiedConstraint, Error>> {
295296
if let Some(Element::Push(preimage)) = self.pop() {
296297
if preimage.len() != 32 {
297298
return Some(Err(Error::HashPreimageLengthMismatch));
298299
}
299-
if sha256d::Hash::hash(preimage) == *hash {
300+
if hash256::Hash::hash(preimage) == *hash {
300301
self.push(Element::Satisfied);
301302
Some(Ok(SatisfiedConstraint::HashLock {
302303
hash: HashLockType::Hash256(*hash),

src/lib.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,18 @@ pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Ha
159159
/// Used in the sha256 fragment
160160
type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
161161

162+
/// The associated [`hash256::Hash`] type for this [`MiniscriptKey`] type.
163+
/// Used in the sha256 fragment
164+
type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
165+
162166
/// Converts this key to the associated pubkey hash.
163167
fn to_pubkeyhash(&self) -> Self::Hash;
164168
}
165169

166170
impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
167171
type Hash = hash160::Hash;
168172
type Sha256 = sha256::Hash;
173+
type Hash256 = hash256::Hash;
169174

170175
fn to_pubkeyhash(&self) -> Self::Hash {
171176
hash160::Hash::hash(&self.serialize())
@@ -180,6 +185,7 @@ impl MiniscriptKey for bitcoin::PublicKey {
180185

181186
type Hash = hash160::Hash;
182187
type Sha256 = sha256::Hash;
188+
type Hash256 = hash256::Hash;
183189

184190
fn to_pubkeyhash(&self) -> Self::Hash {
185191
hash160::Hash::hash(&self.to_bytes())
@@ -189,6 +195,7 @@ impl MiniscriptKey for bitcoin::PublicKey {
189195
impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
190196
type Hash = hash160::Hash;
191197
type Sha256 = sha256::Hash;
198+
type Hash256 = hash256::Hash;
192199

193200
fn to_pubkeyhash(&self) -> Self::Hash {
194201
hash160::Hash::hash(&self.serialize())
@@ -202,6 +209,7 @@ impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
202209
impl MiniscriptKey for String {
203210
type Hash = String;
204211
type Sha256 = String; // specify hashes as string
212+
type Hash256 = String;
205213

206214
fn to_pubkeyhash(&self) -> Self::Hash {
207215
(&self).to_string()
@@ -229,6 +237,9 @@ pub trait ToPublicKey: MiniscriptKey {
229237

230238
/// Converts the generic associated [`MiniscriptKey::Sha256`] to [`sha256::Hash`]
231239
fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;
240+
241+
/// Converts the generic associated [`MiniscriptKey::Hash256`] to [`hash256::Hash`]
242+
fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;
232243
}
233244

234245
impl ToPublicKey for bitcoin::PublicKey {
@@ -243,6 +254,10 @@ impl ToPublicKey for bitcoin::PublicKey {
243254
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
244255
*hash
245256
}
257+
258+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
259+
*hash
260+
}
246261
}
247262

248263
impl ToPublicKey for bitcoin::secp256k1::PublicKey {
@@ -257,6 +272,10 @@ impl ToPublicKey for bitcoin::secp256k1::PublicKey {
257272
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
258273
*hash
259274
}
275+
276+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
277+
*hash
278+
}
260279
}
261280

262281
impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
@@ -280,6 +299,10 @@ impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
280299
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
281300
*hash
282301
}
302+
303+
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
304+
*hash
305+
}
283306
}
284307

285308
/// Dummy key which de/serializes to the empty string; useful sometimes for testing
@@ -300,6 +323,7 @@ impl str::FromStr for DummyKey {
300323
impl MiniscriptKey for DummyKey {
301324
type Hash = DummyKeyHash;
302325
type Sha256 = DummySha256Hash;
326+
type Hash256 = DummyHash256;
303327

304328
fn to_pubkeyhash(&self) -> Self::Hash {
305329
DummyKeyHash
@@ -334,6 +358,11 @@ impl ToPublicKey for DummyKey {
334358
sha256::Hash::from_str("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352")
335359
.unwrap()
336360
}
361+
362+
fn to_hash256(_hash: &DummyHash256) -> hash256::Hash {
363+
hash256::Hash::from_str("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352")
364+
.unwrap()
365+
}
337366
}
338367

339368
/// Dummy keyhash which de/serializes to the empty string; useful sometimes for testing
@@ -390,8 +419,34 @@ impl hash::Hash for DummySha256Hash {
390419
}
391420
}
392421

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.
422+
/// Dummy keyhash which de/serializes to the empty string; useful for testing
423+
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
424+
pub struct DummyHash256;
425+
426+
impl str::FromStr for DummyHash256 {
427+
type Err = &'static str;
428+
fn from_str(x: &str) -> Result<DummyHash256, &'static str> {
429+
if x.is_empty() {
430+
Ok(DummyHash256)
431+
} else {
432+
Err("non empty dummy hash")
433+
}
434+
}
435+
}
436+
437+
impl fmt::Display for DummyHash256 {
438+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439+
f.write_str("")
440+
}
441+
}
442+
443+
impl hash::Hash for DummyHash256 {
444+
fn hash<H: hash::Hasher>(&self, state: &mut H) {
445+
"DummySha256Hash".hash(state);
446+
}
447+
}
448+
449+
/// Provides the conversion information required in [`TranslatePk`]
395450
pub trait Translator<P, Q, E>
396451
where
397452
P: MiniscriptKey,
@@ -403,8 +458,11 @@ where
403458
/// Translates public key hashes P::Hash -> Q::Hash.
404459
fn pkh(&mut self, pkh: &P::Hash) -> Result<Q::Hash, E>;
405460

406-
/// Translates sha256 hashes from P::Sha256 -> Q::Sha256
461+
/// Provides the translation from P::Sha256 -> Q::Sha256
407462
fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
463+
464+
/// Provides the translation from P::Hash256 -> Q::Hash256
465+
fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
408466
}
409467

410468
/// Provides the conversion information required in [`TranslatePk`].
@@ -426,7 +484,7 @@ impl<P, Q, E, T> Translator<P, Q, E> for T
426484
where
427485
T: PkTranslator<P, Q, E>,
428486
P: MiniscriptKey,
429-
Q: MiniscriptKey<Sha256 = P::Sha256>,
487+
Q: MiniscriptKey<Sha256 = P::Sha256, Hash256 = P::Hash256>,
430488
{
431489
fn pk(&mut self, pk: &P) -> Result<Q, E> {
432490
<Self as PkTranslator<P, Q, E>>::pk(self, pk)
@@ -439,6 +497,10 @@ where
439497
fn sha256(&mut self, sha256: &<P as MiniscriptKey>::Sha256) -> Result<<Q>::Sha256, E> {
440498
Ok(sha256.clone())
441499
}
500+
501+
fn hash256(&mut self, hash256: &<P as MiniscriptKey>::Hash256) -> Result<<Q>::Hash256, E> {
502+
Ok(hash256.clone())
503+
}
442504
}
443505

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

0 commit comments

Comments
 (0)