bitcoin_cash/
hash.rs

1use crate::{
2    error::Result, BitcoinByteArray, BitcoinDataType, ByteArray, DataType, FixedByteArray,
3    Function, Op,
4};
5
6use serde_derive::{Deserialize, Serialize};
7use sha1::Digest;
8use std::borrow::Cow;
9use std::fmt::{Debug, Display};
10use std::sync::Arc;
11
12pub trait Hashed: Display + Debug + Sized + Eq + PartialEq {
13    fn as_slice(&self) -> &[u8];
14    fn from_slice(hash: &[u8]) -> Result<Self>;
15    fn from_byte_array(hash: ByteArray) -> Result<Self>;
16    fn function() -> Function;
17    fn digest_slice(msg: &[u8]) -> Arc<[u8]>;
18    fn digest(msg: impl Into<ByteArray>) -> Self {
19        let msg = msg.into();
20        let hash = Self::digest_slice(&msg);
21        Self::from_byte_array(msg.apply_function(hash, Self::function()))
22            .expect("Self::digest_slice produced invalid slice")
23    }
24    fn named(self, name: impl Into<Cow<'static, str>>) -> Self;
25    fn from_hex_le(s: &str) -> Result<Self> {
26        Self::from_slice(&hex::decode(s)?.iter().cloned().rev().collect::<Vec<_>>())
27    }
28    fn from_hex_be(s: &str) -> Result<Self> {
29        Self::from_slice(&hex::decode(s)?)
30    }
31    fn from_slice_le(hash_le: &[u8]) -> Result<Self> {
32        Self::from_slice(&hash_le.iter().cloned().rev().collect::<Vec<_>>())
33    }
34    fn to_vec_le(&self) -> Vec<u8> {
35        self.as_slice().iter().cloned().rev().collect()
36    }
37    fn to_hex_le(&self) -> String {
38        hex::encode(self.to_vec_le())
39    }
40    fn to_hex_be(&self) -> String {
41        hex::encode(self.as_slice())
42    }
43    fn as_byte_array(&self) -> &ByteArray;
44    fn into_byte_array(self) -> ByteArray;
45    fn concat(self, other: impl Into<ByteArray>) -> ByteArray {
46        self.into_byte_array().concat(other)
47    }
48}
49
50#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
51pub struct Sha1(FixedByteArray<[u8; 20]>);
52#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
53pub struct Ripemd160(FixedByteArray<[u8; 20]>);
54#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
55pub struct Sha256(FixedByteArray<[u8; 32]>);
56#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
57pub struct Sha256d(FixedByteArray<[u8; 32]>);
58#[derive(Clone, Eq, PartialEq, Default, Hash, Deserialize, Serialize)]
59pub struct Hash160(FixedByteArray<[u8; 20]>);
60
61impl Sha1 {
62    pub fn new(hash: [u8; 20]) -> Self {
63        Sha1(FixedByteArray::new_unnamed(hash))
64    }
65}
66impl Ripemd160 {
67    pub fn new(hash: [u8; 20]) -> Self {
68        Ripemd160(FixedByteArray::new_unnamed(hash))
69    }
70}
71impl Sha256 {
72    pub fn new(hash: [u8; 32]) -> Self {
73        Sha256(FixedByteArray::new_unnamed(hash))
74    }
75}
76impl Sha256d {
77    pub fn new(hash: [u8; 32]) -> Self {
78        Sha256d(FixedByteArray::new_unnamed(hash))
79    }
80}
81impl Hash160 {
82    pub fn new(hash: [u8; 20]) -> Self {
83        Hash160(FixedByteArray::new_unnamed(hash))
84    }
85}
86
87impl Debug for Sha1 {
88    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
89        write!(fmt, "Sha1({})", self.to_hex_le())
90    }
91}
92impl Debug for Ripemd160 {
93    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
94        write!(fmt, "Ripemd160({})", self.to_hex_le())
95    }
96}
97impl Debug for Sha256 {
98    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
99        write!(fmt, "Sha256({})", self.to_hex_le())
100    }
101}
102impl Debug for Sha256d {
103    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
104        write!(fmt, "Sha256d({})", self.to_hex_le())
105    }
106}
107impl Debug for Hash160 {
108    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
109        write!(fmt, "Hash160({})", self.to_hex_le())
110    }
111}
112
113impl Display for Sha1 {
114    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
115        write!(fmt, "{}", self.to_hex_le())
116    }
117}
118impl Display for Ripemd160 {
119    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
120        write!(fmt, "{}", self.to_hex_le())
121    }
122}
123impl Display for Sha256 {
124    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
125        write!(fmt, "{}", self.to_hex_le())
126    }
127}
128impl Display for Sha256d {
129    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
130        write!(fmt, "{}", self.to_hex_le())
131    }
132}
133impl Display for Hash160 {
134    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
135        write!(fmt, "{}", self.to_hex_le())
136    }
137}
138
139impl Hashed for Sha1 {
140    fn function() -> Function {
141        Function::Sha1
142    }
143    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
144        sha1::Sha1::digest(msg).as_slice().into()
145    }
146    fn as_slice(&self) -> &[u8] {
147        self.0.as_ref()
148    }
149    fn from_slice(hash: &[u8]) -> Result<Self> {
150        Ok(Sha1(FixedByteArray::from_slice_unnamed(hash)?))
151    }
152    fn from_byte_array(hash: ByteArray) -> Result<Self> {
153        Ok(Sha1(FixedByteArray::from_byte_array(hash)?))
154    }
155    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
156        Sha1(self.0.named(name))
157    }
158    fn as_byte_array(&self) -> &ByteArray {
159        self.0.as_byte_array()
160    }
161    fn into_byte_array(self) -> ByteArray {
162        self.0.into_byte_array()
163    }
164}
165
166impl Hashed for Ripemd160 {
167    fn function() -> Function {
168        Function::Ripemd160
169    }
170    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
171        ripemd160::Ripemd160::digest(msg).as_slice().into()
172    }
173    fn as_slice(&self) -> &[u8] {
174        self.0.as_ref()
175    }
176    fn from_slice(hash: &[u8]) -> Result<Self> {
177        Ok(Ripemd160(FixedByteArray::from_slice_unnamed(hash)?))
178    }
179    fn from_byte_array(hash: ByteArray) -> Result<Self> {
180        Ok(Ripemd160(FixedByteArray::from_byte_array(hash)?))
181    }
182    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
183        Ripemd160(self.0.named(name))
184    }
185    fn as_byte_array(&self) -> &ByteArray {
186        self.0.as_byte_array()
187    }
188    fn into_byte_array(self) -> ByteArray {
189        self.0.into_byte_array()
190    }
191}
192
193impl Hashed for Sha256 {
194    fn function() -> Function {
195        Function::Sha256
196    }
197    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
198        sha2::Sha256::digest(msg).as_slice().into()
199    }
200    fn as_slice(&self) -> &[u8] {
201        self.0.as_ref()
202    }
203    fn from_slice(hash: &[u8]) -> Result<Self> {
204        Ok(Sha256(FixedByteArray::from_slice_unnamed(hash)?))
205    }
206    fn from_byte_array(hash: ByteArray) -> Result<Self> {
207        Ok(Sha256(FixedByteArray::from_byte_array(hash)?))
208    }
209    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
210        Sha256(self.0.named(name))
211    }
212    fn as_byte_array(&self) -> &ByteArray {
213        self.0.as_byte_array()
214    }
215    fn into_byte_array(self) -> ByteArray {
216        self.0.into_byte_array()
217    }
218}
219
220impl Hashed for Sha256d {
221    fn function() -> Function {
222        Function::Hash256
223    }
224    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
225        sha2::Sha256::digest(sha2::Sha256::digest(msg).as_slice())
226            .as_slice()
227            .into()
228    }
229    fn as_slice(&self) -> &[u8] {
230        self.0.as_ref()
231    }
232    fn from_slice(hash: &[u8]) -> Result<Self> {
233        Ok(Sha256d(FixedByteArray::from_slice_unnamed(hash)?))
234    }
235    fn from_byte_array(hash: ByteArray) -> Result<Self> {
236        Ok(Sha256d(FixedByteArray::from_byte_array(hash)?))
237    }
238    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
239        Sha256d(self.0.named(name))
240    }
241    fn as_byte_array(&self) -> &ByteArray {
242        self.0.as_byte_array()
243    }
244    fn into_byte_array(self) -> ByteArray {
245        self.0.into_byte_array()
246    }
247}
248
249impl Hashed for Hash160 {
250    fn function() -> Function {
251        Function::Hash160
252    }
253    fn digest_slice(msg: &[u8]) -> Arc<[u8]> {
254        ripemd160::Ripemd160::digest(sha2::Sha256::digest(msg).as_slice())
255            .as_slice()
256            .into()
257    }
258    fn as_slice(&self) -> &[u8] {
259        self.0.as_ref()
260    }
261    fn from_slice(hash: &[u8]) -> Result<Self> {
262        Ok(Hash160(FixedByteArray::from_slice_unnamed(hash)?))
263    }
264    fn from_byte_array(hash: ByteArray) -> Result<Self> {
265        Ok(Hash160(FixedByteArray::from_byte_array(hash)?))
266    }
267    fn named(self, name: impl Into<Cow<'static, str>>) -> Self {
268        Hash160(self.0.named(name))
269    }
270    fn as_byte_array(&self) -> &ByteArray {
271        self.0.as_byte_array()
272    }
273    fn into_byte_array(self) -> ByteArray {
274        self.0.into_byte_array()
275    }
276}
277
278impl BitcoinDataType for Sha1 {
279    type Type = BitcoinByteArray;
280    fn to_data(&self) -> Self::Type {
281        BitcoinByteArray(self.as_byte_array().clone())
282    }
283    fn to_pushop(&self) -> Op {
284        self.as_byte_array().clone().into()
285    }
286    fn to_data_type(&self) -> DataType {
287        DataType::ByteArray(Some(self.0.len()))
288    }
289}
290
291impl BitcoinDataType for Ripemd160 {
292    type Type = BitcoinByteArray;
293    fn to_data(&self) -> Self::Type {
294        BitcoinByteArray(self.as_byte_array().clone())
295    }
296    fn to_pushop(&self) -> Op {
297        self.as_byte_array().clone().into()
298    }
299    fn to_data_type(&self) -> DataType {
300        DataType::ByteArray(Some(self.0.len()))
301    }
302}
303
304impl BitcoinDataType for Sha256 {
305    type Type = BitcoinByteArray;
306    fn to_data(&self) -> Self::Type {
307        BitcoinByteArray(self.as_byte_array().clone())
308    }
309    fn to_pushop(&self) -> Op {
310        self.as_byte_array().clone().into()
311    }
312    fn to_data_type(&self) -> DataType {
313        DataType::ByteArray(Some(self.0.len()))
314    }
315}
316
317impl BitcoinDataType for Sha256d {
318    type Type = BitcoinByteArray;
319    fn to_data(&self) -> Self::Type {
320        BitcoinByteArray(self.as_byte_array().clone())
321    }
322    fn to_pushop(&self) -> Op {
323        self.as_byte_array().clone().into()
324    }
325    fn to_data_type(&self) -> DataType {
326        DataType::ByteArray(Some(self.0.len()))
327    }
328}
329
330impl BitcoinDataType for Hash160 {
331    type Type = BitcoinByteArray;
332    fn to_data(&self) -> Self::Type {
333        BitcoinByteArray(self.as_byte_array().clone())
334    }
335    fn to_pushop(&self) -> Op {
336        self.as_byte_array().clone().into()
337    }
338    fn to_data_type(&self) -> DataType {
339        DataType::ByteArray(Some(self.0.len()))
340    }
341}
342
343impl From<Sha1> for ByteArray {
344    fn from(hash: Sha1) -> Self {
345        hash.into_byte_array()
346    }
347}
348impl From<Ripemd160> for ByteArray {
349    fn from(hash: Ripemd160) -> Self {
350        hash.into_byte_array()
351    }
352}
353impl From<Sha256> for ByteArray {
354    fn from(hash: Sha256) -> Self {
355        hash.into_byte_array()
356    }
357}
358impl From<Sha256d> for ByteArray {
359    fn from(hash: Sha256d) -> Self {
360        hash.into_byte_array()
361    }
362}
363impl From<Hash160> for ByteArray {
364    fn from(hash: Hash160) -> Self {
365        hash.into_byte_array()
366    }
367}
368
369#[cfg(test)]
370mod tests {
371    use super::{Hash160, Hashed, Result, Ripemd160, Sha1, Sha256, Sha256d};
372    use crate::error::ErrorKind;
373    use hex_literal::hex;
374
375    #[test]
376    fn test_sha1_slice() -> Result<()> {
377        const EMPTY_SHA1: [u8; 20] = hex!("da39a3ee5e6b4b0d3255bfef95601890afd80709");
378        assert_eq!(Sha1::digest(b"").as_slice(), EMPTY_SHA1);
379        assert_eq!(Sha1::digest(b""), Sha1::from_slice(&EMPTY_SHA1)?);
380        assert_eq!(
381            ErrorKind::InvalidSize(20, 2).to_string(),
382            Sha1::from_slice(&[0, 0]).unwrap_err().kind().to_string(),
383        );
384        Ok(())
385    }
386
387    #[test]
388    fn test_sha1_hex_be() -> Result<()> {
389        const EMPTY_SHA1: &str = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
390        assert_eq!(Sha1::digest(b"").to_hex_be(), EMPTY_SHA1);
391        assert_eq!(Sha1::digest(b""), Sha1::from_hex_be(EMPTY_SHA1)?);
392        Ok(())
393    }
394
395    #[test]
396    fn test_sha1_hex_le() -> Result<()> {
397        const EMPTY_SHA1_LE: &str = "0907d8af90186095efbf55320d4b6b5eeea339da";
398        assert_eq!(Sha1::digest(b"").to_hex_le(), EMPTY_SHA1_LE);
399        assert_eq!(Sha1::digest(b""), Sha1::from_hex_le(EMPTY_SHA1_LE)?);
400        Ok(())
401    }
402
403    #[test]
404    fn test_ripemd160_slice() -> Result<()> {
405        const EMPTY_RIPEMD: [u8; 20] = hex!("9c1185a5c5e9fc54612808977ee8f548b2258d31");
406        assert_eq!(Ripemd160::digest(b"").as_slice(), EMPTY_RIPEMD);
407        assert_eq!(
408            Ripemd160::digest(b""),
409            Ripemd160::from_slice(&EMPTY_RIPEMD)?
410        );
411        assert_eq!(
412            ErrorKind::InvalidSize(20, 2).to_string(),
413            Ripemd160::from_slice(&[0, 0])
414                .unwrap_err()
415                .kind()
416                .to_string(),
417        );
418        Ok(())
419    }
420
421    #[test]
422    fn test_ripemd160_hex_be() -> Result<()> {
423        const EMPTY_RIPEMD: &str = "9c1185a5c5e9fc54612808977ee8f548b2258d31";
424        assert_eq!(Ripemd160::digest(b"").to_hex_be(), EMPTY_RIPEMD);
425        assert_eq!(
426            Ripemd160::digest(b""),
427            Ripemd160::from_hex_be(EMPTY_RIPEMD)?
428        );
429        Ok(())
430    }
431
432    #[test]
433    fn test_ripemd160_hex_le() -> Result<()> {
434        const EMPTY_RIPEMD_LE: &str = "318d25b248f5e87e9708286154fce9c5a585119c";
435        assert_eq!(Ripemd160::digest(b"").to_hex_le(), EMPTY_RIPEMD_LE);
436        assert_eq!(
437            Ripemd160::digest(b""),
438            Ripemd160::from_hex_le(EMPTY_RIPEMD_LE)?
439        );
440        Ok(())
441    }
442
443    #[test]
444    fn test_sha256_slice() -> Result<()> {
445        const EMPTY_SHA256: [u8; 32] =
446            hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
447        assert_eq!(Sha256::digest(b"").as_slice(), EMPTY_SHA256);
448        assert_eq!(Sha256::digest(b""), Sha256::from_slice(&EMPTY_SHA256)?);
449        assert_eq!(
450            ErrorKind::InvalidSize(32, 2).to_string(),
451            Sha256::from_slice(&[0, 0]).unwrap_err().kind().to_string(),
452        );
453        Ok(())
454    }
455
456    #[test]
457    fn test_sha256_hex_be() -> Result<()> {
458        const EMPTY_SHA256: &str =
459            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
460        assert_eq!(Sha256::digest(b"").to_hex_be(), EMPTY_SHA256);
461        assert_eq!(Sha256::digest(b""), Sha256::from_hex_be(EMPTY_SHA256)?);
462        Ok(())
463    }
464
465    #[test]
466    fn test_sha256_hex_le() -> Result<()> {
467        const EMPTY_SHA256_LE: &str =
468            "55b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3";
469        assert_eq!(Sha256::digest(b"").to_hex_le(), EMPTY_SHA256_LE);
470        assert_eq!(Sha256::digest(b""), Sha256::from_hex_le(EMPTY_SHA256_LE)?);
471        Ok(())
472    }
473
474    #[test]
475    fn test_sha256d_slice() -> Result<()> {
476        const EMPTY_SHA256D: [u8; 32] =
477            hex!("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456");
478        assert_eq!(Sha256d::digest(b"").as_slice(), EMPTY_SHA256D);
479        assert_eq!(Sha256d::digest(b""), Sha256d::from_slice(&EMPTY_SHA256D)?);
480        assert_eq!(
481            ErrorKind::InvalidSize(32, 2).to_string(),
482            Sha256d::from_slice(&[0, 0]).unwrap_err().kind().to_string(),
483        );
484        Ok(())
485    }
486
487    #[test]
488    fn test_sha256d_hex_be() -> Result<()> {
489        const EMPTY_SHA256D: &str =
490            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456";
491        assert_eq!(Sha256d::digest(b"").to_hex_be(), EMPTY_SHA256D);
492        assert_eq!(Sha256d::digest(b""), Sha256d::from_hex_be(EMPTY_SHA256D)?);
493        Ok(())
494    }
495
496    #[test]
497    fn test_sha256d_hex_le() -> Result<()> {
498        const EMPTY_SHA256D_LE: &str =
499            "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d";
500        assert_eq!(Sha256d::digest(b"").to_hex_le(), EMPTY_SHA256D_LE);
501        assert_eq!(
502            Sha256d::digest(b""),
503            Sha256d::from_hex_le(EMPTY_SHA256D_LE)?
504        );
505        Ok(())
506    }
507
508    #[test]
509    fn test_hash160_slice() -> Result<()> {
510        const EMPTY_HASH160: [u8; 20] = hex!("b472a266d0bd89c13706a4132ccfb16f7c3b9fcb");
511        assert_eq!(Hash160::digest(b"").as_slice(), EMPTY_HASH160);
512        assert_eq!(Hash160::digest(b""), Hash160::from_slice(&EMPTY_HASH160)?);
513        assert_eq!(
514            ErrorKind::InvalidSize(20, 2).to_string(),
515            Hash160::from_slice(&[0, 0]).unwrap_err().kind().to_string(),
516        );
517        Ok(())
518    }
519
520    #[test]
521    fn test_hash160_hex_be() -> Result<()> {
522        const EMPTY_HASH160: &str = "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb";
523        assert_eq!(Hash160::digest(b"").to_hex_be(), EMPTY_HASH160);
524        assert_eq!(Hash160::digest(b""), Hash160::from_hex_be(EMPTY_HASH160)?);
525        Ok(())
526    }
527
528    #[test]
529    fn test_hash160_hex_le() -> Result<()> {
530        const EMPTY_HASH160_LE: &str = "cb9f3b7c6fb1cf2c13a40637c189bdd066a272b4";
531        assert_eq!(Hash160::digest(b"").to_hex_le(), EMPTY_HASH160_LE);
532        assert_eq!(
533            Hash160::digest(b""),
534            Hash160::from_hex_le(EMPTY_HASH160_LE)?
535        );
536        Ok(())
537    }
538}