From 46cf7ce61597f7d0149b75203031322c060c3497 Mon Sep 17 00:00:00 2001 From: joii Date: Mon, 9 Sep 2024 22:39:17 +0800 Subject: [PATCH 1/3] TODO Add spawn interfact --- src/context.rs | 65 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/context.rs b/src/context.rs index 7832ce3..a22877f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -17,6 +17,7 @@ use ckb_types::{ }; use rand::{thread_rng, Rng}; use std::collections::HashMap; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; /// Return a random hash @@ -61,15 +62,16 @@ pub struct Context { pub cells_by_type_hash: HashMap, capture_debug: bool, captured_messages: Arc>>, + contracts_dirs: Vec, #[cfg(feature = "native-simulator")] - simulator_binaries: HashMap, - contracts_dir: std::path::PathBuf, + simulator_binaries: HashMap, + #[cfg(feature = "native-simulator")] + simulator_bin_name: String, } impl Default for Context { fn default() -> Self { use std::env; - use std::path::PathBuf; // Get from $TOP/build/$MODE let mut contracts_dir = env::var("TOP").map(PathBuf::from).unwrap_or_default(); @@ -90,14 +92,20 @@ impl Default for Context { cells_by_type_hash: Default::default(), capture_debug: Default::default(), captured_messages: Default::default(), + contracts_dirs: vec![contracts_dir], #[cfg(feature = "native-simulator")] simulator_binaries: Default::default(), - contracts_dir, + #[cfg(feature = "native-simulator")] + simulator_bin_name: "lib_sim".to_string(), } } } impl Context { + pub fn add_contract_dir(&mut self, path: &str) { + self.contracts_dirs.push(path.into()); + } + #[deprecated(since = "0.1.1", note = "Please use the deploy_cell function instead")] pub fn deploy_contract(&mut self, data: Bytes) -> OutPoint { self.deploy_cell(data) @@ -137,25 +145,50 @@ impl Context { } pub fn deploy_cell_by_name(&mut self, filename: &str) -> OutPoint { - let path = self.contracts_dir.join(filename); + let path = self.get_contract_path(filename).expect("get contract path"); let data = std::fs::read(&path).unwrap_or_else(|_| panic!("read local file: {:?}", path)); #[cfg(feature = "native-simulator")] { - let native_path = self.contracts_dir.join(format!( - "lib{}_dbg.{}", - filename.replace("-", "_"), - std::env::consts::DLL_EXTENSION - )); - if native_path.is_file() { + let native_path = self.get_native_simulator_path(filename); + if native_path.is_some() { let code_hash = CellOutput::calc_data_hash(&data); - self.simulator_binaries.insert(code_hash, native_path); + self.simulator_binaries + .insert(code_hash, native_path.unwrap()); } } self.deploy_cell(data.into()) } + fn get_contract_path(&self, filename: &str) -> Option { + for dir in &self.contracts_dirs { + let path = dir.join(filename); + if path.is_file() { + return Some(path); + } + } + + None + } + + #[cfg(feature = "native-simulator")] + fn get_native_simulator_path(&self, filename: &str) -> Option { + let cdylib_name = format!( + "{}.{}", + self.simulator_bin_name + .replace("", &filename.replace("-", "_")), + std::env::consts::DLL_EXTENSION + ); + for dir in &self.contracts_dirs { + let path = dir.join(&cdylib_name); + if path.is_file() { + return Some(path); + } + } + None + } + /// Insert a block header into context pub fn insert_header(&mut self, header: HeaderView) { self.headers.insert(header.hash(), header); @@ -455,7 +488,7 @@ impl Context { std::fs::create_dir(tmp_dir.clone()) .expect("create tmp dir: ckb-simulator-debugger"); } - let tx_file: std::path::PathBuf = tmp_dir.join("ckb_running_tx.json"); + let tx_file: PathBuf = tmp_dir.join("ckb_running_tx.json"); let dump_tx = self.dump_tx(&tx)?; let tx_json = serde_json::to_string(&dump_tx).expect("dump tx to string"); @@ -543,8 +576,8 @@ impl Context { verifier .verify_single(group.group_type, hash, max_cycles) .map_err(|e| { - #[cfg(feature = "logging")] - logging::on_script_error(_hash, &self.hash(), &e); + // #[cfg(feature = "logging")] + // logging::on_script_error(_hash, &self.hash(), &e); e.source(group) })? } @@ -562,7 +595,7 @@ impl Context { #[cfg(feature = "native-simulator")] pub fn set_simulator(&mut self, code_hash: Byte32, path: &str) { - let path = std::path::PathBuf::from(path); + let path = PathBuf::from(path); assert!(path.is_file()); self.simulator_binaries.insert(code_hash, path); } From feac46e82b19fa5c4ee431a0207ec1c816c91e71 Mon Sep 17 00:00:00 2001 From: joii2020 Date: Thu, 26 Sep 2024 10:49:46 +0800 Subject: [PATCH 2/3] Optimize the code structure of native-simulator --- Cargo.lock | 87 +++++++++++++++---- src/context.rs | 221 ++++++++++++++++++++++++++----------------------- 2 files changed, 189 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 485963d..59fe233 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -968,7 +968,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1709,7 +1709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ "windows-core", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1722,7 +1722,7 @@ dependencies = [ "windows-interface", "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1753,7 +1753,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1763,7 +1763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1772,7 +1772,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1781,7 +1781,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1790,28 +1805,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1824,24 +1857,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/src/context.rs b/src/context.rs index a22877f..73e9980 100644 --- a/src/context.rs +++ b/src/context.rs @@ -476,121 +476,134 @@ impl Context { #[cfg(feature = "native-simulator")] { - use core::ffi::c_int; - pub struct Arg(()); - type CkbMainFunc<'a> = - libloading::Symbol<'a, unsafe extern "C" fn(argc: c_int, argv: *const Arg) -> i8>; - - let mut cycles: Cycle = 0; - let tmp_dir = if !self.simulator_binaries.is_empty() { - let tmp_dir = std::env::temp_dir().join("ckb-simulator-debugger"); - if !tmp_dir.exists() { - std::fs::create_dir(tmp_dir.clone()) - .expect("create tmp dir: ckb-simulator-debugger"); - } - let tx_file: PathBuf = tmp_dir.join("ckb_running_tx.json"); - let dump_tx = self.dump_tx(&tx)?; + self.native_simulator_verify(tx, verifier, max_cycles) + } + #[cfg(not(feature = "native-simulator"))] + verifier.verify(max_cycles) + } - let tx_json = serde_json::to_string(&dump_tx).expect("dump tx to string"); - std::fs::write(&tx_file, tx_json).expect("write setup"); + #[cfg(feature = "native-simulator")] + fn native_simulator_verify
( + &self, + tx: &TransactionView, + verifier: TransactionScriptsVerifier
, + max_cycles: u64, + ) -> Result + where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, + { + let mut cycles: Cycle = 0; + + for (hash, group) in verifier.groups() { + let code_hash = if group.script.hash_type() == ScriptHashType::Type.into() { + let code_hash = group.script.code_hash(); + let out_point = match self.cells_by_type_hash.get(&code_hash) { + Some(out_point) => out_point, + None => panic!("unknow code hash(ScriptHashType::Type)"), + }; - std::env::set_var("CKB_TX_FILE", tx_file.to_str().unwrap()); - Some(tmp_dir) + match self.cells.get(out_point) { + Some((_cell, bin)) => CellOutput::calc_data_hash(bin), + None => panic!("unknow code hash(ScriptHashType::Type) in deps"), + } } else { - None + group.script.code_hash() }; - let mut native_binaries = self - .simulator_binaries - .iter() - .map(|(code_hash, path)| { - let buf = vec![ - code_hash.as_bytes().to_vec(), - vec![0xff], - 0u32.to_le_bytes().to_vec(), - 0u32.to_le_bytes().to_vec(), - ] - .concat(); - - format!( - "\"0x{}\" : \"{}\",", - faster_hex::hex_string(&buf), - path.to_str().unwrap() - ) - }) - .collect::>() - .concat(); - if !native_binaries.is_empty() { - native_binaries.pop(); - } + let use_cycles = match self.simulator_binaries.get(&code_hash) { + Some(sim_path) => self.run_simulator(sim_path, tx, group), + None => { + group.script.code_hash(); + verifier + .verify_single(group.group_type, hash, max_cycles) + .map_err(|e| e.source(group))? + } + }; + let r = cycles.overflowing_add(use_cycles); + assert!(!r.1, "cycles overflow"); + cycles = r.0; + } + Ok(cycles) + } - let native_binaries = format!("{{ {} }}", native_binaries); + #[cfg(feature = "native-simulator")] + fn run_simulator( + &self, + sim_path: &PathBuf, + tx: &TransactionView, + group: &ckb_script::ScriptGroup, + ) -> u64 { + println!( + "run native-simulator: {}", + sim_path.file_name().unwrap().to_str().unwrap() + ); + let tmp_dir = if !self.simulator_binaries.is_empty() { + let tmp_dir = std::env::temp_dir().join("ckb-simulator-debugger"); + if !tmp_dir.exists() { + std::fs::create_dir(tmp_dir.clone()) + .expect("create tmp dir: ckb-simulator-debugger"); + } + let tx_file: PathBuf = tmp_dir.join("ckb_running_tx.json"); + let dump_tx = self.dump_tx(&tx).unwrap(); - for (hash, group) in verifier.groups() { - let code_hash = if group.script.hash_type() == ScriptHashType::Type.into() { - let code_hash = group.script.code_hash(); - let out_point = match self.cells_by_type_hash.get(&code_hash) { - Some(out_point) => out_point, - None => panic!("unknow code hash(ScriptHashType::Type)"), - }; + let tx_json = serde_json::to_string(&dump_tx).expect("dump tx to string"); + std::fs::write(&tx_file, tx_json).expect("write setup"); - match self.cells.get(out_point) { - Some((_cell, bin)) => CellOutput::calc_data_hash(bin), - None => panic!("unknow code hash(ScriptHashType::Type) in deps"), - } - } else { - group.script.code_hash() - }; + std::env::set_var("CKB_TX_FILE", tx_file.to_str().unwrap()); + Some(tmp_dir) + } else { + None + }; + let running_setup = tmp_dir.as_ref().unwrap().join("ckb_running_setup.json"); + + let mut native_binaries = self + .simulator_binaries + .iter() + .map(|(code_hash, path)| { + let buf = vec![ + code_hash.as_bytes().to_vec(), + vec![0xff], + 0u32.to_le_bytes().to_vec(), + 0u32.to_le_bytes().to_vec(), + ] + .concat(); - let use_cycles = match self.simulator_binaries.get(&code_hash) { - Some(sim_path) => { - println!( - "run native-simulator: {}", - sim_path.file_name().unwrap().to_str().unwrap() - ); - let running_setup = - tmp_dir.as_ref().unwrap().join("ckb_running_setup.json"); - - let setup = format!( - "{{\"is_lock_script\": {}, \"is_output\": false, \"script_index\": {}, \"vm_version\": 1, \"native_binaries\": {}, \"run_type\": \"DynamicLib\" }}", - group.group_type == ckb_script::ScriptGroupType::Lock, - group.input_indices[0], native_binaries - ); - println!("---- setup: {}", &setup); - std::fs::write(&running_setup, setup).expect("write setup"); - std::env::set_var("CKB_RUNNING_SETUP", running_setup.to_str().unwrap()); - - unsafe { - if let Ok(lib) = libloading::Library::new(sim_path) { - if let Ok(func) = lib.get(b"__ckb_std_main") { - let func: CkbMainFunc = func; - let rc = { func(0, [].as_ptr()) }; - assert!(rc == 0, "run native-simulator failed"); - } - } - } - 0 - } - None => { - group.script.code_hash(); - verifier - .verify_single(group.group_type, hash, max_cycles) - .map_err(|e| { - // #[cfg(feature = "logging")] - // logging::on_script_error(_hash, &self.hash(), &e); - e.source(group) - })? - } - }; - let r = cycles.overflowing_add(use_cycles); - assert!(!r.1, "cycles overflow"); - cycles = r.0; - } - Ok(cycles) + format!( + "\"0x{}\" : \"{}\",", + faster_hex::hex_string(&buf), + path.to_str().unwrap() + ) + }) + .collect::>() + .concat(); + if !native_binaries.is_empty() { + native_binaries.pop(); } - #[cfg(not(feature = "native-simulator"))] - verifier.verify(max_cycles) + let native_binaries = format!("{{ {} }}", native_binaries); + + let setup = format!( + "{{\"is_lock_script\": {}, \"is_output\": false, \"script_index\": {}, \"vm_version\": {}, \"native_binaries\": {}, \"run_type\": \"DynamicLib\" }}", + group.group_type == ckb_script::ScriptGroupType::Lock, + group.input_indices[0], 2, native_binaries + ); + std::fs::write(&running_setup, setup).expect("write setup"); + std::env::set_var("CKB_RUNNING_SETUP", running_setup.to_str().unwrap()); + + type CkbMainFunc<'a> = + libloading::Symbol<'a, unsafe extern "C" fn(argc: i32, argv: *const *const i8) -> i8>; + + // ckb_x64_simulator::run_native_simulator(sim_path); + unsafe { + let lib = libloading::Library::new(sim_path).expect("Load library"); + + let func: CkbMainFunc = lib + .get(b"__ckb_std_main") + .expect("load function : __ckb_std_main"); + let argv = vec![]; + func(0, argv.as_ptr()); + } + 0 } #[cfg(feature = "native-simulator")] From 281c4ec6e8db9c6e86d9196b734f3494539165b2 Mon Sep 17 00:00:00 2001 From: joii2020 Date: Mon, 30 Sep 2024 21:24:03 +0800 Subject: [PATCH 3/3] Run set_script_info before ckb_main when native simulator --- src/context.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/context.rs b/src/context.rs index 73e9980..6fd521a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -592,11 +592,20 @@ impl Context { type CkbMainFunc<'a> = libloading::Symbol<'a, unsafe extern "C" fn(argc: i32, argv: *const *const i8) -> i8>; + type SetScriptInfo<'a> = libloading::Symbol< + 'a, + unsafe extern "C" fn(ptr: *const std::ffi::c_void, tx_ctx_id: u64, vm_ctx_id: u64), + >; // ckb_x64_simulator::run_native_simulator(sim_path); unsafe { let lib = libloading::Library::new(sim_path).expect("Load library"); + let func: SetScriptInfo = lib + .get(b"__set_script_info") + .expect("load function : __update_spawn_info"); + func(std::ptr::null(), 0, 0); + let func: CkbMainFunc = lib .get(b"__ckb_std_main") .expect("load function : __ckb_std_main");