diff --git a/README.md b/README.md index 6822974..1b79347 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,16 @@ +# CKB Test Tool -### CKB Test Tool A helper library for writing CKB script test cases. It is migrated from [capsule](https://github.com/nervosnetwork/capsule) +```toml +[dependencies] +ckb-testtool = "0.14" +``` + +## Usage + +See [https://docs.rs/ckb-testtool/latest/ckb_testtool/](https://docs.rs/ckb-testtool/latest/ckb_testtool/) + +## License + +MIT diff --git a/rust-toolchain b/rust-toolchain index 5c8c298..dbd4126 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.75.0 \ No newline at end of file +1.81.0 diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..8210f34 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,5 @@ +max_width = 100 +tab_spaces = 4 +reorder_imports = true +reorder_modules = true +use_try_shorthand = true diff --git a/src/builtin.rs b/src/builtin.rs index f7c372b..d66617a 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -4,7 +4,7 @@ use ckb_types::bytes::Bytes; use lazy_static::lazy_static; lazy_static! { - /// Always return success + /// A CKB script that always returns success. pub static ref ALWAYS_SUCCESS: Bytes = ckb_always_success_script::ALWAYS_SUCCESS.to_vec().into(); } diff --git a/src/context.rs b/src/context.rs index f88a914..e8077f8 100644 --- a/src/context.rs +++ b/src/context.rs @@ -7,7 +7,7 @@ use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::{ bytes::Bytes, core::{ - cell::{CellMeta, CellMetaBuilder, ResolvedTransaction}, + cell::{CellMetaBuilder, ResolvedTransaction}, hardfork::{HardForks, CKB2021, CKB2023}, Capacity, Cycle, DepType, EpochExt, HeaderBuilder, HeaderView, ScriptHashType, TransactionInfo, TransactionView, @@ -17,10 +17,11 @@ use ckb_types::{ }; use rand::{rngs::StdRng, thread_rng, Rng, SeedableRng}; use std::collections::HashMap; +use std::env; use std::path::PathBuf; use std::sync::{Arc, Mutex}; -/// Return a random hash +/// Return a random hash. pub fn random_hash() -> Byte32 { let mut rng = thread_rng(); let mut buf = [0u8; 32]; @@ -28,12 +29,12 @@ pub fn random_hash() -> Byte32 { buf.pack() } -/// Return a random OutPoint +/// Return a random OutPoint. pub fn random_out_point() -> OutPoint { OutPoint::new_builder().tx_hash(random_hash()).build() } -/// Return a random Type ID Script +/// Return a random Type ID Script. pub fn random_type_id_script() -> Script { let args = random_hash().as_bytes(); debug_assert_eq!(args.len(), 32); @@ -44,13 +45,16 @@ pub fn random_type_id_script() -> Script { .build() } +/// A single debug message. By setting context.capture_debug, you can capture debug syscalls issued by your script. #[derive(Debug, Clone, Eq, PartialEq)] pub struct Message { + /// The current script hash. pub id: Byte32, + /// Payload. pub message: String, } -/// Verification Context +/// Verification Context. #[derive(Clone)] pub struct Context { pub cells: HashMap, @@ -72,10 +76,9 @@ pub struct Context { impl Default for Context { fn default() -> Self { - use std::env; - // Get from $TOP/build/$MODE + // The search directory for scripts is $TOP/build/$MODE. You can change this path by setting the $TOP and $MODE + // environment variables. If you do nothing, the default path is ../build/release. let mut contracts_dir = env::var("TOP").map(PathBuf::from).unwrap_or_default(); - contracts_dir.push("build"); if !contracts_dir.exists() { contracts_dir.pop(); @@ -104,28 +107,25 @@ impl Default for Context { } impl Context { - /// Create a new context with a deterministic random number generator, which can be used to generate deterministic out point of deployed contract + /// Create a new context with a deterministic random number generator, which can be used to generate deterministic + /// out point of deployed contract. pub fn new_with_deterministic_rng() -> Self { Self { deterministic_rng: true, ..Default::default() } } + + /// Add new script search paths. Note that this does not replace the default search paths. 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) - } - - /// Deploy a cell - /// return the out-point of the cell + /// Deploy a cell. pub fn deploy_cell(&mut self, data: Bytes) -> OutPoint { let data_hash = CellOutput::calc_data_hash(&data); if let Some(out_point) = self.cells_by_data_hash.get(&data_hash) { - // contract has been deployed + // Contract has already been deployed. return out_point.to_owned(); } let (out_point, type_id_script) = if self.deterministic_rng { @@ -162,6 +162,8 @@ impl Context { out_point } + /// Deploy a cell by filename. It provides the same functionality as the deploy_cell function, but looks for data + /// in the file system. pub fn deploy_cell_by_name(&mut self, filename: &str) -> OutPoint { 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)); @@ -179,6 +181,7 @@ impl Context { self.deploy_cell(data.into()) } + /// Get the full path of the specified script. fn get_contract_path(&self, filename: &str) -> Option { for dir in &self.contracts_dirs { let path = dir.join(filename); @@ -186,11 +189,11 @@ impl Context { return Some(path); } } - None } #[cfg(feature = "native-simulator")] + /// Get the full path of the specified script. Only useful in simulator mode. fn get_native_simulator_path(&self, filename: &str) -> Option { let cdylib_name = format!( "{}.{}", @@ -207,13 +210,12 @@ impl Context { None } - /// Insert a block header into context + /// Insert a block header into context. Afterwards, the header can be retrieved by its hash. pub fn insert_header(&mut self, header: HeaderView) { self.headers.insert(header.hash(), header); } - /// Link a cell with a block - /// to make the load_header_by_cell syscalls works + /// Link a cell with a block to make the load_header_by_cell syscalls works. pub fn link_cell_with_block( &mut self, out_point: OutPoint, @@ -230,29 +232,19 @@ impl Context { ); } - #[deprecated( - since = "0.1.1", - note = "Please use the get_cell_by_data_hash function instead" - )] - pub fn get_contract_out_point(&self, data_hash: &Byte32) -> Option { - self.get_cell_by_data_hash(data_hash) - } - - /// Get the out-point of a cell by data_hash - /// the cell must has deployed to this context + /// Get the out-point of a cell by data_hash. The cell must has deployed to this context. pub fn get_cell_by_data_hash(&self, data_hash: &Byte32) -> Option { self.cells_by_data_hash.get(data_hash).cloned() } - /// Create a cell with data - /// return the out-point + /// Create a cell with data. pub fn create_cell(&mut self, cell: CellOutput, data: Bytes) -> OutPoint { let out_point = random_out_point(); self.create_cell_with_out_point(out_point.clone(), cell, data); out_point } - /// Create cell with specified out-point and cell data + /// Create cell with specified out-point and cell data. pub fn create_cell_with_out_point( &mut self, out_point: OutPoint, @@ -268,21 +260,12 @@ impl Context { self.cells.insert(out_point, (cell, data)); } - #[deprecated( - since = "0.1.1", - note = "Please use the create_cell_with_out_point function instead" - )] - pub fn insert_cell(&mut self, out_point: OutPoint, cell: CellOutput, data: Bytes) { - self.create_cell_with_out_point(out_point, cell, data) - } - - /// Get cell output and data by out-point + /// Get cell output and data by out-point. pub fn get_cell(&self, out_point: &OutPoint) -> Option<(CellOutput, Bytes)> { self.cells.get(out_point).cloned() } - /// Build script with out_point, hash_type, args - /// return none if the out-point is not exist + /// Build script with out_point, hash_type, args. Return none if the out-point is not exist. pub fn build_script_with_hash_type( &mut self, out_point: &OutPoint, @@ -308,12 +291,14 @@ impl Context { .build(), ) } - /// Build script with out_point, args and hash_type(ScriptHashType::Type) - /// return none if the out-point is not exist + + /// Build script with out_point, args and hash_type(ScriptHashType::Type). Return none if the out-point is not + /// exist. pub fn build_script(&mut self, out_point: &OutPoint, args: Bytes) -> Option