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::resolution::{
7        ResolutionTable, VersionConstraint, add_and_unify, get_package,
8    },
9};
10use move_core_types::account_address::AccountAddress;
11use std::{collections::BTreeMap, rc::Rc};
12use sui_types::{base_types::ObjectID, error::ExecutionError};
13
14#[derive(Clone, Debug)]
15pub struct RootedLinkage {
16    pub link_context: AccountAddress,
17    pub resolved_linkage: Rc<ResolvedLinkage>,
18}
19
20impl RootedLinkage {
21    pub fn new(link_context: AccountAddress, resolved_linkage: ResolvedLinkage) -> RootedLinkage {
22        Self {
23            link_context,
24            resolved_linkage: Rc::new(resolved_linkage),
25        }
26    }
27
28    /// We need to late-bind the "self" resolution since for publication and upgrade we don't know
29    /// this a priori when loading the PTB.
30    pub fn new_for_publication(
31        link_context: ObjectID,
32        original_package_id: ObjectID,
33        mut resolved_linkage: ResolvedLinkage,
34    ) -> RootedLinkage {
35        // original package ID maps to the link context (new package ID) in this context
36        resolved_linkage
37            .linkage
38            .insert(original_package_id, link_context);
39        // Add resolution from the new package ID to the original package ID.
40        resolved_linkage
41            .linkage_resolution
42            .insert(link_context, original_package_id);
43        let resolved_linkage = Rc::new(resolved_linkage);
44        Self {
45            link_context: *link_context,
46            resolved_linkage,
47        }
48    }
49}
50
51#[derive(Debug)]
52pub struct ResolvedLinkage {
53    pub linkage: BTreeMap<ObjectID, ObjectID>,
54    // A mapping of every package ID to its runtime ID.
55    // Note: Multiple packages can have the same runtime ID in this mapping, and domain of this map
56    // is a superset of range of `linkage`.
57    pub linkage_resolution: BTreeMap<ObjectID, ObjectID>,
58}
59
60impl ResolvedLinkage {
61    /// In the current linkage resolve an object ID to its original package ID.
62    pub fn resolve_to_original_id(&self, object_id: &ObjectID) -> Option<ObjectID> {
63        self.linkage_resolution.get(object_id).copied()
64    }
65
66    /// Given a list of object IDs, generate a `ResolvedLinkage` for them.
67    /// Since this linkage analysis should only be used for types, all packages are resolved
68    /// "upwards" (i.e., later versions of the package are preferred).
69    pub fn type_linkage(
70        ids: &[ObjectID],
71        store: &dyn PackageStore,
72    ) -> Result<Self, ExecutionError> {
73        let mut resolution_table = ResolutionTable::empty();
74        for id in ids {
75            let pkg = get_package(id, store)?;
76            let transitive_deps = pkg
77                .linkage_table()
78                .values()
79                .map(|info| info.upgraded_id)
80                .collect::<Vec<_>>();
81            let package_id = pkg.id();
82            add_and_unify(
83                &package_id,
84                store,
85                &mut resolution_table,
86                VersionConstraint::at_least,
87            )?;
88            for object_id in transitive_deps.iter() {
89                add_and_unify(
90                    object_id,
91                    store,
92                    &mut resolution_table,
93                    VersionConstraint::at_least,
94                )?;
95            }
96        }
97
98        Ok(ResolvedLinkage::from_resolution_table(resolution_table))
99    }
100
101    /// Create a `ResolvedLinkage` from a `ResolutionTable`.
102    pub(crate) fn from_resolution_table(resolution_table: ResolutionTable) -> Self {
103        let mut linkage = BTreeMap::new();
104        for (original_id, resolution) in resolution_table.resolution_table {
105            match resolution {
106                VersionConstraint::Exact(_version, object_id)
107                | VersionConstraint::AtLeast(_version, object_id) => {
108                    linkage.insert(original_id, object_id);
109                }
110            }
111        }
112        Self {
113            linkage,
114            linkage_resolution: resolution_table.all_versions_resolution_table,
115        }
116    }
117}