sui_adapter_latest/static_programmable_transactions/linkage/
config.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{collections::BTreeMap, rc::Rc, sync::Arc};
5
6use crate::{
7    data_store::PackageStore,
8    static_programmable_transactions::linkage::resolution::{
9        ResolutionTable, VersionConstraint, add_and_unify,
10    },
11};
12use move_binary_format::binary_config::BinaryConfig;
13use move_vm_runtime::{
14    shared::types::{OriginalId, VersionId},
15    validation::verification::ast::Package as VerifiedPackage,
16};
17use sui_protocol_config::Amendments;
18use sui_types::{
19    MOVE_STDLIB_PACKAGE_ID, SUI_FRAMEWORK_PACKAGE_ID, SUI_SYSTEM_PACKAGE_ID, base_types::ObjectID,
20    error::ExecutionError,
21};
22
23/// These are the set of native packages in Sui -- importantly they can be used implicitly by
24/// different parts of the system and are not required to be explicitly imported always.
25/// Additionally, there is no versioning concerns around these as they are "stable" for a given
26/// epoch, and are the special packages that are always available, and updated in-place.
27const NATIVE_PACKAGE_IDS: &[ObjectID] = &[
28    SUI_FRAMEWORK_PACKAGE_ID,
29    SUI_SYSTEM_PACKAGE_ID,
30    MOVE_STDLIB_PACKAGE_ID,
31];
32
33/// Metadata and shared operations for the PTB linkage analysis.
34#[derive(Debug)]
35pub struct ResolutionConfig_ {
36    /// Config to use for the linkage analysis.
37    linkage_config: LinkageConfig,
38    /// Config to use for the binary analysis (needed for deserialization to determine if a
39    /// function is a non-public entry function).
40    binary_config: BinaryConfig,
41}
42
43#[derive(Debug, Clone)]
44pub struct ResolutionConfig(Rc<ResolutionConfig_>);
45
46/// Configuration for the linkage analysis.
47#[derive(Debug, Clone)]
48pub struct LinkageConfig {
49    /// Whether system packages should always be included as a member in the generated linkage.
50    /// This is almost always true except for system transactions and genesis transactions.
51    pub always_include_system_packages: bool,
52    /// If special amendments should be included in the generated linkage.
53    pub include_special_amendments: Option<Arc<Amendments>>,
54}
55
56impl ResolutionConfig {
57    pub fn new(linkage_config: LinkageConfig, binary_config: BinaryConfig) -> Self {
58        Self(Rc::new(ResolutionConfig_ {
59            linkage_config,
60            binary_config,
61        }))
62    }
63
64    pub fn linkage_config(&self) -> &LinkageConfig {
65        &self.0.linkage_config
66    }
67
68    pub fn binary_config(&self) -> &BinaryConfig {
69        &self.0.binary_config
70    }
71
72    pub(crate) fn resolution_table_with_native_packages(
73        &self,
74        store: &dyn PackageStore,
75    ) -> Result<ResolutionTable, ExecutionError> {
76        let mut resolution_table = ResolutionTable::empty(self.clone());
77        if self.0.linkage_config.always_include_system_packages {
78            for id in NATIVE_PACKAGE_IDS {
79                #[cfg(debug_assertions)]
80                {
81                    use crate::static_programmable_transactions::linkage::resolution::get_package;
82                    let package = get_package(id, store)?;
83                    debug_assert_eq!(package.version_id(), **id);
84                    debug_assert_eq!(package.original_id(), **id);
85                }
86                add_and_unify(id, store, &mut resolution_table, VersionConstraint::exact)?;
87            }
88        }
89
90        Ok(resolution_table)
91    }
92
93    pub(crate) fn linkage_table(&self, pkg: &VerifiedPackage) -> BTreeMap<OriginalId, VersionId> {
94        let linkage_table = pkg.linkage_table().clone();
95        self.linkage_config()
96            .apply_linkage_amendments(pkg.version_id(), linkage_table)
97    }
98}
99
100impl LinkageConfig {
101    pub fn new(
102        include_special_amendments: Option<Arc<Amendments>>,
103        always_include_system_packages: bool,
104    ) -> Self {
105        Self {
106            include_special_amendments,
107            always_include_system_packages,
108        }
109    }
110
111    fn apply_linkage_amendments(
112        &self,
113        root: VersionId,
114        mut linkage: BTreeMap<OriginalId, VersionId>,
115    ) -> BTreeMap<OriginalId, VersionId> {
116        let Some(amendments) = &self.include_special_amendments else {
117            return linkage;
118        };
119
120        if let Some(amendments_for_root) = amendments.get(&root) {
121            for (orig_id, upgraded_id) in amendments_for_root.iter() {
122                // Upgrade linkage. This can either an insert or override.
123                linkage.insert(*orig_id, *upgraded_id);
124            }
125        }
126        linkage
127    }
128}