bc/
hashtypes.rs

1// Bitcoin protocol consensus library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved.
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22use amplify::{Bytes20, Bytes32, Wrapper};
23use commit_verify::{DigestExt, Ripemd160, Sha256};
24
25use crate::{
26    CompressedPk, LegacyPk, RedeemScript, UncompressedPk, WitnessScript, LIB_NAME_BITCOIN,
27};
28
29#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
30#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
31#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
32#[strict_type(lib = LIB_NAME_BITCOIN)]
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
34pub struct PubkeyHash(
35    #[from]
36    #[from([u8; 20])]
37    pub Bytes20,
38);
39
40impl From<PubkeyHash> for [u8; 20] {
41    fn from(value: PubkeyHash) -> Self { value.0.into_inner() }
42}
43
44impl From<CompressedPk> for PubkeyHash {
45    fn from(pk: CompressedPk) -> Self {
46        let mut engine = Sha256::default();
47        engine.input_raw(&pk.to_byte_array());
48        let mut engine2 = Ripemd160::default();
49        engine2.input_raw(&engine.finish());
50        Self(engine2.finish().into())
51    }
52}
53
54impl From<UncompressedPk> for PubkeyHash {
55    fn from(pk: UncompressedPk) -> Self {
56        let mut engine = Sha256::default();
57        engine.input_raw(&pk.to_byte_array());
58        let mut engine2 = Ripemd160::default();
59        engine2.input_raw(&engine.finish());
60        Self(engine2.finish().into())
61    }
62}
63
64impl From<LegacyPk> for PubkeyHash {
65    fn from(pk: LegacyPk) -> Self {
66        let mut engine = Sha256::default();
67        engine.input_raw(&pk.to_vec());
68        let mut engine2 = Ripemd160::default();
69        engine2.input_raw(&engine.finish());
70        Self(engine2.finish().into())
71    }
72}
73
74#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
75#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
76#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
77#[strict_type(lib = LIB_NAME_BITCOIN)]
78#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
79pub struct ScriptHash(
80    #[from]
81    #[from([u8; 20])]
82    pub Bytes20,
83);
84
85impl From<ScriptHash> for [u8; 20] {
86    fn from(value: ScriptHash) -> Self { value.0.into_inner() }
87}
88
89impl From<&RedeemScript> for ScriptHash {
90    fn from(redeem_script: &RedeemScript) -> Self {
91        let mut engine = Sha256::default();
92        engine.input_raw(redeem_script.as_slice());
93        let mut engine2 = Ripemd160::default();
94        engine2.input_raw(&engine.finish());
95        Self(engine2.finish().into())
96    }
97}
98
99#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
100#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
101#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
102#[strict_type(lib = LIB_NAME_BITCOIN)]
103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
104pub struct WPubkeyHash(
105    #[from]
106    #[from([u8; 20])]
107    pub Bytes20,
108);
109
110impl From<WPubkeyHash> for [u8; 20] {
111    fn from(value: WPubkeyHash) -> Self { value.0.into_inner() }
112}
113
114impl From<CompressedPk> for WPubkeyHash {
115    fn from(pk: CompressedPk) -> Self {
116        let mut engine = Sha256::default();
117        engine.input_raw(&pk.to_byte_array());
118        let mut engine2 = Ripemd160::default();
119        engine2.input_raw(&engine.finish());
120        Self(engine2.finish().into())
121    }
122}
123
124#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
125#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
126#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
127#[strict_type(lib = LIB_NAME_BITCOIN)]
128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
129pub struct WScriptHash(
130    #[from]
131    #[from([u8; 32])]
132    pub Bytes32,
133);
134
135impl From<WScriptHash> for [u8; 32] {
136    fn from(value: WScriptHash) -> Self { value.0.into_inner() }
137}
138
139impl From<&WitnessScript> for WScriptHash {
140    fn from(witness_script: &WitnessScript) -> Self {
141        let mut engine = Sha256::default();
142        engine.input_raw(witness_script.as_slice());
143        let mut engine2 = Sha256::default();
144        engine2.input_raw(&engine.finish());
145        Self(engine2.finish().into())
146    }
147}