diem_types/
account_state_blob.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8use diem_crypto::{
9    hash::{CryptoHash, CryptoHasher},
10    HashValue,
11};
12use diem_crypto_derive::CryptoHasher;
13#[cfg(any(test, feature = "fuzzing"))]
14use proptest::{arbitrary::Arbitrary, prelude::*};
15use serde::{Deserialize, Serialize};
16use std::fmt;
17
18#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, CryptoHasher)]
19pub struct AccountStateBlob {
20    blob: Vec<u8>,
21}
22
23impl fmt::Debug for AccountStateBlob {
24    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25        write!(
26            f,
27            "AccountStateBlob {{ \n \
28             Raw: 0x{} \n \
29             }}",
30            hex::encode(&self.blob),
31        )
32    }
33}
34
35impl AsRef<[u8]> for AccountStateBlob {
36    fn as_ref(&self) -> &[u8] { &self.blob }
37}
38
39impl From<&AccountStateBlob> for Vec<u8> {
40    fn from(account_state_blob: &AccountStateBlob) -> Vec<u8> {
41        account_state_blob.blob.clone()
42    }
43}
44
45impl From<AccountStateBlob> for Vec<u8> {
46    fn from(account_state_blob: AccountStateBlob) -> Vec<u8> {
47        Self::from(&account_state_blob)
48    }
49}
50
51impl From<Vec<u8>> for AccountStateBlob {
52    fn from(blob: Vec<u8>) -> AccountStateBlob { AccountStateBlob { blob } }
53}
54
55impl CryptoHash for AccountStateBlob {
56    type Hasher = AccountStateBlobHasher;
57
58    fn hash(&self) -> HashValue {
59        let mut hasher = Self::Hasher::default();
60        hasher.update(&self.blob);
61        hasher.finish()
62    }
63}
64
65#[cfg(any(test, feature = "fuzzing"))]
66prop_compose! {
67    fn account_state_blob_strategy()(
68        entries in proptest::collection::btree_map(
69            proptest::collection::vec(any::<u8>(), 1..32),
70            proptest::collection::vec(any::<u8>(), 1..64),
71            0..5,
72        )
73    ) -> AccountStateBlob {
74        AccountStateBlob::from(bcs::to_bytes(&entries).unwrap())
75    }
76}
77
78#[cfg(any(test, feature = "fuzzing"))]
79impl Arbitrary for AccountStateBlob {
80    type Parameters = ();
81    type Strategy = BoxedStrategy<Self>;
82
83    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
84        account_state_blob_strategy().boxed()
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use bcs::test_helpers::assert_canonical_encode_decode;
92    use proptest::collection::vec;
93
94    fn hash_blob(blob: &[u8]) -> HashValue {
95        let mut hasher = AccountStateBlobHasher::default();
96        hasher.update(blob);
97        hasher.finish()
98    }
99
100    proptest! {
101        #[test]
102        fn account_state_blob_hash(blob in vec(any::<u8>(), 1..100)) {
103            prop_assert_eq!(hash_blob(&blob), AccountStateBlob::from(blob).hash());
104        }
105
106        #[test]
107        fn account_state_blob_bcs_roundtrip(account_state_blob in any::<AccountStateBlob>()) {
108            assert_canonical_encode_decode(account_state_blob);
109        }
110    }
111
112    #[test]
113    fn test_debug_does_not_panic() {
114        let _ = format!("{:#?}", AccountStateBlob::from(vec![1u8, 2u8, 3u8]));
115    }
116}