1use crate::sha256;
6
7crate::internal_macros::general_hash_type! {
8 256,
9 true,
10 "Output of the SHA256d hash function."
11}
12
13impl Hash {
14 pub fn from_engine(e: HashEngine) -> Self {
16 let sha2 = sha256::Hash::from_engine(e.0);
17 let sha2d = sha256::Hash::hash(sha2.as_byte_array());
18
19 let mut ret = [0; 32];
20 ret.copy_from_slice(sha2d.as_byte_array());
21 Self(ret)
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct HashEngine(sha256::HashEngine);
28
29impl HashEngine {
30 pub const fn new() -> Self { Self(sha256::HashEngine::new()) }
32}
33
34impl Default for HashEngine {
35 fn default() -> Self { Self::new() }
36}
37
38impl crate::HashEngine for HashEngine {
39 type Hash = Hash;
40 type Bytes = [u8; 32];
41 const BLOCK_SIZE: usize = 64; fn input(&mut self, data: &[u8]) { self.0.input(data) }
44 fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() }
45 fn finalize(self) -> Self::Hash { Hash::from_engine(self) }
46}
47
48#[cfg(test)]
49mod tests {
50 #[allow(unused_imports)] use crate::sha256d;
52
53 #[test]
54 #[cfg(feature = "alloc")]
55 #[cfg(feature = "hex")]
56 fn test() {
57 use alloc::string::ToString;
58
59 use crate::{sha256, HashEngine};
60
61 #[derive(Clone)]
62 struct Test {
63 input: &'static str,
64 output: [u8; 32],
65 output_str: &'static str,
66 }
67
68 #[rustfmt::skip]
69 let tests = [
70 Test {
72 input: "",
73 output: [
74 0x5d, 0xf6, 0xe0, 0xe2, 0x76, 0x13, 0x59, 0xd3,
75 0x0a, 0x82, 0x75, 0x05, 0x8e, 0x29, 0x9f, 0xcc,
76 0x03, 0x81, 0x53, 0x45, 0x45, 0xf5, 0x5c, 0xf4,
77 0x3e, 0x41, 0x98, 0x3f, 0x5d, 0x4c, 0x94, 0x56,
78 ],
79 output_str: "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d",
80 },
81 ];
82
83 for test in tests {
84 let hash = sha256d::Hash::hash(test.input.as_bytes());
86 assert_eq!(hash, test.output_str.parse::<sha256d::Hash>().expect("parse hex"));
87 assert_eq!(hash.as_byte_array(), &test.output);
88 assert_eq!(hash.to_string(), test.output_str);
89
90 let mut engine = sha256d::Hash::engine();
92 for ch in test.input.as_bytes() {
93 engine.input(&[*ch]);
94 }
95 let manual_hash = sha256d::Hash::from_engine(engine);
96 assert_eq!(hash, manual_hash);
97
98 let sha2_hash = sha256::Hash::hash(test.input.as_bytes());
100 let sha2d_hash = sha2_hash.hash_again();
101 assert_eq!(hash, sha2d_hash);
102
103 assert_eq!(hash.to_byte_array(), test.output);
104 }
105 }
106
107 #[test]
108 #[cfg(feature = "alloc")]
109 #[cfg(feature = "hex")]
110 fn fmt_roundtrips() {
111 use alloc::format;
112
113 let hash = sha256d::Hash::hash(b"some arbitrary bytes");
114 let hex = format!("{}", hash);
115 let rinsed = hex.parse::<sha256d::Hash>().expect("failed to parse hex");
116 assert_eq!(rinsed, hash)
117 }
118
119 #[test]
120 #[cfg(feature = "serde")]
121 fn sha256_serde() {
122 use serde_test::{assert_tokens, Configure, Token};
123
124 #[rustfmt::skip]
125 static HASH_BYTES: [u8; 32] = [
126 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
127 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
128 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
129 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
130 ];
131
132 let hash = sha256d::Hash::from_byte_array(HASH_BYTES);
133 assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
134 assert_tokens(
135 &hash.readable(),
136 &[Token::Str("6cfb35868c4465b7c289d7d5641563aa973db6a929655282a7bf95c8257f53ef")],
137 );
138 }
139}