diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index b769fa5e35..202fbadd32 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -313,8 +313,8 @@ impl length. -// check_spawn_out_of_cycles: child script out-of-cycles. -// check_spawn_exec: A exec B spawn C. -// check_spawn_strcat_wrap: A spawn B spwan C. -// check_spawn_out_of_cycles_wrap: A spawn B spwan C, but C out-of-cycles. -// check_spawn_recursive: A spawn A spawn A ... ... spawn A -// check_spawn_big_memory_size: fails when memory_limit > 8. -// check_spawn_big_content_length: fails when content_length > 256K. -// check_peak_memory_4m_to_32m: spawn should success when peak memory <= 32M -// check_peak_memory_2m_to_32m: spawn should success when peak memory <= 32M -// check_peak_memory_512k_to_32m: spawn should success when peak memory <= 32M -// check_spawn_snapshot: A spawn B, then B gets suspended to snapshot and resume again. -// check_spawn_state: Like check_spawn_snapshot but invoking verifier.resume_from_state instead. -// check_spawn_current_memory: Use current_memory() to terminate infinite recursion. -// check_spawn_current_cycles: callee's current_cycles should inherit caller's current_cycles. -// check_spawn_times_bug_1: BUG: execution results may be inconsistent -// check_spawn_times_bug_2: BUG: execution results may be inconsistent - #[test] fn check_vm_version() { let script_version = SCRIPT_VERSION; @@ -61,71 +37,6 @@ 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; @@ -160,493 +71,241 @@ fn check_spawn_strcat() { 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); +#[test] +fn check_spawn_out_of_cycles() { + let script_version = SCRIPT_VERSION; -// 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); -// } + 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"); -// #[test] -// fn check_spawn_big_content_length() { -// let script_version = SCRIPT_VERSION; + 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 (spawn_caller_cell, spawn_caller_data_hash) = -// load_cell_from_path("testdata/spawn_big_content_length"); + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// 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 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()) + } +} -// let transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); +#[test] +fn check_spawn_exec() { + let script_version = SCRIPT_VERSION; -// 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); -// } + 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"); -// #[test] -// fn check_peak_memory_4m_to_32m() { -// let script_version = SCRIPT_VERSION; + 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 (spawn_caller_cell, spawn_caller_data_hash) = -// load_cell_from_path("testdata/spawn_peak_memory_4m_to_32m"); + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// 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 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); +} -// let transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); +#[test] +fn check_spawn_strcat_wrap() { + let script_version = SCRIPT_VERSION; -// 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); -// } + 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"); -// #[test] -// fn check_peak_memory_2m_to_32m() { -// let script_version = SCRIPT_VERSION; + 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 (spawn_caller_cell, spawn_caller_data_hash) = -// load_cell_from_path("testdata/spawn_peak_memory_2m_to_32m"); + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// 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 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); +} -// let transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); +#[test] +fn check_spawn_out_of_cycles_wrap() { + let script_version = SCRIPT_VERSION; -// 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); -// } + 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"); -// #[test] -// fn check_peak_memory_512k_to_32m() { -// let script_version = SCRIPT_VERSION; + 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 (spawn_caller_cell, spawn_caller_data_hash) = -// load_cell_from_path("testdata/spawn_peak_memory_512k_to_32m"); + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// 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 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()) + } +} -// let transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); +#[test] +fn check_spawn_recursive() { + let script_version = SCRIPT_VERSION; -// 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); -// } + let (spawn_caller_cell, spawn_caller_data_hash) = + load_cell_from_path("testdata/spawn_recursive"); -// #[test] -// fn check_spawn_snapshot() { -// let script_version = SCRIPT_VERSION; -// if script_version <= ScriptVersion::V1 { -// return; -// } + 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 (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 transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// 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 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(script_version, &rtx, 70_000_000); + if script_version >= ScriptVersion::V2 { + let msg = result.unwrap_err().to_string(); + assert!(msg.contains("ExceededMaximumCycles")) + } else { + assert!(result.is_err()) + } +} -// let transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); +#[test] +fn check_spawn_snapshot() { + let script_version = SCRIPT_VERSION; + if script_version <= ScriptVersion::V1 { + return; + } -// 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 (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 (cycles, chunks_count) = verifier -// .verify_until_completed(script_version, &rtx) -// .unwrap(); -// assert_eq!(cycles, cycles_once); -// assert!(chunks_count > 1); -// } + 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(); + + // TODO + // 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() { @@ -853,70 +512,40 @@ fn check_spawn_strcat() { // 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; +#[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_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 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 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); -// } + 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); +} +// TODO: will reach memory limit // #[test] // fn check_spawn_times_bug_1() { // let script_version = SCRIPT_VERSION; @@ -944,7 +573,9 @@ fn check_spawn_strcat() { // }; // let verifier = TransactionScriptsVerifierWithEnv::new(); // let result = verifier.verify_without_limit(script_version, &rtx); -// assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); +// let err = result.unwrap_err(); +// println!("{:?}", err); +// // assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); // } // #[test] diff --git a/script/testdata/Makefile b/script/testdata/Makefile index e4db1600f5..90d7a50941 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -57,9 +57,19 @@ ALL_BINS := jalr_zero \ load_arithmetic \ debugger \ spawn_caller_strcat \ - spawn_callee_strcat - - + spawn_callee_strcat \ + spawn_caller_exec \ + spawn_callee_exec_caller \ + spawn_callee_exec_callee \ + spawn_caller_strcat_wrap \ + spawn_recursive \ + spawn_callee_out_of_cycles \ + spawn_caller_out_of_cycles \ + spawn_caller_out_of_cycles_wrap \ + spawn_caller_current_cycles \ + spawn_callee_current_cycles \ + spawn_times + ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -126,4 +136,15 @@ load_arithmetic: load_arithmetic.c spawn_caller_strcat: spawn_caller_strcat.c utils.h spawn_callee_strcat: spawn_callee_strcat.c utils.h +spawn_caller_exec: spawn_caller_exec.c +spawn_callee_exec_caller: spawn_callee_exec_caller.c +spawn_callee_exec_callee: spawn_callee_exec_callee.c +spawn_caller_strcat_wrap: spawn_caller_strcat_wrap.c utils.h +spawn_recursive: spawn_recursive.c utils.h +spawn_caller_out_of_cycles: spawn_caller_out_of_cycles.c +spawn_callee_out_of_cycles: spawn_callee_out_of_cycles.c +spawn_caller_out_of_cycles_wrap: spawn_caller_out_of_cycles_wrap.c +spawn_caller_current_cycles: spawn_caller_current_cycles.c +spawn_callee_current_cycles: spawn_callee_current_cycles.c +spawn_times: spawn_times.c diff --git a/script/testdata/spawn_callee_current_cycles b/script/testdata/spawn_callee_current_cycles new file mode 100755 index 0000000000..a49bc961bb Binary files /dev/null and b/script/testdata/spawn_callee_current_cycles differ diff --git a/script/testdata/spawn_callee_current_cycles.c b/script/testdata/spawn_callee_current_cycles.c new file mode 100644 index 0000000000..1e7e7f11d4 --- /dev/null +++ b/script/testdata/spawn_callee_current_cycles.c @@ -0,0 +1,28 @@ +#include +#include +#include + +#include "ckb_syscalls.h" + +int atoi(const char *s) { + int n = 0, neg = 0; + switch (*s) { + case '-': + neg = 1; + case '+': + s++; + } + /* Compute n as a negative number to avoid overflow on INT_MIN */ + while (_is_digit(*s)) n = 10 * n - (*s++ - '0'); + return neg ? n : -n; +} + +int main(int argc, const char *argv[]) { + int caller_cycles = atoi(argv[0]); + // Callee's current cycles must > caller's current cycles. + int callee_cycles = ckb_current_cycles(); + if (callee_cycles < caller_cycles + 100000) { + return 1; + } + return 0; +} diff --git a/script/testdata/spawn_callee_exec_callee b/script/testdata/spawn_callee_exec_callee new file mode 100755 index 0000000000..e7e344be7a Binary files /dev/null and b/script/testdata/spawn_callee_exec_callee differ diff --git a/script/testdata/spawn_callee_exec_callee.c b/script/testdata/spawn_callee_exec_callee.c new file mode 100644 index 0000000000..a53d0f5123 --- /dev/null +++ b/script/testdata/spawn_callee_exec_callee.c @@ -0,0 +1,3 @@ +#include + +int main() { return 0; } diff --git a/script/testdata/spawn_callee_exec_caller b/script/testdata/spawn_callee_exec_caller new file mode 100755 index 0000000000..671dd0acd2 Binary files /dev/null and b/script/testdata/spawn_callee_exec_caller differ diff --git a/script/testdata/spawn_callee_exec_caller.c b/script/testdata/spawn_callee_exec_caller.c new file mode 100644 index 0000000000..289a95b699 --- /dev/null +++ b/script/testdata/spawn_callee_exec_caller.c @@ -0,0 +1,8 @@ +#include +#include "ckb_syscalls.h" + +int main() { + // syscall exec + syscall(2043, 2, 3, 0, 0, 0, NULL); + return -1; +} diff --git a/script/testdata/spawn_callee_out_of_cycles b/script/testdata/spawn_callee_out_of_cycles new file mode 100755 index 0000000000..3b2f6684d2 Binary files /dev/null and b/script/testdata/spawn_callee_out_of_cycles differ diff --git a/script/testdata/spawn_callee_out_of_cycles.c b/script/testdata/spawn_callee_out_of_cycles.c new file mode 100644 index 0000000000..caad7a35f3 --- /dev/null +++ b/script/testdata/spawn_callee_out_of_cycles.c @@ -0,0 +1,10 @@ +#include + +int fib(int n) { + if (n < 2) { + return n; + } + return fib(n - 1) + fib(n - 2); +} + +int main() { return fib(100); } diff --git a/script/testdata/spawn_caller_current_cycles b/script/testdata/spawn_caller_current_cycles new file mode 100755 index 0000000000..d22c5283b0 Binary files /dev/null and b/script/testdata/spawn_caller_current_cycles differ diff --git a/script/testdata/spawn_caller_current_cycles.c b/script/testdata/spawn_caller_current_cycles.c new file mode 100644 index 0000000000..af6149bed5 --- /dev/null +++ b/script/testdata/spawn_caller_current_cycles.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include "utils.h" +#include "ckb_syscalls.h" + +int fib(int n) { + if (n < 2) { + return n; + } + return fib(n - 1) + fib(n - 2); +} + +int main() { + // Use invalid calculations to make the current cycles a larger value. + if (fib(20) != 6765) { + return 1; + } + + int cycles = ckb_current_cycles(); + char buffer[16] = {0}; + sprintf_(buffer, "%d", cycles); + const char *argv[] = {&buffer[0], 0}; + return simple_spawn_args(1, 1, argv); +} diff --git a/script/testdata/spawn_caller_exec b/script/testdata/spawn_caller_exec new file mode 100755 index 0000000000..dffd1dd715 Binary files /dev/null and b/script/testdata/spawn_caller_exec differ diff --git a/script/testdata/spawn_caller_exec.c b/script/testdata/spawn_caller_exec.c new file mode 100644 index 0000000000..2d63e2f952 --- /dev/null +++ b/script/testdata/spawn_caller_exec.c @@ -0,0 +1,4 @@ +#include +#include "utils.h" + +int main() { return simple_spawn(1); } diff --git a/script/testdata/spawn_caller_out_of_cycles b/script/testdata/spawn_caller_out_of_cycles new file mode 100755 index 0000000000..a702a77577 Binary files /dev/null and b/script/testdata/spawn_caller_out_of_cycles differ diff --git a/script/testdata/spawn_caller_out_of_cycles.c b/script/testdata/spawn_caller_out_of_cycles.c new file mode 100644 index 0000000000..e64f5f398a --- /dev/null +++ b/script/testdata/spawn_caller_out_of_cycles.c @@ -0,0 +1,3 @@ +#include "utils.h" + +int main() { return simple_spawn(1); } diff --git a/script/testdata/spawn_caller_out_of_cycles_wrap b/script/testdata/spawn_caller_out_of_cycles_wrap new file mode 100755 index 0000000000..376bcc8ada Binary files /dev/null and b/script/testdata/spawn_caller_out_of_cycles_wrap differ diff --git a/script/testdata/spawn_caller_out_of_cycles_wrap.c b/script/testdata/spawn_caller_out_of_cycles_wrap.c new file mode 100644 index 0000000000..6d182a140f --- /dev/null +++ b/script/testdata/spawn_caller_out_of_cycles_wrap.c @@ -0,0 +1,2 @@ +#include "utils.h" +int main() { return simple_spawn(2); } diff --git a/script/testdata/spawn_caller_strcat b/script/testdata/spawn_caller_strcat index 98358ec114..57a356128f 100755 Binary files a/script/testdata/spawn_caller_strcat and b/script/testdata/spawn_caller_strcat differ diff --git a/script/testdata/spawn_caller_strcat.c b/script/testdata/spawn_caller_strcat.c index 6bb675e2b3..b1cd8f26a2 100644 --- a/script/testdata/spawn_caller_strcat.c +++ b/script/testdata/spawn_caller_strcat.c @@ -5,13 +5,11 @@ #include "utils.h" int main() { - printf("start spawn_caller_strcat ..."); int err = 0; const char *argv[] = {"hello", "world"}; uint64_t pid = 0; uint64_t fds[2] = {0}; uint64_t inherited_fds[3] = {0}; - printf("create_std_pipes ..."); err = create_std_pipes(fds, inherited_fds); CHECK(err); @@ -21,7 +19,6 @@ int main() { .process_id = &pid, .inherited_fds = inherited_fds, }; - printf("start spawn ..."); err = ckb_spawn(1, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); CHECK(err); uint8_t buffer[1024] = {0}; diff --git a/script/testdata/spawn_caller_strcat_wrap b/script/testdata/spawn_caller_strcat_wrap new file mode 100755 index 0000000000..7f49a82ec0 Binary files /dev/null and b/script/testdata/spawn_caller_strcat_wrap differ diff --git a/script/testdata/spawn_caller_strcat_wrap.c b/script/testdata/spawn_caller_strcat_wrap.c new file mode 100644 index 0000000000..ad246f46b0 --- /dev/null +++ b/script/testdata/spawn_caller_strcat_wrap.c @@ -0,0 +1,6 @@ +#include +#include +#include +#include "utils.h" + +int main() { return simple_spawn(2); } \ No newline at end of file diff --git a/script/testdata/spawn_recursive b/script/testdata/spawn_recursive new file mode 100755 index 0000000000..4e5934da75 Binary files /dev/null and b/script/testdata/spawn_recursive differ diff --git a/script/testdata/spawn_recursive.c b/script/testdata/spawn_recursive.c new file mode 100644 index 0000000000..29b80ee430 --- /dev/null +++ b/script/testdata/spawn_recursive.c @@ -0,0 +1,4 @@ + +#include "utils.h" + +int main() { return simple_spawn(0); } diff --git a/script/testdata/spawn_times b/script/testdata/spawn_times new file mode 100755 index 0000000000..4a5e1eeddf Binary files /dev/null and b/script/testdata/spawn_times differ diff --git a/script/testdata/spawn_times.c b/script/testdata/spawn_times.c new file mode 100644 index 0000000000..da331d2162 --- /dev/null +++ b/script/testdata/spawn_times.c @@ -0,0 +1,13 @@ + +#include "utils.h" + +int main() { + int err = 0; + for (size_t i = 0; i < 10000; i++) { + err = simple_spawn(0); + CHECK(err); + } + +exit: + return err; +} diff --git a/script/testdata/utils.h b/script/testdata/utils.h index ae98955cb7..13f12af87b 100644 --- a/script/testdata/utils.h +++ b/script/testdata/utils.h @@ -2,7 +2,10 @@ #ifndef __UTILS_H__ #define __UTILS_H__ +#include "ckb_consts.h" #include +#include "ckb_consts.h" +#include "ckb_syscalls.h" enum CkbSpawnError { ErrorCommon = 31, @@ -62,3 +65,37 @@ int create_std_pipes(uint64_t* fds, uint64_t* inherited_fds) { exit: return err; } + +// spawn script at `index` in cell_deps without any argc, argv +int simple_spawn(size_t index) { + int err = 0; + int8_t spawn_exit_code = 255; + const char* argv[1] = {0}; + uint64_t pid = 0; + uint64_t fds[1] = {0}; + spawn_args_t spgs = {.argc = 0, .argv = argv, .process_id = &pid, .inherited_fds = fds}; + err = ckb_spawn(index, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); + CHECK(err); + err = ckb_wait(pid, &spawn_exit_code); + CHECK(err); + CHECK(spawn_exit_code); + +exit: + return err; +} + +// spawn script at `index` in cell_deps with argv +int simple_spawn_args(size_t index, int argc, const char* argv[]) { + int err = 0; + int8_t spawn_exit_code = 255; + uint64_t pid = 0; + uint64_t fds[1] = {0}; + spawn_args_t spgs = {.argc = argc, .argv = argv, .process_id = &pid, .inherited_fds = fds}; + err = ckb_spawn(index, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); + CHECK(err); + err = ckb_wait(pid, &spawn_exit_code); + CHECK(err); + CHECK(spawn_exit_code); +exit: + return err; +}