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