Skip to main content

aptos_crypto_link/
hash.rs

1// Copyright (c) Aptos
2// SPDX-License-Identifier: Apache-2.0
3
4//! This module defines traits and implementations of
5//! [cryptographic hash functions](https://en.wikipedia.org/wiki/Cryptographic_hash_function)
6//!
7//! It is designed to help authors protect against two types of real world attacks:
8//!
9//! 1. **Semantic Ambiguity**: imagine that Alice has a private key and is using
10//!    two different applications, X and Y. X asks Alice to sign a message saying
11//!    "I am Alice". Alice accepts to sign this message in the context of X. However,
12//!    unbeknownst to Alice, in application Y, messages beginning with the letter "I"
13//!    represent transfers. " am " represents a transfer of 500 coins and "Alice"
14//!    can be interpreted as a destination address. When Alice signed the message she
15//!    needed to be aware of how other applications might interpret that message.
16//!
17//! 2. **Format Ambiguity**: imagine a program that hashes a pair of strings.
18//!    To hash the strings `a` and `b` it hashes `a + "||" + b`. The pair of
19//!    strings `a="foo||", b = "bar"` and `a="foo", b = "||bar"` result in the
20//!    same input to the hash function and therefore the same hash. This
21//!    creates a collision.
22//!
23//! Regarding (1), this library makes it easy for developers to create as
24//! many new "hashable" Rust types as needed so that each Rust type hashed and signed
25//! has a unique meaning, that is, unambiguously captures the intent of a signer.
26//!
27//! Regarding (2), this library provides the `CryptoHasher` abstraction to easily manage
28//! cryptographic seeds for hashing. Hashing seeds aim to ensure that
29//! the hashes of values of a given type `MyNewStruct` never collide with hashes of values
30//! from another type.
31//!
32//! Finally, to prevent format ambiguity within a same type `MyNewStruct` and facilitate protocol
33//! specifications, we use [Binary Canonical Serialization (BCS)](https://docs.rs/bcs/)
34//! as the recommended solution to write Rust values into a hasher.
35//!
36//! # Quick Start
37//!
38//! To obtain a `hash()` method for any new type `MyNewStruct`, it is (strongly) recommended to
39//! use the derive macros of `serde` and `aptos_crypto_derive` as follows:
40//! ```
41//! use aptos_crypto::hash::CryptoHash;
42//! use aptos_crypto_derive::{CryptoHasher, BCSCryptoHash};
43//! use serde::{Deserialize, Serialize};
44//! #[derive(Serialize, Deserialize, CryptoHasher, BCSCryptoHash)]
45//! struct MyNewStruct { /*...*/ }
46//!
47//! let value = MyNewStruct { /*...*/ };
48//! value.hash();
49//! ```
50//!
51//! Under the hood, this will generate a new implementation `MyNewStructHasher` for the trait
52//! `CryptoHasher` and implement the trait `CryptoHash` for `MyNewStruct` using BCS.
53//!
54//! # Implementing New Hashers
55//!
56//! The trait `CryptoHasher` captures the notion of a pre-seeded hash function, aka a "hasher".
57//! New implementations can be defined in two ways.
58//!
59//! ## Derive macro (recommended)
60//!
61//! For any new structure `MyNewStruct` that needs to be hashed, it is recommended to simply
62//! use the derive macro [`CryptoHasher`](https://doc.rust-lang.org/reference/procedural-macros.html).
63//!
64//! ```
65//! use aptos_crypto_derive::CryptoHasher;
66//! use serde::Deserialize;
67//! #[derive(Deserialize, CryptoHasher)]
68//! #[serde(rename = "OptionalCustomSerdeName")]
69//! struct MyNewStruct { /*...*/ }
70//! ```
71//!
72//! The macro `CryptoHasher` will define a hasher automatically called `MyNewStructHasher`, and derive a salt
73//! using the name of the type as seen by the Serde library. In the example above, this name
74//! was changed using the Serde parameter `rename`: the salt will be based on the value `OptionalCustomSerdeName`
75//! instead of the default name `MyNewStruct`.
76//!
77//! ## Customized hashers
78//!
79//! **IMPORTANT:** Do NOT use this for new code unless you know what you are doing.
80//!
81//! This library also provides a few customized hashers defined in the code as follows:
82//!
83//! ```
84//! # // To get around that there's no way to doc-test a non-exported macro:
85//! # macro_rules! define_hasher { ($e:expr) => () }
86//! define_hasher! { (MyNewDataHasher, MY_NEW_DATA_HASHER, MY_NEW_DATA_SEED, b"MyUniqueSaltString") }
87//! ```
88//!
89//! # Using a hasher directly
90//!
91//! **IMPORTANT:** Do NOT use this for new code unless you know what you are doing.
92//!
93//! ```
94//! use aptos_crypto::hash::{CryptoHasher, TestOnlyHasher};
95//!
96//! let mut hasher = TestOnlyHasher::default();
97//! hasher.update("Test message".as_bytes());
98//! let hash_value = hasher.finish();
99//! ```
100#![allow(clippy::integer_arithmetic)]
101use bytes::Bytes;
102use hex::FromHex;
103use more_asserts::{debug_assert_ge, debug_assert_lt};
104use once_cell::sync::{Lazy, OnceCell};
105#[cfg(any(test, feature = "fuzzing"))]
106use proptest_derive::Arbitrary;
107use rand::{rngs::OsRng, Rng};
108use serde::{de, ser, Deserialize, Serialize};
109use std::{
110    self,
111    convert::{AsRef, TryFrom},
112    fmt,
113    str::FromStr,
114};
115use tiny_keccak::{Hasher, Sha3};
116
117/// A prefix used to begin the salt of every hashable structure. The salt
118/// consists in this global prefix, concatenated with the specified
119/// serialization name of the struct.
120pub(crate) const HASH_PREFIX: &[u8] = b"APTOS::";
121
122/// Output value of our hash function. Intentionally opaque for safety and modularity.
123#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
124#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
125pub struct HashValue {
126    hash: [u8; HashValue::LENGTH],
127}
128
129impl HashValue {
130    /// The length of the hash in bytes.
131    pub const LENGTH: usize = 32;
132    /// The length of the hash in bits.
133    pub const LENGTH_IN_BITS: usize = Self::LENGTH * 8;
134
135    /// Create a new [`HashValue`] from a byte array.
136    pub fn new(hash: [u8; HashValue::LENGTH]) -> Self {
137        HashValue { hash }
138    }
139
140    /// Create from a slice (e.g. retrieved from storage).
141    pub fn from_slice<T: AsRef<[u8]>>(bytes: T) -> Result<Self, HashValueParseError> {
142        <[u8; Self::LENGTH]>::try_from(bytes.as_ref())
143            .map_err(|_| HashValueParseError)
144            .map(Self::new)
145    }
146
147    /// Dumps into a vector.
148    pub fn to_vec(&self) -> Vec<u8> {
149        self.hash.to_vec()
150    }
151
152    /// Creates a zero-initialized instance.
153    pub const fn zero() -> Self {
154        HashValue {
155            hash: [0; HashValue::LENGTH],
156        }
157    }
158
159    /// Create a cryptographically random instance.
160    pub fn random() -> Self {
161        let mut rng = OsRng;
162        let hash: [u8; HashValue::LENGTH] = rng.gen();
163        HashValue { hash }
164    }
165
166    /// Creates a random instance with given rng. Useful in unit tests.
167    pub fn random_with_rng<R: Rng>(rng: &mut R) -> Self {
168        let hash: [u8; HashValue::LENGTH] = rng.gen();
169        HashValue { hash }
170    }
171
172    /// Convenience function that computes a `HashValue` internally equal to
173    /// the sha3_256 of a byte buffer. It will handle hasher creation, data
174    /// feeding and finalization.
175    ///
176    /// Note this will not result in the `<T as CryptoHash>::hash()` for any
177    /// reasonable struct T, as this computes a sha3 without any ornaments.
178    pub fn sha3_256_of(buffer: &[u8]) -> Self {
179        let mut sha3 = Sha3::v256();
180        sha3.update(buffer);
181        HashValue::from_keccak(sha3)
182    }
183
184    #[cfg(test)]
185    pub fn from_iter_sha3<'a, I>(buffers: I) -> Self
186    where
187        I: IntoIterator<Item = &'a [u8]>,
188    {
189        let mut sha3 = Sha3::v256();
190        for buffer in buffers {
191            sha3.update(buffer);
192        }
193        HashValue::from_keccak(sha3)
194    }
195
196    fn as_ref_mut(&mut self) -> &mut [u8] {
197        &mut self.hash[..]
198    }
199
200    fn from_keccak(state: Sha3) -> Self {
201        let mut hash = Self::zero();
202        state.finalize(hash.as_ref_mut());
203        hash
204    }
205
206    /// Returns the `index`-th bit in the bytes.
207    pub fn bit(&self, index: usize) -> bool {
208        debug_assert!(index < Self::LENGTH_IN_BITS); // assumed precondition
209        let pos = index / 8;
210        let bit = 7 - index % 8;
211        (self.hash[pos] >> bit) & 1 != 0
212    }
213
214    /// Returns the `index`-th nibble in the bytes.
215    pub fn nibble(&self, index: usize) -> u8 {
216        debug_assert!(index < Self::LENGTH * 2); // assumed precondition
217        let pos = index / 2;
218        let shift = if index % 2 == 0 { 4 } else { 0 };
219        (self.hash[pos] >> shift) & 0x0f
220    }
221
222    /// Returns a `HashValueBitIterator` over all the bits that represent this `HashValue`.
223    pub fn iter_bits(&self) -> HashValueBitIterator<'_> {
224        HashValueBitIterator::new(self)
225    }
226
227    /// Constructs a `HashValue` from an iterator of bits.
228    pub fn from_bit_iter(
229        iter: impl ExactSizeIterator<Item = bool>,
230    ) -> Result<Self, HashValueParseError> {
231        if iter.len() != Self::LENGTH_IN_BITS {
232            return Err(HashValueParseError);
233        }
234
235        let mut buf = [0; Self::LENGTH];
236        for (i, bit) in iter.enumerate() {
237            if bit {
238                buf[i / 8] |= 1 << (7 - i % 8);
239            }
240        }
241        Ok(Self::new(buf))
242    }
243
244    /// Returns the length of common prefix of `self` and `other` in bits.
245    pub fn common_prefix_bits_len(&self, other: HashValue) -> usize {
246        self.iter_bits()
247            .zip(other.iter_bits())
248            .take_while(|(x, y)| x == y)
249            .count()
250    }
251
252    /// Full hex representation of a given hash value.
253    pub fn to_hex(&self) -> String {
254        format!("{:x}", self)
255    }
256
257    /// Full hex representation of a given hash value with `0x` prefix.
258    pub fn to_hex_literal(&self) -> String {
259        format!("{:#x}", self)
260    }
261
262    /// Parse a given hex string to a hash value.
263    pub fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, HashValueParseError> {
264        <[u8; Self::LENGTH]>::from_hex(hex)
265            .map_err(|_| HashValueParseError)
266            .map(Self::new)
267    }
268
269    /// Create a hash value whose contents are just the given integer. Useful for
270    /// generating basic mock hash values.
271    ///
272    /// Ex: HashValue::from_u64(0x1234) => HashValue([0, .., 0, 0x12, 0x34])
273    #[cfg(any(test, feature = "fuzzing"))]
274    pub fn from_u64(v: u64) -> Self {
275        let mut hash = [0u8; Self::LENGTH];
276        let bytes = v.to_be_bytes();
277        hash[Self::LENGTH - bytes.len()..].copy_from_slice(&bytes[..]);
278        Self::new(hash)
279    }
280}
281
282impl ser::Serialize for HashValue {
283    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
284    where
285        S: ser::Serializer,
286    {
287        if serializer.is_human_readable() {
288            serializer.serialize_str(&self.to_hex())
289        } else {
290            // In order to preserve the Serde data model and help analysis tools,
291            // make sure to wrap our value in a container with the same name
292            // as the original type.
293            #[derive(Serialize)]
294            #[serde(rename = "HashValue")]
295            struct Value<'a> {
296                hash: &'a [u8; HashValue::LENGTH],
297            }
298            Value { hash: &self.hash }.serialize(serializer)
299        }
300    }
301}
302
303impl<'de> de::Deserialize<'de> for HashValue {
304    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
305    where
306        D: de::Deserializer<'de>,
307    {
308        if deserializer.is_human_readable() {
309            let encoded_hash = <String>::deserialize(deserializer)?;
310            HashValue::from_hex(encoded_hash.as_str())
311                .map_err(<D::Error as ::serde::de::Error>::custom)
312        } else {
313            // See comment in serialize.
314            #[derive(Deserialize)]
315            #[serde(rename = "HashValue")]
316            struct Value {
317                hash: [u8; HashValue::LENGTH],
318            }
319
320            let value = Value::deserialize(deserializer)
321                .map_err(<D::Error as ::serde::de::Error>::custom)?;
322            Ok(Self::new(value.hash))
323        }
324    }
325}
326
327impl Default for HashValue {
328    fn default() -> Self {
329        HashValue::zero()
330    }
331}
332
333impl AsRef<[u8; HashValue::LENGTH]> for HashValue {
334    fn as_ref(&self) -> &[u8; HashValue::LENGTH] {
335        &self.hash
336    }
337}
338
339impl std::ops::Deref for HashValue {
340    type Target = [u8; Self::LENGTH];
341
342    fn deref(&self) -> &Self::Target {
343        &self.hash
344    }
345}
346
347impl std::ops::Index<usize> for HashValue {
348    type Output = u8;
349
350    fn index(&self, s: usize) -> &u8 {
351        self.hash.index(s)
352    }
353}
354
355impl fmt::Binary for HashValue {
356    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
357        for byte in &self.hash {
358            write!(f, "{:08b}", byte)?;
359        }
360        Ok(())
361    }
362}
363
364impl fmt::LowerHex for HashValue {
365    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366        if f.alternate() {
367            write!(f, "0x")?;
368        }
369        for byte in &self.hash {
370            write!(f, "{:02x}", byte)?;
371        }
372        Ok(())
373    }
374}
375
376impl fmt::Debug for HashValue {
377    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378        write!(f, "HashValue(")?;
379        <Self as fmt::LowerHex>::fmt(self, f)?;
380        write!(f, ")")?;
381        Ok(())
382    }
383}
384
385/// Will print shortened (4 bytes) hash
386impl fmt::Display for HashValue {
387    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
388        for byte in self.hash.iter().take(4) {
389            write!(f, "{:02x}", byte)?;
390        }
391        Ok(())
392    }
393}
394
395impl From<HashValue> for Bytes {
396    fn from(value: HashValue) -> Bytes {
397        Bytes::copy_from_slice(value.hash.as_ref())
398    }
399}
400
401impl FromStr for HashValue {
402    type Err = HashValueParseError;
403
404    fn from_str(s: &str) -> Result<Self, HashValueParseError> {
405        HashValue::from_hex(s)
406    }
407}
408
409/// Parse error when attempting to construct a HashValue
410#[derive(Clone, Copy, Debug)]
411pub struct HashValueParseError;
412
413impl fmt::Display for HashValueParseError {
414    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415        write!(f, "unable to parse HashValue")
416    }
417}
418
419impl std::error::Error for HashValueParseError {}
420
421/// An iterator over `HashValue` that generates one bit for each iteration.
422pub struct HashValueBitIterator<'a> {
423    /// The reference to the bytes that represent the `HashValue`.
424    hash_bytes: &'a [u8],
425    pos: std::ops::Range<usize>,
426    // invariant hash_bytes.len() == HashValue::LENGTH;
427    // invariant pos.end == hash_bytes.len() * 8;
428}
429
430impl<'a> HashValueBitIterator<'a> {
431    /// Constructs a new `HashValueBitIterator` using given `HashValue`.
432    fn new(hash_value: &'a HashValue) -> Self {
433        HashValueBitIterator {
434            hash_bytes: hash_value.as_ref(),
435            pos: (0..HashValue::LENGTH_IN_BITS),
436        }
437    }
438
439    /// Returns the `index`-th bit in the bytes.
440    fn get_bit(&self, index: usize) -> bool {
441        debug_assert_eq!(self.hash_bytes.len(), HashValue::LENGTH); // invariant
442        debug_assert_lt!(index, self.hash_bytes.len() * 8); // assumed precondition
443        debug_assert_ge!(index, 0); // assumed precondition
444        let pos = index / 8;
445        let bit = 7 - index % 8;
446        (self.hash_bytes[pos] >> bit) & 1 != 0
447    }
448}
449
450impl<'a> std::iter::Iterator for HashValueBitIterator<'a> {
451    type Item = bool;
452
453    fn next(&mut self) -> Option<Self::Item> {
454        self.pos.next().map(|x| self.get_bit(x))
455    }
456
457    fn size_hint(&self) -> (usize, Option<usize>) {
458        self.pos.size_hint()
459    }
460}
461
462impl<'a> std::iter::DoubleEndedIterator for HashValueBitIterator<'a> {
463    fn next_back(&mut self) -> Option<Self::Item> {
464        self.pos.next_back().map(|x| self.get_bit(x))
465    }
466}
467
468impl<'a> std::iter::ExactSizeIterator for HashValueBitIterator<'a> {}
469
470/// A type that can be cryptographically hashed to produce a `HashValue`.
471///
472/// In most cases, this trait should not be implemented manually but rather derived using
473/// the macros `serde::Serialize`, `CryptoHasher`, and `BCSCryptoHash`.
474pub trait CryptoHash {
475    /// The associated `Hasher` type which comes with a unique salt for this type.
476    type Hasher: CryptoHasher;
477
478    /// Hashes the object and produces a `HashValue`.
479    fn hash(&self) -> HashValue;
480}
481
482/// A trait for representing the state of a cryptographic hasher.
483pub trait CryptoHasher: Default + std::io::Write {
484    /// the seed used to initialize hashing `Self` before the serialization bytes of the actual value
485    fn seed() -> &'static [u8; 32];
486
487    /// Write bytes into the hasher.
488    fn update(&mut self, bytes: &[u8]);
489
490    /// Finish constructing the [`HashValue`].
491    fn finish(self) -> HashValue;
492
493    /// Convenience method to compute the hash of a complete byte slice.
494    fn hash_all(bytes: &[u8]) -> HashValue {
495        let mut hasher = Self::default();
496        hasher.update(bytes);
497        hasher.finish()
498    }
499}
500
501/// The default hasher underlying generated implementations of `CryptoHasher`.
502#[doc(hidden)]
503#[derive(Clone)]
504pub struct DefaultHasher {
505    state: Sha3,
506}
507
508impl DefaultHasher {
509    #[doc(hidden)]
510    /// This function does not return a HashValue in the sense of our usual
511    /// hashes, but a construction of initial bytes that are fed into any hash
512    /// provided we're passed  a (bcs) serialization name as argument.
513    pub fn prefixed_hash(buffer: &[u8]) -> [u8; HashValue::LENGTH] {
514        // The salt is initial material we prefix to actual value bytes for
515        // domain separation. Its length is variable.
516        let salt: Vec<u8> = [HASH_PREFIX, buffer].concat();
517        // The seed is a fixed-length hash of the salt, thereby preventing
518        // suffix attacks on the domain separation bytes.
519        HashValue::sha3_256_of(&salt[..]).hash
520    }
521
522    #[doc(hidden)]
523    pub fn new(typename: &[u8]) -> Self {
524        let mut state = Sha3::v256();
525        if !typename.is_empty() {
526            state.update(&Self::prefixed_hash(typename));
527        }
528        DefaultHasher { state }
529    }
530
531    #[doc(hidden)]
532    pub fn update(&mut self, bytes: &[u8]) {
533        self.state.update(bytes);
534    }
535
536    #[doc(hidden)]
537    pub fn finish(self) -> HashValue {
538        let mut hasher = HashValue::default();
539        self.state.finalize(hasher.as_ref_mut());
540        hasher
541    }
542}
543
544impl fmt::Debug for DefaultHasher {
545    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
546        write!(f, "DefaultHasher: state = Sha3")
547    }
548}
549
550macro_rules! define_hasher {
551    (
552        $(#[$attr:meta])*
553        ($hasher_type: ident, $hasher_name: ident, $seed_name: ident, $salt: expr)
554    ) => {
555
556        #[derive(Clone, Debug)]
557        $(#[$attr])*
558        pub struct $hasher_type(DefaultHasher);
559
560        impl $hasher_type {
561            fn new() -> Self {
562                $hasher_type(DefaultHasher::new($salt))
563            }
564        }
565
566        static $hasher_name: Lazy<$hasher_type> = Lazy::new(|| { $hasher_type::new() });
567        static $seed_name: OnceCell<[u8; 32]> = OnceCell::new();
568
569        impl Default for $hasher_type {
570            fn default() -> Self {
571                $hasher_name.clone()
572            }
573        }
574
575        impl CryptoHasher for $hasher_type {
576            fn seed() -> &'static [u8;32] {
577                $seed_name.get_or_init(|| {
578                    DefaultHasher::prefixed_hash($salt)
579                })
580            }
581
582            fn update(&mut self, bytes: &[u8]) {
583                self.0.update(bytes);
584            }
585
586            fn finish(self) -> HashValue {
587                self.0.finish()
588            }
589        }
590
591        impl std::io::Write for $hasher_type {
592            fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
593                self.0.update(bytes);
594                Ok(bytes.len())
595            }
596            fn flush(&mut self) -> std::io::Result<()> {
597                Ok(())
598            }
599        }
600    };
601}
602
603define_hasher! {
604    /// The hasher used to compute the hash of an internal node in the transaction accumulator.
605    (
606        TransactionAccumulatorHasher,
607        TRANSACTION_ACCUMULATOR_HASHER,
608        TRANSACTION_ACCUMULATOR_SEED,
609        b"TransactionAccumulator"
610    )
611}
612
613define_hasher! {
614    /// The hasher used to compute the hash of an internal node in the event accumulator.
615    (
616        EventAccumulatorHasher,
617        EVENT_ACCUMULATOR_HASHER,
618        EVENT_ACCUMULATOR_SEED,
619        b"EventAccumulator"
620    )
621}
622
623define_hasher! {
624    /// The hasher used to compute the hash of an internal node in the Sparse Merkle Tree.
625    (
626        SparseMerkleInternalHasher,
627        SPARSE_MERKLE_INTERNAL_HASHER,
628        SPARSE_MERKLE_INTERNAL_SEED,
629        b"SparseMerkleInternal"
630    )
631}
632
633define_hasher! {
634    /// The hasher used only for testing. It doesn't have a salt.
635    (TestOnlyHasher, TEST_ONLY_HASHER, TEST_ONLY_SEED, b"")
636}
637
638fn create_literal_hash(word: &str) -> HashValue {
639    let mut s = word.as_bytes().to_vec();
640    assert!(s.len() <= HashValue::LENGTH);
641    s.resize(HashValue::LENGTH, 0);
642    HashValue::from_slice(&s).expect("Cannot fail")
643}
644
645/// Placeholder hash of `Accumulator`.
646pub static ACCUMULATOR_PLACEHOLDER_HASH: Lazy<HashValue> =
647    Lazy::new(|| create_literal_hash("ACCUMULATOR_PLACEHOLDER_HASH"));
648
649/// Placeholder hash of `SparseMerkleTree`.
650pub static SPARSE_MERKLE_PLACEHOLDER_HASH: Lazy<HashValue> =
651    Lazy::new(|| create_literal_hash("SPARSE_MERKLE_PLACEHOLDER_HASH"));
652
653/// Block id reserved as the id of parent block of the genesis block.
654pub static PRE_GENESIS_BLOCK_ID: Lazy<HashValue> =
655    Lazy::new(|| create_literal_hash("PRE_GENESIS_BLOCK_ID"));
656
657/// Genesis block id is used as a parent of the very first block executed by the executor.
658pub static GENESIS_BLOCK_ID: Lazy<HashValue> = Lazy::new(|| {
659    // This maintains the invariant that block.id() == block.hash(), for
660    // the genesis block and allows us to (de/)serialize it consistently
661    HashValue::new([
662        0x5e, 0x10, 0xba, 0xd4, 0x5b, 0x35, 0xed, 0x92, 0x9c, 0xd6, 0xd2, 0xc7, 0x09, 0x8b, 0x13,
663        0x5d, 0x02, 0xdd, 0x25, 0x9a, 0xe8, 0x8a, 0x8d, 0x09, 0xf4, 0xeb, 0x5f, 0xba, 0xe9, 0xa6,
664        0xf6, 0xe4,
665    ])
666});
667
668/// Provides a test_only_hash() method that can be used in tests on types that implement
669/// `serde::Serialize`.
670///
671/// # Example
672/// ```
673/// use aptos_crypto::hash::TestOnlyHash;
674///
675/// b"hello world".test_only_hash();
676/// ```
677pub trait TestOnlyHash {
678    /// Generates a hash used only for tests.
679    fn test_only_hash(&self) -> HashValue;
680}
681
682impl<T: ser::Serialize + ?Sized> TestOnlyHash for T {
683    fn test_only_hash(&self) -> HashValue {
684        let bytes = bcs::to_bytes(self).expect("serialize failed during hash.");
685        let mut hasher = TestOnlyHasher::default();
686        hasher.update(&bytes);
687        hasher.finish()
688    }
689}