sui_adapter_latest/static_programmable_transactions/linkage/
resolved_linkage.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    data_store::PackageStore,
6    static_programmable_transactions::linkage::{
7        config::ResolutionConfig,
8        resolution::{ResolutionTable, VersionConstraint},
9    },
10};
11use move_vm_runtime::shared::linkage_context::LinkageContext;
12use std::{borrow::Borrow, collections::BTreeMap, rc::Rc};
13use sui_types::{base_types::ObjectID, error::ExecutionErrorTrait};
14
15#[derive(Clone, Debug)]
16pub struct ExecutableLinkage(pub Rc<ResolvedLinkage>);
17
18impl ExecutableLinkage {
19    pub fn new(resolved_linkage: ResolvedLinkage) -> Self {
20        Self(Rc::new(resolved_linkage))
21    }
22
23    /// Given a list of object IDs, generate a `ResolvedLinkage` for them.
24    /// Since this linkage analysis should only be used for types, all packages are resolved
25    /// "upwards" (i.e., later versions of the package are preferred).
26    pub fn type_linkage<I, E>(
27        config: ResolutionConfig,
28        ids: I,
29        store: &dyn PackageStore,
30    ) -> Result<Self, E>
31    where
32        E: ExecutionErrorTrait,
33        I: IntoIterator,
34        I::Item: Borrow<ObjectID>,
35    {
36        let mut resolution_table = ResolutionTable::empty(config);
37        resolution_table.add_type_linkages_to_table(ids, store)?;
38        Ok(Self::new(ResolvedLinkage::from_resolution_table(
39            resolution_table,
40        )))
41    }
42
43    pub fn linkage_context<E: ExecutionErrorTrait>(&self) -> Result<LinkageContext, E> {
44        LinkageContext::new(self.0.linkage.iter().map(|(k, v)| (**k, **v)).collect()).map_err(|e| {
45            make_invariant_violation!(
46                "Failed to create linkage context from resolved linkage: {:?}",
47                e
48            )
49            .into()
50        })
51    }
52}
53
54#[derive(Debug)]
55pub struct ResolvedLinkage {
56    // A mapping of original package ID to its resolved version ID for that linkage.
57    pub linkage: BTreeMap<ObjectID, ObjectID>,
58    // A mapping of every package ID to its runtime ID.
59    // Note: Multiple packages can have the same runtime ID in this mapping, and domain of this map
60    // is a superset of range of `linkage`.
61    pub linkage_resolution: BTreeMap<ObjectID, ObjectID>,
62}
63
64impl ResolvedLinkage {
65    /// In the current linkage resolve an object ID to its original package ID.
66    pub fn resolve_to_original_id(&self, object_id: &ObjectID) -> Option<ObjectID> {
67        self.linkage_resolution.get(object_id).copied()
68    }
69
70    /// Create a `ResolvedLinkage` from a `ResolutionTable`.
71    pub(crate) fn from_resolution_table(resolution_table: ResolutionTable) -> Self {
72        let mut linkage = BTreeMap::new();
73        for (original_id, resolution) in resolution_table.resolution_table {
74            match resolution {
75                VersionConstraint::Exact(_version, object_id)
76                | VersionConstraint::AtLeast(_version, object_id) => {
77                    linkage.insert(original_id, object_id);
78                }
79            }
80        }
81        Self {
82            linkage,
83            linkage_resolution: resolution_table.all_versions_resolution_table,
84        }
85    }
86
87    /// We need to late-bind the "self" resolution since for publication and upgrade we don't know
88    /// this a priori when loading the PTB.
89    pub fn update_for_publication(
90        package_version_id: ObjectID,
91        original_package_id: ObjectID,
92        mut resolved_linkage: ResolvedLinkage,
93    ) -> ExecutableLinkage {
94        // original package ID maps to the link context (new package ID) in this context
95        resolved_linkage
96            .linkage
97            .insert(original_package_id, package_version_id);
98        // Add resolution from the new package ID to the original package ID.
99        resolved_linkage
100            .linkage_resolution
101            .insert(package_version_id, original_package_id);
102        ExecutableLinkage::new(resolved_linkage)
103    }
104}