sui_adapter_latest/data_store/
transaction_package_store.rs1use indexmap::IndexMap;
5use move_core_types::{
6 account_address::AccountAddress,
7 resolver::{ModuleResolver, SerializedPackage},
8};
9use move_vm_runtime::{
10 shared::types::VersionId, validation::verification::ast::Package as VerifiedPackage,
11};
12use std::{cell::RefCell, rc::Rc, sync::Arc};
13use sui_types::{
14 base_types::ObjectID,
15 error::{ExecutionError, SuiError, SuiResult},
16 move_package::MovePackage,
17 storage::BackingPackageStore,
18};
19
20#[allow(clippy::type_complexity)]
26pub struct TransactionPackageStore<'a> {
27 package_store: &'a dyn BackingPackageStore,
28
29 new_packages: RefCell<IndexMap<ObjectID, (Rc<MovePackage>, Arc<VerifiedPackage>)>>,
33
34 package_cache: RefCell<IndexMap<ObjectID, Option<Rc<MovePackage>>>>,
37}
38
39impl<'a> TransactionPackageStore<'a> {
40 pub fn new(package_store: &'a dyn BackingPackageStore) -> Self {
41 Self {
42 package_store,
43 new_packages: RefCell::new(IndexMap::new()),
44 package_cache: RefCell::new(IndexMap::new()),
45 }
46 }
47
48 pub fn push_package(
51 &self,
52 id: ObjectID,
53 package: Rc<MovePackage>,
54 verified_package: VerifiedPackage,
55 ) -> Result<(), ExecutionError> {
56 debug_assert!(!self.new_packages.borrow().contains_key(&id));
58
59 if self
62 .new_packages
63 .borrow_mut()
64 .insert(id, (package, Arc::new(verified_package)))
65 .is_some()
66 {
67 invariant_violation!(
68 "Package with ID {} already exists in the new packages. This should never happen.",
69 id
70 );
71 }
72
73 Ok(())
74 }
75
76 pub fn pop_package(&self, id: ObjectID) -> Result<Arc<VerifiedPackage>, ExecutionError> {
82 if self
83 .new_packages
84 .borrow()
85 .last()
86 .is_none_or(|(pkg_id, _)| *pkg_id != id)
87 {
88 make_invariant_violation!(
89 "Tried to pop package {} from new packages, but new packages was empty or \
90 it is not the most recent package inserted. This should never happen.",
91 id
92 );
93 }
94
95 let Some((pkg_id, (_move_pkg, verified_pkg))) = self.new_packages.borrow_mut().pop() else {
96 unreachable!(
97 "We just checked that new packages is not empty, so this should never happen."
98 );
99 };
100 assert_eq!(
101 pkg_id, id,
102 "Popped package ID {} does not match requested ID {}. This should never happen as was checked above.",
103 pkg_id, id
104 );
105
106 Ok(verified_pkg)
107 }
108
109 pub fn fetch_new_package(
112 &self,
113 id: &ObjectID,
114 ) -> Option<(Rc<MovePackage>, Arc<VerifiedPackage>)> {
115 self.new_packages.borrow().get(id).cloned()
116 }
117
118 pub fn to_new_packages(&self) -> Vec<MovePackage> {
120 self.new_packages
121 .borrow()
122 .iter()
123 .map(|(_, (move_pkg, _))| move_pkg.as_ref().clone())
124 .collect()
125 }
126
127 pub fn fetch_move_package(
131 &self,
132 package_version_id: VersionId,
133 ) -> SuiResult<Option<Rc<MovePackage>>> {
134 if let Some((move_pkg, _verified_pkg)) = self.fetch_new_package(&package_version_id.into())
135 {
136 return Ok(Some(move_pkg));
137 }
138
139 if let Some(cached_pkg) = self
140 .package_cache
141 .borrow()
142 .get(&ObjectID::from(package_version_id))
143 {
144 return Ok(cached_pkg.clone());
145 }
146
147 let move_package = self
148 .package_store
149 .get_package_object(&package_version_id.into())?
150 .map(|pkg| Rc::new(pkg.move_package().clone()));
151
152 self.package_cache
153 .borrow_mut()
154 .insert(package_version_id.into(), move_package.clone());
155
156 Ok(move_package)
157 }
158
159 fn fetch_package(&self, package_version_id: VersionId) -> SuiResult<Option<SerializedPackage>> {
163 self.fetch_move_package(package_version_id)
164 .and_then(|opt_pkg| {
165 opt_pkg
166 .as_ref()
167 .map(|pkg| pkg.as_ref().into_serialized_move_package())
168 .transpose()
169 })
170 }
171}
172
173impl ModuleResolver for TransactionPackageStore<'_> {
175 type Error = SuiError;
176 fn get_packages_static<const N: usize>(
177 &self,
178 ids: [AccountAddress; N],
179 ) -> Result<[Option<SerializedPackage>; N], Self::Error> {
180 let mut packages = [const { None }; N];
183 for (i, id) in ids.iter().enumerate() {
184 packages[i] = self.fetch_package(*id)?;
185 }
186
187 Ok(packages)
188 }
189
190 fn get_packages<'a>(
191 &self,
192 ids: impl ExactSizeIterator<Item = &'a AccountAddress>,
193 ) -> Result<Vec<Option<SerializedPackage>>, Self::Error> {
194 ids.map(|id| self.fetch_package(*id)).collect()
195 }
196}