1use alloc::{
42 format,
43 string::{String, ToString},
44 sync::Arc,
45 vec::Vec,
46};
47
48use miden_assembly_syntax::ast::{self, AttributeSet, PathBuf};
49use miden_core::{
50 Word,
51 mast::{MastForest, MastNodeExt, MastNodeId, UntrustedMastForest},
52 serde::{
53 BudgetedReader, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
54 SliceReader,
55 },
56};
57
58use super::{
59 ConstantExport, PackageId, PackageModule, PackageSubmodule, ProcedureExport, TargetType,
60 TypeExport,
61};
62use crate::{
63 Dependency, ManifestValidationError, Package, PackageExport, PackageManifest, Section,
64 debug_info::DebugSourceNodeId,
65};
66
67#[cfg(test)]
68mod tests;
69
70const MAGIC_PACKAGE: &[u8; 5] = b"MASP\0";
75
76const VERSION: [u8; 3] = [7, 0, 0];
80
81const PACKAGE_BYTE_READ_BUDGET_MULTIPLIER: usize = 64;
86
87impl Package {
91 #[doc(hidden)]
92 pub fn write_header_into<W: ByteWriter>(&self, target: &mut W) {
93 target.write_bytes(MAGIC_PACKAGE);
95 target.write_bytes(&VERSION);
96
97 self.name.write_into(target);
99
100 self.version.to_string().write_into(target);
102
103 self.description.write_into(target);
105
106 target.write_u8(self.kind.into());
108 }
109
110 #[doc(hidden)]
111 pub fn write_trailer_into<W: ByteWriter>(&self, target: &mut W) {
112 self.manifest.write_into(target);
114
115 target.write_usize(self.sections.len());
117 for section in self.sections.iter() {
118 section.write_into(target);
119 }
120 }
121
122 #[track_caller]
133 pub fn read_from_trusted<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
134 let header = Self::read_header_from(source)?;
135 let mast_forest = Self::read_mast_forest(source, false)?;
136 Self::read_from_with_header_and_mast(source, header, mast_forest, false, false)
137 }
138
139 #[track_caller]
151 pub fn read_from_bytes_trusted(bytes: &[u8]) -> Result<Self, DeserializationError> {
152 let budget = bytes.len().saturating_mul(PACKAGE_BYTE_READ_BUDGET_MULTIPLIER);
153 let mut reader = BudgetedReader::new(SliceReader::new(bytes), budget);
154 Self::read_from_trusted(&mut reader)
155 }
156
157 #[track_caller]
158 fn read_mast_forest<R: ByteReader>(
159 source: &mut R,
160 validate_mast_forest: bool,
161 ) -> Result<Arc<MastForest>, DeserializationError> {
162 if validate_mast_forest {
163 UntrustedMastForest::read_from(source)?.validate().map_err(|err| {
164 DeserializationError::InvalidValue(format!(
165 "library contains an invalid untrusted MAST forest: {err}"
166 ))
167 })
168 } else {
169 MastForest::read_from(source)
170 }
171 .map(Arc::new)
172 }
173}
174
175impl Serializable for Package {
176 fn write_into<W: ByteWriter>(&self, target: &mut W) {
177 self.write_header_into(target);
178
179 self.mast.write_into(target);
181
182 self.write_trailer_into(target);
183 }
184}
185
186struct PackageHeader {
187 name: PackageId,
188 version: crate::Version,
189 description: Option<String>,
190 kind: TargetType,
191}
192
193impl Package {
194 fn read_header_from<R: ByteReader>(
195 source: &mut R,
196 ) -> Result<PackageHeader, DeserializationError> {
197 let magic: [u8; 5] = source.read_array()?;
199 if magic != *MAGIC_PACKAGE {
200 return Err(DeserializationError::InvalidValue(format!(
201 "invalid magic bytes. Expected '{MAGIC_PACKAGE:?}', got '{magic:?}'"
202 )));
203 }
204
205 let version: [u8; 3] = source.read_array()?;
206 if version != VERSION {
207 return Err(DeserializationError::InvalidValue(format!(
208 "unsupported version. Got '{version:?}', but only '{VERSION:?}' is supported"
209 )));
210 }
211
212 let name = PackageId::read_from(source)?;
214
215 let version = String::read_from(source)?
217 .parse::<crate::Version>()
218 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
219
220 let description = Option::<String>::read_from(source)?;
222
223 let kind_tag = source.read_u8()?;
225 let kind = TargetType::try_from(kind_tag)
226 .map_err(|e| DeserializationError::InvalidValue(e.to_string()))?;
227
228 Ok(PackageHeader { name, version, description, kind })
229 }
230
231 fn read_from_with_header_and_mast<R: ByteReader>(
232 source: &mut R,
233 header: PackageHeader,
234 mast: Arc<MastForest>,
235 validate_manifest: bool,
236 validate_debug_sections: bool,
237 ) -> Result<Self, DeserializationError> {
238 let PackageHeader { name, version, description, kind } = header;
239
240 let manifest = if validate_manifest {
242 PackageManifest::read_from_safe(source, &mast)?
243 } else {
244 PackageManifest::read_from_trusted(source, &mast)?
245 };
246
247 let sections = Vec::<Section>::read_from(source)?;
249
250 let package = Self {
251 name,
252 version,
253 description,
254 kind,
255 mast,
256 manifest,
257 sections,
258 debug_sections_trusted: true,
259 };
260
261 if validate_debug_sections {
262 package.debug_info().map_err(|err| {
263 DeserializationError::InvalidValue(format!(
264 "package contains invalid debug information: {err}"
265 ))
266 })?;
267 }
268
269 if validate_manifest {
270 package
271 .interface_commitment()
272 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
273 }
274
275 Ok(package)
276 }
277}
278
279impl Deserializable for Package {
280 #[track_caller]
288 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
289 let header = Self::read_header_from(source)?;
290
291 let mast = Self::read_mast_forest(source, true)?;
293
294 Self::read_from_with_header_and_mast(source, header, mast, true, true)
295 }
296
297 #[track_caller]
304 fn read_from_bytes(bytes: &[u8]) -> Result<Self, DeserializationError> {
305 let budget = bytes.len().saturating_mul(PACKAGE_BYTE_READ_BUDGET_MULTIPLIER);
306 let mut reader = BudgetedReader::new(SliceReader::new(bytes), budget);
307 Self::read_from(&mut reader)
308 }
309}
310
311impl Serializable for PackageManifest {
315 fn write_into<W: ByteWriter>(&self, target: &mut W) {
316 target.write_usize(self.num_exports());
318 for export in self.exports() {
319 export.write_into(target);
320 }
321
322 target.write_usize(self.num_modules());
324 for module in self.modules() {
325 module.write_into(target);
326 }
327
328 target.write_usize(self.num_dependencies());
330 for dep in self.dependencies() {
331 dep.write_into(target);
332 }
333
334 if let Some(entrypoint) = self.entrypoint.as_ref() {
336 target.write_bool(true);
337 entrypoint.write_into(target);
338 } else {
339 target.write_bool(false);
340 }
341 }
342}
343
344impl PackageManifest {
345 pub fn read_from_trusted<R: ByteReader>(
346 source: &mut R,
347 mast: &MastForest,
348 ) -> Result<Self, DeserializationError> {
349 let exports_len = source.read_usize()?;
351 let max_exports = source.max_alloc(PackageExport::min_serialized_size());
352 if exports_len > max_exports {
353 return Err(DeserializationError::InvalidValue(format!(
354 "requested {exports_len} elements but reader can provide at most {max_exports}"
355 )));
356 }
357 let mut exports = Vec::with_capacity(exports_len);
358 for _ in 0..exports_len {
359 exports.push(PackageExport::read_from_trusted(source, mast)?);
360 }
361
362 let modules_len = source.read_usize()?;
364 let max_modules = source.max_alloc(PackageModule::min_serialized_size());
365 if modules_len > max_modules {
366 return Err(DeserializationError::InvalidValue(format!(
367 "requested {modules_len} elements but reader can provide at most {max_modules}"
368 )));
369 }
370 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
371
372 let dependencies = Vec::<Dependency>::read_from(source)?;
374
375 let entrypoint = if source.read_bool()? {
377 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
378 } else {
379 None
380 };
381
382 PackageManifest::new(exports)
383 .and_then(|manifest| manifest.with_modules(modules))
384 .and_then(|manifest| manifest.with_dependencies(dependencies))
385 .and_then(|manifest| {
386 if let Some(entrypoint) = entrypoint {
387 manifest.with_entrypoint(entrypoint)
388 } else {
389 Ok(manifest)
390 }
391 })
392 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
393 }
394
395 pub fn read_from_safe<R: ByteReader>(
396 source: &mut R,
397 mast: &MastForest,
398 ) -> Result<Self, DeserializationError> {
399 let exports_len = source.read_usize()?;
401 let max_exports = source.max_alloc(PackageExport::min_serialized_size());
402 if exports_len > max_exports {
403 return Err(DeserializationError::InvalidValue(format!(
404 "requested {exports_len} elements but reader can provide at most {max_exports}"
405 )));
406 }
407 let mut exports = Vec::with_capacity(exports_len);
408 for _ in 0..exports_len {
409 exports.push(PackageExport::read_from_safe(source, mast)?);
410 }
411
412 let modules_len = source.read_usize()?;
414 let max_modules = source.max_alloc(PackageModule::min_serialized_size());
415 if modules_len > max_modules {
416 return Err(DeserializationError::InvalidValue(format!(
417 "requested {modules_len} elements but reader can provide at most {max_modules}"
418 )));
419 }
420 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
421
422 let dependencies = Vec::<Dependency>::read_from(source)?;
424
425 let entrypoint = if source.read_bool()? {
427 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
428 } else {
429 None
430 };
431
432 PackageManifest::new(exports)
433 .and_then(|manifest| manifest.with_modules(modules))
434 .and_then(|manifest| manifest.with_dependencies(dependencies))
435 .and_then(|manifest| {
436 if let Some(entrypoint) = entrypoint {
437 manifest.with_entrypoint(entrypoint)
438 } else {
439 Ok(manifest)
440 }
441 })
442 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
443 }
444}
445
446impl Deserializable for PackageManifest {
447 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
448 let exports_len = source.read_usize()?;
450 let exports = source.read_many_iter(exports_len)?.collect::<Result<Vec<_>, _>>()?;
451
452 let modules_len = source.read_usize()?;
454 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
455
456 let dependencies = Vec::<Dependency>::read_from(source)?;
458
459 let entrypoint = if source.read_bool()? {
461 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
462 } else {
463 None
464 };
465
466 PackageManifest::new(exports)
467 .and_then(|manifest| manifest.with_modules(modules))
468 .and_then(|manifest| manifest.with_dependencies(dependencies))
469 .and_then(|manifest| {
470 if let Some(entrypoint) = entrypoint {
471 manifest.with_entrypoint(entrypoint)
472 } else {
473 Ok(manifest)
474 }
475 })
476 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
477 }
478}
479
480impl Serializable for PackageModule {
484 fn write_into<W: ByteWriter>(&self, target: &mut W) {
485 self.path.write_into(target);
486 target.write_usize(self.submodules.len());
487 for submodule in self.submodules.iter() {
488 submodule.write_into(target);
489 }
490 }
491}
492
493impl Deserializable for PackageModule {
494 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
495 let path = PathBuf::read_from(source)?.into_boxed_path().into();
496 let submodules = Vec::<PackageSubmodule>::read_from(source)?;
497 Ok(Self { path, submodules })
498 }
499}
500
501impl Serializable for PackageSubmodule {
502 fn write_into<W: ByteWriter>(&self, target: &mut W) {
503 self.name.write_into(target);
504 }
505}
506
507impl Deserializable for PackageSubmodule {
508 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
509 let name = ast::Ident::read_from(source)?;
510 Ok(Self { name })
511 }
512}
513
514impl Serializable for PackageExport {
518 fn write_into<W: ByteWriter>(&self, target: &mut W) {
519 target.write_u8(self.tag());
520 match self {
521 Self::Procedure(export) => export.write_into(target),
522 Self::Constant(export) => export.write_into(target),
523 Self::Type(export) => export.write_into(target),
524 }
525 }
526}
527
528impl PackageExport {
529 pub fn read_from_trusted<R: ByteReader>(
530 source: &mut R,
531 mast: &MastForest,
532 ) -> Result<Self, DeserializationError> {
533 match source.read_u8()? {
534 1 => ProcedureExport::read_from_trusted(source, mast).map(Self::Procedure),
535 2 => ConstantExport::read_from(source).map(Self::Constant),
536 3 => TypeExport::read_from(source).map(Self::Type),
537 invalid => Err(DeserializationError::InvalidValue(format!(
538 "unexpected PackageExport tag: '{invalid}'"
539 ))),
540 }
541 }
542
543 pub fn read_from_safe<R: ByteReader>(
544 source: &mut R,
545 mast: &MastForest,
546 ) -> Result<Self, DeserializationError> {
547 match source.read_u8()? {
548 1 => ProcedureExport::read_from_safe(source, mast).map(Self::Procedure),
549 2 => ConstantExport::read_from(source).map(Self::Constant),
550 3 => TypeExport::read_from(source).map(Self::Type),
551 invalid => Err(DeserializationError::InvalidValue(format!(
552 "unexpected PackageExport tag: '{invalid}'"
553 ))),
554 }
555 }
556}
557
558impl Deserializable for PackageExport {
559 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
560 match source.read_u8()? {
561 1 => ProcedureExport::read_from(source).map(Self::Procedure),
562 2 => ConstantExport::read_from(source).map(Self::Constant),
563 3 => TypeExport::read_from(source).map(Self::Type),
564 invalid => Err(DeserializationError::InvalidValue(format!(
565 "unexpected PackageExport tag: '{invalid}'"
566 ))),
567 }
568 }
569}
570
571impl Serializable for ProcedureExport {
572 fn write_into<W: ByteWriter>(&self, target: &mut W) {
573 self.path.write_into(target);
574 if let Some(node_id) = self.node {
575 target.write_bool(true);
576 target.write_u32(node_id.into());
577 } else {
578 target.write_bool(false);
579 }
580 if let Some(source_node) = self.source_node {
581 target.write_bool(true);
582 source_node.write_into(target);
583 } else {
584 target.write_bool(false);
585 }
586 self.digest.write_into(target);
587 match self.signature.as_ref() {
588 Some(sig) => {
589 target.write_bool(true);
590 sig.write_into(target);
591 },
592 None => {
593 target.write_bool(false);
594 },
595 }
596 self.attributes.write_into(target);
597 }
598}
599
600impl ProcedureExport {
601 pub fn read_from_trusted<R: ByteReader>(
602 source: &mut R,
603 mast: &MastForest,
604 ) -> Result<Self, DeserializationError> {
605 use miden_assembly_syntax::ast::types::FunctionType;
606 let path = PathBuf::read_from(source)?.into_boxed_path().into();
607 let node = if source.read_bool()? {
608 Some(MastNodeId::from_u32_safe(source.read_u32()?, mast)?)
609 } else {
610 None
611 };
612 let source_node = if source.read_bool()? {
613 Some(DebugSourceNodeId::read_from(source)?)
614 } else {
615 None
616 };
617 let digest = Word::read_from(source)?;
618 let signature = if source.read_bool()? {
619 Some(FunctionType::read_from(source)?)
620 } else {
621 None
622 };
623 let attributes = AttributeSet::read_from(source)?;
624 Ok(Self {
625 path,
626 node,
627 source_node,
628 digest,
629 signature,
630 attributes,
631 })
632 }
633
634 pub fn read_from_safe<R: ByteReader>(
635 source: &mut R,
636 mast: &MastForest,
637 ) -> Result<Self, DeserializationError> {
638 use miden_assembly_syntax::ast::types::FunctionType;
639 let path = PathBuf::read_from(source)?.into_boxed_path().into();
640 let node = if source.read_bool()? {
641 let node_id = MastNodeId::from_u32_safe(source.read_u32()?, mast)?;
642 if !mast.is_procedure_root(node_id) {
643 return Err(DeserializationError::InvalidValue(
644 ManifestValidationError::InvalidProcedureExport { path }.to_string(),
645 ));
646 }
647 Some(node_id)
648 } else {
649 None
650 };
651 let source_node = if source.read_bool()? {
652 Some(DebugSourceNodeId::read_from(source)?)
653 } else {
654 None
655 };
656 let digest = Word::read_from(source)?;
657 if let Some(node) = node
659 && digest != mast[node].digest()
660 {
661 return Err(DeserializationError::InvalidValue(
662 ManifestValidationError::InvalidProcedureExport { path }.to_string(),
663 ));
664 }
665 let signature = if source.read_bool()? {
666 Some(FunctionType::read_from(source)?)
667 } else {
668 None
669 };
670 let attributes = AttributeSet::read_from(source)?;
671 Ok(Self {
672 path,
673 node,
674 source_node,
675 digest,
676 signature,
677 attributes,
678 })
679 }
680}
681
682impl Deserializable for ProcedureExport {
683 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
684 use miden_assembly_syntax::ast::types::FunctionType;
685 let path = PathBuf::read_from(source)?.into_boxed_path().into();
686 let node = if source.read_bool()? {
687 Some(MastNodeId::new_unchecked(source.read_u32()?))
688 } else {
689 None
690 };
691 let source_node = if source.read_bool()? {
692 Some(DebugSourceNodeId::read_from(source)?)
693 } else {
694 None
695 };
696 let digest = Word::read_from(source)?;
697 let signature = if source.read_bool()? {
698 Some(FunctionType::read_from(source)?)
699 } else {
700 None
701 };
702 let attributes = AttributeSet::read_from(source)?;
703 Ok(Self {
704 path,
705 node,
706 source_node,
707 digest,
708 signature,
709 attributes,
710 })
711 }
712}
713
714impl Serializable for ConstantExport {
715 fn write_into<W: ByteWriter>(&self, target: &mut W) {
716 self.path.write_into(target);
717 self.value.write_into(target);
718 }
719}
720
721impl Deserializable for ConstantExport {
722 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
723 let path = PathBuf::read_from(source)?.into_boxed_path().into();
724 let value = ast::ConstantValue::read_from(source)?;
725 Ok(Self { path, value })
726 }
727}
728
729impl Serializable for TypeExport {
730 fn write_into<W: ByteWriter>(&self, target: &mut W) {
731 self.path.write_into(target);
732 self.ty.write_into(target);
733 }
734}
735
736impl Deserializable for TypeExport {
737 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
738 use miden_assembly_syntax::ast::types::Type;
739 let path = PathBuf::read_from(source)?.into_boxed_path().into();
740 let ty = Type::read_from(source)?;
741 Ok(Self { path, ty })
742 }
743}