From 703b568796b2e0b394a9df931aa1c03818ea3696 Mon Sep 17 00:00:00 2001 From: Milosz Muszynski Date: Thu, 30 Oct 2025 15:18:53 +0100 Subject: [PATCH 1/2] piecrust: commit-specific storage for bytecodes --- piecrust/CHANGELOG.md | 2 ++ piecrust/src/store/commit/finalizer.rs | 25 ++++++++++++++++++-- piecrust/src/store/commit/reader.rs | 6 ++++- piecrust/src/store/commit/writer.rs | 32 +++++++++++++++++++++++--- piecrust/src/store/session.rs | 17 ++++++++++++-- 5 files changed, 74 insertions(+), 8 deletions(-) diff --git a/piecrust/CHANGELOG.md b/piecrust/CHANGELOG.md index 15ddde0d..79873853 100644 --- a/piecrust/CHANGELOG.md +++ b/piecrust/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Enriched commit-specific storage to support contract bytecodes [#450] - Added blocking 'init' method to be called only during deployment [#433] ## [0.27.2] - 2025-02-20 @@ -518,6 +519,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +[#450]: https://github.com/dusk-network/piecrust/issues/450 [#rusk_3470]: https://github.com/dusk-network/rusk/issues/3470 [#rusk_3341]: https://github.com/dusk-network/rusk/issues/3341 [#440]: https://github.com/dusk-network/piecrust/issues/440 diff --git a/piecrust/src/store/commit/finalizer.rs b/piecrust/src/store/commit/finalizer.rs index d40678c6..4d6fa5ef 100644 --- a/piecrust/src/store/commit/finalizer.rs +++ b/piecrust/src/store/commit/finalizer.rs @@ -7,8 +7,8 @@ use crate::store::baseinfo::BaseInfo; use crate::store::hasher::Hash; use crate::store::{ - BASE_FILE, ELEMENT_FILE, LEAF_DIR, MAIN_DIR, MEMORY_DIR, TREE_POS_FILE, - TREE_POS_OPT_FILE, + BASE_FILE, BYTECODE_DIR, ELEMENT_FILE, LEAF_DIR, MAIN_DIR, MEMORY_DIR, + METADATA_EXTENSION, OBJECTCODE_EXTENSION, TREE_POS_FILE, TREE_POS_OPT_FILE, }; use std::path::Path; use std::{fs, io}; @@ -26,6 +26,27 @@ impl CommitFinalizer { let base_info = BaseInfo::from_path(&base_info_path)?; for contract_hint in base_info.contract_hints { let contract_hex = hex::encode(contract_hint); + // BYTECODE + let bytecode_src_dir = main_dir.join(BYTECODE_DIR).join(&root); + let bytecode_src_path = bytecode_src_dir.join(&contract_hex); + let module_src_path = + bytecode_src_path.with_extension(OBJECTCODE_EXTENSION); + let metadata_src_path = + bytecode_src_path.with_extension(METADATA_EXTENSION); + let bytecode_dst_path = + main_dir.join(BYTECODE_DIR).join(&contract_hex); + let module_dst_path = + bytecode_dst_path.with_extension(OBJECTCODE_EXTENSION); + let metadata_dst_path = + bytecode_dst_path.with_extension(METADATA_EXTENSION); + if bytecode_src_path.is_file() + && module_src_path.is_file() + && metadata_src_path.is_file() + { + fs::rename(&bytecode_src_path, bytecode_dst_path)?; + fs::rename(&module_src_path, module_dst_path)?; + fs::rename(&metadata_src_path, metadata_dst_path)?; + } // MEMORY let src_path = main_dir.join(MEMORY_DIR).join(&contract_hex).join(&root); diff --git a/piecrust/src/store/commit/reader.rs b/piecrust/src/store/commit/reader.rs index ebce502d..d3cb4d39 100644 --- a/piecrust/src/store/commit/reader.rs +++ b/piecrust/src/store/commit/reader.rs @@ -121,7 +121,11 @@ impl CommitReader { // Check that all contracts in the index file have a corresponding // bytecode and memory pages specified. - let bytecode_path = bytecode_dir.join(&contract_hex); + let bytecode_path = commit_id + .as_ref() + .map(|cid| bytecode_dir.join(cid).join(&contract_hex)) + .filter(|p| p.is_file()) + .unwrap_or(bytecode_dir.join(&contract_hex)); if !bytecode_path.is_file() { return Err(io::Error::new( io::ErrorKind::InvalidData, diff --git a/piecrust/src/store/commit/writer.rs b/piecrust/src/store/commit/writer.rs index e28de570..83620e7e 100644 --- a/piecrust/src/store/commit/writer.rs +++ b/piecrust/src/store/commit/writer.rs @@ -89,6 +89,7 @@ impl CommitWriter { struct Directories { main_dir: PathBuf, bytecode_main_dir: PathBuf, + bytecode_commit_dir: PathBuf, memory_main_dir: PathBuf, leaf_main_dir: PathBuf, } @@ -100,6 +101,10 @@ impl CommitWriter { let bytecode_main_dir = main_dir.join(BYTECODE_DIR); fs::create_dir_all(&bytecode_main_dir)?; + let bytecode_commit_dir = + bytecode_main_dir.join(commit_id.as_ref()); + fs::create_dir_all(&bytecode_commit_dir)?; + let memory_main_dir = main_dir.join(MEMORY_DIR); fs::create_dir_all(&memory_main_dir)?; @@ -109,6 +114,7 @@ impl CommitWriter { Directories { main_dir, bytecode_main_dir, + bytecode_commit_dir, memory_main_dir, leaf_main_dir, } @@ -149,13 +155,33 @@ impl CommitWriter { let metadata_main_path = bytecode_main_path.with_extension(METADATA_EXTENSION); + let bytecode_commit_path = + directories.bytecode_commit_dir.join(&contract_hex); + let module_commit_path = + bytecode_commit_path.with_extension(OBJECTCODE_EXTENSION); + let metadata_commit_path = + bytecode_commit_path.with_extension(METADATA_EXTENSION); + // If the contract is new, we write the bytecode, module, and // metadata files to disk. if contract_data.is_new { // we write them to the main location - fs::write(bytecode_main_path, &contract_data.bytecode)?; - fs::write(module_main_path, contract_data.module.serialize())?; - fs::write(metadata_main_path, &contract_data.metadata)?; + fs::write(bytecode_commit_path, &contract_data.bytecode)?; + fs::write( + module_commit_path, + contract_data.module.serialize(), + )?; + fs::write(metadata_commit_path, &contract_data.metadata)?; + // if main does not have this contract yet, we store it there as + // well + if !bytecode_main_path.is_file() { + fs::write(bytecode_main_path, &contract_data.bytecode)?; + fs::write( + module_main_path, + contract_data.module.serialize(), + )?; + fs::write(metadata_main_path, &contract_data.metadata)?; + } dirty = true; } if dirty { diff --git a/piecrust/src/store/session.rs b/piecrust/src/store/session.rs index 10b97dc7..4dc49cfb 100644 --- a/piecrust/src/store/session.rs +++ b/piecrust/src/store/session.rs @@ -297,8 +297,21 @@ impl ContractSession { let contract_hex = hex::encode(contract); - let bytecode_path = - base_dir.join(BYTECODE_DIR).join(&contract_hex); + let bytecode_path = commit_id + .as_ref() + .map(|hash| { + base_dir + .join(BYTECODE_DIR) + .join(hex::encode(hash.as_bytes())) + .join(&contract_hex) + }) + .filter(|p| p.is_file()) + .unwrap_or( + base_dir + .join(BYTECODE_DIR) + .join(&contract_hex), + ); + let module_path = bytecode_path .with_extension(OBJECTCODE_EXTENSION); let metadata_path = bytecode_path From b3f09ff85684d06c6107940616186478f05d524b Mon Sep 17 00:00:00 2001 From: Milosz Muszynski Date: Thu, 6 Nov 2025 10:28:59 +0100 Subject: [PATCH 2/2] piecrust: fixed indexmap dependency --- piecrust/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/piecrust/Cargo.toml b/piecrust/Cargo.toml index 6110adf8..9eabf96a 100644 --- a/piecrust/Cargo.toml +++ b/piecrust/Cargo.toml @@ -28,6 +28,7 @@ hex = "0.4" dusk-merkle = { version = "0.5", features = ["rkyv-impl"] } const-decoder = "0.3" tracing = "0.1.40" +indexmap = "=2.11.4" [dev-dependencies] once_cell = "1.18"