From b0d7b162c09adf922f03ec7528c887488acc6e88 Mon Sep 17 00:00:00 2001 From: Zehui Zheng Date: Tue, 13 Jan 2026 17:48:55 -0800 Subject: [PATCH] feat: bump emulator to 0.20 chore: update emulator submodule, link omp chore: update step submodule chore: update bindings, fix tests --- .github/actions/cartesi-machine/action.yml | 2 +- .github/workflows/build.yml | 6 +- .../contracts/src/DaveConsensus.sol | 2 +- .../contracts/test/DaveConsensus.t.sol | 2 +- .../node/blockchain-reader/src/lib.rs | 5 +- .../node/blockchain-reader/src/test_utils.rs | 9 +- .../src/persistent_state_access.rs | 5 +- .../node/state-manager/src/sql/test_helper.rs | 5 +- justfile | 4 +- machine/emulator | 2 +- machine/rust-bindings/Cargo.toml | 2 +- .../cartesi-machine-sys/build.rs | 24 +- .../cartesi-machine/src/config/machine.rs | 228 +++++++++++++++--- .../cartesi-machine/src/constants.rs | 18 +- .../cartesi-machine/src/machine.rs | 101 ++++---- machine/step | 2 +- prt/client-lua/computation/machine.lua | 2 +- prt/client-lua/cryptography/hash.lua | 3 +- prt/measure_constants/Dockerfile | 2 +- .../runners/helpers/patched_commitment.lua | 2 +- prt/tests/rollups/dave/node.lua | 10 +- prt/tests/rollups/justfile | 2 +- prt/tests/rollups/test_cases/simple.lua | 2 +- prt/tests/rollups/test_env.lua | 6 +- test/programs/justfile | 17 +- 25 files changed, 339 insertions(+), 124 deletions(-) diff --git a/.github/actions/cartesi-machine/action.yml b/.github/actions/cartesi-machine/action.yml index 8df8a10c..1071a82b 100644 --- a/.github/actions/cartesi-machine/action.yml +++ b/.github/actions/cartesi-machine/action.yml @@ -4,7 +4,7 @@ inputs: version: description: 'Version of Cartesi Machine to install' required: false - default: 0.19.0 + default: 0.20.0-test suffix-version: description: 'Suffix of Cartesi Machine to install' required: false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2f9b4e8..131f20e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: - name: Install Cartesi Machine uses: ./.github/actions/cartesi-machine with: - version: 0.19.0 + version: 0.20.0-test suffix-version: "" - name: Setup env @@ -71,7 +71,7 @@ jobs: - name: Install Cartesi Machine uses: ./.github/actions/cartesi-machine with: - version: 0.19.0 + version: 0.20.0-test - name: Download PRT contracts working-directory: ./prt/contracts run: | @@ -138,7 +138,7 @@ jobs: working-directory: ./machine/emulator run: | make bundle-boost - wget https://github.com/cartesi/machine-emulator/releases/download/v0.19.0/add-generated-files.diff + wget https://github.com/cartesi/machine-emulator/releases/download/v0.20.0-test/add-generated-files.diff git apply add-generated-files.diff make sudo make install diff --git a/cartesi-rollups/contracts/src/DaveConsensus.sol b/cartesi-rollups/contracts/src/DaveConsensus.sol index 5b7a687d..c3976d19 100644 --- a/cartesi-rollups/contracts/src/DaveConsensus.sol +++ b/cartesi-rollups/contracts/src/DaveConsensus.sol @@ -221,7 +221,7 @@ contract DaveConsensus is IDaveConsensus, ERC165 { require(proof.length == Memory.LOG2_MAX_SIZE, InvalidOutputsMerkleRootProofSize(proof.length)); bytes32 allegedStateHash = proof.merkleRootAfterReplacement( - EmulatorConstants.PMA_CMIO_TX_BUFFER_START >> EmulatorConstants.TREE_LOG2_WORD_SIZE, + EmulatorConstants.AR_CMIO_TX_BUFFER_START >> EmulatorConstants.HASH_TREE_LOG2_WORD_SIZE, keccak256(abi.encode(outputsMerkleRoot)) ); diff --git a/cartesi-rollups/contracts/test/DaveConsensus.t.sol b/cartesi-rollups/contracts/test/DaveConsensus.t.sol index da91e095..4e40f1ba 100644 --- a/cartesi-rollups/contracts/test/DaveConsensus.t.sol +++ b/cartesi-rollups/contracts/test/DaveConsensus.t.sol @@ -601,7 +601,7 @@ contract DaveConsensusTest is Test { bytes32 root = new LibMerkle32Wrapper() .merkleRootAfterReplacement( - siblings, EmulatorConstants.PMA_CMIO_TX_BUFFER_START >> EmulatorConstants.TREE_LOG2_WORD_SIZE, leaf + siblings, EmulatorConstants.AR_CMIO_TX_BUFFER_START >> EmulatorConstants.TREE_LOG2_WORD_SIZE, leaf ); assertEq(current, root); diff --git a/cartesi-rollups/node/blockchain-reader/src/lib.rs b/cartesi-rollups/node/blockchain-reader/src/lib.rs index 23973a57..e8bf8c77 100644 --- a/cartesi-rollups/node/blockchain-reader/src/lib.rs +++ b/cartesi-rollups/node/blockchain-reader/src/lib.rs @@ -569,7 +569,10 @@ mod blockchain_reader_tests { let mut machine = Machine::create( &MachineConfig::new_with_ram(RAMConfig { length: 134217728, - image_filename: "../../../test/programs/linux.bin".into(), + backing_store: cartesi_machine::config::machine::BackingStoreConfig { + data_filename: "../../../test/programs/linux.bin".into(), + ..Default::default() + }, }), &RuntimeConfig::default(), ) diff --git a/cartesi-rollups/node/blockchain-reader/src/test_utils.rs b/cartesi-rollups/node/blockchain-reader/src/test_utils.rs index b69ea563..36ec2b61 100644 --- a/cartesi-rollups/node/blockchain-reader/src/test_utils.rs +++ b/cartesi-rollups/node/blockchain-reader/src/test_utils.rs @@ -13,7 +13,7 @@ use cartesi_rollups_contracts::i_input_box::IInputBox; use serde::Deserialize; use std::{ fs::{self, File}, - io::Read, + io::{Read, Seek}, path::PathBuf, }; @@ -77,8 +77,11 @@ pub async fn spawn_anvil_and_provider() -> Result<(AnvilInstance, DynProvider, A let dave_app_factory = deployment_address("DaveAppFactory"); let initial_hash = { - // $ xxd -p -c32 test/programs/echo/machine-image/hash - let mut file = File::open(program_path.join("machine-image").join("hash")).unwrap(); + // Root hash is stored in hash_tree.sht at offset 0x60 (node 1's hash in sparse tree). + // Equivalent to: xxd -seek 0x60 -l 0x20 -c 0x20 -p .../machine-image/hash_tree.sht + let mut file = + File::open(program_path.join("machine-image").join("hash_tree.sht")).unwrap(); + file.seek(std::io::SeekFrom::Start(0x60)).unwrap(); let mut buffer = [0u8; 32]; file.read_exact(&mut buffer).unwrap(); buffer diff --git a/cartesi-rollups/node/state-manager/src/persistent_state_access.rs b/cartesi-rollups/node/state-manager/src/persistent_state_access.rs index b11d772f..704d1a60 100644 --- a/cartesi-rollups/node/state-manager/src/persistent_state_access.rs +++ b/cartesi-rollups/node/state-manager/src/persistent_state_access.rs @@ -330,7 +330,10 @@ mod tests { let mut machine = Machine::create( &MachineConfig::new_with_ram(RAMConfig { length: 134217728, - image_filename: "../../../test/programs/linux.bin".into(), + backing_store: cartesi_machine::config::machine::BackingStoreConfig { + data_filename: "../../../test/programs/linux.bin".into(), + ..Default::default() + }, }), &RuntimeConfig::default(), ) diff --git a/cartesi-rollups/node/state-manager/src/sql/test_helper.rs b/cartesi-rollups/node/state-manager/src/sql/test_helper.rs index 73758261..d849c6b0 100644 --- a/cartesi-rollups/node/state-manager/src/sql/test_helper.rs +++ b/cartesi-rollups/node/state-manager/src/sql/test_helper.rs @@ -21,7 +21,10 @@ pub fn setup_db() -> (TempDir, Connection) { let mut machine = Machine::create( &MachineConfig::new_with_ram(RAMConfig { length: 134217728, - image_filename: "../../../test/programs/linux.bin".into(), + backing_store: cartesi_machine::config::machine::BackingStoreConfig { + data_filename: "../../../test/programs/linux.bin".into(), + ..Default::default() + }, }), &RuntimeConfig::default(), ) diff --git a/justfile b/justfile index 5918c637..0b4b0e88 100644 --- a/justfile +++ b/justfile @@ -1,7 +1,7 @@ update-submodules: git submodule update --recursive --init -apply-generated-files-diff VERSION="v0.19.0": +apply-generated-files-diff VERSION="v0.20.0-test": cd machine/emulator && \ wget https://github.com/cartesi/machine-emulator/releases/download/{{VERSION}}/add-generated-files.diff && \ git apply add-generated-files.diff @@ -16,7 +16,7 @@ clean-contracts: clean-consensus-contracts clean-prt-contracts clean-bindings cl make -C machine/emulator clean depclean distclean setup: update-submodules clean-emulator clean-contracts bundle-boost apply-generated-files-diff - make -C machine/emulator # Requires docker, necessary for machine bindings + make -C machine/emulator -j8 # Requires docker, necessary for machine bindings # Run this once after cloning, if using a docker environment setup-docker: setup build-docker-image diff --git a/machine/emulator b/machine/emulator index ce402f96..83e8d769 160000 --- a/machine/emulator +++ b/machine/emulator @@ -1 +1 @@ -Subproject commit ce402f96d6757c8f4b2f08cba861cd80ab6bf834 +Subproject commit 83e8d7695515f9ca59993f1bd669131f730f560f diff --git a/machine/rust-bindings/Cargo.toml b/machine/rust-bindings/Cargo.toml index 91400111..b10455a6 100644 --- a/machine/rust-bindings/Cargo.toml +++ b/machine/rust-bindings/Cargo.toml @@ -8,7 +8,7 @@ members = [ [workspace.package] -version = "0.19.0" +version = "0.20.0-test" edition = "2021" license = "Apache-2.0" diff --git a/machine/rust-bindings/cartesi-machine-sys/build.rs b/machine/rust-bindings/cartesi-machine-sys/build.rs index 527c6543..75748ffe 100644 --- a/machine/rust-bindings/cartesi-machine-sys/build.rs +++ b/machine/rust-bindings/cartesi-machine-sys/build.rs @@ -39,6 +39,28 @@ fn main() { } } + // OpenMP linker configuration (cross-platform) + if cfg!(target_os = "macos") { + // macOS: Try Homebrew first, then MacPorts + let homebrew_libomp = PathBuf::from("/opt/homebrew/opt/libomp"); + if homebrew_libomp.exists() { + println!("cargo:rustc-link-search={}/lib", homebrew_libomp.display()); + println!("cargo:rustc-link-lib=omp"); + } else { + let macports_libomp = PathBuf::from("/opt/local/lib/libomp"); + if macports_libomp.exists() { + println!("cargo:rustc-link-search=/opt/local/lib/libomp"); + println!("cargo:rustc-link-lib=gomp"); + } else { + // Fallback: let system linker find it + println!("cargo:rustc-link-lib=omp"); + } + } + } else { + // Linux and other Unix-like systems: libgomp comes with GCC + println!("cargo:rustc-link-lib=gomp"); + } + // // Generate bindings // @@ -197,7 +219,7 @@ mod build_cm { process::{Command, Stdio}, }; - const VERSION_STRING: &str = "v0.19.0"; + const VERSION_STRING: &str = "v0.20.0-test"; pub fn download(machine_dir_path: &Path) { let patch_file = machine_dir_path.join("add-generated-files.diff"); diff --git a/machine/rust-bindings/cartesi-machine/src/config/machine.rs b/machine/rust-bindings/cartesi-machine/src/config/machine.rs index e599ed6f..5d3b6dde 100644 --- a/machine/rust-bindings/cartesi-machine/src/config/machine.rs +++ b/machine/rust-bindings/cartesi-machine/src/config/machine.rs @@ -4,15 +4,43 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; +/// Backing store config; matches C++ backing_store_config (data_filename, etc.). +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct BackingStoreConfig { + #[serde(default)] + pub shared: bool, + #[serde(default)] + pub create: bool, + #[serde(default)] + pub truncate: bool, + #[serde(default)] + pub data_filename: PathBuf, + #[serde(default)] + pub dht_filename: PathBuf, + #[serde(default)] + pub dpt_filename: PathBuf, +} + +/// Config with only backing_store; matches C++ backing_store_config_only. +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct BackingStoreConfigOnly { + #[serde(default)] + pub backing_store: BackingStoreConfig, +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MachineConfig { pub processor: ProcessorConfig, pub ram: RAMConfig, pub dtb: DTBConfig, pub flash_drive: FlashDriveConfigs, + #[serde(default)] pub tlb: TLBConfig, + #[serde(default)] pub clint: CLINTConfig, + #[serde(default)] pub plic: PLICConfig, + #[serde(default)] pub htif: HTIFConfig, pub uarch: UarchConfig, pub cmio: CmioConfig, @@ -93,106 +121,206 @@ fn default_config() -> MachineConfig { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct ProcessorConfig { + #[serde(default)] + pub backing_store: BackingStoreConfig, + #[serde(default)] pub x0: u64, + #[serde(default)] pub x1: u64, + #[serde(default)] pub x2: u64, + #[serde(default)] pub x3: u64, + #[serde(default)] pub x4: u64, + #[serde(default)] pub x5: u64, + #[serde(default)] pub x6: u64, + #[serde(default)] pub x7: u64, + #[serde(default)] pub x8: u64, + #[serde(default)] pub x9: u64, + #[serde(default)] pub x10: u64, + #[serde(default)] pub x11: u64, + #[serde(default)] pub x12: u64, + #[serde(default)] pub x13: u64, + #[serde(default)] pub x14: u64, + #[serde(default)] pub x15: u64, + #[serde(default)] pub x16: u64, + #[serde(default)] pub x17: u64, + #[serde(default)] pub x18: u64, + #[serde(default)] pub x19: u64, + #[serde(default)] pub x20: u64, + #[serde(default)] pub x21: u64, + #[serde(default)] pub x22: u64, + #[serde(default)] pub x23: u64, + #[serde(default)] pub x24: u64, + #[serde(default)] pub x25: u64, + #[serde(default)] pub x26: u64, + #[serde(default)] pub x27: u64, + #[serde(default)] pub x28: u64, + #[serde(default)] pub x29: u64, + #[serde(default)] pub x30: u64, + #[serde(default)] pub x31: u64, + #[serde(default)] pub f0: u64, + #[serde(default)] pub f1: u64, + #[serde(default)] pub f2: u64, + #[serde(default)] pub f3: u64, + #[serde(default)] pub f4: u64, + #[serde(default)] pub f5: u64, + #[serde(default)] pub f6: u64, + #[serde(default)] pub f7: u64, + #[serde(default)] pub f8: u64, + #[serde(default)] pub f9: u64, + #[serde(default)] pub f10: u64, + #[serde(default)] pub f11: u64, + #[serde(default)] pub f12: u64, + #[serde(default)] pub f13: u64, + #[serde(default)] pub f14: u64, + #[serde(default)] pub f15: u64, + #[serde(default)] pub f16: u64, + #[serde(default)] pub f17: u64, + #[serde(default)] pub f18: u64, + #[serde(default)] pub f19: u64, + #[serde(default)] pub f20: u64, + #[serde(default)] pub f21: u64, + #[serde(default)] pub f22: u64, + #[serde(default)] pub f23: u64, + #[serde(default)] pub f24: u64, + #[serde(default)] pub f25: u64, + #[serde(default)] pub f26: u64, + #[serde(default)] pub f27: u64, + #[serde(default)] pub f28: u64, + #[serde(default)] pub f29: u64, + #[serde(default)] pub f30: u64, + #[serde(default)] pub f31: u64, + #[serde(default)] pub pc: u64, + #[serde(default)] pub fcsr: u64, + #[serde(default)] pub mvendorid: u64, + #[serde(default)] pub marchid: u64, + #[serde(default)] pub mimpid: u64, + #[serde(default)] pub mcycle: u64, + #[serde(default)] pub icycleinstret: u64, + #[serde(default)] pub mstatus: u64, + #[serde(default)] pub mtvec: u64, + #[serde(default)] pub mscratch: u64, + #[serde(default)] pub mepc: u64, + #[serde(default)] pub mcause: u64, + #[serde(default)] pub mtval: u64, + #[serde(default)] pub misa: u64, + #[serde(default)] pub mie: u64, + #[serde(default)] pub mip: u64, + #[serde(default)] pub medeleg: u64, + #[serde(default)] pub mideleg: u64, + #[serde(default)] pub mcounteren: u64, + #[serde(default)] pub menvcfg: u64, + #[serde(default)] pub stvec: u64, + #[serde(default)] pub sscratch: u64, + #[serde(default)] pub sepc: u64, + #[serde(default)] pub scause: u64, + #[serde(default)] pub stval: u64, + #[serde(default)] pub satp: u64, + #[serde(default)] pub scounteren: u64, + #[serde(default)] pub senvcfg: u64, + #[serde(default)] pub ilrsc: u64, + #[serde(default)] pub iprv: u64, + #[serde(default)] #[serde(rename = "iflags_X")] pub iflags_x: u64, + #[serde(default)] #[serde(rename = "iflags_Y")] pub iflags_y: u64, + #[serde(default)] #[serde(rename = "iflags_H")] pub iflags_h: u64, + #[serde(default)] pub iunrep: u64, } @@ -205,7 +333,7 @@ impl Default for ProcessorConfig { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RAMConfig { pub length: u64, - pub image_filename: PathBuf, + pub backing_store: BackingStoreConfig, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -213,7 +341,7 @@ pub struct DTBConfig { pub bootargs: String, pub init: String, pub entrypoint: String, - pub image_filename: PathBuf, + pub backing_store: BackingStoreConfig, } impl Default for DTBConfig { @@ -224,18 +352,18 @@ impl Default for DTBConfig { #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct MemoryRangeConfig { - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none", default)] pub start: Option, - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none", default)] pub length: Option, - pub image_filename: PathBuf, - pub shared: bool, + #[serde(default)] + pub read_only: bool, + pub backing_store: BackingStoreConfig, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct CmioBufferConfig { - pub image_filename: PathBuf, - pub shared: bool, + pub backing_store: BackingStoreConfig, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] @@ -272,91 +400,113 @@ pub struct VirtIODeviceConfig { pub type FlashDriveConfigs = Vec; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct TLBConfig { - pub image_filename: PathBuf, -} - -impl Default for TLBConfig { - fn default() -> Self { - default_config().tlb - } + #[serde(default)] + pub backing_store: BackingStoreConfig, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct CLINTConfig { + #[serde(default)] pub mtimecmp: u64, } -impl Default for CLINTConfig { - fn default() -> Self { - default_config().clint - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct PLICConfig { + #[serde(default)] pub girqpend: u64, + #[serde(default)] pub girqsrvd: u64, } -impl Default for PLICConfig { - fn default() -> Self { - default_config().plic - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct HTIFConfig { + #[serde(default)] pub fromhost: u64, + #[serde(default)] pub tohost: u64, + #[serde(default)] pub console_getchar: bool, + #[serde(default)] pub yield_manual: bool, + #[serde(default)] pub yield_automatic: bool, } -impl Default for HTIFConfig { - fn default() -> Self { - default_config().htif - } -} - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct UarchProcessorConfig { + #[serde(default)] + pub backing_store: BackingStoreConfig, + #[serde(default)] pub x0: u64, + #[serde(default)] pub x1: u64, + #[serde(default)] pub x2: u64, + #[serde(default)] pub x3: u64, + #[serde(default)] pub x4: u64, + #[serde(default)] pub x5: u64, + #[serde(default)] pub x6: u64, + #[serde(default)] pub x7: u64, + #[serde(default)] pub x8: u64, + #[serde(default)] pub x9: u64, + #[serde(default)] pub x10: u64, + #[serde(default)] pub x11: u64, + #[serde(default)] pub x12: u64, + #[serde(default)] pub x13: u64, + #[serde(default)] pub x14: u64, + #[serde(default)] pub x15: u64, + #[serde(default)] pub x16: u64, + #[serde(default)] pub x17: u64, + #[serde(default)] pub x18: u64, + #[serde(default)] pub x19: u64, + #[serde(default)] pub x20: u64, + #[serde(default)] pub x21: u64, + #[serde(default)] pub x22: u64, + #[serde(default)] pub x23: u64, + #[serde(default)] pub x24: u64, + #[serde(default)] pub x25: u64, + #[serde(default)] pub x26: u64, + #[serde(default)] pub x27: u64, + #[serde(default)] pub x28: u64, + #[serde(default)] pub x29: u64, + #[serde(default)] pub x30: u64, + #[serde(default)] pub x31: u64, + #[serde(default)] pub pc: u64, + #[serde(default)] pub cycle: u64, + #[serde(default)] pub halt_flag: bool, } @@ -368,9 +518,9 @@ impl Default for UarchProcessorConfig { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct UarchRAMConfig { - #[serde(skip_serializing_if = "Option::is_none")] + #[serde(skip_serializing_if = "Option::is_none", default)] pub length: Option, - pub image_filename: PathBuf, + pub backing_store: BackingStoreConfig, } impl Default for UarchRAMConfig { diff --git a/machine/rust-bindings/cartesi-machine/src/constants.rs b/machine/rust-bindings/cartesi-machine/src/constants.rs index 9e8088af..fef0a375 100644 --- a/machine/rust-bindings/cartesi-machine/src/constants.rs +++ b/machine/rust-bindings/cartesi-machine/src/constants.rs @@ -6,19 +6,19 @@ pub mod machine { use cartesi_machine_sys::*; // pub const CYCLE_MAX: u64 = CM_MCYCLE_MAX as u64; - pub const HASH_SIZE: u32 = CM_HASH_SIZE; - pub const TREE_LOG2_WORD_SIZE: u32 = CM_TREE_LOG2_WORD_SIZE; - pub const TREE_LOG2_PAGE_SIZE: u32 = CM_TREE_LOG2_PAGE_SIZE; - pub const TREE_LOG2_ROOT_SIZE: u32 = CM_TREE_LOG2_ROOT_SIZE; + pub const HASH_SIZE: u32 = CM_HASH_SIZE as u32; + pub const TREE_LOG2_WORD_SIZE: u32 = CM_HASH_TREE_LOG2_WORD_SIZE as u32; + pub const TREE_LOG2_PAGE_SIZE: u32 = CM_HASH_TREE_LOG2_PAGE_SIZE as u32; + pub const TREE_LOG2_ROOT_SIZE: u32 = CM_HASH_TREE_LOG2_ROOT_SIZE as u32; } pub mod pma { use cartesi_machine_sys::*; - pub const RX_START: u64 = CM_PMA_CMIO_RX_BUFFER_START as u64; - pub const RX_LOG2_SIZE: u64 = CM_PMA_CMIO_RX_BUFFER_LOG2_SIZE as u64; - pub const TX_START: u64 = CM_PMA_CMIO_TX_BUFFER_START as u64; - pub const TX_LOG2_SIZE: u64 = CM_PMA_CMIO_TX_BUFFER_LOG2_SIZE as u64; - pub const RAM_START: u64 = CM_PMA_RAM_START as u64; + pub const RX_START: u64 = CM_AR_CMIO_RX_BUFFER_START as u64; + pub const RX_LOG2_SIZE: u64 = CM_AR_CMIO_RX_BUFFER_LOG2_SIZE as u64; + pub const TX_START: u64 = CM_AR_CMIO_TX_BUFFER_START as u64; + pub const TX_LOG2_SIZE: u64 = CM_AR_CMIO_TX_BUFFER_LOG2_SIZE as u64; + pub const RAM_START: u64 = CM_AR_RAM_START as u64; } pub mod break_reason { diff --git a/machine/rust-bindings/cartesi-machine/src/machine.rs b/machine/rust-bindings/cartesi-machine/src/machine.rs index 371ccb07..26dd7d6a 100644 --- a/machine/rust-bindings/cartesi-machine/src/machine.rs +++ b/machine/rust-bindings/cartesi-machine/src/machine.rs @@ -92,12 +92,14 @@ impl Machine { pub fn create(config: &MachineConfig, runtime_config: &RuntimeConfig) -> Result { let config_json = serialize_to_json!(&config); let runtime_config_json = serialize_to_json!(&runtime_config); + let dir_cstr = CString::new("").unwrap(); // in-memory machine let mut machine: *mut cartesi_machine_sys::cm_machine = ptr::null_mut(); let err_code = unsafe { cartesi_machine_sys::cm_create_new( config_json.as_ptr(), runtime_config_json.as_ptr(), + dir_cstr.as_ptr(), &mut machine, ) }; @@ -116,6 +118,7 @@ impl Machine { cartesi_machine_sys::cm_load_new( dir_cstr.as_ptr(), runtime_config_json.as_ptr(), + cartesi_machine_sys::CM_SHARING_CONFIG, &mut machine, ) }; @@ -125,9 +128,18 @@ impl Machine { } /// Stores a machine instance to a directory, serializing its entire state. + /// Uses CM_SHARING_ALL so that the current machine state is written for all + /// address ranges (required when storing in-memory machines that have no + /// backing files). pub fn store(&mut self, dir: &Path) -> Result<()> { let dir_cstr = path_to_cstring(dir); - let err_code = unsafe { cartesi_machine_sys::cm_store(self.machine, dir_cstr.as_ptr()) }; + let err_code = unsafe { + cartesi_machine_sys::cm_store( + self.machine, + dir_cstr.as_ptr(), + cartesi_machine_sys::CM_SHARING_ALL, + ) + }; check_err!(err_code)?; Ok(()) @@ -164,25 +176,20 @@ impl Machine { shared: bool, image_path: Option<&Path>, ) -> Result<()> { - let image_cstr = match image_path { - Some(path) => path_to_cstring(path), - None => CString::new("").unwrap(), - }; - - let image_ptr = if image_path.is_some() { - image_cstr.as_ptr() - } else { - ptr::null() - }; + let range_config = serde_json::json!({ + "start": start, + "length": length, + "read_only": false, + "backing_store": { + "data_filename": image_path.map(|p| p.to_string_lossy().to_string()).unwrap_or_default(), + "shared": shared + } + }); + + let range_json = serialize_to_json!(&range_config); let err_code = unsafe { - cartesi_machine_sys::cm_replace_memory_range( - self.machine, - start, - length, - shared, - image_ptr, - ) + cartesi_machine_sys::cm_replace_memory_range(self.machine, range_json.as_ptr()) }; check_err!(err_code)?; @@ -205,7 +212,7 @@ impl Machine { pub fn memory_ranges(&mut self) -> Result { let mut ranges_ptr: *const c_char = ptr::null(); let err_code = - unsafe { cartesi_machine_sys::cm_get_memory_ranges(self.machine, &mut ranges_ptr) }; + unsafe { cartesi_machine_sys::cm_get_address_ranges(self.machine, &mut ranges_ptr) }; check_err!(err_code)?; let ranges = parse_json_from_cstring!(ranges_ptr); @@ -650,7 +657,7 @@ mod tests { use crate::{ config::{ - machine::{DTBConfig, MachineConfig, MemoryRangeConfig, RAMConfig}, + machine::{BackingStoreConfig, MachineConfig, MemoryRangeConfig, RAMConfig}, runtime::RuntimeConfig, }, constants, @@ -659,36 +666,46 @@ mod tests { }; fn make_basic_machine_config() -> MachineConfig { - MachineConfig::new_with_ram(RAMConfig { + let mut config = Machine::default_config().expect("failed to get default config"); + config.ram = RAMConfig { length: 134217728, - image_filename: "../../../test/programs/linux.bin".into(), - }) - .dtb(DTBConfig { - entrypoint: "echo Hello from inside!".to_string(), - ..Default::default() - }) - .add_flash_drive(MemoryRangeConfig { - image_filename: "../../../test/programs/rootfs.ext2".into(), + backing_store: BackingStoreConfig { + data_filename: "../../../test/programs/linux.bin".into(), + ..Default::default() + }, + }; + config.dtb.entrypoint = "echo Hello from inside!".to_string(); + config.flash_drive = vec![MemoryRangeConfig { + backing_store: BackingStoreConfig { + data_filename: "../../../test/programs/rootfs.ext2".into(), + ..Default::default() + }, ..Default::default() - }) + }]; + config } fn make_cmio_machine_config() -> MachineConfig { - MachineConfig::new_with_ram(RAMConfig { + let mut config = Machine::default_config().expect("failed to get default config"); + config.ram = RAMConfig { length: 134217728, - image_filename: "../../../test/programs/linux.bin".into(), - }) - .dtb(DTBConfig { - entrypoint: - "echo '{\"domain\":16,\"id\":\"'$(echo -n Hello from inside! | hex --encode)'\"}' \ + backing_store: BackingStoreConfig { + data_filename: "../../../test/programs/linux.bin".into(), + ..Default::default() + }, + }; + config.dtb.entrypoint = + "echo '{\"domain\":16,\"id\":\"'$(echo -n Hello from inside! | hex --encode)'\"}' \ | rollup gio | grep -Eo '0x[0-9a-f]+' | tr -d '\\n' | hex --decode; echo" - .to_string(), - ..Default::default() - }) - .add_flash_drive(MemoryRangeConfig { - image_filename: "../../../test/programs/rootfs.ext2".into(), + .to_string(); + config.flash_drive = vec![MemoryRangeConfig { + backing_store: BackingStoreConfig { + data_filename: "../../../test/programs/rootfs.ext2".into(), + ..Default::default() + }, ..Default::default() - }) + }]; + config } fn create_machine(config: &MachineConfig) -> Result { diff --git a/machine/step b/machine/step index e8050ddf..3807f441 160000 --- a/machine/step +++ b/machine/step @@ -1 +1 @@ -Subproject commit e8050ddfdb986d6014bebdfc1d33e16cb3b2528a +Subproject commit 3807f4418cc4dde73d30ed7ef0deba91d7035508 diff --git a/prt/client-lua/computation/machine.lua b/prt/client-lua/computation/machine.lua index e292f87e..655d883a 100644 --- a/prt/client-lua/computation/machine.lua +++ b/prt/client-lua/computation/machine.lua @@ -334,7 +334,7 @@ function Machine:prove_read_leaf(address) return data end -local keccak = require "cartesi".keccak +local keccak = cartesi.keccak256 function Machine:prove_write_leaf(address) -- always write aligned 32 bytes (one leaf) diff --git a/prt/client-lua/cryptography/hash.lua b/prt/client-lua/cryptography/hash.lua index 30638be4..e334a9a9 100644 --- a/prt/client-lua/cryptography/hash.lua +++ b/prt/client-lua/cryptography/hash.lua @@ -1,4 +1,5 @@ -local keccak = require "cartesi".keccak +local cartesi = require "cartesi" +local keccak = cartesi.keccak256 local conversion = require "utils.conversion" local interned_hashes = {} diff --git a/prt/measure_constants/Dockerfile b/prt/measure_constants/Dockerfile index 09eace3f..028c896b 100644 --- a/prt/measure_constants/Dockerfile +++ b/prt/measure_constants/Dockerfile @@ -1,4 +1,4 @@ -FROM cartesi/machine-emulator:0.19.0 +FROM cartesi/machine-emulator:0.20.0-test USER root RUN apt-get update && \ diff --git a/prt/tests/common/runners/helpers/patched_commitment.lua b/prt/tests/common/runners/helpers/patched_commitment.lua index 81820f40..a46bf4ae 100644 --- a/prt/tests/common/runners/helpers/patched_commitment.lua +++ b/prt/tests/common/runners/helpers/patched_commitment.lua @@ -32,7 +32,7 @@ local function filter_map_patches(patches, base_cycle, log2_stride, log2_stride_ local span = bint256.one() << (log2_stride_count + log2_stride) local mask = (bint256.one() << log2_stride) - 1 if (patch.meta_cycle & mask):iszero() and -- alignment; first bits are zero - patch.meta_cycle > base_cycle and -- meta_cycle is within lower bound + patch.meta_cycle > base_cycle and -- meta_cycle is within lower bound patch.meta_cycle <= base_cycle + span -- meta_cycle is within upper bounds then local position = ((patch.meta_cycle - base_cycle) >> log2_stride) - 1 diff --git a/prt/tests/rollups/dave/node.lua b/prt/tests/rollups/dave/node.lua index 7ff56ae7..b1d828e1 100644 --- a/prt/tests/rollups/dave/node.lua +++ b/prt/tests/rollups/dave/node.lua @@ -61,6 +61,7 @@ sqlite3 -readonly ./_state/%d/db \ 'SELECT repetitions, HEX(leaf) FROM leafs WHERE level=0 ORDER BY leaf_index ASC' 2>&1 ]] function Dave:root_commitment(epoch_index) + print(string.format("[Dave] root_commitment(epoch_index=%d) called", epoch_index)) local query = function() assert(db_exists(epoch_index), string.format("db %d doesn't exist ", epoch_index)) @@ -87,14 +88,21 @@ function Dave:root_commitment(epoch_index) builder:add(leaf, repetitions) end - return initial_state, builder:build(initial_state.root_hash) + local commitment = builder:build(initial_state.root_hash) + print(string.format("[Dave] root_commitment(epoch_index=%d) -> root=%s", epoch_index, commitment.root_hash:hex_string())) + return initial_state, commitment end local initial_state, commitment + local attempt = 0 time.sleep_until(function() + attempt = attempt + 1 self.sender:advance_blocks(1) local ok ok, initial_state, commitment = pcall(query) + if not ok and (attempt == 1 or attempt % 10 == 0) then + print(string.format("[Dave] root_commitment(epoch_index=%d) attempt %d failed: %s", epoch_index, attempt, tostring(initial_state))) + end return ok end, 5) diff --git a/prt/tests/rollups/justfile b/prt/tests/rollups/justfile index 260ed98c..5aa45d93 100644 --- a/prt/tests/rollups/justfile +++ b/prt/tests/rollups/justfile @@ -10,7 +10,7 @@ test PROGRAM SCRIPT: ANVIL_LOAD_PATH=`realpath {{ANVIL_LOAD_PATH}}` \ ANVIL_DUMP_PATH="anvil_{{PROGRAM}}_{{SCRIPT}}.json" \ TEMPLATE_MACHINE=`realpath ../../../test/programs/{{PROGRAM}}/machine-image` \ - TEMPLATE_MACHINE_HASH=0x`xxd -p -c32 ../../../test/programs/{{PROGRAM}}/machine-image/hash` \ + TEMPLATE_MACHINE_HASH=0x`xxd -seek 0x60 -l 0x20 -c 0x20 -p ../../../test/programs/{{PROGRAM}}/machine-image/hash_tree.sht` \ DAVE_APP_FACTORY=`jq -r .address {{DEPLOYMENTS_DIR}}/DaveAppFactory.json` \ INPUT_BOX=`jq -r .address {{DEPLOYMENTS_DIR}}/InputBox.json` \ ERC20_PORTAL=`jq -r .address {{DEPLOYMENTS_DIR}}/ERC20Portal.json` \ diff --git a/prt/tests/rollups/test_cases/simple.lua b/prt/tests/rollups/test_cases/simple.lua index bfdb3026..269a4855 100755 --- a/prt/tests/rollups/test_cases/simple.lua +++ b/prt/tests/rollups/test_cases/simple.lua @@ -5,7 +5,7 @@ local env = require "test_env" -- Main Execution -env.spawn_blockchain {env.sample_inputs[1]} +env.spawn_blockchain { env.sample_inputs[1] } local first_epoch = assert(env.reader:read_epochs_sealed()[1]) assert(first_epoch.input_upper_bound == 1) -- there's one input for epoch 0 already! diff --git a/prt/tests/rollups/test_env.lua b/prt/tests/rollups/test_env.lua index e6ca8a85..56b18c41 100644 --- a/prt/tests/rollups/test_env.lua +++ b/prt/tests/rollups/test_env.lua @@ -56,10 +56,12 @@ function Env.spawn_blockchain(inputs) local blockchain = Blockchain:new(ANVIL_LOAD_PATH, ANVIL_DUMP_PATH) Env.blockchain = blockchain - Env.reader = Reader:new(INPUT_BOX_ADDRESS, DAVE_APP_FACTORY_ADDRESS, TEMPLATE_MACHINE_HASH, SALT, blockchain.endpoint) + Env.reader = Reader:new(INPUT_BOX_ADDRESS, DAVE_APP_FACTORY_ADDRESS, TEMPLATE_MACHINE_HASH, SALT, blockchain + .endpoint) Env.app_address = Env.reader.app_address Env.consensus_address = Env.reader.consensus_address - Env.sender = Sender:new(INPUT_BOX_ADDRESS, DAVE_APP_FACTORY_ADDRESS, Env.app_address, blockchain.pks[1], blockchain.endpoint) + Env.sender = Sender:new(INPUT_BOX_ADDRESS, DAVE_APP_FACTORY_ADDRESS, Env.app_address, blockchain.pks[1], + blockchain.endpoint) Env.sender:tx_add_inputs(inputs) Env.sender:tx_new_dave_app(TEMPLATE_MACHINE_HASH, SALT) Env.sender:advance_blocks(2) diff --git a/test/programs/justfile b/test/programs/justfile index c5acdb2d..6f30ba3a 100644 --- a/test/programs/justfile +++ b/test/programs/justfile @@ -1,7 +1,7 @@ download-deps: clean-deps wget https://github.com/cartesi/image-kernel/releases/download/v0.20.0/linux-6.5.13-ctsi-1-v0.20.0.bin \ -O ./linux.bin - wget https://github.com/cartesi/machine-emulator-tools/releases/download/v0.17.1/rootfs-tools.ext2 \ + wget https://github.com/cartesi/machine-emulator-tools/releases/download/v0.17.2/rootfs-tools.ext2 \ -O ./rootfs.ext2 clean-deps: @@ -16,16 +16,16 @@ clean-program prog: # yield build-yield: clean-yield - cartesi-machine --ram-image=./linux.bin \ - --flash-drive=label:root,filename:./rootfs.ext2 \ + cartesi-machine --ram-image=./linux.bin --final-hash \ + --flash-drive=label:root,data_filename:./rootfs.ext2 \ --no-rollback --store=./yield/machine-image \ -- "while true; do yield manual rx-accepted; yield manual rx-rejected; done" clean-yield: (clean-program "yield") # echo build-echo: clean-echo - cartesi-machine --ram-image=./linux.bin \ - --flash-drive=label:root,filename:./rootfs.ext2 \ + cartesi-machine --ram-image=./linux.bin --final-hash \ + --flash-drive=label:root,data_filename:./rootfs.ext2 \ --no-rollback --store=./echo/machine-image \ -- "ioctl-echo-loop --vouchers=1 --notices=1 --reports=1 --verbose=1 --reject=2" clean-echo: (clean-program "echo") @@ -34,6 +34,9 @@ clean-echo: (clean-program "echo") build-honeypot-snapshot: clean-honeypot-snapshot clean-honeypot-project git clone https://github.com/cartesi/honeypot.git honeypot/project git -C honeypot/project reset --hard 34d00721a527eeb7ed8cce2a13a142e3d8de9aad # v3.0.0 + sed -i 's/,filename:/,data_filename:/g' honeypot/project/Makefile + sed -i 's/--append-bootargs=ro/--append-bootargs=rw/g' honeypot/project/Makefile + sed -i 's/label:state,length:4096,user:dapp/label:state,length:4096,user:dapp,mke2fs:false,mount:false/g' honeypot/project/Makefile mkdir -p honeypot/project/config/devnet ./honeypot/generate-devnet-honeypot-config.sh > honeypot/project/config/devnet/honeypot-config.hpp make -C honeypot/project snapshot HONEYPOT_CONFIG=devnet @@ -44,8 +47,8 @@ clean-honeypot-project: # compute build-compute: clean-compute - cartesi-machine --ram-image=./linux.bin \ - --flash-drive=label:root,filename:./rootfs.ext2 \ + cartesi-machine --ram-image=./linux.bin --final-hash \ + --flash-drive=label:root,data_filename:./rootfs.ext2 \ --no-rollback --store=./compute/machine-image \ --max-mcycle=0 \ -- "while dd if=/dev/zero bs=1M count=64 2>/dev/null | md5sum >/dev/null; do :; done"