1use move_binary_format::normalized;
5use move_binary_format::{
6 CompiledModule, binary_config::BinaryConfig, compatibility::Compatibility,
7};
8use move_core_types::gas_algebra::InternalGas;
9use serde::{Deserialize, Serialize};
10use std::fmt::Formatter;
11use std::sync::LazyLock;
12use sui_types::base_types::ObjectRef;
13use sui_types::storage::ObjectStore;
14use sui_types::{BRIDGE_PACKAGE_ID, DEEPBOOK_PACKAGE_ID};
15use sui_types::{
16 MOVE_STDLIB_PACKAGE_ID, SUI_FRAMEWORK_PACKAGE_ID, SUI_SYSTEM_PACKAGE_ID,
17 base_types::ObjectID,
18 digests::TransactionDigest,
19 move_package::MovePackage,
20 object::{OBJECT_START_VERSION, Object},
21};
22use tracing::error;
23
24pub struct SystemPackageMetadata {
26 pub name: String,
28 pub path: String,
30 pub compiled: SystemPackage,
32}
33
34#[derive(Clone, Serialize, PartialEq, Eq, Deserialize)]
37pub struct SystemPackage {
38 pub id: ObjectID,
39 pub bytes: Vec<Vec<u8>>,
40 pub dependencies: Vec<ObjectID>,
41}
42
43impl SystemPackageMetadata {
44 pub fn new(
45 name: impl ToString,
46 path: impl ToString,
47 id: ObjectID,
48 raw_bytes: &'static [u8],
49 dependencies: &[ObjectID],
50 ) -> Self {
51 SystemPackageMetadata {
52 name: name.to_string(),
53 path: path.to_string(),
54 compiled: SystemPackage::new(id, raw_bytes, dependencies),
55 }
56 }
57}
58
59impl SystemPackage {
60 pub fn new(id: ObjectID, raw_bytes: &'static [u8], dependencies: &[ObjectID]) -> Self {
61 let bytes: Vec<Vec<u8>> = bcs::from_bytes(raw_bytes).unwrap();
62 Self {
63 id,
64 bytes,
65 dependencies: dependencies.to_vec(),
66 }
67 }
68
69 pub fn modules(&self) -> Vec<CompiledModule> {
70 self.bytes
71 .iter()
72 .map(|b| CompiledModule::deserialize_with_defaults(b).unwrap())
73 .collect()
74 }
75
76 pub fn genesis_move_package(&self) -> MovePackage {
77 MovePackage::new_system(
78 OBJECT_START_VERSION,
79 &self.modules(),
80 self.dependencies.iter().copied(),
81 )
82 }
83
84 pub fn genesis_object(&self) -> Object {
85 Object::new_system_package(
86 &self.modules(),
87 OBJECT_START_VERSION,
88 self.dependencies.to_vec(),
89 TransactionDigest::genesis_marker(),
90 )
91 }
92}
93
94impl std::fmt::Debug for SystemPackage {
95 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96 writeln!(f, "Object ID: {:?}", self.id)?;
97 writeln!(f, "Size: {}", self.bytes.len())?;
98 writeln!(f, "Dependencies: {:?}", self.dependencies)?;
99 Ok(())
100 }
101}
102
103macro_rules! define_system_package_metadata {
104 ([$(($id:expr, $name: expr, $path:expr, $deps:expr)),* $(,)?]) => {{
105 static PACKAGES: LazyLock<Vec<SystemPackageMetadata>> = LazyLock::new(|| {
106 vec![
107 $(SystemPackageMetadata::new(
108 $name,
109 concat!("crates/sui-framework/packages/", $path),
110 $id,
111 include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/packages_compiled", "/", $path)),
112 &$deps,
113 )),*
114 ]
115 });
116 &PACKAGES
117 }}
118}
119
120pub struct BuiltInFramework;
121impl BuiltInFramework {
122 pub fn iter_system_package_metadata() -> impl Iterator<Item = &'static SystemPackageMetadata> {
123 define_system_package_metadata!([
127 (MOVE_STDLIB_PACKAGE_ID, "MoveStdlib", "move-stdlib", []),
128 (
129 SUI_FRAMEWORK_PACKAGE_ID,
130 "Sui",
131 "sui-framework",
132 [MOVE_STDLIB_PACKAGE_ID]
133 ),
134 (
135 SUI_SYSTEM_PACKAGE_ID,
136 "SuiSystem",
137 "sui-system",
138 [MOVE_STDLIB_PACKAGE_ID, SUI_FRAMEWORK_PACKAGE_ID]
139 ),
140 (
141 DEEPBOOK_PACKAGE_ID,
142 "DeepBook",
143 "deepbook",
144 [MOVE_STDLIB_PACKAGE_ID, SUI_FRAMEWORK_PACKAGE_ID]
145 ),
146 (
147 BRIDGE_PACKAGE_ID,
148 "Bridge",
149 "bridge",
150 [
151 MOVE_STDLIB_PACKAGE_ID,
152 SUI_FRAMEWORK_PACKAGE_ID,
153 SUI_SYSTEM_PACKAGE_ID
154 ]
155 )
156 ])
157 .iter()
158 }
159
160 pub fn all_package_ids() -> Vec<ObjectID> {
161 Self::iter_system_packages().map(|p| p.id).collect()
162 }
163
164 pub fn get_package_by_id(id: &ObjectID) -> &'static SystemPackage {
165 Self::iter_system_packages().find(|s| &s.id == id).unwrap()
166 }
167
168 pub fn iter_system_packages() -> impl Iterator<Item = &'static SystemPackage> {
169 BuiltInFramework::iter_system_package_metadata().map(|m| &m.compiled)
170 }
171
172 pub fn genesis_move_packages() -> impl Iterator<Item = MovePackage> {
173 Self::iter_system_packages().map(|package| package.genesis_move_package())
174 }
175
176 pub fn genesis_objects() -> impl Iterator<Item = Object> {
177 Self::iter_system_packages().map(|package| package.genesis_object())
178 }
179}
180
181pub const DEFAULT_FRAMEWORK_PATH: &str = env!("CARGO_MANIFEST_DIR");
182
183pub fn legacy_test_cost() -> InternalGas {
184 InternalGas::new(0)
185}
186
187pub async fn compare_system_package<S: ObjectStore>(
199 object_store: &S,
200 id: &ObjectID,
201 modules: &[CompiledModule],
202 dependencies: Vec<ObjectID>,
203 binary_config: &BinaryConfig,
204) -> Option<ObjectRef> {
205 let cur_object = match object_store.get_object(id) {
206 Some(cur_object) => cur_object,
207
208 None => {
209 return Some(
211 Object::new_system_package(
212 modules,
213 OBJECT_START_VERSION,
216 dependencies,
217 TransactionDigest::genesis_marker(),
220 )
221 .compute_object_reference(),
222 );
223 }
224 };
225
226 let cur_ref = cur_object.compute_object_reference();
227 let cur_pkg = cur_object
228 .data
229 .try_as_package()
230 .expect("Framework not package");
231
232 let mut new_object = Object::new_system_package(
233 modules,
234 cur_object.version(),
237 dependencies,
238 cur_object.previous_transaction,
239 );
240
241 if cur_ref == new_object.compute_object_reference() {
242 return Some(cur_ref);
243 }
244
245 let compatibility = Compatibility::framework_upgrade_check();
246
247 let new_pkg = new_object
248 .data
249 .try_as_package_mut()
250 .expect("Created as package");
251
252 let pool = &mut normalized::RcPool::new();
253 let cur_normalized = match cur_pkg.normalize(pool, binary_config, false) {
254 Ok(v) => v,
255 Err(e) => {
256 error!("Could not normalize existing package: {e:?}");
257 return None;
258 }
259 };
260 let mut new_normalized = new_pkg
261 .normalize(pool, binary_config, false)
262 .ok()?;
263
264 for (name, cur_module) in cur_normalized {
265 let new_module = new_normalized.remove(&name)?;
266
267 if let Err(e) = compatibility.check(&cur_module, &new_module) {
268 error!("Compatibility check failed, for new version of {id}::{name}: {e:?}");
269 return None;
270 }
271 }
272
273 new_pkg.increment_version();
274 Some(new_object.compute_object_reference())
275}