Skip to main content

miden_client/rpc/domain/
digest.rs

1use alloc::string::String;
2use core::fmt::{self, Debug, Display, Formatter};
3
4use hex::ToHex;
5use miden_protocol::account::StorageMapKey;
6use miden_protocol::note::NoteId;
7use miden_protocol::{Felt, StarkField, Word};
8
9use crate::rpc::errors::RpcConversionError;
10use crate::rpc::generated as proto;
11
12// FORMATTING
13// ================================================================================================
14
15impl Display for proto::primitives::Digest {
16    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
17        f.write_str(&self.encode_hex::<String>())
18    }
19}
20
21impl Debug for proto::primitives::Digest {
22    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
23        Display::fmt(self, f)
24    }
25}
26
27impl ToHex for &proto::primitives::Digest {
28    fn encode_hex<T: FromIterator<char>>(&self) -> T {
29        (*self).encode_hex()
30    }
31
32    fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
33        (*self).encode_hex_upper()
34    }
35}
36
37impl ToHex for proto::primitives::Digest {
38    fn encode_hex<T: FromIterator<char>>(&self) -> T {
39        const HEX_LOWER: [char; 16] =
40            ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
41        [self.d0, self.d1, self.d2, self.d3]
42            .into_iter()
43            .flat_map(u64::to_be_bytes)
44            .flat_map(|b| [HEX_LOWER[(b >> 4) as usize], HEX_LOWER[(b & 0xf) as usize]])
45            .collect()
46    }
47
48    fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
49        const HEX_UPPER: [char; 16] =
50            ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
51        [self.d0, self.d1, self.d2, self.d3]
52            .into_iter()
53            .flat_map(u64::to_be_bytes)
54            .flat_map(|b| [HEX_UPPER[(b >> 4) as usize], HEX_UPPER[(b & 0xf) as usize]])
55            .collect()
56    }
57}
58
59// INTO
60// ================================================================================================
61
62impl From<Word> for proto::primitives::Digest {
63    fn from(value: Word) -> Self {
64        Self {
65            d0: value[0].as_int(),
66            d1: value[1].as_int(),
67            d2: value[2].as_int(),
68            d3: value[3].as_int(),
69        }
70    }
71}
72
73impl From<&Word> for proto::primitives::Digest {
74    fn from(value: &Word) -> Self {
75        (*value).into()
76    }
77}
78
79impl From<&NoteId> for proto::primitives::Digest {
80    fn from(value: &NoteId) -> Self {
81        value.as_word().into()
82    }
83}
84
85impl From<NoteId> for proto::primitives::Digest {
86    fn from(value: NoteId) -> Self {
87        value.as_word().into()
88    }
89}
90
91// FROM DIGEST
92// ================================================================================================
93
94impl TryFrom<proto::primitives::Digest> for [Felt; 4] {
95    type Error = RpcConversionError;
96
97    fn try_from(value: proto::primitives::Digest) -> Result<Self, Self::Error> {
98        if [value.d0, value.d1, value.d2, value.d3]
99            .iter()
100            .all(|v| *v < <Felt as StarkField>::MODULUS)
101        {
102            Ok([
103                Felt::new(value.d0),
104                Felt::new(value.d1),
105                Felt::new(value.d2),
106                Felt::new(value.d3),
107            ])
108        } else {
109            Err(RpcConversionError::NotAValidFelt)
110        }
111    }
112}
113
114impl TryFrom<proto::primitives::Digest> for Word {
115    type Error = RpcConversionError;
116
117    fn try_from(value: proto::primitives::Digest) -> Result<Self, Self::Error> {
118        Ok(Self::new(value.try_into()?))
119    }
120}
121
122impl TryFrom<&proto::primitives::Digest> for [Felt; 4] {
123    type Error = RpcConversionError;
124
125    fn try_from(value: &proto::primitives::Digest) -> Result<Self, Self::Error> {
126        (*value).try_into()
127    }
128}
129
130impl TryFrom<&proto::primitives::Digest> for Word {
131    type Error = RpcConversionError;
132
133    fn try_from(value: &proto::primitives::Digest) -> Result<Self, Self::Error> {
134        (*value).try_into()
135    }
136}
137
138impl TryFrom<proto::primitives::Digest> for StorageMapKey {
139    type Error = RpcConversionError;
140
141    fn try_from(value: proto::primitives::Digest) -> Result<Self, Self::Error> {
142        Ok(StorageMapKey::new(value.try_into()?))
143    }
144}