miniscript_debug/miniscript/
hash256.rs

1// Miniscript
2// Written in 2022 by
3//     Sanket Kanjalkar <sanket1729@gmail.com>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! Hash256 type
16//!
17//! This module is _identical_ in functionality to the `bitcoin_hashes::sha256d` hash type
18//! but the `FromHex/FromStr` and `ToHex/Display` implementations use `DISPLAY_BACKWARDS = false`.
19//!
20use core::ops::Index;
21use core::slice::SliceIndex;
22use core::str;
23
24use bitcoin::hashes::{
25    self, borrow_slice_impl, hex, hex_fmt_impl, serde_impl, sha256, Hash as HashTrait,
26};
27
28/// Output of the SHA256d hash function
29#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
30#[repr(transparent)]
31pub struct Hash([u8; 32]);
32
33hex_fmt_impl!(Debug, Hash);
34hex_fmt_impl!(Display, Hash);
35hex_fmt_impl!(LowerHex, Hash);
36serde_impl!(Hash, 32);
37borrow_slice_impl!(Hash);
38
39impl<I: SliceIndex<[u8]>> Index<I> for Hash {
40    type Output = I::Output;
41
42    #[inline]
43    fn index(&self, index: I) -> &Self::Output {
44        &self.0[index]
45    }
46}
47
48impl str::FromStr for Hash {
49    type Err = hex::Error;
50    fn from_str(s: &str) -> Result<Self, Self::Err> {
51        hex::FromHex::from_hex(s)
52    }
53}
54
55impl HashTrait for Hash {
56    type Engine = sha256::HashEngine;
57    type Inner = [u8; 32];
58
59    fn engine() -> sha256::HashEngine {
60        sha256::Hash::engine()
61    }
62
63    fn from_engine(e: sha256::HashEngine) -> Hash {
64        let sha2 = sha256::Hash::from_engine(e);
65        let sha2d = sha256::Hash::hash(&sha2[..]);
66
67        let mut ret = [0; 32];
68        ret.copy_from_slice(&sha2d[..]);
69        Hash(ret)
70    }
71
72    const LEN: usize = 32;
73
74    fn from_slice(sl: &[u8]) -> Result<Hash, hashes::Error> {
75        if sl.len() != 32 {
76            Err(hashes::Error::InvalidLength(Self::LEN, sl.len()))
77        } else {
78            let mut ret = [0; 32];
79            ret.copy_from_slice(sl);
80            Ok(Hash(ret))
81        }
82    }
83
84    /// sha256d has DISPLAY_BACKWARD as true
85    const DISPLAY_BACKWARD: bool = false;
86
87    fn into_inner(self) -> Self::Inner {
88        self.0
89    }
90
91    fn as_inner(&self) -> &Self::Inner {
92        &self.0
93    }
94
95    fn from_inner(inner: Self::Inner) -> Self {
96        Hash(inner)
97    }
98
99    fn all_zeros() -> Self {
100        Self([0u8; 32])
101    }
102}