1#![no_std]
2
3#[macro_use]
4extern crate alloc;
5
6#[cfg(feature = "std")]
7extern crate std;
8
9pub mod account;
10pub mod asset;
11pub mod batch;
12pub mod block;
13pub mod note;
14pub mod transaction;
15
16#[cfg(any(feature = "testing", test))]
17pub mod testing;
18
19mod constants;
20mod errors;
21
22pub use constants::*;
26pub use errors::{
27 AccountDeltaError, AccountError, AccountIdError, AssetError, AssetVaultError,
28 BatchAccountUpdateError, ChainMmrError, NoteError, NullifierTreeError, ProposedBatchError,
29 ProposedBlockError, ProvenTransactionError, TransactionInputError, TransactionOutputError,
30 TransactionScriptError,
31};
32pub use miden_crypto::hash::rpo::{Rpo256 as Hasher, RpoDigest as Digest};
33pub use vm_core::{
34 EMPTY_WORD, Felt, FieldElement, ONE, StarkField, WORD_SIZE, Word, ZERO,
35 mast::{MastForest, MastNodeId},
36 prettier::PrettyPrint,
37};
38
39pub mod assembly {
40 pub use assembly::{
41 Assembler, AssemblyError, Compile, CompileOptions, DefaultSourceManager, KernelLibrary,
42 Library, LibraryNamespace, LibraryPath, SourceManager, Version,
43 ast::{Module, ModuleKind, ProcedureName, QualifiedProcedureName},
44 mast,
45 };
46}
47
48pub mod crypto {
49 pub use miden_crypto::{dsa, hash, merkle, rand, utils};
50}
51
52pub mod utils {
53 use alloc::string::{String, ToString};
54
55 pub use miden_crypto::utils::{HexParseError, bytes_to_hex_string, collections, hex_to_bytes};
56 pub use vm_core::utils::*;
57 use vm_core::{Felt, StarkField, Word};
58
59 pub mod serde {
60 pub use miden_crypto::utils::{
61 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
62 };
63 }
64
65 pub fn word_to_masm_push_string(word: &Word) -> String {
76 format!("{}.{}.{}.{}", word[0], word[1], word[2], word[3])
77 }
78
79 pub const fn parse_hex_string_as_word(hex: &str) -> Result<[Felt; 4], &'static str> {
80 const fn parse_hex_digit(digit: u8) -> Result<u8, &'static str> {
81 match digit {
82 b'0'..=b'9' => Ok(digit - b'0'),
83 b'A'..=b'F' => Ok(digit - b'A' + 0x0a),
84 b'a'..=b'f' => Ok(digit - b'a' + 0x0a),
85 _ => Err("Invalid hex character"),
86 }
87 }
88 let hex_bytes = match hex.as_bytes() {
90 [b'0', b'x', rest @ ..] => rest,
91 _ => return Err("Hex string must have a \"0x\" prefix"),
92 };
93
94 if hex_bytes.len() > 64 {
95 return Err("Hex string has more than 64 characters");
96 }
97
98 let mut felts = [0u64; 4];
99 let mut i = 0;
100 while i < hex_bytes.len() {
101 let hex_digit = match parse_hex_digit(hex_bytes[i]) {
102 Ok(v) => v as u64,
105 Err(e) => return Err(e),
106 };
107
108 let inibble = if i % 2 == 0 { (i + 1) % 16 } else { (i - 1) % 16 };
111
112 let value = hex_digit << (inibble * 4);
113 felts[i / 2 / 8] += value;
114
115 i += 1;
116 }
117
118 let mut idx = 0;
121 while idx < felts.len() {
122 if felts[idx] > Felt::MODULUS {
123 return Err("Felt overflow");
124 }
125 idx += 1;
126 }
127
128 Ok([
129 Felt::new(felts[0]),
130 Felt::new(felts[1]),
131 Felt::new(felts[2]),
132 Felt::new(felts[3]),
133 ])
134 }
135
136 #[macro_export]
140 macro_rules! digest {
141 ($hex:expr) => {{
142 let felts: [$crate::Felt; 4] = match $crate::utils::parse_hex_string_as_word($hex) {
143 Ok(v) => v,
144 Err(e) => panic!("{}", e),
145 };
146
147 $crate::Digest::new(felts)
148 }};
149 }
150
151 pub fn parse_hex_to_felts(hex: &str) -> Result<[Felt; 4], String> {
152 match parse_hex_string_as_word(hex) {
153 Ok(felts) => Ok(felts),
154 Err(e) => Err(e.to_string()),
155 }
156 }
157
158 #[cfg(test)]
159 mod tests {
160 #[rstest::rstest]
161 #[case::missing_prefix("1234")]
162 #[case::invalid_character("1234567890abcdefg")]
163 #[case::too_long("0xx00000000000000000000000000000000000000000000000000000000000000001")]
164 #[case::overflow_felt0(
165 "0xffffffffffffffff000000000000000000000000000000000000000000000000"
166 )]
167 #[case::overflow_felt1(
168 "0x0000000000000000ffffffffffffffff00000000000000000000000000000000"
169 )]
170 #[case::overflow_felt2(
171 "0x00000000000000000000000000000000ffffffffffffffff0000000000000000"
172 )]
173 #[case::overflow_felt3(
174 "0x000000000000000000000000000000000000000000000000ffffffffffffffff"
175 )]
176 #[should_panic]
177 fn digest_macro_invalid(#[case] bad_input: &str) {
178 digest!(bad_input);
179 }
180
181 #[rstest::rstest]
182 #[case::each_digit("0x1234567890abcdef")]
183 #[case::empty("0x")]
184 #[case::zero("0x0")]
185 #[case::zero_full("0x0000000000000000000000000000000000000000000000000000000000000000")]
186 #[case::one_lsb("0x1")]
187 #[case::one_msb("0x0000000000000000000000000000000000000000000000000000000000000001")]
188 #[case::one_partial("0x0001")]
189 #[case::odd("0x123")]
190 #[case::even("0x1234")]
191 #[case::touch_each_felt(
192 "0x00000000000123450000000000067890000000000000abcd00000000000000ef"
193 )]
194 #[case::unique_felt("0x111111111111111155555555555555559999999999999999cccccccccccccccc")]
195 #[case::digits_on_repeat(
196 "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
197 )]
198 fn digest_macro(#[case] input: &str) {
199 let uut = digest!(input);
200
201 let padded_input = format!("{input:<66}").replace(" ", "0");
204 let expected = crate::Digest::try_from(std::dbg!(padded_input)).unwrap();
205
206 assert_eq!(uut, expected);
207 }
208 }
209}
210
211pub mod vm {
212 pub use miden_verifier::ExecutionProof;
213 pub use vm_core::{AdviceMap, Program, ProgramInfo, sys_events::SystemEvent};
214 pub use vm_processor::{AdviceInputs, RowIndex, StackInputs, StackOutputs};
215}