zebra_chain/transaction/
hash.rs1use std::{fmt, sync::Arc};
32
33#[cfg(any(test, feature = "proptest-impl"))]
34use proptest_derive::Arbitrary;
35
36use hex::{FromHex, ToHex};
37
38use crate::serialization::{
39 ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize,
40};
41
42use super::{txid::TxIdBuilder, AuthDigest, Transaction};
43
44#[derive(
59 Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, serde::Deserialize, serde::Serialize,
60)]
61#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
62pub struct Hash(pub [u8; 32]);
63
64impl From<Transaction> for Hash {
65 fn from(transaction: Transaction) -> Self {
66 Hash::from(&transaction)
68 }
69}
70
71impl From<&Transaction> for Hash {
72 fn from(transaction: &Transaction) -> Self {
73 let hasher = TxIdBuilder::new(transaction);
74 hasher
75 .txid()
76 .expect("zcash_primitives and Zebra transaction formats must be compatible")
77 }
78}
79
80impl From<Arc<Transaction>> for Hash {
81 fn from(transaction: Arc<Transaction>) -> Self {
82 Hash::from(transaction.as_ref())
83 }
84}
85
86impl From<[u8; 32]> for Hash {
87 fn from(bytes: [u8; 32]) -> Self {
88 Self(bytes)
89 }
90}
91
92impl From<Hash> for [u8; 32] {
93 fn from(hash: Hash) -> Self {
94 hash.0
95 }
96}
97
98impl From<&Hash> for [u8; 32] {
99 fn from(hash: &Hash) -> Self {
100 (*hash).into()
101 }
102}
103
104impl Hash {
105 pub fn bytes_in_display_order(&self) -> [u8; 32] {
110 let mut reversed_bytes = self.0;
111 reversed_bytes.reverse();
112 reversed_bytes
113 }
114
115 pub fn from_bytes_in_display_order(bytes_in_display_order: &[u8; 32]) -> Hash {
120 let mut internal_byte_order = *bytes_in_display_order;
121 internal_byte_order.reverse();
122
123 Hash(internal_byte_order)
124 }
125}
126
127impl ToHex for &Hash {
128 fn encode_hex<T: FromIterator<char>>(&self) -> T {
129 self.bytes_in_display_order().encode_hex()
130 }
131
132 fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
133 self.bytes_in_display_order().encode_hex_upper()
134 }
135}
136
137impl ToHex for Hash {
138 fn encode_hex<T: FromIterator<char>>(&self) -> T {
139 (&self).encode_hex()
140 }
141
142 fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
143 (&self).encode_hex_upper()
144 }
145}
146
147impl FromHex for Hash {
148 type Error = <[u8; 32] as FromHex>::Error;
149
150 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
151 let mut hash = <[u8; 32]>::from_hex(hex)?;
152 hash.reverse();
153
154 Ok(hash.into())
155 }
156}
157
158impl fmt::Display for Hash {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 f.write_str(&self.encode_hex::<String>())
161 }
162}
163
164impl fmt::Debug for Hash {
165 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166 f.debug_tuple("transaction::Hash")
167 .field(&self.encode_hex::<String>())
168 .finish()
169 }
170}
171
172impl std::str::FromStr for Hash {
173 type Err = SerializationError;
174
175 fn from_str(s: &str) -> Result<Self, Self::Err> {
176 let mut bytes = [0; 32];
177 if hex::decode_to_slice(s, &mut bytes[..]).is_err() {
178 Err(SerializationError::Parse("hex decoding error"))
179 } else {
180 bytes.reverse();
181 Ok(Hash(bytes))
182 }
183 }
184}
185
186impl ZcashSerialize for Hash {
187 fn zcash_serialize<W: std::io::Write>(&self, mut writer: W) -> Result<(), std::io::Error> {
188 writer.write_32_bytes(&self.into())
189 }
190}
191
192impl ZcashDeserialize for Hash {
193 fn zcash_deserialize<R: std::io::Read>(mut reader: R) -> Result<Self, SerializationError> {
194 Ok(reader.read_32_bytes()?.into())
195 }
196}
197
198#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
209#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
210pub struct WtxId {
211 pub id: Hash,
213
214 pub auth_digest: AuthDigest,
216}
217
218impl WtxId {
219 pub fn as_bytes(&self) -> [u8; 64] {
221 <[u8; 64]>::from(self)
222 }
223}
224
225impl From<Transaction> for WtxId {
226 fn from(transaction: Transaction) -> Self {
232 WtxId::from(&transaction)
234 }
235}
236
237impl From<&Transaction> for WtxId {
238 fn from(transaction: &Transaction) -> Self {
244 Self {
245 id: transaction.into(),
246 auth_digest: transaction.into(),
247 }
248 }
249}
250
251impl From<Arc<Transaction>> for WtxId {
252 fn from(transaction: Arc<Transaction>) -> Self {
258 transaction.as_ref().into()
259 }
260}
261
262impl From<[u8; 64]> for WtxId {
263 fn from(bytes: [u8; 64]) -> Self {
264 let id: [u8; 32] = bytes[0..32].try_into().expect("length is 64");
265 let auth_digest: [u8; 32] = bytes[32..64].try_into().expect("length is 64");
266
267 Self {
268 id: id.into(),
269 auth_digest: auth_digest.into(),
270 }
271 }
272}
273
274impl From<WtxId> for [u8; 64] {
275 fn from(wtx_id: WtxId) -> Self {
276 let mut bytes = [0; 64];
277 let (id, auth_digest) = bytes.split_at_mut(32);
278
279 id.copy_from_slice(&wtx_id.id.0);
280 auth_digest.copy_from_slice(&wtx_id.auth_digest.0);
281
282 bytes
283 }
284}
285
286impl From<&WtxId> for [u8; 64] {
287 fn from(wtx_id: &WtxId) -> Self {
288 (*wtx_id).into()
289 }
290}
291
292impl TryFrom<&[u8]> for WtxId {
293 type Error = SerializationError;
294
295 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
296 let bytes: [u8; 64] = bytes.try_into()?;
297
298 Ok(bytes.into())
299 }
300}
301
302impl TryFrom<Vec<u8>> for WtxId {
303 type Error = SerializationError;
304
305 fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
306 bytes.as_slice().try_into()
307 }
308}
309
310impl TryFrom<&Vec<u8>> for WtxId {
311 type Error = SerializationError;
312
313 fn try_from(bytes: &Vec<u8>) -> Result<Self, Self::Error> {
314 bytes.clone().try_into()
315 }
316}
317
318impl fmt::Display for WtxId {
319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 f.write_str(&self.id.to_string())?;
321 f.write_str(&self.auth_digest.to_string())
322 }
323}
324
325impl std::str::FromStr for WtxId {
326 type Err = SerializationError;
327
328 fn from_str(s: &str) -> Result<Self, Self::Err> {
329 let s = s.as_bytes();
332
333 if s.len() == 128 {
334 let (id, auth_digest) = s.split_at(64);
335 let id = std::str::from_utf8(id)?;
336 let auth_digest = std::str::from_utf8(auth_digest)?;
337
338 Ok(Self {
339 id: id.parse()?,
340 auth_digest: auth_digest.parse()?,
341 })
342 } else {
343 Err(SerializationError::Parse(
344 "wrong length for WtxId hex string",
345 ))
346 }
347 }
348}
349
350impl ZcashSerialize for WtxId {
351 fn zcash_serialize<W: std::io::Write>(&self, mut writer: W) -> Result<(), std::io::Error> {
352 writer.write_64_bytes(&self.into())
353 }
354}
355
356impl ZcashDeserialize for WtxId {
357 fn zcash_deserialize<R: std::io::Read>(mut reader: R) -> Result<Self, SerializationError> {
358 Ok(reader.read_64_bytes()?.into())
359 }
360}