diff --git a/Cargo.lock b/Cargo.lock index cd7374ed6a..2523a91e86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4041,6 +4041,7 @@ dependencies = [ "move-model", "move-package", "moveos-compiler", + "moveos-types", "moveos-verifier", "once_cell", "serde 1.0.208", diff --git a/crates/rooch/src/commands/move_cli/commands/build.rs b/crates/rooch/src/commands/move_cli/commands/build.rs index 4ba06ac424..b7646759f2 100644 --- a/crates/rooch/src/commands/move_cli/commands/build.rs +++ b/crates/rooch/src/commands/move_cli/commands/build.rs @@ -39,10 +39,6 @@ pub struct BuildCommand { #[clap(flatten)] move_args: Move, - /// If true, export package binary to the output directory with name `package.blob` - #[clap(long, default_value = "false")] - export: bool, - /// Return command outputs in json format #[clap(long, default_value = "false")] json: bool, @@ -76,44 +72,43 @@ impl CommandAction> for BuildCommand { run_verifier(rerooted_path.clone(), config_cloned.clone(), &mut package)?; - if self.export { - let export_path = match &config_cloned.install_dir { - None => rerooted_path - .join("build") - .join(package.compiled_package_info.package_name.as_str()) - .join("package.blob"), - Some(value) => value.clone().join("package.blob"), - }; - - let blob = package - .root_compiled_units - .iter() - .map(|unit| unit.unit.serialize(None)) - .collect::>(); - - // Get the modules from the package - let modules = package.root_modules_map(); - let empty_modules = modules.iter_modules_owned().is_empty(); - let pkg_address = if !empty_modules { - let first_module = &modules.iter_modules_owned()[0]; - first_module.self_id().address().to_owned() - } else { - return Err(RoochError::MoveCompilationError(format!( - "compiling move modules error! Is the project or module empty: {:?}", - empty_modules, - ))); - }; - let package_data = PackageData::new( - MoveString::from(package.compiled_package_info.package_name.as_str()), - pkg_address, - blob, - ); - let mut file = BufWriter::new(File::create(export_path.clone())?); - bcs::serialize_into(&mut file, &package_data)?; - file.flush()?; - - println!("Exported package to {}", export_path.display()); - } + // export bcs serialized package data to `package.rpd`(rpd for Rooch Package Data). + let export_path = match &config_cloned.install_dir { + None => rerooted_path + .join("build") + .join(package.compiled_package_info.package_name.as_str()) + .join("package.rpd"), + Some(value) => value.clone().join("package.rpd"), + }; + + let blob = package + .root_compiled_units + .iter() + .map(|unit| unit.unit.serialize(None)) + .collect::>(); + + // Get the modules from the package + let modules = package.root_modules_map(); + let empty_modules = modules.iter_modules_owned().is_empty(); + let pkg_address = if !empty_modules { + let first_module = &modules.iter_modules_owned()[0]; + first_module.self_id().address().to_owned() + } else { + return Err(RoochError::MoveCompilationError(format!( + "compiling move modules error! Is the project or module empty: {:?}", + empty_modules, + ))); + }; + let package_data = PackageData::new( + MoveString::from(package.compiled_package_info.package_name.as_str()), + pkg_address, + blob, + ); + let mut file = BufWriter::new(File::create(export_path.clone())?); + bcs::serialize_into(&mut file, &package_data)?; + file.flush()?; + + println!("Exported package to {}", export_path.display()); print_serialized_success(self.json) } diff --git a/crates/testsuite/features/cmd.feature b/crates/testsuite/features/cmd.feature index c1277f3ac5..f55ca35288 100644 --- a/crates/testsuite/features/cmd.feature +++ b/crates/testsuite/features/cmd.feature @@ -240,9 +240,9 @@ Feature: Rooch CLI integration tests Given a server for publish_through_entry_function # The counter example, publishing from saved package binary. - Then cmd: "move build -p ../../examples/counter --named-addresses rooch_examples=default --export --json" + Then cmd: "move build -p ../../examples/counter --named-addresses rooch_examples=default --json" Then assert: "{{$.move[-1].Result}} == Success" - Then cmd: "move run --function 0x2::module_store::publish_package_entry --sender default --args 'file:../../examples/counter/build/counter/package.blob' --json" + Then cmd: "move run --function 0x2::module_store::publish_package_entry --sender default --args 'file:../../examples/counter/build/counter/package.rpd' --json" Then assert: "{{$.move[-1].execution_info.status.type}} == executed" Then cmd: "move view --function default::counter::value" Then assert: "{{$.move[-1].return_values[0].decoded_value}} == 0" diff --git a/frameworks/framework-builder/Cargo.toml b/frameworks/framework-builder/Cargo.toml index 69603b4130..3837c16555 100644 --- a/frameworks/framework-builder/Cargo.toml +++ b/frameworks/framework-builder/Cargo.toml @@ -30,6 +30,7 @@ move-errmapgen = { workspace = true } move-docgen = { workspace = true } move-model = { workspace = true } +moveos-types = { workspace = true } moveos-verifier = { workspace = true } moveos-compiler = { workspace = true } diff --git a/frameworks/framework-builder/src/lib.rs b/frameworks/framework-builder/src/lib.rs index ae0df54da5..da82c22e79 100644 --- a/frameworks/framework-builder/src/lib.rs +++ b/frameworks/framework-builder/src/lib.rs @@ -9,6 +9,8 @@ use move_core_types::account_address::AccountAddress; use move_model::model::GlobalEnv; use move_package::{compilation::compiled_package::CompiledPackage, BuildConfig, ModelConfig}; use moveos_compiler::dependency_order::sort_by_dependency_order; +use moveos_types::move_std::string::MoveString; +use moveos_types::moveos_std::module_store::PackageData; use moveos_verifier::build::run_verifier; use serde::{Deserialize, Serialize}; use std::{ @@ -68,6 +70,14 @@ impl StdlibPackage { }) .collect::>>() } + + pub fn as_package_data(&self) -> PackageData { + PackageData::new( + MoveString::from(self.package_name.as_str()), + self.genesis_account, + self.modules.clone(), + ) + } } #[derive(Debug, Clone)] diff --git a/frameworks/framework-builder/src/releaser.rs b/frameworks/framework-builder/src/releaser.rs index b2396bace8..ee47bc7937 100644 --- a/frameworks/framework-builder/src/releaser.rs +++ b/frameworks/framework-builder/src/releaser.rs @@ -82,7 +82,8 @@ pub fn release(version: StdlibVersion, check_compatibility: bool) -> Result PathBuf { + release_dir().join(self.to_string()) + } + pub fn create_dir(&self) -> Result<()> { let dir = release_dir().join(self.to_string()); if dir.exists() { @@ -67,11 +71,14 @@ impl StdlibVersion { std::fs::create_dir_all(&dir).map_err(|e| anyhow!("Create dir {:?} failed: {:?}", dir, e)) } + /// Deprecated pub(crate) fn load_from_file(&self) -> Result { let file = self.output_file(); Stdlib::load_from_file(file) } + /// Deprecated + /// We will save each package separately pub fn save(&self, stdlib: &Stdlib) -> Result<()> { let file = self.output_file(); let parent = file @@ -85,6 +92,32 @@ impl StdlibVersion { .save_to_file(&file) .map_err(|e| anyhow!("Save stdlib to {:?} failed: {:?}", file, e)) } + + /// Save each package in the stdlib to a separate file + pub fn save_each_package(&self, stdlib: &Stdlib) -> Result<()> { + let dir = self.output_dir(); + if !dir.exists() { + std::fs::create_dir_all(&dir) + .map_err(|e| anyhow!("Create dir {:?} failed: {:?}", dir, e))?; + } + for package in &stdlib.packages { + let package_data = package.as_package_data(); + let file = dir + .join(package.genesis_account.to_hex_literal()) + .join("package.rpd"); + let parent = file + .parent() + .ok_or_else(|| anyhow!("Parent dir not found"))?; + if !parent.exists() { + std::fs::create_dir_all(parent) + .map_err(|e| anyhow!("Create dir {:?} failed: {:?}", parent, e))?; + } + package_data + .save_to_file(&file) + .map_err(|e| anyhow!("Save package to {:?} failed: {:?}", file, e))?; + } + Ok(()) + } } impl PartialOrd for StdlibVersion { diff --git a/frameworks/framework-release/released/8/0x1/package.rpd b/frameworks/framework-release/released/8/0x1/package.rpd new file mode 100644 index 0000000000..88adae99ef Binary files /dev/null and b/frameworks/framework-release/released/8/0x1/package.rpd differ diff --git a/frameworks/framework-release/released/8/0x2/package.rpd b/frameworks/framework-release/released/8/0x2/package.rpd new file mode 100644 index 0000000000..2b8c4e1b22 Binary files /dev/null and b/frameworks/framework-release/released/8/0x2/package.rpd differ diff --git a/frameworks/framework-release/released/8/0x3/package.rpd b/frameworks/framework-release/released/8/0x3/package.rpd new file mode 100644 index 0000000000..91cfe30710 Binary files /dev/null and b/frameworks/framework-release/released/8/0x3/package.rpd differ diff --git a/frameworks/framework-release/released/8/0x4/package.rpd b/frameworks/framework-release/released/8/0x4/package.rpd new file mode 100644 index 0000000000..0efdd3503b Binary files /dev/null and b/frameworks/framework-release/released/8/0x4/package.rpd differ diff --git a/moveos/moveos-types/src/moveos_std/module_store.rs b/moveos/moveos-types/src/moveos_std/module_store.rs index 7607f7cddd..0ef32af4f3 100644 --- a/moveos/moveos-types/src/moveos_std/module_store.rs +++ b/moveos/moveos-types/src/moveos_std/module_store.rs @@ -9,6 +9,7 @@ use crate::{ addresses::MOVEOS_STD_ADDRESS, state::{MoveStructState, MoveStructType}, }; +use anyhow::Result; use move_core_types::language_storage::StructTag; use move_core_types::{ account_address::AccountAddress, @@ -17,6 +18,9 @@ use move_core_types::{ value::{MoveStructLayout, MoveTypeLayout}, }; use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::io::Write; +use std::path::Path; pub const MODULE_NAME: &IdentStr = ident_str!("module_store"); @@ -97,12 +101,12 @@ impl MoveStructState for Package { ///////////// PackageData //////////////// #[derive(Eq, PartialEq, Debug, Clone, Deserialize, Serialize)] pub struct PackageData { - package_name: MoveString, + pub package_name: MoveString, /// The address of the package to be published. /// This must be same as every module's address in the package. - package_id: AccountAddress, + pub package_id: AccountAddress, /// bytecode of modules. - modules: Vec>, + pub modules: Vec>, } impl PackageData { @@ -117,6 +121,13 @@ impl PackageData { modules, } } + + pub fn save_to_file>(&self, file: P) -> Result<()> { + let mut file = File::create(file)?; + let contents = bcs::to_bytes(&self)?; + file.write_all(&contents)?; + Ok(()) + } } impl MoveStructType for PackageData { diff --git a/sdk/typescript/rooch-sdk/test-e2e/setup.ts b/sdk/typescript/rooch-sdk/test-e2e/setup.ts index 3fa3dfe2bc..0e47083d70 100644 --- a/sdk/typescript/rooch-sdk/test-e2e/setup.ts +++ b/sdk/typescript/rooch-sdk/test-e2e/setup.ts @@ -61,23 +61,23 @@ export class TestBox extends TestBoxA { options: { namedAddresses: string } = { - namedAddresses: 'rooch_examples=default', - }, + namedAddresses: 'rooch_examples=default', + }, ) { const namedAddresses = options.namedAddresses.replaceAll( 'default', box.address().toHexAddress(), ) this.roochCommand( - `move build -p ${packagePath} --named-addresses ${namedAddresses} --install-dir ${this.tmpDir.name} --export --json`, + `move build -p ${packagePath} --named-addresses ${namedAddresses} --install-dir ${this.tmpDir.name} --json`, ) let fileBytes: Uint8Array try { - fileBytes = fs.readFileSync(this.tmpDir.name + '/package.blob') + fileBytes = fs.readFileSync(this.tmpDir.name + '/package.rpd') const tx = new Transaction() tx.callFunction({ - target: '0x2::module_store::publish_modules_entry', + target: '0x2::module_store::publish_package_entry', args: [Args.vec('u8', Array.from(fileBytes))], })