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