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(
34    feature = "serde",
35    derive(Serialize, Deserialize),
36    serde(crate = "serde_crate", transparent)
37)]
38pub struct PubkeyHash(
39    #[from]
40    #[from([u8; 20])]
41    pub Bytes20,
42);
43
44impl From<PubkeyHash> for [u8; 20] {
45    fn from(value: PubkeyHash) -> Self { value.0.into_inner() }
46}
47
48impl From<CompressedPk> for PubkeyHash {
49    fn from(pk: CompressedPk) -> Self {
50        let mut engine = Sha256::default();
51        engine.input_raw(&pk.to_byte_array());
52        let mut engine2 = Ripemd160::default();
53        engine2.input_raw(&engine.finish());
54        Self(engine2.finish().into())
55    }
56}
57
58impl From<UncompressedPk> for PubkeyHash {
59    fn from(pk: UncompressedPk) -> Self {
60        let mut engine = Sha256::default();
61        engine.input_raw(&pk.to_byte_array());
62        let mut engine2 = Ripemd160::default();
63        engine2.input_raw(&engine.finish());
64        Self(engine2.finish().into())
65    }
66}
67
68impl From<LegacyPk> for PubkeyHash {
69    fn from(pk: LegacyPk) -> Self {
70        let mut engine = Sha256::default();
71        engine.input_raw(&pk.to_vec());
72        let mut engine2 = Ripemd160::default();
73        engine2.input_raw(&engine.finish());
74        Self(engine2.finish().into())
75    }
76}
77
78#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
79#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
80#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
81#[strict_type(lib = LIB_NAME_BITCOIN)]
82#[cfg_attr(
83    feature = "serde",
84    derive(Serialize, Deserialize),
85    serde(crate = "serde_crate", transparent)
86)]
87pub struct ScriptHash(
88    #[from]
89    #[from([u8; 20])]
90    pub Bytes20,
91);
92
93impl From<ScriptHash> for [u8; 20] {
94    fn from(value: ScriptHash) -> Self { value.0.into_inner() }
95}
96
97impl From<&RedeemScript> for ScriptHash {
98    fn from(redeem_script: &RedeemScript) -> Self {
99        let mut engine = Sha256::default();
100        engine.input_raw(redeem_script.as_slice());
101        let mut engine2 = Ripemd160::default();
102        engine2.input_raw(&engine.finish());
103        Self(engine2.finish().into())
104    }
105}
106
107#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
108#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
109#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
110#[strict_type(lib = LIB_NAME_BITCOIN)]
111#[cfg_attr(
112    feature = "serde",
113    derive(Serialize, Deserialize),
114    serde(crate = "serde_crate", transparent)
115)]
116pub struct WPubkeyHash(
117    #[from]
118    #[from([u8; 20])]
119    pub Bytes20,
120);
121
122impl From<WPubkeyHash> for [u8; 20] {
123    fn from(value: WPubkeyHash) -> Self { value.0.into_inner() }
124}
125
126impl From<CompressedPk> for WPubkeyHash {
127    fn from(pk: CompressedPk) -> Self {
128        let mut engine = Sha256::default();
129        engine.input_raw(&pk.to_byte_array());
130        let mut engine2 = Ripemd160::default();
131        engine2.input_raw(&engine.finish());
132        Self(engine2.finish().into())
133    }
134}
135
136#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
137#[wrapper(Index, RangeOps, AsSlice, BorrowSlice, Hex, Display, FromStr)]
138#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
139#[strict_type(lib = LIB_NAME_BITCOIN)]
140#[cfg_attr(
141    feature = "serde",
142    derive(Serialize, Deserialize),
143    serde(crate = "serde_crate", transparent)
144)]
145pub struct WScriptHash(
146    #[from]
147    #[from([u8; 32])]
148    pub Bytes32,
149);
150
151impl From<WScriptHash> for [u8; 32] {
152    fn from(value: WScriptHash) -> Self { value.0.into_inner() }
153}
154
155impl From<&WitnessScript> for WScriptHash {
156    fn from(witness_script: &WitnessScript) -> Self {
157        let mut engine = Sha256::default();
158        engine.input_raw(witness_script.as_slice());
159        let mut engine2 = Sha256::default();
160        engine2.input_raw(&engine.finish());
161        Self(engine2.finish().into())
162    }
163}