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::ExecutionError};
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>(
27        config: ResolutionConfig,
28        ids: I,
29        store: &dyn PackageStore,
30    ) -> Result<Self, ExecutionError>
31    where
32        I: IntoIterator,
33        I::Item: Borrow<ObjectID>,
34    {
35        let mut resolution_table = ResolutionTable::empty(config);
36        resolution_table.add_type_linkages_to_table(ids, store)?;
37        Ok(Self::new(ResolvedLinkage::from_resolution_table(
38            resolution_table,
39        )))
40    }
41
42    pub fn linkage_context(&self) -> Result<LinkageContext, ExecutionError> {
43        LinkageContext::new(self.0.linkage.iter().map(|(k, v)| (**k, **v)).collect()).map_err(|e| {
44            make_invariant_violation!(
45                "Failed to create linkage context from resolved linkage: {:?}",
46                e
47            )
48        })
49    }
50}
51
52#[derive(Debug)]
53pub struct ResolvedLinkage {
54    // A mapping of original package ID to its resolved version ID for that linkage.
55    pub linkage: BTreeMap<ObjectID, ObjectID>,
56    // A mapping of every package ID to its runtime ID.
57    // Note: Multiple packages can have the same runtime ID in this mapping, and domain of this map
58    // is a superset of range of `linkage`.
59    pub linkage_resolution: BTreeMap<ObjectID, ObjectID>,
60}
61
62impl ResolvedLinkage {
63    /// In the current linkage resolve an object ID to its original package ID.
64    pub fn resolve_to_original_id(&self, object_id: &ObjectID) -> Option<ObjectID> {
65        self.linkage_resolution.get(object_id).copied()
66    }
67
68    /// Create a `ResolvedLinkage` from a `ResolutionTable`.
69    pub(crate) fn from_resolution_table(resolution_table: ResolutionTable) -> Self {
70        let mut linkage = BTreeMap::new();
71        for (original_id, resolution) in resolution_table.resolution_table {
72            match resolution {
73                VersionConstraint::Exact(_version, object_id)
74                | VersionConstraint::AtLeast(_version, object_id) => {
75                    linkage.insert(original_id, object_id);
76                }
77            }
78        }
79        Self {
80            linkage,
81            linkage_resolution: resolution_table.all_versions_resolution_table,
82        }
83    }
84
85    /// We need to late-bind the "self" resolution since for publication and upgrade we don't know
86    /// this a priori when loading the PTB.
87    pub fn update_for_publication(
88        package_version_id: ObjectID,
89        original_package_id: ObjectID,
90        mut resolved_linkage: ResolvedLinkage,
91    ) -> ExecutableLinkage {
92        // original package ID maps to the link context (new package ID) in this context
93        resolved_linkage
94            .linkage
95            .insert(original_package_id, package_version_id);
96        // Add resolution from the new package ID to the original package ID.
97        resolved_linkage
98            .linkage_resolution
99            .insert(package_version_id, original_package_id);
100        ExecutableLinkage::new(resolved_linkage)
101    }
102}