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 mut package = Self {
251 name,
252 version,
253 mast_forest_commitment: Default::default(),
254 description,
255 kind,
256 mast,
257 manifest,
258 sections,
259 debug_sections_trusted: true,
260 };
261
262 if validate_debug_sections {
263 package.debug_info().map_err(|err| {
264 DeserializationError::InvalidValue(format!(
265 "package contains invalid debug information: {err}"
266 ))
267 })?;
268 }
269
270 if validate_manifest {
271 package
272 .compute_interface_commitment()
273 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
274 }
275 package.recompute_mast_commitment();
276
277 Ok(package)
278 }
279}
280
281impl Deserializable for Package {
282 #[track_caller]
290 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
291 let header = Self::read_header_from(source)?;
292
293 let mast = Self::read_mast_forest(source, true)?;
295
296 Self::read_from_with_header_and_mast(source, header, mast, true, true)
297 }
298
299 #[track_caller]
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
313impl Serializable for PackageManifest {
317 fn write_into<W: ByteWriter>(&self, target: &mut W) {
318 target.write_usize(self.num_exports());
320 for export in self.exports() {
321 export.write_into(target);
322 }
323
324 target.write_usize(self.num_modules());
326 for module in self.modules() {
327 module.write_into(target);
328 }
329
330 target.write_usize(self.num_dependencies());
332 for dep in self.dependencies() {
333 dep.write_into(target);
334 }
335
336 if let Some(entrypoint) = self.entrypoint.as_ref() {
338 target.write_bool(true);
339 entrypoint.write_into(target);
340 } else {
341 target.write_bool(false);
342 }
343 }
344}
345
346impl PackageManifest {
347 pub fn read_from_trusted<R: ByteReader>(
348 source: &mut R,
349 mast: &MastForest,
350 ) -> Result<Self, DeserializationError> {
351 let exports_len = source.read_usize()?;
353 let max_exports = source.max_alloc(PackageExport::min_serialized_size());
354 if exports_len > max_exports {
355 return Err(DeserializationError::InvalidValue(format!(
356 "requested {exports_len} elements but reader can provide at most {max_exports}"
357 )));
358 }
359 let mut exports = Vec::with_capacity(exports_len);
360 for _ in 0..exports_len {
361 exports.push(PackageExport::read_from_trusted(source, mast)?);
362 }
363
364 let modules_len = source.read_usize()?;
366 let max_modules = source.max_alloc(PackageModule::min_serialized_size());
367 if modules_len > max_modules {
368 return Err(DeserializationError::InvalidValue(format!(
369 "requested {modules_len} elements but reader can provide at most {max_modules}"
370 )));
371 }
372 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
373
374 let dependencies = Vec::<Dependency>::read_from(source)?;
376
377 let entrypoint = if source.read_bool()? {
379 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
380 } else {
381 None
382 };
383
384 PackageManifest::new(exports)
385 .and_then(|manifest| manifest.with_modules(modules))
386 .and_then(|manifest| manifest.with_dependencies(dependencies))
387 .and_then(|manifest| {
388 if let Some(entrypoint) = entrypoint {
389 manifest.with_entrypoint(entrypoint)
390 } else {
391 Ok(manifest)
392 }
393 })
394 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
395 }
396
397 pub fn read_from_safe<R: ByteReader>(
398 source: &mut R,
399 mast: &MastForest,
400 ) -> Result<Self, DeserializationError> {
401 let exports_len = source.read_usize()?;
403 let max_exports = source.max_alloc(PackageExport::min_serialized_size());
404 if exports_len > max_exports {
405 return Err(DeserializationError::InvalidValue(format!(
406 "requested {exports_len} elements but reader can provide at most {max_exports}"
407 )));
408 }
409 let mut exports = Vec::with_capacity(exports_len);
410 for _ in 0..exports_len {
411 exports.push(PackageExport::read_from_safe(source, mast)?);
412 }
413
414 let modules_len = source.read_usize()?;
416 let max_modules = source.max_alloc(PackageModule::min_serialized_size());
417 if modules_len > max_modules {
418 return Err(DeserializationError::InvalidValue(format!(
419 "requested {modules_len} elements but reader can provide at most {max_modules}"
420 )));
421 }
422 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
423
424 let dependencies = Vec::<Dependency>::read_from(source)?;
426
427 let entrypoint = if source.read_bool()? {
429 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
430 } else {
431 None
432 };
433
434 PackageManifest::new(exports)
435 .and_then(|manifest| manifest.with_modules(modules))
436 .and_then(|manifest| manifest.with_dependencies(dependencies))
437 .and_then(|manifest| {
438 if let Some(entrypoint) = entrypoint {
439 manifest.with_entrypoint(entrypoint)
440 } else {
441 Ok(manifest)
442 }
443 })
444 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
445 }
446}
447
448impl Deserializable for PackageManifest {
449 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
450 let exports_len = source.read_usize()?;
452 let exports = source.read_many_iter(exports_len)?.collect::<Result<Vec<_>, _>>()?;
453
454 let modules_len = source.read_usize()?;
456 let modules = source.read_many_iter(modules_len)?.collect::<Result<Vec<_>, _>>()?;
457
458 let dependencies = Vec::<Dependency>::read_from(source)?;
460
461 let entrypoint = if source.read_bool()? {
463 Some(PathBuf::read_from(source).map(Arc::<ast::Path>::from)?)
464 } else {
465 None
466 };
467
468 PackageManifest::new(exports)
469 .and_then(|manifest| manifest.with_modules(modules))
470 .and_then(|manifest| manifest.with_dependencies(dependencies))
471 .and_then(|manifest| {
472 if let Some(entrypoint) = entrypoint {
473 manifest.with_entrypoint(entrypoint)
474 } else {
475 Ok(manifest)
476 }
477 })
478 .map_err(|error| DeserializationError::InvalidValue(error.to_string()))
479 }
480}
481
482impl Serializable for PackageModule {
486 fn write_into<W: ByteWriter>(&self, target: &mut W) {
487 self.path.write_into(target);
488 target.write_usize(self.submodules.len());
489 for submodule in self.submodules.iter() {
490 submodule.write_into(target);
491 }
492 }
493}
494
495impl Deserializable for PackageModule {
496 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
497 let path = PathBuf::read_from(source)?.into_boxed_path().into();
498 let submodules = Vec::<PackageSubmodule>::read_from(source)?;
499 Ok(Self { path, submodules })
500 }
501}
502
503impl Serializable for PackageSubmodule {
504 fn write_into<W: ByteWriter>(&self, target: &mut W) {
505 self.name.write_into(target);
506 }
507}
508
509impl Deserializable for PackageSubmodule {
510 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
511 let name = ast::Ident::read_from(source)?;
512 Ok(Self { name })
513 }
514}
515
516impl Serializable for PackageExport {
520 fn write_into<W: ByteWriter>(&self, target: &mut W) {
521 target.write_u8(self.tag());
522 match self {
523 Self::Procedure(export) => export.write_into(target),
524 Self::Constant(export) => export.write_into(target),
525 Self::Type(export) => export.write_into(target),
526 }
527 }
528}
529
530impl PackageExport {
531 pub fn read_from_trusted<R: ByteReader>(
532 source: &mut R,
533 mast: &MastForest,
534 ) -> Result<Self, DeserializationError> {
535 match source.read_u8()? {
536 1 => ProcedureExport::read_from_trusted(source, mast).map(Self::Procedure),
537 2 => ConstantExport::read_from(source).map(Self::Constant),
538 3 => TypeExport::read_from(source).map(Self::Type),
539 invalid => Err(DeserializationError::InvalidValue(format!(
540 "unexpected PackageExport tag: '{invalid}'"
541 ))),
542 }
543 }
544
545 pub fn read_from_safe<R: ByteReader>(
546 source: &mut R,
547 mast: &MastForest,
548 ) -> Result<Self, DeserializationError> {
549 match source.read_u8()? {
550 1 => ProcedureExport::read_from_safe(source, mast).map(Self::Procedure),
551 2 => ConstantExport::read_from(source).map(Self::Constant),
552 3 => TypeExport::read_from(source).map(Self::Type),
553 invalid => Err(DeserializationError::InvalidValue(format!(
554 "unexpected PackageExport tag: '{invalid}'"
555 ))),
556 }
557 }
558}
559
560impl Deserializable for PackageExport {
561 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
562 match source.read_u8()? {
563 1 => ProcedureExport::read_from(source).map(Self::Procedure),
564 2 => ConstantExport::read_from(source).map(Self::Constant),
565 3 => TypeExport::read_from(source).map(Self::Type),
566 invalid => Err(DeserializationError::InvalidValue(format!(
567 "unexpected PackageExport tag: '{invalid}'"
568 ))),
569 }
570 }
571}
572
573impl Serializable for ProcedureExport {
574 fn write_into<W: ByteWriter>(&self, target: &mut W) {
575 self.path.write_into(target);
576 if let Some(node_id) = self.node {
577 target.write_bool(true);
578 target.write_u32(node_id.into());
579 } else {
580 target.write_bool(false);
581 }
582 if let Some(source_node) = self.source_node {
583 target.write_bool(true);
584 source_node.write_into(target);
585 } else {
586 target.write_bool(false);
587 }
588 self.digest.write_into(target);
589 match self.signature.as_ref() {
590 Some(sig) => {
591 target.write_bool(true);
592 sig.write_into(target);
593 },
594 None => {
595 target.write_bool(false);
596 },
597 }
598 self.attributes.write_into(target);
599 }
600}
601
602impl ProcedureExport {
603 pub fn read_from_trusted<R: ByteReader>(
604 source: &mut R,
605 mast: &MastForest,
606 ) -> Result<Self, DeserializationError> {
607 use miden_assembly_syntax::ast::types::FunctionType;
608 let path = PathBuf::read_from(source)?.into_boxed_path().into();
609 let node = if source.read_bool()? {
610 Some(MastNodeId::from_u32_safe(source.read_u32()?, mast)?)
611 } else {
612 None
613 };
614 let source_node = if source.read_bool()? {
615 Some(DebugSourceNodeId::read_from(source)?)
616 } else {
617 None
618 };
619 let digest = Word::read_from(source)?;
620 let signature = if source.read_bool()? {
621 Some(FunctionType::read_from(source)?)
622 } else {
623 None
624 };
625 let attributes = AttributeSet::read_from(source)?;
626 Ok(Self {
627 path,
628 node,
629 source_node,
630 digest,
631 signature,
632 attributes,
633 })
634 }
635
636 pub fn read_from_safe<R: ByteReader>(
637 source: &mut R,
638 mast: &MastForest,
639 ) -> Result<Self, DeserializationError> {
640 use miden_assembly_syntax::ast::types::FunctionType;
641 let path = PathBuf::read_from(source)?.into_boxed_path().into();
642 let node = if source.read_bool()? {
643 let node_id = MastNodeId::from_u32_safe(source.read_u32()?, mast)?;
644 if !mast.is_procedure_root(node_id) {
645 return Err(DeserializationError::InvalidValue(
646 ManifestValidationError::InvalidProcedureExport { path }.to_string(),
647 ));
648 }
649 Some(node_id)
650 } else {
651 None
652 };
653 let source_node = if source.read_bool()? {
654 Some(DebugSourceNodeId::read_from(source)?)
655 } else {
656 None
657 };
658 let digest = Word::read_from(source)?;
659 if let Some(node) = node
661 && digest != mast[node].digest()
662 {
663 return Err(DeserializationError::InvalidValue(
664 ManifestValidationError::InvalidProcedureExport { path }.to_string(),
665 ));
666 }
667 let signature = if source.read_bool()? {
668 Some(FunctionType::read_from(source)?)
669 } else {
670 None
671 };
672 let attributes = AttributeSet::read_from(source)?;
673 Ok(Self {
674 path,
675 node,
676 source_node,
677 digest,
678 signature,
679 attributes,
680 })
681 }
682}
683
684impl Deserializable for ProcedureExport {
685 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
686 use miden_assembly_syntax::ast::types::FunctionType;
687 let path = PathBuf::read_from(source)?.into_boxed_path().into();
688 let node = if source.read_bool()? {
689 Some(MastNodeId::new_unchecked(source.read_u32()?))
690 } else {
691 None
692 };
693 let source_node = if source.read_bool()? {
694 Some(DebugSourceNodeId::read_from(source)?)
695 } else {
696 None
697 };
698 let digest = Word::read_from(source)?;
699 let signature = if source.read_bool()? {
700 Some(FunctionType::read_from(source)?)
701 } else {
702 None
703 };
704 let attributes = AttributeSet::read_from(source)?;
705 Ok(Self {
706 path,
707 node,
708 source_node,
709 digest,
710 signature,
711 attributes,
712 })
713 }
714}
715
716impl Serializable for ConstantExport {
717 fn write_into<W: ByteWriter>(&self, target: &mut W) {
718 self.path.write_into(target);
719 self.value.write_into(target);
720 }
721}
722
723impl Deserializable for ConstantExport {
724 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
725 let path = PathBuf::read_from(source)?.into_boxed_path().into();
726 let value = ast::ConstantValue::read_from(source)?;
727 Ok(Self { path, value })
728 }
729}
730
731impl Serializable for TypeExport {
732 fn write_into<W: ByteWriter>(&self, target: &mut W) {
733 self.path.write_into(target);
734 self.ty.write_into(target);
735 }
736}
737
738impl Deserializable for TypeExport {
739 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
740 use miden_assembly_syntax::ast::types::Type;
741 let path = PathBuf::read_from(source)?.into_boxed_path().into();
742 let ty = Type::read_from(source)?;
743 Ok(Self { path, ty })
744 }
745}