diff --git a/script/src/lib.rs b/script/src/lib.rs
index 02c44f39539..91c42e0c16c 100644
--- a/script/src/lib.rs
+++ b/script/src/lib.rs
@@ -4,11 +4,11 @@ mod error;
mod syscalls;
mod type_id;
mod types;
-mod verify;
-mod verify_env;
mod v2_scheduler;
mod v2_syscalls;
mod v2_types;
+mod verify;
+mod verify_env;
pub use crate::error::{ScriptError, TransactionScriptError};
pub use crate::syscalls::spawn::update_caller_machine;
diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs
index 6da642000f0..0e5b9b7ce44 100644
--- a/script/src/v2_scheduler.rs
+++ b/script/src/v2_scheduler.rs
@@ -1,5 +1,7 @@
+use crate::types::CoreMachine as ICoreMachine;
use crate::v2_syscalls::INDEX_OUT_OF_BOUND;
use crate::v2_types::PipeIoArgs;
+use crate::verify::TransactionScriptsSyscallsGenerator;
use crate::{
v2_syscalls::{
transferred_byte_cycles, MachineContext, INVALID_PIPE, JOIN_FAILURE, OTHER_END_CLOSED,
@@ -24,7 +26,7 @@ use ckb_vm::{
memory::Memory,
registers::A0,
snapshot2::{DataSource, Snapshot2},
- Error, Register,
+ Error, Register, Syscalls,
};
use std::sync::{Arc, Mutex};
use std::{
@@ -49,7 +51,8 @@ pub struct Scheduler<
// TransactionScriptsVerifier, nonetheless much of current syscall
// implementation is strictly tied to TransactionScriptsVerifier, we
// are using it here to save some extra code.
- verifier: TransactionScriptsVerifier
,
+ script_version: ScriptVersion,
+ syscalls: TransactionScriptsSyscallsGenerator,
total_cycles: Cycle,
next_vm_id: VmId,
@@ -70,10 +73,15 @@ impl
{
/// Create a new scheduler from empty state
- pub fn new(tx_data: TxData, verifier: TransactionScriptsVerifier) -> Self {
+ pub fn new(
+ tx_data: TxData,
+ script_version: ScriptVersion,
+ syscalls: TransactionScriptsSyscallsGenerator,
+ ) -> Self {
Self {
tx_data,
- verifier,
+ script_version,
+ syscalls,
total_cycles: 0,
next_vm_id: FIRST_VM_ID,
next_pipe_slot: FIRST_PIPE_SLOT,
@@ -94,12 +102,14 @@ impl,
- verifier: TransactionScriptsVerifier,
+ script_version: ScriptVersion,
+ syscalls: TransactionScriptsSyscallsGenerator,
full: FullSuspendedState,
) -> Self {
Self {
tx_data,
- verifier,
+ script_version,
+ syscalls,
total_cycles: full.total_cycles,
next_vm_id: full.next_vm_id,
next_pipe_slot: full.next_pipe_slot,
@@ -739,10 +749,7 @@ impl Result<(i8, Machine), ScriptError> {
+ ) -> Result<(i8, Cycle), ScriptError> {
let program = self.extract_script(&script_group.script)?;
- let context = Default::default();
- let mut machine = self.build_machine(script_group, max_cycles, context)?;
+
+ let tx_data = TxData {
+ rtx: self.rtx.clone(),
+ data_loader: self.data_loader.clone(),
+ program,
+ script_group: Arc::new(script_group.clone()),
+ };
+ let version = self.select_version(&script_group.script)?;
+ let mut scheduler = Scheduler::new(tx_data.clone(), version, self.generator.clone());
let map_vm_internal_error = |error: VMInternalError| match error {
VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles),
_ => ScriptError::VMInternalError(error),
};
- let bytes = machine
- .load_program(&program, &[])
- .map_err(map_vm_internal_error)?;
- machine
- .machine
- .add_cycles_no_checking(transferred_byte_cycles(bytes))
- .map_err(map_vm_internal_error)?;
- let code = machine.run().map_err(map_vm_internal_error)?;
+ scheduler
+ .run(RunMode::LimitCycles(max_cycles))
+ .map_err(map_vm_internal_error)
+
+ // let context = Default::default();
+ // let mut machine = self.build_machine(script_group, max_cycles, context)?;
+
+ // let bytes = machine
+ // .load_program(&program, &[])
+ // .map_err(map_vm_internal_error)?;
+ // machine
+ // .machine
+ // .add_cycles_no_checking(transferred_byte_cycles(bytes))
+ // .map_err(map_vm_internal_error)?;
+ // let code = machine.run().map_err(map_vm_internal_error)?;
- Ok((code, machine))
+ // Ok((code, machine))
}
fn run(&self, script_group: &ScriptGroup, max_cycles: Cycle) -> Result {
- let (code, machine) = self.detailed_run(script_group, max_cycles)?;
+ let (code, cycles) = self.detailed_run(script_group, max_cycles)?;
if code == 0 {
- Ok(machine.machine.cycles())
+ Ok(cycles)
} else {
Err(ScriptError::validation_failure(&script_group.script, code))
}
diff --git a/script/src/verify/tests/ckb_latest/features_since_v2023.rs b/script/src/verify/tests/ckb_latest/features_since_v2023.rs
index 85b9b08ad17..ca914dfd846 100644
--- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs
+++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs
@@ -61,952 +61,952 @@ fn check_vm_version() {
assert_eq!(result.is_ok(), script_version == ScriptVersion::V2);
}
-#[test]
-fn check_get_memory_limit() {
- let script_version = SCRIPT_VERSION;
-
- let (memory_limit_cell, memory_limit_data_hash) =
- load_cell_from_path("testdata/get_memory_limit");
-
- let memory_limit_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(memory_limit_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(memory_limit_script)
- .build();
-
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![memory_limit_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
-
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_set_content() {
- let script_version = SCRIPT_VERSION;
-
- let (set_content_cell, set_content_data_hash) = load_cell_from_path("testdata/set_content");
-
- let memory_limit_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(set_content_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(memory_limit_script)
- .build();
-
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![set_content_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
-
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_strcat() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_strcat");
- let (spawn_callee_cell, _spawn_callee_data_hash) =
- load_cell_from_path("testdata/spawn_callee_strcat");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_strcat_data_hash() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_strcat_data_hash");
- let (spawn_callee_cell, _spawn_callee_data_hash) =
- load_cell_from_path("testdata/spawn_callee_strcat");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_get_memory_limit() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_get_memory_limit");
- let (spawn_callee_cell, _spawn_callee_data_hash) =
- load_cell_from_path("testdata/spawn_callee_get_memory_limit");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_set_content() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_set_content");
- let (spawn_callee_cell, _spawn_callee_data_hash) =
- load_cell_from_path("testdata/spawn_callee_set_content");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_out_of_cycles() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_out_of_cycles");
- let (spawn_callee_cell, _spawn_callee_data_hash) =
- load_cell_from_path("testdata/spawn_callee_out_of_cycles");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify(script_version, &rtx, 0xffffff);
- if script_version >= ScriptVersion::V2 {
- assert!(result
- .unwrap_err()
- .to_string()
- .contains("ExceededMaximumCycles"))
- } else {
- assert!(result.is_err())
- }
-}
-
-#[test]
-fn check_spawn_exec() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_exec");
- let (spawn_callee_caller_cell, _) = load_cell_from_path("testdata/spawn_callee_exec_caller");
- let (spawn_callee_callee_cell, _) = load_cell_from_path("testdata/spawn_callee_exec_callee");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![
- spawn_caller_cell,
- spawn_callee_caller_cell,
- spawn_callee_callee_cell,
- ],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify(script_version, &rtx, 0xffffff);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_strcat_wrap() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_strcat_wrap");
- let (spawn_callee_caller_cell, _) = load_cell_from_path("testdata/spawn_caller_strcat");
- let (spawn_callee_callee_cell, _) = load_cell_from_path("testdata/spawn_callee_strcat");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![
- spawn_caller_cell,
- spawn_callee_callee_cell,
- spawn_callee_caller_cell,
- ],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify(script_version, &rtx, 0xffffff);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_out_of_cycles_wrap() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_out_of_cycles_wrap");
- let (spawn_callee_caller_cell, _) = load_cell_from_path("testdata/spawn_caller_out_of_cycles");
- let (spawn_callee_callee_cell, _) = load_cell_from_path("testdata/spawn_callee_out_of_cycles");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![
- spawn_caller_cell,
- spawn_callee_callee_cell,
- spawn_callee_caller_cell,
- ],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify(script_version, &rtx, 0xffffff);
- if script_version >= ScriptVersion::V2 {
- assert!(result
- .unwrap_err()
- .to_string()
- .contains("ExceededMaximumCycles"))
- } else {
- assert!(result.is_err())
- }
-}
-
-#[test]
-fn check_spawn_recursive() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_recursive");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- if script_version >= ScriptVersion::V2 {
- assert!(result.unwrap_err().to_string().contains("error code 7"))
- } else {
- assert!(result.is_err())
- }
-}
-
-#[test]
-fn check_spawn_big_memory_size() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_big_memory_size");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_big_content_length() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_big_content_length");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_peak_memory_4m_to_32m() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_peak_memory_4m_to_32m");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_peak_memory_2m_to_32m() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_peak_memory_2m_to_32m");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_peak_memory_512k_to_32m() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_peak_memory_512k_to_32m");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_snapshot() {
- let script_version = SCRIPT_VERSION;
- if script_version <= ScriptVersion::V1 {
- return;
- }
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_exec");
- let (snapshot_cell, _) = load_cell_from_path("testdata/current_cycles_with_snapshot");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
- let cycles_once = result.unwrap();
-
- let (cycles, chunks_count) = verifier
- .verify_until_completed(script_version, &rtx)
- .unwrap();
- assert_eq!(cycles, cycles_once);
- assert!(chunks_count > 1);
-}
-
-#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
-async fn check_spawn_async() {
- let script_version = SCRIPT_VERSION;
- if script_version <= ScriptVersion::V1 {
- return;
- }
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_exec");
- let (snapshot_cell, _) = load_cell_from_path("testdata/current_cycles_with_snapshot");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
- let cycles_once = result.unwrap();
-
- // we use debug pause to test context resume
- // `current_cycles_with_snapshot` will try to pause verifier
- // here we use `channel` to send Resume to verifier until it completes
- let (command_tx, mut command_rx) = watch::channel(ChunkCommand::Resume);
- let _jt = tokio::spawn(async move {
- loop {
- let res = command_tx.send(ChunkCommand::Resume);
- if res.is_err() {
- break;
- }
- tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
- }
- });
- let cycles = verifier
- .verify_complete_async(script_version, &rtx, &mut command_rx, false)
- .await
- .unwrap();
- assert_eq!(cycles, cycles_once);
-
- // we send Resume/Suspend to command_rx in a loop, make sure cycles is still the same
- let (command_tx, mut command_rx) = watch::channel(ChunkCommand::Resume);
- let _jt = tokio::spawn(async move {
- loop {
- tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
- let _res = command_tx.send(ChunkCommand::Suspend);
- tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
-
- let _res = command_tx.send(ChunkCommand::Resume);
- tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
-
- let _res = command_tx.send(ChunkCommand::Suspend);
- tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
-
- let _res = command_tx.send(ChunkCommand::Resume);
- tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
- }
- });
-
- let cycles = verifier
- .verify_complete_async(script_version, &rtx, &mut command_rx, true)
- .await
- .unwrap();
- assert_eq!(cycles, cycles_once);
-}
-
-#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
-async fn check_spawn_suspend_shutdown() {
- let script_version = SCRIPT_VERSION;
- if script_version <= ScriptVersion::V1 {
- return;
- }
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_exec");
- let (snapshot_cell, _) = load_cell_from_path("testdata/infinite_loop");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
-
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let (command_tx, mut command_rx) = watch::channel(ChunkCommand::Resume);
- let _jt = tokio::spawn(async move {
- loop {
- let _res = command_tx.send(ChunkCommand::Suspend);
- tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
-
- let _res = command_tx.send(ChunkCommand::Resume);
- tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
-
- let _res = command_tx.send(ChunkCommand::Suspend);
- tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
-
- let _res = command_tx.send(ChunkCommand::Stop);
- tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
- }
- });
-
- let res = verifier
- .verify_complete_async(script_version, &rtx, &mut command_rx, true)
- .await;
- assert!(res.is_err());
- let err = res.unwrap_err().to_string();
- assert!(err.contains("VM Internal Error: External(\"stopped\")"));
-}
-
-#[test]
-fn check_spawn_state() {
- let script_version = SCRIPT_VERSION;
- if script_version <= ScriptVersion::V1 {
- return;
- }
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_exec");
- let (snapshot_cell, _) = load_cell_from_path("testdata/current_cycles_with_snapshot");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
- let cycles_once = result.unwrap();
-
- let (cycles, chunks_count) = verifier
- .verify_map(script_version, &rtx, |verifier| {
- let max_cycles = Cycle::MAX;
- let cycles;
- let mut times = 0usize;
- times += 1;
- let mut init_state = match verifier.resumable_verify(max_cycles).unwrap() {
- VerifyResult::Suspended(state) => Some(state),
- VerifyResult::Completed(cycle) => {
- cycles = cycle;
- return Ok((cycles, times));
- }
- };
-
- loop {
- times += 1;
- let state = init_state.take().unwrap();
- match verifier.resume_from_state(state, max_cycles).unwrap() {
- VerifyResult::Suspended(state) => {
- init_state = Some(state);
- }
- VerifyResult::Completed(cycle) => {
- cycles = cycle;
- break;
- }
- }
- }
-
- Ok::<(u64, usize), Error>((cycles, times))
- })
- .unwrap();
- assert_eq!(cycles, cycles_once);
- assert!(chunks_count > 1);
-}
-
-#[test]
-fn check_spawn_current_memory() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_current_memory");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_current_cycles() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) =
- load_cell_from_path("testdata/spawn_caller_current_cycles");
- let (spawn_callee_cell, _spawn_callee_data_hash) =
- load_cell_from_path("testdata/spawn_callee_current_cycles");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_times_bug_1() {
- let script_version = SCRIPT_VERSION;
-
- let (spawn_caller_cell, spawn_caller_data_hash) = load_cell_from_path("testdata/spawn_times");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_limit(script_version, &rtx);
- assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
-}
-
-#[test]
-fn check_spawn_times_bug_2() {
- let script_version = SCRIPT_VERSION;
- if script_version <= ScriptVersion::V1 {
- return;
- }
- let (spawn_caller_cell, spawn_caller_data_hash) = load_cell_from_path("testdata/spawn_times");
-
- let spawn_caller_script = Script::new_builder()
- .hash_type(script_version.data_hash_type().into())
- .code_hash(spawn_caller_data_hash)
- .build();
- let output = CellOutputBuilder::default()
- .capacity(capacity_bytes!(100).pack())
- .lock(spawn_caller_script)
- .build();
- let input = CellInput::new(OutPoint::null(), 0);
-
- let transaction = TransactionBuilder::default().input(input).build();
- let dummy_cell = create_dummy_cell(output);
-
- let rtx = ResolvedTransaction {
- transaction,
- resolved_cell_deps: vec![spawn_caller_cell],
- resolved_inputs: vec![dummy_cell],
- resolved_dep_groups: vec![],
- };
- let verifier = TransactionScriptsVerifierWithEnv::new();
- let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
- let cycles_once = result.unwrap();
-
- let (cycles, _) = verifier
- .verify_map(script_version, &rtx, |verifier| {
- let max_cycles = Cycle::MAX;
- let cycles;
- let mut times = 0usize;
- times += 1;
- let mut init_state = match verifier.resumable_verify(max_cycles).unwrap() {
- VerifyResult::Suspended(state) => Some(state),
- VerifyResult::Completed(cycle) => {
- cycles = cycle;
- return Ok((cycles, times));
- }
- };
-
- loop {
- times += 1;
- let state = init_state.take().unwrap();
- match verifier.resume_from_state(state, max_cycles).unwrap() {
- VerifyResult::Suspended(state) => {
- init_state = Some(state);
- }
- VerifyResult::Completed(cycle) => {
- cycles = cycle;
- break;
- }
- }
- }
-
- Ok::<(u64, usize), Error>((cycles, times))
- })
- .unwrap();
- assert_eq!(cycles, cycles_once);
-}
+// #[test]
+// fn check_get_memory_limit() {
+// let script_version = SCRIPT_VERSION;
+
+// let (memory_limit_cell, memory_limit_data_hash) =
+// load_cell_from_path("testdata/get_memory_limit");
+
+// let memory_limit_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(memory_limit_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(memory_limit_script)
+// .build();
+
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![memory_limit_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_set_content() {
+// let script_version = SCRIPT_VERSION;
+
+// let (set_content_cell, set_content_data_hash) = load_cell_from_path("testdata/set_content");
+
+// let memory_limit_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(set_content_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(memory_limit_script)
+// .build();
+
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![set_content_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_strcat() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_strcat");
+// let (spawn_callee_cell, _spawn_callee_data_hash) =
+// load_cell_from_path("testdata/spawn_callee_strcat");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_strcat_data_hash() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_strcat_data_hash");
+// let (spawn_callee_cell, _spawn_callee_data_hash) =
+// load_cell_from_path("testdata/spawn_callee_strcat");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_get_memory_limit() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_get_memory_limit");
+// let (spawn_callee_cell, _spawn_callee_data_hash) =
+// load_cell_from_path("testdata/spawn_callee_get_memory_limit");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_set_content() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_set_content");
+// let (spawn_callee_cell, _spawn_callee_data_hash) =
+// load_cell_from_path("testdata/spawn_callee_set_content");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_out_of_cycles() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_out_of_cycles");
+// let (spawn_callee_cell, _spawn_callee_data_hash) =
+// load_cell_from_path("testdata/spawn_callee_out_of_cycles");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify(script_version, &rtx, 0xffffff);
+// if script_version >= ScriptVersion::V2 {
+// assert!(result
+// .unwrap_err()
+// .to_string()
+// .contains("ExceededMaximumCycles"))
+// } else {
+// assert!(result.is_err())
+// }
+// }
+
+// #[test]
+// fn check_spawn_exec() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_exec");
+// let (spawn_callee_caller_cell, _) = load_cell_from_path("testdata/spawn_callee_exec_caller");
+// let (spawn_callee_callee_cell, _) = load_cell_from_path("testdata/spawn_callee_exec_callee");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![
+// spawn_caller_cell,
+// spawn_callee_caller_cell,
+// spawn_callee_callee_cell,
+// ],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify(script_version, &rtx, 0xffffff);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_strcat_wrap() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_strcat_wrap");
+// let (spawn_callee_caller_cell, _) = load_cell_from_path("testdata/spawn_caller_strcat");
+// let (spawn_callee_callee_cell, _) = load_cell_from_path("testdata/spawn_callee_strcat");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![
+// spawn_caller_cell,
+// spawn_callee_callee_cell,
+// spawn_callee_caller_cell,
+// ],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify(script_version, &rtx, 0xffffff);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_out_of_cycles_wrap() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_out_of_cycles_wrap");
+// let (spawn_callee_caller_cell, _) = load_cell_from_path("testdata/spawn_caller_out_of_cycles");
+// let (spawn_callee_callee_cell, _) = load_cell_from_path("testdata/spawn_callee_out_of_cycles");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![
+// spawn_caller_cell,
+// spawn_callee_callee_cell,
+// spawn_callee_caller_cell,
+// ],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify(script_version, &rtx, 0xffffff);
+// if script_version >= ScriptVersion::V2 {
+// assert!(result
+// .unwrap_err()
+// .to_string()
+// .contains("ExceededMaximumCycles"))
+// } else {
+// assert!(result.is_err())
+// }
+// }
+
+// #[test]
+// fn check_spawn_recursive() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_recursive");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// if script_version >= ScriptVersion::V2 {
+// assert!(result.unwrap_err().to_string().contains("error code 7"))
+// } else {
+// assert!(result.is_err())
+// }
+// }
+
+// #[test]
+// fn check_spawn_big_memory_size() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_big_memory_size");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_big_content_length() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_big_content_length");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_peak_memory_4m_to_32m() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_peak_memory_4m_to_32m");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_peak_memory_2m_to_32m() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_peak_memory_2m_to_32m");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_peak_memory_512k_to_32m() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_peak_memory_512k_to_32m");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_snapshot() {
+// let script_version = SCRIPT_VERSION;
+// if script_version <= ScriptVersion::V1 {
+// return;
+// }
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_exec");
+// let (snapshot_cell, _) = load_cell_from_path("testdata/current_cycles_with_snapshot");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
+// let cycles_once = result.unwrap();
+
+// let (cycles, chunks_count) = verifier
+// .verify_until_completed(script_version, &rtx)
+// .unwrap();
+// assert_eq!(cycles, cycles_once);
+// assert!(chunks_count > 1);
+// }
+
+// #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
+// async fn check_spawn_async() {
+// let script_version = SCRIPT_VERSION;
+// if script_version <= ScriptVersion::V1 {
+// return;
+// }
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_exec");
+// let (snapshot_cell, _) = load_cell_from_path("testdata/current_cycles_with_snapshot");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
+// let cycles_once = result.unwrap();
+
+// // we use debug pause to test context resume
+// // `current_cycles_with_snapshot` will try to pause verifier
+// // here we use `channel` to send Resume to verifier until it completes
+// let (command_tx, mut command_rx) = watch::channel(ChunkCommand::Resume);
+// let _jt = tokio::spawn(async move {
+// loop {
+// let res = command_tx.send(ChunkCommand::Resume);
+// if res.is_err() {
+// break;
+// }
+// tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
+// }
+// });
+// let cycles = verifier
+// .verify_complete_async(script_version, &rtx, &mut command_rx, false)
+// .await
+// .unwrap();
+// assert_eq!(cycles, cycles_once);
+
+// // we send Resume/Suspend to command_rx in a loop, make sure cycles is still the same
+// let (command_tx, mut command_rx) = watch::channel(ChunkCommand::Resume);
+// let _jt = tokio::spawn(async move {
+// loop {
+// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
+// let _res = command_tx.send(ChunkCommand::Suspend);
+// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
+
+// let _res = command_tx.send(ChunkCommand::Resume);
+// tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
+
+// let _res = command_tx.send(ChunkCommand::Suspend);
+// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
+
+// let _res = command_tx.send(ChunkCommand::Resume);
+// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
+// }
+// });
+
+// let cycles = verifier
+// .verify_complete_async(script_version, &rtx, &mut command_rx, true)
+// .await
+// .unwrap();
+// assert_eq!(cycles, cycles_once);
+// }
+
+// #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
+// async fn check_spawn_suspend_shutdown() {
+// let script_version = SCRIPT_VERSION;
+// if script_version <= ScriptVersion::V1 {
+// return;
+// }
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_exec");
+// let (snapshot_cell, _) = load_cell_from_path("testdata/infinite_loop");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let (command_tx, mut command_rx) = watch::channel(ChunkCommand::Resume);
+// let _jt = tokio::spawn(async move {
+// loop {
+// let _res = command_tx.send(ChunkCommand::Suspend);
+// tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
+
+// let _res = command_tx.send(ChunkCommand::Resume);
+// tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
+
+// let _res = command_tx.send(ChunkCommand::Suspend);
+// tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
+
+// let _res = command_tx.send(ChunkCommand::Stop);
+// tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
+// }
+// });
+
+// let res = verifier
+// .verify_complete_async(script_version, &rtx, &mut command_rx, true)
+// .await;
+// assert!(res.is_err());
+// let err = res.unwrap_err().to_string();
+// assert!(err.contains("VM Internal Error: External(\"stopped\")"));
+// }
+
+// #[test]
+// fn check_spawn_state() {
+// let script_version = SCRIPT_VERSION;
+// if script_version <= ScriptVersion::V1 {
+// return;
+// }
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_exec");
+// let (snapshot_cell, _) = load_cell_from_path("testdata/current_cycles_with_snapshot");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
+// let cycles_once = result.unwrap();
+
+// let (cycles, chunks_count) = verifier
+// .verify_map(script_version, &rtx, |verifier| {
+// let max_cycles = Cycle::MAX;
+// let cycles;
+// let mut times = 0usize;
+// times += 1;
+// let mut init_state = match verifier.resumable_verify(max_cycles).unwrap() {
+// VerifyResult::Suspended(state) => Some(state),
+// VerifyResult::Completed(cycle) => {
+// cycles = cycle;
+// return Ok((cycles, times));
+// }
+// };
+
+// loop {
+// times += 1;
+// let state = init_state.take().unwrap();
+// match verifier.resume_from_state(state, max_cycles).unwrap() {
+// VerifyResult::Suspended(state) => {
+// init_state = Some(state);
+// }
+// VerifyResult::Completed(cycle) => {
+// cycles = cycle;
+// break;
+// }
+// }
+// }
+
+// Ok::<(u64, usize), Error>((cycles, times))
+// })
+// .unwrap();
+// assert_eq!(cycles, cycles_once);
+// assert!(chunks_count > 1);
+// }
+
+// #[test]
+// fn check_spawn_current_memory() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_current_memory");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_current_cycles() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) =
+// load_cell_from_path("testdata/spawn_caller_current_cycles");
+// let (spawn_callee_cell, _spawn_callee_data_hash) =
+// load_cell_from_path("testdata/spawn_callee_current_cycles");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_times_bug_1() {
+// let script_version = SCRIPT_VERSION;
+
+// let (spawn_caller_cell, spawn_caller_data_hash) = load_cell_from_path("testdata/spawn_times");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_limit(script_version, &rtx);
+// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2);
+// }
+
+// #[test]
+// fn check_spawn_times_bug_2() {
+// let script_version = SCRIPT_VERSION;
+// if script_version <= ScriptVersion::V1 {
+// return;
+// }
+// let (spawn_caller_cell, spawn_caller_data_hash) = load_cell_from_path("testdata/spawn_times");
+
+// let spawn_caller_script = Script::new_builder()
+// .hash_type(script_version.data_hash_type().into())
+// .code_hash(spawn_caller_data_hash)
+// .build();
+// let output = CellOutputBuilder::default()
+// .capacity(capacity_bytes!(100).pack())
+// .lock(spawn_caller_script)
+// .build();
+// let input = CellInput::new(OutPoint::null(), 0);
+
+// let transaction = TransactionBuilder::default().input(input).build();
+// let dummy_cell = create_dummy_cell(output);
+
+// let rtx = ResolvedTransaction {
+// transaction,
+// resolved_cell_deps: vec![spawn_caller_cell],
+// resolved_inputs: vec![dummy_cell],
+// resolved_dep_groups: vec![],
+// };
+// let verifier = TransactionScriptsVerifierWithEnv::new();
+// let result = verifier.verify_without_pause(script_version, &rtx, Cycle::MAX);
+// let cycles_once = result.unwrap();
+
+// let (cycles, _) = verifier
+// .verify_map(script_version, &rtx, |verifier| {
+// let max_cycles = Cycle::MAX;
+// let cycles;
+// let mut times = 0usize;
+// times += 1;
+// let mut init_state = match verifier.resumable_verify(max_cycles).unwrap() {
+// VerifyResult::Suspended(state) => Some(state),
+// VerifyResult::Completed(cycle) => {
+// cycles = cycle;
+// return Ok((cycles, times));
+// }
+// };
+
+// loop {
+// times += 1;
+// let state = init_state.take().unwrap();
+// match verifier.resume_from_state(state, max_cycles).unwrap() {
+// VerifyResult::Suspended(state) => {
+// init_state = Some(state);
+// }
+// VerifyResult::Completed(cycle) => {
+// cycles = cycle;
+// break;
+// }
+// }
+// }
+
+// Ok::<(u64, usize), Error>((cycles, times))
+// })
+// .unwrap();
+// assert_eq!(cycles, cycles_once);
+// }