miden_client/rpc/domain/
digest.rs1use 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
12impl 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
59impl 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
91impl 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}