Skip to main content

mini_bitcoin_script/
hash.rs

1use ripemd::Ripemd160;
2use sha2::{Digest, Sha256};
3
4/// Computes the SHA-256 hash of the input data.
5///
6/// Returns a 32-byte digest. This is the fundamental hash primitive
7/// used throughout Bitcoin for transaction hashing, block hashing,
8/// and as a building block for [`hash160`] and [`hash256`].
9pub fn sha256(data: &[u8]) -> [u8; 32] {
10    let mut hasher = Sha256::new();
11    hasher.update(data);
12    hasher.finalize().into()
13}
14
15/// Computes the RIPEMD-160 hash of the input data.
16///
17/// Returns a 20-byte digest. Used in Bitcoin as the second step
18/// of the [`hash160`] address-derivation hash.
19pub fn ripemd160(data: &[u8]) -> [u8; 20] {
20    let mut hasher = Ripemd160::new();
21    hasher.update(data);
22    hasher.finalize().into()
23}
24
25/// Computes HASH160: RIPEMD-160 of SHA-256.
26///
27/// This is the standard Bitcoin address hash function, used in P2PKH
28/// to derive a 20-byte address from a public key.
29///
30/// `hash160(data) = ripemd160(sha256(data))`
31pub fn hash160(data: &[u8]) -> [u8; 20] {
32    ripemd160(&sha256(data))
33}
34
35/// Computes HASH256: double SHA-256.
36///
37/// This is the standard Bitcoin transaction and block hash function.
38///
39/// `hash256(data) = sha256(sha256(data))`
40pub fn hash256(data: &[u8]) -> [u8; 32] {
41    sha256(&sha256(data))
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use hex_literal::hex;
48
49    #[test]
50    fn sha256_empty() {
51        let result = sha256(b"");
52        assert_eq!(
53            result,
54            hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
55        );
56    }
57
58    #[test]
59    fn ripemd160_empty() {
60        let result = ripemd160(b"");
61        assert_eq!(result, hex!("9c1185a5c5e9fc54612808977ee8f548b2258d31"));
62    }
63
64    #[test]
65    fn hash160_empty() {
66        let result = hash160(b"");
67        assert_eq!(result, hex!("b472a266d0bd89c13706a4132ccfb16f7c3b9fcb"));
68    }
69
70    #[test]
71    fn hash256_empty() {
72        let result = hash256(b"");
73        assert_eq!(
74            result,
75            hex!("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456")
76        );
77    }
78
79    #[test]
80    fn sha256_hello() {
81        // SHA-256("hello") — well-known test vector
82        let result = sha256(b"hello");
83        assert_eq!(
84            result,
85            hex!("2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")
86        );
87    }
88
89    #[test]
90    fn hash160_is_ripemd160_of_sha256() {
91        let data = b"test composition";
92        let expected = ripemd160(&sha256(data));
93        assert_eq!(hash160(data), expected);
94    }
95
96    #[test]
97    fn hash256_is_double_sha256() {
98        let data = b"test composition";
99        let expected = sha256(&sha256(data));
100        assert_eq!(hash256(data), expected);
101    }
102}