1use alloc::{
47 format,
48 string::{String, ToString},
49 sync::Arc,
50 vec::Vec,
51};
52
53use miden_assembly_syntax::ast::{self, AttributeSet, PathBuf};
54use miden_core::{
55 Word,
56 mast::{MastForest, MastNodeExt, MastNodeId, UntrustedMastForest},
57 serde::{
58 BudgetedReader, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
59 SliceReader,
60 },
61};
62
63use super::{
64 ConstantExport, PackageId, PackageModule, PackageSubmodule, ProcedureExport, TargetType,
65 TypeExport,
66};
67use crate::{
68 Dependency, ManifestValidationError, Package, PackageExport, PackageManifest, Section,
69 debug_info::DebugSourceNodeId,
70};
71
72#[cfg(test)]
73mod tests;
74
75const MAGIC_PACKAGE: &[u8; 5] = b"MASP\0";
80
81const VERSION: [u8; 3] = [6, 0, 0];
85
86const PACKAGE_BYTE_READ_BUDGET_MULTIPLIER: usize = 64;
91
92impl Package {
96 #[doc(hidden)]
97 pub fn write_header_into<W: ByteWriter>(&self, target: &mut W) {
98 target.write_bytes(MAGIC_PACKAGE);
100 target.write_bytes(&VERSION);
101
102 self.name.write_into(target);
104
105 self.version.to_string().write_into(target);
107
108 self.description.write_into(target);
110
111 target.write_u8(self.kind.into());
113 }
114
115 #[doc(hidden)]
116 pub fn write_trailer_into<W: ByteWriter>(&self, target: &mut W) {
117 self.manifest.write_into(target);
119
120 target.write_usize(self.sections.len());
122 for section in self.sections.iter() {
123 section.write_into(target);
124 }
125 }
126
127 pub fn read_from_unchecked<R: ByteReader>(
138 source: &mut R,
139 ) -> Result<Self, DeserializationError> {
140 let header = Self::read_header_from(source)?;
141 let mast_forest = Self::read_mast_forest(source, false)?;
142 Self::read_from_with_header_and_mast(source, header, mast_forest, true)
143 }
144
145 pub fn read_from_bytes_unchecked(bytes: &[u8]) -> Result<Self, DeserializationError> {
156 let mut source = SliceReader::new(bytes);
157 Self::read_from_unchecked(&mut source)
158 }
159
160 pub fn read_from_trusted<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
168 let header = Self::read_header_from(source)?;
169 let mast_forest = Self::read_mast_forest(source, true)?;
170 Self::read_from_with_header_and_mast(source, header, mast_forest, true)
171 }
172
173 pub fn read_from_bytes_trusted(bytes: &[u8]) -> Result<Self, DeserializationError> {
177 let budget = bytes.len().saturating_mul(PACKAGE_BYTE_READ_BUDGET_MULTIPLIER);
178 let mut reader = BudgetedReader::new(SliceReader::new(bytes), budget);
179 Self::read_from_trusted(&mut reader)
180 }
181
182 fn read_mast_forest<R: ByteReader>(
183 source: &mut R,
184 validate_mast_forest: bool,
185 ) -> Result<Arc<MastForest>, DeserializationError> {
186 if validate_mast_forest {
187 UntrustedMastForest::read_from(source)?.validate().map_err(|err| {
188 DeserializationError::InvalidValue(format!(
189 "library contains an invalid untrusted MAST forest: {err}"
190 ))
191 })
192 } else {
193 MastForest::read_from(source)
194 }
195 .map(Arc::new)
196 }
197}
198
199impl Serializable for Package {
200 fn write_into<W: ByteWriter>(&self, target: &mut W) {
201 self.write_header_into(target);
202
203 self.mast.write_into(target);
205
206 self.write_trailer_into(target);
207 }
208}
209
210struct PackageHeader {
211 name: PackageId,
212 version: crate::Version,
213 description: Option<String>,
214 kind: TargetType,
215}
216
217impl Package {
218 fn read_header_from<R: ByteReader>(
219 source: &mut R,
220 ) -> Result<PackageHeader, DeserializationError> {
221 let magic: [u8; 5] = source.read_array()?;
223 if magic != *MAGIC_PACKAGE {
224 return Err(DeserializationError::InvalidValue(format!(
225 "invalid magic bytes. Expected '{MAGIC_PACKAGE:?}', got '{magic:?}'"
226 )));
227 }
228
229 let version: [u8; 3] = source.read_array()?;
230 if version != VERSION {
231 return Err(DeserializationError::InvalidValue(format!(
232 "unsupported version. Got '{version:?}', but only '{VERSION:?}' is supported"
233 )));
234 }
235
236 let name = PackageId::read_from(source)?;
238
239 let version = String::read_from(source)?
241 .parse::<crate::Version>()
242 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
243
244 let description = Option::<String>::read_from(source)?;
246
247 let kind_tag = source.read_u8()?;
249 let kind = TargetType::try_from(kind_tag)
250 .map_err(|e| DeserializationError::InvalidValue(e.to_string()))?;
251
252 Ok(PackageHeader { name, version, description, kind })
253 }
254
255 fn read_from_with_header_and_mast<R: ByteReader>(
256 source: &mut R,
257 header: PackageHeader,
258 mast: Arc<MastForest>,
259 debug_sections_trusted: bool,
260 ) -> Result<Self, DeserializationError> {
261 let PackageHeader { name, version, description, kind } = header;
262
263 let manifest = PackageManifest::read_from_safe(source, &mast)?;
265
266 let mut sections = Vec::<Section>::read_from(source)?;
268 if !debug_sections_trusted && sections.iter().any(|section| section.id.is_debug()) {
269 log::warn!(
270 "Package read ignored debug sections from an untrusted artifact; use Package::read_from_trusted for local cache/debug reads"
271 );
272 sections.retain(|section| !section.id.is_debug());
273 }
274
275 let mut package = Self {
276 name,
277 version,
278 digest: Default::default(),
279 description,
280 kind,
281 mast,
282 manifest,
283 sections,
284 debug_sections_trusted,
285 };
286
287 package
288 .compute_interface_digest()
289 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
290 package.recompute_mast_commitment();
291
292 Ok(package)
293 }
294}
295
296impl Deserializable for Package {
297 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
298 let header = Self::read_header_from(source)?;
299
300 let mast = Self::read_mast_forest(source, true)?;
302
303 Self::read_from_with_header_and_mast(source, header, mast, false)
304 }
305
306 fn read_from_bytes(bytes: &[u8]) -> Result<Self, DeserializationError> {
307 let budget = bytes.len().saturating_mul(PACKAGE_BYTE_READ_BUDGET_MULTIPLIER);
308 let mut reader = BudgetedReader::new(SliceReader::new(bytes), budget);
309 Self::read_from(&mut reader)
310 }
311}
312
313#[cfg(feature = "serde")]
317impl serde::Serialize for PackageManifest {
318 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
319 where
320 S: serde::Serializer,
321 {
322 use alloc::collections::BTreeMap;
323
324 use miden_assembly_syntax::Path;
325 use serde::ser::SerializeStruct;
326
327 struct PackageExports<'a>(&'a BTreeMap<Arc<Path>, PackageExport>);
328
329 impl serde::Serialize for PackageExports<'_> {
330 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
331 where
332 S: serde::Serializer,
333 {
334 use serde::ser::SerializeSeq;
335
336 let mut serializer = serializer.serialize_seq(Some(self.0.len()))?;
337 for value in self.0.values() {
338 serializer.serialize_element(value)?;
339 }
340 serializer.end()
341 }
342 }
343
344 struct PackageModules<'a>(&'a BTreeMap<Arc<Path>, PackageModule>);
345
346 impl serde::Serialize for PackageModules<'_> {
347 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
348 where
349 S: serde::Serializer,
350 {
351 use serde::ser::SerializeSeq;
352
353 let mut serializer = serializer.serialize_seq(Some(self.0.len()))?;
354 for value in self.0.values() {
355 serializer.serialize_element(value)?;
356 }
357 serializer.end()
358 }
359 }
360
361 let mut serializer = serializer.serialize_struct("PackageManifest", 4)?;
362 serializer.serialize_field("exports", &PackageExports(&self.exports))?;
363 serializer.serialize_field("modules", &PackageModules(&self.modules))?;
364 serializer.serialize_field("dependencies", &self.dependencies)?;
365 serializer.serialize_field("entrypoint", &self.entrypoint)?;
366 serializer.end()
367 }
368}
369
370#[cfg(feature = "serde")]
371impl<'de> serde::Deserialize<'de> for PackageManifest {
372 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
373 where
374 D: serde::Deserializer<'de>,
375 {
376 #[derive(serde::Deserialize)]
377 #[serde(field_identifier, rename_all = "lowercase")]
378 enum Field {
379 Exports,
380 Modules,
381 Dependencies,
382 Entrypoint,
383 }
384
385 struct PackageManifestVisitor;
386
387 impl<'de> serde::de::Visitor<'de> for PackageManifestVisitor {
388 type Value = PackageManifest;
389
390 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
391 formatter.write_str("struct PackageManifest")
392 }
393
394 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
395 where
396 A: serde::de::SeqAccess<'de>,
397 {
398 let exports = seq
399 .next_element::<Vec<PackageExport>>()?
400 .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
401 let modules = seq
402 .next_element::<Vec<PackageModule>>()?
403 .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
404 let dependencies = seq
405 .next_element::<Vec<Dependency>>()?
406 .ok_or_else(|| serde::de::Error::invalid_length(2, &self))?;
407 let entrypoint = seq
408 .next_element::<Option<PathBuf>>()
409 .map(|p| p.map(|p| p.map(Arc::<ast::Path>::from)))?;
410 PackageManifest::new(exports)
411 .and_then(|manifest| manifest.with_modules(modules))
412 .and_then(|manifest| manifest.with_dependencies(dependencies))
413 .and_then(|manifest| {
414 if let Some(Some(entrypoint)) = entrypoint {
415 manifest.with_entrypoint(entrypoint)
416 } else {
417 Ok(manifest)
418 }
419 })
420 .map_err(serde::de::Error::custom)
421 }
422
423 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
424 where
425 A: serde::de::MapAccess<'de>,
426 {
427 let mut exports = None;
428 let mut modules = None;
429 let mut dependencies = None;
430 let mut entrypoint = None;
431 while let Some(key) = map.next_key()? {
432 match key {
433 Field::Exports => {
434 if exports.is_some() {
435 return Err(serde::de::Error::duplicate_field("exports"));
436 }
437 exports = Some(map.next_value::<Vec<PackageExport>>()?);
438 },
439 Field::Modules => {
440 if modules.is_some() {
441 return Err(serde::de::Error::duplicate_field("modules"));
442 }
443 modules = Some(map.next_value::<Vec<PackageModule>>()?);
444 },
445 Field::Dependencies => {
446 if dependencies.is_some() {
447 return Err(serde::de::Error::duplicate_field("dependencies"));
448 }
449 dependencies = Some(map.next_value::<Vec<Dependency>>()?);
450 },
451 Field::Entrypoint => {
452 if entrypoint.is_some() {
453 return Err(serde::de::Error::duplicate_field("entrypoint"));
454 }
455 entrypoint = Some(
456 map.next_value::<Option<PathBuf>>()
457 .map(|p| p.map(Arc::<ast::Path>::from))?,
458 );
459 },
460 }
461 }
462 let exports = exports.ok_or_else(|| serde::de::Error::missing_field("exports"))?;
463 let modules = modules.ok_or_else(|| serde::de::Error::missing_field("modules"))?;
464 let dependencies =
465 dependencies.ok_or_else(|| serde::de::Error::missing_field("dependencies"))?;
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(Some(entrypoint)) = entrypoint {
471 manifest.with_entrypoint(entrypoint)
472 } else {
473 Ok(manifest)
474 }
475 })
476 .map_err(serde::de::Error::custom)
477 }
478 }
479
480 deserializer.deserialize_struct(
481 "PackageManifest",
482 &["exports", "modules", "dependencies", "entrypoint"],
483 PackageManifestVisitor,
484 )
485 }
486}
487
488impl Serializable for PackageManifest {
489 fn write_into<W: ByteWriter>(&self, target: &mut W) {
490 target.write_usize(self.num_exports());
492 for export in self.exports() {
493 export.write_into(target);
494 }
495
496 target.write_usize(self.num_modules());
498 for module in self.modules() {
499 module.write_into(target);
500 }
501
502 target.write_usize(self.num_dependencies());
504 for dep in self.dependencies() {
505 dep.write_into(target);
506 }
507
508 if let Some(entrypoint) = self.entrypoint.as_ref() {
510 target.write_bool(true);
511 entrypoint.write_into(target);
512 } else {
513 target.write_bool(false);
514 }
515 }
516}
517
518impl PackageManifest {
519 pub fn read_from_safe<R: ByteReader>(
520 source: &mut R,
521 mast: &MastForest,
522 ) -> Result<Self, DeserializationError> {
523 let exports_len = source.read_usize()?;
525 let max_exports = source.max_alloc(PackageExport::min_serialized_size());
526 if exports_len > max_exports {
527 return Err(DeserializationError::InvalidValue(format!(
528 "requested {exports_len} elements but reader can provide at most {max_exports}"
529 )));
530 }
531 let mut exports = Vec::with_capacity(exports_len);
532 for _ in 0..exports_len {
533 exports.push(PackageExport::read_from_safe(source, mast)?);
534 }
535
536 let modules_len = source.read_usize()?;
538 let max_modules = source.max_alloc(PackageModule::min_serialized_size());
539 if modules_len > max_modules {
540 return Err(DeserializationError::InvalidValue(format!(
541 "requested {modules_len} elements but reader can provide at most {max_modules}"
542 )));
543 }
544 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
545
546 let dependencies = Vec::<Dependency>::read_from(source)?;
548
549 let entrypoint = if source.read_bool()? {
551 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
552 } else {
553 None
554 };
555
556 PackageManifest::new(exports)
557 .and_then(|manifest| manifest.with_modules(modules))
558 .and_then(|manifest| manifest.with_dependencies(dependencies))
559 .and_then(|manifest| {
560 if let Some(entrypoint) = entrypoint {
561 manifest.with_entrypoint(entrypoint)
562 } else {
563 Ok(manifest)
564 }
565 })
566 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
567 }
568}
569
570impl Deserializable for PackageManifest {
571 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
572 let exports_len = source.read_usize()?;
574 let exports = source.read_many_iter(exports_len)?.collect::<Result<Vec<_>, _>>()?;
575
576 let modules_len = source.read_usize()?;
578 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
579
580 let dependencies = Vec::<Dependency>::read_from(source)?;
582
583 let entrypoint = if source.read_bool()? {
585 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
586 } else {
587 None
588 };
589
590 PackageManifest::new(exports)
591 .and_then(|manifest| manifest.with_modules(modules))
592 .and_then(|manifest| manifest.with_dependencies(dependencies))
593 .and_then(|manifest| {
594 if let Some(entrypoint) = entrypoint {
595 manifest.with_entrypoint(entrypoint)
596 } else {
597 Ok(manifest)
598 }
599 })
600 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
601 }
602}
603
604impl Serializable for PackageModule {
608 fn write_into<W: ByteWriter>(&self, target: &mut W) {
609 self.path.write_into(target);
610 target.write_usize(self.submodules.len());
611 for submodule in self.submodules.iter() {
612 submodule.write_into(target);
613 }
614 }
615}
616
617impl Deserializable for PackageModule {
618 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
619 let path = PathBuf::read_from(source)?.into_boxed_path().into();
620 let submodules = Vec::<PackageSubmodule>::read_from(source)?;
621 Ok(Self { path, submodules })
622 }
623}
624
625impl Serializable for PackageSubmodule {
626 fn write_into<W: ByteWriter>(&self, target: &mut W) {
627 self.name.write_into(target);
628 }
629}
630
631impl Deserializable for PackageSubmodule {
632 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
633 let name = ast::Ident::read_from(source)?;
634 Ok(Self { name })
635 }
636}
637
638impl Serializable for PackageExport {
642 fn write_into<W: ByteWriter>(&self, target: &mut W) {
643 target.write_u8(self.tag());
644 match self {
645 Self::Procedure(export) => export.write_into(target),
646 Self::Constant(export) => export.write_into(target),
647 Self::Type(export) => export.write_into(target),
648 }
649 }
650}
651
652impl PackageExport {
653 pub fn read_from_safe<R: ByteReader>(
654 source: &mut R,
655 mast: &MastForest,
656 ) -> Result<Self, DeserializationError> {
657 match source.read_u8()? {
658 1 => ProcedureExport::read_from_safe(source, mast).map(Self::Procedure),
659 2 => ConstantExport::read_from(source).map(Self::Constant),
660 3 => TypeExport::read_from(source).map(Self::Type),
661 invalid => Err(DeserializationError::InvalidValue(format!(
662 "unexpected PackageExport tag: '{invalid}'"
663 ))),
664 }
665 }
666}
667
668impl Deserializable for PackageExport {
669 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
670 match source.read_u8()? {
671 1 => ProcedureExport::read_from(source).map(Self::Procedure),
672 2 => ConstantExport::read_from(source).map(Self::Constant),
673 3 => TypeExport::read_from(source).map(Self::Type),
674 invalid => Err(DeserializationError::InvalidValue(format!(
675 "unexpected PackageExport tag: '{invalid}'"
676 ))),
677 }
678 }
679}
680
681impl Serializable for ProcedureExport {
682 fn write_into<W: ByteWriter>(&self, target: &mut W) {
683 self.path.write_into(target);
684 if let Some(node_id) = self.node {
685 target.write_bool(true);
686 target.write_u32(node_id.into());
687 } else {
688 target.write_bool(false);
689 }
690 if let Some(source_node) = self.source_node {
691 target.write_bool(true);
692 source_node.write_into(target);
693 } else {
694 target.write_bool(false);
695 }
696 self.digest.write_into(target);
697 match self.signature.as_ref() {
698 Some(sig) => {
699 target.write_bool(true);
700 sig.write_into(target);
701 },
702 None => {
703 target.write_bool(false);
704 },
705 }
706 self.attributes.write_into(target);
707 }
708}
709
710impl ProcedureExport {
711 pub fn read_from_safe<R: ByteReader>(
712 source: &mut R,
713 mast: &MastForest,
714 ) -> Result<Self, DeserializationError> {
715 use miden_assembly_syntax::ast::types::FunctionType;
716 let path = PathBuf::read_from(source)?.into_boxed_path().into();
717 let node = if source.read_bool()? {
718 let node_id = MastNodeId::from_u32_safe(source.read_u32()?, mast)?;
719 if !mast.is_procedure_root(node_id) {
720 return Err(DeserializationError::InvalidValue(
721 ManifestValidationError::InvalidProcedureExport { path }.to_string(),
722 ));
723 }
724 Some(node_id)
725 } else {
726 None
727 };
728 let source_node = if source.read_bool()? {
729 Some(DebugSourceNodeId::read_from(source)?)
730 } else {
731 None
732 };
733 let digest = Word::read_from(source)?;
734 if let Some(node) = node
736 && digest != mast[node].digest()
737 {
738 return Err(DeserializationError::InvalidValue(
739 ManifestValidationError::InvalidProcedureExport { path }.to_string(),
740 ));
741 }
742 let signature = if source.read_bool()? {
743 Some(FunctionType::read_from(source)?)
744 } else {
745 None
746 };
747 let attributes = AttributeSet::read_from(source)?;
748 Ok(Self {
749 path,
750 node,
751 source_node,
752 digest,
753 signature,
754 attributes,
755 })
756 }
757}
758
759impl Deserializable for ProcedureExport {
760 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
761 use miden_assembly_syntax::ast::types::FunctionType;
762 let path = PathBuf::read_from(source)?.into_boxed_path().into();
763 let node = if source.read_bool()? {
764 Some(MastNodeId::new_unchecked(source.read_u32()?))
765 } else {
766 None
767 };
768 let source_node = if source.read_bool()? {
769 Some(DebugSourceNodeId::read_from(source)?)
770 } else {
771 None
772 };
773 let digest = Word::read_from(source)?;
774 let signature = if source.read_bool()? {
775 Some(FunctionType::read_from(source)?)
776 } else {
777 None
778 };
779 let attributes = AttributeSet::read_from(source)?;
780 Ok(Self {
781 path,
782 node,
783 source_node,
784 digest,
785 signature,
786 attributes,
787 })
788 }
789}
790
791impl Serializable for ConstantExport {
792 fn write_into<W: ByteWriter>(&self, target: &mut W) {
793 self.path.write_into(target);
794 self.value.write_into(target);
795 }
796}
797
798impl Deserializable for ConstantExport {
799 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
800 let path = PathBuf::read_from(source)?.into_boxed_path().into();
801 let value = ast::ConstantValue::read_from(source)?;
802 Ok(Self { path, value })
803 }
804}
805
806impl Serializable for TypeExport {
807 fn write_into<W: ByteWriter>(&self, target: &mut W) {
808 self.path.write_into(target);
809 self.ty.write_into(target);
810 }
811}
812
813impl Deserializable for TypeExport {
814 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
815 use miden_assembly_syntax::ast::types::Type;
816 let path = PathBuf::read_from(source)?.into_boxed_path().into();
817 let ty = Type::read_from(source)?;
818 Ok(Self { path, ty })
819 }
820}