Skip to main content

miden_base_sys/bindings/
types.rs

1extern crate alloc;
2
3use miden_field_repr::FromFeltRepr;
4use miden_stdlib_sys::{Felt, Word, felt};
5
6/// Packs a scalar felt into the low limb of a protocol word.
7fn padded_word_from_felt(value: Felt) -> Word {
8    Word::new([felt!(0), felt!(0), felt!(0), value])
9}
10
11/// Extracts a scalar felt from a protocol word with zero-padded high limbs.
12fn felt_from_padded_word(value: Word) -> Result<Felt, &'static str> {
13    if value[0] != felt!(0) || value[1] != felt!(0) || value[2] != felt!(0) {
14        return Err("expected zero padding in the upper three felts");
15    }
16
17    Ok(value[3])
18}
19
20/// Unique identifier for a Miden account, composed of two field elements.
21#[derive(Copy, Clone, Debug, PartialEq, Eq, FromFeltRepr)]
22pub struct AccountId {
23    pub prefix: Felt,
24    pub suffix: Felt,
25}
26
27impl AccountId {
28    /// Creates a new AccountId from prefix and suffix Felt values.
29    pub fn new(prefix: Felt, suffix: Felt) -> Self {
30        Self { prefix, suffix }
31    }
32}
33
34/// Raw protocol return layout for account identifiers.
35/// The protocol MASM procedures are returning [suffix, prefix]
36#[derive(Copy, Clone)]
37#[repr(C)]
38pub(crate) struct RawAccountId {
39    pub suffix: Felt,
40    pub prefix: Felt,
41}
42
43impl RawAccountId {
44    /// Converts the protocol return layout into the Rust [`AccountId`] layout.
45    pub(crate) fn into_account_id(self) -> AccountId {
46        AccountId::new(self.prefix, self.suffix)
47    }
48}
49
50impl From<AccountId> for Word {
51    #[inline]
52    fn from(value: AccountId) -> Self {
53        Word::from([felt!(0), felt!(0), value.suffix, value.prefix])
54    }
55}
56
57impl TryFrom<Word> for AccountId {
58    type Error = &'static str;
59
60    #[inline]
61    fn try_from(value: Word) -> Result<Self, Self::Error> {
62        if value[0] != felt!(0) || value[1] != felt!(0) {
63            return Err("expected zero padding in the upper two felts");
64        }
65
66        Ok(Self {
67            prefix: value[3],
68            suffix: value[2],
69        })
70    }
71}
72
73/// A fungible or non-fungible asset encoded as separate vault key and value words.
74///
75/// The `key` identifies the asset in the account vault and the `value` stores the corresponding
76/// asset contents. This matches the v0.14 protocol/base ABI.
77#[derive(Copy, Clone, Debug, PartialEq, Eq)]
78#[repr(C)]
79pub struct Asset {
80    /// The asset's vault key.
81    pub key: Word,
82    /// The asset's vault value.
83    pub value: Word,
84}
85
86impl Asset {
87    /// Creates a new [`Asset`] from its key and value words.
88    pub fn new(key: impl Into<Word>, value: impl Into<Word>) -> Self {
89        Self {
90            key: key.into(),
91            value: value.into(),
92        }
93    }
94}
95
96impl From<Asset> for (Word, Word) {
97    fn from(val: Asset) -> Self {
98        (val.key, val.value)
99    }
100}
101
102/// A note recipient digest.
103#[derive(Clone, Debug, PartialEq, Eq)]
104#[repr(transparent)]
105pub struct Recipient {
106    pub inner: Word,
107}
108
109/// The note metadata returned by `*_note::get_metadata` procedures.
110///
111/// In the Miden protocol, metadata retrieval returns both the note attachment and the metadata
112/// header as separate words.
113#[derive(Copy, Clone, Debug, PartialEq, Eq)]
114#[repr(C)]
115pub struct NoteMetadata {
116    /// The attachment of the note.
117    pub attachment: Word,
118    /// The metadata header of the note.
119    pub header: Word,
120}
121
122impl NoteMetadata {
123    /// Creates a new [`NoteMetadata`] from attachment and header.
124    pub fn new(attachment: Word, header: Word) -> Self {
125        Self { attachment, header }
126    }
127}
128
129impl From<[Felt; 4]> for Recipient {
130    fn from(value: [Felt; 4]) -> Self {
131        Recipient {
132            inner: Word::from(value),
133        }
134    }
135}
136
137impl From<Word> for Recipient {
138    fn from(value: Word) -> Self {
139        Recipient { inner: value }
140    }
141}
142
143impl From<Recipient> for Word {
144    #[inline]
145    fn from(value: Recipient) -> Self {
146        value.inner
147    }
148}
149
150#[derive(Clone, Copy, Debug, PartialEq, Eq)]
151#[repr(transparent)]
152pub struct Tag {
153    pub inner: Felt,
154}
155
156impl From<Felt> for Tag {
157    fn from(value: Felt) -> Self {
158        Tag { inner: value }
159    }
160}
161
162impl From<Tag> for Word {
163    #[inline]
164    fn from(value: Tag) -> Self {
165        padded_word_from_felt(value.inner)
166    }
167}
168
169impl TryFrom<Word> for Tag {
170    type Error = &'static str;
171
172    #[inline]
173    fn try_from(value: Word) -> Result<Self, Self::Error> {
174        Ok(Tag {
175            inner: felt_from_padded_word(value)?,
176        })
177    }
178}
179
180#[derive(Clone, Copy, Debug, PartialEq, Eq)]
181#[repr(transparent)]
182pub struct NoteIdx {
183    pub inner: Felt,
184}
185
186impl From<NoteIdx> for Word {
187    #[inline]
188    fn from(value: NoteIdx) -> Self {
189        padded_word_from_felt(value.inner)
190    }
191}
192
193impl TryFrom<Word> for NoteIdx {
194    type Error = &'static str;
195
196    #[inline]
197    fn try_from(value: Word) -> Result<Self, Self::Error> {
198        Ok(NoteIdx {
199            inner: felt_from_padded_word(value)?,
200        })
201    }
202}
203
204#[derive(Clone, Copy, Debug, PartialEq, Eq)]
205#[repr(transparent)]
206pub struct NoteType {
207    pub inner: Felt,
208}
209
210impl From<Felt> for NoteType {
211    fn from(value: Felt) -> Self {
212        NoteType { inner: value }
213    }
214}
215
216impl From<NoteType> for Word {
217    #[inline]
218    fn from(value: NoteType) -> Self {
219        padded_word_from_felt(value.inner)
220    }
221}
222
223impl TryFrom<Word> for NoteType {
224    type Error = &'static str;
225
226    #[inline]
227    fn try_from(value: Word) -> Result<Self, Self::Error> {
228        Ok(NoteType {
229            inner: felt_from_padded_word(value)?,
230        })
231    }
232}
233
234/// The partial hash of a storage slot name.
235///
236/// A slot id consists of two field elements: a `prefix` and a `suffix`.
237///
238/// Slot ids uniquely identify slots in account storage and are used by the host functions exposed
239/// via `miden::protocol::*`.
240#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
241pub struct StorageSlotId {
242    suffix: Felt,
243    prefix: Felt,
244}
245
246impl StorageSlotId {
247    /// Creates a new [`StorageSlotId`] from the provided felts.
248    ///
249    /// Note: this constructor takes `(suffix, prefix)` to match the values returned by
250    /// `miden_protocol::account::StorageSlotId::{suffix,prefix}`.
251    pub fn new(suffix: Felt, prefix: Felt) -> Self {
252        Self { suffix, prefix }
253    }
254
255    /// Creates a new [`StorageSlotId`] from the provided felts in host-call order.
256    ///
257    /// Host functions take the `prefix` first and then the `suffix`.
258    pub fn from_prefix_suffix(prefix: Felt, suffix: Felt) -> Self {
259        Self { suffix, prefix }
260    }
261
262    /// Returns the `(prefix, suffix)` pair in host-call order.
263    pub fn to_prefix_suffix(&self) -> (Felt, Felt) {
264        (self.prefix, self.suffix)
265    }
266
267    /// Returns the `(suffix, prefix)` pair in storage-slot order.
268    pub fn to_suffix_prefix(&self) -> (Felt, Felt) {
269        (self.suffix, self.prefix)
270    }
271
272    /// Returns the suffix of the [`StorageSlotId`].
273    pub fn suffix(&self) -> Felt {
274        self.suffix
275    }
276
277    /// Returns the prefix of the [`StorageSlotId`].
278    pub fn prefix(&self) -> Felt {
279        self.prefix
280    }
281}