Skip to main content

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::{PackageMetadata, 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::shared::types::{OriginalId, VersionId};
14use sui_protocol_config::Amendments;
15use sui_types::{
16    MOVE_STDLIB_PACKAGE_ID, SUI_FRAMEWORK_PACKAGE_ID, SUI_SYSTEM_PACKAGE_ID, base_types::ObjectID,
17    error::ExecutionErrorTrait,
18};
19
20/// These are the set of native packages in Sui -- importantly they can be used implicitly by
21/// different parts of the system and are not required to be explicitly imported always.
22/// Additionally, there is no versioning concerns around these as they are "stable" for a given
23/// epoch, and are the special packages that are always available, and updated in-place.
24const NATIVE_PACKAGE_IDS: &[ObjectID] = &[
25    SUI_FRAMEWORK_PACKAGE_ID,
26    SUI_SYSTEM_PACKAGE_ID,
27    MOVE_STDLIB_PACKAGE_ID,
28];
29
30/// Metadata and shared operations for the PTB linkage analysis.
31#[derive(Debug)]
32pub struct ResolutionConfig_ {
33    /// Config to use for the linkage analysis.
34    linkage_config: LinkageConfig,
35    /// Config to use for the binary analysis (needed for deserialization to determine if a
36    /// function is a non-public entry function).
37    binary_config: BinaryConfig,
38}
39
40#[derive(Debug, Clone)]
41pub struct ResolutionConfig(Rc<ResolutionConfig_>);
42
43/// Configuration for the linkage analysis.
44#[derive(Debug, Clone)]
45pub struct LinkageConfig {
46    /// Whether system packages should always be included as a member in the generated linkage.
47    /// This is almost always true except for system transactions and genesis transactions.
48    pub always_include_system_packages: bool,
49    /// If special amendments should be included in the generated linkage.
50    pub include_special_amendments: Option<Arc<Amendments>>,
51}
52
53impl ResolutionConfig {
54    pub fn new(linkage_config: LinkageConfig, binary_config: BinaryConfig) -> Self {
55        Self(Rc::new(ResolutionConfig_ {
56            linkage_config,
57            binary_config,
58        }))
59    }
60
61    pub fn linkage_config(&self) -> &LinkageConfig {
62        &self.0.linkage_config
63    }
64
65    pub fn binary_config(&self) -> &BinaryConfig {
66        &self.0.binary_config
67    }
68
69    pub(crate) fn resolution_table_with_native_packages<
70        E: ExecutionErrorTrait,
71        S: PackageStore + ?Sized,
72    >(
73        &self,
74        store: &S,
75    ) -> Result<ResolutionTable, E> {
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<P: PackageMetadata>(
94        &self,
95        pkg: &P,
96    ) -> BTreeMap<OriginalId, VersionId> {
97        self.linkage_config()
98            .apply_linkage_amendments(*pkg.version_id(), pkg.linkage_table())
99    }
100}
101
102impl LinkageConfig {
103    pub fn new(
104        include_special_amendments: Option<Arc<Amendments>>,
105        always_include_system_packages: bool,
106    ) -> Self {
107        Self {
108            include_special_amendments,
109            always_include_system_packages,
110        }
111    }
112
113    fn apply_linkage_amendments(
114        &self,
115        root: VersionId,
116        mut linkage: BTreeMap<OriginalId, VersionId>,
117    ) -> BTreeMap<OriginalId, VersionId> {
118        let Some(amendments) = &self.include_special_amendments else {
119            return linkage;
120        };
121
122        if let Some(amendments_for_root) = amendments.get(&root) {
123            for (orig_id, upgraded_id) in amendments_for_root.iter() {
124                // Upgrade linkage. This can either an insert or override.
125                linkage.insert(*orig_id, *upgraded_id);
126            }
127        }
128        linkage
129    }
130}