Skip to main content

miden_client/rpc/domain/
digest.rs

1use alloc::string::String;
2use alloc::vec::Vec;
3use core::fmt::{self, Debug, Display, Formatter};
4
5use hex::ToHex;
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        let mut data: Vec<char> = Vec::with_capacity(Word::SERIALIZED_SIZE);
40        data.extend(format!("{:016x}", self.d0).chars());
41        data.extend(format!("{:016x}", self.d1).chars());
42        data.extend(format!("{:016x}", self.d2).chars());
43        data.extend(format!("{:016x}", self.d3).chars());
44        data.into_iter().collect()
45    }
46
47    fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
48        let mut data: Vec<char> = Vec::with_capacity(Word::SERIALIZED_SIZE);
49        data.extend(format!("{:016X}", self.d0).chars());
50        data.extend(format!("{:016X}", self.d1).chars());
51        data.extend(format!("{:016X}", self.d2).chars());
52        data.extend(format!("{:016X}", self.d3).chars());
53        data.into_iter().collect()
54    }
55}
56
57// INTO
58// ================================================================================================
59
60impl From<Word> for proto::primitives::Digest {
61    fn from(value: Word) -> Self {
62        Self {
63            d0: value[0].as_int(),
64            d1: value[1].as_int(),
65            d2: value[2].as_int(),
66            d3: value[3].as_int(),
67        }
68    }
69}
70
71impl From<&Word> for proto::primitives::Digest {
72    fn from(value: &Word) -> Self {
73        (*value).into()
74    }
75}
76
77impl From<&NoteId> for proto::primitives::Digest {
78    fn from(value: &NoteId) -> Self {
79        value.as_word().into()
80    }
81}
82
83impl From<NoteId> for proto::primitives::Digest {
84    fn from(value: NoteId) -> Self {
85        value.as_word().into()
86    }
87}
88
89// FROM DIGEST
90// ================================================================================================
91
92impl TryFrom<proto::primitives::Digest> for [Felt; 4] {
93    type Error = RpcConversionError;
94
95    fn try_from(value: proto::primitives::Digest) -> Result<Self, Self::Error> {
96        if [value.d0, value.d1, value.d2, value.d3]
97            .iter()
98            .all(|v| *v < <Felt as StarkField>::MODULUS)
99        {
100            Ok([
101                Felt::new(value.d0),
102                Felt::new(value.d1),
103                Felt::new(value.d2),
104                Felt::new(value.d3),
105            ])
106        } else {
107            Err(RpcConversionError::NotAValidFelt)
108        }
109    }
110}
111
112impl TryFrom<proto::primitives::Digest> for Word {
113    type Error = RpcConversionError;
114
115    fn try_from(value: proto::primitives::Digest) -> Result<Self, Self::Error> {
116        Ok(Self::new(value.try_into()?))
117    }
118}
119
120impl TryFrom<&proto::primitives::Digest> for [Felt; 4] {
121    type Error = RpcConversionError;
122
123    fn try_from(value: &proto::primitives::Digest) -> Result<Self, Self::Error> {
124        (*value).try_into()
125    }
126}
127
128impl TryFrom<&proto::primitives::Digest> for Word {
129    type Error = RpcConversionError;
130
131    fn try_from(value: &proto::primitives::Digest) -> Result<Self, Self::Error> {
132        (*value).try_into()
133    }
134}