diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9a5ff45..1cd5360 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -9,6 +9,10 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Deps + run: | + wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 18 && rm llvm.sh + rustup target add riscv64imac-unknown-none-elf - name: Install Rust components run: rustup component add rustfmt clippy - name: Check format @@ -19,4 +23,7 @@ jobs: run: cargo build - name: Run cargo test run: cargo test --all - \ No newline at end of file + - name: Build native-simulator test contracts + run: cd tests/test-contracts && make build + - name: Run cargo test (with native-simulator) + run: cargo test --features="native-simulator" --all diff --git a/Cargo.lock b/Cargo.lock index 429cbac..3f69102 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 203f249..f88a914 100644 --- a/src/context.rs +++ b/src/context.rs @@ -17,6 +17,7 @@ use ckb_types::{ }; use rand::{rngs::StdRng, thread_rng, Rng, SeedableRng}; use std::collections::HashMap; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; /// Return a random hash @@ -62,15 +63,16 @@ pub struct Context { deterministic_rng: bool, 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(); @@ -92,9 +94,11 @@ impl Default for Context { deterministic_rng: false, 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(), } } } @@ -107,6 +111,9 @@ impl Context { ..Default::default() } } + 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 { @@ -156,25 +163,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); @@ -462,126 +494,148 @@ 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: std::path::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>; + 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"); + let argv = vec![]; + func(0, argv.as_ptr()); + } + 0 } #[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); } diff --git a/tests/native_simulator_cases.rs b/tests/native_simulator_cases.rs new file mode 100644 index 0000000..80c8767 --- /dev/null +++ b/tests/native_simulator_cases.rs @@ -0,0 +1,80 @@ +#[cfg(feature = "native-simulator")] +mod native_simulator_cases { + + use ckb_testtool::{ + ckb_types::{ + bytes::Bytes, + core::{ScriptHashType, TransactionBuilder}, + packed::{CellInput, CellOutput}, + prelude::*, + }, + context::Context, + }; + + const MAX_CYCLES: u64 = 500_000_000_000; + + #[test] + fn test_spawn() { + let mut context = Context::default(); + + context.add_contract_dir("test-contracts/target/debug/"); + context.add_contract_dir("tests/test-contracts/target/debug/"); + context.add_contract_dir("test-contracts/build/release/"); + context.add_contract_dir("tests/test-contracts/build/release/"); + + let out_point_parent = context.deploy_cell_by_name("simple-spawn"); + + let args: Vec = vec![]; + + let lock_script = context + .build_script_with_hash_type( + &out_point_parent, + ScriptHashType::Data2, + Default::default(), + ) + .expect("script") + .as_builder() + .args(args.pack()) + .build(); + let input: CellInput = CellInput::new_builder() + .previous_output( + context.create_cell( + CellOutput::new_builder() + .capacity(1000u64.pack()) + .lock(lock_script.clone()) + .build(), + Bytes::new(), + ), + ) + .build(); + + let outputs = vec![ + CellOutput::new_builder() + .capacity(500u64.pack()) + .lock(lock_script.clone()) + .build(), + CellOutput::new_builder() + .capacity(500u64.pack()) + .lock(lock_script) + .build(), + ]; + + let outputs_data = vec![Bytes::new(); 2]; + + // build transaction + let tx = TransactionBuilder::default() + // .set_inputs(vec![input, input3, input2]) + .set_inputs(vec![input]) + .outputs(outputs) + .outputs_data(outputs_data.pack()) + .build(); + + let tx = context.complete_tx(tx); + + // run + let result = context.verify_tx(&tx, MAX_CYCLES); + let cycles = result.unwrap(); + + println!("Cycles: {}", cycles); + } +} diff --git a/tests/test-contracts/.gitignore b/tests/test-contracts/.gitignore new file mode 100644 index 0000000..0ff4f2f --- /dev/null +++ b/tests/test-contracts/.gitignore @@ -0,0 +1,3 @@ +/build +/target +/tests/failed_txs diff --git a/tests/test-contracts/Cargo.lock b/tests/test-contracts/Cargo.lock new file mode 100644 index 0000000..39a3ac0 --- /dev/null +++ b/tests/test-contracts/Cargo.lock @@ -0,0 +1,767 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "blake2b-ref" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "294d17c72e0ba59fad763caa112368d0672083779cdebbb97164f4bb4c1e339a" + +[[package]] +name = "blake2b-rs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89a8565807f21b913288968e391819e7f9b2f0f46c7b89549c051cccf3a2771" +dependencies = [ + "cc", + "cty", +] + +[[package]] +name = "buddy-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee741d62dcaf41ca303576ef890989ccb01d5dd77f8ce1a6d6c7846ab5d09efb" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907d8581360765417f8f2e0e7d602733bbed60156b4465b7617243689ef9b83d" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ckb-channel" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4c7f5530737f8a02329075581b29ab7003a72d6ee747d1b2ea9d2239faea7a" +dependencies = [ + "crossbeam-channel", +] + +[[package]] +name = "ckb-constant" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e1424bf7490c14cdbd13697629ece8c1ba0ed02ff1c8a5b14a8713431ec6ff8" + +[[package]] +name = "ckb-error" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109adb3c26e697861e3f57c1ca8cf2f2a399c46e64c97be2b05f751535ac1b75" +dependencies = [ + "anyhow", + "ckb-occupied-capacity", + "derive_more", + "thiserror", +] + +[[package]] +name = "ckb-fixed-hash" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ea8f4896f945ecdb473cc8b747a47a9f282393a37a681bcbe0cdde94894bfc" +dependencies = [ + "ckb-fixed-hash-core", + "ckb-fixed-hash-macros", +] + +[[package]] +name = "ckb-fixed-hash-core" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c265cd6b0ec00b8dc671b9344906a2428f9b756e4e789660c71f535252fe2d" +dependencies = [ + "ckb_schemars", + "faster-hex", + "serde", + "thiserror", +] + +[[package]] +name = "ckb-fixed-hash-macros" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976b10df5474be0ff33b22a84b44875e065679fc41155350c11e420124910ca1" +dependencies = [ + "ckb-fixed-hash-core", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ckb-gen-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc221d4b9d6d39215b1d62be855861b8b0c8d668ca29874903b0bf5d0b4d9fa" +dependencies = [ + "cfg-if", + "ckb-error", + "ckb-fixed-hash", + "ckb-hash", + "ckb-occupied-capacity", + "molecule", + "numext-fixed-uint", +] + +[[package]] +name = "ckb-hash" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ba7c72f86f239b3e0154f51d6cd5d0d83bbaa8775fdc7b6bcac459ae24b6fd" +dependencies = [ + "blake2b-ref", + "blake2b-rs", +] + +[[package]] +name = "ckb-jsonrpc-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3983584cc6e269125c3bf502fa6d84a4f6e47d5b4c1e3a4070db86382ed4ba15" +dependencies = [ + "ckb-types", + "ckb_schemars", + "faster-hex", + "serde", + "serde_json", +] + +[[package]] +name = "ckb-merkle-mountain-range" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ccb671c5921be8a84686e6212ca184cb1d7c51cadcdbfcbd1cc3f042f5dfb8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ckb-mock-tx-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bce36d06097bca7df141a89ba970566bbf4075945c6dd95a0771e8830c2c1a8" +dependencies = [ + "ckb-jsonrpc-types", + "ckb-traits", + "ckb-types", + "serde", +] + +[[package]] +name = "ckb-occupied-capacity" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6b706bce252b627543ce3bac5240f4d2f1e5d73daca9e451c88db44c2ea94bb" +dependencies = [ + "ckb-occupied-capacity-core", + "ckb-occupied-capacity-macros", +] + +[[package]] +name = "ckb-occupied-capacity-core" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510608e5c7c2f3bf025c6ae80ed7782a1cd12897e15dc930167c8dbd3165ece6" +dependencies = [ + "serde", +] + +[[package]] +name = "ckb-occupied-capacity-macros" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79a3fd71708b5068fb377497d6be6dbca53725f1a13d174335105c4bd39ffd5" +dependencies = [ + "ckb-occupied-capacity-core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ckb-rational" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91835c60dba878e54da2dfcfad62369638b88f910d9e8c7eb31f9c357a331ff7" +dependencies = [ + "numext-fixed-uint", + "serde", +] + +[[package]] +name = "ckb-std" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a673595baadfa1712ff03a36e1519f28015cf9944282410863d5e256336f5b9" +dependencies = [ + "buddy-alloc", + "cc", + "ckb-gen-types", + "ckb-x64-simulator", + "gcd", +] + +[[package]] +name = "ckb-traits" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab91cb32bd5655b5b4c6574d6f07dd919d93759dc9e07f9ee6a2a9823848c4dc" +dependencies = [ + "ckb-types", +] + +[[package]] +name = "ckb-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02dc76ea18e9838ec996c0f1f8a822d65176d2c9f052b3855c1d0a2d0a4d885" +dependencies = [ + "bit-vec", + "bytes", + "ckb-channel", + "ckb-constant", + "ckb-error", + "ckb-fixed-hash", + "ckb-gen-types", + "ckb-hash", + "ckb-merkle-mountain-range", + "ckb-occupied-capacity", + "ckb-rational", + "derive_more", + "golomb-coded-set", + "merkle-cbt", + "molecule", + "numext-fixed-uint", + "once_cell", + "paste", +] + +[[package]] +name = "ckb-x64-simulator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4734273cff42f99205f5d3b6d6673786339443ca169ed5ff85bfc69730d910" +dependencies = [ + "cc", + "ckb-mock-tx-types", + "ckb-types", + "faster-hex", + "lazy_static", + "libc", + "libloading", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "ckb_schemars" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21f99fca82a4eb8708e406e99246987b087ecc1e1babeece1a0b1d5238b1750" +dependencies = [ + "ckb_schemars_derive", + "dyn-clone", + "serde", + "serde_json", +] + +[[package]] +name = "ckb_schemars_derive" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c813b4fadbdd9f33b1cf02a1ddfa9537d955c8d2fbe150d1fc1684dbf78e73" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "faster-hex" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "golomb-coded-set" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f314a99fb5b7f0f9d0a8388539578f83f3aca6a65f588b8dbeefb731e2f98" +dependencies = [ + "siphasher", +] + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +dependencies = [ + "winapi", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "merkle-cbt" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171d2f700835121c3b04ccf0880882987a050fd5c7ae88148abf537d33dd3a56" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "molecule" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6efe1c7efcd0bdf4ca590e104bcb13087d9968956ae4ae98e92fb8c1da0f3730" +dependencies = [ + "bytes", + "cfg-if", + "faster-hex", +] + +[[package]] +name = "numext-constructor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621fe0f044729f810c6815cdd77e8f5e0cd803ce4f6a38380ebfc1322af98661" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "numext-fixed-uint" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c68c76f96d589d1009a666c5072f37f3114d682696505f2cf445f27766c7d70" +dependencies = [ + "numext-fixed-uint-core", + "numext-fixed-uint-hack", +] + +[[package]] +name = "numext-fixed-uint-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aab1d6457b97b49482f22a92f0f58a2f39bdd7f3b2f977eae67e8bc206aa980" +dependencies = [ + "heapsize", + "numext-constructor", + "rand", + "serde", + "thiserror", +] + +[[package]] +name = "numext-fixed-uint-hack" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200f8d55c36ec1b6a8cf810115be85d4814f045e0097dfd50033ba25adb4c9e" +dependencies = [ + "numext-fixed-uint-core", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "simple-spawn" +version = "0.1.0" +dependencies = [ + "ckb-std", +] + +[[package]] +name = "simple-spawn-sim" +version = "0.1.0" +dependencies = [ + "ckb-std", + "simple-spawn", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-targets" +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_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/tests/test-contracts/Cargo.toml b/tests/test-contracts/Cargo.toml new file mode 100644 index 0000000..642519b --- /dev/null +++ b/tests/test-contracts/Cargo.toml @@ -0,0 +1,15 @@ +[workspace] +resolver = "2" + +members = [ + # Please don't remove the following line, we use it to automatically + # detect insertion point for newly generated crates. + # @@INSERTION_POINT@@ + "native-simulators/simple-spawn-sim", + "contracts/simple-spawn", +] + +[profile.release] +overflow-checks = true +strip = true +codegen-units = 1 \ No newline at end of file diff --git a/tests/test-contracts/Makefile b/tests/test-contracts/Makefile new file mode 100644 index 0000000..a784fe0 --- /dev/null +++ b/tests/test-contracts/Makefile @@ -0,0 +1,137 @@ +# We cannot use $(shell pwd), which will return unix path format on Windows, +# making it hard to use. +cur_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +TOP := $(cur_dir) +# RUSTFLAGS that are likely to be tweaked by developers. For example, +# while we enable debug logs by default here, some might want to strip them +# for minimal code size / consumed cycles. +CUSTOM_RUSTFLAGS := -C debug-assertions +# Additional cargo args to append here. For example, one can use +# make test CARGO_ARGS="-- --nocapture" so as to inspect data emitted to +# stdout in unit tests +CARGO_ARGS := +MODE := release +# Tweak this to change the clang version to use for building C code. By default +# we use a bash script with somes heuristics to find clang in current system. +CLANG := $(shell $(TOP)/scripts/find_clang) +# When this is set, a single contract will be built instead of all contracts +CONTRACT := +# By default, we would clean build/{release,debug} folder first, in case old +# contracts are mixed together with new ones, if for some reason you want to +# revert this behavior, you can change this to anything other than true +CLEAN_BUILD_DIR_FIRST := true +BUILD_DIR := build/$(MODE) + +ifeq (release,$(MODE)) + MODE_ARGS := --release +endif + +# Pass setups to child make processes +export CUSTOM_RUSTFLAGS +export TOP +export CARGO_ARGS +export MODE +export CLANG +export BUILD_DIR + +default: build + +build: + @if [ "x$(CLEAN_BUILD_DIR_FIRST)" = "xtrue" ]; then \ + echo "Cleaning $(BUILD_DIR) directory..."; \ + rm -rf $(BUILD_DIR); \ + fi + mkdir -p $(BUILD_DIR) + @set -eu; \ + if [ "x$(CONTRACT)" = "x" ]; then \ + for contract in $(wildcard contracts/*); do \ + $(MAKE) -e -C $$contract build; \ + done; \ + for crate in $(wildcard crates/*); do \ + cargo build -p $$(basename $$crate) $(MODE_ARGS) $(CARGO_ARGS); \ + done; \ + for sim in $(wildcard native-simulators/*); do \ + cargo build -p $$(basename $$sim) $(CARGO_ARGS); \ + done; \ + else \ + $(MAKE) -e -C contracts/$(CONTRACT) build; \ + cargo build -p $(CONTRACT)-sim; \ + fi; + +# Run a single make task for a specific contract. For example: +# +# make run CONTRACT=stack-reorder TASK=adjust_stack_size STACK_SIZE=0x200000 +TASK := +run: + $(MAKE) -e -C contracts/$(CONTRACT) $(TASK) + +check: + cargo check $(CARGO_ARGS) + +clippy: + cargo clippy $(CARGO_ARGS) + +fmt: + cargo fmt $(CARGO_ARGS) + +# Arbitrary cargo command is supported here. For example: +# +# make cargo CARGO_CMD=expand CARGO_ARGS="--ugly" +# +# Invokes: +# cargo expand --ugly +CARGO_CMD := +cargo: + cargo $(CARGO_CMD) $(CARGO_ARGS) + +clean: + rm -rf build + cargo clean + +TEMPLATE_TYPE := --git +TEMPLATE_REPO := https://github.com/cryptape/ckb-script-templates +CRATE := +TEMPLATE := contract +DESTINATION := contracts +generate: + @set -eu; \ + if [ "x$(CRATE)" = "x" ]; then \ + cargo generate $(TEMPLATE_TYPE) $(TEMPLATE_REPO) $(TEMPLATE) \ + --destination $(DESTINATION); \ + GENERATED_DIR=$$(ls -dt $(DESTINATION)/* | head -n 1); \ + if [ -f "$$GENERATED_DIR/.cargo-generate/tests.rs" ]; then \ + cat $$GENERATED_DIR/.cargo-generate/tests.rs >> tests/src/tests.rs; \ + rm -rf $$GENERATED_DIR/.cargo-generate/; \ + fi; \ + sed "s,@@INSERTION_POINT@@,@@INSERTION_POINT@@\n \"$$GENERATED_DIR\"\,," Cargo.toml > Cargo.toml.new; \ + mv Cargo.toml.new Cargo.toml; \ + else \ + cargo generate $(TEMPLATE_TYPE) $(TEMPLATE_REPO) $(TEMPLATE) \ + --destination $(DESTINATION) \ + --name $(CRATE); \ + if [ -f "$(DESTINATION)/$(CRATE)/.cargo-generate/tests.rs" ]; then \ + cat $(DESTINATION)/$(CRATE)/.cargo-generate/tests.rs >> tests/src/tests.rs; \ + rm -rf $(DESTINATION)/$(CRATE)/.cargo-generate/; \ + fi; \ + sed '/@@INSERTION_POINT@@/s/$$/\n "$(DESTINATION)\/$(CRATE)",/' Cargo.toml > Cargo.toml.new; \ + mv Cargo.toml.new Cargo.toml; \ + fi; + +generate-native-simulator: + @set -eu; \ + cargo generate $(TEMPLATE_TYPE) $(TEMPLATE_REPO) native-simulator \ + -n $(CRATE)-sim \ + --destination native-simulators; \ + sed '/@@INSERTION_POINT@@/s/$$/\n "native-simulators\/$(CRATE)-sim",/' Cargo.toml > Cargo.toml.new; \ + mv Cargo.toml.new Cargo.toml; + +prepare: + rustup target add riscv64imac-unknown-none-elf + +# Generate checksum info for reproducible build +CHECKSUM_FILE := build/checksums-$(MODE).txt +checksum: build + shasum -a 256 build/$(MODE)/* > $(CHECKSUM_FILE) + +.PHONY: build check clippy fmt cargo clean prepare checksum diff --git a/tests/test-contracts/README.md b/tests/test-contracts/README.md new file mode 100644 index 0000000..c770eba --- /dev/null +++ b/tests/test-contracts/README.md @@ -0,0 +1,7 @@ +# test-contracts + +TODO: Write this readme + +*This project was bootstrapped with [ckb-script-templates].* + +[ckb-script-templates]: https://github.com/cryptape/ckb-script-templates diff --git a/tests/test-contracts/contracts/simple-spawn/.gitignore b/tests/test-contracts/contracts/simple-spawn/.gitignore new file mode 100644 index 0000000..c3dca1b --- /dev/null +++ b/tests/test-contracts/contracts/simple-spawn/.gitignore @@ -0,0 +1,2 @@ +/build +/target diff --git a/tests/test-contracts/contracts/simple-spawn/Cargo.toml b/tests/test-contracts/contracts/simple-spawn/Cargo.toml new file mode 100644 index 0000000..021ad7c --- /dev/null +++ b/tests/test-contracts/contracts/simple-spawn/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "simple-spawn" +version = "0.1.0" +edition = "2021" + +[dependencies] +ckb-std = "0.16.3" + +[features] +native-simulator = ["ckb-std/native-simulator"] diff --git a/tests/test-contracts/contracts/simple-spawn/Makefile b/tests/test-contracts/contracts/simple-spawn/Makefile new file mode 100644 index 0000000..6577c81 --- /dev/null +++ b/tests/test-contracts/contracts/simple-spawn/Makefile @@ -0,0 +1,78 @@ +# We cannot use $(shell pwd), which will return unix path format on Windows, +# making it hard to use. +cur_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +TOP := $(cur_dir) +# RUSTFLAGS that are likely to be tweaked by developers. For example, +# while we enable debug logs by default here, some might want to strip them +# for minimal code size / consumed cycles. +CUSTOM_RUSTFLAGS := -C debug-assertions +# RUSTFLAGS that are less likely to be tweaked by developers. Most likely +# one would want to keep the default values here. +FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs,-a $(CUSTOM_RUSTFLAGS) +# Additional cargo args to append here. For example, one can use +# make test CARGO_ARGS="-- --nocapture" so as to inspect data emitted to +# stdout in unit tests +CARGO_ARGS := +MODE := release +# Tweak this to change the clang version to use for building C code. By default +# we use a bash script with somes heuristics to find clang in current system. +CLANG := $(shell $(TOP)/scripts/find_clang) +AR := $(subst clang,llvm-ar,$(CLANG)) +OBJCOPY := $(subst clang,llvm-objcopy,$(CLANG)) +# When this is set to some value, the generated binaries will be copied over +BUILD_DIR := +# Generated binaries to copy. By convention, a Rust crate's directory name will +# likely match the crate name, which is also the name of the final binary. +# However if this is not the case, you can tweak this variable. As the name hints, +# more than one binary is supported here. +BINARIES := $(notdir $(shell pwd)) + +ifeq (release,$(MODE)) + MODE_ARGS := --release +endif + +default: build test + +build: + RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" TARGET_AR="$(AR)" \ + cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS) + @set -eu; \ + if [ "x$(BUILD_DIR)" != "x" ]; then \ + for binary in $(BINARIES); do \ + echo "Copying binary $$binary to build directory"; \ + cp $(TOP)/target/riscv64imac-unknown-none-elf/$(MODE)/$$binary $(TOP)/$(BUILD_DIR); \ + done \ + fi + +# test, check, clippy and fmt here are provided for completeness, +# there is nothing wrong invoking cargo directly instead of make. +test: + cargo test $(CARGO_ARGS) + +check: + cargo check $(CARGO_ARGS) + +clippy: + cargo clippy $(CARGO_ARGS) + +fmt: + cargo fmt $(CARGO_ARGS) + +# Arbitrary cargo command is supported here. For example: +# +# make cargo CARGO_CMD=expand CARGO_ARGS="--ugly" +# +# Invokes: +# cargo expand --ugly +CARGO_CMD := +cargo: + cargo $(CARGO_CMD) $(CARGO_ARGS) + +clean: + cargo clean + +prepare: + rustup target add riscv64imac-unknown-none-elf + +.PHONY: build test check clippy fmt cargo clean prepare diff --git a/tests/test-contracts/contracts/simple-spawn/README.md b/tests/test-contracts/contracts/simple-spawn/README.md new file mode 100644 index 0000000..6392db9 --- /dev/null +++ b/tests/test-contracts/contracts/simple-spawn/README.md @@ -0,0 +1,7 @@ +# simple-spawn + +TODO: Write this readme + +*This contract was bootstrapped with [ckb-script-templates].* + +[ckb-script-templates]: https://github.com/cryptape/ckb-script-templates diff --git a/tests/test-contracts/contracts/simple-spawn/src/lib.rs b/tests/test-contracts/contracts/simple-spawn/src/lib.rs new file mode 100644 index 0000000..7b58725 --- /dev/null +++ b/tests/test-contracts/contracts/simple-spawn/src/lib.rs @@ -0,0 +1,7 @@ +#![cfg_attr(not(feature = "native-simulator"), no_std)] +#![allow(special_module_name)] +#![allow(unused_attributes)] +#[cfg(feature = "native-simulator")] +mod main; +#[cfg(feature = "native-simulator")] +pub use main::program_entry; diff --git a/tests/test-contracts/contracts/simple-spawn/src/main.rs b/tests/test-contracts/contracts/simple-spawn/src/main.rs new file mode 100644 index 0000000..2a91dc7 --- /dev/null +++ b/tests/test-contracts/contracts/simple-spawn/src/main.rs @@ -0,0 +1,56 @@ +#![cfg_attr(not(any(feature = "native-simulator", test)), no_std)] +#![cfg_attr(not(test), no_main)] + +#[cfg(any(feature = "native-simulator", test))] +extern crate alloc; + +#[cfg(not(any(feature = "native-simulator", test)))] +ckb_std::entry!(program_entry); +#[cfg(not(any(feature = "native-simulator", test)))] +ckb_std::default_alloc!(); + +use alloc::vec::Vec; +use ckb_std::{ckb_constants::Source, ckb_types::core::ScriptHashType}; +use core::ffi::CStr; + +fn parent_entry() -> i8 { + let args = ["test"]; + let args_buf: Vec> = args.iter().map(|f| [f.as_bytes(), &[0]].concat()).collect(); + let c_args: Vec<&CStr> = args_buf + .iter() + .map(|f| unsafe { CStr::from_bytes_with_nul_unchecked(f) }) + .collect(); + + let inherited_fds = [0]; + + let pid = ckb_std::high_level::spawn_cell( + &ckb_std::high_level::load_cell_lock(0, Source::GroupInput) + .unwrap() + .code_hash() + .raw_data(), + ScriptHashType::Data2, + &c_args, + &inherited_fds, + ) + .unwrap(); + + ckb_std::debug!("child pid: {}", pid); + + 0 +} + +fn child_entry() -> i8 { + ckb_std::debug!("spawn child stared"); + 0 +} + +pub fn program_entry() -> i8 { + ckb_std::debug!("This is a sample contract!"); + + let argv = ckb_std::env::argv(); + if argv.is_empty() { + parent_entry() + } else { + child_entry() + } +} diff --git a/tests/test-contracts/native-simulators/simple-spawn-sim/.gitignore b/tests/test-contracts/native-simulators/simple-spawn-sim/.gitignore new file mode 100644 index 0000000..c3dca1b --- /dev/null +++ b/tests/test-contracts/native-simulators/simple-spawn-sim/.gitignore @@ -0,0 +1,2 @@ +/build +/target diff --git a/tests/test-contracts/native-simulators/simple-spawn-sim/Cargo.toml b/tests/test-contracts/native-simulators/simple-spawn-sim/Cargo.toml new file mode 100644 index 0000000..99b67ec --- /dev/null +++ b/tests/test-contracts/native-simulators/simple-spawn-sim/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "simple-spawn-sim" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +simple-spawn = { path = "../../contracts/simple-spawn", features = ["native-simulator"] } +ckb-std = { version = "0.16.3", features = ["native-simulator"] } + +[lib] +crate-type = ["cdylib"] diff --git a/tests/test-contracts/native-simulators/simple-spawn-sim/README.md b/tests/test-contracts/native-simulators/simple-spawn-sim/README.md new file mode 100644 index 0000000..2ee96db --- /dev/null +++ b/tests/test-contracts/native-simulators/simple-spawn-sim/README.md @@ -0,0 +1,10 @@ +# simple-spawn-sim + +TODO: Write this readme + +*This template is used to provide native simulator for a particular contract, and is not designed to be used on its own.* + +*This project was bootstrapped with [ckb-script-templates].* + + +[ckb-script-templates]: https://github.com/cryptape/ckb-script-templates diff --git a/tests/test-contracts/native-simulators/simple-spawn-sim/src/lib.rs b/tests/test-contracts/native-simulators/simple-spawn-sim/src/lib.rs new file mode 100644 index 0000000..c0b9c90 --- /dev/null +++ b/tests/test-contracts/native-simulators/simple-spawn-sim/src/lib.rs @@ -0,0 +1 @@ +ckb_std::entry_simulator!(simple_spawn::program_entry); diff --git a/tests/test-contracts/scripts/find_clang b/tests/test-contracts/scripts/find_clang new file mode 100755 index 0000000..f1ffeed --- /dev/null +++ b/tests/test-contracts/scripts/find_clang @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# +# An utility script used to find a binary of clang 16+ + +if [[ -n "${CLANG}" ]]; then + echo "${CLANG}" + exit 0 +fi + +CANDIDATES=("clang" "clang-16" "clang-17" "clang-18") + +BREW_PREFIX=$(brew --prefix 2> /dev/null) +if [[ -n "${BREW_PREFIX}" ]]; then + CANDIDATES+=( + "${BREW_PREFIX}/opt/llvm/bin/clang" + "${BREW_PREFIX}/opt/llvm@16/bin/clang" + "${BREW_PREFIX}/opt/llvm@17/bin/clang" + "${BREW_PREFIX}/opt/llvm@18/bin/clang" + ) +fi + +for candidate in ${CANDIDATES[@]}; do + OUTPUT=$($candidate -dumpversion 2> /dev/null | cut -d'.' -f 1) + + if [[ $((OUTPUT)) -ge 16 ]]; then + echo "$candidate" + exit 0 + fi +done + +>&2 echo "Cannot find clang of version 16+!" +exit 1 diff --git a/tests/test-contracts/scripts/reproducible_build_docker b/tests/test-contracts/scripts/reproducible_build_docker new file mode 100755 index 0000000..fdf35ad --- /dev/null +++ b/tests/test-contracts/scripts/reproducible_build_docker @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# +# An utility script helping with reproducible script builds via docker. +# Note that this utility serves only as one example, docker is not +# necessarily THE way to do reproducible build, nor is it the best way +# to do reproducible build. +set -ex + +DOCKER="${DOCKER:-docker}" +# docker pull docker.io/cryptape/llvm-n-rust:20240630 +DOCKER_IMAGE="${DOCKER_IMAGE:-docker.io/cryptape/llvm-n-rust@sha256:bafaf76d4f342a69b8691c08e77a330b7740631f3d1d9c9bee4ead521b29ee55}" +CHECKSUM_FILE_PATH="${CHECKSUM_FILE_PATH:-checksums.txt}" + +# We are parsing command line arguments based on tips from: +# https://stackoverflow.com/a/14203146 + +while [[ $# -gt 0 ]]; do + case $1 in + -p|--proxy) + PROXY="$2" + shift # past argument + shift # past value + ;; + -u|--update) + UPDATE="yes" + shift # past argument + ;; + --no-clean) + NOCLEAN="yes" + shift # past argument + ;; + -*|--*) + echo "Unknown option $1" + exit 1 + ;; + *) + echo "Unknown argument $1" + exit 1 + ;; + esac +done + +if [[ -n "${PROXY}" ]]; then + DOCKER_RUN_ARGS="-e ALL_PROXY=${PROXY} -e HTTPS_PROXY=${PROXY} -e HTTP_PROXY=${PROXY} ${DOCKER_RUN_ARGS}" +fi + +TASKS="" +if [[ "${NOCLEAN}" != "yes" ]]; then + TASKS+=" clean " +fi + +if [[ "${UPDATE}" = "yes" ]]; then + TASKS+=" checksum CHECKSUM_FILE=${CHECKSUM_FILE_PATH} " +else + TASKS+=" build " +fi + +$DOCKER run --rm $DOCKER_RUN_ARGS -v `pwd`:/code $DOCKER_IMAGE make $TASKS +# Reset file ownerships for all files docker might touch +$DOCKER run --rm $DOCKER_RUN_ARGS -e UID=`id -u` -e GID=`id -g` -v `pwd`:/code $DOCKER_IMAGE bash -c 'chown -R -f $UID:$GID checksums.txt build target' + +if [[ "${UPDATE}" = "yes" ]]; then + echo "${CHECKSUM_FILE_PATH} file is updated with latest binary hashes!" +else + shasum -a 256 -c ${CHECKSUM_FILE_PATH} +fi