1use 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}