Skip to content

Commit f9f3e56

Browse files
committed
Add Hash256 associated type
1 parent 4871d15 commit f9f3e56

File tree

19 files changed

+208
-89
lines changed

19 files changed

+208
-89
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: 70 additions & 7 deletions
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 hash256 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)