From 8d8ce5526c106bfba55e5391e12550cc8120c05a Mon Sep 17 00:00:00 2001 From: Mohanson Date: Mon, 4 Mar 2024 14:20:00 +0800 Subject: [PATCH 001/135] Just copy codes in it --- Cargo.lock | 4 +- script/Cargo.toml | 2 +- script/src/lib.rs | 3 + script/src/v2_scheduler.rs | 778 +++++++++++++++++++++++++++++++++++++ script/src/v2_syscalls.rs | 529 +++++++++++++++++++++++++ script/src/v2_types.rs | 275 +++++++++++++ 6 files changed, 1588 insertions(+), 3 deletions(-) create mode 100644 script/src/v2_scheduler.rs create mode 100644 script/src/v2_syscalls.rs create mode 100644 script/src/v2_types.rs diff --git a/Cargo.lock b/Cargo.lock index ff99548f85..f828918306 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1733,7 +1733,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/chenyukang/ckb-vm.git?branch=yukang-local-changes#9cd3c20b009ea8e74a46143cafdde0acac9e323b" +source = "git+https://github.com/libraries/ckb-vm?branch=spawn2#953a9474ce7d5d0d29cc8cd173265a150805a54a" dependencies = [ "byteorder", "bytes", @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/chenyukang/ckb-vm.git?branch=yukang-local-changes#9cd3c20b009ea8e74a46143cafdde0acac9e323b" +source = "git+https://github.com/libraries/ckb-vm?branch=spawn2#953a9474ce7d5d0d29cc8cd173265a150805a54a" dependencies = [ "paste", ] diff --git a/script/Cargo.toml b/script/Cargo.toml index 9230b358c1..c595451420 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,7 +22,7 @@ ckb-traits = { path = "../traits", version = "= 0.114.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.114.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.114.0-pre" } -ckb-vm = { git = "https://github.com/chenyukang/ckb-vm.git", version = "=0.24.9", idefault-features = false, branch = "yukang-local-changes"} +ckb-vm = { git = "https://github.com/libraries/ckb-vm", branch = "spawn2", features = ["asm"] } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.114.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/script/src/lib.rs b/script/src/lib.rs index b24f94db63..02c44f3953 100644 --- a/script/src/lib.rs +++ b/script/src/lib.rs @@ -6,6 +6,9 @@ mod type_id; mod types; mod verify; mod verify_env; +mod v2_scheduler; +mod v2_syscalls; +mod v2_types; 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 new file mode 100644 index 0000000000..6da642000f --- /dev/null +++ b/script/src/v2_scheduler.rs @@ -0,0 +1,778 @@ +use crate::v2_syscalls::INDEX_OUT_OF_BOUND; +use crate::v2_types::PipeIoArgs; +use crate::{ + v2_syscalls::{ + transferred_byte_cycles, MachineContext, INVALID_PIPE, JOIN_FAILURE, OTHER_END_CLOSED, + SUCCESS, + }, + v2_types::{ + DataPieceId, FullSuspendedState, Message, PipeId, RunMode, TxData, VmId, VmState, + FIRST_PIPE_SLOT, FIRST_VM_ID, + }, +}; +use crate::{ScriptVersion, TransactionScriptsVerifier}; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; +use ckb_types::core::Cycle; +use ckb_vm::{ + bytes::Bytes, + cost_model::estimate_cycles, + elf::parse_elf, + machine::{ + asm::{AsmCoreMachine, AsmMachine}, + CoreMachine, DefaultMachineBuilder, Pause, SupportMachine, + }, + memory::Memory, + registers::A0, + snapshot2::{DataSource, Snapshot2}, + Error, Register, +}; +use std::sync::{Arc, Mutex}; +use std::{ + collections::{BTreeMap, HashMap}, + mem::size_of, +}; + +const ROOT_VM_ID: VmId = FIRST_VM_ID; +const MAX_INSTANTIATED_VMS: usize = 4; + +/// A single Scheduler instance is used to verify a single script +/// within a CKB transaction. +/// +/// A scheduler holds & manipulates a core, the scheduler also holds +/// all CKB-VM machines, each CKB-VM machine also gets a mutable reference +/// of the core for IO operations. +pub struct Scheduler< + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +> { + tx_data: TxData
, + // In fact, Scheduler here has the potential to totally replace + // TransactionScriptsVerifier, nonetheless much of current syscall + // implementation is strictly tied to TransactionScriptsVerifier, we + // are using it here to save some extra code. + verifier: TransactionScriptsVerifier
, + + total_cycles: Cycle, + next_vm_id: VmId, + next_pipe_slot: u64, + states: BTreeMap, + pipes: HashMap, + inherited_fd: BTreeMap>, + instantiated: BTreeMap, AsmMachine)>, + suspended: HashMap>, + terminated_vms: HashMap, + + // message_box is expected to be empty before returning from `run` + // function, there is no need to persist messages. + message_box: Arc>>, +} + +impl + Scheduler
+{ + /// Create a new scheduler from empty state + pub fn new(tx_data: TxData
, verifier: TransactionScriptsVerifier
) -> Self { + Self { + tx_data, + verifier, + total_cycles: 0, + next_vm_id: FIRST_VM_ID, + next_pipe_slot: FIRST_PIPE_SLOT, + states: BTreeMap::default(), + pipes: HashMap::default(), + inherited_fd: BTreeMap::default(), + instantiated: BTreeMap::default(), + suspended: HashMap::default(), + message_box: Arc::new(Mutex::new(Vec::new())), + terminated_vms: HashMap::default(), + } + } + + pub fn consumed_cycles(&self) -> Cycle { + self.total_cycles + } + + /// Resume a previously suspended scheduler state + pub fn resume( + tx_data: TxData
, + verifier: TransactionScriptsVerifier
, + full: FullSuspendedState, + ) -> Self { + Self { + tx_data, + verifier, + total_cycles: full.total_cycles, + next_vm_id: full.next_vm_id, + next_pipe_slot: full.next_pipe_slot, + states: full + .vms + .iter() + .map(|(id, state, _)| (*id, state.clone())) + .collect(), + pipes: full.pipes.into_iter().collect(), + inherited_fd: full.inherited_fd.into_iter().collect(), + instantiated: BTreeMap::default(), + suspended: full + .vms + .into_iter() + .map(|(id, _, snapshot)| (id, snapshot)) + .collect(), + message_box: Arc::new(Mutex::new(Vec::new())), + terminated_vms: full.terminated_vms.into_iter().collect(), + } + } + + /// Suspend current scheduler into a serializable full state + pub fn suspend(mut self) -> Result { + let mut vms = Vec::with_capacity(self.states.len()); + let instantiated_ids: Vec<_> = self.instantiated.keys().cloned().collect(); + for id in instantiated_ids { + self.suspend_vm(&id)?; + } + for (id, state) in self.states { + let snapshot = self.suspended.remove(&id).unwrap(); + vms.push((id, state, snapshot)); + } + Ok(FullSuspendedState { + total_cycles: self.total_cycles, + next_vm_id: self.next_vm_id, + next_pipe_slot: self.next_pipe_slot, + vms, + pipes: self.pipes.into_iter().collect(), + inherited_fd: self.inherited_fd.into_iter().collect(), + terminated_vms: self.terminated_vms.into_iter().collect(), + }) + } + + /// This is the only entrypoint for running the scheduler, + /// both newly created instance and resumed instance are supported. + /// It accepts 2 run mode, one can either limit the cycles to execute, + /// or use a pause signal to trigger termination. + /// + /// Only when the execution terminates without VM errors, will this + /// function return an exit code(could still be non-zero) and total + /// consumed cycles. + /// + /// Err would be returned in the following cases: + /// * Cycle limit reached, the returned error would be ckb_vm::Error::CyclesExceeded, + /// * Pause trigger, the returned error would be ckb_vm::Error::Pause, + /// * Other terminating errors + pub fn run(&mut self, mode: RunMode) -> Result<(i8, Cycle), Error> { + if self.states.is_empty() { + // Booting phase, we will need to initialize the first VM. + assert_eq!( + self.boot_vm(&DataPieceId::Program, 0, u64::max_value(), &[])?, + ROOT_VM_ID + ); + } + assert!(self.states.contains_key(&ROOT_VM_ID)); + + let (pause, mut limit_cycles) = match mode { + RunMode::LimitCycles(limit_cycles) => (Pause::new(), limit_cycles), + RunMode::Pause(pause) => (pause, u64::max_value()), + }; + + while self.states[&ROOT_VM_ID] != VmState::Terminated { + let consumed_cycles = self.iterate(pause.clone(), limit_cycles)?; + limit_cycles = consumed_cycles + .checked_sub(consumed_cycles) + .ok_or(Error::CyclesExceeded)?; + } + + // At this point, root VM cannot be suspended + let root_vm = &self.instantiated[&ROOT_VM_ID]; + Ok((root_vm.1.machine.exit_code(), self.total_cycles)) + } + + // This is internal function that does the actual VM execution loop. + // Here both pause signal and limit_cycles are provided so as to simplify + // branches. + fn iterate(&mut self, pause: Pause, limit_cycles: Cycle) -> Result { + // 1. Process all pending VM reads & writes + self.process_io()?; + // 2. Run an actual VM + // Find a runnable VM that has the largest ID + let vm_id_to_run = self + .states + .iter() + .rev() + .filter(|(_, state)| matches!(state, VmState::Runnable)) + .map(|(id, _)| *id) + .next(); + if vm_id_to_run.is_none() { + return Err(Error::Unexpected( + "A deadlock situation has been reached!".to_string(), + )); + } + let vm_id_to_run = vm_id_to_run.unwrap(); + // log::debug!("Running VM {}", vm_id_to_run); + let (result, consumed_cycles) = { + self.ensure_vms_instantiated(&[vm_id_to_run])?; + let (context, machine) = self.instantiated.get_mut(&vm_id_to_run).unwrap(); + context.set_base_cycles(self.total_cycles); + machine.set_max_cycles(limit_cycles); + machine.machine.set_pause(pause); + let result = machine.run(); + let consumed_cycles = { + let c = machine.machine.cycles(); + machine.machine.set_cycles(0); + c + }; + // This shall be the only place where total_cycles gets updated + self.total_cycles = self + .total_cycles + .checked_add(consumed_cycles) + .ok_or(Error::CyclesOverflow)?; + (result, consumed_cycles) + }; + // 3. Process message box, update VM states accordingly + self.process_message_box()?; + assert!(self.message_box.lock().expect("lock").is_empty()); + // log::debug!("VM states: {:?}", self.states); + // log::debug!("Pipes and owners: {:?}", self.pipes); + // 4. If the VM terminates, update VMs in join state, also closes its pipes + match result { + Ok(code) => { + // log::debug!("VM {} terminates with code {}", vm_id_to_run, code); + self.terminated_vms.insert(vm_id_to_run, code); + // When root VM terminates, the execution stops immediately, we will purge + // all non-root VMs, and only keep root VM in states. + // When non-root VM terminates, we only purge the VM's own states. + if vm_id_to_run == ROOT_VM_ID { + self.ensure_vms_instantiated(&[vm_id_to_run])?; + self.instantiated.retain(|id, _| *id == vm_id_to_run); + self.suspended.clear(); + self.states.clear(); + self.states.insert(vm_id_to_run, VmState::Terminated); + } else { + let mut joining_vms: Vec<(VmId, u64)> = Vec::new(); + self.states.iter().for_each(|(vm_id, state)| { + if let VmState::Join { + target_vm_id, + exit_code_addr, + } = state + { + if *target_vm_id == vm_id_to_run { + joining_vms.push((*vm_id, *exit_code_addr)); + } + } + }); + // For all joining VMs, update exit code, then mark them as + // runnable state. + for (vm_id, exit_code_addr) in joining_vms { + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine + .machine + .memory_mut() + .store8(&exit_code_addr, &u64::from_i8(code))?; + machine.machine.set_register(A0, SUCCESS as u64); + self.states.insert(vm_id, VmState::Runnable); + } + // Close pipes + self.pipes.retain(|_, vm_id| *vm_id != vm_id_to_run); + // Clear terminated VM states + self.states.remove(&vm_id_to_run); + self.instantiated.remove(&vm_id_to_run); + self.suspended.remove(&vm_id_to_run); + } + Ok(consumed_cycles) + } + Err(Error::External(msg)) if msg == "YIELD" => Ok(consumed_cycles), + Err(e) => Err(e), + } + } + + fn process_message_box(&mut self) -> Result<(), Error> { + let messages: Vec = self.message_box.lock().expect("lock").drain(..).collect(); + for message in messages { + match message { + Message::Spawn(vm_id, args) => { + // All pipes must belong to the correct owner + for pipe in &args.pipes { + if !(self.pipes.contains_key(pipe) && (self.pipes[pipe] == vm_id)) { + return Err(Error::Unexpected(format!( + "VM {} does not own pipe {}!", + vm_id, pipe.0, + ))); + } + } + // TODO: spawn limits + let spawned_vm_id = + self.boot_vm(&args.data_piece_id, args.offset, args.length, &args.argv)?; + // Move passed pipes from spawner to spawnee + for pipe in &args.pipes { + self.pipes.insert(*pipe, spawned_vm_id); + } + // here we keep the original version of file descriptors. + // if one fd is moved afterward, this inherited file descriptors doesn't change. + // log::info!( + // "VmId = {} with Inherited file descriptor {:?}", + // spawned_vm_id, + // args.pipes + // ); + self.inherited_fd.insert(spawned_vm_id, args.pipes.clone()); + + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine + .machine + .memory_mut() + .store64(&args.instance_id_addr, &spawned_vm_id)?; + machine.machine.set_register(A0, SUCCESS as u64); + } + } + Message::Join(vm_id, args) => { + if let Some(exit_code) = self.terminated_vms.get(&args.target_id).copied() { + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine + .machine + .memory_mut() + .store8(&args.exit_code_addr, &u64::from_i8(exit_code))?; + machine.machine.set_register(A0, SUCCESS as u64); + self.states.insert(vm_id, VmState::Runnable); + } + continue; + } + if !self.states.contains_key(&args.target_id) { + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, JOIN_FAILURE as u64); + } + continue; + } + // Return code will be updated when the joining VM exits + self.states.insert( + vm_id, + VmState::Join { + target_vm_id: args.target_id, + exit_code_addr: args.exit_code_addr, + }, + ); + } + Message::Pipe(vm_id, args) => { + // TODO: pipe limits + let (p1, p2, slot) = PipeId::create(self.next_pipe_slot); + self.next_pipe_slot = slot; + // log::debug!("VM {} creates pipes ({}, {})", vm_id, p1.0, p2.0); + + self.pipes.insert(p1, vm_id); + self.pipes.insert(p2, vm_id); + + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine + .machine + .memory_mut() + .store64(&args.pipe1_addr, &p1.0)?; + machine + .machine + .memory_mut() + .store64(&args.pipe2_addr, &p2.0)?; + machine.machine.set_register(A0, SUCCESS as u64); + } + } + Message::PipeRead(vm_id, args) => { + if !(self.pipes.contains_key(&args.pipe) && (self.pipes[&args.pipe] == vm_id)) { + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, INVALID_PIPE as u64); + } + continue; + } + if !self.pipes.contains_key(&args.pipe.other_pipe()) { + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, OTHER_END_CLOSED as u64); + } + continue; + } + // Return code will be updated when the read operation finishes + self.states.insert( + vm_id, + VmState::WaitForRead { + pipe: args.pipe, + length: args.length, + buffer_addr: args.buffer_addr, + length_addr: args.length_addr, + }, + ); + } + Message::PipeWrite(vm_id, args) => { + if !(self.pipes.contains_key(&args.pipe) && (self.pipes[&args.pipe] == vm_id)) { + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, INVALID_PIPE as u64); + } + continue; + } + if !self.pipes.contains_key(&args.pipe.other_pipe()) { + self.ensure_vms_instantiated(&[vm_id])?; + { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, OTHER_END_CLOSED as u64); + } + continue; + } + // Return code will be updated when the write operation finishes + self.states.insert( + vm_id, + VmState::WaitForWrite { + pipe: args.pipe, + consumed: 0, + length: args.length, + buffer_addr: args.buffer_addr, + length_addr: args.length_addr, + }, + ); + } + Message::InheritedFileDescriptor(vm_id, args) => { + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let PipeIoArgs { + buffer_addr, + length_addr, + .. + } = args; + let input_length = machine + .machine + .inner_mut() + .memory_mut() + .load64(&length_addr)?; + let inherited_fd = &self.inherited_fd[&vm_id]; + let actual_length = inherited_fd.len() as u64; + if buffer_addr == 0 { + if input_length == 0 { + machine + .machine + .inner_mut() + .memory_mut() + .store64(&length_addr, &actual_length)?; + machine.machine.set_register(A0, SUCCESS as u64); + } else { + // TODO: in the previous convention + // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0009-vm-syscalls/0009-vm-syscalls.md#partial-loading + // this will load data in to address 0 without notice. It is now marked as an error. + machine.machine.set_register(A0, INDEX_OUT_OF_BOUND as u64); + } + continue; + } + let mut buffer_addr2 = buffer_addr; + let copy_length = u64::min(input_length, actual_length); + for i in 0..copy_length { + let fd = inherited_fd[i as usize].0; + machine + .machine + .inner_mut() + .memory_mut() + .store64(&buffer_addr2, &fd)?; + buffer_addr2 += size_of::() as u64; + } + machine + .machine + .inner_mut() + .memory_mut() + .store64(&length_addr, &actual_length)?; + machine.machine.set_register(A0, SUCCESS as u64); + } + } + } + Ok(()) + } + + fn process_io(&mut self) -> Result<(), Error> { + let mut reads: HashMap = HashMap::default(); + let mut closed_pipes: Vec = Vec::new(); + self.states.iter().for_each(|(vm_id, state)| { + if let VmState::WaitForRead { pipe, .. } = state { + if self.pipes.contains_key(&pipe.other_pipe()) { + reads.insert(*pipe, (*vm_id, state.clone())); + } else { + closed_pipes.push(*vm_id); + } + } + }); + let mut pairs: Vec<[(VmId, VmState); 2]> = Vec::new(); + self.states.iter().for_each(|(vm_id, state)| { + if let VmState::WaitForWrite { pipe, .. } = state { + if self.pipes.contains_key(&pipe.other_pipe()) { + if let Some((read_vm_id, read_state)) = reads.get(&pipe.other_pipe()) { + pairs.push([(*read_vm_id, read_state.clone()), (*vm_id, state.clone())]); + } + } else { + closed_pipes.push(*vm_id); + } + } + }); + // Finish read / write syscalls for pipes that are closed on the other end + for vm_id in closed_pipes { + match self.states[&vm_id].clone() { + VmState::WaitForRead { length_addr, .. } => { + let (_, read_machine) = self.instantiated.get_mut(&vm_id).unwrap(); + read_machine + .machine + .memory_mut() + .store64(&length_addr, &0)?; + read_machine.machine.set_register(A0, SUCCESS as u64); + self.states.insert(vm_id, VmState::Runnable); + } + VmState::WaitForWrite { + consumed, + length_addr, + .. + } => { + let (_, write_machine) = self.instantiated.get_mut(&vm_id).unwrap(); + write_machine + .machine + .memory_mut() + .store64(&length_addr, &consumed)?; + write_machine.machine.set_register(A0, SUCCESS as u64); + self.states.insert(vm_id, VmState::Runnable); + } + _ => (), + } + } + // Transfering data from write pipes to read pipes + for [(read_vm_id, read_state), (write_vm_id, write_state)] in pairs { + let VmState::WaitForRead { + length: read_length, + buffer_addr: read_buffer_addr, + length_addr: read_length_addr, + .. + } = read_state + else { + unreachable!() + }; + let VmState::WaitForWrite { + pipe: write_pipe, + mut consumed, + length: write_length, + buffer_addr: write_buffer_addr, + length_addr: write_length_addr, + } = write_state + else { + unreachable!() + }; + + self.ensure_vms_instantiated(&[read_vm_id, write_vm_id])?; + { + let fillable = read_length; + let consumable = write_length - consumed; + let copiable = std::cmp::min(fillable, consumable); + + // Actual data copying + // TODO: charge cycles + let data = self + .instantiated + .get_mut(&write_vm_id) + .unwrap() + .1 + .machine + .memory_mut() + .load_bytes(write_buffer_addr.wrapping_add(consumed), copiable)?; + self.instantiated + .get_mut(&read_vm_id) + .unwrap() + .1 + .machine + .memory_mut() + .store_bytes(read_buffer_addr, &data)?; + + // Read syscall terminates as soon as some data are filled + let (_, read_machine) = self.instantiated.get_mut(&read_vm_id).unwrap(); + read_machine + .machine + .memory_mut() + .store64(&read_length_addr, &copiable)?; + read_machine.machine.set_register(A0, SUCCESS as u64); + self.states.insert(read_vm_id, VmState::Runnable); + + // Write syscall, however, terminates only when all the data + // have been written, or when the pairing read pipe is closed. + consumed += copiable; + if consumed == write_length { + // write VM has fulfilled its write request + let (_, write_machine) = self.instantiated.get_mut(&write_vm_id).unwrap(); + write_machine + .machine + .memory_mut() + .store64(&write_length_addr, &write_length)?; + write_machine.machine.set_register(A0, SUCCESS as u64); + self.states.insert(write_vm_id, VmState::Runnable); + } else { + // Only update write VM state + self.states.insert( + write_vm_id, + VmState::WaitForWrite { + pipe: write_pipe, + consumed, + length: write_length, + buffer_addr: write_buffer_addr, + length_addr: write_length_addr, + }, + ); + } + } + } + Ok(()) + } + + // Ensure VMs are instantiated + fn ensure_vms_instantiated(&mut self, ids: &[VmId]) -> Result<(), Error> { + if ids.len() > MAX_INSTANTIATED_VMS { + return Err(Error::Unexpected(format!( + "At most {} VMs can be instantiated but {} are requested!", + MAX_INSTANTIATED_VMS, + ids.len() + ))); + } + + let mut uninstantiated_ids: Vec = ids + .iter() + .filter(|id| !self.instantiated.contains_key(id)) + .copied() + .collect(); + while (!uninstantiated_ids.is_empty()) && (self.instantiated.len() < MAX_INSTANTIATED_VMS) { + let id = uninstantiated_ids.pop().unwrap(); + self.resume_vm(&id)?; + } + + if !uninstantiated_ids.is_empty() { + // instantiated is a BTreeMap, an iterator on it maintains key order to ensure deterministic behavior + let suspendable_ids: Vec = self + .instantiated + .keys() + .filter(|id| !ids.contains(id)) + .copied() + .collect(); + + assert!(suspendable_ids.len() >= uninstantiated_ids.len()); + for i in 0..uninstantiated_ids.len() { + self.suspend_vm(&suspendable_ids[i])?; + self.resume_vm(&uninstantiated_ids[i])?; + } + } + + Ok(()) + } + + // Resume a suspended VM + fn resume_vm(&mut self, id: &VmId) -> Result<(), Error> { + println!("Resuming VM: {}", id); + if !self.suspended.contains_key(id) { + return Err(Error::Unexpected(format!("VM {:?} is not suspended!", id))); + } + let snapshot = &self.suspended[id]; + let (context, mut machine) = self.create_dummy_vm(id)?; + { + let mut sc = context.snapshot2_context().lock().expect("lock"); + sc.resume(&mut machine.machine, snapshot)?; + } + // TODO: charge cycles + self.instantiated.insert(*id, (context, machine)); + self.suspended.remove(id); + Ok(()) + } + + // Suspend an instantiated VM + fn suspend_vm(&mut self, id: &VmId) -> Result<(), Error> { + // log::debug!("Suspending VM: {}", id); + if !self.instantiated.contains_key(id) { + return Err(Error::Unexpected(format!( + "VM {:?} is not instantiated!", + id + ))); + } + // TODO: charge cycles + let (context, machine) = self.instantiated.get_mut(id).unwrap(); + let snapshot = { + let sc = context.snapshot2_context().lock().expect("lock"); + sc.make_snapshot(&mut machine.machine)? + }; + self.suspended.insert(*id, snapshot); + self.instantiated.remove(id); + Ok(()) + } + + fn boot_vm( + &mut self, + data_piece_id: &DataPieceId, + offset: u64, + length: u64, + args: &[Bytes], + ) -> Result { + // Newly booted VM will be instantiated by default + while self.instantiated.len() >= MAX_INSTANTIATED_VMS { + // instantiated is a BTreeMap, first_entry will maintain key order + let id = *self.instantiated.first_entry().unwrap().key(); + self.suspend_vm(&id)?; + } + + let id = self.next_vm_id; + self.next_vm_id += 1; + let (context, mut machine) = self.create_dummy_vm(&id)?; + { + let mut sc = context.snapshot2_context().lock().expect("lock"); + let (program, _) = sc.data_source().load_data(data_piece_id, offset, length)?; + let metadata = parse_elf::(&program, machine.machine.version())?; + let bytes = machine.load_program_with_metadata(&program, &metadata, args)?; + sc.mark_program(&mut machine.machine, &metadata, data_piece_id, offset)?; + machine + .machine + .add_cycles_no_checking(transferred_byte_cycles(bytes))?; + } + self.instantiated.insert(id, (context, machine)); + self.states.insert(id, VmState::Runnable); + + Ok(id) + } + + // Create a new VM instance with syscalls attached + fn create_dummy_vm(&self, id: &VmId) -> Result<(MachineContext
, AsmMachine), Error> { + // The code here looks slightly weird, since I don't want to copy over all syscall + // impls here again. Ideally, this scheduler package should be merged with ckb-script, + // or simply replace ckb-script. That way, the quirks here will be eliminated. + let version = self + .verifier + .select_version(&self.tx_data.script_group.script) + .map_err(|e| Error::Unexpected(format!("Select version error: {:?}", e)))?; + // log::debug!("Creating VM {} using version {:?}", id, version); + let core_machine = AsmCoreMachine::new( + version.vm_isa(), + version.vm_version(), + // We will update max_cycles for each machine when it gets a chance to run + u64::max_value(), + ); + let machine_context = + MachineContext::new(*id, self.message_box.clone(), self.tx_data.clone()); + let machine_builder = DefaultMachineBuilder::new(core_machine) + .instruction_cycle_func(Box::new(estimate_cycles)) + // ckb-vm iterates syscalls in insertion order, by putting + // MachineContext at the first place, we can override other + // syscalls with implementations from MachineContext. For example, + // we can override load_cell_data syscall with a new implementation. + .syscall(Box::new(machine_context.clone())); + let syscalls = self.verifier.generate_syscalls( + // Skip current spawn implementation + if version == ScriptVersion::V2 { + ScriptVersion::V1 + } else { + version + }, + &self.tx_data.script_group, + Default::default(), + ); + let machine_builder = syscalls + .into_iter() + .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); + let default_machine = machine_builder.build(); + Ok((machine_context, AsmMachine::new(default_machine))) + } +} diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs new file mode 100644 index 0000000000..aa256897d7 --- /dev/null +++ b/script/src/v2_syscalls.rs @@ -0,0 +1,529 @@ +// Syscall implementation + +use crate::v2_types::{ + DataPieceId, JoinArgs, Message, PipeArgs, PipeId, PipeIoArgs, SpawnArgs, TxData, VmId, +}; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; +use ckb_vm::{ + bytes::Bytes, + machine::SupportMachine, + memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, + registers::{A0, A1, A2, A3, A4, A5, A7}, + snapshot2::{DataSource, Snapshot2Context}, + syscalls::Syscalls, + Error, Register, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Clone)] +pub struct MachineContext< + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +> { + id: VmId, + base_cycles: Arc>, + message_box: Arc>>, + snapshot2_context: Arc>>>, +} + +impl + MachineContext
+{ + pub fn new(id: VmId, message_box: Arc>>, tx_data: TxData
) -> Self { + Self { + id, + base_cycles: Arc::new(Mutex::new(0)), + message_box, + snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(tx_data))), + } + } + + pub fn snapshot2_context(&self) -> &Arc>>> { + &self.snapshot2_context + } + + pub fn base_cycles(&self) -> u64 { + *self.base_cycles.lock().expect("lock") + } + + pub fn set_base_cycles(&mut self, base_cycles: u64) { + *self.base_cycles.lock().expect("lock") = base_cycles; + } + + // The different architecture here requires a re-implementation on current + // cycles syscall. + fn current_cycles(&mut self, machine: &mut Mac) -> Result<(), Error> { + let cycles = self + .base_cycles() + .checked_add(machine.cycles()) + .ok_or(Error::CyclesOverflow)?; + machine.set_register(A0, Mac::REG::from_u64(cycles)); + Ok(()) + } + + // Reimplementation of load_cell_data but keep tracks of pages that are copied from + // surrounding transaction data. Those pages do not need to be added to snapshots. + fn load_cell_data(&mut self, machine: &mut Mac) -> Result<(), Error> { + let index = machine.registers()[A3].to_u64(); + let source = machine.registers()[A4].to_u64(); + + let data_piece_id = match DataPieceId::try_from((source, index)) { + Ok(id) => id, + Err(e) => { + // Current implementation would throw an error immediately + // for some source values, but return INDEX_OUT_OF_BOUND error + // for other values. Here for simplicity, we would return + // INDEX_OUT_OF_BOUND error in all cases. But the code might + // differ to mimic current on-chain behavior + println!("DataPieceId parsing error: {:?}", e); + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + }; + + let addr = machine.registers()[A0].to_u64(); + let size_addr = machine.registers()[A1].clone(); + let size = machine.memory_mut().load64(&size_addr)?.to_u64(); + let offset = machine.registers()[A2].to_u64(); + + let mut sc = self.snapshot2_context().lock().expect("lock"); + let (wrote_size, full_size) = + match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { + Ok(val) => val, + Err(Error::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; + + machine + .memory_mut() + .store64(&size_addr, &Mac::REG::from_u64(full_size))?; + machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; + machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); + Ok(()) + } + + // Reimplementation of load_cell_data_as_code but keep tracks of pages that are copied from + // surrounding transaction data. Those pages do not need to be added to snapshots. + // + // Different from load_cell_data, this method showcases advanced usage of Snapshot2, where + // one manually does the actual memory copying, then calls track_pages method to setup metadata + // used by Snapshot2. It does not rely on higher level methods provided by Snapshot2. + fn load_cell_data_as_code( + &mut self, + machine: &mut Mac, + ) -> Result<(), Error> { + let addr = machine.registers()[A0].to_u64(); + let memory_size = machine.registers()[A1].to_u64(); + let content_offset = machine.registers()[A2].to_u64(); + let content_size = machine.registers()[A3].to_u64(); + + let index = machine.registers()[A4].to_u64(); + let source = machine.registers()[A5].to_u64(); + + let data_piece_id = match DataPieceId::try_from((source, index)) { + Ok(id) => id, + Err(e) => { + // Current implementation would throw an error immediately + // for some source values, but return INDEX_OUT_OF_BOUND error + // for other values. Here for simplicity, we would return + // INDEX_OUT_OF_BOUND error in all cases. But the code might + // differ to mimic current on-chain behavior + println!("DataPieceId parsing error: {:?}", e); + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + }; + + let mut sc = self.snapshot2_context().lock().expect("lock"); + // We are using 0..u64::max_value() to fetch full cell, there is + // also no need to keep the full length value. Since cell's length + // is already full length. + let (cell, _) = match sc + .data_source() + .load_data(&data_piece_id, 0, u64::max_value()) + { + Ok(val) => val, + Err(Error::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; + + let content_end = content_offset + .checked_add(content_size) + .ok_or(Error::MemOutOfBound)?; + if content_offset >= cell.len() as u64 + || content_end > cell.len() as u64 + || content_size > memory_size + { + machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); + return Ok(()); + } + + machine.memory_mut().init_pages( + addr, + memory_size, + FLAG_EXECUTABLE | FLAG_FREEZED, + Some(cell.slice((content_offset as usize)..(content_end as usize))), + 0, + )?; + sc.track_pages(machine, addr, memory_size, &data_piece_id, content_offset)?; + + machine.add_cycles_no_checking(transferred_byte_cycles(memory_size))?; + machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); + Ok(()) + } + + // Reimplementing debug syscall for printing debug messages + fn debug(&mut self, machine: &mut Mac) -> Result<(), Error> { + let mut addr = machine.registers()[A0].to_u64(); + let mut buffer = Vec::new(); + + loop { + let byte = machine + .memory_mut() + .load8(&Mac::REG::from_u64(addr))? + .to_u8(); + if byte == 0 { + break; + } + buffer.push(byte); + addr += 1; + } + + machine.add_cycles_no_checking(transferred_byte_cycles(buffer.len() as u64))?; + let s = String::from_utf8(buffer) + .map_err(|e| Error::External(format!("String from buffer {e:?}")))?; + println!("VM {}: {}", self.id, s); + + Ok(()) + } + + // New, concurrent spawn implementation + fn spawn(&mut self, machine: &mut Mac) -> Result<(), Error> { + let index = machine.registers()[A0].to_u64(); + let source = machine.registers()[A1].to_u64(); + + let data_piece_id = match DataPieceId::try_from((source, index)) { + Ok(id) => id, + Err(e) => { + // Current implementation would throw an error immediately + // for some source values, but return INDEX_OUT_OF_BOUND error + // for other values. Here for simplicity, we would return + // INDEX_OUT_OF_BOUND error in all cases. But the code might + // differ to mimic current on-chain behavior + println!("DataPieceId parsing error: {:?}", e); + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + }; + + let bounds = machine.registers()[A2].to_u64(); + let offset = bounds >> 32; + let length = bounds as u32 as u64; + + let argv = { + let argc = machine.registers()[A3].to_u64(); + let mut argv_addr = machine.registers()[A4].to_u64(); + let mut argv_vec = Vec::with_capacity(argc as usize); + for _ in 0..argc { + let target_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(argv_addr))? + .to_u64(); + let cstr = load_c_string(machine, target_addr)?; + argv_vec.push(cstr); + argv_addr += 8; + } + argv_vec + }; + + let (instance_id_addr, pipes) = { + let spgs_addr = machine.registers()[A5].to_u64(); + let instance_id_addr_addr = spgs_addr; + let instance_id_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(instance_id_addr_addr))? + .to_u64(); + let pipes_addr_addr = spgs_addr.wrapping_add(8); + let mut pipes_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(pipes_addr_addr))? + .to_u64(); + + let mut pipes = vec![]; + if pipes_addr != 0 { + loop { + let pipe = machine + .memory_mut() + .load64(&Mac::REG::from_u64(pipes_addr))? + .to_u64(); + if pipe == 0 { + break; + } + pipes.push(PipeId(pipe)); + pipes_addr += 8; + } + } + (instance_id_addr, pipes) + }; + + // We are fetching the actual cell here for some in-place validation + { + let sc = self.snapshot2_context().lock().expect("lock"); + let (_, full_length) = match sc.data_source().load_data(&data_piece_id, 0, 0) { + Ok(val) => val, + Err(Error::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; + if offset >= full_length { + machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); + return Ok(()); + } + if length > 0 { + let end = offset.checked_add(length).ok_or(Error::MemOutOfBound)?; + if end > full_length { + machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); + return Ok(()); + } + } + } + + // TODO: charge spawn base cycles + self.message_box.lock().expect("lock").push(Message::Spawn( + self.id, + SpawnArgs { + data_piece_id, + offset, + length, + argv, + pipes, + instance_id_addr, + }, + )); + + // At this point, all execution has been finished, and it is expected + // to return Ok(()) denoting success. However we want spawn to yield + // its control back to scheduler, so a runnable VM with a higher ID can + // start its execution first. That's why we actually return a yield error + // here. + Err(Error::External("YIELD".to_string())) + } + + // Join syscall blocks till the specified VM finishes execution, then + // returns with its exit code + fn join(&mut self, machine: &mut Mac) -> Result<(), Error> { + let target_id = machine.registers()[A0].to_u64(); + let exit_code_addr = machine.registers()[A1].to_u64(); + + // TODO: charge cycles + self.message_box.lock().expect("lock").push(Message::Join( + self.id, + JoinArgs { + target_id, + exit_code_addr, + }, + )); + + // Like spawn, join yields control upon success + Err(Error::External("YIELD".to_string())) + } + + // Fetch current instance ID + fn instance_id(&mut self, machine: &mut Mac) -> Result<(), Error> { + // TODO: charge cycles + machine.set_register(A0, Mac::REG::from_u64(self.id)); + Ok(()) + } + + // Create a pair of pipes + fn pipe(&mut self, machine: &mut Mac) -> Result<(), Error> { + let pipe1_addr = machine.registers()[A0].to_u64(); + let pipe2_addr = pipe1_addr.wrapping_add(8); + + // TODO: charge cycles + self.message_box.lock().expect("lock").push(Message::Pipe( + self.id, + PipeArgs { + pipe1_addr, + pipe2_addr, + }, + )); + + Err(Error::External("YIELD".to_string())) + } + + // Write to pipe + fn pipe_write(&mut self, machine: &mut Mac) -> Result<(), Error> { + let buffer_addr = machine.registers()[A0].to_u64(); + let length_addr = machine.registers()[A1].to_u64(); + let length = machine + .memory_mut() + .load64(&Mac::REG::from_u64(length_addr))? + .to_u64(); + let pipe = PipeId(machine.registers()[A2].to_u64()); + + // We can only do basic checks here, when the message is actually processed, + // more complete checks will be performed. + // We will also leave to the actual write operation to test memory permissions. + if !pipe.is_write() { + machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); + return Ok(()); + } + + // TODO: charge cycles + self.message_box + .lock() + .expect("lock") + .push(Message::PipeWrite( + self.id, + PipeIoArgs { + pipe, + length, + buffer_addr, + length_addr, + }, + )); + + // A0 will be updated once the write operation is fulfilled + Err(Error::External("YIELD".to_string())) + } + + // Read from pipe + fn pipe_read(&mut self, machine: &mut Mac) -> Result<(), Error> { + let buffer_addr = machine.registers()[A0].to_u64(); + let length_addr = machine.registers()[A1].to_u64(); + let length = machine + .memory_mut() + .load64(&Mac::REG::from_u64(length_addr))? + .to_u64(); + let pipe = PipeId(machine.registers()[A2].to_u64()); + + // We can only do basic checks here, when the message is actually processed, + // more complete checks will be performed. + // We will also leave to the actual write operation to test memory permissions. + if !pipe.is_read() { + machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); + return Ok(()); + } + + // TODO: charge cycles + self.message_box + .lock() + .expect("lock") + .push(Message::PipeRead( + self.id, + PipeIoArgs { + pipe, + length, + buffer_addr, + length_addr, + }, + )); + + // A0 will be updated once the read operation is fulfilled + Err(Error::External("YIELD".to_string())) + } + fn inherited_file_descriptors( + &mut self, + machine: &mut Mac, + ) -> Result<(), Error> { + let buffer_addr = machine.registers()[A0].to_u64(); + let length_addr = machine.registers()[A1].to_u64(); + self.message_box + .lock() + .expect("lock") + .push(Message::InheritedFileDescriptor( + self.id, + PipeIoArgs { + pipe: PipeId(0), + length: 0, + buffer_addr, + length_addr, + }, + )); + Err(Error::External("YIELD".to_string())) + } +} + +impl< + Mac: SupportMachine, + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, + > Syscalls for MachineContext
+{ + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + let code = machine.registers()[A7].to_u64(); + match code { + 2042 => self.current_cycles(machine), + 2091 => self.load_cell_data_as_code(machine), + 2092 => self.load_cell_data(machine), + 2177 => self.debug(machine), + // The syscall numbers here are picked intentionally to be different + // than currently assigned syscall numbers for spawn calls + 2601 => self.spawn(machine), + 2602 => self.join(machine), + 2603 => self.instance_id(machine), + 2604 => self.pipe(machine), + 2605 => self.pipe_write(machine), + 2606 => self.pipe_read(machine), + 2607 => self.inherited_file_descriptors(machine), + _ => return Ok(false), + }?; + Ok(true) + } +} + +// Below are all simple utilities copied over from ckb-script package to +// ease the implementation. + +/// How many bytes can transfer when VM costs one cycle. +// 0.25 cycles per byte +const BYTES_PER_CYCLE: u64 = 4; + +/// Calculates how many cycles spent to load the specified number of bytes. +pub(crate) fn transferred_byte_cycles(bytes: u64) -> u64 { + // Compiler will optimize the divisin here to shifts. + (bytes + BYTES_PER_CYCLE - 1) / BYTES_PER_CYCLE +} + +pub(crate) const SUCCESS: u8 = 0; +pub(crate) const INDEX_OUT_OF_BOUND: u8 = 1; +pub(crate) const SLICE_OUT_OF_BOUND: u8 = 3; +pub(crate) const JOIN_FAILURE: u8 = 5; +pub(crate) const INVALID_PIPE: u8 = 6; +pub(crate) const OTHER_END_CLOSED: u8 = 7; + +fn load_c_string(machine: &mut Mac, addr: u64) -> Result { + let mut buffer = Vec::new(); + let mut addr = addr; + + loop { + let byte = machine + .memory_mut() + .load8(&Mac::REG::from_u64(addr))? + .to_u8(); + if byte == 0 { + break; + } + buffer.push(byte); + addr += 1; + } + + Ok(Bytes::from(buffer)) +} diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs new file mode 100644 index 0000000000..831835dc06 --- /dev/null +++ b/script/src/v2_types.rs @@ -0,0 +1,275 @@ +// Core data structures here + +use crate::ScriptGroup; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; +use ckb_types::core::{cell::ResolvedTransaction, Cycle}; +use ckb_vm::{ + bytes::Bytes, + machine::Pause, + snapshot2::{DataSource, Snapshot2}, + Error, RISCV_GENERAL_REGISTER_NUMBER, +}; +use std::mem::size_of; +use std::sync::Arc; + +pub type VmId = u64; + +pub const FIRST_VM_ID: VmId = 0; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct PipeId(pub(crate) u64); + +pub const FIRST_PIPE_SLOT: u64 = 2; + +impl PipeId { + pub fn create(slot: u64) -> (PipeId, PipeId, u64) { + (PipeId(slot), PipeId(slot + 1), slot + 2) + } + + pub fn other_pipe(&self) -> PipeId { + PipeId(self.0 ^ 0x1) + } + + pub fn is_read(&self) -> bool { + self.0 % 2 == 0 + } + + pub fn is_write(&self) -> bool { + self.0 % 2 == 1 + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum VmState { + Runnable, + Terminated, + Join { + target_vm_id: VmId, + exit_code_addr: u64, + }, + WaitForWrite { + pipe: PipeId, + consumed: u64, + length: u64, + buffer_addr: u64, + length_addr: u64, + }, + WaitForRead { + pipe: PipeId, + length: u64, + buffer_addr: u64, + length_addr: u64, + }, +} + +#[derive(Clone, Debug)] +pub struct SpawnArgs { + pub data_piece_id: DataPieceId, + pub offset: u64, + pub length: u64, + pub argv: Vec, + pub pipes: Vec, + pub instance_id_addr: u64, +} + +#[derive(Clone, Debug)] +pub struct JoinArgs { + pub target_id: VmId, + pub exit_code_addr: u64, +} + +#[derive(Clone, Debug)] +pub struct PipeArgs { + pub pipe1_addr: u64, + pub pipe2_addr: u64, +} + +#[derive(Clone, Debug)] +pub struct PipeIoArgs { + pub pipe: PipeId, + pub length: u64, + pub buffer_addr: u64, + pub length_addr: u64, +} + +#[derive(Clone, Debug)] +pub enum Message { + Spawn(VmId, SpawnArgs), + Join(VmId, JoinArgs), + Pipe(VmId, PipeArgs), + PipeRead(VmId, PipeIoArgs), + PipeWrite(VmId, PipeIoArgs), + InheritedFileDescriptor(VmId, PipeIoArgs), +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum DataPieceId { + Program, + Input(u32), + Output(u32), + CellDep(u32), + GroupInput(u32), + GroupOutput(u32), +} + +impl TryFrom<(u64, u64)> for DataPieceId { + type Error = String; + + fn try_from(value: (u64, u64)) -> Result { + let (source, index) = value; + let index: u32 = + u32::try_from(index).map_err(|e| format!("Error casting index to u32: {}", e))?; + match source { + 1 => Ok(DataPieceId::Input(index)), + 2 => Ok(DataPieceId::Output(index)), + 3 => Ok(DataPieceId::CellDep(index)), + 0x0100000000000001 => Ok(DataPieceId::GroupInput(index)), + 0x0100000000000002 => Ok(DataPieceId::GroupOutput(index)), + _ => Err(format!("Invalid source value: {:#x}", source)), + } + } +} + +/// Full state representing all VM instances from verifying a CKB script. +/// It should be serializable to binary formats, while also be able to +/// fully recover the running environment with the full transaction environment. +#[derive(Clone, Debug)] +pub struct FullSuspendedState { + pub total_cycles: Cycle, + pub next_vm_id: VmId, + pub next_pipe_slot: u64, + pub vms: Vec<(VmId, VmState, Snapshot2)>, + pub pipes: Vec<(PipeId, VmId)>, + pub inherited_fd: Vec<(VmId, Vec)>, + pub terminated_vms: Vec<(VmId, i8)>, +} + +impl FullSuspendedState { + pub fn size(&self) -> u64 { + (size_of::() + + size_of::() + + size_of::() + + self.vms.iter().fold(0, |mut acc, (_, _, snapshot)| { + acc += size_of::() + size_of::(); + acc += snapshot.pages_from_source.len() + * (size_of::() + + size_of::() + + size_of::() + + size_of::() + + size_of::()); + for dirty_page in &snapshot.dirty_pages { + acc += size_of::() + size_of::() + dirty_page.2.len(); + } + acc += size_of::() + + RISCV_GENERAL_REGISTER_NUMBER * size_of::() + + size_of::() + + size_of::() + + size_of::(); + acc + }) + + (self.pipes.len() * (size_of::() + size_of::()))) as u64 + + (self.inherited_fd.len() * (size_of::())) as u64 + + (self.terminated_vms.len() * (size_of::() + size_of::())) as u64 + } +} + +/// Context data for current running transaction & script +#[derive(Clone)] +pub struct TxData
{ + pub rtx: Arc, + pub data_loader: DL, + // Ideally one might not want to keep program here, since program is totally + // deducible from rtx + data_loader, however, for a demo here, program + // does help us save some extra coding. + pub program: Bytes, + pub script_group: Arc, +} + +impl + DataSource for TxData
+{ + fn load_data(&self, id: &DataPieceId, offset: u64, length: u64) -> Result<(Bytes, u64), Error> { + match id { + DataPieceId::Program => { + // This is just a shortcut so we don't have to copy over the logic in extract_script, + // ideally you can also only define the rest 5, then figure out a way to convert + // script group to the actual cell dep index. + Ok(self.program.clone()) + } + DataPieceId::Input(i) => { + let cell = self + .rtx + .resolved_inputs + .get(*i as usize) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.data_loader.load_cell_data(cell).ok_or_else(|| { + Error::Unexpected(format!("Loading input cell #{}'s data failed!", i)) + }) + } + DataPieceId::Output(i) => self + .rtx + .transaction + .outputs_data() + .get(*i as usize) + .map(|data| data.raw_data()) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())), + DataPieceId::CellDep(i) => { + let cell = self + .rtx + .resolved_cell_deps + .get(*i as usize) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.data_loader.load_cell_data(cell).ok_or_else(|| { + Error::Unexpected(format!("Loading dep cell #{}'s data failed!", i)) + }) + } + DataPieceId::GroupInput(i) => { + let gi = *self + .script_group + .input_indices + .get(*i as usize) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + let cell = self + .rtx + .resolved_inputs + .get(gi) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.data_loader.load_cell_data(cell).ok_or_else(|| { + Error::Unexpected(format!("Loading input cell #{}'s data failed!", gi)) + }) + } + DataPieceId::GroupOutput(i) => { + let gi = *self + .script_group + .output_indices + .get(*i as usize) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.rtx + .transaction + .outputs_data() + .get(gi) + .map(|data| data.raw_data()) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())) + } + } + .map(|data| { + let offset = std::cmp::min(offset as usize, data.len()); + let full_length = data.len() - offset; + let slice_length = if length > 0 { + std::cmp::min(full_length, length as usize) + } else { + full_length + }; + ( + data.slice(offset..offset + slice_length), + full_length as u64, + ) + }) + } +} + +#[derive(Clone)] +pub enum RunMode { + LimitCycles(Cycle), + Pause(Pause), +} From a5192668ab29624400e6ef8c36d3b921f426a1c9 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Mon, 4 Mar 2024 20:23:38 +0800 Subject: [PATCH 002/135] Use scheduler to run tests (#2) --- script/src/lib.rs | 4 +- script/src/v2_scheduler.rs | 43 +- script/src/v2_syscalls.rs | 24 +- script/src/verify.rs | 44 +- .../tests/ckb_latest/features_since_v2023.rs | 1898 ++++++++--------- 5 files changed, 1022 insertions(+), 991 deletions(-) diff --git a/script/src/lib.rs b/script/src/lib.rs index 02c44f3953..91c42e0c16 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 6da642000f..af48f6476a 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>, message_box: Arc>>, snapshot2_context: Arc>>>, + script_version: ScriptVersion, } impl MachineContext
{ - pub fn new(id: VmId, message_box: Arc>>, tx_data: TxData
) -> Self { + pub fn new( + id: VmId, + message_box: Arc>>, + tx_data: TxData
, + script_version: ScriptVersion, + ) -> Self { Self { id, base_cycles: Arc::new(Mutex::new(0)), message_box, snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(tx_data))), + script_version, } } @@ -470,7 +480,13 @@ impl< fn ecall(&mut self, machine: &mut Mac) -> Result { let code = machine.registers()[A7].to_u64(); match code { - 2042 => self.current_cycles(machine), + 2042 => { + if self.script_version >= ScriptVersion::V1 { + self.current_cycles(machine) + } else { + return Ok(false); + } + } 2091 => self.load_cell_data_as_code(machine), 2092 => self.load_cell_data(machine), 2177 => self.debug(machine), diff --git a/script/src/verify.rs b/script/src/verify.rs index 4a7006170f..8f6f0e5cbe 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1,5 +1,7 @@ #[cfg(test)] use crate::syscalls::Pause; +use crate::v2_scheduler::Scheduler; +use crate::v2_types::{RunMode, TxData}; use crate::{ cost_model::transferred_byte_cycles, error::{ScriptError, TransactionScriptError}, @@ -1092,33 +1094,47 @@ 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 85b9b08ad1..ca914dfd84 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); +// } From 10724bab9ce691e731815b2edb238844a9097215 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 5 Mar 2024 13:54:01 +0800 Subject: [PATCH 003/135] Add place args to spawn --- script/src/v2_syscalls.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index 405754d231..4cf5a890b7 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -11,7 +11,7 @@ use ckb_vm::{ bytes::Bytes, machine::SupportMachine, memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, - registers::{A0, A1, A2, A3, A4, A5, A7}, + registers::{A0, A1, A2, A3, A4, A5, A6, A7}, snapshot2::{DataSource, Snapshot2Context}, syscalls::Syscalls, Error, Register, @@ -220,6 +220,7 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { let index = machine.registers()[A0].to_u64(); let source = machine.registers()[A1].to_u64(); + let place = machine.registers()[A2].to_u64(); // TODO: support reading data from witness let data_piece_id = match DataPieceId::try_from((source, index)) { Ok(id) => id, @@ -235,13 +236,13 @@ impl> 32; let length = bounds as u32 as u64; let argv = { - let argc = machine.registers()[A3].to_u64(); - let mut argv_addr = machine.registers()[A4].to_u64(); + let argc = machine.registers()[A4].to_u64(); + let mut argv_addr = machine.registers()[A5].to_u64(); let mut argv_vec = Vec::with_capacity(argc as usize); for _ in 0..argc { let target_addr = machine @@ -256,7 +257,7 @@ impl Date: Tue, 5 Mar 2024 13:56:05 +0800 Subject: [PATCH 004/135] Add a todo for ckb_close --- script/src/v2_syscalls.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index 4cf5a890b7..7c5b5e6229 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -467,6 +467,11 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { + // TODO + unimplemented!() + } } impl< @@ -500,6 +505,7 @@ impl< 2605 => self.pipe_write(machine), 2606 => self.pipe_read(machine), 2607 => self.inherited_file_descriptors(machine), + 2608 => self.close(machine), _ => return Ok(false), }?; Ok(true) From 3584a7ccdf9a3b73388c7577ca98f0194912d1a1 Mon Sep 17 00:00:00 2001 From: xjd Date: Tue, 5 Mar 2024 13:58:36 +0800 Subject: [PATCH 005/135] Remove all old spawn test cases (#3) Update ckb-c-stdlib with new spawn syscalls. Update db feature --- script/Cargo.toml | 4 +- script/testdata/Makefile | 68 ++----------- script/testdata/README.md | 2 +- script/testdata/add1.lib | Bin 4832 -> 5416 bytes script/testdata/cadd_hint_lock | Bin 464 -> 960 bytes script/testdata/cpop_lock | Bin 4736 -> 33576 bytes script/testdata/current_cycles | Bin 3696 -> 32448 bytes script/testdata/current_cycles_with_snapshot | Bin 3720 -> 32496 bytes script/testdata/debugger | Bin 3784 -> 32552 bytes script/testdata/div2.lib | Bin 4832 -> 5416 bytes script/testdata/exec_callee | Bin 3688 -> 32440 bytes script/testdata/exec_caller_big_offset_length | Bin 3776 -> 32576 bytes script/testdata/exec_caller_from_cell_data | Bin 3768 -> 32552 bytes script/testdata/exec_caller_from_witness | Bin 3768 -> 32552 bytes script/testdata/exec_configurable_callee | Bin 9856 -> 41472 bytes script/testdata/exec_configurable_caller | Bin 7936 -> 39616 bytes script/testdata/get_memory_limit | Bin 3976 -> 0 bytes script/testdata/get_memory_limit.c | 8 -- script/testdata/infinite_loop | Bin 3624 -> 32384 bytes script/testdata/is_even.lib | Bin 4832 -> 5416 bytes script/testdata/jalr_zero | Bin 464 -> 968 bytes script/testdata/load_arithmetic | Bin 7248 -> 38752 bytes script/testdata/load_code_to_stack_then_reuse | Bin 6880 -> 37464 bytes script/testdata/load_is_even_into_global | Bin 6840 -> 38400 bytes script/testdata/load_is_even_with_snapshot | Bin 6952 -> 38456 bytes script/testdata/mop_adc_lock | Bin 768 -> 1328 bytes script/testdata/mul2.lib | Bin 4832 -> 5416 bytes script/testdata/set_content | Bin 4072 -> 0 bytes script/testdata/set_content.c | 12 --- script/testdata/spawn_big_content_length | Bin 4000 -> 0 bytes script/testdata/spawn_big_content_length.c | 19 ---- script/testdata/spawn_big_memory_size | Bin 3984 -> 0 bytes script/testdata/spawn_big_memory_size.c | 18 ---- script/testdata/spawn_callee_current_cycles | Bin 4760 -> 0 bytes script/testdata/spawn_callee_current_cycles.c | 15 --- script/testdata/spawn_callee_exec_callee | Bin 3944 -> 0 bytes script/testdata/spawn_callee_exec_callee.c | 1 - script/testdata/spawn_callee_exec_caller | Bin 3968 -> 0 bytes script/testdata/spawn_callee_exec_caller.c | 6 -- script/testdata/spawn_callee_get_memory_limit | Bin 3968 -> 0 bytes .../testdata/spawn_callee_get_memory_limit.c | 3 - script/testdata/spawn_callee_out_of_cycles | Bin 4808 -> 0 bytes script/testdata/spawn_callee_out_of_cycles.c | 8 -- script/testdata/spawn_callee_set_content | Bin 4776 -> 0 bytes script/testdata/spawn_callee_set_content.c | 18 ---- script/testdata/spawn_callee_strcat | Bin 4448 -> 0 bytes script/testdata/spawn_callee_strcat.c | 17 ---- script/testdata/spawn_caller_current_cycles | Bin 7008 -> 0 bytes script/testdata/spawn_caller_current_cycles.c | 41 -------- script/testdata/spawn_caller_exec | Bin 3984 -> 0 bytes script/testdata/spawn_caller_exec.c | 14 --- script/testdata/spawn_caller_get_memory_limit | Bin 4080 -> 0 bytes .../testdata/spawn_caller_get_memory_limit.c | 46 --------- script/testdata/spawn_caller_out_of_cycles | Bin 3984 -> 0 bytes script/testdata/spawn_caller_out_of_cycles.c | 18 ---- .../testdata/spawn_caller_out_of_cycles_wrap | Bin 4000 -> 0 bytes .../spawn_caller_out_of_cycles_wrap.c | 19 ---- script/testdata/spawn_caller_set_content | Bin 4360 -> 0 bytes script/testdata/spawn_caller_set_content.c | 95 ------------------ script/testdata/spawn_caller_strcat | Bin 4576 -> 0 bytes script/testdata/spawn_caller_strcat.c | 31 ------ script/testdata/spawn_caller_strcat_data_hash | Bin 7016 -> 0 bytes .../testdata/spawn_caller_strcat_data_hash.c | 39 ------- script/testdata/spawn_caller_strcat_wrap | Bin 4000 -> 0 bytes script/testdata/spawn_caller_strcat_wrap.c | 19 ---- script/testdata/spawn_current_memory | Bin 4240 -> 0 bytes script/testdata/spawn_current_memory.c | 28 ------ script/testdata/spawn_peak_memory_2m_to_32m | Bin 7008 -> 0 bytes script/testdata/spawn_peak_memory_2m_to_32m.c | 36 ------- script/testdata/spawn_peak_memory_4m_to_32m | Bin 7008 -> 0 bytes script/testdata/spawn_peak_memory_4m_to_32m.c | 36 ------- script/testdata/spawn_peak_memory_512k_to_32m | Bin 7008 -> 0 bytes .../testdata/spawn_peak_memory_512k_to_32m.c | 36 ------- script/testdata/spawn_recursive | Bin 4000 -> 0 bytes script/testdata/spawn_recursive.c | 19 ---- script/testdata/spawn_times | Bin 15288 -> 0 bytes script/testdata/spawn_times.md | 81 --------------- script/testdata/sub1.lib | Bin 4832 -> 5416 bytes script/testdata/vm_version | Bin 3648 -> 32392 bytes script/testdata/vm_version_2 | Bin 11696 -> 32400 bytes script/testdata/vm_version_with_snapshot | Bin 3696 -> 32456 bytes 81 files changed, 11 insertions(+), 746 deletions(-) delete mode 100755 script/testdata/get_memory_limit delete mode 100644 script/testdata/get_memory_limit.c delete mode 100755 script/testdata/set_content delete mode 100644 script/testdata/set_content.c delete mode 100755 script/testdata/spawn_big_content_length delete mode 100644 script/testdata/spawn_big_content_length.c delete mode 100755 script/testdata/spawn_big_memory_size delete mode 100644 script/testdata/spawn_big_memory_size.c delete mode 100755 script/testdata/spawn_callee_current_cycles delete mode 100644 script/testdata/spawn_callee_current_cycles.c delete mode 100755 script/testdata/spawn_callee_exec_callee delete mode 100644 script/testdata/spawn_callee_exec_callee.c delete mode 100755 script/testdata/spawn_callee_exec_caller delete mode 100644 script/testdata/spawn_callee_exec_caller.c delete mode 100755 script/testdata/spawn_callee_get_memory_limit delete mode 100644 script/testdata/spawn_callee_get_memory_limit.c delete mode 100755 script/testdata/spawn_callee_out_of_cycles delete mode 100644 script/testdata/spawn_callee_out_of_cycles.c delete mode 100755 script/testdata/spawn_callee_set_content delete mode 100644 script/testdata/spawn_callee_set_content.c delete mode 100755 script/testdata/spawn_callee_strcat delete mode 100644 script/testdata/spawn_callee_strcat.c delete mode 100755 script/testdata/spawn_caller_current_cycles delete mode 100644 script/testdata/spawn_caller_current_cycles.c delete mode 100755 script/testdata/spawn_caller_exec delete mode 100644 script/testdata/spawn_caller_exec.c delete mode 100755 script/testdata/spawn_caller_get_memory_limit delete mode 100644 script/testdata/spawn_caller_get_memory_limit.c delete mode 100755 script/testdata/spawn_caller_out_of_cycles delete mode 100644 script/testdata/spawn_caller_out_of_cycles.c delete mode 100755 script/testdata/spawn_caller_out_of_cycles_wrap delete mode 100644 script/testdata/spawn_caller_out_of_cycles_wrap.c delete mode 100755 script/testdata/spawn_caller_set_content delete mode 100644 script/testdata/spawn_caller_set_content.c delete mode 100755 script/testdata/spawn_caller_strcat delete mode 100644 script/testdata/spawn_caller_strcat.c delete mode 100755 script/testdata/spawn_caller_strcat_data_hash delete mode 100644 script/testdata/spawn_caller_strcat_data_hash.c delete mode 100755 script/testdata/spawn_caller_strcat_wrap delete mode 100644 script/testdata/spawn_caller_strcat_wrap.c delete mode 100755 script/testdata/spawn_current_memory delete mode 100644 script/testdata/spawn_current_memory.c delete mode 100755 script/testdata/spawn_peak_memory_2m_to_32m delete mode 100644 script/testdata/spawn_peak_memory_2m_to_32m.c delete mode 100755 script/testdata/spawn_peak_memory_4m_to_32m delete mode 100644 script/testdata/spawn_peak_memory_4m_to_32m.c delete mode 100755 script/testdata/spawn_peak_memory_512k_to_32m delete mode 100644 script/testdata/spawn_peak_memory_512k_to_32m.c delete mode 100755 script/testdata/spawn_recursive delete mode 100644 script/testdata/spawn_recursive.c delete mode 100755 script/testdata/spawn_times delete mode 100644 script/testdata/spawn_times.md diff --git a/script/Cargo.toml b/script/Cargo.toml index c595451420..7a32b42357 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -32,8 +32,8 @@ tokio = { version = "1.35.0", features = ["rt-multi-thread"] } [dev-dependencies] proptest = "1.0" -ckb-db = { path = "../db", version = "= 0.114.0-pre" } -ckb-store = { path = "../store", version = "= 0.114.0-pre" } +ckb-db = { path = "../db", version = "= 0.114.0-pre", features = ["portable"] } +ckb-store = { path = "../store", version = "= 0.114.0-pre", features = ["portable"] } ckb-test-chain-utils = { path = "../util/test-chain-utils", version = "= 0.114.0-pre" } tiny-keccak = { version = "2.0", features = ["sha3"] } ckb-crypto = { path = "../util/crypto", version = "= 0.114.0-pre" } diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 70567978d3..59eebd1032 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -9,11 +9,15 @@ LIB_TARGET := riscv64-unknown-linux-gnu LIB_CC := $(LIB_TARGET)-gcc LIB_OBJCOPY := $(LIB_TARGET)-objcopy -# Tip: add `-DDEBUG` to enable the debug outputs COMMON_CFLAGS := -O3 \ -I deps/ckb-c-stdlib \ -I deps/ckb-c-stdlib/molecule \ - -Wall -Werror -g + -Wall -Werror +# enable log +COMMON_CFLAGS += -DCKB_C_STDLIB_PRINTF -DCKB_C_STDLIB_PRINTF_BUFFER_SIZE=1024 +# enable debug +# COMMON_CFLAGS += -g + BIN_CFLAGS := $(COMMON_CFLAGS) LIB_CFLAGS := -shared -fPIC -nostdlib -nostartfiles -fvisibility=hidden $(COMMON_CFLAGS) @@ -21,8 +25,6 @@ COMMON_LDFLAGS := -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-secti BIN_LDFLAGS := $(COMMON_LDFLAGS) LIB_LDFLAGS := $(COMMON_LDFLAGS) -OBJCOPY_FLAGS := --strip-debug --strip-all - # nervos/ckb-riscv-gnu-toolchain:bionic-20210804 BIN_BUILDER_DOCKER := nervos/ckb-riscv-gnu-toolchain@sha256:cfeb97864cf2039a0900bfa83c3f112a780b2281bded395604b8a8a693c95e08 # nervos/ckb-riscv-gnu-toolchain:gnu-bionic-20210727 @@ -50,32 +52,8 @@ ALL_BINS := jalr_zero \ load_is_even_into_global \ load_is_even_with_snapshot \ load_arithmetic \ - debugger \ - get_memory_limit \ - set_content \ - spawn_big_content_length \ - spawn_big_memory_size \ - spawn_callee_exec_callee \ - spawn_callee_exec_caller \ - spawn_callee_get_memory_limit \ - spawn_callee_out_of_cycles \ - spawn_callee_set_content \ - spawn_callee_strcat \ - spawn_caller_exec \ - spawn_caller_get_memory_limit \ - spawn_caller_out_of_cycles \ - spawn_caller_out_of_cycles_wrap \ - spawn_caller_set_content \ - spawn_caller_strcat_wrap \ - spawn_caller_strcat \ - spawn_caller_strcat_data_hash \ - spawn_recursive \ - spawn_current_memory \ - spawn_caller_current_cycles \ - spawn_callee_current_cycles \ - spawn_peak_memory_512k_to_32m \ - spawn_peak_memory_2m_to_32m \ - spawn_peak_memory_4m_to_32m + debugger + ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -99,24 +77,20 @@ clean: clean-bins clean-libs %: %.c $(BIN_CC) $(BIN_CFLAGS) $(BIN_LDFLAGS) -o $@ $< - $(BIN_OBJCOPY) $(OBJCOPY_FLAGS) $@ %.lib: %.c $(LIB_CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) -o $@ $< - $(LIB_OBJCOPY) $(OBJCOPY_FLAGS) $@ %: %.S $(BIN_AS) -o $@.o $< $(BIN_LD) -o $@ $@.o @rm $@.o - $(BIN_OBJCOPY) $(OBJCOPY_FLAGS) $@ jalr_zero: jalr_zero.S cadd_hint_lock: cadd_hint_lock.S $(BIN_AS) -march=rv64imc -o $@.o $< $(BIN_LD) -o $@ $@.o @rm $@.o - $(BIN_OBJCOPY) $(OBJCOPY_FLAGS) $@ cpop_lock: cpop_lock.c mop_adc_lock: mop_adc_lock.S current_cycles: current_cycles.c @@ -140,29 +114,3 @@ sub1.lib: sub1.c mul2.lib: mul2.c div2.lib: div2.c load_arithmetic: load_arithmetic.c - -get_memory_limit: get_memory_limit.c -set_content: set_content.c -spawn_big_content_length: spawn_big_content_length.c -spawn_big_memory_size: spawn_big_memory_size.c -spawn_callee_current_cycles: spawn_callee_current_cycles.c -spawn_callee_exec_callee: spawn_callee_exec_callee.c -spawn_callee_exec_caller: spawn_callee_exec_caller.c -spawn_callee_get_memory_limit: spawn_callee_get_memory_limit.c -spawn_callee_out_of_cycles: spawn_callee_out_of_cycles.c -spawn_callee_set_content: spawn_callee_out_of_cycles.c -spawn_callee_strcat: spawn_callee_strcat.c -spawn_caller_current_cycles: spawn_caller_current_cycles.c -spawn_caller_exec: spawn_caller_exec.c -spawn_caller_get_memory_limit: spawn_caller_get_memory_limit.c -spawn_caller_out_of_cycles: spawn_caller_out_of_cycles.c -spawn_caller_out_of_cycles_wrap: spawn_caller_out_of_cycles_wrap.c -spawn_caller_set_content: spawn_caller_set_content.c -spawn_caller_strcat_wrap: spawn_caller_strcat_wrap.c -spawn_caller_strcat: spawn_caller_strcat.c -spawn_caller_strcat_data_hash: spawn_caller_strcat_data_hash.c -spawn_peak_memory_512k_to_32m: spawn_peak_memory_512k_to_32m.c -spawn_peak_memory_2m_to_32m: spawn_peak_memory_2m_to_32m.c -spawn_peak_memory_4m_to_32m: spawn_peak_memory_4m_to_32m.c -spawn_recursive: spawn_recursive.c -spawn_current_memory: spawn_current_memory.c diff --git a/script/testdata/README.md b/script/testdata/README.md index ce35495eb8..d4964cb16d 100644 --- a/script/testdata/README.md +++ b/script/testdata/README.md @@ -4,7 +4,7 @@ - Create a directory named `deps`. - - Clone https://github.com/nervosnetwork/ckb-c-stdlib into `deps`. + - Clone https://github.com/XuJiandong/ckb-c-stdlib.git with branch `syscall-spawn` into `deps`. - Build all scripts with `docker`. diff --git a/script/testdata/add1.lib b/script/testdata/add1.lib index 1c916b0a73677b35305d4448319eaeb329b1f614..e6cd7e9c06e71f1e56d1eb1b6eed0e0603aad13c 100755 GIT binary patch delta 523 zcmaE$x>0TyuLP2!lV1W! s*~yy1_Kd2NGl8V`$K;zwalDX5`NlRbsy0ncO?YXATM diff --git a/script/testdata/cadd_hint_lock b/script/testdata/cadd_hint_lock index 1f46b6b2eea23c5d89c0354c18c73e0ada82a83c..0a365e08a4519a5ca060a0fbfcfc091d9b01f634 100755 GIT binary patch literal 960 zcmb_a%}T>S5T2waMDP&tQt>4AElbT&I%n}yum!+bN}eDgyl&%yP%X&9iM3Ev>1MQH(iO8BO9M9zm(%=%!1RjMq~ z{3(Pddlr;a2(BddUyb0+`LuEjJ9}udG#|{t*hbgN<|pm+Xm-fP!VJ*Jq8i)4S!&-^ zNdsu<6;f>F!q-pHl>4dFR>>PsxK+MQyxw1|?Bd)PO@C0+=d6ams^M>H`U7M4qiGzC z*le0kc#^e{345K}4(kRNmwm=C?uH=?`n}SR^PJ^8$~f{>Su%`x1T2{h0lfTa%%d2Q zXA&Qj$CCvIuRMZZQ)g5nKA1^PvIG0^~+sk}nCt@jktchWmlu!b?t0f+b|;X3gYF5!df?v{*n^!b}ei@y4^X{lo^q1XQc2C+-b delta 69 zcmX@Wet~&{hWG^r2w((K4h$9yj6jlwfq9~R)?{&}bVlyUjZF5F8<^QAA7`?i?7}R< NxdN&|dGbRhc>vIZ4YmLP diff --git a/script/testdata/cpop_lock b/script/testdata/cpop_lock index cce506539fa59a47ba87ba26d6bb12c1aa606901..ca9ac0deb75ee2764fd0ee6ae2ff54ac67df51ff 100755 GIT binary patch literal 33576 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 NVe&!_@yQAe8~_WIB542s diff --git a/script/testdata/current_cycles b/script/testdata/current_cycles index c524f6d090c8578b96e0f20e3ce0362fec7eed3a..8880779257b57bdfa9b0c69d55c01dc042d4efa8 100755 GIT binary patch literal 32448 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 L%-sC7u>Ai6%$h9p delta 123 zcmX@`m+^zl1P$>G+zepA2qYaCEEt%8BsT-sMtgql$?+BOlOHiVGjdOEthArpP{%U) zNTto>hDw&nELAp)>XRL->=}(GHv&n^$p?X?!(_&4dq&sEjzH3Ha$~jqms=T diff --git a/script/testdata/current_cycles_with_snapshot b/script/testdata/current_cycles_with_snapshot index 62e6752e6643d97c7f6d65ca8947717b4c31099b..e3c1e2605596ae6102943744b0c748b63c745455 100755 GIT binary patch literal 32496 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 delta 123 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 S%oz){DP!_N7V*gnH5>poyCm%Z diff --git a/script/testdata/div2.lib b/script/testdata/div2.lib index 1775b76a35367c412c0c0bbc969fab1fe87b5095..d631c7773a2d1a6ba50b0d9e2c6d25dcb23e9be4 100755 GIT binary patch delta 523 zcmaE$x delta 105 zcmZ3X^+0ukhIoPi0~jy@Ne2cC238=+#lX4I{to}-2ZF7P{F5_<>>0TyuLP2!lV1W! s*~yy1_Kd2NGl8V`$K;zwalDX5`NlRbsy0ncO?YXATM diff --git a/script/testdata/exec_callee b/script/testdata/exec_callee index 81c802765d5975fa079df0c5b7181868583e9aa2..776580d800d8fe052b1105b25414099dfcf6824d 100755 GIT binary patch literal 32440 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 NFgdYMc=DQR9soBVBL4sY diff --git a/script/testdata/exec_caller_big_offset_length b/script/testdata/exec_caller_big_offset_length index 1ea87c14ca059181a9cb1e44af017cc8fdd84cd1..659dd922dae57bb49f7ebeae2f56828f8434333e 100755 GIT binary patch literal 32576 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 delta 126 zcmX@`kMV%)1P$>6+zepA2qYaCEEt%8Bo71kMtgDY$pAn7r=5lH$@J_sbkCNtL9PySHNGWkfI O2xlnNqKwIkHSz#)g(Ir~ diff --git a/script/testdata/exec_caller_from_cell_data b/script/testdata/exec_caller_from_cell_data index 64fa89fc7315d4dd94a47c7b6160b26f46818b57..08f075eac57464b3cb7e5acbb4985de97024ce9d 100755 GIT binary patch literal 32552 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 S%;^iYDP!_P7V*gnH5>pJc_eQD diff --git a/script/testdata/exec_caller_from_witness b/script/testdata/exec_caller_from_witness index a22f978254c2b731e401c367c4cad234a03a8ed5..ac4ad0f26e22e98d40741a08565aa86981fc2bd8 100755 GIT binary patch literal 32552 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 delta 131 zcmZ4Sk8y|W1P$>W+zepA2qYaCEEt%8Bo71kMtgql$&D51lOHiVGjdN}S!vHGIQb=z zl$@+tWzVQQITJ|gPhJTmttY<(l8%!#tL+&*CT9Xk-^nY1WZ2}F)%KGYu&^*PPkzWO S%;^iYDP!_P7V*gnH5>pIyCiJ@ diff --git a/script/testdata/exec_configurable_callee b/script/testdata/exec_configurable_callee index c99bb78cad740cf7e59844806c34643b6f0e6fca..69b97ca6d17e7c01f2dc53e7686e3b47bdffb911 100755 GIT binary patch literal 41472 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 delta 2489 zcmZ8jZBSEJ8b0UV+}uDCjC0lSDS-%)4_ze`5Rrlfg086Tpx9Y|h!>5uRz*7?okBit zE`b^ldX%7|v*?U<-DyWRK)cjI!9`syooRP1>MmR020|HkL5o5BfIXKF*V+5yocEmP zobx{CeV>!O=D!f;oSLO-vldK$5VvU{2@tqd0D0}(Vd<$sGtgWQRR3El6_?NAX))qv zJf7|A>FFW3UfURxaambuV40_?3p|y@P=#Ow9E{>J3IQ5l0y+h5l?`m7mAQZS;r{!!tpb4Hjc z9M!#Av!(r7myv9-N8|PzI;P8bZ#UO$k3kJ^IWf8zeFrt0s4otvYG|w3nGOK5q#sqk z1pq^JD%C&XUV8IqpK41cKD9_4A46p{p_>9rM~q8MIdmphK$+9L9N_2S(@ZE`||doh(7oR7T~_MYSBhYBWjk*UKy!^>ho6?d(3>>_suNhlEZ5>cZh>+KBY zw&crkz(}^HGnm}kC})GELF878ygifkbOv%;+T{!d2sXbtknv9ddfDwXKUv3+&mQb> zh>^%N(Z?$QqLh8%C&bb6;|}0kbnXQ9W||Jh&1rYSLdk!~Jc}Hu6T!)2)igWoUBD`7 z|B_Nhp&UZA4D;@H>K)xcw1=IHUsa#JYGy>SPn`S)eRVfr=H0L&`L9zee@`u86b_Qz z?q0y@6hJuXoFbDPgh0tAIo$@pAN}$!muONz{dh5SQA5C0?MZvp&Qv^|Vz%7|lnmu% zlW5^>FyV38+W_nCR5znu}9Fmz{uZreo|-p7iA1SL!PqPczP2;0M%t?8*q+ z`-?C8B940aIXkqIV#^7M=t`T?)3=C!!iz$(7@k+mrHf0f>ccJsE2PiKAZ zQ}z2A4jyus_3HT_A(DEhTAggs77&&DuFGo=xh6dFObUBV1Czp$r<0fJgn*rXo>jLZIaPX%U^+1%&(y zUUF-nyfjnT*EuG9(lSOBh~klGE}aOJx*VN=Y*tu>{pX)t8e{OR8DkawSXef{XP}c=r6;p_-V@9==|(f7tUT@ILUU@acM zWd^p|LnsZb*&`EO@-d83DG{!}m?S<9|D<7uP)!du6bPoH^x#e-Z`7_h1zMfj%g@2T zTbAYaw2+BaWS>C@9(Uv1Lg88Bz(c1nU>p!Q+RY^>iH2T%_aM<$S3e{Sd;7&qw_@DW zk5kx>Q`rB&8s}4S`^zP&a;0#=7V~0-=!qyX?b!S}())@80^Gu#Wn% zqnFE30CHV0;NFP^+}adCZrT92joSg4y$_I?p8~D}pSN~H zEl0!i+!sIyRZr-B@1zS0e8&aZLS+ znMxshf4Wa0Iqhz6YNZd@V0g{4dj!Z%i8gu~xcvc*fv*=uDl7<4#=mNx&$L|d^d)8|< zdjE_r>^B&h_XfIc7Tq>m?#NL7nb3gMc*UC@=9uq553q;y|3fdv&9J+O0?z7SHcCIM uhWF9?*v>(gY5OF$x1#p5YMf+i7S7gadr;rm(EkENM`~RF diff --git a/script/testdata/exec_configurable_caller b/script/testdata/exec_configurable_caller index 911eb8d2745a83154b58a818fb772fda1b101904..80d9137fcd2b29d0338378ba4a86cc4bc14a5ccf 100755 GIT binary patch literal 39616 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 diff --git a/script/testdata/get_memory_limit b/script/testdata/get_memory_limit deleted file mode 100755 index fbf37219f1c2fa43ae2592ce27f636dad411390c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3976 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�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 Y{oMDsxtCqOm@k>&^HX#4*ZlJT4_U4iGynhq delta 123 zcmZqp%eX>jf`)hoHv;mbe+stZO`a8*|FMwvOyusWR^M+ NPFAQb36m46B&+8 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 H#OMFtM-A=+ delta 2395 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 Y_99BTa7mmR&uac?T)t=J_q1>PFC}^Cr~m)} diff --git a/script/testdata/load_is_even_into_global b/script/testdata/load_is_even_into_global index 9fba1493f28ad57c0dc400f164a51076e6f947f6..1c50a9b40f4f1a5fef7c284acc007d5227100ecf 100755 GIT binary patch literal 38400 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 U(~5bZ{IfQw{Iu?h{>111-<)7d(EtDd delta 2381 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 delta 1929 zcmX|CZBSEJ8h+2cxw#4X0QagvL>jn4fT~5p21G=$h0qr5$Dr&FeiW`6Z5e5G2THdX zlFKDf6FxjZ(9-EDGj_+_?&xNvN-ZiKimS7owYx1YyX*ir5Omy4Y#|u6VQ--J&YWl7 zbKg1VdCq&DbIzqd5Wh3Er|ME;Vd+B>?tmO1BvgZ{V|$|VQuK1_QpX|BFEZA136xe@ z#0ZVy?*u=zYw;%Z3H8_y6Sa5@?UpC|t0C|*-bBQv{cWpm6#zp~H`fe5jrw7wJ0xiN+Hvenih@3JnN88_duKUJ4Iu|umEnpGZ@ z2xl3YLZ9B*44BePCUr%6n>w8kRdc3GVzVw4sspa$`zdy&j>5+bDt^M(=-j(>WK&$gmHQ%;giV^7(3ltG+|?nQG*55NPnZHg2{|e)86jx(mEOGwu<%jR)E;__>L@ zQQYH9YU~6zTS;+Ege*eE=Haj9I%~FTQX*JIWpR_Eq)~pSfK%R~da8QgKH@z#VHCbW zSRPy)aC0?#Ag%N@PtdXMs(9ZQ7T=r>i|@{d&vlE_XTzd66BZu?!*$~i{$nfj!;ar1 z9ky2s7N%{)PH|HfadF{?i0EVY_g_pd-S#M>h%gGzS{aQ-CSH3SCVrjt zUhf-XD?QV@PdrY~R9XZJn{f&T-0b;B@ZbK8rQ`i%wu_uJi}4FyKHG)FhuPC(ZgJW& zE%LONH))983FGJtG1%QRE8YuEMRs*S%KN6I{hE^YYwDlDw9>-T4wKtMEdV2+`I;wj5B+eheCN@rV~O)i^r7r= ziGId1E;iEt?)7S}{v>bR!Wf^eA;ybHlM5Nge1!NU7}&Y*W>ZkWG{|0W<>t(Y(SnSL zO#thW9i_yi!V{%3{CL6)Ih!%5B&2RfZv%1?=AYX^h(}cxTM>NQE!AKSPAIc&t5P%?jz} zj=YJP%Woi@kB;;J&f^sw2DAom>DZ1~Tqogk__BmsaY(`fyye7pRE+B++=VYoxEF^` bY{wZ686xrRXh!*kZh69kIMKo24OsnuaAex! diff --git a/script/testdata/mop_adc_lock b/script/testdata/mop_adc_lock index d24fad349c61da23cf73e937cb1fba355d9a2b7d..6593665e1363516bf3953bf82171d4824287502a 100755 GIT binary patch delta 560 zcmZo*+rTwJLwo}>0~oLXNe2cC21X#s#=yGKeg@-YW+qu#W}rv~5TgTT1||lE$qSi; z>sc5+{zsP;01GfO%wa^;DGC%90IFXhi7KuR7H4EwA&4sO0ToAgfjL5bJ&=h2&OoLB z(7EUa`Qs3e!y%rEL!2QuzaTy_B{@DPKRH`3pCK)=J~M|QK0ZAsKPfRMz92s{uOzid z1t=2i;uzu>@8s(4=@%al<{t+fV+$!amuY U#dh)*77@;Cj1XPQlLJ}g0SSE%K>z>% diff --git a/script/testdata/mul2.lib b/script/testdata/mul2.lib index 4ce9d55c693969fb7610419bb4def28392573b60..889d6cf06d4b2e3293d58e932f723db83fbcc8ef 100755 GIT binary patch delta 523 zcmaE$x>0TyuLP2!lV1W! s*~yy1_Kd2NGl8V`$K;zwalDX5`NlRbsy0ncO?YXATM diff --git a/script/testdata/set_content b/script/testdata/set_content deleted file mode 100755 index 63b8d7ef3eb27d0a73e3aaed621130f24d8226cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4072 zcmeHKeP~lx6hH6fy~JW?+oh~?>KYqqwxU_n*7@Bfc4=a9Dq{*2HuL%t+s?+1Bz{6! zUeYwC&M)E;hYY%giMTNYDG|qTrIrdq*!~a)!l+GV3M-_tc6FPsJGbxME-maY{~Gkb zxxaJn`JH=S?!9^M-jA$X>sf{YDlGg4#M`R$nU%muzHE?~8PO`(mYF%WGx#~rz<+L zU@lelO5+>d=lcWkvQQQrt1U&J*etG4OKn=q^Y)d%)Jye@O|nH#9t(PLzycU6xTN8M zw@R5ZSM};{urL9C6l+8VEiNtp#rnpt0{-}NfT+~hs|`sL+D_(=yfczD3*Ws^f_ z!8&Q}^T>#XnBNJj1Q((iSph#&R5miuY;`saMZ<%3t>(5}JzAcwj%3W@=?rKa*O|54 zZM*dLQb&ke&IRJB(G^ox=Rk8btZC3{xGjW9SmG&UbKI8M%wfl7XOEL@<%NKMQ(Z+^ zJk-xdk4{2g>f49WBkHM5T{mO-sr-yZlXBnxyJ$Gzzpm~#cd6qnKrGhmzYKa!5)$ep z=us0qB5Hy|L`|p=Q4=g8YJx#TO#mV)&iTYdK{OVEd#9r@o|$ghd#4+d(U<|`8l8cR zzx>abzprH3+1gm@Q2&$9lJ6gScT9Ct8gF>gnO3dqD(x96f4Xga*XZt%57JFTVqP9w zaq8<+p@wIT!4(l$(lI_IZs#DxT~DuAE_N`*(0eVdQ> z9A{4qf4F&H&px(Iz!?b|B5=|1Y>n6v=JeM%5FP{#d8Th-U7%VSfr+z{A(Ca|Dr5!M zbd`$5VI~ze{B`$1ZA3^04O>jXUapX^KF#b7vGIqu^!PM~ZyC{koTTeIy-r+5!?KUd z)9TUado^b1j!;~CVX5O;u}~a{|MFB`BeFtQL%5IY8Eam*Dk+Tz*Mv(y@4skkw~O0H zxMh9UTPAh-8+Qs-S2QNRe#1+Tpt|J_=+V>P_(>P37YpveC3Oj07_4rd)G^llU&)@= z==2*WUv=LKUbdMS>yKyjSMOK;%Oafioyc4815f@rVjT}mH`&`29qRN3&Tqzj575VS zt9qGsxNpr&OKHO#^Mw1{zlMJE^ zUIYN6x5ex8_=F}f`dr6+VDubt3O)ghu9iJ}J%ZZ>#@79gUPp<+&zelOnU@nxrpcQT*2e+EGa^d za4J_Q5%Ys9djR z@@ajFZ(yV#C%;?C?^g0Dj}Ab6iW@MH`}}nOT~YGwc;m?xnn(LAXyoRPDd)a1<#6<0 z&rkF1Xpk}K{J~N(8j5mnT`PMt?cDnBV1#7grkyQH{;Ju%(_GS}RDoS+W9@@;XfyZb b9diOSk9HG(=Gkc{V!KkmC8v*=bMyZJZq&?U diff --git a/script/testdata/set_content.c b/script/testdata/set_content.c deleted file mode 100644 index b6b80a211b..0000000000 --- a/script/testdata/set_content.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "ckb_syscalls.h" - -int main() { - uint64_t length = 5; - if (ckb_set_content((uint8_t *)"hello", &length) != 0) { - return 1; - } - if (length != 0) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_big_content_length b/script/testdata/spawn_big_content_length deleted file mode 100755 index 0b63b00c4d4c38d4155431010a92ec4130794cfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4000 zcmeHKZ%k8H6uo$R>Qqu-uSK$`F>@Ivn|-`iU|J__{euZv z|4?dC6!T2$vTUg|GtMoGi6J#E8zV?CSxmMM#w8|OrJazB1kB2Cn~a^yd$%hj`{bu3 zoaEf!Irsd|J@4In`+DyO+#6<^q7V@p{f4l&TkbQ-fkduk;Ft+*LJDY?qo)ATVFvov z%W;{Wfn6C(GDszi?1ET!1fecGCcH@TTykIo}i~#u7{({UNdDW zUM8M=+wX$G^Uzct^^)UR{n(?#&QYW7pz%3;YG)=nZ%87ND0>kwt0ocej@vw@m|(u9A+JFQHeo5Uk~zvE!! zKz#%%kAVg(+S3oyeOB65LrJyI0YeN>zhhPrEJri2d>*QxbbPp(vo$2d;7Gk%b+cYM zQI;}>#!N!b7*aQGHmRAL_1@QutpR2YPOzBRWi~Idu7{FHZ#;W*hx$LugfJdQRBMpa63%wRVlrwVd|H8I9mOrs$}; zUzmKpYVML%X&ZIdw)eHuCr00^JVmcdEpDs%&C&V|aOx|03VfFc9>ue!k=!^XFSXv{zLRSK?gUu9|6IH~$ zY5&Gx$;F`ymX3O1=Qy)^@LJ1^Mtl8MzT&dVz?!!__W&7NZXqpr+Uq}RLS`ZF4*E!0 zgwBr`n`bl>m-{Q;cPfo`>&%Oe0ske7f#QBRqrGys;$If#bnF4%vhP{^n-S_*L`Cu5 zF7H&PwlE$O?0bX;si>l#n)ZQ7q*ng!d?RCT*0%|B5-X+Od+!SpnpR0j^8fEh-e!gI z_UBd4I37&=#KL!WNtR|{X$F>NU}*-HX5h(Y;Ie#PCTOXvdrk9lbEVzB!Cqyos4#4L zMPsPcSL!Q}6te8tlj*713B{eQF5xJmI53%f)_L^Rs@BTG75f~x;c+A2=7hs>Fq81_B(lp9qC&SwYvB5PAA`v^!vdfwvBi5 zkS9Tt%Z2p9`woZw5G2n(nVxsMovlqr+;)8Mcw)i-z4$*F-#M_1&wCgp`2*0=)EhLZhZ3ZJde@Z^DP05Fv|9XCsZvq34N#+j~ -#include - -#include "ckb_syscalls.h" - -int main() { - uint64_t spawn_content_length = 0xffffffff; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = NULL, - .content = NULL, - .content_length = &spawn_content_length, - }; - int success = ckb_spawn(1, 3, 0, 0, NULL, &spgs); - if (success != 5) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_big_memory_size b/script/testdata/spawn_big_memory_size deleted file mode 100755 index 7c0b7f8ebfa74fd857ed90625d5a95042b7e0013..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3984 zcmeHKZERCj7=G{VZOdf3%}yu6Tv>6|1)FspGQO6MdD}q@5F^HsD80KaTZJOD1%yE8 z$GY0V_(-vxF(z{j#2_&yxRhWFF3SRmA;BL66B1L_%9gmKBW?~AobTDaXWn7_#Xqw* zIp=xL`##S(_nvcld(Kh*bsNhtK#hf8fwY?Cm{m^PD3lzMvqC+nuwDpHAi^FFW94#Q zrq9BbSx<84NCee$a>@+AVbUoYMJSfqgr!l$50^?hihixcyC5UgHI@YV%8Vvg-H`{V zQ1u5V)_P74hLV+$Jm^<2C1>rC_J$0bV@KIBHQ&uMwxEr%cSYkLz8&^qmqjpM#JuQ! z#n;HOnst#+DyHdjF$zV@YKud^I?!$(_!Vo`c`>*z=G*i6f6-iP#Ot?@jbM zSZ5<6jeQy!@d)!9VU^(`v>_`LU`i@ShuV1O#!Nh_ZPsbIX3bbt&Jr83irpiiYguL0 zaa?oowIz-Sx0DMdvt!GqdFN0YvNsSmVG@>j4B7u;4m;L6`<$$sy#KnU>ZrJPkc}Uh zf`RO}cjEgs)9bn}CknHLBaPau=hj~(!=b=M&7ieQlVkxBiMGHwFlf_|(xkzFC8b8h zlHw4tq*RDlQY<2t6oZH*1&CPiy(cG&;)w{{?2aeY%uLPR>~2ZN6Go86=nRbns{Tj> z2Fl7$HYBop2k(EHerN9+#mJCx!Q{!HF_veODrALMc2$U_ zQ6?KT{(1d&Lrh4AjT_A2ey*6XJ|5W?VUu^R81QNKT`{45FHP5VW}Uc>4dutHa+)ibJfx|rDyoUU&y}G>J4kB zUhrHApR=18{)ZEW^S5gLVG+)et;kz&Lrs1&Vv`z}Ub45VJ2bg9T)>L^9$ zf%zGjpMm)qc)S_tk@hq;WG2 z?sfab{lM_(a>Z)z{#WbVwR>u|dq^daN+i`Gk7wU5GjUo430fr(CGa5tn0)O%zt=Cc zg30gtzz-%@`}Q4P!Q%pxd$-%aUGRE^gJ9Z$4eC1uzkoUkT75n+iSK(nuH7h}c`}pW z_j}!~`}{6) zjG3nt`hdKC0huUYgJ$&$WRIc|+eHffDOrC?)>9tsfVL@GFrj>Yx^H@9eKX!plty(l zwhA4kJ|mykGV-D3zn-7!t>}HLk$`f*ubPl+- -#include - -#include "ckb_syscalls.h" - -int main() { - spawn_args_t spgs = { - .memory_limit = 9, - .exit_code = NULL, - .content = NULL, - .content_length = NULL, - }; - int success = ckb_spawn(1, 3, 0, 0, NULL, &spgs); - if (success != 6) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_callee_current_cycles b/script/testdata/spawn_callee_current_cycles deleted file mode 100755 index 1c2dd40aa077b6b63675e0cae5d1acad0e851907..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4760 zcmeHLe@t7|9{--(+k1<{6)Zk9FxSxu%5#0NqGN8u7QF2?eQcWNo-=ula;bn?-DugI z39&yYrLd_>mzHHQ@*|sX)0ip2nwj@_l^{!AO!OstyceSatt&>dVkojX5YOS>Go|WZ z{$Wh`Cg1Zp-(TnZJ?Grs+jCwJ9yBuu0VM`zfJl2}ol!P)sih9F8KE2$xXpxB7-2t) zb)T-59n)ZUnoKhhR4%jq*aEPbmy8r4OOlBfhk2`P-bu{-e>=E>#Z-`ee-jaIk<#Cy^?=-swGA~zgZ;ezb$}X53 zt{3Wdjs^X^Q^T`PZmKYD2qcW+(FADrZZ>LI*6F@KzsAR|V?E*6)cQrCZnz$MHxqB- zNxZ~P?EMqZiJHo~-a4jHY4y0aRTcZi14B&k&>Tc#{}>M*UT)2KdTPVzj6h}UTNbBq{B z+z`x}{^LRp+A(}t!-GORlE^w!b;fK+Ihj+{d47HYRio`+RJQEP^YYODxsyTb#V;>2 z=l$Ymql~!fGHQ8ToKz#RQ@u)AZBRYORCIZ9W}k}0l9<@F%kz2s%r!AKp*rag&&NI( zonQE?$bF|0*$gnKz=S>!^H<-HIYIZK(noe83EjCw^M6Zzl^IGUV8;s z^6j?4*aNB5nMjb=GWpTMcGG`?zAKA`?U@s=43Zoq7s;aBadCi-*;7SE?J>u)_@piJ ze(Tl9S-)Zc&A#2HZ~LcjVBl{D9-da5cc*qn3$2l z6nDPa>D#%m*SkIdd9A5MaTg0dwm-gpo!GXD@kUs!=sBclDI3p;-BPxAx`wNpa8@4f zJ+SV$z2pkGGPVw z@^0!_E9Ur7%wKfv!%r##)`+)gN2zy!%_3eW5|8aw(K7k5pvYoh%Pb6VZI7qS$8=S!95Eq}NKhK38E!;IpbzA3dvk!VtTS}4e@r$~%qa{Ch5ucVvu%GH9C3)wGRZ2kJ6@I|>tmVXBCs}V=BJ?vPIaDqY^D{*3+NC0X`^Jo<@6Y=( z9+#0;_Hw>tH?EOzT1IOBy`wZMfYpW%UoX4Kerf76CH_~iLMtno!Zik`i=S$kW7~9N3Ls3yKwTRMu&J1kbt{v zma^&KJ!Op>_m}Lmlg3IKku=ZS?afb@l1{Bvf?5eg2^<&z^o|CHv&m_#1-;YuoD=j- z&(>L;R?yoT_C3*Lwc9}7_)Md7pS7vUdKmOiV1f1}KZgXh4hQJPXYF>|Gh`4_q2B6r zHZ|5ZJ8k68*RLk>4JO}aa#kiZxg-&k=)vWOZ@>qzWt5F25>NHzob;tHmj_Jyn**w4 z(Ezu~@%S*hMD%=4&+X*S;K!6M>#&hrDbRSM{2UnZd6BWFHuQV;`<-m$GP{Xxm~~K*_~#faa2uYT07Md Q+(0%3Q-cK8+w}PF0h|wop8x;= diff --git a/script/testdata/spawn_callee_current_cycles.c b/script/testdata/spawn_callee_current_cycles.c deleted file mode 100644 index c2005c9da4..0000000000 --- a/script/testdata/spawn_callee_current_cycles.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -#include "ckb_syscalls.h" - -int main(int argc, 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 deleted file mode 100755 index 16864323598229a6097dc1f13551ec8b386d35c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3944 zcmeHKZAe>J7=G`~y@|H2)kWs|wWg++O}b#z&364DR&UalVP&jC3!Ay#r0UvqHc3CB zEH^QR*e@g{X&Hmguu{4)3L=q?;Y6guC~QAU2ZdoxR)q;^nVH?%&b`NbPZx##>aT$> zyytn}bDrm(bI&=sIpy|Gx)Q9PkjcsEp}y4oUHC>__P%eyjQ zSgRS3XSTU}M*{KEPzJ1(j1cfgQ4zUS>(cX~n&z(q{`dxfs4NcXLvmK%&HR~vUKTR& z{Yxb{Y(4*_Y1OC_jT$rHFGJ^9VG}U6%)^!^yN7CvO2>n@^4E=yNM zCau!BNzgZMvFf>cL9Sox2yq*@Ks+_QaZYfKwnf8Xn_kx?5GG+sXOPWxEn-eMb~^i< zYzHp}{M+lw!_tuvHhO#(hEw0&j~>&`ZST1mD@YYg*6LF3yMGr=1pNKl5o?b&&H}_@ zZT_oZ)FmOIO@a|U!6Tw4I7IY>1`$2MBBCc4MDzq8qT_pKvn!*q5ZpNzjq%KU$=*5F zoQ%dyp!CrlnDm$Z74r|5th=xymO3)>`19n4N8Wp=xhc==dEA}WZ0T9wH(vI%VdjJB z{Zk*MTgRpRe75||H)le7o;3$IMqo|X%$&5BgAmuB-nc>PUd{%SoIwg4*PO1tUz~ci zdhV)2>zwfIJlS`WJvH(1&Vzji*+U}ENYE64OO9tXQdgKW-rzvI7c}KtzK!*OW>W;R z7i3c;!^Snp3fA{zAz@vf+#h1&_lJx)nxjKzj2|WG zy3Vf?$Jy7NElX>sqwiN+NQwS2Rg^CRh_* z|Ha59`{`ZM-YIU~aDV%(!8kZpsJW)I@V2e5Jb3zt{`;qtJew6BXV6Kq8UEZZl zZ{_?}-1h*(%oWW5lMP@i_RZ-)2SC?XRj| zc0ZW@g~#vZk}b`^(hMxkz|ssX&A^MzK&N`{rD(6Kd&ls4TcykOmaDp|qQbKI4TGi9 zTxqTVrODo~?|Dt_UhLe{;gya7BVfoC@}6UFS9er)RrBhNL9^EKGAB1hk(u3wW%RIfMB^?7PU(S-TR9DTd0Z&&q{M;}0QidEQ< zJAS%v<}Yv9whQklxkh!gZVLvv`a$))HmDwI{%ibHZ^eK-lg{6msvlGJn<-Jn#r>0Q zO8Upmw!o}gzmsAlAu?BSPyK_FtDd@emF{h4%R7b0G-<{SG6x4gMBexRc#rl5$ D|M0X3 diff --git a/script/testdata/spawn_callee_exec_callee.c b/script/testdata/spawn_callee_exec_callee.c deleted file mode 100644 index 76e8197013..0000000000 --- a/script/testdata/spawn_callee_exec_callee.c +++ /dev/null @@ -1 +0,0 @@ -int main() { return 0; } diff --git a/script/testdata/spawn_callee_exec_caller b/script/testdata/spawn_callee_exec_caller deleted file mode 100755 index 0a3f6b60161dcbc2eaf4dcb43d9f098a351d0876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3968 zcmeHKeP~lx6hH6fy~NIH+oh~?+8G;Zw&Ft5bkoicQoEOQGE~MKRB-0?CAOW$)g*p` zGcRcxQ&&YIiDPVZ4U^$M5TryLqn27K48i>&4umZ>nJuhPW$mh)t~)pH-7XdOmwyd< z;N0K2=bqm^_uYHnd-om_-mKP^XX^e=4nLkKW8BTW# zMg;>*NyXSui{RRnjzxy;dfipKcDyocjgH!+?orS;)!FpiRlEGgGG~}u!37hU@s%@z zYp5j_(KYIIoP$J?DCq=7bDU#tltJlT0@nSHrzM(22?Hgoc2d7~m^ZlLJ0qxBC zuFLVlOyOv~F5|iNcgaXFa8WyG>(VAzfOxzma1M;R6eP7NFrp@TMARgQh?>+Oq9$2H z)Fgw5ngm2teD0~KqF6i(H@jnTp2?N$&F-dDEN%iNM`v&}Q2A#(Fi=*0YC}A;Z}7pV zsU7>?zNfh?Pi}h9nbp*FE$>ZNKH5C_?)dhx_p;4tsi1(ZI`Qp^@TSL2p_Nfs+A%pJ zZQ&ryUCgdrA$2ZfLn+Q61rKVD*4`=2JYPF=&Z%{c_%|NzJX-rejT5oaW1 zio#jvD7Goe>IpG%0y9v^ui<^TD%@qm9y*F|K^zV(YZQcXtQg%fDQLOzyQ;u>0_pXXi}+Azbl`q*q-<8 zAu(5$DDQLo3kn*RDoFYNccf3V*n0h|+Gjm?$A9MWJ324(GcZ2`^D{6%1M@TRbTe>V zJr7fKG&Ht3hdUY~D8Oso#Rhy=^|}05AfYTruxG z@LFwKO?&lD4=F@aNTfL8@$BDYAx5*PK(hjp0zL!)v#-_X_xia}N(%%@uyXOTIH{yfhsK d`|Q>{A2BJ9y7Ql%`Uvh&@59b~C)!W){{gp_T<9DTf2%CrvJief_c zUP~zj(U_XnWm&>#G>cmn6GLiT79>b8Sxndu;}Vml(oRT5f@Uyu)3I}T@3LaDU;bLc zNzVPwIrlsFym#;I>%E_`@7rjKLPTivJHnn>j#=c68@ZB!`z&ZXQb4;Fy#$C_8HlZu z`(^qv>|eGdgH*z(T+x@^gOD2!3PKR&OFm|)vf}PSDUaYuwZyw3BgwNCh-_&}m8s~O zMK_8SL*m>{&$-b+yfie6Ql^lbVnvp+i8jhE+M_-0pbv)0Ll5()Ede14V@1ZTE{$?a zb;Gv-A-)-*sAwJ1gv5DGH}xdvjL5>M>x$roG|G$m4P%lurkh1VIjE9mw<5|m`*8Tl z#bIkfX(~7_&Z{!#X7R}4k1UKFvc;j|6llnP;2)pVk!hG8(9X+vtM$$jrkG888clBP6 z<)(9|tm?Gq?%xHI0pY4@)Y7Yp(+I_4&B7(5QzubEl|(wwgc1-m!2p6L6o8-!8W1!= z0fHtFASk@|{Cr+C7D9LWqcJ75)Y5nQ8 zwhtaEu8VVf9(QLH)x9Nysq&|L=RTS_IQ?;^DaGgH&=q~(^@a94YY3J_(8jL0MSdTH zLd?}n*=D|bEgeiUT0U?>(P_S4n10o~c*&u1PWo#*20Q3elb_Tc89YKCP;x_i7?sGN^yg z7#w2qG3)cGgCRP8e^>`kb9~qU_M;?O*QIr0y6THhmuFNn(GSfQ@fKHDbAFTKSs_;# zi2wRjS|hwdmqV~~Z4{d`ph${y!END^uSPG}JL~y<(@gQmRri8cckNcb;%l{0Y1{G2 z17vdFLOSqt*M8PUY<%7w^o6PjogX(fFK8(?_cy%n)LPxnh1Wg9!Ao`{#r||gclmDR zzbwq@JOI2k6H5GB;p>!$8o+zIqDz(8!3Y-E_Xv$p1BxMPJ^-d9W%74rKt^xYw+AzB zY>t*=R_-6)}){=WzEHtS8dzcIh;c`);f627CWvN{8+Gq5@Xt23}V11~lMJ@R>& zpuMi{UF{pqRW8@tF0-k!(zyLit+C2bWvE0_mwoSn<%o436!*6H_;y6GU^4kiZ~Hsu zma5juMh|W{-0-+L6xWB%wn9k$TPvax7l&{Tmc5`*yLHLQYRG+d be^v~eB#(r%-<`xT9+L0Fj_e@V&*%RGEa<-? diff --git a/script/testdata/spawn_callee_get_memory_limit.c b/script/testdata/spawn_callee_get_memory_limit.c deleted file mode 100644 index 574544f877..0000000000 --- a/script/testdata/spawn_callee_get_memory_limit.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "ckb_syscalls.h" - -int main() { return ckb_get_memory_limit(); } diff --git a/script/testdata/spawn_callee_out_of_cycles b/script/testdata/spawn_callee_out_of_cycles deleted file mode 100755 index c0819018bbcf85aeffa87090f1096746ea26b98c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4808 zcmeHLdr%Zd8t>Vs3#jOF!DB^v7%)`a;;{x{kz0^mB1tf@f>&ClvJA`9CCaYos2KJ! zJJ}bOwK<5{_&7+o)6`j(mba8!kwY|creb;48B_7fgWct!qF`kStbxq+Ff$2ob${ir ztKzHb{(WD6-*5Vx?w;xCd0+Xaii0446%P0wP?m#fQ!tK2k+eej6kr43!a5v;K?Hkw zu&rb%6F3jvo@cW?QOKX;o9zMMypVRX2xj#!fUXOS|3Wm)WAPx{&LGRnTV_xu^a%nf z=1~y0m3!F`%+Vh2F}5b)qd-xWwJ%|^cx3DFw!n@)mq;NHOeF=2#zb$3!y*NSB8gc9 zP-it)BDzkx4m>6?nOqc77z$>%i_d<7$&zq?%o^y60cTH#vb?t6BUm=Y^0!t`H_GJv zcM;#-e0`gqgZZlSYuai!wef0WlMCi(y_u&G^KtDv?Z&3ocmQ06ynq-tjEgNuNYrdl zj)F5e(Qu$(%(ma&ptaAoj)Kw>SY#aKs{m1rj{Ppk_v9^0=ri3kj0*zCN2x0tzEZ*~ z^AESe(HepUFHCei54M$Z%JUGq@8dASg(E*uQPFTBD`AweNxSdifM77e*D-x7bbI{n z^KYJh_sG{@Fhc#xn&74p!!Qnj+j^$$A5a|XtNC|I%l;fp} zlrdye0-pW!rAPGxhx-3Ib!zgbV9eyzu^&b*4qpqL?^8{Uj_rPuuft@%gL1A0aQ4T1 zYtbZCsVWBREC)K?|57*D5cXb5-L0~kO8-jyMSh7`7Y#x=a&9~D3cm+frvKW>P(GSu zzHPp1J!w2(S5{2$tow>knNIraPp>RkJr-k6;_UW;gI(|I3iv`6+_s zWSixpb%_6O&VfO@S7?PiT($8N^mc>DYqx{_XXqYh_4d`yq0L>V2s*pVp2qb_=6v+F zIh1qPdiL~D+X>I?Tte9@i#!5HzVKu_+m6s#(3$5H-R*pfrfYKm)@?0I~osPSCm zF8qA$JMbAqmL&||s8p60^|^?`!(w5W78!;kHRKsA zl7IaAL9SKpF(q$KGhOCIQc)*{cHo@W{;our&HgSa)Sr9Ud7YUj96K~pBN`j0&y6*j((ZW-pqc3-NR zh)eA3jpY7Wn8sJhUm64%RlOh)T8W+C##vS9(tE%yhz1|t%&44*LzEFusJE;zE-`0f zmA1>&QJ97(|IwUy?tbboQB+K035;8Ghp&TgUvv{6AZMsId5T#Okn@@pqo4_ZZsZL2 zGBR$2Dl12r{dtnXTeJ3XDrQkEy)Sk$Shb4XU)d}CeirtFXA_ z=a#%Ju=DzA9ohg8B~*El{Q8F1WYy_=Q+I2rN=;QLRUOi5_wPxglrl99Wi+5P=pXA^?G#~km@xD^+2kr+Fenv)@p#Xx~^KkTU}qT#(=Z}8mwNf)~g|phBBQFNYVGS zT1_1!&txW5>-F{3W&8CS>cit#3$^!Bdop!4r(}4>qL7v^SqEdo58OGj3|bT)9z$n@ zJIu6P+ah#ZZTR@0}O+^M9eY=Q&s&+f3PP?ra-{pE3ED&TfSI HeExp`Ub0!L diff --git a/script/testdata/spawn_callee_out_of_cycles.c b/script/testdata/spawn_callee_out_of_cycles.c deleted file mode 100644 index dbaa71d22a..0000000000 --- a/script/testdata/spawn_callee_out_of_cycles.c +++ /dev/null @@ -1,8 +0,0 @@ -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_callee_set_content b/script/testdata/spawn_callee_set_content deleted file mode 100755 index b66210df7b9cf8d5b4359bafbfd1ca080eef14a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4776 zcmeHLe@q+K9sl0>d}kUO!;DHRNaNrPQrfx@(RD)^xo%vzu(XIeZTjfeRuEvXx?j~DGG?tFb`OJQMMUn$2qk$z&<1F1O@7| zVFN-q$ROLlHp;{dsL#+zCXC88z8`x4YB|YC5OO3Pvsl#j%Kp9iQXD~#Y=2uu5@*Ww znTsabL}_OVF7Hwd`_fOkPmKB_MPdq!Pj}mo9%9o)b9&^3jTZtcN9AM+Z1;+;(r!9I z&(Qza20bEW@mVOV&l>7JBDA6!)G(($!zn>&K9Te{8AQ%xc)Sk=4$>a8-R}*d3WDP% zr$#A0ce>y2jcfr3`KG?oh`t3)7j-M^b)Ok!Q|F^)&?w)kdSFZ%ja8<=YeH4BwD}RB zEUCGM8^Ne4w`fur_bsrA6Dd5i@9$PVs{T6M?1OApv+hl!GMpFoU|NZr7! ze6&qXh~@X1av!qz%xnVXC>^j-zr<`Rw`gXp$?VuO847T18jfjWXNwbtVA9ARPl9Iu z6GjcgwE2EpXcL(&j6V{e-MV6Sj5Q&4J7!}hX7Rm<{U6L}Ta{zLK{qSWn(VGF4e*CX z>CoXth{fNV3bnH`?(q*ihb;2P`Cu799{mT zxA^<8HSOv0#{o}q8Vz@m=7Y(5LV0r!FXvIUW7jntDEMQ^ob%P^Erzs* zeygq^z%5gCRL$2_9SsEn2SZ_=giq%g^!b4=SF?0)q-n)Q5cG#(T1-$v#wx zcqdZOmya!P+RfwOymd4e`s^ce64InbEUXD zd-}~0oCD{=S(LR`hsm7%)p*u^OFV~5IinwR-ilrbD2AzpzjW!l-WP|5|8VH(ImIPk zde6$FgOLggIXAjIgpJ<%qv$E*Y-gkP%Jih>ZO5~=$Gwi9fXn~oU$$N;5!41 z?ji&BFNBh;^1p?9K=DWr7T)lc1XFZGfmp(hp3Qt-fQko7Zh!PeWzZfKN@~l6VI~K& zPA3nDbYyBohpK5C(WCKqQG7jj|8uMVA*Qo^)3M?NI~)3ah0%A#o>zIY(6*ds&+|vV zUXu0=@6H7g-G3~UIjc_*^`(U!fzAD+r>q?{{Jt4xQ*6k!sMWoDB}Z|ND_2@}-FFQP zt}CEJn(p1tv_T86z6xj9d^kC7Xj;@#=In3reS*{Ko?Lv;JtCa7mQ&_`zOK74QFfPw zIUUa+p6X*IzT@%LN}&4iy{NR4P3&U4#?;(z<{?J)ftJWNEJV4B-8pN8xg)aOv?|n3 zh(xGb75XOx`?aXL{{=ZfNzbECWjrS%sjaV2^4D*Y5FV6~5dP1RT+K$qM}MmLh5Op< zmrC@OurBK>u)YH8E3m!->nrf{R=_2n_Xt|6tADNC*0kN}eB4=KC@U-9`H;4JyMDXA z3?!Ge?wLCl(>|2ErMZ=F2g;0wOpdap{Z|#u+YgpCxN&F49gn-$-0rrQ%kiMmE~1IMn_p@6G}v2O>_z(flGxTB#sM9^ z)<`bWa6GZsu+o#hMxHR^H3w8{q5&R|U3PvUFP0M|nDUzX!9%keu2QAScXF+YU{xPJ7bT_Ys^(KS|yi%rrl13Zhy jDEGk(+MVw{^%)KlN6c6!wG$i0-FQ=wxFopKXU6{<`dg8f diff --git a/script/testdata/spawn_callee_set_content.c b/script/testdata/spawn_callee_set_content.c deleted file mode 100644 index ed376ba5ce..0000000000 --- a/script/testdata/spawn_callee_set_content.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -#include "ckb_syscalls.h" - -int main(int argc, char *argv[]) { - uint64_t size = (uint64_t)atoi(argv[0]); - uint64_t real = (uint64_t)atoi(argv[1]); - uint8_t data[20] = {}; - int success = ckb_set_content(&data[0], &size); - if (success != 0) { - return 1; - } - if (size != real) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_callee_strcat b/script/testdata/spawn_callee_strcat deleted file mode 100755 index ecc962b30c69442ca3acb1037a40d7f3ebcd4aa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4448 zcmeHLe{2)?6@TaZ;kuH7c$6a(0unHG{+< zO{J{1FBjubnj%v>(;6v_r7)N_ZL)%^ZWGXm8V#|nf6%l=szU6=(FiitNQ?@^dtcuj zB>uO5P0EwL@AKaGy?5XDefPaPKfi7LsZB#spppju3qb!MU4{D~<)wT%fBf5oA}`mRkT!oNQDPie;U65mSv~uX$3AQ}I2m>~~2)HLkJ5 zXRVy(Qq}z#Fg#CBP>V0PPfYqFl~M*Q%}*cx`>la{V|T`H>va?*yfO-=ej>%36NWX8 zCaHqS0F)=!pImA}f5UT9dvz*w^i8ozdKM^~&qmpO_AXqw2yPV-5BSko+w38m$1I() zjC;6V^OjN2@qTXzvkE2}U3yk((Vg~tBNYH4U&R%@L}m2@zHfE!`m7l^|M)sAjh=P= z=2rQ_j(B59<+PZfvRvv!hFsZq*@{+H)@masil$`zcy5H5l0jdap1le7K%b)39cRwg;^@kHCK=CkB7olAg?jt zPkT3g8}?pUw_&IuoIE^vXCz-+E*0wOhU$JPUB=UAeYeH4)PgyXfLKq~vM?09QRb>( zAL=)+iFOw6u4rEiEPFGTfoT|XR7!I7V{H>Ka_kQo@vLuQnD2Wj)-wfXBVP_(9TGlB zaMc5Szj$h9*!3Y>!9BDj1KOOJV1Z7o1@Y4#;C>ci9x-*cXw+)t$O>erl_x4NkFVDS_YMmBzI!*PlKOU2s?(Y{j24Q{w?VPZW0f~vF zHdY7&k7>j>V-Wm3bYI=|(&SThxp4>Qobl}J9qZM+HS^le*T-JhyussX6sv+T?6|*G z=npW)KQX{x6RUK!e+dr){cI2xhJ01Qj3z>(m$-GXTqq4t$w1ZJE7ux=d|a%0u~wX5 ziiy{6(l1Mz$n|qZ%%=OC3FU9%>NAypMi|Dm;hjw>Za(z$I*acTU)pf8%yGYzFZD;Av+iNN7XYU%%Ow~N} zB0haB==aFKSn~c7cCkQ>lJ`n=KbP9hcrEzO0k}Yo(i6T#KZ+_HRK5@YQSh(Jz9Gct z=z96RTwf;RoPuin|2xXN0(ioF<@a^pbI;Cy&EofPl~yaTT7lIHtX5#P0^h9yxh0vr z3camRv(oRVXy3K#dBZbpn_aFgt~zr~O>O-T4Yiw1n@u$!o9ugA9?UfE!=ySpx`ZP@ zSy5z)+0G+BuIt!*sOEs1FrF}hu(#aq?l)?Q(8|luDuWtsnbMPb64jG?oj>@aV(!ixiJ2J$F!Y! diff --git a/script/testdata/spawn_callee_strcat.c b/script/testdata/spawn_callee_strcat.c deleted file mode 100644 index f2f3f56e6c..0000000000 --- a/script/testdata/spawn_callee_strcat.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -#include "ckb_syscalls.h" - -int main(int argc, char *argv[]) { - char content[80]; - for (int i = 0; i < argc; i++) { - strcat(content, argv[i]); - } - uint64_t content_size = (uint64_t)strlen(content); - ckb_set_content((uint8_t *)&content[0], &content_size); - if (content_size != (uint64_t)strlen(content)) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_caller_current_cycles b/script/testdata/spawn_caller_current_cycles deleted file mode 100755 index efa2fcec4dc2521451a7944a9c92c52bcb89966a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7008 zcmeHMeNYqE7C*cBB7&%m6-%^6qEMMOkB=xyFcXj@N-gc{tM+52m9T_QQ6UjsMl@fW zHG$~((t>SlOW{3UwNs{}l0WqQDfyv|!#{cehn$`d9zz z40q=4@7#NS=bp1?@9s_RJ)qxgz%dN?g2Ru%v|@3#Psb?=7PA7=tAn*5K-U1saVo>yu?m-QJUdk$Yg!ycnVTl=$Yr}lbj>EkYmiG~dJTH5JU7ye+ z?n`!!fTB!r+CH9Dd8E_Plt7Ju?!cC+mTUPF&yQ`r^~&|HH@W*0r}M(nr}cUEJh@8> zgs)5>mwp!U@3|2n)f#D7XU}EqnjbxWj8rF5q4*U@7Z1nZ4X+D&U&P2v#wyfQHeILo zlxT!6V1D{?8!>krMEdrE*rFTOJn{rNr}jp9UPYP7VZ-!xJ!Y^QFr(e*k7_<(LANju zM&~J@g<566R*rxzclt${*e0~=--lMg7$giidPV>?`XwOJ4!>vAj`}54pdCL3+PhR~ zR+M&1r1zmQDZ}EZCG-6UUvlzeVk=iq3q)0rzPcISIEU=P)2%nlM3l?-p~Kd+0Kjiw zZjw><37H!UOAp!g$a{7idQ>uz+5A`+D^VttwW1LyP~-Y10W*w@E*mC4$zG7q4I@l<`D8arqy~a>+!53jVt|ljtt2zZfM(7u=GoDK=;=s6JQs*L&nyqG3BMJj zujoFeu-tOG(5>|qkGIhQ@6QoA6%B;#gJtAu^37nw37yJ$@*uWZ>;9a&L1!L(%{Snd zdwz=KQSw7`fUy4%PikfRZ%2YL|H-yLU3@qo3`YX7X!b;3e^h?xc7)LdoM$5%`m^kS z<7(vbLz%<&{Iky9l0d_Fgm8{8^hbIlL3%1%+jr@3HJ$IZ8{0hbLoKd^A~}Wbfo^z2 zW*LkGperI5_D3{Sfi8Iz+mJwI-dc3My1(|?Kd0Wgdv84c?%B~h!zYJ6?Q8EbOpT0g zyP0Dl)xCQ)0yE&dZ?Its!s_6m|6<`ZQXA@gd;A?b==ugD*9GgXSg8A{ zF^!bO!kL;F4;K3L)e)8FM*Ulq)|W${qz&$%*NcTU8kZMB=j(2^?923}HK^#bu3)qk zBi9FA0SJBe;h@I%H;l~6bZMkdVWEHd`UmQR5)ZPY4C{{(7i*-!`g+*i%zAvl+ZV46 zZaVi4%|>^+qi%JgD~Gt~3TIvN9DjGe_sxz6V+m&(+?p5)`=le&*Rqd|f{pBrb8I9J zMe#r1BtMfvOS7&F)RS3Ebic+G`mSa&Kt}^J3q$W#Tn^ATBN}M~1nZNqlLe0y-L~eF z?PP52?ehGJ*zGs=<<*_2dyQ(Z_%rkNFGv{bD$y6^_4sKc$RxQS9!~5__YCR?-yq0d zUZ;}@bHSdwq<|7G7do0k!z&{CqOKA@O=B{N3m7KDBI*%a=$gUoEyyWqDZe}frwwCz*R0{Xb?YcB%<#Cwz7r!p3QA3NTAraGxVb9o?r46uCz^nM%1jML|q+9 zn+TY<7t=HE@A?hNG*Q)w`}a)3`OqiV{59gpdhf@LF`<~jY)Po{^1TJU4%;blr_L*G z!T}l^OKfeRlypF=xC4}^wu%s<+A2hdYO4Sts;xLeR9i8GsI~$^RM9tMVq%`Zk%Di1 z{zegY|B8R>d%45km;|g3w`0(j_*0|peB9E*+Qv{-=iRqEm|RKzdh{=XQxb5Vp+Rs) zg1x@e*=@whs?2Yc;xRnF&oGoTyk?Zo4beL&R?+Ql`^Mm&E?gFi2`I5#AOgcd>WLuT zEp>L&)0!<^cql<1qLv@Jq&<$_Km znO+p??7pX>^yq0Y*~IjW^lH`fqk@m^<9T=8eS&q~Wi364Q~BdthhG_bt*@|$kV^67 z`u2J%Z~A5D3J=I#=xgz;5GdiPz7@*}cQo$o5Gn}A9zmV@+QQIcb)>C8T-0mLAzMhi zwzoW|qNM`gZbE*XNgg;_Fr7iTXrb~WA(*Z>lccG^MlT4S^uWYndy;1aZxSGuGsC-# zSV&_bI_c*xuV_7{4rkJ)ROe~oe1`Sr;42i~bnToHMYH>y3dv&~{4BmdD}_RQX+vV4 zc-a4fT4%ptTBv<}Nx}3&(?Um6{}ekTnfZ8vLTjD@(@UEL9rkf&2EFXP&ZEYAyatJaIYYR~Eym+k$veUx}C%k=THqK{NASB)i0Y8lg>xRy%<6 zShL_XHsL^GN@`lVdi9!&wd+iUM3K3;q_nKOVteI|ox7^4E!N#Nd-jsGXrS3Ln}OL3 z%w}LV1G5?ULuTL}w+B$m{qNt*A%8P3J<9&ij#|Xx84h{@_9 zMQC?pw#;T=HUqO6n9aa!27X@#6x{wakH!rfG8Iphq?ygD&Fb`&l+?AW6sc*dG*t?) zDr5eZUwX2iMb4|sEJO|3F+ielzNorpjk+vtSIV|Z=3-(l1aqmatlYgll@SU}EEKXp zuwX#|pt6)&tkqUiA*ih8y;e|F?<_J|O`tNDZY!=fRhmInwxi6t%~V}&B0*J*8obQ% zEG!gSETAHGR#uvKFoQ4=s!UdEby?wVtC{(O{ksdZ1~Y5({XKt#L-$(@vSm#aCvbo^ znjR`>L;Jo(8rQ3kvMarUJ6~A&5F3CWj{iOI7-x?*r`ht$c>~*I&ORP2Guuj}j762V zkK*j3xbqAC7=s^!_s`>>kYe5g_KP|D#hf9}`z?D7QZVY k$oH-pv|rAvo|~cI?fGt|&BxC7F*w1+U;1Dtl4sig9|w`;asU7T diff --git a/script/testdata/spawn_caller_current_cycles.c b/script/testdata/spawn_caller_current_cycles.c deleted file mode 100644 index f508cd3966..0000000000 --- a/script/testdata/spawn_caller_current_cycles.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include - -#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[8]; - itoa(cycles, buffer, 10); - const char *argv[] = { &buffer[0] }; - int8_t spawn_exit_code = 255; - uint8_t spawn_content[80] = {}; - uint64_t spawn_content_length = 80; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - int success = ckb_spawn(1, 3, 0, 1, argv, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 0) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_caller_exec b/script/testdata/spawn_caller_exec deleted file mode 100755 index 429e98b60b9f98a540a2cb3cbde09295aefcf5b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3984 zcmeHKe@Giw9DjGYOX}*XE;84(w$XHElP(yOt-mGeF0o~_WvpWsHgjH5b#1yfN$n3P zyGx8&Y_*k?#4!feurj)>6pEyDj83d5j6(NE>7cNsCab~(Ez{|?I`@6vy(|{?SN|IL zh41@(zwdoM@7=xka(V9~?oAs_QHU6genU8`QR=Kp!<}3?z-?Bv8L6OLiJk#OM;NFp zR@xPM2KHtmIUplpWS6vMw;Fw_BL4T|?IElWqPz4w5!RD$You36|^RD4S%X>>Z)V$L|Kb&}AN) z%A;OldA}Hep2Ne{E-lM$t^dj|#!3*1NPNFGD9vcwsXubMBo6v~wg_HN%YJTHJtRj% z`bi{~fwMHX5mC0ush{V*PE;3^CIiFLj5^&tiF=m5=b-1HJqBZrfd}pSvyZ0x9JI5V zlE>}_MkGl6j#))8{Y}8~i&R1B_)rt)+?9-khV5F-ExUT6ENu>tS%uCqq^;j#)iSs2 z(i>|XL8gT9$5Im;7C7fnQzWF>snsxbn2A}!8DKL^-BRYLqsH0iq+9U&@2D*g2}cL% z$njY;koxvPq*cAJqvJ+2H{arBX7q6)YtsUwZjZie&Bwj*#O#;Q$38V*) zvw+}n1`s^10tAoKfZ%Zo5Il|m!Qs7UX7VD@AiCQbiL%sUN#E_PPeh^yB#+VV9}~;| zjEVzA#pkM`siT8)pC#Tq`qq@{hBUovu05^V(y_iTS@wAM^g9##$KOvkCWV|Fy8O(Q zGr?W+^??mxw5Dx(LD<8fAagCfp+sn3Ne2>)PVgUBowhtEOub-Pxa3efM}0LX`%coQ zMn9-I*msaV#KVjP3}MvcnBOF{g&6%+2J!a;h8)v3(GH~A7)CSaBtv+Tj;VkZ*wnFJ zC=5}lkm0Y}_p8EuB4F5Q3iLDinDxon{vaKDa8nOYbL^%O;ztRxu8Zr$wCyZDTb5Q& zMBcVor4hcc>cU#bd?8=xkNxskUL(9hmxHi(Z4{T&t4c`IflZI;pDwQYO;Au>0QAU$OI>p$wkHX-jW`cz$nE)1KSW_1*o`zzje8l8Uo z>^k?&z$Lqh;(qATU%prIFAH-{?*rb7J1qXS2(>Jtdhy;aZ&RnYF`^arJwgLiud1J# z@k2ukc?One zV0i|XXJB~-o^A$ul=Cq`du{Dj-OEjtF4t==i@Bo0wD}dCsnS?!tUz*;efPdhP4yla z+|%L}S`o!T$mFx0*4Hg9l}9QX+_>OzA>iVa+kNbi2?ve542?1fGI#+HGJ2c6K97%Y zL`I+Mgbx{A%?$@UyxWD0Er(lt4ZO$0pG3w3kdWBP`*_gF(CGCdqwt~I?K%wN#V0fJ zKA)$h@tDtr4<1i#_`etbC*wN?w(-RbqikJp;?6cW;4ZNO$grN!GWQbYzM?=z^JKmT zT2^K0MP>a&g{WMEGWr!tM9=_vUY7p6qCcTPbvD%gs9+?xhI#Qke?xYT*Te%-QvMV8eQvVO+c*cbQ diff --git a/script/testdata/spawn_caller_exec.c b/script/testdata/spawn_caller_exec.c deleted file mode 100644 index 614342713f..0000000000 --- a/script/testdata/spawn_caller_exec.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -#include "ckb_syscalls.h" - -int main() { - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = NULL, - .content = NULL, - .content_length = NULL, - }; - return ckb_spawn(1, 3, 0, 0, NULL, &spgs); -} diff --git a/script/testdata/spawn_caller_get_memory_limit b/script/testdata/spawn_caller_get_memory_limit deleted file mode 100755 index 5b600a24e6819cf3b5473ae3b8dc083a8a8e2506..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4080 zcmeHKe@qis9RJ?+u9b-cq#HV67OHe3uAvmCP9+6)g_#Y=GM8bp$#GO*T4$l^G$FQE z3M-1v)U+@%g^@`rhl^y<^<#R+^$f5gL96;+>ac7CBM6LNZ9s0-HgF?Q(bu5e_gI>&ldg zY0!}7Dv80A-y_9Q!RNT$xi8@mzCHsbi-nNzd-@IqZ4#jUdi@ z9MxN+Kk*<5>*MCSox4rL5ATyddUa5)NZ~dJ!Cb}-EM=X8nAPo=*w7SlL zUK56pIt+T$5Q~T!Vh~Y7Dn!%}jffhe5K%*bh>E{^YAVYg@WRc0e}JXtTl!{yW7r=s zfHX#rIPNO`GvFG|D>zjVh&o1QJ`2C=cr&58;!f_E>4~Yf^sOC?6wlTr-;VE^crVr* z5i&C9lH*?;_wIPq=vn83HQmWMp`HORb1Am2Q0Q4sd%}!P5D%-m%I|8UtIFrjHK|+1 zoK;5#kI+ZQ-mls_xR>6?Z%U&k&PMSf7mV^3uV(SM@lXgIA4cKL{)PI=@d$ zcYVQ$;+Q(_f2-W$zRqha&g3^e((+m{cyCtPBeFvmymbrhHR zD>-)>oqpT&^Y*Krb2TQ4`|+gy!mZNBEW+v9iM(Y$u;d>lRI@-0kh5LVt&VMFToyd{ z0K?RPYKWQ=(F8avKgYDR^qjb#@~k8I(&wajM8=QTNIuE^A4K^zPn&OiS-#SKKmH4g z&+R2yT7jh%SXzOl6t~-)8-d-rZQuhu@t0K zP2J9gNM$_^-qGGE90H0%lgVZ~4!vC7UUr~#x1BURX#~<7wc8KwGZCYim!Me!L4r;M z0Apucr?bP!H-ph>`_KtSTifnE9lYHJ#`gW~&fR=R2Y&>Nd(ctr7T(EYodnIDonRC` zu-k3>v3P!FM&9Y{Xm38~w2@DaCl>PVCGTW%haoaC?-7(FiQn3(f}ggFBnLfGuh5ix zk8)3vuT2Xz>HZqbJe^V>k@qhm6Xk2xLj5w?QqX{YR!V(Bu20DI3Qy@k@f9>pBvH=N}UoWzA|?uM(~C_|EAO++UfQG0Oq6V A*#H0l diff --git a/script/testdata/spawn_caller_get_memory_limit.c b/script/testdata/spawn_caller_get_memory_limit.c deleted file mode 100644 index 6b6ea48662..0000000000 --- a/script/testdata/spawn_caller_get_memory_limit.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -#include "ckb_syscalls.h" - -int main() { - int8_t spawn_exit_code; - uint8_t spawn_content[80] = {}; - uint64_t spawn_content_length = 80; - spawn_args_t spgs = { - .memory_limit = 0, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - uint64_t success = 0; - - spgs.memory_limit = 3; - success = ckb_spawn(1, 3, 0, 0, NULL, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 3) { - return 1; - } - - spgs.memory_limit = 7; - success = ckb_spawn(1, 3, 0, 0, NULL, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 7) { - return 1; - } - - spgs.memory_limit = 8; - success = ckb_spawn(1, 3, 0, 0, NULL, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 8) { - return 1; - } - - return 0; -} diff --git a/script/testdata/spawn_caller_out_of_cycles b/script/testdata/spawn_caller_out_of_cycles deleted file mode 100755 index d4ac5f515c80540fc550255bd270f0e6fcec080e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3984 zcmeHKZ){Ul6hH6vy_U&jo1IRCLATsV~nsyVvrakSxPVlmt}#(kl+V`35h9dWlLPr5jTel&U5$PogKzcd^0=A zxxaJo`Tg#F@7~+jd*2scwXqBX)L8fxNX@3US=GeNd?g?`E35C>=vI#L2U5km~@Ip5ek($VQJBisQDwsijJaBr|>SSNOko^vQVDVW-8mW zkXoeamB-e)PxlAn<)JLVGN$O9J=9v4Vl(V8JHiWH0%MbHjJ-1){ou`@7rQKg(E{d0 z{jz6)7X$t%_8z%b@6z+a>ZXeUf4mGJDwp-@L-M%3gZVx0ge+v?yQfR=74`gQruhR( zG+@kvzXF|Sg{8pQvZJ3q_#|0hRGtc6lgG80(^=B9{JnrZ57^^4?hty&ZajW}tjEDR z>ltP2)5wU1nBNGi1ec%%Sph#&R6ab=A~-jtqG4U5UdJ_RM=CNkks+(pH3a&mRaQO6 zHOdl!M<(!PE+dT;{z z(%;^V9?(v%>%0=nPv;NS>(cJqe-#Y|{Fk)-)=q7l1&GC3{O7@_OF}}M1S5KaM?_C> zi0BCoB6@;FL{Bh?=m|hX$M+r|FNnrMaH}gCl#3^Y@jM zo~(|%F|I3qz*1iBrMR!Hq(&iEAv;+>!=&+<*I6EsUBFn&@tMY3#MgRJ0+&c#x3m`R6C zf8MxL7ZH;|(?(0Mmn$T!kA}8~*!bP6Mtqw6SIrpTPttXrS|_f3W9jjVjCLgYdaYHy zE*96FS?G9FEEWgiKR;B~h^)|s5bj?aBjlacB;~Q-ityrd{oVGXjnbB3uC(t`>x990 z`Ff$|bDf2^t$FSq)U;j)Bi4+Ue>6mFQo$|wSX%;TuGO?m7#Jb{7qahk2IJa^MeeJ? z^L7g({BXi};da$OEW$au4S92J^5hpIHSoZkC40NFU7K0M`K`F`0s5G;nqFo+fFZHv z>UZXA729*ZMI?W7zViF_zo1~%0tHF#|6ufO=GENzqV^g0y^)`I{I1U0>8ZU9M%W+M22=%gUDxmTGggxeAn&ee<^ImijF?xTno4 z9RNnakSpXp2bR~iRqw6Z;UeMP;tOluymFTl*a z9KBy%Kfg*;uR+uLIch}Fg!O_P{V7#{O4U;y?SR%P)?gy{`RTstR`rc|Kgl(!qiw4& z$knIR^IA$h)cn`;Q@s@f(kGq2QB^;x>Q_>tijR*^wka7OH`@%O`d4PODqPY;G{iQe l -#include - -#include "ckb_syscalls.h" - -int main() { - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = NULL, - .content = NULL, - .content_length = NULL, - }; - uint64_t success = ckb_spawn(1, 3, 0, 0, NULL, &spgs); - if (success == 0) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_caller_out_of_cycles_wrap b/script/testdata/spawn_caller_out_of_cycles_wrap deleted file mode 100755 index 1c3a8da92269c0f1016e6692aa099a19706be092..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4000 zcmeHKeN0nV6hH6vy;dd@Sjm_ZN1=vpL>mgskEx`{UMpllvrIQkHv4$3z_d=6h= z9~4#uKT^|5%rc~zG0rSY45@Kh7$ZcJ#bo=#xWr_sv=fq%6tXhhCS&LF-s=j>{_?+t zlbriI=bqoW=e>JxU+?{hd&5Li6v#ruuRy&0QlC)@#Ii+$#Eh^N6xgnYXAt2SgMFK% zxI|CG-n1neawUT7l2~R0poa{KA|vFAK4B?Qd!=}9zL+PYOC|EIODN~nt1)b7$E2=9#Z=~v+6GD_pCD> zE(zZ}TY#^uW}0{&cQ?xF)Y8=DY2gRVL0S$;h7XI2?Iw zcNnWrp!&_)-kH>(g|^mEV(s(D2>Pkt2&({>q#0RWHtn%gRh?SJ)G4P* z6P1ApqtG`2>c(wGHN(_-UN5xxnPSEpj!$h^;H+cK$gU@B!Xzx=G_wE29JlPU4qE9} z7TxaP;%7vXhw?f(R?1>sx+vmRX_ zNrx54@@?rU67svLc(?A)yAP@ZeAK6_Gx&y>T*B&~IN+zl4~Mn*G{=YaXwO9DbzNL1 zrn7#1Z)rj~6@078=()q^S6?W!%;)p@-tf;)#5E!-bj^>u*hFzz1B$38<=fI-bb0im zxnsAmXOdYza-(HVqrG`2S8-KkU`^Yfe*~2+cR-7t_U4b8fJw-?2bYuuaN%}k^PGm_ zvVS4_PNmWAn0v`S?7Lz%P}~n^wAb#J|HC4jj(x~m^*u{|H$p87)BxGrWu3~zcE)YQ zeGf1~4Jd}FSudJIOwxDfTL~{@e49u-wpRSTpLipEf(uh5r+ z7&15POZU|5!Qzfqr*Hx&4oxPPb)48-)mm|^{GgpQJZS{doU+@GA2AT4i5HdJwGDXgl`?jHxnLjO^*QTXI&3`?=oNq*fj496_6q3>yvFt zGH|mk6)Aty(%wZb>5{5I1KL>o*fLuBzPoo>K+co9iJyLUxf8KNs&C2YBj)n_zX7r5 B%Xt6* diff --git a/script/testdata/spawn_caller_out_of_cycles_wrap.c b/script/testdata/spawn_caller_out_of_cycles_wrap.c deleted file mode 100644 index bbb717e58c..0000000000 --- a/script/testdata/spawn_caller_out_of_cycles_wrap.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#include "ckb_syscalls.h" - -int main() { - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - uint64_t success = ckb_spawn(2, 3, 0, 0, NULL, &spgs); - if (success != 0) { - return 1; - } - return spawn_exit_code; -} diff --git a/script/testdata/spawn_caller_set_content b/script/testdata/spawn_caller_set_content deleted file mode 100755 index f610c38817d1b17a1f285d9b2b7a6ebc79fbfd05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4360 zcmeHLeN0nV6hE(hZ6Pu#D+)%Kg*s5;Itr+W+O)E^&iIvOx`8@dN(H7>X$wvhVm~OX zC>m4OvKSMj3)$2xB*xUROeBPeSxmM+j7v5^6ynoBJ_xangC&S?l11CD*LdOr z*t?)jGZ7Tc^Ud`D+~A!QLCTQ{ON?@p_upK`#Zh!fINnVjX`D8}rAv>9qgl1Xa4%bU z+cmnyda27DO!p2$M6XQ{M~6YPB(__mYcXmWw{sYr(yA9|Tb{eV8OFkX?9X>!YmtfG z-1(r@?F^;?_+88cnb$QYt7BfoUU2C!MxKP@l8Gz@E4n$&y8-*ygpw@Ktpi3sJaYEM zXC2yv^oZxaYfK!yG)#JSeW$~oyNiQ3_yH8JL2>^1Xp2!$O2$GMmyqH2GQSd55-xff zvfR!?l{FuPguSrVP!LTs6imn@l~6F*S(Y5*udgp^k9f=Tp*^Y|QI84+6)6mebd5Sj z@6#tsQ zK^?tjP*3=A4(iF2n7ffJa5vgnhBGNvj}Vj;d&~drOlI>i3F(8~WxCQG5$x%JOu`-z z4`oDieFGYE;{eEtHfdxmd%*QhiqXravF>31(CTSjX*bDxkgy4pu*~O>{TF7Raa(Ci zsh~oHYqqs8tKMAMCGejbhtB?Qd;Qho>8%azfw=y-0j;Fp`uLB8KDYChxJ%O@4hjGQ zfih<+C?sJBiNl~k35gIGW@^Es z#-gx4kO^FlI`@DxRaO^NQ{&y(CUB2VbL*QIClj4rlW72u5$fkDQDj%0C?(|57UrJOW{pRIQA-B8-6xdSS`BCoEo8uqB6>$<= zzMoq*E@yOc&&Y37B3En~f5Y10X*H-A-47QO*B@ukvIwVUAM#?p7m;6`xlja5Gua2S zYQ@pbtW$%#2S6v&EWFK(xt;mQAw`wVV-AOF_bPltXI;a6y}EUv)f3M{U`;tDLTz^ko54}YJaXecZ!kgqAru~^ny@^Z7Y zRrzb>svKpGG8;ITVfVh57VREPZmY1HtAWv>%1TAH>J51nIVZCZTS;Xim6=p$tk$Yy zDx#E_I4I%3%z+&NKxr?xJ8TY92`C+wPaL4MohUUqOrW%sA3kC;SuLQfI9}m6Y_i!* zr$KoH8&v0bb`DDHc2Js6Sgn@hq!ThirODy2Rg_dYEaW)y%7uJ`$+wx@%}5!XX%XZK z9{T1LJoe5j3D_d>{4ocbMBJCYiNEK`=CJ`{_%=Nctl;DEYBW>meURQ07o>-UZ3RY= zD=v+1(4&^E=*=pb{U`RV)D!^dyOJK)?x z -#include - -#include "ckb_syscalls.h" - -int main_lt_content_length() { - int8_t spawn_exit_code = -1; - uint8_t spawn_content[10] = {}; - uint64_t spawn_content_length = 10; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - const char *argv[] = {"8", "8"}; - uint64_t success = 0; - - success = ckb_spawn(1, 3, 0, 2, argv, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 0) { - return 1; - } - if (spawn_content_length != 8) { - return 1; - } - return 0; -} - -int main_eq_content_length() { - int8_t spawn_exit_code = -1; - uint8_t spawn_content[10] = {}; - uint64_t spawn_content_length = 10; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - const char *argv[] = {"10", "10"}; - uint64_t success = 0; - - success = ckb_spawn(1, 3, 0, 2, argv, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 0) { - return 1; - } - if (spawn_content_length != 10) { - return 1; - } - return 0; -} - -int main_gt_content_length() { - int8_t spawn_exit_code = -1; - uint8_t spawn_content[10] = {}; - uint64_t spawn_content_length = 10; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - const char *argv[] = {"12", "10"}; - uint64_t success = 0; - - success = ckb_spawn(1, 3, 0, 2, argv, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 0) { - return 1; - } - if (spawn_content_length != 10) { - return 1; - } - return 0; -} - -int main() { - if (main_lt_content_length() != 0) { - return 1; - } - if (main_eq_content_length() != 0) { - return 1; - } - if (main_gt_content_length() != 0) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_caller_strcat b/script/testdata/spawn_caller_strcat deleted file mode 100755 index 1e1ed6edb3373f29e9c85a3bd9b17d308791dc5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4576 zcmeHLZ%iBK8Gr8Vv!P83#I&RhG=NiBS?2+!OS&YUNoqTbmZn;lwyCs*3x3B-}j&Iz4so!V)>qxrYKN|hJOLk-j;1<*^#(c5{SEp0>4O))1Or@FqTsm${MzAC@3!$ zfA*ZvffFi%*&^!U;1ls;90xE%rSL+%uO>t9EIoYf{GWq?tQ43AzK1n{{fn zEAT{lOHf^<=A+5!%~^~6D())}fF2uDD(_&W! z;>i!j#iN?+j-K};>yqmxo3%;L*qxFI-an)nHuq?vG(aTc^q&X4HU@*580fJLGKkm) z)ri;zRfyOIX+&&;6e6}kK*WaYPN$2+NDywE5+e+iK)6({%JjMf4OvB|fJ**kzl=$C2}k$k7R%QN5MLVTxFTe8XxNi)6b9H$NR7UMX=#v(~3vC zApJ#Qua3!Nai+m&j)!tQmg5(4d?d%mkpHm#`?IR|sq~(O6Dif>J(~s+HH%NqJv06M z)Q?iF39hh^t~>em$>5%)1H$GoZ0w%Pa{JT}R1c*#S8*rqriGZglHCVss0g@G67HWr^np*9R>T9&qO-66I9H)>!%6>19`ei!Kh)uUlZ z_XcXiGjvpiQNos;4wkVwrayBjn16ImPSql4AF)A%= z32izze8zTsH@9y}T@fF0Wh(XWT`N|-rEOrW+wT7yjIL{-M@|3UpDV*wuIL8*Qd0(f zBSvSYlCrG3Nlv`BQolX(kmrhU-qt`_K6y=lX{`RsC=zpgKgJb&%#gPlw~GO)pS)G- zx;3e7YQGuZH~?{~Uv)W<=1~N2IojF|BX%A3w%HY3QBePte9t^cOYiaNyt@e9@bN~; z?k|_HzCuFc`+p#1HTN2?|GH_t=kw{mGI*=5(b^8I?ZDa&tnI+s4t%v8ctxf&a-F20 zZP%`ESANae=x{vdXfoE-4Zo*Vf14M~@D~njbB4h=Xphof=WowH@y761&4mYld1}Knq<-6bk)QOD6 zSB{qJTsfcA-ubjz*Q1k^=1RU_eh&O{zFbx>ccF~0;5X4zl$Zayod3F+{*U~< z=qKajL%V{M{BNwVO0mR5atJ+x4aYu`Q}USdf5}sMHX -#include - -#include "ckb_syscalls.h" - -int main() { - const char *argv[] = {"hello", "world"}; - int8_t spawn_exit_code = 255; - uint8_t spawn_content[80] = {}; - uint64_t spawn_content_length = 80; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - int success = ckb_spawn(1, 3, 0, 2, argv, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 0) { - return 1; - } - if (strlen((char *)spawn_content) != 10) { - return 1; - } - if (strcmp((char *)spawn_content, "helloworld") != 0) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_caller_strcat_data_hash b/script/testdata/spawn_caller_strcat_data_hash deleted file mode 100755 index 9d32803cd06f45ce704dec2409e19f5b20d95914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7016 zcmeHMe@qiu9{9||hv*XhM< zJ7p*ZS>lb-^*FN#SzNuGxeKc`yV>e6NfVmoym*oqJk|dtM(tOAT2^tr`e1vdR zie!IE6bvI^X9O=s!brWMdszd}so<3&LLARyD;XvQ9^wQ)0qt_$?wWw2T|vA zXVi_u;6BL}BJgJUsb0pD%8mn6=!11Dr4S+ zQeFXl#T`R=llHh==(8&8<#qM<(&m^6W|Em^X2~J)9{GU$k$g-BQm6A~nL)rZjC zFPD2}x!Pc?Q@<3JyQn!OqUqUDLd5o~XMFpb}Bcl}b$s44^ zD1$b+e2xnSV|}6NnKpUwS(vVVg6XH2rc0gxiZX+vlwNNDrGg+=C}NBb17UFJ$021A zyLriw(^vs#$8ntsH(WH*KMSB=&#|l=todzjVk-&sg6R@ zQa~_vY;g)%aI9krTP30;Ta2t2``U_aL*LH+b9!L%?!*sc!=thvQy-+=yYGKEczBlD zdZ{t1@v1xTwk#uHikWI2W8BH-l^}&98NjV+U(b%@qrCNu{jE(IF1n(ZMC%WF zd|wW6HL}oKji0wJ@GTfAko(H-JdYn{?A@~7{6?9F1ZZt7ws(O_?uAa77gVTsQV3D+ zlp;jEQ-TonP7)#NodiPEI{_i;Xf*@^v0N()x0|_EiU^P7?dH8+t~DL_81>AEJ#D7d z-jkTzvZ2*i(K~(4t3|(h?pMi8Z$I*&ea`81sp3qhP2ILB(9%=z)$h88%|M^E&7)r% zAmgm3tr42v+Z1#>(v+SqjnHs5g^3!Xd@%zv%0!uj^T;H0QjkP6iD;5u9Ht3G6ZDE8 zDEAx`BfKyv)l ze2WL3}Yzbq(b=PS`TdAC@sfEC^ zm=+}!453U}Pk3~NM{jt%5FY!(;~g~auXuMt@;MRMHeK(RtZQ7^F_<>{&gAZ~eWUOD z&4YAI44Kh%xryC2x7WGa4a@5$L-YQ!|8eA4NarqE2SWd@I+s-SXDOJzcc#Z^zG!U($s2A6v^dh; zABx5?{F->Pw5k;Y-Gvm^Uh(lc~jg|ex>u154@ulSCJ z-#Mw2Og@?BmyL11*5x~Hni4jgUQsxgU`k*-_h$L`4Zm%dSiB1p`j~c!mk2m>Tr1D_ zeq=nch2AkLP44L~38tv7-HelbD%Vhk^-J%Aw&W(L5U0BKuN1d|j=c?SvP3xDuPqLy z5c&m=@IEL{QN0;_t^B&P%cvpr-+idMbSLvaR@mmmE@Y?p2ZeVZdJ_diJKk$E>SX@) zQhPqyivfCwcF7e-fI%c~8VkKnLuZ>ZE$g&JMP^gBMWZpBthr`7M`zK|=G=8_GqbI0 zbF(tF)*NlNMyJ(Tb8?EZbXIeYS)(c9X8|a&mX#erOzja{nFV2(7a7qgiqQ&0D-f+f zv;xrzL@V$=tw53Re}7oO&jb{Mytjn^pRHKR<23Ujhi;*rTn}&%W7R~)oC*`HMy^+XtLB<>P+BO z#&>qTkQD4dN!Us&=^7yPh?K@rwwi2RY1Yxq1Lb%y;ep1(@$&NOG7TooCLYW@&^%Nk z08m$!R94xlOlDA5S$|UnYTFTusmcUuYsrBko2lFi>e9odRR>Hqo9P&+ix4Byyj>*^ z=E_P?(?`n7t%va>I779ms>)VsuCB7;!-SvQ@V6L$qr+$a2uH&lM!vm^PI+H$=(zBe zh7O#=9$A7kU%`Lz^M!i``W0&cK`cZ8SSI+R!(+a^xOd=LdExd?U9Um^G_ zgnJC}Izya8j4$FZks|gb|0KabNpKYH{+s`Lq`<#ej4!Ug6v2N>MExS?D~RwfN#yHS zBHa53*F$3X7xfbbTM&Wg6yw_kf4ktHD;f$I8UJl0#}P9l>_q=xM9BH -#include -#include - -#include "ckb_exec.h" -#include "ckb_syscalls.h" - -int main() { - const char *argv[] = {"hello", "world"}; - - int8_t spawn_exit_code = -1; - uint8_t spawn_content[80] = {}; - uint64_t spawn_content_length = 80; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = &spawn_content[0], - .content_length = &spawn_content_length, - }; - uint8_t hash[32] = {}; - uint32_t hash_len = 0; - _exec_hex2bin( - "1dc91c6a0d93ffba6d11bae8bc74d4cb89506e58203e7361434e77f24eb7b11f", hash, - 32, &hash_len); - int success = ckb_spawn_cell(hash, 0, 0, 0, 2, argv, &spgs); - if (success != 0) { - return 1; - } - if (spawn_exit_code != 0) { - return 1; - } - if (strlen((char *)spawn_content) != 10) { - return 1; - } - if (strcmp((char *)spawn_content, "helloworld") != 0) { - return 1; - } - return 0; -} diff --git a/script/testdata/spawn_caller_strcat_wrap b/script/testdata/spawn_caller_strcat_wrap deleted file mode 100755 index 1c3a8da92269c0f1016e6692aa099a19706be092..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4000 zcmeHKeN0nV6hH6vy;dd@Sjm_ZN1=vpL>mgskEx`{UMpllvrIQkHv4$3z_d=6h= z9~4#uKT^|5%rc~zG0rSY45@Kh7$ZcJ#bo=#xWr_sv=fq%6tXhhCS&LF-s=j>{_?+t zlbriI=bqoW=e>JxU+?{hd&5Li6v#ruuRy&0QlC)@#Ii+$#Eh^N6xgnYXAt2SgMFK% zxI|CG-n1neawUT7l2~R0poa{KA|vFAK4B?Qd!=}9zL+PYOC|EIODN~nt1)b7$E2=9#Z=~v+6GD_pCD> zE(zZ}TY#^uW}0{&cQ?xF)Y8=DY2gRVL0S$;h7XI2?Iw zcNnWrp!&_)-kH>(g|^mEV(s(D2>Pkt2&({>q#0RWHtn%gRh?SJ)G4P* z6P1ApqtG`2>c(wGHN(_-UN5xxnPSEpj!$h^;H+cK$gU@B!Xzx=G_wE29JlPU4qE9} z7TxaP;%7vXhw?f(R?1>sx+vmRX_ zNrx54@@?rU67svLc(?A)yAP@ZeAK6_Gx&y>T*B&~IN+zl4~Mn*G{=YaXwO9DbzNL1 zrn7#1Z)rj~6@078=()q^S6?W!%;)p@-tf;)#5E!-bj^>u*hFzz1B$38<=fI-bb0im zxnsAmXOdYza-(HVqrG`2S8-KkU`^Yfe*~2+cR-7t_U4b8fJw-?2bYuuaN%}k^PGm_ zvVS4_PNmWAn0v`S?7Lz%P}~n^wAb#J|HC4jj(x~m^*u{|H$p87)BxGrWu3~zcE)YQ zeGf1~4Jd}FSudJIOwxDfTL~{@e49u-wpRSTpLipEf(uh5r+ z7&15POZU|5!Qzfqr*Hx&4oxPPb)48-)mm|^{GgpQJZS{doU+@GA2AT4i5HdJwGDXgl`?jHxnLjO^*QTXI&3`?=oNq*fj496_6q3>yvFt zGH|mk6)Aty(%wZb>5{5I1KL>o*fLuBzPoo>K+co9iJyLUxf8KNs&C2YBj)n_zX7r5 B%Xt6* diff --git a/script/testdata/spawn_caller_strcat_wrap.c b/script/testdata/spawn_caller_strcat_wrap.c deleted file mode 100644 index bbb717e58c..0000000000 --- a/script/testdata/spawn_caller_strcat_wrap.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#include "ckb_syscalls.h" - -int main() { - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - uint64_t success = ckb_spawn(2, 3, 0, 0, NULL, &spgs); - if (success != 0) { - return 1; - } - return spawn_exit_code; -} diff --git a/script/testdata/spawn_current_memory b/script/testdata/spawn_current_memory deleted file mode 100755 index 417eaca59965076e7f47f8639ee4e36979cce6c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4240 zcmeHLeN0nV6hH6vwS|ZRD;qdbkqT_Yb$m^6D52t`%xpr2x?r+Nc~oFpg|_0yV(bT{ z7R8U$v@C83(##pR7&BwaT+}hbG+9ixKZr|AHawFRlXl*>76jj?3YD@! zCh${=?plvaS?1_cGRMs)54L~cxTOTyEf>hTT+BzuDjUD;zZIH($FH1#3%bG)58~yK zE2B5Y3rCwCnI3-=WXIVM!?*ECNy$;3sEWC4Oj`T^!yEK=tDLu68B`C>#C=C=P|4-m z%Fpdq-zor)ZQx6l(>AGUVg8IhW#e%UixY9hRPs+UmiCIZUiBDQ(^2ItzXq6+vGJcL ze!HoSPwjWyu}vz1XU9m-w(oe-bA=CQJB;eosZUOXI;+?kEhFYWiwuvG`Gc?$al31g zg(Hhk9qFy*Yqs=zT)GOCa&v`ZG(DK>9xf8vhCx-izDUJwuCQ%Ru5xm#IJ<9XboC5h z(~GO-+NM%AR}dy)2`7-vHAgT9t2Whi*0A+*T!)RtnJ%HRhxHtsg6^T41D+hWKpxt^+(Nol_@UZ}1Z>{wrsFeZmD*~WK^~(`a{Tw2yUxtY4XAx2T z3?ix@5K(d7lasL?uM_&(JYG37Te5v^l>v`81H>FH_F-%KUtVi>;_}ml-l4{xM;`~? zZG3xNcEc9h@~9;!Ti?2}vp@au*3gd8og?oBtNVrMXg2f2l@rb_)0K|ZZdleFni0x4 zaB|mzt5*pvi&#g1OA+h`Wk>S{5{8oUW-eAKY6dNv4tE}Aj|{%QX;0@KcCQ{+#F62K z_NwW1LbHogU*$mmz>yK1{gt;BWNX|odD@oY9%FqnWI5Kgt`rhn%#bVN?|Tml-THtd z`buNyuJ{;cZWPJm-)i|01w>4Ow2+)0<-6xLQzWii*P%-M+mRDrEt4}CAms~ZS zpii*-et9hJ5!s>3PW;uBFnn}}EMN;c*11+*=xNs-EfvZ}xaHl~>ZVfEU3cSTmz3G^ zl7bf=LT=q%P@|>p`Z2{_BE~k7C{ifi~yi9*O@IQi@q8( z7Q-P6XiWQS^cFp640XG9oAgElXzKUXTXyM9CjDX1>_&suMV?uNYO@(M!hWOCu#a>? zMySzSET;PE0~Q1Mka=by?_lz7CU+zvBeNDkQJ&xze7N8T^E`=1i^Nm^)9)maRyvOj z5EWrBMVrLaH1u9Z?`!0)7%q{v8XK3O()fJo9OO&)LFpPe*9FZ_@l|Yz4T~?8;!CA? z%A*}nn_>YrgpZ$|zj7(Q6z@#oLgT1Ui -#include - -#include "ckb_syscalls.h" - -int main(int argc, char *argv[]) { - int peak_memory = ckb_current_memory(); - if (peak_memory != (argc + 1) * 8) { - return 1; - } - if (peak_memory < 56) { - int spawn_argc = argc + 1; - const char *spawn_argv[] = {"", "", "", "", "", "", "", ""}; - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - uint64_t success = ckb_spawn(0, 3, 0, spawn_argc, spawn_argv, &spgs); - if (success != 0) { - return success; - } - } else { - return 0; - } -} diff --git a/script/testdata/spawn_peak_memory_2m_to_32m b/script/testdata/spawn_peak_memory_2m_to_32m deleted file mode 100755 index ebe14775dbf2d198e55a33f8a5f6e51325583e18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7008 zcmeHMeN0nX7C-m3?}LF6*fPQ_xK=8l?o0=S@naYn3bs{eM%@obon*(BN2RD$fvR9a zrtRakfI7z1fD?DJ3ej1e#JEe?8qF@tvJ5606ZgY)H-iDQRx z6V1BAccWbvs@i}&F2Xp58GaGnC#+2T2x~CQ<1(Z#Ho1*V2*-G>%YyO<8>Qz)25XGf z>xTV4Gicb=z>MaHird2F{E;wdwyrGKs8@q~b&f?;FHn0rgQE*)jMalRexDC%*cKp6 z!r~8Mwz?&bIbx}(?y9D0Xw+#zt|;9@ za5Meb&t9i=t_dimPnC=GU_j@hf!rf9lDt<{F7feo1C;;3B=iS=d&|F{nOW6-xg#Z* z5;m|w$IZv-BOX@|Gf>{nbW#8v9W}1Apko8j%>+P)TQ`jnw{A5?+`3g5aqFfq;?|8Y z;?@lqal@6Jm`L?^h;ZYGzk^1zSL()*tpR^W0Z1{tp0F$bVTY?fbKcRij$qxu)F%Oy z&Wz?p@HM7junN*$Dwh7CGWee1ebeOlPzA9`V5u z?xe4CI{5j`>DXqTdCc+ZBq-*m zs(TNDx2mRaCJ$Hj1>cTF&jrZ3$?4B;HT=adPR-=Eri^^jM`DmzBnrLuMz1pG=}I!| zX;Uzb9kT`g(DEQ~-lytC6TkNAy}uKCd;7@>-gn|BsvZ`EOFmFtV$tzE!jPG2s(a&a zI_56*{g5eAF}iGAS+V>`n9=(#c-?ER92lfDbC618vQ;#gTE#_Id_zgXkS|ucX^`qZ zdjE0o!-44wCv+|jcr{1$cxhDORShs8tYM*fnGXLRb*{PS3VXGjW@B@M14EDXq7he( ztZ`%{y`Ra_GV#ab0Yyu&@oX zTcR`k1~rK4p3uStyf>K=0%|SqIiPATxs?&jDw#QJVX8-*6-`}D)WMM*6+63jQoF1; zj!@7BCoHk$e2Y)5yQl{17eYZ&(Up#NP`%Oy6GzvOUm6> ztr=y2ThE-Wlsu~=KQRKHYT2$IRXe$$f?!v-9@zP5qik9U7?SDi-J?_X9@yL4~i zHV3&_$%QAEgAT{OT}7l*WtE^x0$zd!3;_BDdxNvyX{`di)7Iz&ef^$ltJ4a4n|<5% zdaJ_*`r6&K&TZEEdTSHtw_`==OS}dNsu~(V&+l8!7<+UK;9ZIbUS z?9vzdJi`odv6@=$$8brID_J^3=>_+T^S=dA?I&@b`baD{r?NH CAN{`o diff --git a/script/testdata/spawn_peak_memory_2m_to_32m.c b/script/testdata/spawn_peak_memory_2m_to_32m.c deleted file mode 100644 index 11beb1e02a..0000000000 --- a/script/testdata/spawn_peak_memory_2m_to_32m.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -#include "ckb_syscalls.h" - -int main(int argc, char *argv[]) { - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 4, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - int8_t can_i_spawn = 0; - if (argc == 0) { - can_i_spawn = 1; - } - uint64_t depth = (uint64_t)atoi(argv[0]); - if (depth < 14) { - can_i_spawn = 1; - } - if (can_i_spawn) { - char buffer[20]; - itoa(depth + 1, buffer, 10); - const char *argv[] = {buffer}; - uint64_t success = ckb_spawn(0, 3, 0, 1, argv, &spgs); - if (success != 0) { - return success; - } - if (spawn_exit_code != 0) { - return 1; - } - } - return 0; -} diff --git a/script/testdata/spawn_peak_memory_4m_to_32m b/script/testdata/spawn_peak_memory_4m_to_32m deleted file mode 100755 index 28d8274b57dd8c45041079d8493a84481f63fea3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7008 zcmeHMeN0nX7C-m3?}LF6*fPQ_xK=8l?o0=S@nakr3bsXeM%@obon*(BN2RD$fvRXi zrtRak;KvwK0~mL*0?}Qa#JEe?8qF@tvJ5606ZgYqHp=brP4e3QuB=0v>?dO*EAcMLsPGKwZe#8U z6I#+d4wiRSz3%ASjuQi(_FQosMylr3#Wr`dccIf<`oNE|blN-C74eLCLO-*j>!p}u znRCj_Kl%kA<86znI?w8Hkx_VA%XNv1O?2KkXfs56ZUh;R8IegeWpO!K{+2C515PIu zCQ?zJby6_jgFHI&c zk%kt3`0Ak4JNq8aWaBveo}rAd0WytG{5(1@U`Wp$5r*88Oz6Zonc4j(Bc7Rtb{sp5 zn`qV@y&LVaP}K(HaS_G|%eRNNXah)x|smzaOk^B&@Fk43PUk#^-X5M>0#bCeKqT#X{RYM$@1d;1uBOna1(0L>_rQvQ+r&$(w z#A-C`C5mqizvR!D_ z+-YC?bnvs`>DXqTdBXAPBq-*9ABjO?ktp=qo4v}MofTx( zPE#-q-PCRSyfoWgn<6v*_d=VaQA!tb6Nk zI_56*-H<6#KDKN^S+V?Rn9=(#dfk;*4-8V8IY=ck*(w@LE#ji9zM&*x$QN6+X^`qZ ze*a1Eqk-v*9Xb~WyqcqWyfiBJssa^&I>ab0Yyu&@=f zo1-)Q1~rK4p3uStyf>K=0%|SqIiPAPxs?&jDw#QFVX8-+=fa^L*Ufev$1CBGq}p4Z=FpVI0s zUrST{k}aZ5tLEN@V*54FVNG}WAKF$EpL!EcGnsI5sJLcIi;OA%CT~Snt9yIudyYQg zoVf@Y|NOD;!f@d;7U48)!aVK2 zZ4Pp=k_%5Rha8T5yNXDs$|^yX1iS_3r>)Tm`uaW9R;Ly8Hv6{i z^;U-s^tHQdo!hMS_11%+-;NcfFYy{AsA^~cJ-^4{uT~{CvVWHBsPMkY ze-$=7pTDyHw6Z_maC|}H=QG6l+cTwt+2!+|Z^~bpv=Vp7oXY(-%KnYA{|bdDV|@Jg z@HmNB7{^omUymD?vXgv>>3!UA?7eZcr{`50;|z+wGE8(OcV&#=q@2I~`9a)|_x~?> CNd2<_ diff --git a/script/testdata/spawn_peak_memory_4m_to_32m.c b/script/testdata/spawn_peak_memory_4m_to_32m.c deleted file mode 100644 index bd91167ce0..0000000000 --- a/script/testdata/spawn_peak_memory_4m_to_32m.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -#include "ckb_syscalls.h" - -int main(int argc, char *argv[]) { - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - int8_t can_i_spawn = 0; - if (argc == 0) { - can_i_spawn = 1; - } - uint64_t depth = (uint64_t)atoi(argv[0]); - if (depth < 7) { - can_i_spawn = 1; - } - if (can_i_spawn) { - char buffer[20]; - itoa(depth + 1, buffer, 10); - const char *argv[] = {buffer}; - uint64_t success = ckb_spawn(0, 3, 0, 1, argv, &spgs); - if (success != 0) { - return success; - } - if (spawn_exit_code != 0) { - return 1; - } - } - return 0; -} diff --git a/script/testdata/spawn_peak_memory_512k_to_32m b/script/testdata/spawn_peak_memory_512k_to_32m deleted file mode 100755 index 118c5ab1d3667660fd139ae7df1657e77c51cb44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7008 zcmeHMeN0nX7C-m3?}LF6n4&NXu9XU?JJSJS{1``;f^F5ELHEN^C)u&(Q7NNUfvRXi zZ2NdE_%X)RfD?BTh3Jk>V%#Ncjb@i+31YG_aX(ylGs!H_j_qWL#aP4-Dtj;QJwKY6 zzvi#a_9XZH?z!i8?m6$g+xOCY4;tSyQ3!z|6x;`*waH@@vcZxgb%?D3mV*jk(;yWi z>{jEkv)M8+0X8J)N+g2xOSTs+0B%k)DhL^pPFM`-$~t7oelj+*67Q0X3eS+~Hs%jA zp~bCHaJ{GMb;sUy93Sv>=8I7Per`j2Q#X4LM05E=KgRMY?^svFGwccd%9?Vc9CKW= z{OoQO|M=H{jCU-i+5)S`MaJP(E!QP3GSLN5&}NDD{0K50H6oK}%Hi^I{B4_sCY(?@ zjHjal>x5vw2P1!@jV*nCoL~Ep!KR^&_Ss)}T%DN!ez&_`Bf2LvUi2vC6Spx6!V8^z}ihclP}#ST;oAj|^pe1CS{?elRvWV93lL7KYptOz3!&%3Qts9FQ^xCrAoX81+)fUvUhL#)FrkIRs`$mBLMAspkaE(WT`-|s_Rh4Q)l&LaJ`$$RoB7lSfC{=ut&6%W`J!|W z!AtIqYO#-R7@++7CZRw0`w{j}FGA9uL=v*#Ww?+7*wJp3$x zGMTabNMQ(9n604rZ*HfFX5RZC&0xRSrr~m$RYM$@1d;1uBOna1aOQA)Qp4S(PO&WT zh}CG=OBCN8e#M_P{-bynT03}G!-9%G63#eZb>37Ob5dukbA4%W>@d-Y;JC)1cf5Hbx zxl_K*so=HSQ}Ina^OWP&DNxFR0bS$sX1$U&syx+7kv!KZoSsic{$n4fAbH6`FBF_(>pPeeScN(L^ww7T*J9&&A!Q3gL&+IVJHXstJ=AK)0=@@ z)%{1ok(!4%lgF$2f-gENjsvZ`E%RW$DX3>dV!jPHT-|)`g zb<92L2O(3Wa%}0ivSRtsFr)Wf^t#tv-8V>SW+9cx>ewTTO_`i4@3Azysu#zCt4 z*n_9Rg9B3+PwHG8@M@0g@zSW$s~TWHSi?fgQXT$1>RfZsRrY!X&Bo^h2Zo;NMI){n zS>wn^dcSP=*|_S8JGSnjH>6r|XkOQF;Z$|(gRu`IABAd$`IHoD@!^Yy#dYy5!h&|l zZH-Oy>(wBtdqNB5^WIcS2&lEZXP>I2Y$Pj~Q#O6h!qkpBEBANprw)vMT)Dk#JGH}# z;|N9VaMBWA#<%*^x=U)Xekl~Clw9pN1gbaMVd9v(s69$`sxV7fc4!`-C%)vk)@_>b>HKRS(#P+YR4 zwCwGr%a*UO*6_8qZFTngkGJn|?A*1xp|Q!iXYan|{RapSw2CYwqA1U?E#qZTKNES} zFeB(&L?Tqq2=y&O?AnWV|M$Qj5*AB|A4q z!pkx$_WyO1cM)J#>5VVSUUS?T`-;Z98%ar4AX$NA1(Fp=R^a8&dPlpk zZi&tIwymtRxVU8bB5lbM{StjKNG5aj#%Cjj^*DHAeG|VI@BQGeI)iT9yR@u+$?oE< z4sx-Q3r{Ww9F9FZN=T>1DnX3|yaY`c0Q61vCTFA5S_68gt=S3s#$B~mrxo-z`_^rZ zR)-Dr^*igGTdj?a*8QO0h83kR@tP#4X=(yJzsupU?Ie?s4E0v0v$4KrkJCmrNxrv` zZ!q~b&+PeQjLc{RCE1}EWF2qhz9e{Cea1r>-^@y1`ptL`oX8^O!!M~IA3Mkz!0Wh2 zD0qupl4s`)l1k1#UX(;#hmEsvQ~WvEpOeoolw%BK4kf;VZ(&3F3;sE>e~#>^@V?7` zB{sa6zq08#Q5*y zaT2jOfv5PtnJ_M8C;1T52e{$byAx>7&Z{;g7!-eHnCMFG${4{3Ie+_$gSemQ|6g9z B{SN>D diff --git a/script/testdata/spawn_peak_memory_512k_to_32m.c b/script/testdata/spawn_peak_memory_512k_to_32m.c deleted file mode 100644 index 21680926ce..0000000000 --- a/script/testdata/spawn_peak_memory_512k_to_32m.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -#include "ckb_syscalls.h" - -int main(int argc, char *argv[]) { - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 1, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - int8_t can_i_spawn = 0; - if (argc == 0) { - can_i_spawn = 1; - } - uint64_t depth = (uint64_t)atoi(argv[0]); - if (depth < 56) { - can_i_spawn = 1; - } - if (can_i_spawn) { - char buffer[20]; - itoa(depth + 1, buffer, 10); - const char *argv[] = {buffer}; - uint64_t success = ckb_spawn(0, 3, 0, 1, argv, &spgs); - if (success != 0) { - return success; - } - if (spawn_exit_code != 0) { - return 1; - } - } - return 0; -} diff --git a/script/testdata/spawn_recursive b/script/testdata/spawn_recursive deleted file mode 100755 index ce415ca010271fe7468c86cc025a6f4120082d52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4000 zcmeHKZ%k8H6ume?bt);a*CJWOn7Iv;%|2c$Fs+le{=tN- ze<-ymig~7WS+*d}40Fq3Vn~h4#t0Hj7L)CRaf!)RXeT5i0kSgOCS&LF-t7v>KKW@0 zCpq_b&ON_#&wKaYzTW!*_qvIuC`5!tzai}HllzQvAeJc^IA%oKkOJD(=qW&SjDfz* za$KgTU~kHj3{nXryCjw#L8t={3PKQNOFm{PLC?tXGr3Y8!BZ-UcU?x3SDEAC3S-Jd zar+eNDNyu#k~{4ehrHoJ{}lRmOKZ#gTM^X^x?--F@HdHIRZP;;bdut_ILhQPQRe(r z;+eO7P8d83O=nRrt{qjdGl=88ZV@U4M=EV zgBnlg!RxBoPjzdDC2Lqah1^A;EX{2~lxb@E=ef@YDsu{Bz7fx?GI4PVkL>x5gOU9; zVW>O~>Nji8%_Ms*w6&6wYF`9~=%;?itUOqbMqqi}R8HZ0eP#xut&RdM_MzjMaC?i

8J4^3r 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 rhOeqW)vsuW!09_uL_9sWNaV{n +#include "blockchain.h" #include "ckb_dlfcn.h" #include "ckb_syscalls.h" -#include "blockchain.h" #ifdef DEBUG #include @@ -19,36 +19,33 @@ char message[2048]; #define SCRIPT_SIZE 32768 #define BUFFER_SIZE 32768 -typedef uint64_t(arithmetic_func_t) (uint64_t); +typedef uint64_t(arithmetic_func_t)(uint64_t); uint8_t CODE_BUFFER[BUFFER_SIZE] __attribute__((aligned(RISCV_PGSIZE))); void to_hex(char* dst, uint8_t* src, size_t len) { - for (size_t i = 0; i> 4; char lo = src[i] & 0xf; - dst[i*2] = hi + (hi < 10 ? '0' : ('a' - 10)); - dst[i*2+1] = lo + (lo < 10 ? '0' : ('a' - 10)); + dst[i * 2] = hi + (hi < 10 ? '0' : ('a' - 10)); + dst[i * 2 + 1] = lo + (lo < 10 ? '0' : ('a' - 10)); } - dst[len*2] = '\0'; + dst[len * 2] = '\0'; } -void write_u64_le_to_hex (char* dst, uint64_t number) { - uint8_t* bytes = (uint8_t *)(&number); +void write_u64_le_to_hex(char* dst, uint64_t number) { + uint8_t* bytes = (uint8_t*)(&number); to_hex(dst, bytes, 8); } -void try_pause() { - syscall(2178, 0, 0, 0, 0, 0, 0); -} +void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); } -uint64_t read_u64_le (const uint8_t *src) { - return *(const uint64_t *)src; -} +uint64_t read_u64_le(const uint8_t* src) { return *(const uint64_t*)src; } int try_load_code(uint64_t* number, uint8_t* code_hash) { - sprintf(message, "X in [%p, %p)", CODE_BUFFER, CODE_BUFFER+BUFFER_SIZE); ckb_debug(message); - void *handle = NULL; + sprintf(message, "X in [%p, %p)", CODE_BUFFER, CODE_BUFFER + BUFFER_SIZE); + ckb_debug(message); + void* handle = NULL; uint64_t consumed_size = 0; uint8_t hash_type = 0; int ret = ckb_dlopen2(code_hash, hash_type, CODE_BUFFER, BUFFER_SIZE, &handle, &consumed_size); @@ -56,7 +53,7 @@ int try_load_code(uint64_t* number, uint8_t* code_hash) { return -6; } try_pause(); - arithmetic_func_t* func = (arithmetic_func_t*) ckb_dlsym(handle, "apply"); + arithmetic_func_t* func = (arithmetic_func_t*)ckb_dlsym(handle, "apply"); if (func == NULL) { return -7; } @@ -65,7 +62,7 @@ int try_load_code(uint64_t* number, uint8_t* code_hash) { return CKB_SUCCESS; } -int main (int argc, char *argv[]) { +int main(int argc, char* argv[]) { int ret; uint64_t len = SCRIPT_SIZE; uint8_t script[SCRIPT_SIZE]; @@ -81,7 +78,7 @@ int main (int argc, char *argv[]) { mol_seg_t script_seg; mol_seg_t args_seg; mol_seg_t bytes_seg; - script_seg.ptr = (uint8_t *)script; + script_seg.ptr = (uint8_t*)script; script_seg.size = len; if (MolReader_Script_verify(&script_seg, false) != MOL_OK) { return -3; @@ -89,27 +86,35 @@ int main (int argc, char *argv[]) { args_seg = MolReader_Script_get_args(&script_seg); bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); - if (bytes_seg.size != 1 + 8*7 + 32) { + if (bytes_seg.size != 1 + 8 * 7 + 32) { return -4; } - uint8_t flag = bytes_seg.ptr[0]; - uint64_t recursion = read_u64_le(bytes_seg.ptr+1); - uint64_t number = read_u64_le(bytes_seg.ptr+1+8); - uint64_t expected = read_u64_le(bytes_seg.ptr+1+8*2); - uint64_t index = read_u64_le(bytes_seg.ptr+1+8*3); - uint64_t source = read_u64_le(bytes_seg.ptr+1+8*4); - uint64_t place = read_u64_le(bytes_seg.ptr+1+8*5); - uint64_t bounds = read_u64_le(bytes_seg.ptr+1+8*6); - - sprintf(message, "flag = %x", flag ); ckb_debug(message); - sprintf(message, "recursion = %ld", recursion); ckb_debug(message); - sprintf(message, "number = %ld", number ); ckb_debug(message); - sprintf(message, "expected = %ld", expected ); ckb_debug(message); - sprintf(message, "index = %ld", index ); ckb_debug(message); - sprintf(message, "source = %ld", source ); ckb_debug(message); - sprintf(message, "place = %ld", place ); ckb_debug(message); - sprintf(message, "bounds = %ld", bounds ); ckb_debug(message); + uint8_t flag = bytes_seg.ptr[0]; + uint64_t recursion = read_u64_le(bytes_seg.ptr + 1); + uint64_t number = read_u64_le(bytes_seg.ptr + 1 + 8); + uint64_t expected = read_u64_le(bytes_seg.ptr + 1 + 8 * 2); + uint64_t index = read_u64_le(bytes_seg.ptr + 1 + 8 * 3); + uint64_t source = read_u64_le(bytes_seg.ptr + 1 + 8 * 4); + uint64_t place = read_u64_le(bytes_seg.ptr + 1 + 8 * 5); + uint64_t bounds = read_u64_le(bytes_seg.ptr + 1 + 8 * 6); + + sprintf(message, "flag = %x", flag); + ckb_debug(message); + sprintf(message, "recursion = %ld", recursion); + ckb_debug(message); + sprintf(message, "number = %ld", number); + ckb_debug(message); + sprintf(message, "expected = %ld", expected); + ckb_debug(message); + sprintf(message, "index = %ld", index); + ckb_debug(message); + sprintf(message, "source = %ld", source); + ckb_debug(message); + sprintf(message, "place = %ld", place); + ckb_debug(message); + sprintf(message, "bounds = %ld", bounds); + ckb_debug(message); try_pause(); @@ -123,37 +128,37 @@ int main (int argc, char *argv[]) { bool if_load_before_exec = (flag & 0b0001) == 0b0001; if (if_load_before_exec) { - ret = try_load_code(&number, bytes_seg.ptr+1+8*7); + ret = try_load_code(&number, bytes_seg.ptr + 1 + 8 * 7); if (ret != CKB_SUCCESS) { return ret; } try_pause(); - sprintf(message, "(apply before exec) number = %ld", number); ckb_debug(message); + sprintf(message, "(apply before exec) number = %ld", number); + ckb_debug(message); } { int argc_new = EXEC_ARGC; - char flag_str[1*2+1]; - char recursion_str[8*2+1]; - char number_str[8*2+1]; - char expected_str[8*2+1]; - char index_str[8*2+1]; - char source_str[8*2+1]; - char place_str[8*2+1]; - char bounds_str[8*2+1]; - char code_hash_str[32*2+1]; - char *argv_new[EXEC_ARGC] = { - flag_str, recursion_str, number_str, expected_str, - index_str, source_str, place_str, bounds_str, code_hash_str }; - to_hex(flag_str, bytes_seg.ptr, 1); - write_u64_le_to_hex(recursion_str, recursion-1); - write_u64_le_to_hex(number_str, number-1); + char flag_str[1 * 2 + 1]; + char recursion_str[8 * 2 + 1]; + char number_str[8 * 2 + 1]; + char expected_str[8 * 2 + 1]; + char index_str[8 * 2 + 1]; + char source_str[8 * 2 + 1]; + char place_str[8 * 2 + 1]; + char bounds_str[8 * 2 + 1]; + char code_hash_str[32 * 2 + 1]; + char* argv_new[EXEC_ARGC] = {flag_str, recursion_str, number_str, expected_str, index_str, + source_str, place_str, bounds_str, code_hash_str}; + to_hex(flag_str, bytes_seg.ptr, 1); + write_u64_le_to_hex(recursion_str, recursion - 1); + write_u64_le_to_hex(number_str, number - 1); write_u64_le_to_hex(expected_str, expected); - to_hex(index_str, bytes_seg.ptr+1+8*3, 8); - to_hex(source_str, bytes_seg.ptr+1+8*4, 8); - to_hex(place_str, bytes_seg.ptr+1+8*5, 8); - to_hex(bounds_str, bytes_seg.ptr+1+8*6, 8); - to_hex(code_hash_str, bytes_seg.ptr+1+8*7, 32); + to_hex(index_str, bytes_seg.ptr + 1 + 8 * 3, 8); + to_hex(source_str, bytes_seg.ptr + 1 + 8 * 4, 8); + to_hex(place_str, bytes_seg.ptr + 1 + 8 * 5, 8); + to_hex(bounds_str, bytes_seg.ptr + 1 + 8 * 6, 8); + to_hex(code_hash_str, bytes_seg.ptr + 1 + 8 * 7, 32); int ret = syscall(2043, index, source, place, bounds, argc_new, argv_new); if (ret != CKB_SUCCESS) { return ret; diff --git a/script/testdata/infinite_loop b/script/testdata/infinite_loop index 587db81534a5b4e5197a9cbc88d28d5038fad5e2..778627008ad13851f2e3afea1bd4fc4918d4f082 100755 GIT binary patch literal 1168 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�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 Y{oMDsxtCqOm@k>&^HX#4*ZlJT4_U4iGynhq diff --git a/script/testdata/infinite_loop.c b/script/testdata/infinite_loop.c index 2a90f89cc7..ebe4d9a48d 100644 --- a/script/testdata/infinite_loop.c +++ b/script/testdata/infinite_loop.c @@ -7,8 +7,8 @@ #define sprintf(...) #endif - int main() { - for(; ;) {} + for (;;) { + } return CKB_SUCCESS; } diff --git a/script/testdata/is_even.c b/script/testdata/is_even.c index 44a23ed326..5d268ad424 100644 --- a/script/testdata/is_even.c +++ b/script/testdata/is_even.c @@ -1,7 +1,8 @@ +#include #include #include -__attribute__((visibility("default"))) bool is_even (uint64_t num) { +__attribute__((visibility("default"))) bool is_even(uint64_t num) { if (num & 0x1) { return false; } else { diff --git a/script/testdata/is_even.lib b/script/testdata/is_even.lib index 9e45b77c71702488f3edec48b6f84d2a47fd906c..4d8f9aeeee0c0c578b599d4d3bd80fb0b6da77f1 100755 GIT binary patch literal 5728 zcmeHL&1(};5TA6Lwtf|Dg%$-}{J;uzX%(ULV3VesQjBTshbSmZ+J>~!BqdqJo~-qv zH=%-mgSX-z;KiG#B8Y;QUObA5)SHbn+4<$GNfE@8JCMx0-^{$3H}CC(c@OPav?&lE zkU>94MjK5Y5>mxhhbM?GL<1D$|8_c5v<<3FJ@!uL0jI;|d0JT9Z1={SC#v~`rUVW@ znQkw?KJ^1{^QNWipWS)!`%}_1X_Eb#*{M;Uhy$+S$zUIeC;3W!WR7|yc0yt&HsW8* zGr&-&x#V|o_S2Va^!ZCxHzb2vOZx^RSwGeSO!%<|xWw->L zk#os$QcKy{#FDd|UCg-2+!;zI7BjS%cary$8P36!S-e_c%`$#*n&^`8CTzSmK6V>DA6#Vz8J;plxXRM%v0IQlO`ti|7 zWYFvxjnAAn`}?has}F{IaD%&8)W6cq;FcEqP>mae`d8!4gng>UgM|83<1K{ztMT1^ zvFHtIBdoL9o_E2lL_FCboQ|?ij!iRtFO-q8R1cT)6kz+>xN>d;ug#y^-y+^^vQR-I zEZ6JnZ!li3f4|efepc;w_4V4hTXW=$+=_>iGTBQuk>6B~kLI%JbTZ@e+Wwa0-9zpSeCIgV;Jq3E_X56W z+(XA%|FclY!XM`!yr+S`!gQ7eIWzFbcLM%Q4JDq~AU^Jo3yeu_@DHf~j(d(xilo;d zhIE-FnR{3fe0Si8BQfOes*OL$n9PZLc2(np*WM>M)8Ioj{&<%JKgIe=(&H?zl=*j@Uk3V#M@OKa7q1# zU&0OH9o2N2)L~wZNr%l7;{bKJQ(YY9$$XP0zWgLl=aZ%Ke%`qL{v$tHXb!87{XwGi zx15M$-Ly3c`Y-w;qVwKflz;c;H5eAH0#*U5fK|XMU=^?mSOu&CRspNP|E+-3dSZ{Y zklXtmjm3YaK5E_1>Z7Lop#DioW;%a!#g#^D z{aUe9a!c-wBMj(p6$_n`=?+)8&?_Bx2s)+XIf9<)_`y0?o;zGQW8Ud}R=1dpn6^W+ zDx3N{N8h4@*+lc=vX2?gpB?vt#&>o9(VwgF+4H=MeW&xPO9P=&zt1)EH%a@Z)o-3CP#Rbsl|TDk zSW>=T4}u=AA36xmu1S)M${%Q=d_T|d5930A(Kntuw_$J3nU;@$BF05n(&q6$DZhin HL->CH(Y<>D diff --git a/script/testdata/load_arithmetic b/script/testdata/load_arithmetic index b1fcd181cf4d245d7887fe974f5b7c543482c12c..df1c2037610d78231fb7d6273499b493284910f8 100755 GIT binary patch literal 6608 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 H#OMFtM-A=+ diff --git a/script/testdata/load_arithmetic.c b/script/testdata/load_arithmetic.c index b1c34bb181..95c06a831d 100644 --- a/script/testdata/load_arithmetic.c +++ b/script/testdata/load_arithmetic.c @@ -7,9 +7,10 @@ * - `num0 == num1` is zero at last. */ +#include +#include "blockchain.h" #include "ckb_dlfcn.h" #include "ckb_syscalls.h" -#include "blockchain.h" #ifdef DEBUG #include @@ -22,32 +23,28 @@ #define CODE_BUFFER_SIZE (1024 * 32) #define CACHE_CAPACITY 4 -typedef uint64_t(arithmetic_func_t) (uint64_t); +typedef uint64_t(arithmetic_func_t)(uint64_t); -void try_pause() { - syscall(2178, 0, 0, 0, 0, 0, 0); -} +void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); } -uint64_t read_u64_le (const uint8_t *src) { - return *(const uint64_t *)src; -} +uint64_t read_u64_le(const uint8_t* src) { return *(const uint64_t*)src; } -int load_arithmetic_func (arithmetic_func_t** func, uint8_t* code_hash, uint8_t* code_buffer) { - void *handle = NULL; +int load_arithmetic_func(arithmetic_func_t** func, uint8_t* code_hash, uint8_t* code_buffer) { + void* handle = NULL; uint64_t consumed_size = 0; uint8_t hash_type = 0; int ret = ckb_dlopen2(code_hash, hash_type, code_buffer, CODE_BUFFER_SIZE, &handle, &consumed_size); if (ret != CKB_SUCCESS) { return -11; } - *func = (arithmetic_func_t*) ckb_dlsym(handle, "apply"); + *func = (arithmetic_func_t*)ckb_dlsym(handle, "apply"); if (*func == NULL) { return -12; } return CKB_SUCCESS; } -int main (int argc, char *argv[]) { +int main(int argc, char* argv[]) { int ret; uint64_t len = SCRIPT_SIZE; uint8_t script[SCRIPT_SIZE]; @@ -66,7 +63,7 @@ int main (int argc, char *argv[]) { mol_seg_t script_seg; mol_seg_t args_seg; mol_seg_t bytes_seg; - script_seg.ptr = (uint8_t *)script; + script_seg.ptr = (uint8_t*)script; script_seg.size = len; if (MolReader_Script_verify(&script_seg, false) != MOL_OK) { return -3; @@ -79,8 +76,9 @@ int main (int argc, char *argv[]) { } volatile uint64_t num0 = read_u64_le(bytes_seg.ptr); - volatile uint64_t num1 = read_u64_le(bytes_seg.ptr+8); - sprintf(message, "before num0 = %ld, num1 = %ld", num0, num1); ckb_debug(message); + volatile uint64_t num1 = read_u64_le(bytes_seg.ptr + 8); + sprintf(message, "before num0 = %ld, num1 = %ld", num0, num1); + ckb_debug(message); if (num0 == num1) { return CKB_SUCCESS; @@ -113,7 +111,7 @@ int main (int argc, char *argv[]) { for (int i = 0; i < cache_size; i++) { if (0 == memcmp(code_hash_ptr, cached_code_hash[i], 32)) { // Find the function from caches. - tmp_func = (arithmetic_func_t*) cached_funcs[i]; + tmp_func = (arithmetic_func_t*)cached_funcs[i]; is_found = true; } } @@ -144,7 +142,7 @@ int main (int argc, char *argv[]) { // Cache the current function. if (cache_size < CACHE_CAPACITY) { cached_code_hash[cache_size] = code_hash_ptr; - cached_funcs[cache_size] = (void*) tmp_func; + cached_funcs[cache_size] = (void*)tmp_func; cache_size += 1; } } @@ -156,7 +154,8 @@ int main (int argc, char *argv[]) { called_funcs_count += 1; } - sprintf(message, "after num0 = %ld, num1 = %ld", num0, num1); ckb_debug(message); + sprintf(message, "after num0 = %ld, num1 = %ld", num0, num1); + ckb_debug(message); if (num0 != num1) { return -5; diff --git a/script/testdata/load_code_to_stack_then_reuse b/script/testdata/load_code_to_stack_then_reuse index 2b01578d4f899a3387b8b97568f8aafe12fb9de2..52881964bf26ff8e25d012b3b65f1dec2088a867 100755 GIT binary patch delta 4089 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 literal 37464 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 +#include "blockchain.h" #include "ckb_dlfcn.h" #include "ckb_syscalls.h" -#include "blockchain.h" #ifdef DEBUG #include @@ -22,13 +22,12 @@ char message[2048]; #define bool2char(b) ((b) ? '+' : '-') -uint64_t read_u64_le (const uint8_t *src) { - return *(const uint64_t *)src; -} +uint64_t read_u64_le(const uint8_t *src) { return *(const uint64_t *)src; } -int try_load_code(bool if_load_code, uint8_t* code_hash) { +int try_load_code(bool if_load_code, uint8_t *code_hash) { uint8_t buf[BUFFER_SIZE] __attribute__((aligned(RISCV_PGSIZE))); - sprintf(message, "%c X in [%p, %p)", bool2char(if_load_code), buf, buf+BUFFER_SIZE); ckb_debug(message); + sprintf(message, "%c X in [%p, %p)", bool2char(if_load_code), buf, buf + BUFFER_SIZE); + ckb_debug(message); if (if_load_code) { void *handle = NULL; uint64_t consumed_size = 0; @@ -43,16 +42,16 @@ int try_load_code(bool if_load_code, uint8_t* code_hash) { volatile void try_write_stack(bool if_write_stack, int size) { volatile uint8_t buf[size] __attribute__((aligned(RISCV_PGSIZE))); - sprintf(message, "%c W in [%p, %p)", bool2char(if_write_stack), buf, buf+size); ckb_debug(message); + sprintf(message, "%c W in [%p, %p)", bool2char(if_write_stack), buf, buf + size); + ckb_debug(message); if (if_write_stack) { - for (int i=0; i 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 U(~5bZ{IfQw{Iu?h{>111-<)7d(EtDd diff --git a/script/testdata/load_is_even_into_global.c b/script/testdata/load_is_even_into_global.c index 7dbab0cac6..4ee73a71da 100644 --- a/script/testdata/load_is_even_into_global.c +++ b/script/testdata/load_is_even_into_global.c @@ -7,9 +7,10 @@ * - `number` is not even. */ +#include +#include "blockchain.h" #include "ckb_dlfcn.h" #include "ckb_syscalls.h" -#include "blockchain.h" #ifdef DEBUG #include @@ -19,15 +20,13 @@ #endif #define SCRIPT_SIZE 32768 -#define CODE_BUFFER_SIZE (100 * 1024) +#define CODE_BUFFER_SIZE (100 * 1024) uint8_t CODE_BUFFER[CODE_BUFFER_SIZE] __attribute__((aligned(RISCV_PGSIZE))); -uint64_t read_u64_le (const uint8_t *src) { - return *(const uint64_t *)src; -} +uint64_t read_u64_le(const uint8_t *src) { return *(const uint64_t *)src; } -int main (int argc, char *argv[]) { +int main(int argc, char *argv[]) { int ret; uint64_t len = SCRIPT_SIZE; uint8_t script[SCRIPT_SIZE]; @@ -59,7 +58,8 @@ int main (int argc, char *argv[]) { } volatile uint64_t number = read_u64_le(bytes_seg.ptr); - sprintf(message, "number = %ld", number); ckb_debug(message); + sprintf(message, "number = %ld", number); + ckb_debug(message); if (number == 0) { return CKB_SUCCESS; @@ -71,7 +71,7 @@ int main (int argc, char *argv[]) { uint64_t consumed_size = 0; uint8_t hash_type = 0; - ret = ckb_dlopen2(bytes_seg.ptr+8, hash_type, CODE_BUFFER, CODE_BUFFER_SIZE, &handle, &consumed_size); + ret = ckb_dlopen2(bytes_seg.ptr + 8, hash_type, CODE_BUFFER, CODE_BUFFER_SIZE, &handle, &consumed_size); if (ret != CKB_SUCCESS) { return ret; } @@ -83,7 +83,8 @@ int main (int argc, char *argv[]) { is_even = func(number); } - sprintf(message, "is_even(%ld) = %d", number, is_even); ckb_debug(message); + sprintf(message, "is_even(%ld) = %d", number, is_even); + ckb_debug(message); if (is_even) { return -8; diff --git a/script/testdata/load_is_even_with_snapshot b/script/testdata/load_is_even_with_snapshot index 5543b994816366b78e92a059e4d31b02b6903eba..340259290e936c13085a20bb190b2fb24cd9525d 100755 GIT binary patch delta 4396 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 diff --git a/script/testdata/load_is_even_with_snapshot.c b/script/testdata/load_is_even_with_snapshot.c index 7004277e63..4b305c7882 100644 --- a/script/testdata/load_is_even_with_snapshot.c +++ b/script/testdata/load_is_even_with_snapshot.c @@ -6,10 +6,10 @@ * - `number` is zero. * - `number` is not even. */ - +#include +#include "blockchain.h" #include "ckb_dlfcn.h" #include "ckb_syscalls.h" -#include "blockchain.h" #ifdef DEBUG #include @@ -20,15 +20,11 @@ #define SCRIPT_SIZE 32768 -void try_pause() { - syscall(2178, 0, 0, 0, 0, 0, 0); -} +void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); } -uint64_t read_u64_le (const uint8_t *src) { - return *(const uint64_t *)src; -} +uint64_t read_u64_le(const uint8_t *src) { return *(const uint64_t *)src; } -int main (int argc, char *argv[]) { +int main(int argc, char *argv[]) { int ret; uint64_t len = SCRIPT_SIZE; uint8_t script[SCRIPT_SIZE]; @@ -60,7 +56,8 @@ int main (int argc, char *argv[]) { } volatile uint64_t number = read_u64_le(bytes_seg.ptr); - sprintf(message, "number = %ld", number); ckb_debug(message); + sprintf(message, "number = %ld", number); + ckb_debug(message); if (number == 0) { return CKB_SUCCESS; @@ -74,7 +71,7 @@ int main (int argc, char *argv[]) { uint64_t code_buffer_size = 100 * 1024; uint8_t code_buffer[code_buffer_size] __attribute__((aligned(RISCV_PGSIZE))); uint8_t hash_type = 0; - ret = ckb_dlopen2(bytes_seg.ptr+8, hash_type, code_buffer, code_buffer_size, &handle, &consumed_size); + ret = ckb_dlopen2(bytes_seg.ptr + 8, hash_type, code_buffer, code_buffer_size, &handle, &consumed_size); if (ret != CKB_SUCCESS) { return ret; } @@ -87,7 +84,8 @@ int main (int argc, char *argv[]) { is_even = func(number); } - sprintf(message, "is_even(%ld) = %d", number, is_even); ckb_debug(message); + sprintf(message, "is_even(%ld) = %d", number, is_even); + ckb_debug(message); if (is_even) { return -8; diff --git a/script/testdata/mul2.c b/script/testdata/mul2.c index 4163351fc6..99c6533122 100644 --- a/script/testdata/mul2.c +++ b/script/testdata/mul2.c @@ -1,5 +1,3 @@ #include -__attribute__((visibility("default"))) uint64_t apply (uint64_t num) { - return num * 2; -} +__attribute__((visibility("default"))) uint64_t apply(uint64_t num) { return num * 2; } diff --git a/script/testdata/mul2.lib b/script/testdata/mul2.lib index 889d6cf06d4b2e3293d58e932f723db83fbcc8ef..5529fbb34cd81601cc03669b1f95a2877758d75d 100755 GIT binary patch literal 5728 zcmeHLOKVd>6h6sq+WM-s69N9p)|JI2dD^_v<+z?FOplZ3$fOX zOQ8#Q{)XZYaO2K}bR!CGx^XEgqB|SU$vt0QO^OR$c?Xhj=9}})nK?6e;LM{)JnHxP z2*sf9B&}_~%ZzEqZjW1$zA+l60RMNm&;oD3e&tQX-#EuZzChlz(?EShKXBpXaq1uS3Qw<3q0z z{au?GjbQnVaNww=x>{DD(L-1%LKZU-W_OS+SmH#s+X@P?cohS0~SU5al z4#cJxE}26^){qs1;Q?rH7K`}Tni-tsVjt>xgAo6EzKyU?^?ZO3zk0r%F#mdfe_ky8 z26YnFS#Qs~VAe8j-5{KfYM&gNHu_eoGSyl$UiRC^_Kki|DBn2$%gXngT&XD`t~bl; z=a_Gnzu#+NZ>#;jygsv*zG^LzJ#lwBbaOIH_O02OaAaa(He$yor>8=(h&>+~k4J2> zWAT~sP~4u0M&}~)6?Wf)fW8#ez6)5z^^B8PB&+BYTwFmdm0hz|62%p=me;dv=Au&| ztB_15tbE!b%Sk@qf9_9YR+q?1<+!z!%Vd&ShnMwNioAQsoq_Kh=NdSuUT`nqd&WI< zhWme(N;&9p{(%E6^h%T5LvjZ}kM9KdObx}K*uX#Tk1Nc{+@K%R3J~`ko0N-QgJ{xq zuF2Tr%HX>L!jJfnyQ|Uv2y-$f?%56X4{W?oaHfHy4SKvw0`=LDt=xijq8;Ii_{RR= zyTf~4P#28-!u;WXnzdpAJ(=8)q6TKUQT>A+DBq*#gH@Aq%~ZWUt5$k-I%SQJ(r#Rn r@WZO#Rl!l_go0n}i|k2d?p#OdSI0>ZitrCw?xkk>hpN91!xsAAGXuC; literal 5416 zcmeHL&ubGw6n^O@TCHg8N%7zw6e{9k3WC^6x5;J=jfut<^t8mZG(z)(W(&3+kAgj6=CCqX0iHs zKX8%pmJ__>9JTgvxIgB(3U6L3W56h26fg=H1&jhl0i%FXz$jo8FbWt2SOL^c&$N*H z{%bN2VTNj>*8Qk9YRY$NpH~&nDlREr$?$3t>QmU~GXCKI7ozU=%jF05ir?72WtU1$ z$+>%q2`#Q-p;OY`;tCgfrFn~>Q<~2c^i1=!b*?N>yP~g{_8*V*lR;y3FEwEbWJEL(gY`-996duIbMQ^Wv=ycnoE;&2n zKD)&j9*`669)*$B?!D}gvo~O?GwAhp`ytlzuPE0$a(1GN4o2)7AkK%}nMlLAzgm*fOzaL;EgCs_D0+guO{8(j+{lrV;=$^s-w&&K8QzNcbH4w=U~4Aao%+p-Ye;L zk4@q5y}G~x`nqYQK!rL0(RY&=LUgRIi_@% diff --git a/script/testdata/spawn_callee_strcat b/script/testdata/spawn_callee_strcat new file mode 100755 index 0000000000000000000000000000000000000000..ce58976b5e21e559c75a0f1797ddce45b73dcede GIT binary patch literal 4792 zcmbtYe^66L9^dzp_cnw;BF`EisEBA=Z5get?di!RAc@+R>zwuO>YYu)CQvK{gdlq2 z9SI~66SVc&qJy56j@UAHH*F(&VkzhKs8`Sabo|lI*dmW2T2!EF;R? zl^|49KQ1ncNm6Snbqfj^JI;YAPgj<;D26cgyh4c zM1J;`x)U{~M8GJnhGVkbg>)a?pWLNTY;{vcr;#!_P5hQyP371fH5gF43Uo0HIO%!L zh*DzYh%aEfZ8ERh_i1CAWF-QvpmIe^ zZARU@b%(d|;dnjL!h|6o9}0!gUUdRL6i+*|ct*n_o=u>#mA+XyUp~gE0X<_sQVOz# z-oSb&<3dAf9UCuOyseYs{t!|l>lwiPVMxu$0_;oRjqM+X1HXbYVFMiFZ)X6sB{m*y zrxVd`^%OK!HrZf8Oy8Us6QcSa;vkUC1Q!95jeIbLhcbF=0|!5&IXQ=Ocqzn(G6C8V zpUkBwY3_F_8dcRMEl~OOxqEVbt378uOzcTF#{k;3Q%LfKyZuS0l)kh*0q6s=&f)L^ z)~`S7**y8AyW8*DSv-hpVre=#Q1^2Kw^~V~(dAUW#~pLl6Sd)1VJm&h!@Z?ON3(<7 z*js2^+q{;2se4maRld8aDh6ka#D~8bPmu@-PWBq^<(J#}+j9YxE$oZE>CB?C`PUTm zdM|%_8gTAF)0Ik8ahk^Kq!A_1N*~7p8IL_q+K*xafRQbLIAZD(A))YeNT`qP=cXuW zY6q(LAflu6VObejA-Ychh5M2G4TYq0BqSt#5OO{#?4++Od6UeF=X2)Ab6RYHN2&r9 zj*MKMKPLzDns!tlEC2k` ze4pWxP;q)llo}K&vv1*9x6-4W4C{H-BbJU_zonJvNO=GjSuo@EX)pltf z?5nuP)*Xw;(!v0T_n)$XXRDc+;9Q82-DoAYlCUkJjd!W(bL6x zU&?cy{!wk>36*eb;($_0=BsE%LY2p=xHK ztTPrkpGGof;qiho?c=%xkh3;(kcT=KuY88)l*)f*_Q$+w_cY^u>W*{mCh{9UcE<|Z zRbguBaU&UXUL9zJOo$&IR-@h_uoZsMuqWH)#n>3Z4j55zD4B=*Y3fO&4yN+3i*_zU zOc2-H-`O_L91l_ir=h-s@jR?%kvy1&Wm%*P{zlfR1DsW^q0%u2^1dlR`0n5k59hJy z%0U&008)QzM2SI7%obkd2S_bnD9cfSW{(~F>)P!$akWzc3Ky(wgx`f-T5j9Jz{v;V zLLd#Vh>?r+yIV*)6wddPwM@OCtBnJwXD{IE2g6Z2RE}$ROKF;0>9}HDQP@(bT-*D5 zJ~-Cqlk&+xAv`o1&7v?p z*ezyBKg%ddw0Wp>R5g@Ha*i{e+~y;hW+2J6kP_@78p7nxZtT@OStmZf(s|EZFu%R# zeifLZ!m|N%0w2y;s?Ep1oaqNJeffdKd7_ptRu?+>4-WiZBQ2`$MLFPz} zF%B$rqaBJV8-I=b>>~_Z+pyM;&pfst)RdT{KKOHaR>pq(1d|H^qoTQcteS5#M1xUsPb+DI*1MCb^2VluA zD*eG_9L@;OzRb3Hk>*TlWIu0*nvIyp!Mo~=;;EKdrpAT`aDKIvn-w$M$%4i$a7@ac zP&yns?Bl#sfcqVi5t5<0SpHwbVgCF`c3@-#=ZMsN-8)=^f}HkS*_6%N!gjX_jTKB4 zD-GA3lV1=!2qx`kd|+s{8$> z`lR-lNY0+d84{+#p10Z?VG2N-i{i){7W=&hI)%J9kTWQ44~c_u;BF*byImWa>V+w_ zVX|L!DjnXl!Y=lFR@J)qcvjB};7r$=BQ?0{)^^)J)FB8B2 za)_J^QkKsgA*XJp_rVUCNd;nBf6T_DBjdF$wBr~VqA}`hrJnlu9kPEu4>V!>7Y^Bd zM_V)fM?2bl%MVRmm)6J0oOF(L;b@D;V9OYMWTdT&XXGH+i{CKx_)T&e+y8#ghyDNP zOYXToU~X`~IA@D9hr<$g-*FSSNbk7aFJxJ>+_Ug0+As+K-uZevo%0Zuygu;h310CT zL*x{Y0)tHS7h>%uf?HoL=CR%kCsMP)XN!)7jbSk0w{r8Y7LX~=mnSszM`j!}u#mO9Id<;qJfm3A}Hwh^Oc z$l}OA7|*ws|2F%{Ec41|m;Peavuje95OGs>_M+4WOu4HbOr1YJV}8awV3>nt%L>cU zdO)ROQm$dj)-Qat@R8Da=3?@&kO#sK%>1b)!*`;$#e30sS^UBT^x}Q%UR(x#a38_~ zG9X=w#!D0Y-kTWVlIY68jqtsa0BA8lV{Vst_fv@iGex{##Ay+KSj4Z1cr|v7v?uV7 z*qMkg6LCA<8>BriUiMaEn!=vmS(mt!r!by?Ij3Ty@~epwZqMPLhWMWt#UmhoycEH) zcN6Z5evA`4()~4ARM-@e$Ma6U*N#`hC)nXdJ5s*piE6td@;{vS;E&k(tAtOO_eVCS zxun8j&a24Jx0QhiZLcUQ0%p6T#9}Tgu@{UZ#qs)bdnqm)M?S!68S{bJTu@Y!XDKq5 zmSEIYmX48?OAXH&%vm|6<+)}v9%rpwY0k-A8lm&b%W+*;${e8BQfSA_du44_i^BrU zHajk+jPi}e4oe>H9c9t}MTv6QHaI{=SxH1X1KR`{sHC_US2adS`D9oejz6)t_E0gpVabu~$qOKZwT!6U*T4 zJ`}%GOf1of`WaZ4%s=tmkiL^7VBYvfWJ#0y$1#oPE{%ZW9@E9|Epx|Vgp~9on2e>h zOBm^&5%nJsnGj_t CbuuFW literal 0 HcmV?d00001 diff --git a/script/testdata/spawn_callee_strcat.c b/script/testdata/spawn_callee_strcat.c new file mode 100644 index 0000000000..75bdaf4409 --- /dev/null +++ b/script/testdata/spawn_callee_strcat.c @@ -0,0 +1,32 @@ +#include +#include + +#include "ckb_syscalls.h" +#include "utils.h" + +char *strcat(char *restrict dest, const char *restrict src) { + strcpy(dest + strlen(dest), src); + return dest; +} + +int main(int argc, char *argv[]) { + int err = 0; + char content[80]; + for (int i = 0; i < argc; i++) { + strcat(content, argv[i]); + } + size_t content_size = (uint64_t)strlen(content); + uint64_t fds[2] = {0}; + uint64_t length = countof(fds); + err = ckb_inherited_file_descriptors(fds, &length); + CHECK(err); + CHECK2(length == 2, ErrorCommon); + size_t content_size2 = content_size; + printf("fds[CKB_STDOUT] = %d", fds[CKB_STDOUT]); + err = ckb_write(fds[CKB_STDOUT], content, &content_size); + CHECK(err); + CHECK2(content_size2 == content_size, ErrorWrite); + +exit: + return err; +} diff --git a/script/testdata/spawn_caller_strcat b/script/testdata/spawn_caller_strcat new file mode 100755 index 0000000000000000000000000000000000000000..98358ec114504fca3a0940bb7cc72a152512d044 GIT binary patch literal 5328 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 +#include + +#include "ckb_syscalls.h" +#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); + + spawn_args_t spgs = { + .argc = 2, + .argv = argv, + .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}; + size_t length = 1024; + err = ckb_read(fds[CKB_STDIN], buffer, &length); + CHECK(err); + err = memcmp("helloworld", buffer, length); + CHECK(err); + +exit: + return err; +} diff --git a/script/testdata/sub1.c b/script/testdata/sub1.c index 90d790729d..a31aaf63c4 100644 --- a/script/testdata/sub1.c +++ b/script/testdata/sub1.c @@ -1,5 +1,3 @@ #include -__attribute__((visibility("default"))) uint64_t apply (uint64_t num) { - return num - 1; -} +__attribute__((visibility("default"))) uint64_t apply(uint64_t num) { return num - 1; } diff --git a/script/testdata/sub1.lib b/script/testdata/sub1.lib index b1a89a227be89c21c924ac5fc09c1006c955b6ca..c3fb211c9b1c55ea8ae26c66b59101d8f33c7d5d 100755 GIT binary patch literal 5728 zcmeHLOKVd>6h6uA%U7(e(yE{rRH#@lEh3aIY|}I?r7^92fQoQQ+K?9VBDn>-DAu}h zDRkk^-%$JkZrr($ZbZRNH!ej*bZ6r^x#!EPNpYbo??Cd+d~?1zGiT-woOu+EO!$31 zLNVw&No&XNGNanD*X35EZudeX#Y`- z)D^{JioJ^E+{JVW9fr_n7K`{-n;D$tVjpUGgAo5(zJ;()wR|ffezklXVg9xJ!Ms@d z4eB7Qv(}z>!K`N7xkGJ$^45ygd~ndvuDzzC#&G(U0gvenOU<|Vucm5me(_E=Ax4) zE1yWktX#?=%Sk-sf9{W^SC`02X1TSLO{WtXhnMwNioAQsoq_Kh=Nj0rUT`nqd&WI< zp8J0mi&^M#{(*f>^h%T5LvjZ}kM9KdObx}K*uX#TkL%3I+@K%T3J~`ko0N)PgJ{xC zuF2SA%HX>L!jJfnyQ|*+Fmo~{?%7TC53IjWaHfGHb$Yx@0`=LDt=xijq8;Xn_{RR= zyTg0lfG!yOh55sOl(k|4J(=8)q6TKEQTc-&DBq*#2P!6|nyGqyRxS7HbV?c_rCq-! r;fGYer-I|m2?f8{7ul2Y+_{d@tBw;O6yYDV+)Iu08>)W*!zTLQa#y(9 literal 5416 zcmeHL&ubGw6n^QZTCHd-2#N>ypimJPa}Y!?-6oqgbWJq2pr<8GOCy*cG+QtSQ9Su4 zc=BKJU+^M$@K6!OlkvUX_r={!Dh2U21Iah<+xKSPd^@x7=9L%J777JIv*;U%^;xMk zeXzQcbc9}`JG99EXJ|S0T~wcW@I}V~Qt8h)C%9WWm)NB%S^Sxp1Vr2d^M8vw)HvXh z+K)a(I}&%?rfE`(8X{M6+0Z zydSv8cq=Jha*kVjID9@PdU@f^Yh?@=1&jhl0i%FXz$jo8FbWt2i~>dhqW~*_y6K4) za^HVV1|rN*ZPdCS)kaPEPVLjG;z`A2#fv#!O+tMN`&7;!{QpAK-F~HV*IxA-Ti5M! z*(p1>jxnLdRV;K$yIWl0La!`u5p>G(MS`ALezwk)=N4Da$UE!Ls@rKM>02`@C-rxc zzD{PnWe?2q@}3IJ=jT1I{Gq;ojCVu%d_FGobL;fc!FJi{P*{E1a39nw6h3ST?4q~VKXAJ3QJ0*Z zai851jP}Wic3(uX)$Tp(kh3>nt25~JcKZ?5^RFn^J92j7iw;KY8z9by+?hzjxxjh6 z%-oO3WPo_=FW}WUO7=$55U(a(_gm3;r + +enum CkbSpawnError { + ErrorCommon = 31, + ErrorRead, + ErrorWrite, + ErrorPipe, + ErrorSpawn, +}; + +#define CHECK2(cond, code) \ + do { \ + if (!(cond)) { \ + printf("error at %s:%d, error code %d", __FILE__, __LINE__, code); \ + err = code; \ + goto exit; \ + } \ + } while (0) + +#define CHECK(_code) \ + do { \ + int code = (_code); \ + if (code != 0) { \ + printf("error at %s:%d, error code %d", __FILE__, __LINE__, code); \ + err = code; \ + goto exit; \ + } \ + } while (0) +#endif + +#define countof(array) (sizeof(array) / sizeof(array[0])) + +// conventions +#define CKB_STDIN (0) +#define CKB_STDOUT (1) + +// mimic stdio pipes on linux +int create_std_pipes(uint64_t* fds, uint64_t* inherited_fds) { + printf("entering create_std_pipes"); + int err = 0; + + uint64_t to_child[2] = {0}; + uint64_t to_parent[2] = {0}; + printf("call ckb_pipe"); + err = ckb_pipe(to_child); + CHECK(err); + printf("call ckb_pipe"); + err = ckb_pipe(to_parent); + CHECK(err); + + inherited_fds[0] = to_child[0]; + inherited_fds[1] = to_parent[1]; + inherited_fds[2] = 0; + + fds[CKB_STDIN] = to_parent[0]; + fds[CKB_STDOUT] = to_child[1]; + +exit: + return err; +} diff --git a/script/testdata/verify.c b/script/testdata/verify.c index 9c3a1a4402..c42eb92b76 100644 --- a/script/testdata/verify.c +++ b/script/testdata/verify.c @@ -1,4 +1,5 @@ #include + #include "sha3.h" #define SHA3_BLOCK_SIZE 32 @@ -7,15 +8,11 @@ #define CUSTOM_PRINT_ERR 1 #include "syscall.h" -void custom_abort() -{ - syscall_errno(93, 10, 0, 0, 0, 0, 0); -} +void custom_abort() { syscall_errno(93, 10, 0, 0, 0, 0, 0); } -int custom_print_err(const char * arg, ...) -{ - (void) arg; - return 0; +int custom_print_err(const char* arg, ...) { + (void)arg; + return 0; } #include @@ -26,39 +23,40 @@ int custom_print_err(const char * arg, ...) */ #include -int char_to_int(char ch) -{ - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } - if (ch >= 'a' && ch <= 'f') { - return ch - 'a' + 10; - } - return -1; +int char_to_int(char ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } + return -1; } -int hex_to_bin(char* buf, size_t buf_len, const char* hex) -{ - int i = 0; +int hex_to_bin(char* buf, size_t buf_len, const char* hex) { + int i = 0; - for (; i < buf_len && hex[i * 2] != '\0' && hex[i * 2 + 1] != '\0'; i++) { - int a = char_to_int(hex[i * 2]); - int b = char_to_int(hex[i * 2 + 1]); + for (; i < buf_len && hex[i * 2] != '\0' && hex[i * 2 + 1] != '\0'; i++) { + int a = char_to_int(hex[i * 2]); + int b = char_to_int(hex[i * 2 + 1]); - if (a < 0 || b < 0) { - return -1; - } + if (a < 0 || b < 0) { + return -1; + } - buf[i] = ((a & 0xF) << 4) | (b & 0xF); - } + buf[i] = ((a & 0xF) << 4) | (b & 0xF); + } - if (i == buf_len && hex[i * 2] != '\0') { - return -1; - } - return i; + if (i == buf_len && hex[i * 2] != '\0') { + return -1; + } + return i; } -#define CHECK_LEN(x) if ((x) <= 0) { return x; } +#define CHECK_LEN(x) \ + if ((x) <= 0) { \ + return x; \ + } /* * Arguments are listed in the following order: @@ -80,56 +78,55 @@ int hex_to_bin(char* buf, size_t buf_len, const char* hex) * Note all hex values passed in as arguments must have lower case letters for * deterministic behavior. */ -int main(int argc, char* argv[]) -{ - char buf[256]; - int len; +int main(int argc, char* argv[]) { + char buf[256]; + int len; - if (argc < 4) { - return -1; - } - - secp256k1_context context; - int ret = secp256k1_context_initialize(&context, SECP256K1_CONTEXT_VERIFY); - if (ret == 0) { - return 4; - } - - len = hex_to_bin(buf, 65, argv[argc - 2]); - CHECK_LEN(len); - secp256k1_pubkey pubkey; - - ret = secp256k1_ec_pubkey_parse(&context, &pubkey, buf, len); - if (ret == 0) { - return 1; - } - - len = hex_to_bin(buf, 256, argv[argc - 1]); - CHECK_LEN(len); - secp256k1_ecdsa_signature signature; - secp256k1_ecdsa_signature_parse_der(&context, &signature, buf, len); - if (ret == 0) { - return 3; - } - - sha3_ctx_t sha3_ctx; - unsigned char hash[SHA3_BLOCK_SIZE]; - sha3_init(&sha3_ctx, SHA3_BLOCK_SIZE); - for (int i = 1; i < argc -2; i++) { - sha3_update(&sha3_ctx, argv[i], strlen(argv[i])); - } - sha3_final(hash, &sha3_ctx); - - sha3_init(&sha3_ctx, SHA3_BLOCK_SIZE); - sha3_update(&sha3_ctx, hash, SHA3_BLOCK_SIZE); - sha3_final(hash, &sha3_ctx); - - ret = secp256k1_ecdsa_verify(&context, &signature, hash, &pubkey); - if (ret == 1) { - ret = 0; - } else { - ret = 2; - } - - return ret; + if (argc < 4) { + return -1; + } + + secp256k1_context context; + int ret = secp256k1_context_initialize(&context, SECP256K1_CONTEXT_VERIFY); + if (ret == 0) { + return 4; + } + + len = hex_to_bin(buf, 65, argv[argc - 2]); + CHECK_LEN(len); + secp256k1_pubkey pubkey; + + ret = secp256k1_ec_pubkey_parse(&context, &pubkey, buf, len); + if (ret == 0) { + return 1; + } + + len = hex_to_bin(buf, 256, argv[argc - 1]); + CHECK_LEN(len); + secp256k1_ecdsa_signature signature; + secp256k1_ecdsa_signature_parse_der(&context, &signature, buf, len); + if (ret == 0) { + return 3; + } + + sha3_ctx_t sha3_ctx; + unsigned char hash[SHA3_BLOCK_SIZE]; + sha3_init(&sha3_ctx, SHA3_BLOCK_SIZE); + for (int i = 1; i < argc - 2; i++) { + sha3_update(&sha3_ctx, argv[i], strlen(argv[i])); + } + sha3_final(hash, &sha3_ctx); + + sha3_init(&sha3_ctx, SHA3_BLOCK_SIZE); + sha3_update(&sha3_ctx, hash, SHA3_BLOCK_SIZE); + sha3_final(hash, &sha3_ctx); + + ret = secp256k1_ecdsa_verify(&context, &signature, hash, &pubkey); + if (ret == 1) { + ret = 0; + } else { + ret = 2; + } + + return ret; } diff --git a/script/testdata/vm_version b/script/testdata/vm_version index e105dad85c11b987e1fdb77be46bed27b36b28c0..e2c0225e5b710d150448d0bc33d24af0f5eec395 100755 GIT binary patch literal 1192 zcmbtUPixdr5TERJ>w2-VP$>11f(LC&=&BVd1$WzKqhOc9)|>FirlAcq*(G@{>p^P# z1cg1+quxC4sUM&pz>ne070;qG*?Ba5WxY5d^XE6enfG2Y$*J?ISuzYzQi5MV(WhJk z)H(6JG;t_bhi90r!!4N2Srz77G02e*?E@EnZi-Y-1f z_zWLEoG$|mvoBf6Sp%c_WBmO0u==e+EO%#T(|X{xUO%*IHM?f7Lt_QuBuxE27#6xS zW+mxAeG)$Et&511N6JTq$$v;0_dMWz7ineS!xusH%XsNRr=EeIe{}o~0w&_4#mRF~ zc`L^a7@61c2IBL$7xf;NxPXpeB7ULqx2E)Y!F|-ZER0F^@TNZcx^Jf7KI8hj(2qnv zNYbzy+dc?!bkgm3C!*I4V;Lm(5ozx>4jN+HabLECz<9ge7EWt7_d97SQt2fUA}@?F zd7T>^deQ?C#D@TO`Yw`Q2dzvd_E>o`7)Y@FZWIMEI{75no|H-0c`E~&ng5r2*n-~B zEVok6bHMQ?TV?c#S;hp_>m#VXi+NSZmbfI!(um`<^>VPFF4~jHq%XC*6Uu1h5?agV&e*rf=W}Y(o`gf<)f8~0b-=gUCe*vmAarpoM literal 32392 zcmeHw37DNlm3Gxv-`#pkZ|NmTC*4^wKqrB0AX}O&1R_QPP6&jX?%TIJZF;kBH%SmA zovYc9?}Y@B#) z+(qM$UT}-pzHK+;cRjfzT@|@~_A~poZ`;!(#O~qYyQ?l8exvF#`P;;YhnKx74wTix z=&H!26YBRn>Q%9!9^Y87>{zT{QW7+0Se ze*L(fYrnXC&(up_6(>!S6;ofC`O>oX{q4Ii4;NL1;i85sPdyO*dFds)F9{dPm8tQ& zg8l8wT<+qAD}7GGF7cxcE$#c-gRV&H_HBDNL=v}#+xPtT0Z%3+)5NF6MKuwX z{?F~(*1!L~Ki~1-@aw0)e#UF-Ub*b0eFtX#{?s?mdujF+_wI_Ew&VUQrVKx|ZRy0s z>whc@XI__DpAete5N-d_V9VBhTZ0RJ^uCr&`!=te4AWGwzfX`#Yz; zvaG%8^4Q|4@RG&#SI&IN^igba#Y?6a*asI?@2;IMKCx$SYWtoaKcF5Metq`N9g8lX zvg_sDu~_4@<9;*w#ua}!<)X7vkG~S8isC`l_(kG`>!&T=U%unc*u2Q{ch>wweEOBA z#I!qW=S^GuY~!xwsoLknj!&$Z_soZ<-Tj@p{}iniiC9_ex+fppbLES28OA;SbcBAG zIyWNdF|#j;zVyy;+expATZDK_-Xd>NpOJ5D-v$x!w4E2L?3|mNGxwPPXq}k{{q^SF zIKkYR_dns|T2prPSO0l_WzSE3{)31p{-4mWzqjG#V#aPbM68+kGEhk5x9_naRos#7N68i;cfPJf}8(RXa6%fH0xJFigC@MWh>-XYq|T`O)Orxl%h3H*3%gUr*3H^Hoq zCx_a^H?`)qp!>zQw1pc%4~S=VCH=wgS>tmRe?Wo3;BJS}yE&fhZWG_vrMCp9 zvGx~qk)6T0WDXP!qvSP#M8WXI%H=3|WAI7Z^>WD+2;35Uh-2~7GESY_f(MxMGwl%f zh|-&o#u7?j*g&-ddX)Cda5ZwY!bv}cic?}?I*2n{)?lgW473$OE=8&Cpg09vei{{>7YsA)saDe?^%J7jWJ z%ZHJ(IVc)H&RV$_ITr+as&0^vqn-~Kv5oTQF#1B1(=Y2#=Axi_Gs zQ$hJ`6ljbTRf4-eD7qGTiz6c33C&m=kB90?(jnbbclZO~ayneIro*qM+)cQYUWMxD zNI7y$vIFxNMOcLHl@$@;OW^goNzc*K36qwc-Qakvt8k z5jj@`wOm<`kpCOk4+Z1c8LQ=WFyYGJh=(DzRz450tAYs|QPl={Gjcv0)Nl^;%O4=; zYQt=i&midk?(>bW;zx9RjV=6L#T5*zSrXG zQIUp9bsj3^V5G9UQBndUoeph>ijjimvdIwF7%3PuG%-@JyO!zoVQ{KjiTIQq*G`CF_KzcMA~5_O*@Q4<2^q%#Yi_% zAy-(Hsw8bNl4_5#eFh_`j>N~1<1i9C0T@Y9S%lz;U#nGp8uTQKk-iIBV)t^YIYcj7CMYXy9`EB&sF>a z1q?<~&uhTsFcM1}jHF)Bb{UMM4ivo~D(Ep18IO_3c#Om{ z9wQx(b;)BS=6H;B268+`Vvfg1L{A& z6Y==mFk)4ggA7_gRck5+YP_c23#x`x(F9O(vMe-L?k#>3ie+O_2c%l?E$I@n zNply1!{UiAoBkwhlSe_;M1j_qh!UY{0DE zqrig%%+{gcp@KmK%oao31!+~AOdE$g3boaSZtCHn9*n#Fk>MXFyphb#01PP0_g%~q%9bvv=5k(@c}b3 zK43=1f%9?;#6^6kD%vjI|%*gnF85tiiBjW>RWPHGkj1QQR z@c}b3K43;B8!$VQ7TACpX;EqdW}23zbKx;-ifFtDN=?9w48b6`A?+xkTa*o$-A;uz zU`E;p%vi4vm~lf;!^ADvLab3%^#YVi>BS#01QK0@?-4Nc(`9RxK2rq{IZw zro(On2DP98gIdghL6SaT)(6H1%*Z$}_$Vsz0W%iy0W&t<2h6U)MDqc&&w}v*v+sfN z0khY^I50@f4h+&l2L@S*519QH1$@9PfhE*|L6-IbGZygyGol0^Fl#|4_<$L=BtBrq zspA7?RB(?dyB;@|2=#>x3<*d=W(&0nIhD+roDG;U+krtX<-lMPwt6r~#)CmJ9t^UK z2ZJlIs(UcV91jN1LyiZ7%<*8b7dajba;kbTNHGrvnd8A=24y@Lq?iYTY>o$mvmoZd zApJNC2I;5SfY}ZRX2IZ0v@Z(=uR`8pfI;pST)>R9qI>EN|1`Lq4%aM=66!;gyB?Ra zU0~@*IdV+01M?6?ScLAC6%pzHc)f1YbM$n=q}>R?ddKGk%>EzRt0E4{U$#gF3ftaELW_QO>$Og=~Tnh&V zIY1r^Qp$rtuB;vm(o7EqAB30(gYBrwgF(+hD2Fi6IO!N;J$gTZIOcreI%JQ!pd z4+hD2Fi6IOK{6f;lJQ`W+5iUW9<*8aNEQq-nU(8gfI;#9&0x-zlrK4NE$pp+e6K%kZV`Bqmtj*MWwkuI5rfM+Agz=n<+Wmw|fmEDy z<2gC3pYCMh7F;6q7GgMEYaph%fY}O6is^K8Ss~dQVg{#!Jgk(Bt)Y9*Ttr`46=CiV zsG3g-F^eHJyvtU2#47jx6L8OAI)1jimSv8GP48%j>@@xG0$1EGPMO5%eLtAmM^MMg zYL@yQ*+yJWopuY@I3$XD#cAc#vVcsNSQR7lQ8FF9;$20w5w59+>3#VXpmQd8VT|W&yLgRMGI@A7VY3~LeYc;!O*$~Y*7?7 z#KQN03?k9{a0`z@iU?0&&Ea@l15rGgx6;T0WIRhr5&>6)V9;Ge2}fM5(n5vJkb6tf z@p5rF%N&EYB1~!ei8U&@PR>>G9QARzPRVmguSbMbh!^o?KdnQznf(IKNVs2c#TPc8cNi9XQM(1cCq5gYsrn;c&mEE$$~>f5->rbPfiA3l7SUL$b&H zw}Z~&e)^OR0v8;Vvyj96Z+%csX^;EKc-&9M<9;%E2jwdNpqvfBdNA^!oCQ7ZC*yHH z8ISwPc-&9M<9;$8_mlCspNz--WU{!Q5iN)Nb#&|PAC$92S=>M7K{@O7xPO#`agyI7X;=xkHh_>J?_`4h3ZDq!4Ar`n8E!dJ?=lWgK`$}xc@J8P|iv`?mx7H zau)Hpe;AC%{XEd~xPR<}aw^C3vZKWUYBP@dD_ zJSevv&VzE5cTk=q$AfY!rw_{6jyGA>kDX92f!7D)I_S&k1l-Rlq7TZ=GW7Ni%2|uY z{rdd}p?FZP{`&{z#=OaYmV2d#G@SvRac-+rpcaQtYc-&9M<9;$8_mlCspW1Q{ z%Go1X+)uC3L0=~49+Z>ULEyJ_P|i}h2jzz6?%_}m%2~n%f!AY7>4S3ZenNE;QE}4g zgL3PqJSbQB2j$ceh^Y?u^Pqg1L5z&lMkCR0qD+}ajAa@zmKnr2orn=@4ZExm#K^s; z0qD%=)e;jZ@hiZcnFNT-5_|(oo>S90&?%O4ft!dLYud#M(hNnU zW$?8!2veDev@#KCWg^l@WNaD539C!S1F5NTr5^@e8Yg}#dj%I6m4z0_y+1*V#@)c) zh!#`wX*49tL?_BPmy9d{dhoqEgo#BT3BigIISy(2prmSp&DgF@#5&i2 zK5n6hvI#-2XwmOOCay(SwoGJC2FcdBqGhIb;$-VQ(K6SPM~RkWEqSzPS!&7oqUCf; zE)XqiNrq6cRKG4J;u+|z*ZHsr)zxc8S6AQYtE)fUs+b31OCBZaPqgIGqJE_%=ZpF^ zmRum}*ORQi40QyPD@e2ICQHo|Gc9$LINVZ4i@BDXFBVv8fjCxEVtfRB6I4nnQUNqo z){qq9OBiBKja}ICR_m=N16-Wn9kzR6f&P512&+TE;evke1RIcFLc+e3t6wbXu8g>4RfvcE1V_=~} z-)m6X?={Hyy#^V-*C2DSy#^aF>Ry8d{a%BN-)oTZdkr#vuR+G|HOTnA1{uHCAmjHM zWE%YoCx3>$23wSU;bhFc2J3wrdkv#i?=|Y*>ZM$*TD;|6LyMWc2FbU%*I<#+_ZozS z{)~Ze(VsDV7mPn+_%#@J#_%{6Fn7klZIe4=U?qO9LGz@{TTy`{I~WR zR51Epw3(RrH3tGT!GtPsV{&<0mKVBf?j~7_RZ!=E866KE5@dBY0j~BRsvD=J^q_f+MPl3zs4MNS*D50*P+;zC<_i^b%IdXcNVdVJ! zcPUAFR#rr)7r^Un1)WAOnRc5|=Xk&qzH8#%$E~pMnw*V%cf3GaxZ?%Z;|tqpyg=F?FOc!a3l|{6zK?qc(>c)tF-dPT?!rUN9WUrN1KjZf2gn~U zP|6=KUm@m?7q~U@#|s4c{&<0mKVBf?j~5<=0)M>lG#G!pzlY$^${KOV3)Q}0?=qE1ZF#|uoT;#{=b48{fYHlvD@!>%2dGm(4z2)$)5 z2wiI+8VT@2yllcPauX4BbX@6^$S;H@a<5`1;q(Cyt_oQ>PL)k8n^9JUt`M?RsIp_5 z!gofFDPCE%7(0MKrxd@l*d?flSXqUd#);ylI4K;EudI?FqD{z|gEFz{qPX~kVpRq| zL-9Bj`tpeyR$&!lhml_+j3};>s;s!!6l#i7bBPl&S|C(9Ue2mF)t0RkLEQ)I0CKEm zZ9BZ$6jG*Y%q*=plB>6Jrfy4Bw#LXYrp9VlBNEUP0CTL6w$xNebXKvNGI0tzFIHZQ z9g}S@I=ik`!gSp_3fEWVu@lf~=%0z>#jJXu2y0L=dz;b?R@$Smu<&!nl%^2B=A%d_e)mq=v=)AG|z;`IDP2(w)$)m;ch*d94GE2{!D zb>=DZB6+bM?pcP+dW|}m*LZgcjsF~q*Vv(>8;BPDBlIM{#Tr56*{Q|330c2&>{ciW$aIJ z$hWnOX-k{fXJ{%-EpeVhHO6yF-7@1BwzBNP_E%cZnuT5~U}@8WW11>v=@kUOfWiks zj`elf;XVtVOOLJ34)=t7kHz0*<}QPijK?;Z(T0QOd+d~ak8RBN*rt4so$5Sxn)QvG zb#J;&(!Dte%f^h{1mm_d^L=e)m01O6>|HR;^?tho`udi zg3BWgz}?fSxf!iCo;%B~uoqy3ol}gr04njco_mV8NN$()7o*0!xo6f(<@AJyp)R&9 zk{u8?|DxFeiJ2}RG1Ed=aY8X?pRt7vEY5Gc>ynbfWYa0My0owd%Glb`tk3$<-`>jM zCZG18(ZSANe3clvCLA2>xY7SBEe?8|^)f)P$5kxnspZ`6Z{x|8vkpuf&C3gL&dMt1 z&YS`xfli)><9RqMcPU{<9EOCvRY2hHcjxIo3QV_oG@-JO(omOb@>!AjC$` zfrVpj@!7@yfY}{mI-kRFy>93NO&aqyHYr-1Kpj}2y`rL#%RzB=IViEKyhf%(&V-4j zTqF1xF3X?k9s*vVQR6sWlSS-odAV8PDzu5br zKcvC^rj+t`Wu?5~sVMLTF@+%@{Ru#i3#OCiMdGgt4p0amRVS59ghHxNUk&Z90n%lH z*NDxHYe|!CXqF9ZZdTru(t1!H=I{p{XzhC3N3}L`IC5^l_hEcr!?ytzYReOy;KbGV z;{80Ny&D&`mX{5@bn?=Vi`k4g+2DegRrHFZvKD z{4qERv1I{U7O-W(OSq^NxKQh&v9v0_b@l;#sab1O)g1a`+3&i;beFh43{jKOMwpFE zdktLoT&RgDa0ND3stXfkxRYlGxyD9{*nFl`h#*9-qQ9A~VmfhBUgwk}XLNZK)NT`r zKnrwlPLx1)qG2x9Ds>KwWL=|VB(%^d86!(T5<}99UOD)TxfOE!ni<1C6c@bErQBb| zsB$+a6zezU;c94Jb-JnXArxkfYoKUUml)gYV?2hWcaHA$SzmXrda8MTV6z?ypA9&g zW~ey_q6y4fW1aR3_rj}s0=*oIs&Q-y2LJuq8Dcp+h5=*E5sj)z&Lz^e;WRbZsdDL1 zJ6l96L|HSdv^!CymW&kH zzNp%yYmBQ(eb*8+0TRY8*C?%@IiWH>?Jb{Rn~j%~wT@ag-_j`6qpk9tl!&Tgo#N+U z42DzjB(#n9606VG=xaiXb`;+tD1yso?37{bdsGKjZrS$Bb;vh{^{cefugZaTwOi~v zqiS*1Q!$1Y>+Zte2XWvrHmK+~w%WI|=LU88&BRZZ|Uq8ij-{R_35MQ;)o zIpg;i>U%EFb%{JX&@Y1Hb4CJM%oD{fWgkcsLA0J;=Z2aCM;BxrW?3`O6u){wIWp1o zFWU9~-DCB5=z82eN%UeB_|;!Iv-0& zH$GkCBq!P0SgV)d6rbuOd>Q>HLN7-GH>Jy+3@ixrxK+9o*NVy<{nl0kc+48*b#f^~ zKE4=6{z5EQ{;?+xU;5#PSVs?G$X9{H6C6VHxR8@@F%!qV1XJe*EDY3f+Kt!gx#L#= zG(vH-%&t{`FO2DHFnGvF)$-gM3f(N1>G*gnqJK0b_ZzK`>T5Wxf9QGp=)i$8<{ z_-9`jQN`ZH*%;j!W?h3GeE7!|f5b-#d7&)D*`7`n!okPMmTxI5U%oRO4hrSxBcFc_ z;IP$sUcPbZ&Tv=sjE}^JgN;RxwLI1GrIv5Bl!+E@$wt=8-=W)ruX~i2QwX1>_%hu+ zqwi%RJ}qUdTdprVb9d2oB{!502dwHN@jaF2`kKDk@~xIeLB*&K+gI3 zR4aFSS$WIOaOrTcs!Tlg)adRk-h27 z-Cb=*_O|x+&C$Owxp4lGL%o}N`!@F;neOhGgUrtEzD&ks3j8W%QY4uz8+H zwrBd18(VwZyVD|>>AC>d0dVsdi)6YdJGs)&8WDqr!AQoY#oHe=2S-W8Jp1E z*W1~sFGIbVuFl?cdn12Q5Wip6VN@o&`%0ZZm^qN{adZCl8Wd(hyO>7)g zrw3qEOIN2hxwEyWr&SAqLeHjK+j-3lbr0fa2H6T+Hm5eW>7so@PyuUD8FY4GL^xI_ z&s$`FM6~h9o>Wg?d%FAho^*S6-)8WGL%r$a2T*%@5M1j(YUAyaj_>YY zIDceTXXBCYJ__GV&CG(Uop@bEB)bqYoNdw`^`lgU}w%piDZA z^6=;(a>?^swL>G7o!Z}*(FU=fICwp9D>@RqcT=*vmA%o?JGiw!4SlWc)N|G<%v6!= zOb@nWJlP3gy8GHNo?SitLj&n#|KNZ~!N+LgPzKgM%eiNyej?guWZ|RmAdl0x9Azx^7;XP3 z&Z{QZ8;sl>_EB@{P{oC*p7ze^Or=IO#{97K9IP_kLzu6lwl~)hD>w(8cgVs5*0-lS znm3B1_B9ZCVZxmYJ8nb0@Zok4#>YUI27_=G<)V~PTas&~S@&GgF?&^u%`t1jp>*pZ zs_nrKbfZV}hU#sZPX)f=V_JWRQhDphh&5?U?bhS$L(-1RAy{S09eM%XTU;{^Wdyuc z2iFge&jG7+R{faIso^chBVUCmT)yC$`r)7Bp<{NX7Mx?mvpx8h7UVj#F8tOmVZ@FC z%IE%(pP1XMW%Stx_J-?Xj&%F75P!aXvv@tX)W@v!J+9Q+*k>*IL^kPbmUO{ixmLtn z$=hsRF!$z|qn!%b=CwVXBj)HYyBgYJu7+=9lN|YNo20g1d~?h(-_Oc9@<6VfW4y&} z;&<2~`QCC{$#NS8LT@?J?FLP6#YRY;<0YG2;Z)3#$J!(mKIi6`!b{&&BNc{B6|ovCG~Eery(Sn%n5iN*$qG%jceMrm>X=5G7~2}ZE}S>% z=9o)xsxhRlRi{{4B(1WfZ)lqsAr_gpT};1ugs4dtvDH>ZpVN9?Y?~$bWRw2Uk{|U+ zBDT@ePF!}zF0)DAo=&kW*X>>UolecVm?Q6UN$12I>Gu7`BR1tK`ht~y!j;0zaA{xh zX|Zou@>|&?NB+PjsV(y6m}3rjIq|*R>RkGNxcqf7N4lVabz3J{X=6b0+?XRLyRgs& z*90-gco=g`PVx099#|Qd9bT+m?`PKR6P(th_+@VMoR(EC ze_hOxF1BHt=Oo*lF>zK~m>SF*Epcv6qEj!|313yx*Phkry*{DSy5+`yGPgB z9M_pf$-%FP6^i>@eL12Ee;eTbPhL(k{sv5me*Qp2!AFTuY#TK_BHWJ_<`z*RD*VqC z=42=l69?SS80Mv$=VMNiCUqRPFcG{GE((~RsmAyZU`j{v@@2^>Q93eFrt6l2OvLMKXVNotzA4mlvoJdJUWGc7h*r7$(v;$ z^zu%&S`X03ap8|K($fp)?_!%?INw)|k)9kQoxh)74!_;W-`mUiTn@GpEpyKV7w^7W z%a2?i_zxy3a@GyEB7Dl~aroGsTRd*l-E-f?`@e0|-2!~CwW$P0U9{%_zWkhE(_gmo z?qTZU{zRhX@Y}kAcIjX8&Y2fhjo=@VQ@;bVZbg`2)7?7UXbbR_C(64Agj>-*fqK~w z?$=*kKg@)Dd5)jBdimpA<&ZC2SI3QE|M9k7w-wnq(o)?@6AYM)az$ z7dy7X9jK2^>3|o4FPXuijt(u@-sj?w?Sp*-nPltG7K9;t`n%JE>2@AdBuA0R4PhZ# zI3j* zT9#aP`qE_5h9n`GADb+QqKz79W2H9uW+ISp5tVd7&U`VKYD2jFeR{7u-ABZd$u&!t zoVg^~vTVi5(_ygd&DT=6d9HEL+KKc*0N@e?U-b;Eu&9Q5STS_ z3(?bx2({VzLp0y2vr#I`Jesk;K;6PU!qN~ViPqz(qVklaBJF~2g#k;Jwwt@8dPOux1 zT}NxTatw@gBxM+e_k3T9XA{1%f!f*`M7oCKFfa|^ECHUz=|eh zvb;U9_s{!on-Jy}23^SWjSXTBSKd7z`fY++*PI%+KDj&b1W}SJ@18r`Y=V;;tNh8x z$hF@+7kAq7xz9)HDAc#IpuEGOPum4{Ec>a8pVjzMr?cO!s|RfP#T3f<6xM$h@@W6u z92t_Xd?E6qEI;nf=Nszo*NHiof3x*-d~!dooJ(WD!ZhaTH>`0lFL0Q0X6Ae@20dE& zxfUv4F+WFm6xk1rlExAbF5wmb+nCOk^C_(BCgc^SQM_TbDRg|Xxw~tj?Cr=XOrz|E zb4-cn3Nj1F?^Cw?TqEwUi}^M%K8NSvGxAQIyFX;p3d^S~u=q^DgmdNGojBCd)bBoZ zU55IXh)Xf|LfQX|m-gJm0C|J9jnzB%LP kj!n|H=Y|Z|QlPxBe(spu+{-OLfiIWf^9ytH*TVAu1@O@>BLDyZ diff --git a/script/testdata/vm_version.c b/script/testdata/vm_version.c index 427f1227f6..d7397d8c98 100644 --- a/script/testdata/vm_version.c +++ b/script/testdata/vm_version.c @@ -2,7 +2,7 @@ int main() { if (syscall(2041, 0, 0, 0, 0, 0, 0) == 1) { - return 0; + return 0; } return 1; } diff --git a/script/testdata/vm_version_2 b/script/testdata/vm_version_2 index e3871ba942ad7a63fd309e0d8a945db72a09160c..ebc92ae7c8fbab5bb13d8e1b2f43609b545d2260 100755 GIT binary patch literal 1192 zcmbtU%}(1u5FRH4!U-3tQbaESap<2c5`I*n3KD{2wW`ueX|G*5!2%=fMD{icCooTd zlmk7s*B*1?0eAo&qc?(juG$%AR)ww7OULqlv)_C(yK9eqV!x?p3l~?^T5YrV*lB!tQY@9MlC=WWr$|SB-0p!?e@zRY>Jq5SFbe@iFB0nsQpNonw zrMv+{^FCigejfLt-opYXlv#hN>9;1-dChgyxr#U^dyBV;_4Rc>PT)P}^>v{ah@Kb4 zekT-Vs|`ZzA9Y&pk?3~(PNQnomUMZaK6)Q3cInJ`mHz?v2-H|f$N7D zys!24ThJ`SYYLX^=M50odpz67h?2?8%fC+!8xl``^MpQJ}!^S|~83(y;y z=0fUu_IbX^s6g+SMGR2B-h%48m{*C6sv8tii(|KSH5ptn@k|S-JVn!7-xI|~EO^HW m^exk!XTHEVi}-i9zW##=`QJGIrAlPf^M3=sCUTqr literal 32400 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 diff --git a/script/testdata/vm_version_2.c b/script/testdata/vm_version_2.c index 2b1cff6e02..0576c517a0 100644 --- a/script/testdata/vm_version_2.c +++ b/script/testdata/vm_version_2.c @@ -2,7 +2,7 @@ int main() { if (syscall(2041, 0, 0, 0, 0, 0, 0) == 2) { - return 0; + return 0; } return 1; } diff --git a/script/testdata/vm_version_with_snapshot b/script/testdata/vm_version_with_snapshot index 7685e8d3ced47133d3bc536861857f653f3daf65..4f27a8944f54e07b226eb9faa2c4255e0f71e12e 100755 GIT binary patch literal 1256 zcmb_c&x_Mg5T4g;cI!b}_q4hmDtM?r2wM>m5ovcfjmpv$>Wbjuk!GWfY?7KhV?9W> z3&I|S9=z)R;=!Zfy$FI=E8YZu%uD92-AM7W4?5q>H{VR&dzo}#ZZr#wfm#Ll4l;U| zT7Wtws#@mATpg}rwhjw0pQ?1y{8dOV>p7;JLMUg19dEw*F7h8L~%-q|3eFk7Od^;?d7lAdu zP6j_l#SgmFT5D_9Dpjksb*@sY88u@C8t0LYyx2*ARnVO)>rry$vUjPs!hLCMX&f|| z{Lj+xjD0%iv{Zw_ba>!vK$m#HWVbX2-+oU~se2l28Ts*2c8@A=q&$Oh`7pnU{37l} zy|+_TaD()pa{Ajd`rM;F>RcPt=fMp9;~D%D;`7gi#OH|{#aUp1{;EzU7sZMV7ET2K8>9P?P%kpSQJ0!$v(y4$v} zfxE#rfDu3Uh223EQHEXR3AZo6a6;dA19Z~aFl-?ruk%#6a*B>(En^e;#^$M+y5By< z4+$0ICkRJ8tvk1`g%DTOo+IUOQ#C42U;hW^dxs?e literal 32456 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νf#Q*)uHXf zhzG|eOw_58W2Mzh3nWXqNwAK4bFy zIk!eEZB2Ns&f05PVwV1uEul4HOL!-fWJ&ecs;INve(|jl%S6rJ{-Xp-7MUa^XBk)H zR`FZxkX&!st>p36&iaTY?QT%_R%DpuIZkrDRZc`K*=CZUe9o;A%UP3NLPVAri4R!i z4-OamU`FgbYjEe=a=5{OsUp&3gw|N$E!X-Z2s2egRvMwz<}L@(ua-I0Bu2JGZwTg2 zxHV!EtZ8((ZB@UKMbe-lT|-;NFtO0w?PBV!!$ftmh-@_`K5DI=7rD=nU&a`kB!&Dm~m)4y%atdCgoIh%A&#FBR3uRUT@wxORJ>HoA^m>D+h zZI>2#$B_6X1!yC1vo2yu{ew_&??La@h-GY~02A$d*~QuP>DJErh$U^%z__iIJkd&? z8?oeS8y33oT0df$EcJ8YBvyTmRo@V?V?y@@gX~qbxQ*)t@_3;+(8RYu;NgTv1oJ(lZvVTy8lwHK!bx z$a3u8%4ON)uin{pD7@G>hFyHZc5?NZjBx(c5@EX{StkzLc$q!TR?${hgzc2ArdeTI zCwmWHVsdO}qJr=GL99?bfN%as;%@`&|JBRRllUvJ{rrK5ypI%tcwofzkgz{mn5`lO zqFem^t-OyE5m7o~x_&<9iK8}%!;bKg!bSmeGvz4%0ZghWUal-TDT;?Ds`Qdk(#MRF zZlj>N*;16{CKyhN@?q)htw8+Z5BV94^Ny6xcqbzG!{V@uN0Fyp1ipujJC|JAS#2Kb zl;h_de7&skvZKit9PrN`hWW$QNT(h9|LDM~&p+WxJ2ht98H48Mc6{+0c=!(?*0M?# zeEDLe_I`1c^ly%m{*_VEpBW{cOZZ6T{&E&pd zeJ0p=_s5j{@b%$ekY1LxZrBy!F=NN#V|#A#O_Oe)`!?Rs7g1QQU4ZXrGw~URqb{b~ z_4h=bEZ#Em_F-z{{yhCDh2O5sYu8wlp1+PY82c8?+7)4@Nw@3psixdnCfz>v9inrsWWpeues z3ehVBqX6Pe-Kk8ytD*S~|OuB!dtxX9gdu&uP+27Nbj<*a9A}HC_ z+nMT5C3$EOA3-8JpoQ3J-xkr<*Mit|a-gegi|A?nP%6=nf5e5rS0*_(@JAi9`8T^- z8vUZ|&KZxM)nM+S=jyIpaEFL!jN=W8LD)VA$BgWlWs0qdCc;vgpC~e3ySInlG zfNpP(+WAg(@v(S(?Xsn3EsZxduUK_DDs1~WEAl&16cyX)L{{J0akLRe#%SG8+C-!^ ztzBz6CLV81tFsh@X>}AsbhRK}tpfoN&8<~Rhj?iUKl_&6($(M6iaVm(>b}uZh>iA( z#?(eVo}w|+iJ~#n>7r4YYfS4KY9bopN?nYuH>!PqV@rR3Uq>rqt;kBIS_j%O6fNED z8CFH+ZB}b*U+MxY*oio=rIlM*29>lVWf+uqd{2TW6|S(p?sm=FIrJyo$3quWnJc6E z*mdLq!@r7ooBhdSMFTRaZ%**t^WXk|d0=0iq5`*}$l`Sw=j={sDikGHW#=6>?^*BG0&{&w9j zHTsKk)rXaTHu72jIeBtcKOYHFmLGfP^A2VAs>H0zWK%xJC;MadY#J5w)0nr$wm;8d zO0A-~UyS=m`sW+yeEGawg?!m7M$vz5sn$!-xw1a_`nMo2KaJw2t`fl}X>i-3ipT@j*y0ygZ`sS|rvgGqzM9JRWqgBo~3lra;U>j}! q;V%}{hdVescTAGHMK93YnmptA<#Pu$lKwirY=Y0v^vzxK_5T|jvpDYn diff --git a/script/testdata/vm_version_with_snapshot.c b/script/testdata/vm_version_with_snapshot.c index 8861f4a4ed..bea91f5fbe 100644 --- a/script/testdata/vm_version_with_snapshot.c +++ b/script/testdata/vm_version_with_snapshot.c @@ -7,22 +7,19 @@ #define sprintf(...) #endif -void try_pause() { - syscall(2178, 0, 0, 0, 0, 0, 0); -} +void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); } -int vm_version() { - return syscall(2041, 0, 0, 0, 0, 0, 0); -} +int vm_version() { return syscall(2041, 0, 0, 0, 0, 0, 0); } int main() { #ifdef DEBUG char message[2048]; #endif int ver; - for (int i=0; i<4096; i++) { + for (int i = 0; i < 4096; i++) { ver = vm_version(); - sprintf(message, "version = %d", ver); ckb_debug(message); + sprintf(message, "version = %d", ver); + ckb_debug(message); if (i > 16) { try_pause(); } From 0041ec14cf9cf75053572a2157dab7862cf13ee8 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Wed, 6 Mar 2024 12:39:58 +0800 Subject: [PATCH 012/135] Enable 2019/2021 test cases (#7) --- script/src/v2_syscalls.rs | 64 +++++++++++++++++++++++++++++----- script/src/verify/tests/mod.rs | 5 ++- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index f30e736dc3..b769fa5e35 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -504,14 +504,62 @@ impl< 2177 => self.debug(machine), // The syscall numbers here are picked intentionally to be different // than currently assigned syscall numbers for spawn calls - 2601 => self.spawn(machine), - 2602 => self.wait(machine), - 2603 => self.process_id(machine), - 2604 => self.pipe(machine), - 2605 => self.pipe_write(machine), - 2606 => self.pipe_read(machine), - 2607 => self.inherited_file_descriptors(machine), - 2608 => self.close(machine), + 2601 => { + if self.script_version >= ScriptVersion::V2 { + self.spawn(machine) + } else { + return Ok(false); + } + } + 2602 => { + if self.script_version >= ScriptVersion::V2 { + self.wait(machine) + } else { + return Ok(false); + } + } + 2603 => { + if self.script_version >= ScriptVersion::V2 { + self.process_id(machine) + } else { + return Ok(false); + } + } + 2604 => { + if self.script_version >= ScriptVersion::V2 { + self.pipe(machine) + } else { + return Ok(false); + } + } + 2605 => { + if self.script_version >= ScriptVersion::V2 { + self.pipe_write(machine) + } else { + return Ok(false); + } + } + 2606 => { + if self.script_version >= ScriptVersion::V2 { + self.pipe_read(machine) + } else { + return Ok(false); + } + } + 2607 => { + if self.script_version >= ScriptVersion::V2 { + self.inherited_file_descriptors(machine) + } else { + return Ok(false); + } + } + 2608 => { + if self.script_version >= ScriptVersion::V2 { + self.close(machine) + } else { + return Ok(false); + } + } _ => return Ok(false), }?; Ok(true) diff --git a/script/src/verify/tests/mod.rs b/script/src/verify/tests/mod.rs index 7e7a3bd428..9729a4f943 100644 --- a/script/src/verify/tests/mod.rs +++ b/script/src/verify/tests/mod.rs @@ -4,8 +4,7 @@ pub(crate) mod utils; -// TODO: enable again -// mod ckb_2019; -// mod ckb_2021; +mod ckb_2019; +mod ckb_2021; #[path = "ckb_latest/mod.rs"] mod ckb_2023; From e4d4aa4b27c6c781ccd5e55ac1e84d395129738e Mon Sep 17 00:00:00 2001 From: xjd Date: Wed, 6 Mar 2024 14:35:53 +0800 Subject: [PATCH 013/135] Add more spawn cases (#8) * Add more test cases * Add more test cases --- script/src/v2_syscalls.rs | 4 +- .../tests/ckb_latest/features_since_v2023.rs | 849 +++++------------- script/testdata/Makefile | 27 +- script/testdata/spawn_callee_current_cycles | Bin 0 -> 1416 bytes script/testdata/spawn_callee_current_cycles.c | 28 + script/testdata/spawn_callee_exec_callee | Bin 0 -> 1184 bytes script/testdata/spawn_callee_exec_callee.c | 3 + script/testdata/spawn_callee_exec_caller | Bin 0 -> 1208 bytes script/testdata/spawn_callee_exec_caller.c | 8 + script/testdata/spawn_callee_out_of_cycles | Bin 0 -> 1928 bytes script/testdata/spawn_callee_out_of_cycles.c | 10 + script/testdata/spawn_caller_current_cycles | Bin 0 -> 5552 bytes script/testdata/spawn_caller_current_cycles.c | 25 + script/testdata/spawn_caller_exec | Bin 0 -> 4648 bytes script/testdata/spawn_caller_exec.c | 4 + script/testdata/spawn_caller_out_of_cycles | Bin 0 -> 4656 bytes script/testdata/spawn_caller_out_of_cycles.c | 3 + .../testdata/spawn_caller_out_of_cycles_wrap | Bin 0 -> 4664 bytes .../spawn_caller_out_of_cycles_wrap.c | 2 + script/testdata/spawn_caller_strcat | Bin 5328 -> 5224 bytes script/testdata/spawn_caller_strcat.c | 3 - script/testdata/spawn_caller_strcat_wrap | Bin 0 -> 4656 bytes script/testdata/spawn_caller_strcat_wrap.c | 6 + script/testdata/spawn_recursive | Bin 0 -> 4648 bytes script/testdata/spawn_recursive.c | 4 + script/testdata/spawn_times | Bin 0 -> 4672 bytes script/testdata/spawn_times.c | 13 + script/testdata/utils.h | 37 + 28 files changed, 409 insertions(+), 617 deletions(-) create mode 100755 script/testdata/spawn_callee_current_cycles create mode 100644 script/testdata/spawn_callee_current_cycles.c create mode 100755 script/testdata/spawn_callee_exec_callee create mode 100644 script/testdata/spawn_callee_exec_callee.c create mode 100755 script/testdata/spawn_callee_exec_caller create mode 100644 script/testdata/spawn_callee_exec_caller.c create mode 100755 script/testdata/spawn_callee_out_of_cycles create mode 100644 script/testdata/spawn_callee_out_of_cycles.c create mode 100755 script/testdata/spawn_caller_current_cycles create mode 100644 script/testdata/spawn_caller_current_cycles.c create mode 100755 script/testdata/spawn_caller_exec create mode 100644 script/testdata/spawn_caller_exec.c create mode 100755 script/testdata/spawn_caller_out_of_cycles create mode 100644 script/testdata/spawn_caller_out_of_cycles.c create mode 100755 script/testdata/spawn_caller_out_of_cycles_wrap create mode 100644 script/testdata/spawn_caller_out_of_cycles_wrap.c create mode 100755 script/testdata/spawn_caller_strcat_wrap create mode 100644 script/testdata/spawn_caller_strcat_wrap.c create mode 100755 script/testdata/spawn_recursive create mode 100644 script/testdata/spawn_recursive.c create mode 100755 script/testdata/spawn_times create mode 100644 script/testdata/spawn_times.c 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 0000000000000000000000000000000000000000..a49bc961bb0c2967f2e1f45d8fde51e4a95a2251 GIT binary patch literal 1416 zcmb_c%}*0S6o1ogx8+2EASwqTkwnpKs2XF$#4WI0Oq7G@!HetevVl$dmE8g1A{4_% zJel;sfrDt$7(ID3@!(1ENc;~>H5xBqOu+bozS+)TS;dnt+4u2#zxQT3^QP0<#Y}_{ z5E6mUz@n#t22gq8l~i+BPK7g=RUr;?z>0CsZwB*fJuTi^SV-1bi)Ok>e!C88tb4Jf z5shR@8KRf;a$;rLM@l1XG`<;KUf6OU+<3MSC#36SCrYY|)8l-uL-kCut8#)|%UzBFimSd9{`qDe3J z!E##{Ji52M)CTQ|IP}iFR|R)Yu5P^8wr?k3cBVJ>MV+0IGObY2%W^9SPHC|Eef2BR z{+6r0Tiu=;G@tAJ{bxIl=tEbJcBE2DO6h@gH*V8&eR~2(2fEQ@%$qoU$~{r+F>*|q zOxdU~`45rsj3@ay*V813)Q3C11pE?rklHOp;nUALC~yyb2U)N`$I>adCbAJUFZ*p14(nK=JR9)ILknDB&kVuIC&M^?Q1W>Ls3<1!JJ zJqeu7VgS}D$_dBnFy@Ln0kb%~Cze~`#4&E!e---@EQzweW}pG>pRWUX9K6MO!i3jv Q+M|A+*Pj!G+=lCa0iVCR3IG5A literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..e7e344be7a0ba450494a290bfa21e3384559e21a GIT binary patch literal 1184 zcmb_bO>5gg5FPm=A2&6pkc47G4sIGm96~7}6g#$TT8dL}+e;72T3HeWOLnBK>p&oJ z|AN8osgPTKPLDnIAGD?Sy0g+ONw%0?vO@c2-+MFKl|~ot%SOhsK#vUk2DLg*W`GI_ z-!o~TvrexpAl{tvMl0BiQ6}KVE(+0*psjql~)=R^!Ld>7Vh!*L;kI zX05hcC^cJe9u>-Er|fJ&bpz?hkG%m{1q^d`J{mmP@wfY1EKn0ylZO+E{~1}_+mQBm z+nNPBdf{CHe+9;$5#eOQE{xKE^5*QD1D1is|<|r1e8W4Q2-wQBe72Tk8K|NhcEO z?$D^(9=oq^*x;Io$A+NuG_BU=o|N{D46i6b{ln^BAby!}5%J&d2Pjd|0r@nT&wnr@ N{|n{s=|n;^|1ZY+Zyo>u literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..671dd0acd25979155e36edcde192da496095fae5 GIT binary patch literal 1208 zcmb_cO>fgc5FIB?Nl!IBRlp&YIPfK_L8w9qp`@*2flxpS<-%dLaaZ6fc7na6>7h!) zol}rF^9Q1yIP(+uCj@cff?&p;744#k3uAfT?3*{UyY|>)|8cA2IAE*<-+^ZD^AVuI zfgh#9p;!a%VzdDlU^!P+So23gUQu(#F@xY1#ESpUcUqH{6HJ0>^>myey$bWyx>F z9hkZ2`6tM);a<#pxWow$Sbu8iA1$c!oa>l#(LTst;O%04d);rh&QLJSbQKtpIGM-i=4PMxfW0jzj_l766PNVJ{t*DFshh4@Z z^v0ICn0dYf?zk!PmS!cjr|KfuDPn>_>Br@9hzX7^_cZUD~ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3b2f6684d2d1739312fad545a995e77c09f9dbc1 GIT binary patch literal 1928 zcmbtVeM}o=7=N#&EfA*&kqs{UkStTDR$$10YF8Mn5m}dkGBdN?+M|?0DbOC=j%*ne zt`%6fKdLP8%t#vDls}fZm=V&5N*ubx5aY++V=XYKd~{tI9D?V2*Slq7!+(5}dwtV!;TA^uCr2?O zh6k0=>V@OslhdZ)^m>?GSjt}+nUu{8MlQQ(J<}xv_{C@@ z;_b%_uvM}yZj_C@*?0nuE6C*RSNdF4zl>@xv{tJxj zK8IfXos-4F7x1p=cBXHf^O1|3#{0L9>0aPE57)cV?gW6lV$Y%87{~Pd!F5)I-FVM~ z3{>^Guv41kWgVJ0$)Q_*6T0;Vn?`Mir`Ll}Z);R9 zA#4Fvz`hwuA6({7Z+L*p3!I1Ce6}$3%f)C~3OXw3a?6=6sF$di@ zJYcd2k#j+k-LGBqLymSbbQ7B%B~6wqkP+y*3q~O);30u_W|U{GT!A@`1>KGZ`WvTE zPmp7ofNEJ+Vo9%w5&_p;P)S{&MO{ZIgYI}W%*3W-S>%WG0 zbja1AKX|Zc*UNgt`>*WE$x-L1vqAA*Sa=Sr6K?~^E+{6XC>(A1dDh(KY^;%=jQoVd z2|E9C$YB?r7W?&4q8!K`RUgW7AU5Sg3lO3cz&-8}lOXPZa|*QAp;BMR8T_JBU{qb& zK{gD}`3-`#=_!XPv`9RDgeHS6-Ik5@fwuznZ?x(%?G_>>UREl?>N!luB zvyrr8xY1@ao3W-=0&A+pa0<7XooXCln8ns)GTN}_Caaw=J9a}$RcY~i#aKz1{v88` zLA|7^3M(^|3bM)R#GHiDL4Zc1)efDHbImnI!U!<4y#~};O#rB!R3l+DK_nb;tdk_d ze3}4iys5F#Y=?qSH)1pW7LcC&9+|Kfg)*c`^PiDNw|X@&5u^)a~;C literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d22c5283b0d07fb543e34530f29d229abed1b5b2 GIT binary patch literal 5552 zcmbtYeOOahnm_j@_udc!M6Ts4qKMcTZHM)%*upduK#1DPbnUd=b+%2zAw(1rLV!kb zN&-oQ1exu%Qa4&1I-=#->DJ=M3WJW$qFW!wXIj^f`aErsi-;5jRyMLP4> zoaedsyyy3RocFx%dC&cLH|ynWk|2Q4Nbo(tquZeYOci7lvjGC5D)2lY(LDr6{IXO~ z=CK5(0{X6q04nrA{#c3*kb%2AAPo%-6ueZKb_G>8HK`CmzK5qQJPf-&K(n7o{^O{8K5Rj*tR(*VcS0o``EI4w=`$Bu& z8-yv9Z!DOq)pPcn%~Td__yIH*)5hMs?1JV3dQ10?jGaw8by`c6Rek;(k!8*zvd!6q z+N|azhuM5j(cQ-HHty;3XLMfRY%666wV7L_IKBL{}SD@)2w!?GLTv-cNO z9RZdqOI2)1OHT9XW%t#AFZ*uv*e07MZg;&knLCj`DqY`FlU(~*?WsD>7p{WQOyrn@ zo1UJA2O}c6v2fCy!BKJ=a&#n-DRnH)`sz700+0(2Ln$vxvA32pB6fN#LP3X%()M%` z>~E$cVBU4W{$?zK61CD>!AA`jeXXxEBK{p_ihGz0;O@|H*g(d>{Si?xUNkpd4XM7R zA!yV^EgIC)-|%sUrAQXf<;yLrnzY)fbWIJvGb%P`)@K5R@TI> zlsQ#72XY*nY&UFF=w&NQ0n)OUk9GLEov~M>j>H44j01=|$9*elr|O1n*WAn2Zl`7M zwozCeN|JG{wLed1H%Uo2xsJ%USwn8v0yeBNWTkJNueUhc*leUty#?7@nzztfyLV<( z=3AR8Lr{)ze7KQt0!N59(}SoN-|yfaJ_CqM{!r+MIfKaL_DRTcJNIxtFuw;ENTsms z8j03PLV_oy4weQY4tX4V7>2Y0O0<$e5sSDq%@f>NV= zMWz?cT1QT@BBW=Jn9!cfacWOu9U)JAQO(^Pr?rC{&jIE3_jzu75BQ1?bHvq{zRhv| zu7iK)+BbfCG5jF%|C^3;Lhe6(l>0d+{Sq`kCUwNQDA5bYcBLLU$1>mh_z33q`E1DC zl1Lr3*{Lo*`ql``B+!e%cVOW;c08PnzvtJL@FM|TmZ@Se_d$m+5Arp*$4c7$vLx?j z(f*S*aȼ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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..dffd1dd7150ca2bcb9ba651b575b1e547f019ea6 GIT binary patch literal 4648 zcmbVQ4^UG_8sGO`-rEoYi9F?Bz#>AgYLC&{qj$Dt2uPx~GQIP>-ZOvl4cv?UFXhx1IosUAK`X1 zMIt2Hxf{4weA6S`T?D9Hac|^pdk&Q=yr!f#x`n%Qfqf@>K&3)8=V-i68c`yx^6(sB z1nhCbJ`~{tEVC5ih-uCQMC-YL*c>^`$Es**C#v}%q@(g+S%$0-%@KihA5y%jly!~< z#Dot5_NT;M^z|nXl3DS5_M&J$4qFhAx>$`Pts08Pkya0>LLLB-PIL<#q_@4sGjSjk z{f5B+;fY#tC=~7HXgc4^D**jm4{DB7e0FV#M}JMMIX5Orjf%Cockry+=t-WzdTz~x z`DDJ=+(mTcJc(tEU*~(BJ;HcC*yw&$6vnrMFT^NMVq@Kx`QE?vh?~w`4cUtqZ(#qg z_MDV+|IQD&pVbwT;KVVNC$WuXesgg1vi&D{_Q~)U26Oc`$V{ew)BMOBy>#|*%@{Gl>nJ<*%tlD%E|}7TlG!;*H=gTM>v1# zt>1lhVe<0C;PCaK8w0rd8jpCEc{`g>1Dnb8Mgse4#ITvCi>Klq)5UPKy_Yo{aj?wQf%mC1%F#;X>ppQtig9a$)bi5?GUnYn&<5FnFg~t9gJWPD{Jdp% zuEUM7DT3`cApcmR0Qb?%IZrU(66u?NpA9;H%GoaI8WW#e5?m0uBE~m z62r$M zN3vO1bDWG3*ZUy0p`_A!eaw?;AV4q3n%H890+~*11|PXmbrRL@)_EZiYSTd0B=W*k)WpT2CiPrLyl_cL`@H|a zF-7)|X%cN-5epoxK6qGvy@lz;-m2KSsV-6YI561UUyF9bn4J1Aj*Lu!6@K5xAGRZa31NPYLbk9Z*|`c>;Wy z3yq;)E5K|HF}SZ)q@=phE|`KTEoy_QLM>FF7MQ}j&gERhI={CwiQmv*%K?q14lf(I~F((k&KWGHAM>l91jYYCUSif z6F5ht=9>=jElP6QZ{w0S$60%vMl@BNEL9q=JG-znaum$k$13FA2*-Ot{1atQ0#OZ}_JlZafQ*!NS{GH83-l-Ee zyhWk24xb%rpZh&2zcv1JQbFo_d)0ZOy*Z&LB9yb$I74DG9C)jz4JHA!xg?6L;c>59 zPbZP@266_a?j~_CjNFTaqt&sgy;+QH43hn-Q|s`a6<_Br<}!ET_8cB8O0erq-U zkko(?P5%oyg*nc2e2TWr0zk0qKc({?#*#Nj$}bDbPgx@OT;caHXsWPQSjfsqL*|l_6!c<22*l$W zo3*4mV?D4`Rh3tzm~AQP)yvWgA5IC6QF);yCA|vYyC7xBl8hx8i-CS2 zR<5#Eqm6({!K6aVR&C6D)cQ!pVpA!3naK;`7iRuUWAGj09qFDiT@-(+fm4yvePSAe z0Sx%j{Q~nDAYU@335W3eZ#INWtSZ2*AfczXIe0*0?h(l!>DmM4N%;E`PD@IQB>Y1O zZ@{jRmWdx?XC`it@Z~tyq&+WPo_>pIYWljQrL4ku4Cb^;_qcUL3AbnQqb2^w-ya`q z2*=*dxPNWKII$z&2NUs_v^xA~$-J}gx8s!Y8FpU5II$z=OTPQP7Lxz*y!(H`&f79R zW8OoO{a7jQ9e5mS)fML2G85UpmMW8FlLciUU@EV%nF?x(iY!%Ox~!(81enTf>AgvU8+ z)|m40mxt(r>S|n4<|-Q~HCxLt^L|-Nq1k2zCQDf%sJ50?l;HX!ZUc}}T~}%|7vSDj z74Fx|l+Ciq1~RJ3L#i2g0+4~qOG|MfW0VwFhS_GTvKG|Xekfu&CjUpT!#X6>a^B=T zz9ZREN8WE#-sdtp4--UR#^w4vCF#8(3rf9m#&`i96HF?Td;3)SUtnel&(zPrx@7*D z$BO*FL=5IlZ$y?fxql4Pct o6CvCp@bkmkLrD157ai_TOv4B{bAJ3&_doUDkp9 +#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 0000000000000000000000000000000000000000..a702a7757742198f6b4d1bc14dbdd48e9702812f GIT binary patch literal 4656 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..376bcc8adacd3c9f86b48dfdd086c6bd6da18779 GIT binary patch literal 4664 zcmbVQ4^UG_8sGO`-rEoYi9E}HEh6-)_BgFQd$lb?KoV^$(>d$4<6N7DO+YM!e?jDm zJrYSGCTP!Riws&ldZJ}|Gqn*tv52;%-Z}QBt>>RQqoq8G)KW!D07pn}H+iojy-sIt zXWrXyf8U?|_WSnRyv?6;pV8A41>{D99{?FmsKQv5#2D9v34&&U-vJuGBY-j_%StkL zB?uMPe@Pui zZRGUuzlXjUJm2q{XdS=Q`_e@Ic)^J3srLGehW8r|ZxMpgStt(1jCzDXAb@sjVuaCX z+MX@2S`GxWR|#n>mkDjMm0%XH1qh@9*Tc0ph4zyfPZaN z!!kbZ74Y`9PlCQbKt|jECxts10Bw$pM%(Ck)U1g`vzVDW17Zi~M;H(__z({PGZ%af z*c{}6$pU2PEloW9jOGAOtc2+8&+AC#z`wk7^p#)+a1hd$aO(<$2b)&b!#i z(@vfRv}1>u;0gA56V9kSsk?m81DKw%;9}03b>6jc=4of2*Ri8y1Z|3>=|o?{6FPp4 zibfMFr~;QW;=C(t!>Ptr23G_J%JjB28&@+>q+i#zj(er=)$G~=XKQVQ$x%n*BixFn zNQ6W?cOCbNZ@Yv$3jmcP?uoo*&!%#OH8LzdmLV%d_lclrFH*d%ly!~- z#DtFm_NT=i^tC4skXiA3_JU|W4qFhAx=@WHts0ERkya0?LLLB-PIL<#q_@1uGjSjk z{knkw;fY#tFcj^^Xgbf!D**js7ix@De13J2M|V}MIy)*!jfmAbxACl7=n0;|dT!0Q zsXNbW>L5CDo)8J* zUEOl--}^E5Gde;NoH(lTB(|{3V+S@a-Pg^-AA+I=UOK5q@S;-XY0xii5#ui2;$aFm z7kmfibn|1;^sK8PU8Q&{tjohXNVwm3$@5@er9D=DEF?>d!#v)9swRP}W9Nbk0hYPh zL2M;pTSOc0Qp4xiC&DGPr7Juqp{qK`&Zyxp2grO&H|e^|%OCjusc-YXxiZo>%=uGq z{{HLp6PLyZhOP}>@5j|wf7r9s+unfc*d33Pl>XUhaDTJ_>o}zFr(#(S zCHY@qdXfNdR%od-%z=U@7Kq>N9~Iz24qe-?CJ{iIZ}ceMuZ`F&sJ#Gb6ib*~HE45L zvA>RHr-84Z1yHbXRSWzs=!oOD{uig5phsrnH1bq8J}6oLO1Sy`t?ys>{U3HID}8hlMxL4M)wZD=<+ zlNLf8j~D?0D9-i|FpsKnJZ91-4OE)dmD!uxuUl?6klf@sZw!BRV2--I@n{!HTup^D z#9;dRTb!7>Owvkr+N6 zIh@79s$*n~xSj{F4JDP<<71vw0|9zL=J+Ok6jPK!C&C98w41$(>Z%yyZO3h`_zhb-I!ETuNv^Z-d$z%oE`2 zTxbmaS^;Kph{1ieA|=(0cEA)&X;BMI6{?{EHNh0V8Y&SD(-<7h*6NMh=s2q@wSP^o z-9QOcd%B^e=|P;|ILgUM8Sddg%Vsz!XHP5}3mo?F?pWYFNHRh))DS8Bb1W!a9MAEM zkK-JXnr}GBHz~O}0t@UD6@%Jt8PVku9t#icL1%B%+;A=cZ{j^%MYj+O4{9FLX@W0YJw8h?9Zfp_xw zb#FoFtixxA+UNd2%5RlFom7ze?p}2sZ*5HIiU{RwCC-pI3--U$)dG_N+E^S#*6_I3 zt)r94cLOoALG2_To zt;=0FM!Il}dOE0QK0QeG&*#2YZ2$5htLJD(ruS%fr)R~XS>>sNJY%PG%}XZQT{=s~ z$iw5Ey#lKMiEjLbk;Su?NN(tO|0hEq4kq^B7&bOJ*UsN;&*iZMrMK%TgWVu(j^A8~ zKO{9^Skw1%wmI9Gj!)6182|`&-Dh;}Ls;_0aOovM`58;(UM!z{{%z(acmiaOBrDmq znd46=GbddAt-W+VJxCAH!;QJbcDxqbR_<(-Z6_&M5H*->5!iA-Va|bjIIS-1FG~$E zigIvYf7{EcPR?w?eh|D@(PPQA2u|lmJj;HJPuJnQe8M3zT6PNmde0H^WqgIDz-dMJ z`Og$u#_s7Q{)s7ahcQi>#cH!u6j=*XP=&>0vluIFW@A}VnT4#3G-N6+PC>8ahd?~8 zvK19qW~>F4ii*;T6q79_y>e-~`Jt5X7?qkWDd}cl$jMon@}MDa^}Liti!v5vECjmw zSh=F860HYR3MLg=wqpH~M~WUUTWBmHFB5qo{KCv%Xbiq%yeHi=ri$WEHE<$Qx=&1D zFn|F+xnE#D1LRA_6yXql@6CpAiB$!-86@=7HWv?Q%snjmBVBvIZzTLf38y8c$0Yn? z39rMhk+uv!#Ljg5ISF5eb4}Vy(&fpBX=>`aq@}!o@fgf$mF{tCh!SoV{Ah{)@%P53 zI)r2Irrp1GVw~8K?}LeWOqv@%S~Bm~o!9p>b~SD4B&5D209RRsl>iZE@h zDlP^_tF6>zEH1ScP9df7`bujVE*4t>z-k$bfYDf3T$*nxHkOrQ)KZa#kyXod&*_ZW zxrP;aMk5|)uUciy&07|t^D8THftf07pu|*U#mswUEoPI=1dJA|8B`XPlojJ@B#Qtb zqq3&NX3EFCts>m7l_{HLgAHU zeG=9pnV0h@=k-0wnmY1cv+}-|(K(nP`Z6xp>j_EkEm=_NmD9%a@R(py+1%Z?(*Fe0 zOM1F~2G%9>Pd{el|0!ZHZ)zj5q{;oGn8tILg}^DVGO6$vOu+~#>&Y+~%WIc0((je@ yvm_?OSQLI_|Ko`eZV~wTaqS@_{OXMk_h+VHgq%J<{^|Rl`tM5r^Q`y<{r>{(>i(+$ literal 0 HcmV?d00001 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 98358ec114504fca3a0940bb7cc72a152512d044..57a356128f540dcdd36522ba9716ebb95f3c9e43 100755 GIT binary patch delta 622 zcmcbh`9foYgy0DtMg|aY0Fw+18WT0mIm`GUyt0Xz?jA?eg&7&QPi|*_YWL=7`sDWZ zr#ccE0?HY7(}Sib?->jnLLYXz?|WgxvG0uyLu<;u z4>l6}zDyQl)MEOeKG}&;h0F9o?@^Fh>`x{aFv>GZOrF3frE2MRG}SeAax3dIVOG{h z?->GgZ|+~zR_gY4`=Yj3x2r%h*X`%#i;TCJ8E1HNZ z9R^0X_aD~poy>88wHWAy*g~%#TAi+`!mO?L+McNW@%yr_CFsMV2d-J~KiGd4X6W3~@#4L$E78)W3bWpMl{P8zaLpRtUa;#D1xObcB$nsJCnx6Qq!z^&mlP!@mgprMfy$5Q-Tp%q3G~vYLg97f1^Coi&$}=);))YL>$oq~5ss=<&78DVlEFdf(w15}l zgay11*=r1wjfBe>%OL)oCw zL)m7c+k1uyHb>JZx3j;rd*hl4Vzs{ns(EGif$0g;7p5Off0`aNJ$cVyV5K9WA@H8z zgG21oPWOE;Y&iA-)!Q)a`v6q^)<$CAm)4Z`3>VBN{?K9)(3q^ksFJPtruQh==w~w| z_Dz*skleSOf%zCaL$ez@Ln}Kg`(uu4|EyWAIV8(nV`>IEN2!(Bgwdnfq|qJdP|v0Y zt(H}7j&4U&T~jBww!Q{h19V1#?#=y++A7`NZeP@v>2?)J3bQdVecZf}@fI`Voy|S0 z&diLmn=f!21X7bH@z|PfWOCJEV03%`Vg2sO92Z!NfdLX*==DRZ6Brz5HB$78TNKGeT`xSxUH7aJqP zGgb)xfW(H0q0mtIJ4os-O@7Fm&sJQLSX81gSx`_|TR~4x59q>-)SR4rAYGncl#>Fa zlZ#RlOH$*DOH$$sG7D0RLCPlc3Q7qwFhDdH7bKSFfkjLCVkckWlVLnC`6FMsSdzg4D*IsaMt*U|gvlrQ^%?sn|KxX_l(HXjr?&d9{aJGo0pPv`(t#{pi576r!1r-aHF nA53->wrBh_xl!1jNr8XzAz?eliph*3_MFZ_5OtoDJB8%|Jptmy 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 0000000000000000000000000000000000000000..7f49a82ec041a6343f9f3f438e89ac221e28bd01 GIT binary patch literal 4656 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 +#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 0000000000000000000000000000000000000000..4e5934da7594d08159b227cd1e9a5a6fc17ba08b GIT binary patch literal 4648 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 G{r> +#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; +} From da968bef2122f620a3cb1284ab518a0b93a02436 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Wed, 6 Mar 2024 15:12:43 +0800 Subject: [PATCH 014/135] Enable 2019/2021 test cases (#9) --- script/src/verify/tests/ckb_latest/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/script/src/verify/tests/ckb_latest/mod.rs b/script/src/verify/tests/ckb_latest/mod.rs index b42cbd2426..ef6ddd5e75 100644 --- a/script/src/verify/tests/ckb_latest/mod.rs +++ b/script/src/verify/tests/ckb_latest/mod.rs @@ -1,6 +1,5 @@ const SCRIPT_VERSION: crate::ScriptVersion = crate::ScriptVersion::latest(); -// TODO: enable it again -// mod features_since_v2019; -// mod features_since_v2021; +mod features_since_v2019; +mod features_since_v2021; mod features_since_v2023; From af11e3124a31b118795c021eb84fda8db6dc5e6d Mon Sep 17 00:00:00 2001 From: Mohanson Date: Thu, 7 Mar 2024 11:11:38 +0800 Subject: [PATCH 015/135] Rewrite some syscalls (#10) * Rewrite current_cycles * Rewrite process_id * Rewrite pipe * Rewrite wait * Rewrite read/write * Rewrite inherited_fd * Rewrite close --- script/src/syscalls/close.rs | 37 +++ script/src/syscalls/current_cycles.rs | 7 +- script/src/syscalls/inherited_fd.rs | 46 ++++ script/src/syscalls/mod.rs | 25 +- script/src/syscalls/pipe.rs | 44 ++++ script/src/syscalls/process_id.rs | 30 +++ script/src/syscalls/read.rs | 62 +++++ script/src/syscalls/spawn.rs | 5 +- .../syscalls/tests/vm_latest/syscalls_2.rs | 2 +- script/src/syscalls/wait.rs | 44 ++++ script/src/syscalls/write.rs | 62 +++++ script/src/v2_scheduler.rs | 23 +- script/src/v2_syscalls.rs | 229 +----------------- script/src/verify.rs | 95 ++++++-- 14 files changed, 447 insertions(+), 264 deletions(-) create mode 100644 script/src/syscalls/close.rs create mode 100644 script/src/syscalls/inherited_fd.rs create mode 100644 script/src/syscalls/pipe.rs create mode 100644 script/src/syscalls/process_id.rs create mode 100644 script/src/syscalls/read.rs create mode 100644 script/src/syscalls/wait.rs create mode 100644 script/src/syscalls/write.rs diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs new file mode 100644 index 0000000000..b797736202 --- /dev/null +++ b/script/src/syscalls/close.rs @@ -0,0 +1,37 @@ +use crate::syscalls::CLOSE; +use crate::v2_types::{Message, PipeId, VmId}; +use ckb_vm::{ + registers::{A0, A7}, + Error as VMError, Register, SupportMachine, Syscalls, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct Close { + id: VmId, + message_box: Arc>>, +} + +impl Close { + pub fn new(id: VmId, message_box: Arc>>) -> Self { + Self { id, message_box } + } +} + +impl Syscalls for Close { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != CLOSE { + return Ok(false); + } + let pipe = PipeId(machine.registers()[A0].to_u64()); + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::Close(self.id, pipe)); + Err(VMError::External("YIELD".to_string())) + } +} diff --git a/script/src/syscalls/current_cycles.rs b/script/src/syscalls/current_cycles.rs index dc87cd281c..a791cef7a4 100644 --- a/script/src/syscalls/current_cycles.rs +++ b/script/src/syscalls/current_cycles.rs @@ -3,14 +3,15 @@ use ckb_vm::{ registers::{A0, A7}, Error as VMError, Register, SupportMachine, Syscalls, }; +use std::sync::{Arc, Mutex}; #[derive(Debug, Default)] pub struct CurrentCycles { - base: u64, + base: Arc>, } impl CurrentCycles { - pub fn new(base: u64) -> Self { + pub fn new(base: Arc>) -> Self { Self { base } } } @@ -26,6 +27,8 @@ impl Syscalls for CurrentCycles { } let cycles = self .base + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? .checked_add(machine.cycles()) .ok_or(VMError::CyclesOverflow)?; machine.set_register(A0, Mac::REG::from_u64(cycles)); diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs new file mode 100644 index 0000000000..b9c79ca15d --- /dev/null +++ b/script/src/syscalls/inherited_fd.rs @@ -0,0 +1,46 @@ +use crate::syscalls::INHERITED_FD; +use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; +use ckb_vm::{ + registers::{A0, A1, A7}, + Error as VMError, Register, SupportMachine, Syscalls, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct InheritedFd { + id: VmId, + message_box: Arc>>, +} + +impl InheritedFd { + pub fn new(id: VmId, message_box: Arc>>) -> Self { + Self { id, message_box } + } +} + +impl Syscalls for InheritedFd { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != INHERITED_FD { + return Ok(false); + } + let buffer_addr = machine.registers()[A0].to_u64(); + let length_addr = machine.registers()[A1].to_u64(); + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::InheritedFileDescriptor( + self.id, + PipeIoArgs { + pipe: PipeId(0), + length: 0, + buffer_addr, + length_addr, + }, + )); + Err(VMError::External("YIELD".to_string())) + } +} diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index ed0f5fc839..0bdfdbf4be 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -1,8 +1,10 @@ +mod close; mod current_cycles; mod current_memory; mod debugger; mod exec; mod get_memory_limit; +mod inherited_fd; mod load_block_extension; mod load_cell; mod load_cell_data; @@ -12,10 +14,15 @@ mod load_script; mod load_script_hash; mod load_tx; mod load_witness; +mod pipe; +mod process_id; +mod read; mod set_content; pub(crate) mod spawn; mod utils; mod vm_version; +mod wait; +mod write; #[cfg(test)] mod pause; @@ -23,11 +30,13 @@ mod pause; #[cfg(test)] mod tests; +pub use self::close::Close; pub use self::current_cycles::CurrentCycles; pub use self::current_memory::CurrentMemory; pub use self::debugger::Debugger; pub use self::exec::Exec; pub use self::get_memory_limit::GetMemoryLimit; +pub use self::inherited_fd::InheritedFd; pub use self::load_block_extension::LoadBlockExtension; pub use self::load_cell::LoadCell; pub use self::load_cell_data::LoadCellData; @@ -37,9 +46,14 @@ pub use self::load_script::LoadScript; pub use self::load_script_hash::LoadScriptHash; pub use self::load_tx::LoadTx; pub use self::load_witness::LoadWitness; +pub use self::pipe::Pipe; +pub use self::process_id::ProcessID; +pub use self::read::Read; pub use self::set_content::SetContent; pub use self::spawn::Spawn; pub use self::vm_version::VMVersion; +pub use self::wait::Wait; +pub use self::write::Write; #[cfg(test)] pub use self::pause::Pause; @@ -75,10 +89,17 @@ pub const LOAD_HEADER_BY_FIELD_SYSCALL_NUMBER: u64 = 2082; pub const LOAD_INPUT_BY_FIELD_SYSCALL_NUMBER: u64 = 2083; pub const LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER: u64 = 2091; pub const LOAD_CELL_DATA_SYSCALL_NUMBER: u64 = 2092; -pub const SPAWN: u64 = 2101; +pub const LOAD_BLOCK_EXTENSION: u64 = 2104; +pub const SPAWN: u64 = 2601; +pub const WAIT: u64 = 2602; +pub const PROCESS_ID: u64 = 2603; +pub const PIPE: u64 = 2604; +pub const WRITE: u64 = 2605; +pub const READ: u64 = 2606; +pub const INHERITED_FD: u64 = 2607; +pub const CLOSE: u64 = 2608; pub const GET_MEMORY_LIMIT: u64 = 2102; pub const SET_CONTENT: u64 = 2103; -pub const LOAD_BLOCK_EXTENSION: u64 = 2104; pub const CURRENT_MEMORY: u64 = 2105; pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; #[cfg(test)] diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs new file mode 100644 index 0000000000..07c508b0b4 --- /dev/null +++ b/script/src/syscalls/pipe.rs @@ -0,0 +1,44 @@ +use crate::syscalls::PIPE; +use crate::v2_types::{Message, PipeArgs, VmId}; +use ckb_vm::{ + registers::{A0, A7}, + Error as VMError, Register, SupportMachine, Syscalls, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct Pipe { + id: VmId, + message_box: Arc>>, +} + +impl Pipe { + pub fn new(id: VmId, message_box: Arc>>) -> Self { + Self { id, message_box } + } +} + +impl Syscalls for Pipe { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != PIPE { + return Ok(false); + } + let pipe1_addr = machine.registers()[A0].to_u64(); + let pipe2_addr = pipe1_addr.wrapping_add(8); + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::Pipe( + self.id, + PipeArgs { + pipe1_addr, + pipe2_addr, + }, + )); + Err(VMError::External("YIELD".to_string())) + } +} diff --git a/script/src/syscalls/process_id.rs b/script/src/syscalls/process_id.rs new file mode 100644 index 0000000000..55114ae18a --- /dev/null +++ b/script/src/syscalls/process_id.rs @@ -0,0 +1,30 @@ +use crate::syscalls::PROCESS_ID; +use ckb_vm::{ + registers::{A0, A7}, + Error as VMError, Register, SupportMachine, Syscalls, +}; + +#[derive(Debug, Default)] +pub struct ProcessID { + id: u64, +} + +impl ProcessID { + pub fn new(id: u64) -> Self { + Self { id } + } +} + +impl Syscalls for ProcessID { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != PROCESS_ID { + return Ok(false); + } + machine.set_register(A0, Mac::REG::from_u64(self.id)); + Ok(true) + } +} diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs new file mode 100644 index 0000000000..90ce16e793 --- /dev/null +++ b/script/src/syscalls/read.rs @@ -0,0 +1,62 @@ +use crate::cost_model::transferred_byte_cycles; +use crate::syscalls::READ; +use crate::v2_syscalls::INVALID_PIPE; +use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; +use ckb_vm::{ + registers::{A0, A1, A2, A7}, + Error as VMError, Memory, Register, SupportMachine, Syscalls, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct Read { + id: VmId, + message_box: Arc>>, +} + +impl Read { + pub fn new(id: VmId, message_box: Arc>>) -> Self { + Self { id, message_box } + } +} + +impl Syscalls for Read { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != READ { + return Ok(false); + } + let pipe = PipeId(machine.registers()[A0].to_u64()); + let buffer_addr = machine.registers()[A1].to_u64(); + let length_addr = machine.registers()[A2].to_u64(); + let length = machine + .memory_mut() + .load64(&Mac::REG::from_u64(length_addr))? + .to_u64(); + + // We can only do basic checks here, when the message is actually processed, + // more complete checks will be performed. + // We will also leave to the actual write operation to test memory permissions. + if !pipe.is_read() { + machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); + return Ok(true); + } + machine.add_cycles_no_checking(transferred_byte_cycles(length))?; + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::PipeRead( + self.id, + PipeIoArgs { + pipe, + length, + buffer_addr, + length_addr, + }, + )); + Err(VMError::External("YIELD".to_string())) + } +} diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 9b7fee0298..ad903e81b8 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -291,9 +291,8 @@ pub fn build_child_machine< let machine_builder = machine_syscalls .into_iter() .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); - let machine_builder = machine_builder.syscall(Box::new( - syscalls_generator.build_current_cycles(*cycles_base), - )); + let machine_builder = + machine_builder.syscall(Box::new(syscalls_generator.build_current_cycles())); let machine_builder = machine_builder.syscall(Box::new( syscalls_generator.build_get_memory_limit(*callee_memory_limit), )); diff --git a/script/src/syscalls/tests/vm_latest/syscalls_2.rs b/script/src/syscalls/tests/vm_latest/syscalls_2.rs index 372b0377d3..bcc7ed5704 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_2.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_2.rs @@ -53,7 +53,7 @@ fn test_current_cycles() { machine.set_cycles(cycles); - let result = CurrentCycles::new(0).ecall(&mut machine); + let result = CurrentCycles::new(Arc::new(Mutex::new(0))).ecall(&mut machine); assert!(result.unwrap()); assert_eq!(machine.registers()[A0], cycles); diff --git a/script/src/syscalls/wait.rs b/script/src/syscalls/wait.rs new file mode 100644 index 0000000000..f2b4dc74b6 --- /dev/null +++ b/script/src/syscalls/wait.rs @@ -0,0 +1,44 @@ +use crate::syscalls::WAIT; +use crate::v2_types::{Message, VmId, WaitArgs}; +use ckb_vm::{ + registers::{A0, A1, A7}, + Error as VMError, Register, SupportMachine, Syscalls, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct Wait { + id: VmId, + message_box: Arc>>, +} + +impl Wait { + pub fn new(id: VmId, message_box: Arc>>) -> Self { + Self { id, message_box } + } +} + +impl Syscalls for Wait { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != WAIT { + return Ok(false); + } + let target_id = machine.registers()[A0].to_u64(); + let exit_code_addr = machine.registers()[A1].to_u64(); + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::Wait( + self.id, + WaitArgs { + target_id, + exit_code_addr, + }, + )); + Err(VMError::External("YIELD".to_string())) + } +} diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs new file mode 100644 index 0000000000..19ec918469 --- /dev/null +++ b/script/src/syscalls/write.rs @@ -0,0 +1,62 @@ +use crate::cost_model::transferred_byte_cycles; +use crate::syscalls::WRITE; +use crate::v2_syscalls::INVALID_PIPE; +use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; +use ckb_vm::{ + registers::{A0, A1, A2, A7}, + Error as VMError, Memory, Register, SupportMachine, Syscalls, +}; +use std::sync::{Arc, Mutex}; + +#[derive(Debug)] +pub struct Write { + id: VmId, + message_box: Arc>>, +} + +impl Write { + pub fn new(id: VmId, message_box: Arc>>) -> Self { + Self { id, message_box } + } +} + +impl Syscalls for Write { + fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { + Ok(()) + } + + fn ecall(&mut self, machine: &mut Mac) -> Result { + if machine.registers()[A7].to_u64() != WRITE { + return Ok(false); + } + let pipe = PipeId(machine.registers()[A0].to_u64()); + let buffer_addr = machine.registers()[A1].to_u64(); + let length_addr = machine.registers()[A2].to_u64(); + let length = machine + .memory_mut() + .load64(&Mac::REG::from_u64(length_addr))? + .to_u64(); + + // We can only do basic checks here, when the message is actually processed, + // more complete checks will be performed. + // We will also leave to the actual write operation to test memory permissions. + if !pipe.is_write() { + machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); + return Ok(true); + } + machine.add_cycles_no_checking(transferred_byte_cycles(length))?; + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::PipeWrite( + self.id, + PipeIoArgs { + pipe, + length, + buffer_addr, + length_addr, + }, + )); + Err(VMError::External("YIELD".to_string())) + } +} diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index afc9865076..3e3745f69f 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -52,7 +52,7 @@ pub struct Scheduler< // implementation is strictly tied to TransactionScriptsVerifier, we // are using it here to save some extra code. script_version: ScriptVersion, - syscalls: TransactionScriptsSyscallsGenerator

, + syscalls_generator: TransactionScriptsSyscallsGenerator
, total_cycles: Cycle, next_vm_id: VmId, @@ -76,12 +76,13 @@ impl, script_version: ScriptVersion, - syscalls: TransactionScriptsSyscallsGenerator
, + syscalls_generator: TransactionScriptsSyscallsGenerator
, ) -> Self { + let message_box = syscalls_generator.message_box.clone(); Self { tx_data, script_version, - syscalls, + syscalls_generator, total_cycles: 0, next_vm_id: FIRST_VM_ID, next_pipe_slot: FIRST_PIPE_SLOT, @@ -90,7 +91,7 @@ impl, script_version: ScriptVersion, - syscalls: TransactionScriptsSyscallsGenerator
, + syscalls_generator: TransactionScriptsSyscallsGenerator
, full: FullSuspendedState, ) -> Self { Self { tx_data, script_version, - syscalls, + syscalls_generator, total_cycles: full.total_cycles, next_vm_id: full.next_vm_id, next_pipe_slot: full.next_pipe_slot, @@ -767,8 +768,13 @@ impl { - id: VmId, - base_cycles: Arc>, - message_box: Arc>>, - snapshot2_context: Arc>>>, - script_version: ScriptVersion, + pub(crate) id: VmId, + pub(crate) base_cycles: Arc>, + pub(crate) message_box: Arc>>, + pub(crate) snapshot2_context: Arc>>>, + pub(crate) script_version: ScriptVersion, } impl @@ -49,25 +47,10 @@ impl u64 { - *self.base_cycles.lock().expect("lock") - } - pub fn set_base_cycles(&mut self, base_cycles: u64) { *self.base_cycles.lock().expect("lock") = base_cycles; } - // The different architecture here requires a re-implementation on current - // cycles syscall. - fn current_cycles(&mut self, machine: &mut Mac) -> Result<(), Error> { - let cycles = self - .base_cycles() - .checked_add(machine.cycles()) - .ok_or(Error::CyclesOverflow)?; - machine.set_register(A0, Mac::REG::from_u64(cycles)); - Ok(()) - } - // Reimplementation of load_cell_data but keep tracks of pages that are copied from // surrounding transaction data. Those pages do not need to be added to snapshots. fn load_cell_data(&mut self, machine: &mut Mac) -> Result<(), Error> { @@ -334,150 +317,6 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { - let target_id = machine.registers()[A0].to_u64(); - let exit_code_addr = machine.registers()[A1].to_u64(); - - // TODO: charge cycles - self.message_box.lock().expect("lock").push(Message::Wait( - self.id, - WaitArgs { - target_id, - exit_code_addr, - }, - )); - - // Like spawn, join yields control upon success - Err(Error::External("YIELD".to_string())) - } - - // Fetch current instance ID - fn process_id(&mut self, machine: &mut Mac) -> Result<(), Error> { - // TODO: charge cycles - machine.set_register(A0, Mac::REG::from_u64(self.id)); - Ok(()) - } - - // Create a pair of pipes - fn pipe(&mut self, machine: &mut Mac) -> Result<(), Error> { - let pipe1_addr = machine.registers()[A0].to_u64(); - let pipe2_addr = pipe1_addr.wrapping_add(8); - // TODO: charge cycles - self.message_box.lock().expect("lock").push(Message::Pipe( - self.id, - PipeArgs { - pipe1_addr, - pipe2_addr, - }, - )); - - Err(Error::External("YIELD".to_string())) - } - - // Write to pipe - fn pipe_write(&mut self, machine: &mut Mac) -> Result<(), Error> { - let pipe = PipeId(machine.registers()[A0].to_u64()); - let buffer_addr = machine.registers()[A1].to_u64(); - let length_addr = machine.registers()[A2].to_u64(); - let length = machine - .memory_mut() - .load64(&Mac::REG::from_u64(length_addr))? - .to_u64(); - - // We can only do basic checks here, when the message is actually processed, - // more complete checks will be performed. - // We will also leave to the actual write operation to test memory permissions. - if !pipe.is_write() { - machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); - return Ok(()); - } - - // TODO: charge cycles - self.message_box - .lock() - .expect("lock") - .push(Message::PipeWrite( - self.id, - PipeIoArgs { - pipe, - length, - buffer_addr, - length_addr, - }, - )); - - // A0 will be updated once the write operation is fulfilled - Err(Error::External("YIELD".to_string())) - } - - // Read from pipe - fn pipe_read(&mut self, machine: &mut Mac) -> Result<(), Error> { - let pipe = PipeId(machine.registers()[A0].to_u64()); - let buffer_addr = machine.registers()[A1].to_u64(); - let length_addr = machine.registers()[A2].to_u64(); - let length = machine - .memory_mut() - .load64(&Mac::REG::from_u64(length_addr))? - .to_u64(); - - // We can only do basic checks here, when the message is actually processed, - // more complete checks will be performed. - // We will also leave to the actual write operation to test memory permissions. - if !pipe.is_read() { - machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); - return Ok(()); - } - - // TODO: charge cycles - self.message_box - .lock() - .expect("lock") - .push(Message::PipeRead( - self.id, - PipeIoArgs { - pipe, - length, - buffer_addr, - length_addr, - }, - )); - - // A0 will be updated once the read operation is fulfilled - Err(Error::External("YIELD".to_string())) - } - - fn inherited_file_descriptors( - &mut self, - machine: &mut Mac, - ) -> Result<(), Error> { - let buffer_addr = machine.registers()[A0].to_u64(); - let length_addr = machine.registers()[A1].to_u64(); - self.message_box - .lock() - .expect("lock") - .push(Message::InheritedFileDescriptor( - self.id, - PipeIoArgs { - pipe: PipeId(0), - length: 0, - buffer_addr, - length_addr, - }, - )); - Err(Error::External("YIELD".to_string())) - } - - fn close(&mut self, machine: &mut Mac) -> Result<(), Error> { - let pipe = PipeId(machine.registers()[A0].to_u64()); - self.message_box - .lock() - .expect("lock") - .push(Message::Close(self.id, pipe)); - Err(Error::External("YIELD".to_string())) - } } impl< @@ -492,13 +331,6 @@ impl< fn ecall(&mut self, machine: &mut Mac) -> Result { let code = machine.registers()[A7].to_u64(); match code { - 2042 => { - if self.script_version >= ScriptVersion::V1 { - self.current_cycles(machine) - } else { - return Ok(false); - } - } 2091 => self.load_cell_data_as_code(machine), 2092 => self.load_cell_data(machine), 2177 => self.debug(machine), @@ -511,55 +343,6 @@ impl< return Ok(false); } } - 2602 => { - if self.script_version >= ScriptVersion::V2 { - self.wait(machine) - } else { - return Ok(false); - } - } - 2603 => { - if self.script_version >= ScriptVersion::V2 { - self.process_id(machine) - } else { - return Ok(false); - } - } - 2604 => { - if self.script_version >= ScriptVersion::V2 { - self.pipe(machine) - } else { - return Ok(false); - } - } - 2605 => { - if self.script_version >= ScriptVersion::V2 { - self.pipe_write(machine) - } else { - return Ok(false); - } - } - 2606 => { - if self.script_version >= ScriptVersion::V2 { - self.pipe_read(machine) - } else { - return Ok(false); - } - } - 2607 => { - if self.script_version >= ScriptVersion::V2 { - self.inherited_file_descriptors(machine) - } else { - return Ok(false); - } - } - 2608 => { - if self.script_version >= ScriptVersion::V2 { - self.close(machine) - } else { - return Ok(false); - } - } _ => return Ok(false), }?; Ok(true) diff --git a/script/src/verify.rs b/script/src/verify.rs index 8f6f0e5cbe..fa61136bba 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1,15 +1,16 @@ #[cfg(test)] use crate::syscalls::Pause; +use crate::syscalls::{InheritedFd, ProcessID}; use crate::v2_scheduler::Scheduler; -use crate::v2_types::{RunMode, TxData}; +use crate::v2_types::{Message, RunMode, TxData, VmId, FIRST_VM_ID}; use crate::{ cost_model::transferred_byte_cycles, error::{ScriptError, TransactionScriptError}, syscalls::{ spawn::{build_child_machine, update_caller_machine}, - CurrentCycles, CurrentMemory, Debugger, Exec, GetMemoryLimit, LoadBlockExtension, LoadCell, - LoadCellData, LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, LoadWitness, - SetContent, Spawn, VMVersion, + Close, CurrentCycles, CurrentMemory, Debugger, Exec, GetMemoryLimit, LoadBlockExtension, + LoadCell, LoadCellData, LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, + LoadWitness, Pipe, Read, SetContent, Spawn, VMVersion, Wait, Write, }, type_id::TypeIdSystemScript, types::{ @@ -144,20 +145,23 @@ impl Binaries { /// TransactionScriptsSyscallsGenerator can be cloned. #[derive(Clone)] pub struct TransactionScriptsSyscallsGenerator
{ + pub(crate) base_cycles: Arc>, pub(crate) data_loader: DL, - debug_printer: DebugPrinter, + pub(crate) debug_printer: DebugPrinter, + pub(crate) message_box: Arc>>, pub(crate) outputs: Arc>, pub(crate) rtx: Arc, #[cfg(test)] - skip_pause: Arc, + pub(crate) skip_pause: Arc, + pub(crate) vm_id: VmId, } impl TransactionScriptsSyscallsGenerator
{ /// Build syscall: current_cycles - pub fn build_current_cycles(&self, base: u64) -> CurrentCycles { - CurrentCycles::new(base) + pub fn build_current_cycles(&self) -> CurrentCycles { + CurrentCycles::new(Arc::clone(&self.base_cycles)) } /// Build syscall: vm_version @@ -278,6 +282,41 @@ impl Wait { + Wait::new(self.vm_id, self.message_box.clone()) + } + + /// Build syscall: process_id + pub fn build_process_id(&self) -> ProcessID { + ProcessID::new(self.vm_id) + } + + /// Build syscall: pipe + pub fn build_pipe(&self) -> Pipe { + Pipe::new(self.vm_id, self.message_box.clone()) + } + + /// Build syscall: write + pub fn build_write(&self) -> Write { + Write::new(self.vm_id, self.message_box.clone()) + } + + /// Build syscall: read + pub fn build_read(&self) -> Read { + Read::new(self.vm_id, self.message_box.clone()) + } + + /// Build syscall: inherited_fd + pub fn inherited_fd(&self) -> InheritedFd { + InheritedFd::new(self.vm_id, self.message_box.clone()) + } + + /// Build syscall: close + pub fn close(&self) -> Close { + Close::new(self.vm_id, self.message_box.clone()) + } + /// Build syscall: current_memory pub fn build_current_memory(&self, current_memory: u64) -> CurrentMemory { CurrentMemory::new(current_memory) @@ -315,8 +354,6 @@ impl= ScriptVersion::V1 { syscalls.append(&mut vec![ Box::new(self.build_vm_version()), @@ -324,14 +361,23 @@ impl= ScriptVersion::V2 { - syscalls.push(Box::new( - self.build_load_block_extension(Arc::clone(&script_group_input_indices)), - )); + syscalls.append(&mut vec![ + Box::new(self.build_load_block_extension(Arc::clone(&script_group_input_indices))), + Box::new(self.build_process_id()), + Box::new(self.build_pipe()), + Box::new(self.build_wait()), + Box::new(self.build_write()), + Box::new(self.build_read()), + Box::new(self.inherited_fd()), + Box::new(self.close()), + ]); } + #[cfg(test)] + syscalls.push(Box::new(Pause::new(Arc::clone(&self.skip_pause)))); syscalls } @@ -343,9 +389,6 @@ impl>, ) -> Vec)>> { let mut syscalls = self.generate_same_syscalls(script_version, script_group); - if script_version >= ScriptVersion::V1 { - syscalls.push(Box::new(self.build_current_cycles(0))); - } if script_version >= ScriptVersion::V2 { syscalls.append(&mut vec![ Box::new(self.build_get_memory_limit(8)), @@ -385,7 +428,7 @@ pub struct TransactionScriptsVerifier
{ consensus: Arc, tx_env: Arc, - generator: TransactionScriptsSyscallsGenerator
, + syscalls_generator: TransactionScriptsSyscallsGenerator
, } impl @@ -481,13 +524,16 @@ impl(&mut self, func: F) { - self.generator.debug_printer = Arc::new(func); + self.syscalls_generator.debug_printer = Arc::new(func); } #[cfg(test)] @@ -1065,7 +1111,7 @@ impl>, ) -> Vec)>> { - self.generator + self.syscalls_generator .generate_root_syscalls(script_version, script_group, context) } @@ -1104,7 +1150,8 @@ impl ScriptError::ExceededMaximumCycles(max_cycles), @@ -1248,7 +1295,7 @@ impl Date: Fri, 8 Mar 2024 11:05:48 +0800 Subject: [PATCH 016/135] Add more test cases (#11) * Add test cases * Add more test cases * typo * Fix spawn with inherited fd without ownership * Add other end close case Fix build.rs * Wait child process and exit --- script/build.rs | 1 + script/src/v2_scheduler.rs | 18 +- .../tests/ckb_latest/features_since_v2023.rs | 92 ++++- script/testdata/Makefile | 6 +- script/testdata/spawn_callee_strcat | Bin 4792 -> 4744 bytes script/testdata/spawn_caller_strcat | Bin 5224 -> 5136 bytes script/testdata/spawn_caller_strcat_wrap | Bin 4656 -> 4608 bytes script/testdata/spawn_cases | Bin 0 -> 12032 bytes script/testdata/spawn_cases.c | 388 ++++++++++++++++++ script/testdata/spawn_recursive | Bin 4648 -> 4600 bytes script/testdata/spawn_times | Bin 4672 -> 4624 bytes script/testdata/utils.h | 97 ++++- 12 files changed, 589 insertions(+), 13 deletions(-) create mode 100755 script/testdata/spawn_cases create mode 100644 script/testdata/spawn_cases.c diff --git a/script/build.rs b/script/build.rs index b9e5a0401e..a201f38439 100644 --- a/script/build.rs +++ b/script/build.rs @@ -19,4 +19,5 @@ fn main() { if cfg!(any(feature = "asm", feature = "detect-asm")) && can_enable_asm { println!("cargo:rustc-cfg=has_asm"); } + println!("cargo:rerun-if-changed=src"); } diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index 3e3745f69f..ae62f0533b 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -299,14 +299,19 @@ impl { // All pipes must belong to the correct owner + let mut pipes_valid = true; for pipe in &args.pipes { if !(self.pipes.contains_key(pipe) && (self.pipes[pipe] == vm_id)) { - return Err(Error::Unexpected(format!( - "VM {} does not own pipe {}!", - vm_id, pipe.0, - ))); + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, INVALID_PIPE as u64); + pipes_valid = false; + break; } } + if !pipes_valid { + continue; + } // TODO: spawn limits let spawned_vm_id = self.boot_vm(&args.data_piece_id, args.offset, args.length, &args.argv)?; @@ -344,6 +349,7 @@ impl (), 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 cfbe0a9cd7..3f6dc80b73 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -6,6 +6,96 @@ use ckb_types::{ use super::SCRIPT_VERSION; use crate::verify::{tests::utils::*, *}; +fn simple_spawn_test(bin_path: &str, args: &[u8]) -> Result { + let script_version = SCRIPT_VERSION; + + let (cell, data_hash) = load_cell_from_path(bin_path); + let script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(data_hash) + .args(Bytes::copy_from_slice(args).pack()) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(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![cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify_without_limit(script_version, &rtx); + result +} + +#[test] +fn check_spawn_simple_read_write() { + let result = simple_spawn_test("testdata/spawn_cases", &[1]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_write_dead_lock() { + let result = simple_spawn_test("testdata/spawn_cases", &[2]); + assert_eq!( + result.unwrap_err().to_string().contains("deadlock"), + SCRIPT_VERSION == ScriptVersion::V2 + ); +} + +#[test] +fn check_spawn_invalid_fd() { + let result = simple_spawn_test("testdata/spawn_cases", &[3]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_wait_dead_lock() { + let result = simple_spawn_test("testdata/spawn_cases", &[4]); + assert_eq!( + result.unwrap_err().to_string().contains("deadlock"), + SCRIPT_VERSION == ScriptVersion::V2 + ); +} + +#[test] +fn check_spawn_read_write_with_close() { + let result = simple_spawn_test("testdata/spawn_cases", &[5]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_wait_multiple() { + let result = simple_spawn_test("testdata/spawn_cases", &[6]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_inherited_fds() { + let result = simple_spawn_test("testdata/spawn_cases", &[7]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_inherited_fds_without_owner() { + let result = simple_spawn_test("testdata/spawn_cases", &[8]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + + +#[test] +fn check_spawn_read_then_close() { + let result = simple_spawn_test("testdata/spawn_cases", &[9]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + #[test] fn check_vm_version() { let script_version = SCRIPT_VERSION; @@ -225,7 +315,7 @@ fn check_spawn_out_of_cycles_wrap() { .to_string() .contains("ExceededMaximumCycles")) } else { - assert!(result.is_err()) + assert!(result.is_err()); } } diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 90d7a50941..89b9ada02f 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -68,7 +68,8 @@ ALL_BINS := jalr_zero \ spawn_caller_out_of_cycles_wrap \ spawn_caller_current_cycles \ spawn_callee_current_cycles \ - spawn_times + spawn_times \ + spawn_cases ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -146,5 +147,6 @@ 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 +spawn_times: spawn_times.c utils.h +spawn_cases: spawn_cases.c utils.h diff --git a/script/testdata/spawn_callee_strcat b/script/testdata/spawn_callee_strcat index ce58976b5e21e559c75a0f1797ddce45b73dcede..545b9ace088906e641fdb2432bf644a811934ae2 100755 GIT binary patch delta 167 zcmdm?+Mzl@gVAH6ra9ML9tJSD%QG?SIpdkhL5%*Ur-fNrPrhd;P)loWJ=YF7brQ@&EugF*B3^ delta 213 zcmeBB-Jv=`gRx?wra2ccF9R6x@=nZp&Uk)u5Tn28Ibl}TGw&G+lpgLsn(CVR*Dcm< zaw{uTR6w!T^Wb)n_+&N#rb4*P=4*_bxO7wVN>Yn5^U@WPi&7IyQsawDQsN6T3sQ?A zwlE|o=Hw_OXD5LLH@EU6voM~W{8FHt6Xp(~$qRXfC)Wt7aLPknrVSR^BdEd{F!`aN UJ!8dWMIn1mZ2^dho={mH0M$A_yZ`_I diff --git a/script/testdata/spawn_caller_strcat b/script/testdata/spawn_caller_strcat index 57a356128f540dcdd36522ba9716ebb95f3c9e43..7773fb4d1f0ce67bb1cf79673bb244713a390c3d 100755 GIT binary patch delta 297 zcmaE%F#!mfE(lK4GUJrvV*mrWiJAUf?f32898I6x&i-KHp+2Vedy|70o!D9*2(z}{ z**uH!12a?C_02u3VeIvlg{>J{&3YYdUz9#DJz#pm^n&RPS8Jmyqg$gJqkE(Kf~0|J0N$w|6u=dk!S%(15CjL=A+v|ewaLu*K4u_-wno! z%^&%~85t*R_7t#ZVmvgtQ%GO1f|n8O&k9~J#jtGhNuhE^xyg>g_KXIT8-ZlP!Z!H7(XyGaoyV7!y3k3A6w}4L#xv@RhYH)UfUD3KYm}w`aVS2&zrZw~Z2l;PYt&OgXZjEk??v3t~J5DYt2HMHb@PS{Ng_U7Zn=o4dv*H_& zuJ<3}KXY*4RxA3XDP4I7i!H;P2anR{JUNuEZ19s|QM$6pPlja)O08@uk4l^>7gaJ< zB_=jCfDCS6KAP&9I=Qv=A;=T&Kh(c{xPNjPua|CWUP)?EW?s5Na#3nxNoss?NlJV{ zWoEu$uEWM89OFx3fnX8n4BqW&m(x5UygYm#bO><5?9tJSb+nCAD%_uOrkXu~u1Iy7=*VM_atp|izSr5MdaR0-y z1f^ECl*GiQ29V66HeogeR+#+cZQMbdEqEeW81p7i6ewrZo6IR_&*(7O6G#?J?gWw> TCZ80v=Pc!i*yK4mP*5HK?u96& delta 177 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 0) { + return child_entry(case_id); + } else { + return parent_entry(case_id); + } +} diff --git a/script/testdata/spawn_recursive b/script/testdata/spawn_recursive index 4e5934da7594d08159b227cd1e9a5a6fc17ba08b..7d5c2c4de3cce51f3c0c6c1faceb5c8b4ed1255b 100755 GIT binary patch delta 125 zcmZ3X@+qi=^Tkr(1Fy>9}6ewrZo6IO^&*(7OQP6&}gCNJ` T4nYgX4U-Q7#d0Py3aJACExRbE delta 171 zcmeyNyh3Gy2IGr~n&zBwJPcqEw=t8Qn~`C1A-A~R1D2zyuBnq-TMrAfvL1Q=;r@qZ z2}-SODT#?q4Ir6CZNh8+qi>tQ}aqvi!$@l6_Sfm6H8L#i%U}C3o;8*iy@{n zBq!$NC?sbmfdx0S@&vOm&YK)5P|g@P`J#aRqj7mu_laNorAMUb;eZQEFmIYJ71?N_;_P zL25C?GKS>DoE(MZ>?E+@W>X$(7RGgx3kAv<=S_YoV9&T=vZkOt +#include + #include "ckb_consts.h" #include "ckb_syscalls.h" +#include "blockchain.h" enum CkbSpawnError { ErrorCommon = 31, @@ -36,6 +38,8 @@ enum CkbSpawnError { #endif #define countof(array) (sizeof(array) / sizeof(array[0])) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) // conventions #define CKB_STDIN (0) @@ -43,15 +47,12 @@ enum CkbSpawnError { // mimic stdio pipes on linux int create_std_pipes(uint64_t* fds, uint64_t* inherited_fds) { - printf("entering create_std_pipes"); int err = 0; uint64_t to_child[2] = {0}; uint64_t to_parent[2] = {0}; - printf("call ckb_pipe"); err = ckb_pipe(to_child); CHECK(err); - printf("call ckb_pipe"); err = ckb_pipe(to_parent); CHECK(err); @@ -99,3 +100,91 @@ int simple_spawn_args(size_t index, int argc, const char* argv[]) { exit: return err; } + +int full_spawn(size_t index, int argc, const char* argv[], uint64_t fds[2], uint64_t* pid) { + int err = 0; + uint64_t inherited_fds[3] = {0}; + err = create_std_pipes(fds, inherited_fds); + CHECK(err); + spawn_args_t spgs = {.argc = argc, .argv = argv, .process_id = pid, .inherited_fds = inherited_fds}; + err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); + CHECK(err); +exit: + return err; +} + +// read exact `length` bytes into buffer. +// Will wait forever when less bytes are written on write fd. +int read_exact(uint64_t fd, void* buffer, size_t length, size_t* actual_length) { + int err = 0; + size_t remaining_length = length; + uint8_t* start_buffer = buffer; + while (true) { + size_t n = remaining_length; + err = ckb_read(fd, start_buffer, &n); + if (err == CKB_OTHER_END_CLOSED) { + err = 0; + break; + } else { + CHECK(err); + } + start_buffer += n; + remaining_length -= n; + *actual_length = length - remaining_length; + if (remaining_length == 0) { + break; + } + } + +exit: + return err; +} + +// write exact `length` bytes into buffer. +// Will wait forever when less bytes are read on read fd. +int write_exact(uint64_t fd, void* buffer, size_t length, size_t* actual_length) { + int err = 0; + size_t remaining_length = length; + uint8_t* start_buffer = buffer; + while (true) { + size_t n = remaining_length; + err = ckb_write(fd, start_buffer, &n); + if (err == CKB_OTHER_END_CLOSED) { + err = 0; + break; + } else { + CHECK(err); + } + start_buffer += n; + remaining_length -= n; + *actual_length = length - remaining_length; + if (remaining_length == 0) { + break; + } + } +exit: + return err; +} + +#define SCRIPT_SIZE 4096 + +int load_script_args(uint8_t* args, size_t* length) { + int err = 0; + uint64_t len = SCRIPT_SIZE; + uint8_t script[SCRIPT_SIZE]; + err = ckb_load_script(script, &len, 0); + CHECK(err); + CHECK2(len <= SCRIPT_SIZE, -2); + mol_seg_t script_seg = {0}; + script_seg.ptr = (uint8_t*)script; + script_seg.size = len; + CHECK2(MolReader_Script_verify(&script_seg, false) == MOL_OK, -3); + mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); + mol_seg_t bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); + size_t copy_length = MIN(bytes_seg.size, *length); + memcpy(args, bytes_seg.ptr, copy_length); + *length = copy_length; + +exit: + return err; +} From d44371f5bf0bda39b7f961312017f1ced95dc394 Mon Sep 17 00:00:00 2001 From: xjd Date: Fri, 8 Mar 2024 13:20:02 +0800 Subject: [PATCH 017/135] Fix EOF issue (#12) --- script/src/v2_scheduler.rs | 4 ++-- script/testdata/spawn_cases | Bin 12032 -> 12048 bytes script/testdata/spawn_cases.c | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index ae62f0533b..ddfa83ab04 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -547,7 +547,7 @@ impl (), diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 4b864816df20ad0ad95ce433c25e00f20d2f73cd..06ee2e2349c72bde12dff96ab309fd7e69657e99 100755 GIT binary patch delta 2817 zcmZuz4NOy46u$4Zef+4S@I+|&Yf;E}lZs3c$pj$-!AxOEXT+hP6hSkGOxVVj*~(f_ zTtfBwvpE@v874#*7N%_I*6QXaZdxQ}izd!D!jKR~OCp>@cr5z-}<5 zOm);}mKh!=Kj{&nO1VSZz;j?NuTnk7jea-yKL?w&B#NS;aLQTuovUYs=MISQ+K%V9&q>s@#GRK|?5IA;JU*3sHqhW18< zug*byMX3B1xjJ0iRXy?jlL1RCd?q!!m0fUYw@QtYawOLI5nHobvX1z zTm)`ePB7b~1g@2pHj;GAunv{P+Hy?orZ`lH+;$&{kc5n>t1-@r@hL@a&^05Mf+SOr z7MrGr;F_>7o!nC8RIM?u8%tNBc+lNjuBlR$V!7ZAeJVU3W=WEd);)%cc5>cxa{c9{ zS1T#~C@c!s2FmRDBhV7Ajg>iqhVvXmGoJHsl5SGFO+)ZXc*Sg14?u_edohij(Rg~R-VT8 z63!HF8>rsyLjx9g1#%snH12Wqmaml0xIMZ@E>?8>+qFAJ%`ByKV$4Xbu>{8nq+>c9;-gP)qOFN}09#NwMz&6b$a z>(yy*h@_J^^V1O0DW|%_6PL5B=f>0Z&lY&IqLntQOY{ur=&xlD~`( zlrwS7>q;Xg*a1{rR<)jrmBh~#tN5F_ehYtH`qnw;#s!HFFUf-0`3K$b^kS{XZ)>0` z{di<%UBmOhEoMv$R;3yX)(KsU6U<_0z^FpWu$sYkbX=T?oImz^Lg&`da=|wOae0b= z6|9*Kd{@~iSPQ%H-LhMP^`b+mCO@00puJx0Z_8$~(}&qntdm=e=@YCg?{w5-cHYeO z`Ol7+Xg+s{kc~p?hrSx`s`R*QAG}s)!EZ?z9k<@E zrh3;K`wSJZJWdbw!lHZt?k-^@+lJN(WN#rmkL(gMC$gK!jL6dC7?6gHL&hQtM3zkN zQ|OusC*s~`a$!|`7^_Qxjq&|v1}J9V&p?Um0N`b0A%Fpq^rgQ=LIHRct!gknqf006 za|(k}8ox7);700xkK#9Y0^FuJq_{nTF-sg{(kB3&)bWyr60yW_4J~TGdJCoT{WSiU zKoVa-8@NaD6QKm}qZ^M?+_{(l2D(3(rj8yxajd5aI3Fuusl#H${2$6d#5fVM|xNP{STg)GQ*-#yL)%96y{5=|GVG+`*;7> zwr#6*Yg<(4z7PiBXSMhVfcr?&@})iqI*_M9R_u9 z9RPUX{v$Ro88G=CZ);ymNH-gMxKv}eZSr`_4?CKnf}Av*oAY?H55c0a7?r(Lqp%}` zNjt1XN6FrG5VnW8*}50dpjoy~GU|Eqi*um5u=*J)tYkK{OL*!Z&kTD+&2ywt2WVQo z&kcpHvigA<*fOiEZ%C8LSdbUz4kC5c{W?(XXvX^$`6ynQ$6I`>%e2tWnMaM)h_UCJ zs`GJ1tRsaM4>uYDEe4D@f>;ZuR+6Y8KTA=|XjIP)zfWIF_^ZrfdnromcSv=M4%{hL zOe9j~>4$eCqEu4e!SC85BQ^)t-g-gGg4mGJ>c1JSSZL2Tb{TbI^%}01onC*cv(ZrK z#5`5V?l=c(qU#k^m>Xz{Ja3Tb@A({8=jNmP)y@R$o4fF%0ylO zcgKk*tbz-$P@vH9f5Kh!c~lWRKL6vj0aqb(j!m&sq7vB=${(FU?5NC-jq7QtBI%-5 z(cg>D3AZ4&GD0PJ~8Ue;JMWa4U8`pLfBRlyk(?IY&OfF8iyDY`o^JvY4V z8mP&T#>f$O!QYYP>%MLAYQ}%Q_bIe${Ua^79MGZ7#C+b?p7I-6I$(1`oK`Af@<^j$ zi+E%1&>8cZ2`3WvN;50O+h@$IFnMr_A5$3Rr|IQ0+a~G>Ll!HZ+1CSRR!IH#r86t^ zOw>D9)GM|hF31|=CKmcwFZ)!fo}+|AQS)}?ZksPxfba(i`Af&yJ;@+V36*1x2K0>` z0=yw3HH_|~f~v@8>mmrfu0A4NenM<(`^(3 zcOKL)sEIlw7SqrLn}tdfC#ik(Ecu3qi6-AGv0?$IS08cn{%fd<83r1BJl{5iF;m1G~160w5DM62t2ylbq$HNG)jN%WGeA(4JrS?s+#Be9I zSEDNx8zT+m(zF0XN{SgB$08ixSqJ@(Iza<1qxd+?;WvkwcJHV)Z_`)R)i#(-yX#E) zw7wJkUKW}X6;Pd`Wolu1N@|ewE@8L?C{J)QkYjp d Date: Fri, 8 Mar 2024 14:24:25 +0800 Subject: [PATCH 018/135] Rewrite spawn (#13) * Support spawn program in witnesses * Add cycles charge for spawn * Generic type * Staged * Rewrite spawn --- script/src/lib.rs | 1 - script/src/syscalls/current_memory.rs | 30 - script/src/syscalls/get_memory_limit.rs | 30 - script/src/syscalls/mod.rs | 12 - script/src/syscalls/set_content.rs | 51 -- script/src/syscalls/spawn.rs | 412 +++------- .../syscalls/tests/vm_latest/syscalls_2.rs | 42 - script/src/v2_scheduler.rs | 19 +- script/src/v2_syscalls.rs | 166 +--- script/src/v2_types.rs | 63 +- script/src/verify.rs | 767 +++++++++--------- .../tests/ckb_latest/features_since_v2023.rs | 1 - 12 files changed, 548 insertions(+), 1046 deletions(-) delete mode 100644 script/src/syscalls/current_memory.rs delete mode 100644 script/src/syscalls/get_memory_limit.rs delete mode 100644 script/src/syscalls/set_content.rs diff --git a/script/src/lib.rs b/script/src/lib.rs index 91c42e0c16..10f0f96757 100644 --- a/script/src/lib.rs +++ b/script/src/lib.rs @@ -11,7 +11,6 @@ mod verify; mod verify_env; pub use crate::error::{ScriptError, TransactionScriptError}; -pub use crate::syscalls::spawn::update_caller_machine; pub use crate::types::{ ChunkCommand, CoreMachine, MachineContext, ResumableMachine, ScriptGroup, ScriptGroupType, ScriptVersion, TransactionSnapshot, TransactionState, VerifyResult, VmIsa, VmVersion, diff --git a/script/src/syscalls/current_memory.rs b/script/src/syscalls/current_memory.rs deleted file mode 100644 index 401d778191..0000000000 --- a/script/src/syscalls/current_memory.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::syscalls::CURRENT_MEMORY; -use ckb_vm::{ - registers::{A0, A7}, - Error as VMError, Register, SupportMachine, Syscalls, -}; - -#[derive(Debug, Default)] -pub struct CurrentMemory { - value: u64, -} - -impl CurrentMemory { - pub fn new(value: u64) -> Self { - Self { value } - } -} - -impl Syscalls for CurrentMemory { - fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { - Ok(()) - } - - fn ecall(&mut self, machine: &mut Mac) -> Result { - if machine.registers()[A7].to_u64() != CURRENT_MEMORY { - return Ok(false); - } - machine.set_register(A0, Mac::REG::from_u64(self.value)); - Ok(true) - } -} diff --git a/script/src/syscalls/get_memory_limit.rs b/script/src/syscalls/get_memory_limit.rs deleted file mode 100644 index 7b28887ce1..0000000000 --- a/script/src/syscalls/get_memory_limit.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::syscalls::GET_MEMORY_LIMIT; -use ckb_vm::{ - registers::{A0, A7}, - Error as VMError, Register, SupportMachine, Syscalls, -}; - -#[derive(Debug)] -pub struct GetMemoryLimit { - memory_limit: u64, -} - -impl GetMemoryLimit { - pub fn new(memory_limit: u64) -> Self { - Self { memory_limit } - } -} - -impl Syscalls for GetMemoryLimit { - fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { - Ok(()) - } - - fn ecall(&mut self, machine: &mut Mac) -> Result { - if machine.registers()[A7].to_u64() != GET_MEMORY_LIMIT { - return Ok(false); - } - machine.set_register(A0, Mac::REG::from_u64(self.memory_limit)); - Ok(true) - } -} diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index 0bdfdbf4be..15e23e1462 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -1,9 +1,7 @@ mod close; mod current_cycles; -mod current_memory; mod debugger; mod exec; -mod get_memory_limit; mod inherited_fd; mod load_block_extension; mod load_cell; @@ -17,7 +15,6 @@ mod load_witness; mod pipe; mod process_id; mod read; -mod set_content; pub(crate) mod spawn; mod utils; mod vm_version; @@ -32,10 +29,8 @@ mod tests; pub use self::close::Close; pub use self::current_cycles::CurrentCycles; -pub use self::current_memory::CurrentMemory; pub use self::debugger::Debugger; pub use self::exec::Exec; -pub use self::get_memory_limit::GetMemoryLimit; pub use self::inherited_fd::InheritedFd; pub use self::load_block_extension::LoadBlockExtension; pub use self::load_cell::LoadCell; @@ -49,7 +44,6 @@ pub use self::load_witness::LoadWitness; pub use self::pipe::Pipe; pub use self::process_id::ProcessID; pub use self::read::Read; -pub use self::set_content::SetContent; pub use self::spawn::Spawn; pub use self::vm_version::VMVersion; pub use self::wait::Wait; @@ -69,9 +63,6 @@ pub const INDEX_OUT_OF_BOUND: u8 = 1; pub const ITEM_MISSING: u8 = 2; pub const SLICE_OUT_OF_BOUND: u8 = 3; pub const WRONG_FORMAT: u8 = 4; -pub const SPAWN_EXCEEDED_MAX_CONTENT_LENGTH: u8 = 5; -pub const SPAWN_WRONG_MEMORY_LIMIT: u8 = 6; -pub const SPAWN_EXCEEDED_MAX_PEAK_MEMORY: u8 = 7; pub const VM_VERSION: u64 = 2041; pub const CURRENT_CYCLES: u64 = 2042; @@ -98,9 +89,6 @@ pub const WRITE: u64 = 2605; pub const READ: u64 = 2606; pub const INHERITED_FD: u64 = 2607; pub const CLOSE: u64 = 2608; -pub const GET_MEMORY_LIMIT: u64 = 2102; -pub const SET_CONTENT: u64 = 2103; -pub const CURRENT_MEMORY: u64 = 2105; pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; #[cfg(test)] pub const DEBUG_PAUSE: u64 = 2178; diff --git a/script/src/syscalls/set_content.rs b/script/src/syscalls/set_content.rs deleted file mode 100644 index c1442c30c9..0000000000 --- a/script/src/syscalls/set_content.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::cost_model::transferred_byte_cycles; -use crate::syscalls::utils::load_bytes; -use crate::syscalls::SET_CONTENT; -use ckb_vm::{ - registers::{A0, A1, A7}, - Error as VMError, Memory, Register, SupportMachine, Syscalls, -}; -use std::sync::{Arc, Mutex}; - -#[derive(Debug)] -pub struct SetContent { - content: Arc>>, - content_size: u64, -} - -impl SetContent { - pub fn new(content: Arc>>, content_size: u64) -> Self { - Self { - content, - content_size, - } - } -} - -impl Syscalls for SetContent { - fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { - Ok(()) - } - - fn ecall(&mut self, machine: &mut Mac) -> Result { - if machine.registers()[A7].to_u64() != SET_CONTENT { - return Ok(false); - } - let content_addr = machine.registers()[A0].to_u64(); - let request_size_addr = machine.registers()[A1].to_u64(); - let request_size = machine - .memory_mut() - .load64(&Mac::REG::from_u64(request_size_addr))?; - let size = std::cmp::min(self.content_size, request_size.to_u64()); - self.content.lock().unwrap().resize(size as usize, 0); - let content = load_bytes(machine, content_addr, size)?; - self.content.lock().unwrap().copy_from_slice(&content); - machine.memory_mut().store64( - &Mac::REG::from_u64(request_size_addr), - &Mac::REG::from_u64(size), - )?; - machine.add_cycles_no_checking(transferred_byte_cycles(size))?; - machine.set_register(A0, Mac::REG::from_u64(0)); - Ok(true) - } -} diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index ad903e81b8..5a91232c74 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,95 +1,42 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::utils::load_c_string; -use crate::syscalls::{ - Source, SourceEntry, INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, - SPAWN_EXCEEDED_MAX_CONTENT_LENGTH, SPAWN_EXCEEDED_MAX_PEAK_MEMORY, SPAWN_EXTRA_CYCLES_BASE, - SPAWN_EXTRA_CYCLES_PER_MEMORY_PAGE, SPAWN_MAX_CONTENT_LENGTH, SPAWN_MAX_MEMORY, - SPAWN_MAX_PEAK_MEMORY, SPAWN_MEMORY_PAGE_SIZE, SPAWN_WRONG_MEMORY_LIMIT, WRONG_FORMAT, -}; -use crate::types::{ - set_vm_max_cycles, CoreMachineType, Machine, MachineContext, ResumableMachine, SpawnData, -}; -use crate::TransactionScriptsSyscallsGenerator; -use crate::{ScriptGroup, ScriptVersion}; +use crate::syscalls::{INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE}; +use crate::v2_types::{DataPieceId, Message, PipeId, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; -use ckb_types::core::cell::CellMeta; use ckb_vm::{ - cost_model::estimate_cycles, - registers::{A0, A1, A2, A3, A4, A5, A7}, - DefaultMachineBuilder, Error as VMError, Memory, Register, SupportMachine, Syscalls, + machine::SupportMachine, + memory::Memory, + registers::{A0, A1, A2, A3, A4, A7}, + snapshot2::{DataSource, Snapshot2Context}, + syscalls::Syscalls, + Error as VMError, Register, }; use std::sync::{Arc, Mutex}; -pub struct Spawn
{ - script_group: ScriptGroup, - script_version: ScriptVersion, - syscalls_generator: TransactionScriptsSyscallsGenerator
, - peak_memory: u64, - cycles_base: u64, - context: Arc>, +pub struct Spawn
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ + id: VmId, + message_box: Arc>>, + snapshot2_context: Arc>>>, } -impl Spawn
{ +impl
Spawn
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ pub fn new( - script_group: ScriptGroup, - script_version: ScriptVersion, - syscalls_generator: TransactionScriptsSyscallsGenerator
, - peak_memory: u64, - cycles_base: u64, - context: Arc>, + id: VmId, + message_box: Arc>>, + snapshot2_context: Arc>>>, ) -> Self { Self { - script_group, - script_version, - syscalls_generator, - peak_memory, - cycles_base, - context, + id, + message_box, + snapshot2_context, } } - - fn data_loader(&self) -> &DL { - &self.syscalls_generator.data_loader - } - - fn outputs(&self) -> &Vec { - &self.syscalls_generator.outputs - } - - #[inline] - fn resolved_inputs(&self) -> &Vec { - &self.syscalls_generator.rtx.resolved_inputs - } - - #[inline] - fn resolved_cell_deps(&self) -> &Vec { - &self.syscalls_generator.rtx.resolved_cell_deps - } - - fn fetch_cell(&self, source: Source, index: usize) -> Result<&CellMeta, u8> { - let cell_opt = match source { - Source::Transaction(SourceEntry::Input) => self.resolved_inputs().get(index), - Source::Transaction(SourceEntry::Output) => self.outputs().get(index), - Source::Transaction(SourceEntry::CellDep) => self.resolved_cell_deps().get(index), - Source::Group(SourceEntry::Input) => self - .script_group - .input_indices - .get(index) - .and_then(|actual_index| self.resolved_inputs().get(*actual_index)), - Source::Group(SourceEntry::Output) => self - .script_group - .output_indices - .get(index) - .and_then(|actual_index| self.outputs().get(*actual_index)), - Source::Transaction(SourceEntry::HeaderDep) - | Source::Group(SourceEntry::CellDep) - | Source::Group(SourceEntry::HeaderDep) => { - return Err(INDEX_OUT_OF_BOUND); - } - }; - - cell_opt.ok_or(INDEX_OUT_OF_BOUND) - } } impl Syscalls for Spawn
@@ -105,243 +52,110 @@ where if machine.registers()[A7].to_u64() != SPAWN { return Ok(false); } - // Arguments for positioning child programs. let index = machine.registers()[A0].to_u64(); - let source = Source::parse_from_u64(machine.registers()[A1].to_u64())?; - let bounds = machine.registers()[A2].to_u64(); - let offset = (bounds >> 32) as usize; - let length = bounds as u32 as usize; - // Arguments for childs. - let argc = machine.registers()[A3].to_u64(); - let argv_addr = machine.registers()[A4].to_u64(); - let spgs_addr = machine.registers()[A5].to_u64(); - let memory_limit_addr = spgs_addr; - let exit_code_addr_addr = spgs_addr.wrapping_add(8); - let content_addr_addr = spgs_addr.wrapping_add(16); - let content_length_addr_addr = spgs_addr.wrapping_add(24); - // Arguments for limiting. - let memory_limit = machine - .memory_mut() - .load64(&Mac::REG::from_u64(memory_limit_addr))? - .to_u64(); - let cycles_limit = machine.max_cycles() - machine.cycles(); - // Arguments for saving outputs from child programs. - let exit_code_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(exit_code_addr_addr))?; - let content_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(content_addr_addr))?; - let content_length_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(content_length_addr_addr))?; - let content_length = machine.memory_mut().load64(&content_length_addr)?.to_u64(); - // Arguments check. - if content_length > SPAWN_MAX_CONTENT_LENGTH { - machine.set_register(A0, Mac::REG::from_u8(SPAWN_EXCEEDED_MAX_CONTENT_LENGTH)); - return Ok(true); - } - if memory_limit > SPAWN_MAX_MEMORY || memory_limit == 0 { - machine.set_register(A0, Mac::REG::from_u8(SPAWN_WRONG_MEMORY_LIMIT)); - return Ok(true); - } - if self.peak_memory + memory_limit > SPAWN_MAX_PEAK_MEMORY { - machine.set_register(A0, Mac::REG::from_u8(SPAWN_EXCEEDED_MAX_PEAK_MEMORY)); - return Ok(true); - } - // Build child machine. - let spawn_data = SpawnData { - callee_peak_memory: self.peak_memory + memory_limit, - callee_memory_limit: memory_limit, - content: Arc::new(Mutex::new(Vec::::new())), - content_length: content_length.to_u64(), - caller_exit_code_addr: exit_code_addr.to_u64(), - caller_content_addr: content_addr.to_u64(), - caller_content_length_addr: content_length_addr.to_u64(), - cycles_base: self.cycles_base + machine.cycles(), - }; - let mut machine_child = build_child_machine( - &self.script_group, - self.script_version, - &self.syscalls_generator, - cycles_limit, - &spawn_data, - &self.context, - )?; - // Get binary. - let program = { - let cell = self.fetch_cell(source, index as usize); - if let Err(err) = cell { - machine.set_register(A0, Mac::REG::from_u8(err)); - return Ok(true); - } - let cell = cell.unwrap(); - let data = self.data_loader().load_cell_data(cell).ok_or_else(|| { - VMError::Unexpected(format!( - "Unexpected load_cell_data failed {}", - cell.out_point, - )) - })?; - let size = data.len(); - if offset >= size { - machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); + let source = machine.registers()[A1].to_u64(); + let place = machine.registers()[A2].to_u64(); + let data_piece_id = match DataPieceId::try_from((source, index, place)) { + Ok(id) => id, + Err(_) => { + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); return Ok(true); - }; - if length == 0 { - data.slice(offset..size) - } else { - let end = offset.checked_add(length).ok_or(VMError::MemOutOfBound)?; - if end > size { - machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); - return Ok(true); - } - data.slice(offset..end) } }; - // Build arguments. - let mut addr = argv_addr.to_u64(); - let mut argv_vec = Vec::new(); + let bounds = machine.registers()[A3].to_u64(); + let offset = bounds >> 32; + let length = bounds as u32 as u64; + let spgs_addr = machine.registers()[A4].to_u64(); + let argc_addr = spgs_addr; + let argc = machine + .memory_mut() + .load64(&Mac::REG::from_u64(argc_addr))? + .to_u64(); + let argv_addr_addr = spgs_addr.wrapping_add(8); + let argv_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(argv_addr_addr))? + .to_u64(); + let mut addr = argv_addr; + let mut argv = Vec::new(); for _ in 0..argc { let target_addr = machine .memory_mut() .load64(&Mac::REG::from_u64(addr))? .to_u64(); let cstr = load_c_string(machine, target_addr)?; - argv_vec.push(cstr); - addr += 8; + argv.push(cstr); + addr = addr.wrapping_add(8); } - // Deduct cycles used to build the child machine - let extra_cycles = - SPAWN_EXTRA_CYCLES_BASE + memory_limit * SPAWN_EXTRA_CYCLES_PER_MEMORY_PAGE; - machine_child.machine.add_cycles_no_checking(extra_cycles)?; - // Load program into child machine. - match machine_child.load_program(&program, &argv_vec) { - Ok(size) => { - machine_child - .machine - .add_cycles_no_checking(transferred_byte_cycles(size))?; + + let process_id_addr_addr = spgs_addr.wrapping_add(16); + let process_id_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(process_id_addr_addr))? + .to_u64(); + let pipes_addr_addr = spgs_addr.wrapping_add(24); + let mut pipes_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(pipes_addr_addr))? + .to_u64(); + + let mut pipes = vec![]; + if pipes_addr != 0 { + loop { + let pipe = machine + .memory_mut() + .load64(&Mac::REG::from_u64(pipes_addr))? + .to_u64(); + if pipe == 0 { + break; + } + pipes.push(PipeId(pipe)); + pipes_addr += 8; } - Err(_) => { - // If loading binary fails, we still need to consume extra_cycles. - machine.add_cycles_no_checking(extra_cycles)?; - machine.set_register(A0, Mac::REG::from_u8(WRONG_FORMAT)); + } + + // We are fetching the actual cell here for some in-place validation + let sc = self + .snapshot2_context + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))?; + let (_, full_length) = match sc.data_source().load_data(&data_piece_id, 0, 0) { + Ok(val) => val, + Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); return Ok(true); } + Err(e) => return Err(e), + }; + if offset >= full_length { + machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); + return Ok(true); } - // Run the child machine and check result. - match machine_child.run() { - Ok(data) => { - update_caller_machine(machine, data, machine_child.machine.cycles(), &spawn_data)?; - Ok(true) - } - Err(err) => { - // `CyclesExceeded` for old version snapshot - // `Pause` for new version suspend with pause signal - // Maybe we need to cleanup in future - if matches!(err, VMError::Pause | VMError::CyclesExceeded) { - let mut context = self.context.lock().map_err(|e| { - VMError::Unexpected(format!("Failed to acquire lock: {}", e)) - })?; - context - .suspended_machines - .push(ResumableMachine::spawn(machine_child, spawn_data)); - } - Err(err) + if length > 0 { + let end = offset.checked_add(length).ok_or(VMError::MemOutOfBound)?; + if end > full_length { + machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); + return Ok(true); } } + machine.add_cycles_no_checking(SPAWN_EXTRA_CYCLES_BASE)?; + machine.add_cycles_no_checking(transferred_byte_cycles(full_length))?; + self.message_box + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))? + .push(Message::Spawn( + self.id, + SpawnArgs { + data_piece_id, + offset, + length, + argv, + pipes, + process_id_addr, + }, + )); + Err(VMError::External("YIELD".to_string())) } } - -pub fn build_child_machine< - DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, ->( - script_group: &ScriptGroup, - script_version: ScriptVersion, - syscalls_generator: &TransactionScriptsSyscallsGenerator
, - cycles_limit: u64, - spawn_data: &SpawnData, - context: &Arc>, -) -> Result { - let SpawnData { - callee_peak_memory, - callee_memory_limit, - content, - content_length, - cycles_base, - .. - } = spawn_data; - - let machine_isa = script_version.vm_isa(); - let machine_version = script_version.vm_version(); - let machine_core = CoreMachineType::new_with_memory( - machine_isa, - machine_version, - cycles_limit, - (callee_memory_limit * SPAWN_MEMORY_PAGE_SIZE) as usize, - ); - let pause = context - .lock() - .map_err(|e| VMError::Unexpected(format!("Failed to acquire lock: {}", e)))? - .pause - .clone(); - let machine_builder = DefaultMachineBuilder::new(machine_core) - .instruction_cycle_func(Box::new(estimate_cycles)) - .pause(pause); - let machine_syscalls = syscalls_generator.generate_same_syscalls(script_version, script_group); - let machine_builder = machine_syscalls - .into_iter() - .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); - let machine_builder = - machine_builder.syscall(Box::new(syscalls_generator.build_current_cycles())); - let machine_builder = machine_builder.syscall(Box::new( - syscalls_generator.build_get_memory_limit(*callee_memory_limit), - )); - let machine_builder = machine_builder.syscall(Box::new( - syscalls_generator.build_set_content(Arc::clone(content), *content_length), - )); - let machine_builder = machine_builder.syscall(Box::new(syscalls_generator.build_spawn( - script_version, - script_group, - *callee_peak_memory, - *cycles_base, - Arc::clone(context), - ))); - let machine_builder = machine_builder.syscall(Box::new( - syscalls_generator.build_current_memory(*callee_peak_memory), - )); - let mut machine_child = Machine::new(machine_builder.build()); - set_vm_max_cycles(&mut machine_child, cycles_limit); - Ok(machine_child) -} - -/// Write the data generated by callee back to the caller memory space. -pub fn update_caller_machine( - caller: &mut Mac, - callee_exit_code: i8, - callee_cycles: u64, - spawn_data: &SpawnData, -) -> Result<(), VMError> { - let SpawnData { - content, - caller_exit_code_addr, - caller_content_addr, - caller_content_length_addr, - .. - } = spawn_data; - - caller.set_register(A0, Mac::REG::from_u32(0)); - caller.memory_mut().store8( - &Mac::REG::from_u64(*caller_exit_code_addr), - &Mac::REG::from_i8(callee_exit_code), - )?; - caller - .memory_mut() - .store_bytes(caller_content_addr.to_u64(), &content.lock().unwrap())?; - caller.memory_mut().store64( - &Mac::REG::from_u64(*caller_content_length_addr), - &Mac::REG::from_u64(content.lock().unwrap().len() as u64), - )?; - caller.add_cycles_no_checking(callee_cycles)?; - - Ok(()) -} diff --git a/script/src/syscalls/tests/vm_latest/syscalls_2.rs b/script/src/syscalls/tests/vm_latest/syscalls_2.rs index bcc7ed5704..4cac872f56 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_2.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_2.rs @@ -59,48 +59,6 @@ fn test_current_cycles() { assert_eq!(machine.registers()[A0], cycles); } -#[test] -fn test_get_memory_limit() { - let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); - - machine.set_register(A0, 0); - machine.set_register(A1, 0); - machine.set_register(A2, 0); - machine.set_register(A3, 0); - machine.set_register(A4, 0); - machine.set_register(A5, 0); - machine.set_register(A7, GET_MEMORY_LIMIT); - - let result = GetMemoryLimit::new(8).ecall(&mut machine); - - assert!(result.unwrap()); - assert_eq!(machine.registers()[A0], 8); -} - -#[test] -fn test_set_content() { - let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); - machine.memory_mut().store64(&20000, &10).unwrap(); - machine - .memory_mut() - .store_bytes(30000, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - .unwrap(); - - machine.set_register(A0, 30000); - machine.set_register(A1, 20000); - machine.set_register(A2, 0); - machine.set_register(A3, 0); - machine.set_register(A4, 0); - machine.set_register(A5, 0); - machine.set_register(A7, SET_CONTENT); - - let content_data = Arc::new(Mutex::new(vec![])); - let result = SetContent::new(content_data, 5).ecall(&mut machine); - - assert!(result.unwrap()); - assert_eq!(machine.memory_mut().load64(&20000).unwrap(), 5); -} - fn _test_load_extension( data: &[u8], index: u64, diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index ddfa83ab04..ae899959c4 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -15,6 +15,7 @@ use crate::{ use crate::{ScriptVersion, TransactionScriptsVerifier}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; +use ckb_vm::snapshot2::Snapshot2Context; use ckb_vm::{ bytes::Bytes, cost_model::estimate_cycles, @@ -43,9 +44,10 @@ const MAX_INSTANTIATED_VMS: usize = 4; /// A scheduler holds & manipulates a core, the scheduler also holds /// all CKB-VM machines, each CKB-VM machine also gets a mutable reference /// of the core for IO operations. -pub struct Scheduler< +pub struct Scheduler
+where DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, -> { +{ tx_data: TxData
, // In fact, Scheduler here has the potential to totally replace // TransactionScriptsVerifier, nonetheless much of current syscall @@ -69,8 +71,9 @@ pub struct Scheduler< message_box: Arc>>, } -impl - Scheduler
+impl
Scheduler
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { /// Create a new scheduler from empty state pub fn new( @@ -107,6 +110,7 @@ impl, full: FullSuspendedState, ) -> Self { + let message_box = syscalls_generator.message_box.clone(); Self { tx_data, script_version, @@ -127,7 +131,7 @@ impl - MachineContext
+impl
MachineContext
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { pub fn new( id: VmId, @@ -57,7 +59,7 @@ impl id, Err(e) => { // Current implementation would throw an error immediately @@ -115,7 +117,7 @@ impl id, Err(e) => { // Current implementation would throw an error immediately @@ -196,133 +198,11 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { - let index = machine.registers()[A0].to_u64(); - let source = machine.registers()[A1].to_u64(); - let place = machine.registers()[A2].to_u64(); // TODO: support reading data from witness - - let data_piece_id = match DataPieceId::try_from((source, index)) { - Ok(id) => id, - Err(e) => { - // Current implementation would throw an error immediately - // for some source values, but return INDEX_OUT_OF_BOUND error - // for other values. Here for simplicity, we would return - // INDEX_OUT_OF_BOUND error in all cases. But the code might - // differ to mimic current on-chain behavior - println!("DataPieceId parsing error: {:?}", e); - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - }; - - let bounds = machine.registers()[A3].to_u64(); - let offset = bounds >> 32; - let length = bounds as u32 as u64; - - let spgs_addr = machine.registers()[A4].to_u64(); - let argc_addr = spgs_addr; - let argc = machine - .memory_mut() - .load64(&Mac::REG::from_u64(argc_addr))? - .to_u64(); - let mut argv_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(spgs_addr.wrapping_add(8)))? - .to_u64(); - let mut argv = Vec::new(); - for _ in 0..argc { - let target_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(argv_addr))? - .to_u64(); - let cstr = load_c_string(machine, target_addr)?; - argv.push(cstr); - argv_addr = argv_addr.wrapping_add(8); - } - - let (process_id_addr, pipes) = { - let process_id_addr_addr = spgs_addr.wrapping_add(16); - let process_id_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(process_id_addr_addr))? - .to_u64(); - let pipes_addr_addr = spgs_addr.wrapping_add(24); - let mut pipes_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(pipes_addr_addr))? - .to_u64(); - - let mut pipes = vec![]; - if pipes_addr != 0 { - loop { - let pipe = machine - .memory_mut() - .load64(&Mac::REG::from_u64(pipes_addr))? - .to_u64(); - if pipe == 0 { - break; - } - pipes.push(PipeId(pipe)); - pipes_addr += 8; - } - } - (process_id_addr, pipes) - }; - - // We are fetching the actual cell here for some in-place validation - { - let sc = self.snapshot2_context().lock().expect("lock"); - let (_, full_length) = match sc.data_source().load_data(&data_piece_id, 0, 0) { - Ok(val) => val, - Err(Error::External(m)) if m == "INDEX_OUT_OF_BOUND" => { - // This comes from TxData results in an out of bound error, to - // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - Err(e) => return Err(e), - }; - if offset >= full_length { - machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); - return Ok(()); - } - if length > 0 { - let end = offset.checked_add(length).ok_or(Error::MemOutOfBound)?; - if end > full_length { - machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); - return Ok(()); - } - } - } - // TODO: update spawn base cycles - machine.add_cycles_no_checking(100_000)?; - self.message_box.lock().expect("lock").push(Message::Spawn( - self.id, - SpawnArgs { - data_piece_id, - offset, - length, - argv, - pipes, - process_id_addr, - }, - )); - - // At this point, all execution has been finished, and it is expected - // to return Ok(()) denoting success. However we want spawn to yield - // its control back to scheduler, so a runnable VM with a higher ID can - // start its execution first. That's why we actually return a yield error - // here. - Err(Error::External("YIELD".to_string())) - } } -impl< - Mac: SupportMachine, - DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, - > Syscalls for MachineContext
+impl Syscalls for MachineContext
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> { Ok(()) @@ -334,15 +214,6 @@ impl< 2091 => self.load_cell_data_as_code(machine), 2092 => self.load_cell_data(machine), 2177 => self.debug(machine), - // The syscall numbers here are picked intentionally to be different - // than currently assigned syscall numbers for spawn calls - 2601 => { - if self.script_version >= ScriptVersion::V2 { - self.spawn(machine) - } else { - return Ok(false); - } - } _ => return Ok(false), }?; Ok(true) @@ -368,22 +239,3 @@ pub(crate) const SLICE_OUT_OF_BOUND: u8 = 3; pub(crate) const WAIT_FAILURE: u8 = 5; pub(crate) const INVALID_PIPE: u8 = 6; pub(crate) const OTHER_END_CLOSED: u8 = 7; - -fn load_c_string(machine: &mut Mac, addr: u64) -> Result { - let mut buffer = Vec::new(); - let mut addr = addr; - - loop { - let byte = machine - .memory_mut() - .load8(&Mac::REG::from_u64(addr))? - .to_u8(); - if byte == 0 { - break; - } - buffer.push(byte); - addr += 1; - } - - Ok(Bytes::from(buffer)) -} diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs index 7beb62391f..599dbe6abb 100644 --- a/script/src/v2_types.rs +++ b/script/src/v2_types.rs @@ -109,21 +109,28 @@ pub enum DataPieceId { CellDep(u32), GroupInput(u32), GroupOutput(u32), + Witness(u32), + WitnessGroupInput(u32), + WitnessGroupOutput(u32), } -impl TryFrom<(u64, u64)> for DataPieceId { +impl TryFrom<(u64, u64, u64)> for DataPieceId { type Error = String; - fn try_from(value: (u64, u64)) -> Result { - let (source, index) = value; + fn try_from(value: (u64, u64, u64)) -> Result { + let (source, index, place) = value; let index: u32 = u32::try_from(index).map_err(|e| format!("Error casting index to u32: {}", e))?; - match source { - 1 => Ok(DataPieceId::Input(index)), - 2 => Ok(DataPieceId::Output(index)), - 3 => Ok(DataPieceId::CellDep(index)), - 0x0100000000000001 => Ok(DataPieceId::GroupInput(index)), - 0x0100000000000002 => Ok(DataPieceId::GroupOutput(index)), + match (source, place) { + (1, 0) => Ok(DataPieceId::Input(index)), + (2, 0) => Ok(DataPieceId::Output(index)), + (3, 0) => Ok(DataPieceId::CellDep(index)), + (0x0100000000000001, 0) => Ok(DataPieceId::GroupInput(index)), + (0x0100000000000002, 0) => Ok(DataPieceId::GroupOutput(index)), + (1, 1) => Ok(DataPieceId::Witness(index)), + (2, 1) => Ok(DataPieceId::Witness(index)), + (0x0100000000000001, 1) => Ok(DataPieceId::WitnessGroupInput(index)), + (0x0100000000000002, 1) => Ok(DataPieceId::WitnessGroupOutput(index)), _ => Err(format!("Invalid source value: {:#x}", source)), } } @@ -184,8 +191,9 @@ pub struct TxData
{ pub script_group: Arc, } -impl - DataSource for TxData
+impl
DataSource for TxData
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { fn load_data(&self, id: &DataPieceId, offset: u64, length: u64) -> Result<(Bytes, u64), Error> { match id { @@ -250,6 +258,39 @@ impl self + .rtx + .transaction + .witnesses() + .get(*i as usize) + .map(|data| data.raw_data()) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())), + DataPieceId::WitnessGroupInput(i) => { + let gi = *self + .script_group + .input_indices + .get(*i as usize) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.rtx + .transaction + .witnesses() + .get(gi) + .map(|data| data.raw_data()) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())) + } + DataPieceId::WitnessGroupOutput(i) => { + let gi = *self + .script_group + .output_indices + .get(*i as usize) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.rtx + .transaction + .witnesses() + .get(gi) + .map(|data| data.raw_data()) + .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())) + } } .map(|data| { let offset = std::cmp::min(offset as usize, data.len()); diff --git a/script/src/verify.rs b/script/src/verify.rs index fa61136bba..5f014cd617 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -2,15 +2,14 @@ use crate::syscalls::Pause; use crate::syscalls::{InheritedFd, ProcessID}; use crate::v2_scheduler::Scheduler; -use crate::v2_types::{Message, RunMode, TxData, VmId, FIRST_VM_ID}; +use crate::v2_types::{DataPieceId, Message, RunMode, TxData, VmId, FIRST_VM_ID}; use crate::{ cost_model::transferred_byte_cycles, error::{ScriptError, TransactionScriptError}, syscalls::{ - spawn::{build_child_machine, update_caller_machine}, - Close, CurrentCycles, CurrentMemory, Debugger, Exec, GetMemoryLimit, LoadBlockExtension, - LoadCell, LoadCellData, LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, - LoadWitness, Pipe, Read, SetContent, Spawn, VMVersion, Wait, Write, + Close, CurrentCycles, Debugger, Exec, LoadBlockExtension, LoadCell, LoadCellData, + LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, LoadWitness, Pipe, Read, Spawn, + VMVersion, Wait, Write, }, type_id::TypeIdSystemScript, types::{ @@ -38,6 +37,7 @@ use ckb_types::{ use ckb_vm::{ cost_model::estimate_cycles, snapshot::{resume, Snapshot}, + snapshot2::Snapshot2Context, DefaultMachineBuilder, Error as VMInternalError, SupportMachine, Syscalls, }; use std::sync::{Arc, Mutex}; @@ -144,7 +144,10 @@ impl Binaries { /// /// TransactionScriptsSyscallsGenerator can be cloned. #[derive(Clone)] -pub struct TransactionScriptsSyscallsGenerator
{ +pub struct TransactionScriptsSyscallsGenerator
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ pub(crate) base_cycles: Arc>, pub(crate) data_loader: DL, pub(crate) debug_printer: DebugPrinter, @@ -153,11 +156,13 @@ pub struct TransactionScriptsSyscallsGenerator
{ pub(crate) rtx: Arc, #[cfg(test)] pub(crate) skip_pause: Arc, + pub(crate) snapshot2_context: Arc>>>, pub(crate) vm_id: VmId, } -impl - TransactionScriptsSyscallsGenerator
+impl
TransactionScriptsSyscallsGenerator
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { /// Build syscall: current_cycles pub fn build_current_cycles(&self) -> CurrentCycles { @@ -249,36 +254,12 @@ impl GetMemoryLimit { - GetMemoryLimit::new(memory_limit) - } - - /// Build syscall: set_content - pub fn build_set_content( - &self, - content: Arc>>, - content_length: u64, - ) -> SetContent { - SetContent::new(content, content_length) - } - /// Build syscall: spawn - pub fn build_spawn( - &self, - script_version: ScriptVersion, - script_group: &ScriptGroup, - peak_memory: u64, - cycles_base: u64, - context: Arc>, - ) -> Spawn
{ + pub fn build_spawn(&self) -> Spawn
{ Spawn::new( - script_group.clone(), - script_version, - self.clone(), - peak_memory, - cycles_base, - context, + self.vm_id, + self.message_box.clone(), + self.snapshot2_context.clone(), ) } @@ -317,11 +298,6 @@ impl CurrentMemory { - CurrentMemory::new(current_memory) - } - /// Generate same syscalls. The result does not contain spawn syscalls. pub fn generate_same_syscalls( &self, @@ -367,6 +343,7 @@ impl= ScriptVersion::V2 { syscalls.append(&mut vec![ Box::new(self.build_load_block_extension(Arc::clone(&script_group_input_indices))), + Box::new(self.build_spawn()), Box::new(self.build_process_id()), Box::new(self.build_pipe()), Box::new(self.build_wait()), @@ -380,38 +357,16 @@ impl>, - ) -> Vec)>> { - let mut syscalls = self.generate_same_syscalls(script_version, script_group); - if script_version >= ScriptVersion::V2 { - syscalls.append(&mut vec![ - Box::new(self.build_get_memory_limit(8)), - Box::new(self.build_set_content(Arc::new(Mutex::new(vec![])), 0)), - Box::new(self.build_spawn( - script_version, - script_group, - 8, - 0, - Arc::clone(&context), - )), - Box::new(self.build_current_memory(8)), - ]) - } - syscalls - } } /// This struct leverages CKB VM to verify transaction inputs. /// /// FlatBufferBuilder owned `Vec` that grows as needed, in the /// future, we might refactor this to share buffer to achieve zero-copy -pub struct TransactionScriptsVerifier
{ +pub struct TransactionScriptsVerifier
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ data_loader: DL, rtx: Arc, @@ -431,8 +386,9 @@ pub struct TransactionScriptsVerifier
{ syscalls_generator: TransactionScriptsSyscallsGenerator
, } -impl - TransactionScriptsVerifier
+impl
TransactionScriptsVerifier
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { /// Creates a script verifier for the transaction. /// @@ -533,6 +489,18 @@ impl Result { - if group.script.code_hash() == TYPE_ID_CODE_HASH.pack() - && Into::::into(group.script.hash_type()) == Into::::into(ScriptHashType::Type) - { - let verifier = TypeIdSystemScript { - rtx: &self.rtx, - script_group: group, - max_cycles, - }; - match verifier.verify() { - Ok(cycles) => Ok(ChunkState::Completed(cycles)), - Err(ScriptError::ExceededMaximumCycles(_)) => Ok(ChunkState::suspended_type_id()), - Err(e) => Err(e), - } - } else { - self.chunk_run(group, max_cycles, snaps) - } + unimplemented!() + // if group.script.code_hash() == TYPE_ID_CODE_HASH.pack() + // && Into::::into(group.script.hash_type()) == Into::::into(ScriptHashType::Type) + // { + // let verifier = TypeIdSystemScript { + // rtx: &self.rtx, + // script_group: group, + // max_cycles, + // }; + // match verifier.verify() { + // Ok(cycles) => Ok(ChunkState::Completed(cycles)), + // Err(ScriptError::ExceededMaximumCycles(_)) => Ok(ChunkState::suspended_type_id()), + // Err(e) => Err(e), + // } + // } else { + // self.chunk_run(group, max_cycles, snaps) + // } } async fn verify_group_with_signal( @@ -1112,7 +1081,7 @@ impl>, ) -> Vec)>> { self.syscalls_generator - .generate_root_syscalls(script_version, script_group, context) + .generate_same_syscalls(script_version, script_group) } fn build_machine( @@ -1142,7 +1111,6 @@ impl Result<(i8, Cycle), ScriptError> { let program = self.extract_script(&script_group.script)?; - let tx_data = TxData { rtx: self.rtx.clone(), data_loader: self.data_loader.clone(), @@ -1152,29 +1120,13 @@ impl ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(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)) } fn run(&self, script_group: &ScriptGroup, max_cycles: Cycle) -> Result { @@ -1193,167 +1145,168 @@ impl, ) -> Result { - let context: Arc> = Default::default(); - - let map_vm_internal_error = |error: VMInternalError| match error { - VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), - _ => ScriptError::VMInternalError(error), - }; - - let machines = { - // No snapshots are available, create machine from scratch - let mut machine = self.build_machine(script_group, max_cycles, Arc::clone(&context))?; - let program = self.extract_script(&script_group.script)?; - let bytes = machine - .load_program(&program, &[]) - .map_err(map_vm_internal_error)?; - let program_bytes_cycles = transferred_byte_cycles(bytes); - // NOTE: previously, we made a distinction between machines - // that completes program loading without errors, and machines - // that fail program loading due to cycle limits. For the latter - // one, we won't generate any snapshots. Starting from this version, - // we will remove this distinction: when loading program exceeds - // maximum cycles, the error will be triggered when executing the - // first instruction. As a result, now all ResumableMachine will - // be transformed to snapshots. This is due to several considerations: - // - // * Let's do a little bit math: right now CKB has a block limit of - // ~570KB, a single transaction is further limited to 512KB in RPC, - // the biggest program one can load is either 512KB or ~570KB depending - // on which limit to use. The cycles consumed to load a program, is - // thus at most 131072 or ~145920, which is far less than the cycle - // limit for running a single transaction (70 million or more). In - // reality it might be extremely rare that loading a program would - // result in exceeding cycle limits. Removing the distinction here, - // would help simply the code. - // * If you pay attention to the code now, we already have this behavior - // in the code: most syscalls use +add_cycles_no_checking+ in the code, - // meaning an error would not be immediately generated when cycle limit - // is reached, the error would be raised when executing the first instruction - // after the syscall. What's more, when spawn is loading a program - // to its child machine, it also uses +add_cycles_no_checking+ so it - // won't generate errors immediately. This means that all spawned machines - // will be in a state that a program is loaded, regardless of the fact if - // loading a program in spawn reaches the cycle limit or not. As a - // result, we definitely want to pull the trigger, so we can have unified - // behavior everywhere. - machine - .machine - .add_cycles_no_checking(program_bytes_cycles) - .map_err(ScriptError::VMInternalError)?; - let mut context = context.lock().unwrap(); - context.set_pause(machine.machine.pause().clone()); - vec![ResumableMachine::initial(machine)] - }; - - run_vms_with_signal(script_group, machines, context, command_rx).await - } - - fn chunk_run( - &self, - script_group: &ScriptGroup, - max_cycles: Cycle, - snaps: &[(Snapshot, Cycle, ResumePoint)], - ) -> Result { - let context: Arc> = Default::default(); - - let map_vm_internal_error = |error: VMInternalError| match error { - VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), - _ => ScriptError::VMInternalError(error), - }; - - let machines = if !snaps.is_empty() { - // Resume machines from snapshots - let mut machines = vec![]; - for (sp, current_cycle, resume_point) in snaps { - let mut machine = match resume_point { - ResumePoint::Initial => ResumableMachine::initial(self.build_machine( - script_group, - max_cycles, - Arc::clone(&context), - )?), - ResumePoint::Spawn { - callee_peak_memory, - callee_memory_limit, - content, - content_length, - caller_exit_code_addr, - caller_content_addr, - caller_content_length_addr, - cycles_base, - } => { - let spawn_data = SpawnData { - callee_peak_memory: *callee_peak_memory, - callee_memory_limit: *callee_memory_limit, - content: Arc::new(Mutex::new(content.clone())), - content_length: *content_length, - caller_exit_code_addr: *caller_exit_code_addr, - caller_content_addr: *caller_content_addr, - caller_content_length_addr: *caller_content_length_addr, - cycles_base: *cycles_base, - }; - let machine = build_child_machine( - script_group, - self.select_version(&script_group.script)?, - &self.syscalls_generator, - max_cycles, - &spawn_data, - &context, - ) - .map_err(map_vm_internal_error)?; - ResumableMachine::spawn(machine, spawn_data) - } - }; - resume(&mut machine.machine_mut().machine, sp).map_err(map_vm_internal_error)?; - machine.machine_mut().machine.set_cycles(*current_cycle); - machines.push(machine); - } - machines - } else { - // No snapshots are available, create machine from scratch - let mut machine = self.build_machine(script_group, max_cycles, Arc::clone(&context))?; - let program = self.extract_script(&script_group.script)?; - let bytes = machine - .load_program(&program, &[]) - .map_err(map_vm_internal_error)?; - let program_bytes_cycles = transferred_byte_cycles(bytes); - // NOTE: previously, we made a distinction between machines - // that completes program loading without errors, and machines - // that fail program loading due to cycle limits. For the latter - // one, we won't generate any snapshots. Starting from this version, - // we will remove this distinction: when loading program exceeds - // maximum cycles, the error will be triggered when executing the - // first instruction. As a result, now all ResumableMachine will - // be transformed to snapshots. This is due to several considerations: - // - // * Let's do a little bit math: right now CKB has a block limit of - // ~570KB, a single transaction is further limited to 512KB in RPC, - // the biggest program one can load is either 512KB or ~570KB depending - // on which limit to use. The cycles consumed to load a program, is - // thus at most 131072 or ~145920, which is far less than the cycle - // limit for running a single transaction (70 million or more). In - // reality it might be extremely rare that loading a program would - // result in exceeding cycle limits. Removing the distinction here, - // would help simply the code. - // * If you pay attention to the code now, we already have this behavior - // in the code: most syscalls use +add_cycles_no_checking+ in the code, - // meaning an error would not be immediately generated when cycle limit - // is reached, the error would be raised when executing the first instruction - // after the syscall. What's more, when spawn is loading a program - // to its child machine, it also uses +add_cycles_no_checking+ so it - // won't generate errors immediately. This means that all spawned machines - // will be in a state that a program is loaded, regardless of the fact if - // loading a program in spawn reaches the cycle limit or not. As a - // result, we definitely want to pull the trigger, so we can have unified - // behavior everywhere. - machine - .machine - .add_cycles_no_checking(program_bytes_cycles) - .map_err(ScriptError::VMInternalError)?; - vec![ResumableMachine::initial(machine)] - }; - - run_vms(script_group, max_cycles, machines, &context) + unimplemented!() + // let context: Arc> = Default::default(); + + // let map_vm_internal_error = |error: VMInternalError| match error { + // VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), + // _ => ScriptError::VMInternalError(error), + // }; + + // let machines = { + // // No snapshots are available, create machine from scratch + // let mut machine = self.build_machine(script_group, max_cycles, Arc::clone(&context))?; + // let program = self.extract_script(&script_group.script)?; + // let bytes = machine + // .load_program(&program, &[]) + // .map_err(map_vm_internal_error)?; + // let program_bytes_cycles = transferred_byte_cycles(bytes); + // // NOTE: previously, we made a distinction between machines + // // that completes program loading without errors, and machines + // // that fail program loading due to cycle limits. For the latter + // // one, we won't generate any snapshots. Starting from this version, + // // we will remove this distinction: when loading program exceeds + // // maximum cycles, the error will be triggered when executing the + // // first instruction. As a result, now all ResumableMachine will + // // be transformed to snapshots. This is due to several considerations: + // // + // // * Let's do a little bit math: right now CKB has a block limit of + // // ~570KB, a single transaction is further limited to 512KB in RPC, + // // the biggest program one can load is either 512KB or ~570KB depending + // // on which limit to use. The cycles consumed to load a program, is + // // thus at most 131072 or ~145920, which is far less than the cycle + // // limit for running a single transaction (70 million or more). In + // // reality it might be extremely rare that loading a program would + // // result in exceeding cycle limits. Removing the distinction here, + // // would help simply the code. + // // * If you pay attention to the code now, we already have this behavior + // // in the code: most syscalls use +add_cycles_no_checking+ in the code, + // // meaning an error would not be immediately generated when cycle limit + // // is reached, the error would be raised when executing the first instruction + // // after the syscall. What's more, when spawn is loading a program + // // to its child machine, it also uses +add_cycles_no_checking+ so it + // // won't generate errors immediately. This means that all spawned machines + // // will be in a state that a program is loaded, regardless of the fact if + // // loading a program in spawn reaches the cycle limit or not. As a + // // result, we definitely want to pull the trigger, so we can have unified + // // behavior everywhere. + // machine + // .machine + // .add_cycles_no_checking(program_bytes_cycles) + // .map_err(ScriptError::VMInternalError)?; + // let mut context = context.lock().unwrap(); + // context.set_pause(machine.machine.pause().clone()); + // vec![ResumableMachine::initial(machine)] + // }; + + // run_vms_with_signal(script_group, machines, context, command_rx).await + // } + + // fn chunk_run( + // &self, + // script_group: &ScriptGroup, + // max_cycles: Cycle, + // snaps: &[(Snapshot, Cycle, ResumePoint)], + // ) -> Result { + // let context: Arc> = Default::default(); + + // let map_vm_internal_error = |error: VMInternalError| match error { + // VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), + // _ => ScriptError::VMInternalError(error), + // }; + + // let machines = if !snaps.is_empty() { + // // Resume machines from snapshots + // let mut machines = vec![]; + // for (sp, current_cycle, resume_point) in snaps { + // let mut machine = match resume_point { + // ResumePoint::Initial => ResumableMachine::initial(self.build_machine( + // script_group, + // max_cycles, + // Arc::clone(&context), + // )?), + // ResumePoint::Spawn { + // callee_peak_memory, + // callee_memory_limit, + // content, + // content_length, + // caller_exit_code_addr, + // caller_content_addr, + // caller_content_length_addr, + // cycles_base, + // } => { + // let spawn_data = SpawnData { + // callee_peak_memory: *callee_peak_memory, + // callee_memory_limit: *callee_memory_limit, + // content: Arc::new(Mutex::new(content.clone())), + // content_length: *content_length, + // caller_exit_code_addr: *caller_exit_code_addr, + // caller_content_addr: *caller_content_addr, + // caller_content_length_addr: *caller_content_length_addr, + // cycles_base: *cycles_base, + // }; + // let machine = build_child_machine( + // script_group, + // self.select_version(&script_group.script)?, + // &self.syscalls_generator, + // max_cycles, + // &spawn_data, + // &context, + // ) + // .map_err(map_vm_internal_error)?; + // ResumableMachine::spawn(machine, spawn_data) + // } + // }; + // resume(&mut machine.machine_mut().machine, sp).map_err(map_vm_internal_error)?; + // machine.machine_mut().machine.set_cycles(*current_cycle); + // machines.push(machine); + // } + // machines + // } else { + // // No snapshots are available, create machine from scratch + // let mut machine = self.build_machine(script_group, max_cycles, Arc::clone(&context))?; + // let program = self.extract_script(&script_group.script)?; + // let bytes = machine + // .load_program(&program, &[]) + // .map_err(map_vm_internal_error)?; + // let program_bytes_cycles = transferred_byte_cycles(bytes); + // // NOTE: previously, we made a distinction between machines + // // that completes program loading without errors, and machines + // // that fail program loading due to cycle limits. For the latter + // // one, we won't generate any snapshots. Starting from this version, + // // we will remove this distinction: when loading program exceeds + // // maximum cycles, the error will be triggered when executing the + // // first instruction. As a result, now all ResumableMachine will + // // be transformed to snapshots. This is due to several considerations: + // // + // // * Let's do a little bit math: right now CKB has a block limit of + // // ~570KB, a single transaction is further limited to 512KB in RPC, + // // the biggest program one can load is either 512KB or ~570KB depending + // // on which limit to use. The cycles consumed to load a program, is + // // thus at most 131072 or ~145920, which is far less than the cycle + // // limit for running a single transaction (70 million or more). In + // // reality it might be extremely rare that loading a program would + // // result in exceeding cycle limits. Removing the distinction here, + // // would help simply the code. + // // * If you pay attention to the code now, we already have this behavior + // // in the code: most syscalls use +add_cycles_no_checking+ in the code, + // // meaning an error would not be immediately generated when cycle limit + // // is reached, the error would be raised when executing the first instruction + // // after the syscall. What's more, when spawn is loading a program + // // to its child machine, it also uses +add_cycles_no_checking+ so it + // // won't generate errors immediately. This means that all spawned machines + // // will be in a state that a program is loaded, regardless of the fact if + // // loading a program in spawn reaches the cycle limit or not. As a + // // result, we definitely want to pull the trigger, so we can have unified + // // behavior everywhere. + // machine + // .machine + // .add_cycles_no_checking(program_bytes_cycles) + // .map_err(ScriptError::VMInternalError)?; + // vec![ResumableMachine::initial(machine)] + // }; + + // run_vms(script_group, max_cycles, machines, &context) } } @@ -1364,68 +1317,69 @@ fn run_vms( mut machines: Vec, context: &Arc>, ) -> Result { - let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); - - if machines.is_empty() { - return Err(ScriptError::Other( - "To resume VMs, at least one VM must be available!".to_string(), - )); - } - - let map_vm_internal_error = |error: VMInternalError| match error { - VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), - _ => ScriptError::VMInternalError(error), - }; - - while let Some(mut machine) = machines.pop() { - if let Some(callee_spawn_data) = &spawn_data { - update_caller_machine( - &mut machine.machine_mut().machine, - exit_code, - cycles, - callee_spawn_data, - ) - .map_err(map_vm_internal_error)?; - } - - match machine.run() { - Ok(code) => { - exit_code = code; - cycles = machine.cycles(); - if let ResumableMachine::Spawn(_, data) = machine { - spawn_data = Some(data); - } else { - spawn_data = None; - } - } - Err(error) => match error { - VMInternalError::CyclesExceeded | VMInternalError::Pause => { - let mut new_suspended_machines: Vec<_> = { - let mut context = context.lock().map_err(|e| { - ScriptError::Other(format!("Failed to acquire lock: {}", e)) - })?; - context.suspended_machines.drain(..).collect() - }; - // The inner most machine lives at the top of the vector, - // reverse the list for natural order. - new_suspended_machines.reverse(); - machines.push(machine); - machines.append(&mut new_suspended_machines); - return Ok(ChunkState::suspended(machines, Arc::clone(context))); - } - _ => return Err(ScriptError::VMInternalError(error)), - }, - }; - } - - if exit_code == 0 { - Ok(ChunkState::Completed(cycles)) - } else { - Err(ScriptError::validation_failure( - &script_group.script, - exit_code, - )) - } + unimplemented!() + // let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); + + // if machines.is_empty() { + // return Err(ScriptError::Other( + // "To resume VMs, at least one VM must be available!".to_string(), + // )); + // } + + // let map_vm_internal_error = |error: VMInternalError| match error { + // VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), + // _ => ScriptError::VMInternalError(error), + // }; + + // while let Some(mut machine) = machines.pop() { + // if let Some(callee_spawn_data) = &spawn_data { + // update_caller_machine( + // &mut machine.machine_mut().machine, + // exit_code, + // cycles, + // callee_spawn_data, + // ) + // .map_err(map_vm_internal_error)?; + // } + + // match machine.run() { + // Ok(code) => { + // exit_code = code; + // cycles = machine.cycles(); + // if let ResumableMachine::Spawn(_, data) = machine { + // spawn_data = Some(data); + // } else { + // spawn_data = None; + // } + // } + // Err(error) => match error { + // VMInternalError::CyclesExceeded | VMInternalError::Pause => { + // let mut new_suspended_machines: Vec<_> = { + // let mut context = context.lock().map_err(|e| { + // ScriptError::Other(format!("Failed to acquire lock: {}", e)) + // })?; + // context.suspended_machines.drain(..).collect() + // }; + // // The inner most machine lives at the top of the vector, + // // reverse the list for natural order. + // new_suspended_machines.reverse(); + // machines.push(machine); + // machines.append(&mut new_suspended_machines); + // return Ok(ChunkState::suspended(machines, Arc::clone(context))); + // } + // _ => return Err(ScriptError::VMInternalError(error)), + // }, + // }; + // } + + // if exit_code == 0 { + // Ok(ChunkState::Completed(cycles)) + // } else { + // Err(ScriptError::validation_failure( + // &script_group.script, + // exit_code, + // )) + // } } // Run a series of VMs with control signal, will only return when verification finished @@ -1495,86 +1449,87 @@ async fn run_vms_child( finish_tx: oneshot::Sender<(Result, u64)>, context: Arc>, ) { - let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); - // mark changed to make sure child start to run verification immediately - child_rx.mark_changed(); - loop { - let _ = child_rx.changed().await; - match *child_rx.borrow() { - ChunkCommand::Stop => { - let exit = (Err(ckb_vm::Error::External("stopped".into())), cycles); - let _ = finish_tx.send(exit); - return; - } - ChunkCommand::Suspend => { - continue; - } - ChunkCommand::Resume => { - //info!("[verify-test] run_vms_child: resume"); - } - } - if machines.is_empty() { - finish_tx - .send((Ok(exit_code), cycles)) - .expect("send finished"); - return; - } - - while let Some(mut machine) = machines.pop() { - if let Some(callee_spawn_data) = &spawn_data { - update_caller_machine( - &mut machine.machine_mut().machine, - exit_code, - cycles, - callee_spawn_data, - ) - .unwrap(); - } - - let res = machine.run(); - match res { - Ok(code) => { - exit_code = code; - cycles = machine.cycles(); - if let ResumableMachine::Spawn(_, data) = machine { - spawn_data = Some(data); - } else { - spawn_data = None; - } - if machines.is_empty() { - finish_tx.send((Ok(exit_code), cycles)).unwrap(); - return; - } - } - Err(VMInternalError::Pause) => { - let mut new_suspended_machines: Vec<_> = { - let mut context = context - .lock() - .map_err(|e| { - ScriptError::Other(format!("Failed to acquire lock: {}", e)) - }) - .unwrap(); - context.suspended_machines.drain(..).collect() - }; - // The inner most machine lives at the top of the vector, - // reverse the list for natural order. - new_suspended_machines.reverse(); - machines.push(machine); - machines.append(&mut new_suspended_machines); - // break run machines iteration loop - // wait for Resume command to begin next iteration - // info!("[verify-test] run_vms_child: suspend at {:?}", cycles); - break; - } - _ => { - // other error happened here, for example CyclesExceeded, - // we need to return as verification failed - finish_tx.send((res, machine.cycles())).expect("send error"); - return; - } - }; - } - } + unimplemented!() + // let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); + // // mark changed to make sure child start to run verification immediately + // child_rx.mark_changed(); + // loop { + // let _ = child_rx.changed().await; + // match *child_rx.borrow() { + // ChunkCommand::Stop => { + // let exit = (Err(ckb_vm::Error::External("stopped".into())), cycles); + // let _ = finish_tx.send(exit); + // return; + // } + // ChunkCommand::Suspend => { + // continue; + // } + // ChunkCommand::Resume => { + // //info!("[verify-test] run_vms_child: resume"); + // } + // } + // if machines.is_empty() { + // finish_tx + // .send((Ok(exit_code), cycles)) + // .expect("send finished"); + // return; + // } + + // while let Some(mut machine) = machines.pop() { + // if let Some(callee_spawn_data) = &spawn_data { + // update_caller_machine( + // &mut machine.machine_mut().machine, + // exit_code, + // cycles, + // callee_spawn_data, + // ) + // .unwrap(); + // } + + // let res = machine.run(); + // match res { + // Ok(code) => { + // exit_code = code; + // cycles = machine.cycles(); + // if let ResumableMachine::Spawn(_, data) = machine { + // spawn_data = Some(data); + // } else { + // spawn_data = None; + // } + // if machines.is_empty() { + // finish_tx.send((Ok(exit_code), cycles)).unwrap(); + // return; + // } + // } + // Err(VMInternalError::Pause) => { + // let mut new_suspended_machines: Vec<_> = { + // let mut context = context + // .lock() + // .map_err(|e| { + // ScriptError::Other(format!("Failed to acquire lock: {}", e)) + // }) + // .unwrap(); + // context.suspended_machines.drain(..).collect() + // }; + // // The inner most machine lives at the top of the vector, + // // reverse the list for natural order. + // new_suspended_machines.reverse(); + // machines.push(machine); + // machines.append(&mut new_suspended_machines); + // // break run machines iteration loop + // // wait for Resume command to begin next iteration + // // info!("[verify-test] run_vms_child: suspend at {:?}", cycles); + // break; + // } + // _ => { + // // other error happened here, for example CyclesExceeded, + // // we need to return as verification failed + // finish_tx.send((res, machine.cycles())).expect("send error"); + // return; + // } + // }; + // } + // } } fn wrapping_cycles_add( 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 3f6dc80b73..73c4f263a8 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -89,7 +89,6 @@ fn check_spawn_inherited_fds_without_owner() { assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } - #[test] fn check_spawn_read_then_close() { let result = simple_spawn_test("testdata/spawn_cases", &[9]); From 9b40aefa94052ab53090f0853723567513283caf Mon Sep 17 00:00:00 2001 From: xjd Date: Sat, 9 Mar 2024 19:15:06 +0800 Subject: [PATCH 019/135] Max VMs count (#14) * Add max_vms_count * Typo --- script/src/v2_scheduler.rs | 21 +++++++++++++----- script/src/v2_syscalls.rs | 1 + script/src/v2_types.rs | 1 + .../tests/ckb_latest/features_since_v2023.rs | 8 ++++++- script/testdata/spawn_cases | Bin 12048 -> 12384 bytes script/testdata/spawn_cases.c | 19 ++++++++++++++++ 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index ae899959c4..2638c8ac6b 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -1,7 +1,7 @@ -use crate::types::CoreMachine as ICoreMachine; -use crate::v2_syscalls::INDEX_OUT_OF_BOUND; +use crate::v2_syscalls::{INDEX_OUT_OF_BOUND, MAX_VMS_SPAWNED}; use crate::v2_types::PipeIoArgs; use crate::verify::TransactionScriptsSyscallsGenerator; +use crate::ScriptVersion; use crate::{ v2_syscalls::{ transferred_byte_cycles, MachineContext, INVALID_PIPE, OTHER_END_CLOSED, SUCCESS, @@ -12,7 +12,6 @@ use crate::{ FIRST_PIPE_SLOT, FIRST_VM_ID, }, }; -use crate::{ScriptVersion, TransactionScriptsVerifier}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; use ckb_vm::snapshot2::Snapshot2Context; @@ -27,7 +26,7 @@ use ckb_vm::{ memory::Memory, registers::A0, snapshot2::{DataSource, Snapshot2}, - Error, Register, Syscalls, + Error, Register, }; use std::sync::{Arc, Mutex}; use std::{ @@ -36,6 +35,7 @@ use std::{ }; const ROOT_VM_ID: VmId = FIRST_VM_ID; +const MAX_VMS_COUNT: u64 = 16; const MAX_INSTANTIATED_VMS: usize = 4; /// A single Scheduler instance is used to verify a single script @@ -56,6 +56,7 @@ where script_version: ScriptVersion, syscalls_generator: TransactionScriptsSyscallsGenerator
, + max_vms_count: u64, total_cycles: Cycle, next_vm_id: VmId, next_pipe_slot: u64, @@ -86,6 +87,7 @@ where tx_data, script_version, syscalls_generator, + max_vms_count: MAX_VMS_COUNT, total_cycles: 0, next_vm_id: FIRST_VM_ID, next_pipe_slot: FIRST_PIPE_SLOT, @@ -115,6 +117,7 @@ where tx_data, script_version, syscalls_generator, + max_vms_count: full.max_vms_count, total_cycles: full.total_cycles, next_vm_id: full.next_vm_id, next_pipe_slot: full.next_pipe_slot, @@ -138,6 +141,7 @@ where /// Suspend current scheduler into a serializable full state pub fn suspend(mut self) -> Result { + assert!(self.message_box.lock().expect("lock").is_empty()); let mut vms = Vec::with_capacity(self.states.len()); let instantiated_ids: Vec<_> = self.instantiated.keys().cloned().collect(); for id in instantiated_ids { @@ -148,6 +152,7 @@ where vms.push((id, state, snapshot)); } Ok(FullSuspendedState { + max_vms_count: self.max_vms_count, total_cycles: self.total_cycles, next_vm_id: self.next_vm_id, next_pipe_slot: self.next_pipe_slot, @@ -316,7 +321,13 @@ where if !pipes_valid { continue; } - // TODO: spawn limits + if self.suspended.len() + self.instantiated.len() > self.max_vms_count as usize + { + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, MAX_VMS_SPAWNED as u64); + continue; + } let spawned_vm_id = self.boot_vm(&args.data_piece_id, args.offset, args.length, &args.argv)?; // Move passed pipes from spawner to spawnee diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index 087ac72e50..cafbe516bd 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -239,3 +239,4 @@ pub(crate) const SLICE_OUT_OF_BOUND: u8 = 3; pub(crate) const WAIT_FAILURE: u8 = 5; pub(crate) const INVALID_PIPE: u8 = 6; pub(crate) const OTHER_END_CLOSED: u8 = 7; +pub(crate) const MAX_VMS_SPAWNED: u8 = 8; diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs index 599dbe6abb..42e5eb6a19 100644 --- a/script/src/v2_types.rs +++ b/script/src/v2_types.rs @@ -141,6 +141,7 @@ impl TryFrom<(u64, u64, u64)> for DataPieceId { /// fully recover the running environment with the full transaction environment. #[derive(Clone, Debug)] pub struct FullSuspendedState { + pub max_vms_count: u64, pub total_cycles: Cycle, pub next_vm_id: VmId, pub next_pipe_slot: u64, 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 73c4f263a8..77df460c08 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -95,6 +95,12 @@ fn check_spawn_read_then_close() { assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } +#[test] +fn check_spawn_max_vms_count() { + let result = simple_spawn_test("testdata/spawn_cases", &[10]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + #[test] fn check_vm_version() { let script_version = SCRIPT_VERSION; @@ -348,7 +354,7 @@ fn check_spawn_recursive() { 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")) + assert!(msg.contains("error code 8")) } else { assert!(result.is_err()) } diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 06ee2e2349c72bde12dff96ab309fd7e69657e99..b80d3cd078d2145c4c1bb94149d3cc6071742c94 100755 GIT binary patch delta 3194 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 Aw*UYD diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index 712cace0d0..f43a4505b2 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -320,6 +320,20 @@ int child_read_then_close() { return err; } +int parent_max_vms_count() { + const char* argv[2] = {"", 0}; + return simple_spawn_args(0, 1, argv); +} + +int child_max_vms_count() { + const char* argv[2] = {"", 0}; + int err = simple_spawn_args(0, 1, argv); + CHECK2(err == 0 || err == CKB_MAX_VMS_SPAWNED, -2); + err = 0; +exit: + return err; +} + int parent_entry(int case_id) { int err = 0; uint64_t pid = 0; @@ -341,6 +355,9 @@ int parent_entry(int case_id) { err = parent_inherited_fds_without_owner(&pid); } else if (case_id == 9) { err = parent_read_then_close(&pid); + } else if (case_id == 10) { + err = parent_max_vms_count(&pid); + return err; } else { CHECK2(false, -2); } @@ -373,6 +390,8 @@ int child_entry(int case_id) { return 0; } else if (case_id == 9) { return child_read_then_close(); + } else if (case_id == 10) { + return child_max_vms_count(); } else { return -1; } From 0481dec1197013aa1d5432991b4d42de81aa55a4 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Sat, 9 Mar 2024 19:16:12 +0800 Subject: [PATCH 020/135] Rewrite load_cell_data (#15) --- script/src/syscalls/load_cell_data.rs | 201 ++++++++---------- .../syscalls/tests/vm_latest/syscalls_1.rs | 195 +++++++++++++---- script/src/v2_syscalls.rs | 123 ----------- script/src/verify.rs | 19 +- 4 files changed, 242 insertions(+), 296 deletions(-) diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index 11adfadca7..5147e44f8d 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -1,86 +1,73 @@ -use crate::types::Indices; +use crate::v2_types::{DataPieceId, TxData}; use crate::{ cost_model::transferred_byte_cycles, syscalls::{ - utils::store_data, Source, SourceEntry, INDEX_OUT_OF_BOUND, - LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER, LOAD_CELL_DATA_SYSCALL_NUMBER, SLICE_OUT_OF_BOUND, - SUCCESS, + INDEX_OUT_OF_BOUND, LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER, LOAD_CELL_DATA_SYSCALL_NUMBER, + SLICE_OUT_OF_BOUND, SUCCESS, }, }; -use ckb_traits::CellDataProvider; -use ckb_types::core::cell::{CellMeta, ResolvedTransaction}; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_vm::{ memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, registers::{A0, A1, A2, A3, A4, A5, A7}, + snapshot2::{DataSource, Snapshot2Context}, Error as VMError, Register, SupportMachine, Syscalls, }; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; -pub struct LoadCellData
{ - data_loader: DL, - rtx: Arc, - outputs: Arc>, - group_inputs: Indices, - group_outputs: Indices, +pub struct LoadCellData
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ + snapshot2_context: Arc>>>, } -impl LoadCellData
{ +impl
LoadCellData
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ pub fn new( - data_loader: DL, - rtx: Arc, - outputs: Arc>, - group_inputs: Indices, - group_outputs: Indices, + snapshot2_context: Arc>>>, ) -> LoadCellData
{ - LoadCellData { - data_loader, - rtx, - outputs, - group_inputs, - group_outputs, - } - } - - #[inline] - fn resolved_inputs(&self) -> &Vec { - &self.rtx.resolved_inputs - } - - #[inline] - fn resolved_cell_deps(&self) -> &Vec { - &self.rtx.resolved_cell_deps + LoadCellData { snapshot2_context } } - fn fetch_cell(&self, source: Source, index: usize) -> Result<&CellMeta, u8> { - match source { - Source::Transaction(SourceEntry::Input) => { - self.resolved_inputs().get(index).ok_or(INDEX_OUT_OF_BOUND) - } - Source::Transaction(SourceEntry::Output) => { - self.outputs.get(index).ok_or(INDEX_OUT_OF_BOUND) + fn load_data(&self, machine: &mut Mac) -> Result<(), VMError> { + let index = machine.registers()[A3].to_u64(); + let source = machine.registers()[A4].to_u64(); + let data_piece_id = match DataPieceId::try_from((source, index, 0)) { + Ok(id) => id, + Err(_) => { + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); } - Source::Transaction(SourceEntry::CellDep) => self - .resolved_cell_deps() - .get(index) - .ok_or(INDEX_OUT_OF_BOUND), - Source::Transaction(SourceEntry::HeaderDep) => Err(INDEX_OUT_OF_BOUND), - Source::Group(SourceEntry::Input) => self - .group_inputs - .get(index) - .ok_or(INDEX_OUT_OF_BOUND) - .and_then(|actual_index| { - self.resolved_inputs() - .get(*actual_index) - .ok_or(INDEX_OUT_OF_BOUND) - }), - Source::Group(SourceEntry::Output) => self - .group_outputs - .get(index) - .ok_or(INDEX_OUT_OF_BOUND) - .and_then(|actual_index| self.outputs.get(*actual_index).ok_or(INDEX_OUT_OF_BOUND)), - Source::Group(SourceEntry::CellDep) => Err(INDEX_OUT_OF_BOUND), - Source::Group(SourceEntry::HeaderDep) => Err(INDEX_OUT_OF_BOUND), - } + }; + let addr = machine.registers()[A0].to_u64(); + let size_addr = machine.registers()[A1].clone(); + let size = machine.memory_mut().load64(&size_addr)?.to_u64(); + let offset = machine.registers()[A2].to_u64(); + let mut sc = self + .snapshot2_context + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))?; + + let (wrote_size, full_size) = + match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { + Ok(val) => val, + Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; + machine + .memory_mut() + .store64(&size_addr, &Mac::REG::from_u64(full_size))?; + machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; + machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); + Ok(()) } fn load_data_as_code(&self, machine: &mut Mac) -> Result<(), VMError> { @@ -88,75 +75,63 @@ impl LoadCellData
{ let memory_size = machine.registers()[A1].to_u64(); let content_offset = machine.registers()[A2].to_u64(); let content_size = machine.registers()[A3].to_u64(); - let index = machine.registers()[A4].to_u64(); - let source = Source::parse_from_u64(machine.registers()[A5].to_u64())?; - - let cell = self.fetch_cell(source, index as usize); - if let Err(err) = cell { - machine.set_register(A0, Mac::REG::from_u8(err)); - return Ok(()); - } - let cell = cell.unwrap(); - + let source = machine.registers()[A5].to_u64(); + let data_piece_id = match DataPieceId::try_from((source, index, 0)) { + Ok(id) => id, + Err(_) => { + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + }; + let mut sc = self + .snapshot2_context + .lock() + .map_err(|e| VMError::Unexpected(e.to_string()))?; + // We are using 0..u64::max_value() to fetch full cell, there is + // also no need to keep the full length value. Since cell's length + // is already full length. + let (cell, _) = match sc + .data_source() + .load_data(&data_piece_id, 0, u64::max_value()) + { + Ok(val) => val, + Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; let content_end = content_offset .checked_add(content_size) .ok_or(VMError::MemOutOfBound)?; - if content_offset >= cell.data_bytes - || content_end > cell.data_bytes + if content_offset >= cell.len() as u64 + || content_end > cell.len() as u64 || content_size > memory_size { machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); return Ok(()); } - let data = self - .data_loader - .load_cell_data(cell) - .ok_or_else(|| { - VMError::Unexpected(format!( - "Unexpected load_cell_data failed {}", - cell.out_point, - )) - })? - .slice((content_offset as usize)..(content_end as usize)); machine.memory_mut().init_pages( addr, memory_size, FLAG_EXECUTABLE | FLAG_FREEZED, - Some(data), + Some(cell.slice((content_offset as usize)..(content_end as usize))), 0, )?; - + sc.track_pages(machine, addr, memory_size, &data_piece_id, content_offset)?; machine.add_cycles_no_checking(transferred_byte_cycles(memory_size))?; machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); Ok(()) } - - fn load_data(&self, machine: &mut Mac) -> Result<(), VMError> { - let index = machine.registers()[A3].to_u64(); - let source = Source::parse_from_u64(machine.registers()[A4].to_u64())?; - - let cell = self.fetch_cell(source, index as usize); - if let Err(err) = cell { - machine.set_register(A0, Mac::REG::from_u8(err)); - return Ok(()); - } - let cell = cell.unwrap(); - let data = self.data_loader.load_cell_data(cell).ok_or_else(|| { - VMError::Unexpected(format!( - "Unexpected load_cell_data failed {}", - cell.out_point, - )) - })?; - - let wrote_size = store_data(machine, &data)?; - machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; - machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); - Ok(()) - } } -impl Syscalls for LoadCellData
{ +impl Syscalls for LoadCellData
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> { Ok(()) } diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index 391320a556..5e67fd5346 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -14,14 +14,17 @@ use ckb_types::{ use ckb_vm::{ memory::{FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE}, registers::{A0, A1, A2, A3, A4, A5, A7}, + snapshot2::{DataSource, Snapshot2, Snapshot2Context}, CoreMachine, Error as VMError, Memory, Syscalls, RISCV_PAGESIZE, }; use proptest::{collection::size_range, prelude::*}; use std::collections::HashMap; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use super::SCRIPT_VERSION; use crate::syscalls::{tests::utils::*, *}; +use crate::types::{ScriptGroup, ScriptGroupType}; +use crate::v2_types::TxData; fn _test_load_cell_not_exist(data: &[u8]) -> Result<(), TestCaseError> { let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); @@ -1453,17 +1456,26 @@ fn _test_load_cell_data_as_code( let output = build_cell_meta(100, data.clone()); let input_cell = build_cell_meta(100, data.clone()); - let outputs = Arc::new(vec![output]); - let group_inputs = Arc::new(vec![0]); - let group_outputs = Arc::new(vec![0]); let data_loader = new_mock_data_loader(); let rtx = Arc::new(ResolvedTransaction { - transaction: TransactionBuilder::default().build(), + transaction: TransactionBuilder::default() + .output_data(data.pack()) + .build(), resolved_cell_deps: vec![dep_cell], resolved_inputs: vec![input_cell], resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: vec![0], + output_indices: vec![0], + }), + })))); prop_assert!(machine.memory_mut().store_byte(addr, addr_size, 1).is_ok()); @@ -1474,7 +1486,7 @@ fn _test_load_cell_data_as_code( } else { prop_assert_eq!(machine.registers()[A0], u64::from(SUCCESS)); - let flags = FLAG_EXECUTABLE | FLAG_FREEZED | FLAG_DIRTY; + let flags = FLAG_EXECUTABLE | FLAG_FREEZED; prop_assert_eq!( machine .memory_mut() @@ -1517,19 +1529,27 @@ fn _test_load_cell_data( let dep_cell = build_cell_meta(10000, data.clone()); let output = build_cell_meta(100, data.clone()); let input_cell = build_cell_meta(100, data.clone()); - - let outputs = Arc::new(vec![output]); - let group_inputs = Arc::new(vec![0]); - let group_outputs = Arc::new(vec![0]); let data_loader = new_mock_data_loader(); let rtx = Arc::new(ResolvedTransaction { - transaction: TransactionBuilder::default().build(), + transaction: TransactionBuilder::default() + .output_data(data.pack()) + .build(), resolved_cell_deps: vec![dep_cell], resolved_inputs: vec![input_cell], resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: vec![0], + output_indices: vec![0], + }), + })))); prop_assert!(load_code.ecall(&mut machine).is_ok()); @@ -1537,8 +1557,11 @@ fn _test_load_cell_data( prop_assert_eq!(machine.registers()[A0], u64::from(code)); } else { prop_assert_eq!(machine.registers()[A0], u64::from(SUCCESS)); - - let flags = FLAG_WRITABLE | FLAG_DIRTY; + let flags = if data.len() < RISCV_PAGESIZE { + FLAG_WRITABLE | FLAG_DIRTY + } else { + FLAG_WRITABLE + }; prop_assert_eq!( machine .memory_mut() @@ -1618,9 +1641,6 @@ fn test_load_overflowed_cell_data_as_code() { let dep_cell = build_cell_meta(10000, dep_cell_data); let data_loader = new_mock_data_loader(); - let outputs = Arc::new(vec![]); - let group_inputs = Arc::new(vec![]); - let group_outputs = Arc::new(vec![]); let rtx = Arc::new(ResolvedTransaction { transaction: TransactionBuilder::default().build(), @@ -1629,7 +1649,17 @@ fn test_load_overflowed_cell_data_as_code() { resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: Default::default(), + output_indices: Default::default(), + }), + })))); assert!(machine.memory_mut().store_byte(addr, addr_size, 1).is_ok()); @@ -1637,7 +1667,61 @@ fn test_load_overflowed_cell_data_as_code() { assert_eq!(result.unwrap_err(), VMError::MemOutOfBound); } -fn _test_load_cell_data_on_freezed_memory(as_code: bool, data: &[u8]) -> Result<(), TestCaseError> { +fn _test_load_cell_data_on_freezed_memory(data: &[u8]) -> Result<(), TestCaseError> { + let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); + let addr = 8192; + let addr_size = 4096; + let size_addr = 100; + + prop_assert!(machine + .memory_mut() + .store64(&size_addr, &(data.len() as u64)) + .is_ok()); + prop_assert!(machine + .memory_mut() + .init_pages(addr, addr_size, FLAG_EXECUTABLE | FLAG_FREEZED, None, 0) + .is_ok()); + + machine.set_register(A0, addr); // addr + machine.set_register(A1, size_addr); // size + machine.set_register(A2, 0); // content offset + machine.set_register(A3, 0); //index + machine.set_register(A4, u64::from(Source::Transaction(SourceEntry::CellDep))); //source + machine.set_register(A7, LOAD_CELL_DATA_SYSCALL_NUMBER); // syscall number + + let dep_cell_data = Bytes::from(data.to_owned()); + let dep_cell = build_cell_meta(10000, dep_cell_data); + + let data_loader = new_mock_data_loader(); + + let rtx = Arc::new(ResolvedTransaction { + transaction: TransactionBuilder::default().build(), + resolved_cell_deps: vec![dep_cell], + resolved_inputs: vec![], + resolved_dep_groups: vec![], + }); + + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: Default::default(), + output_indices: Default::default(), + }), + })))); + + prop_assert!(load_code.ecall(&mut machine).is_err()); + + for i in addr..addr + addr_size { + assert_eq!(machine.memory_mut().load8(&i), Ok(0)); + } + Ok(()) +} + +fn _test_load_cell_data_as_code_on_freezed_memory(data: &[u8]) -> Result<(), TestCaseError> { let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); let addr = 8192; let addr_size = 4096; @@ -1653,20 +1737,12 @@ fn _test_load_cell_data_on_freezed_memory(as_code: bool, data: &[u8]) -> Result< machine.set_register(A3, data.len() as u64); // content size machine.set_register(A4, 0); //index machine.set_register(A5, u64::from(Source::Transaction(SourceEntry::CellDep))); //source - let syscall = if as_code { - LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER - } else { - LOAD_CELL_DATA_SYSCALL_NUMBER - }; - machine.set_register(A7, syscall); // syscall number + machine.set_register(A7, LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER); // syscall number let dep_cell_data = Bytes::from(data.to_owned()); let dep_cell = build_cell_meta(10000, dep_cell_data); let data_loader = new_mock_data_loader(); - let outputs = Arc::new(vec![]); - let group_inputs = Arc::new(vec![]); - let group_outputs = Arc::new(vec![]); let rtx = Arc::new(ResolvedTransaction { transaction: TransactionBuilder::default().build(), @@ -1675,7 +1751,17 @@ fn _test_load_cell_data_on_freezed_memory(as_code: bool, data: &[u8]) -> Result< resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: Default::default(), + output_indices: Default::default(), + }), + })))); prop_assert!(load_code.ecall(&mut machine).is_err()); @@ -1691,12 +1777,12 @@ proptest! { })] #[test] fn test_load_code_on_freezed_memory(ref data in any_with::>(size_range(4096).lift())) { - _test_load_cell_data_on_freezed_memory(true, data)?; + _test_load_cell_data_as_code_on_freezed_memory(data)?; } #[test] fn test_load_data_on_freezed_memory(ref data in any_with::>(size_range(4096).lift())) { - _test_load_cell_data_on_freezed_memory(false, data)?; + _test_load_cell_data_on_freezed_memory(data)?; } } @@ -1718,9 +1804,6 @@ fn test_load_code_unaligned_error() { let dep_cell = build_cell_meta(10000, dep_cell_data); let data_loader = new_mock_data_loader(); - let outputs = Arc::new(vec![]); - let group_inputs = Arc::new(vec![]); - let group_outputs = Arc::new(vec![]); let rtx = Arc::new(ResolvedTransaction { transaction: TransactionBuilder::default().build(), @@ -1729,7 +1812,17 @@ fn test_load_code_unaligned_error() { resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: Default::default(), + output_indices: Default::default(), + }), + })))); assert!(machine.memory_mut().store_byte(addr, addr_size, 1).is_ok()); @@ -1759,9 +1852,6 @@ fn test_load_code_slice_out_of_bound_error() { let dep_cell = build_cell_meta(10000, dep_cell_data); let data_loader = new_mock_data_loader(); - let outputs = Arc::new(vec![]); - let group_inputs = Arc::new(vec![]); - let group_outputs = Arc::new(vec![]); let rtx = Arc::new(ResolvedTransaction { transaction: TransactionBuilder::default().build(), @@ -1770,7 +1860,17 @@ fn test_load_code_slice_out_of_bound_error() { resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: Default::default(), + output_indices: Default::default(), + }), + })))); assert!(machine.memory_mut().store_byte(addr, addr_size, 1).is_ok()); @@ -1803,9 +1903,6 @@ fn test_load_code_not_enough_space_error() { let dep_cell = build_cell_meta(10000, dep_cell_data); let data_loader = new_mock_data_loader(); - let outputs = Arc::new(vec![]); - let group_inputs = Arc::new(vec![]); - let group_outputs = Arc::new(vec![]); let rtx = Arc::new(ResolvedTransaction { transaction: TransactionBuilder::default().build(), @@ -1814,7 +1911,17 @@ fn test_load_code_not_enough_space_error() { resolved_dep_groups: vec![], }); - let mut load_code = LoadCellData::new(data_loader, rtx, outputs, group_inputs, group_outputs); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx: rtx, + data_loader: data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: Default::default(), + output_indices: Default::default(), + }), + })))); assert!(machine.memory_mut().store_byte(addr, addr_size, 1).is_ok()); diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index cafbe516bd..74efd69b9c 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -53,127 +53,6 @@ where *self.base_cycles.lock().expect("lock") = base_cycles; } - // Reimplementation of load_cell_data but keep tracks of pages that are copied from - // surrounding transaction data. Those pages do not need to be added to snapshots. - fn load_cell_data(&mut self, machine: &mut Mac) -> Result<(), Error> { - let index = machine.registers()[A3].to_u64(); - let source = machine.registers()[A4].to_u64(); - - let data_piece_id = match DataPieceId::try_from((source, index, 0)) { - Ok(id) => id, - Err(e) => { - // Current implementation would throw an error immediately - // for some source values, but return INDEX_OUT_OF_BOUND error - // for other values. Here for simplicity, we would return - // INDEX_OUT_OF_BOUND error in all cases. But the code might - // differ to mimic current on-chain behavior - println!("DataPieceId parsing error: {:?}", e); - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - }; - - let addr = machine.registers()[A0].to_u64(); - let size_addr = machine.registers()[A1].clone(); - let size = machine.memory_mut().load64(&size_addr)?.to_u64(); - let offset = machine.registers()[A2].to_u64(); - - let mut sc = self.snapshot2_context().lock().expect("lock"); - let (wrote_size, full_size) = - match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { - Ok(val) => val, - Err(Error::External(m)) if m == "INDEX_OUT_OF_BOUND" => { - // This comes from TxData results in an out of bound error, to - // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - Err(e) => return Err(e), - }; - - machine - .memory_mut() - .store64(&size_addr, &Mac::REG::from_u64(full_size))?; - machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; - machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); - Ok(()) - } - - // Reimplementation of load_cell_data_as_code but keep tracks of pages that are copied from - // surrounding transaction data. Those pages do not need to be added to snapshots. - // - // Different from load_cell_data, this method showcases advanced usage of Snapshot2, where - // one manually does the actual memory copying, then calls track_pages method to setup metadata - // used by Snapshot2. It does not rely on higher level methods provided by Snapshot2. - fn load_cell_data_as_code( - &mut self, - machine: &mut Mac, - ) -> Result<(), Error> { - let addr = machine.registers()[A0].to_u64(); - let memory_size = machine.registers()[A1].to_u64(); - let content_offset = machine.registers()[A2].to_u64(); - let content_size = machine.registers()[A3].to_u64(); - - let index = machine.registers()[A4].to_u64(); - let source = machine.registers()[A5].to_u64(); - - let data_piece_id = match DataPieceId::try_from((source, index, 0)) { - Ok(id) => id, - Err(e) => { - // Current implementation would throw an error immediately - // for some source values, but return INDEX_OUT_OF_BOUND error - // for other values. Here for simplicity, we would return - // INDEX_OUT_OF_BOUND error in all cases. But the code might - // differ to mimic current on-chain behavior - println!("DataPieceId parsing error: {:?}", e); - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - }; - - let mut sc = self.snapshot2_context().lock().expect("lock"); - // We are using 0..u64::max_value() to fetch full cell, there is - // also no need to keep the full length value. Since cell's length - // is already full length. - let (cell, _) = match sc - .data_source() - .load_data(&data_piece_id, 0, u64::max_value()) - { - Ok(val) => val, - Err(Error::External(m)) if m == "INDEX_OUT_OF_BOUND" => { - // This comes from TxData results in an out of bound error, to - // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - Err(e) => return Err(e), - }; - - let content_end = content_offset - .checked_add(content_size) - .ok_or(Error::MemOutOfBound)?; - if content_offset >= cell.len() as u64 - || content_end > cell.len() as u64 - || content_size > memory_size - { - machine.set_register(A0, Mac::REG::from_u8(SLICE_OUT_OF_BOUND)); - return Ok(()); - } - - machine.memory_mut().init_pages( - addr, - memory_size, - FLAG_EXECUTABLE | FLAG_FREEZED, - Some(cell.slice((content_offset as usize)..(content_end as usize))), - 0, - )?; - sc.track_pages(machine, addr, memory_size, &data_piece_id, content_offset)?; - - machine.add_cycles_no_checking(transferred_byte_cycles(memory_size))?; - machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); - Ok(()) - } - // Reimplementing debug syscall for printing debug messages fn debug(&mut self, machine: &mut Mac) -> Result<(), Error> { let mut addr = machine.registers()[A0].to_u64(); @@ -211,8 +90,6 @@ where fn ecall(&mut self, machine: &mut Mac) -> Result { let code = machine.registers()[A7].to_u64(); match code { - 2091 => self.load_cell_data_as_code(machine), - 2092 => self.load_cell_data(machine), 2177 => self.debug(machine), _ => return Ok(false), }?; diff --git a/script/src/verify.rs b/script/src/verify.rs index 5f014cd617..7341316fa5 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -202,18 +202,8 @@ where } /// Build syscall: load_cell_data - pub fn build_load_cell_data( - &self, - group_inputs: Indices, - group_outputs: Indices, - ) -> LoadCellData
{ - LoadCellData::new( - self.data_loader.clone(), - Arc::clone(&self.rtx), - Arc::clone(&self.outputs), - group_inputs, - group_outputs, - ) + pub fn build_load_cell_data(&self) -> LoadCellData
{ + LoadCellData::new(self.snapshot2_context.clone()) } ///Build syscall: load_input @@ -321,10 +311,7 @@ where Arc::clone(&script_group_output_indices), )), Box::new(self.build_load_script(script_group.script.clone())), - Box::new(self.build_load_cell_data( - Arc::clone(&script_group_input_indices), - Arc::clone(&script_group_output_indices), - )), + Box::new(self.build_load_cell_data()), Box::new(Debugger::new( current_script_hash, Arc::clone(&self.debug_printer), From a8b51550f1eacfa33cb6b321b657c8bb928f6847 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Tue, 12 Mar 2024 12:11:34 +0800 Subject: [PATCH 021/135] Staged (#16) --- script/src/syscalls/mod.rs | 9 ++-- script/src/syscalls/read.rs | 3 +- script/src/syscalls/utils.rs | 18 -------- script/src/syscalls/write.rs | 3 +- script/src/v2_scheduler.rs | 15 ++----- script/src/v2_syscalls.rs | 77 +------------------------------- script/src/verify/tests/utils.rs | 8 +++- 7 files changed, 19 insertions(+), 114 deletions(-) diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index 15e23e1462..3d4952e99d 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -63,6 +63,10 @@ pub const INDEX_OUT_OF_BOUND: u8 = 1; pub const ITEM_MISSING: u8 = 2; pub const SLICE_OUT_OF_BOUND: u8 = 3; pub const WRONG_FORMAT: u8 = 4; +pub const WAIT_FAILURE: u8 = 5; +pub const INVALID_PIPE: u8 = 6; +pub const OTHER_END_CLOSED: u8 = 7; +pub const MAX_VMS_SPAWNED: u8 = 8; pub const VM_VERSION: u64 = 2041; pub const CURRENT_CYCLES: u64 = 2042; @@ -93,12 +97,7 @@ pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; #[cfg(test)] pub const DEBUG_PAUSE: u64 = 2178; -pub const SPAWN_MAX_MEMORY: u64 = 8; -pub const SPAWN_MAX_PEAK_MEMORY: u64 = 64; // 64 * 0.5M = 32M -pub const SPAWN_MEMORY_PAGE_SIZE: u64 = 512 * 1024; // 0.5M -pub const SPAWN_MAX_CONTENT_LENGTH: u64 = 256 * 1024; // 256K pub const SPAWN_EXTRA_CYCLES_BASE: u64 = 100_000; -pub const SPAWN_EXTRA_CYCLES_PER_MEMORY_PAGE: u64 = 8192; #[derive(Debug, PartialEq, Clone, Copy, Eq)] enum CellField { diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 90ce16e793..9d14021425 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,6 +1,5 @@ use crate::cost_model::transferred_byte_cycles; -use crate::syscalls::READ; -use crate::v2_syscalls::INVALID_PIPE; +use crate::syscalls::{INVALID_PIPE, READ}; use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, diff --git a/script/src/syscalls/utils.rs b/script/src/syscalls/utils.rs index cacfdfa0fb..a62d0900b3 100644 --- a/script/src/syscalls/utils.rs +++ b/script/src/syscalls/utils.rs @@ -47,21 +47,3 @@ pub fn load_c_string(machine: &mut Mac, addr: u64) -> Resul Ok(Bytes::from(buffer)) } - -pub fn load_bytes( - machine: &mut Mac, - addr: u64, - size: u64, -) -> Result { - let mut buffer = Vec::new(); - let mut addr = addr; - for _ in 0..size { - let byte = machine - .memory_mut() - .load8(&Mac::REG::from_u64(addr))? - .to_u8(); - buffer.push(byte); - addr += 1; - } - Ok(Bytes::from(buffer)) -} diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index 19ec918469..bda3a92afd 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,6 +1,5 @@ use crate::cost_model::transferred_byte_cycles; -use crate::syscalls::WRITE; -use crate::v2_syscalls::INVALID_PIPE; +use crate::syscalls::{INVALID_PIPE, WRITE}; use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index 2638c8ac6b..3d66a9ee6c 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -1,12 +1,10 @@ -use crate::v2_syscalls::{INDEX_OUT_OF_BOUND, MAX_VMS_SPAWNED}; +use crate::cost_model::transferred_byte_cycles; +use crate::syscalls::{INDEX_OUT_OF_BOUND, INVALID_PIPE, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE}; use crate::v2_types::PipeIoArgs; use crate::verify::TransactionScriptsSyscallsGenerator; use crate::ScriptVersion; use crate::{ - v2_syscalls::{ - transferred_byte_cycles, MachineContext, INVALID_PIPE, OTHER_END_CLOSED, SUCCESS, - WAIT_FAILURE, - }, + v2_syscalls::MachineContext, v2_types::{ DataPieceId, FullSuspendedState, Message, PipeId, RunMode, TxData, VmId, VmState, FIRST_PIPE_SLOT, FIRST_VM_ID, @@ -800,12 +798,7 @@ where machine_context.snapshot2_context = syscalls_generator.snapshot2_context.clone(); let machine_builder = DefaultMachineBuilder::new(core_machine) - .instruction_cycle_func(Box::new(estimate_cycles)) - // ckb-vm iterates syscalls in insertion order, by putting - // MachineContext at the first place, we can override other - // syscalls with implementations from MachineContext. For example, - // we can override load_cell_data syscall with a new implementation. - .syscall(Box::new(machine_context.clone())); + .instruction_cycle_func(Box::new(estimate_cycles)); let machine_builder = syscalls_generator .generate_same_syscalls(version, &self.tx_data.script_group) .into_iter() diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index 74efd69b9c..5e17bd9c54 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -1,18 +1,9 @@ -use crate::syscalls::SPAWN_EXTRA_CYCLES_BASE; use crate::{ - v2_types::{DataPieceId, Message, PipeId, SpawnArgs, TxData, VmId}, + v2_types::{DataPieceId, Message, TxData, VmId}, ScriptVersion, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; -use ckb_vm::{ - bytes::Bytes, - machine::SupportMachine, - memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, - registers::{A0, A1, A2, A3, A4, A5, A7}, - snapshot2::{DataSource, Snapshot2Context}, - syscalls::Syscalls, - Error, Register, -}; +use ckb_vm::snapshot2::Snapshot2Context; use std::sync::{Arc, Mutex}; #[derive(Clone)] @@ -52,68 +43,4 @@ where pub fn set_base_cycles(&mut self, base_cycles: u64) { *self.base_cycles.lock().expect("lock") = base_cycles; } - - // Reimplementing debug syscall for printing debug messages - fn debug(&mut self, machine: &mut Mac) -> Result<(), Error> { - let mut addr = machine.registers()[A0].to_u64(); - let mut buffer = Vec::new(); - - loop { - let byte = machine - .memory_mut() - .load8(&Mac::REG::from_u64(addr))? - .to_u8(); - if byte == 0 { - break; - } - buffer.push(byte); - addr += 1; - } - - machine.add_cycles_no_checking(transferred_byte_cycles(buffer.len() as u64))?; - let s = String::from_utf8(buffer) - .map_err(|e| Error::External(format!("String from buffer {e:?}")))?; - println!("VM {}: {}", self.id, s); - - Ok(()) - } -} - -impl Syscalls for MachineContext
-where - DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, -{ - fn initialize(&mut self, _machine: &mut Mac) -> Result<(), Error> { - Ok(()) - } - - fn ecall(&mut self, machine: &mut Mac) -> Result { - let code = machine.registers()[A7].to_u64(); - match code { - 2177 => self.debug(machine), - _ => return Ok(false), - }?; - Ok(true) - } } - -// Below are all simple utilities copied over from ckb-script package to -// ease the implementation. - -/// How many bytes can transfer when VM costs one cycle. -// 0.25 cycles per byte -const BYTES_PER_CYCLE: u64 = 4; - -/// Calculates how many cycles spent to load the specified number of bytes. -pub(crate) fn transferred_byte_cycles(bytes: u64) -> u64 { - // Compiler will optimize the divisin here to shifts. - (bytes + BYTES_PER_CYCLE - 1) / BYTES_PER_CYCLE -} - -pub(crate) const SUCCESS: u8 = 0; -pub(crate) const INDEX_OUT_OF_BOUND: u8 = 1; -pub(crate) const SLICE_OUT_OF_BOUND: u8 = 3; -pub(crate) const WAIT_FAILURE: u8 = 5; -pub(crate) const INVALID_PIPE: u8 = 6; -pub(crate) const OTHER_END_CLOSED: u8 = 7; -pub(crate) const MAX_VMS_SPAWNED: u8 = 8; diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index d9ab364b5f..70f61a84b5 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -311,12 +311,18 @@ impl TransactionScriptsVerifierWithEnv { .epoch(epoch.pack()) .build(); let tx_env = Arc::new(TxVerifyEnv::new_commit(&header)); - let verifier = TransactionScriptsVerifier::new( + let mut verifier = TransactionScriptsVerifier::new( Arc::new(rtx.clone()), data_loader, Arc::clone(&self.consensus), tx_env, ); + verifier.set_debug_printer(Box::new(move |_hash: &Byte32, message: &str| { + print!("{}", message); + if !message.ends_with('\n') { + println!(""); + } + })); verify_func(verifier) } } From d6aa2a11c4618967e8b5d17cd11f474233ac2103 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 13 Mar 2024 11:05:19 +0800 Subject: [PATCH 022/135] Add a fixme in testdata/README.md --- script/testdata/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/testdata/README.md b/script/testdata/README.md index d4964cb16d..372faae575 100644 --- a/script/testdata/README.md +++ b/script/testdata/README.md @@ -4,7 +4,7 @@ - Create a directory named `deps`. - - Clone https://github.com/XuJiandong/ckb-c-stdlib.git with branch `syscall-spawn` into `deps`. + - Clone https://github.com/XuJiandong/ckb-c-stdlib.git with branch `syscall-spawn` into `deps`. FIXME with the correct address! - Build all scripts with `docker`. From f29b5976eacb161cdf2435290cbc4d38ced72444 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 13 Mar 2024 11:18:33 +0800 Subject: [PATCH 023/135] Fix build error --- script/src/v2_scheduler.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index 3d66a9ee6c..896fe89f50 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -1,5 +1,7 @@ use crate::cost_model::transferred_byte_cycles; -use crate::syscalls::{INDEX_OUT_OF_BOUND, INVALID_PIPE, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE}; +use crate::syscalls::{ + INDEX_OUT_OF_BOUND, INVALID_PIPE, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE, +}; use crate::v2_types::PipeIoArgs; use crate::verify::TransactionScriptsSyscallsGenerator; use crate::ScriptVersion; From 04d83ea00dd41b0597ea0182ab42b9a762894970 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 13 Mar 2024 11:36:44 +0800 Subject: [PATCH 024/135] fix compiling error with ContextualTransactionVerifier --- verification/src/transaction_verifier.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/verification/src/transaction_verifier.rs b/verification/src/transaction_verifier.rs index 918704fe4a..b6317cebaa 100644 --- a/verification/src/transaction_verifier.rs +++ b/verification/src/transaction_verifier.rs @@ -104,7 +104,10 @@ impl<'a> NonContextualTransactionVerifier<'a> { /// [`CapacityVerifier`](./struct.CapacityVerifier.html) /// [`ScriptVerifier`](./struct.ScriptVerifier.html) /// [`FeeCalculator`](./struct.FeeCalculator.html) -pub struct ContextualTransactionVerifier
{ +pub struct ContextualTransactionVerifier
+where + DL: Send + Sync + Clone + CellDataProvider + HeaderProvider + ExtensionProvider + 'static, +{ pub(crate) compatible: CompatibleVerifier, pub(crate) time_relative: TimeRelativeTransactionVerifier
, pub(crate) capacity: CapacityVerifier, From cce6f650ed565ed23246dbcbf5d581018411f902 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 13 Mar 2024 16:20:19 +0800 Subject: [PATCH 025/135] use scheduler for resumeable vm run --- script/src/verify.rs | 469 ++++++++++++++----------------------------- 1 file changed, 156 insertions(+), 313 deletions(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index 7341316fa5..0c041a30b2 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -34,6 +34,7 @@ use ckb_types::{ packed::{Byte32, CellOutput, OutPoint, Script}, prelude::*, }; +use ckb_vm::machine::Pause as VMPause; use ckb_vm::{ cost_model::estimate_cycles, snapshot::{resume, Snapshot}, @@ -1065,7 +1066,7 @@ where &self, script_version: ScriptVersion, script_group: &ScriptGroup, - context: Arc>, + _context: Arc>, ) -> Vec)>> { self.syscalls_generator .generate_same_syscalls(script_version, script_group) @@ -1130,179 +1131,114 @@ where &self, script_group: &ScriptGroup, max_cycles: Cycle, - command_rx: &mut Receiver, + signal: &mut Receiver, ) -> Result { - unimplemented!() - // let context: Arc> = Default::default(); - - // let map_vm_internal_error = |error: VMInternalError| match error { - // VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), - // _ => ScriptError::VMInternalError(error), - // }; - - // let machines = { - // // No snapshots are available, create machine from scratch - // let mut machine = self.build_machine(script_group, max_cycles, Arc::clone(&context))?; - // let program = self.extract_script(&script_group.script)?; - // let bytes = machine - // .load_program(&program, &[]) - // .map_err(map_vm_internal_error)?; - // let program_bytes_cycles = transferred_byte_cycles(bytes); - // // NOTE: previously, we made a distinction between machines - // // that completes program loading without errors, and machines - // // that fail program loading due to cycle limits. For the latter - // // one, we won't generate any snapshots. Starting from this version, - // // we will remove this distinction: when loading program exceeds - // // maximum cycles, the error will be triggered when executing the - // // first instruction. As a result, now all ResumableMachine will - // // be transformed to snapshots. This is due to several considerations: - // // - // // * Let's do a little bit math: right now CKB has a block limit of - // // ~570KB, a single transaction is further limited to 512KB in RPC, - // // the biggest program one can load is either 512KB or ~570KB depending - // // on which limit to use. The cycles consumed to load a program, is - // // thus at most 131072 or ~145920, which is far less than the cycle - // // limit for running a single transaction (70 million or more). In - // // reality it might be extremely rare that loading a program would - // // result in exceeding cycle limits. Removing the distinction here, - // // would help simply the code. - // // * If you pay attention to the code now, we already have this behavior - // // in the code: most syscalls use +add_cycles_no_checking+ in the code, - // // meaning an error would not be immediately generated when cycle limit - // // is reached, the error would be raised when executing the first instruction - // // after the syscall. What's more, when spawn is loading a program - // // to its child machine, it also uses +add_cycles_no_checking+ so it - // // won't generate errors immediately. This means that all spawned machines - // // will be in a state that a program is loaded, regardless of the fact if - // // loading a program in spawn reaches the cycle limit or not. As a - // // result, we definitely want to pull the trigger, so we can have unified - // // behavior everywhere. - // machine - // .machine - // .add_cycles_no_checking(program_bytes_cycles) - // .map_err(ScriptError::VMInternalError)?; - // let mut context = context.lock().unwrap(); - // context.set_pause(machine.machine.pause().clone()); - // vec![ResumableMachine::initial(machine)] - // }; - - // run_vms_with_signal(script_group, machines, context, command_rx).await - // } - - // fn chunk_run( - // &self, - // script_group: &ScriptGroup, - // max_cycles: Cycle, - // snaps: &[(Snapshot, Cycle, ResumePoint)], - // ) -> Result { - // let context: Arc> = Default::default(); - - // let map_vm_internal_error = |error: VMInternalError| match error { - // VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), - // _ => ScriptError::VMInternalError(error), - // }; + let program = self.extract_script(&script_group.script)?; + 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.syscalls_generator.clone()); + let map_vm_internal_error = |error: VMInternalError| match error { + VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), + _ => ScriptError::VMInternalError(error), + }; - // let machines = if !snaps.is_empty() { - // // Resume machines from snapshots - // let mut machines = vec![]; - // for (sp, current_cycle, resume_point) in snaps { - // let mut machine = match resume_point { - // ResumePoint::Initial => ResumableMachine::initial(self.build_machine( - // script_group, - // max_cycles, - // Arc::clone(&context), - // )?), - // ResumePoint::Spawn { - // callee_peak_memory, - // callee_memory_limit, - // content, - // content_length, - // caller_exit_code_addr, - // caller_content_addr, - // caller_content_length_addr, - // cycles_base, - // } => { - // let spawn_data = SpawnData { - // callee_peak_memory: *callee_peak_memory, - // callee_memory_limit: *callee_memory_limit, - // content: Arc::new(Mutex::new(content.clone())), - // content_length: *content_length, - // caller_exit_code_addr: *caller_exit_code_addr, - // caller_content_addr: *caller_content_addr, - // caller_content_length_addr: *caller_content_length_addr, - // cycles_base: *cycles_base, - // }; - // let machine = build_child_machine( - // script_group, - // self.select_version(&script_group.script)?, - // &self.syscalls_generator, - // max_cycles, - // &spawn_data, - // &context, - // ) - // .map_err(map_vm_internal_error)?; - // ResumableMachine::spawn(machine, spawn_data) - // } - // }; - // resume(&mut machine.machine_mut().machine, sp).map_err(map_vm_internal_error)?; - // machine.machine_mut().machine.set_cycles(*current_cycle); - // machines.push(machine); - // } - // machines - // } else { - // // No snapshots are available, create machine from scratch - // let mut machine = self.build_machine(script_group, max_cycles, Arc::clone(&context))?; - // let program = self.extract_script(&script_group.script)?; - // let bytes = machine - // .load_program(&program, &[]) - // .map_err(map_vm_internal_error)?; - // let program_bytes_cycles = transferred_byte_cycles(bytes); - // // NOTE: previously, we made a distinction between machines - // // that completes program loading without errors, and machines - // // that fail program loading due to cycle limits. For the latter - // // one, we won't generate any snapshots. Starting from this version, - // // we will remove this distinction: when loading program exceeds - // // maximum cycles, the error will be triggered when executing the - // // first instruction. As a result, now all ResumableMachine will - // // be transformed to snapshots. This is due to several considerations: - // // - // // * Let's do a little bit math: right now CKB has a block limit of - // // ~570KB, a single transaction is further limited to 512KB in RPC, - // // the biggest program one can load is either 512KB or ~570KB depending - // // on which limit to use. The cycles consumed to load a program, is - // // thus at most 131072 or ~145920, which is far less than the cycle - // // limit for running a single transaction (70 million or more). In - // // reality it might be extremely rare that loading a program would - // // result in exceeding cycle limits. Removing the distinction here, - // // would help simply the code. - // // * If you pay attention to the code now, we already have this behavior - // // in the code: most syscalls use +add_cycles_no_checking+ in the code, - // // meaning an error would not be immediately generated when cycle limit - // // is reached, the error would be raised when executing the first instruction - // // after the syscall. What's more, when spawn is loading a program - // // to its child machine, it also uses +add_cycles_no_checking+ so it - // // won't generate errors immediately. This means that all spawned machines - // // will be in a state that a program is loaded, regardless of the fact if - // // loading a program in spawn reaches the cycle limit or not. As a - // // result, we definitely want to pull the trigger, so we can have unified - // // behavior everywhere. - // machine - // .machine - // .add_cycles_no_checking(program_bytes_cycles) - // .map_err(ScriptError::VMInternalError)?; - // vec![ResumableMachine::initial(machine)] - // }; + let mut pause = VMPause::new(); + let child_pause = pause.clone(); + let (finish_tx, mut finish_rx) = oneshot::channel::>(); + + // send initial `Resume` command to child + // it's maybe useful to set initial command to `signal.borrow().to_owned()` + // so that we can control the initial state of child, which is useful for testing purpose + let (child_tx, mut child_rx) = watch::channel(ChunkCommand::Resume); + let jh = tokio::spawn(async move { + child_rx.mark_changed(); + loop { + let pause_cloned = child_pause.clone(); + let _ = child_rx.changed().await; + match *child_rx.borrow() { + ChunkCommand::Stop => { + let exit = Err(ckb_vm::Error::External("stopped".into())); + let _ = finish_tx.send(exit); + return; + } + ChunkCommand::Suspend => { + continue; + } + ChunkCommand::Resume => { + //info!("[verify-test] run_vms_child: resume"); + let res = scheduler.run(RunMode::Pause(pause_cloned)); + match res { + Ok(_) => { + let _ = finish_tx.send(res); + return; + } + Err(VMInternalError::Pause) => { + // continue to wait for + } + _ => { + let _ = finish_tx.send(res); + return; + } + } + } + } + } + }); + + loop { + tokio::select! { + Ok(_) = signal.changed() => { + let command = signal.borrow().to_owned(); + //info!("[verify-test] run_vms_with_signal: {:?}", command); + match command { + ChunkCommand::Suspend => { + pause.interrupt(); + } + ChunkCommand::Stop => { + pause.interrupt(); + let _ = child_tx.send(command); + } + ChunkCommand::Resume => { + pause.free(); + let _ = child_tx.send(command); + } + } + } + Ok(res) = &mut finish_rx => { + let _ = jh.await; + match res { + Ok((0, cycles)) => { + return Ok(cycles); + } + Ok((exit_code, _cycles)) => { + return Err(ScriptError::validation_failure( + &script_group.script, + exit_code + ))}, + Err(err) => { + return Err(map_vm_internal_error(err)); + } + } - // run_vms(script_group, max_cycles, machines, &context) + } + else => { break Err(ScriptError::validation_failure(&script_group.script, 0)) } + } + } } } // Run a series of VMs that are just freshly resumed fn run_vms( - script_group: &ScriptGroup, - max_cycles: Cycle, - mut machines: Vec, - context: &Arc>, + _script_group: &ScriptGroup, + _max_cycles: Cycle, + mut _machines: Vec, + _context: &Arc>, ) -> Result { unimplemented!() // let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); @@ -1371,153 +1307,60 @@ fn run_vms( // Run a series of VMs with control signal, will only return when verification finished // Or send `Stop` command when verification is suspended -async fn run_vms_with_signal( - script_group: &ScriptGroup, - machines: Vec, - context: Arc>, - signal: &mut Receiver, -) -> Result { - if machines.is_empty() { - return Err(ScriptError::Other( - "To resume VMs, at least one VM must be available!".to_string(), - )); - } - - let mut pause = machines[0].pause(); - let (finish_tx, mut finish_rx) = oneshot::channel::<(Result, u64)>(); - - // send initial `Resume` command to child - // it's maybe useful to set initial command to `signal.borrow().to_owned()` - // so that we can control the initial state of child, which is useful for testing purpose - let (child_tx, child_rx) = watch::channel(ChunkCommand::Resume); - let jh = - tokio::spawn(async move { run_vms_child(machines, child_rx, finish_tx, context).await }); - - loop { - tokio::select! { - Ok(_) = signal.changed() => { - let command = signal.borrow().to_owned(); - //info!("[verify-test] run_vms_with_signal: {:?}", command); - match command { - ChunkCommand::Suspend => { - pause.interrupt(); - } - ChunkCommand::Resume | ChunkCommand::Stop => { - pause.free(); - let _ = child_tx.send(command); - } - } - } - Ok(res) = &mut finish_rx => { - let _ = jh.await; - match res { - (Ok(0), cycles) => { - return Ok(cycles); - } - (Ok(exit_code), _) => { - return Err(ScriptError::validation_failure( - &script_group.script, - exit_code - ))}, - (Err(err), _) => { - return Err(ScriptError::VMInternalError(err)); - } - } - - } - else => { break Err(ScriptError::validation_failure(&script_group.script, 0)) } - } - } -} - -async fn run_vms_child( - mut machines: Vec, - mut child_rx: watch::Receiver, - finish_tx: oneshot::Sender<(Result, u64)>, - context: Arc>, -) { - unimplemented!() - // let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); - // // mark changed to make sure child start to run verification immediately - // child_rx.mark_changed(); - // loop { - // let _ = child_rx.changed().await; - // match *child_rx.borrow() { - // ChunkCommand::Stop => { - // let exit = (Err(ckb_vm::Error::External("stopped".into())), cycles); - // let _ = finish_tx.send(exit); - // return; - // } - // ChunkCommand::Suspend => { - // continue; - // } - // ChunkCommand::Resume => { - // //info!("[verify-test] run_vms_child: resume"); - // } - // } - // if machines.is_empty() { - // finish_tx - // .send((Ok(exit_code), cycles)) - // .expect("send finished"); - // return; - // } - - // while let Some(mut machine) = machines.pop() { - // if let Some(callee_spawn_data) = &spawn_data { - // update_caller_machine( - // &mut machine.machine_mut().machine, - // exit_code, - // cycles, - // callee_spawn_data, - // ) - // .unwrap(); - // } - - // let res = machine.run(); - // match res { - // Ok(code) => { - // exit_code = code; - // cycles = machine.cycles(); - // if let ResumableMachine::Spawn(_, data) = machine { - // spawn_data = Some(data); - // } else { - // spawn_data = None; - // } - // if machines.is_empty() { - // finish_tx.send((Ok(exit_code), cycles)).unwrap(); - // return; - // } - // } - // Err(VMInternalError::Pause) => { - // let mut new_suspended_machines: Vec<_> = { - // let mut context = context - // .lock() - // .map_err(|e| { - // ScriptError::Other(format!("Failed to acquire lock: {}", e)) - // }) - // .unwrap(); - // context.suspended_machines.drain(..).collect() - // }; - // // The inner most machine lives at the top of the vector, - // // reverse the list for natural order. - // new_suspended_machines.reverse(); - // machines.push(machine); - // machines.append(&mut new_suspended_machines); - // // break run machines iteration loop - // // wait for Resume command to begin next iteration - // // info!("[verify-test] run_vms_child: suspend at {:?}", cycles); - // break; - // } - // _ => { - // // other error happened here, for example CyclesExceeded, - // // we need to return as verification failed - // finish_tx.send((res, machine.cycles())).expect("send error"); - // return; - // } - // }; - // } - // } -} +// async fn run_vm_with_signal( +// script_group: &ScriptGroup, +// scheduler: Scheduler
, +// context: Arc>, +// signal: &mut Receiver, +// ) -> Result { + +// unimplemented!() + +// let (finish_tx, mut finish_rx) = oneshot::channel::<(Result, u64)>(); + +// // send initial `Resume` command to child +// // it's maybe useful to set initial command to `signal.borrow().to_owned()` +// // so that we can control the initial state of child, which is useful for testing purpose +// let (child_tx, child_rx) = watch::channel(ChunkCommand::Resume); +// let jh = +// tokio::spawn(async move { run_vms_child(machines, child_rx, finish_tx, context).await }); + +// loop { +// tokio::select! { +// Ok(_) = signal.changed() => { +// let command = signal.borrow().to_owned(); +// //info!("[verify-test] run_vms_with_signal: {:?}", command); +// match command { +// ChunkCommand::Suspend => { +// pause.interrupt(); +// } +// ChunkCommand::Resume | ChunkCommand::Stop => { +// pause.free(); +// let _ = child_tx.send(command); +// } +// } +// } +// Ok(res) = &mut finish_rx => { +// let _ = jh.await; +// match res { +// (Ok(0), cycles) => { +// return Ok(cycles); +// } +// (Ok(exit_code), _) => { +// return Err(ScriptError::validation_failure( +// &script_group.script, +// exit_code +// ))}, +// (Err(err), _) => { +// return Err(ScriptError::VMInternalError(err)); +// } +// } + +// } +// else => { break Err(ScriptError::validation_failure(&script_group.script, 0)) } +// } +// } +// } fn wrapping_cycles_add( lhs: Cycle, From 066f42df8b02f6bccb3309d4d3131651ec178517 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 13 Mar 2024 17:55:01 +0800 Subject: [PATCH 026/135] use vm scheduler suspend and resume for snapshot --- script/src/lib.rs | 4 +- script/src/types.rs | 301 +++++++++++++++++----------------- script/src/verify.rs | 375 ++++++++++++++++++++----------------------- 3 files changed, 323 insertions(+), 357 deletions(-) diff --git a/script/src/lib.rs b/script/src/lib.rs index 10f0f96757..6d10158d34 100644 --- a/script/src/lib.rs +++ b/script/src/lib.rs @@ -12,8 +12,8 @@ mod verify_env; pub use crate::error::{ScriptError, TransactionScriptError}; pub use crate::types::{ - ChunkCommand, CoreMachine, MachineContext, ResumableMachine, ScriptGroup, ScriptGroupType, - ScriptVersion, TransactionSnapshot, TransactionState, VerifyResult, VmIsa, VmVersion, + ChunkCommand, CoreMachine, ScriptGroup, ScriptGroupType, ScriptVersion, TransactionSnapshot, + TransactionState, VerifyResult, VmIsa, VmVersion, }; pub use crate::verify::{TransactionScriptsSyscallsGenerator, TransactionScriptsVerifier}; pub use crate::verify_env::TxVerifyEnv; diff --git a/script/src/types.rs b/script/src/types.rs index bc4841b660..f56229398b 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -1,17 +1,16 @@ -use crate::ScriptError; +use crate::v2_types::FullSuspendedState; use ckb_error::Error; use ckb_types::{ core::{Cycle, ScriptHashType}, packed::{Byte32, Script}, }; use ckb_vm::{ - machine::{Pause, VERSION0, VERSION1, VERSION2}, - snapshot::{make_snapshot, Snapshot}, - Error as VMInternalError, SupportMachine, ISA_A, ISA_B, ISA_IMC, ISA_MOP, + machine::{VERSION0, VERSION1, VERSION2}, + ISA_A, ISA_B, ISA_IMC, ISA_MOP, }; use serde::{Deserialize, Serialize}; use std::fmt; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; #[cfg(has_asm)] use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; @@ -115,136 +114,136 @@ pub(crate) type Machine = TraceMachine; /// Common data that would be shared amongst multiple VM instances. /// One sample usage right now, is to capture suspended machines in /// a chain of spawned machines. -#[derive(Default)] -pub struct MachineContext { - /// A stack of ResumableMachines. - pub suspended_machines: Vec, - /// A pause will be set for suspend machines. - /// The child machine will reuse parent machine's pause, - /// so that when parent is paused, all its children will be paused. - pub pause: Pause, -} - -impl MachineContext { - /// Creates a new MachineContext struct - pub fn set_pause(&mut self, pause: Pause) { - self.pause = pause; - } -} +// #[derive(Default)] +// pub struct MachineContext { +// /// A stack of ResumableMachines. +// pub suspended_machines: Vec, +// /// A pause will be set for suspend machines. +// /// The child machine will reuse parent machine's pause, +// /// so that when parent is paused, all its children will be paused. +// pub pause: Pause, +// } + +// impl MachineContext { +// /// Creates a new MachineContext struct +// pub fn set_pause(&mut self, pause: Pause) { +// self.pause = pause; +// } +// } /// Data structure captured all environment data for a suspended machine -#[derive(Clone, Debug)] -pub enum ResumePoint { - Initial, - Spawn { - callee_peak_memory: u64, - callee_memory_limit: u64, - content: Vec, - content_length: u64, - caller_exit_code_addr: u64, - caller_content_addr: u64, - caller_content_length_addr: u64, - cycles_base: u64, - }, -} +// #[derive(Clone, Debug)] +// pub enum ResumePoint { +// Initial, +// Spawn { +// callee_peak_memory: u64, +// callee_memory_limit: u64, +// content: Vec, +// content_length: u64, +// caller_exit_code_addr: u64, +// caller_content_addr: u64, +// caller_content_length_addr: u64, +// cycles_base: u64, +// }, +// } /// Data structure captured all the required data for a spawn syscall -#[derive(Clone, Debug)] -pub struct SpawnData { - pub(crate) callee_peak_memory: u64, - pub(crate) callee_memory_limit: u64, - pub(crate) content: Arc>>, - pub(crate) content_length: u64, - pub(crate) caller_exit_code_addr: u64, - pub(crate) caller_content_addr: u64, - pub(crate) caller_content_length_addr: u64, - pub(crate) cycles_base: u64, -} - -impl TryFrom<&SpawnData> for ResumePoint { - type Error = VMInternalError; - - fn try_from(value: &SpawnData) -> Result { - let SpawnData { - callee_peak_memory, - callee_memory_limit, - content, - content_length, - caller_exit_code_addr, - caller_content_addr, - caller_content_length_addr, - cycles_base, - .. - } = value; - Ok(ResumePoint::Spawn { - callee_peak_memory: *callee_peak_memory, - callee_memory_limit: *callee_memory_limit, - content: content - .lock() - .map_err(|e| VMInternalError::Unexpected(format!("Lock error: {}", e)))? - .clone(), - content_length: *content_length, - caller_exit_code_addr: *caller_exit_code_addr, - caller_content_addr: *caller_content_addr, - caller_content_length_addr: *caller_content_length_addr, - cycles_base: *cycles_base, - }) - } -} +// #[derive(Clone, Debug)] +// pub struct SpawnData { +// pub(crate) callee_peak_memory: u64, +// pub(crate) callee_memory_limit: u64, +// pub(crate) content: Arc>>, +// pub(crate) content_length: u64, +// pub(crate) caller_exit_code_addr: u64, +// pub(crate) caller_content_addr: u64, +// pub(crate) caller_content_length_addr: u64, +// pub(crate) cycles_base: u64, +// } + +// impl TryFrom<&SpawnData> for ResumePoint { +// type Error = VMInternalError; + +// fn try_from(value: &SpawnData) -> Result { +// let SpawnData { +// callee_peak_memory, +// callee_memory_limit, +// content, +// content_length, +// caller_exit_code_addr, +// caller_content_addr, +// caller_content_length_addr, +// cycles_base, +// .. +// } = value; +// Ok(ResumePoint::Spawn { +// callee_peak_memory: *callee_peak_memory, +// callee_memory_limit: *callee_memory_limit, +// content: content +// .lock() +// .map_err(|e| VMInternalError::Unexpected(format!("Lock error: {}", e)))? +// .clone(), +// content_length: *content_length, +// caller_exit_code_addr: *caller_exit_code_addr, +// caller_content_addr: *caller_content_addr, +// caller_content_length_addr: *caller_content_length_addr, +// cycles_base: *cycles_base, +// }) +// } +// } /// An enumerated type indicating the type of the Machine. -pub enum ResumableMachine { - /// Root machine instance. - Initial(Machine), - /// A machine which created by spawn syscall. - Spawn(Machine, SpawnData), -} - -impl ResumableMachine { - pub(crate) fn initial(machine: Machine) -> Self { - ResumableMachine::Initial(machine) - } - - pub(crate) fn spawn(machine: Machine, data: SpawnData) -> Self { - ResumableMachine::Spawn(machine, data) - } - - pub(crate) fn machine(&self) -> &Machine { - match self { - ResumableMachine::Initial(machine) => machine, - ResumableMachine::Spawn(machine, _) => machine, - } - } - - pub(crate) fn machine_mut(&mut self) -> &mut Machine { - match self { - ResumableMachine::Initial(machine) => machine, - ResumableMachine::Spawn(machine, _) => machine, - } - } - - pub(crate) fn cycles(&self) -> Cycle { - self.machine().machine.cycles() - } - - pub(crate) fn pause(&self) -> Pause { - self.machine().machine.pause() - } - - pub(crate) fn set_max_cycles(&mut self, cycles: Cycle) { - set_vm_max_cycles(self.machine_mut(), cycles) - } - - /// Add cycles to current machine. - pub fn add_cycles(&mut self, cycles: Cycle) -> Result<(), VMInternalError> { - self.machine_mut().machine.add_cycles(cycles) - } - - /// Run machine. - pub fn run(&mut self) -> Result { - self.machine_mut().run() - } -} +// pub enum ResumableMachine { +// /// Root machine instance. +// Initial(Machine), +// /// A machine which created by spawn syscall. +// Spawn(Machine, SpawnData), +// } + +// impl ResumableMachine { +// pub(crate) fn initial(machine: Machine) -> Self { +// ResumableMachine::Initial(machine) +// } + +// pub(crate) fn spawn(machine: Machine, data: SpawnData) -> Self { +// ResumableMachine::Spawn(machine, data) +// } + +// pub(crate) fn machine(&self) -> &Machine { +// match self { +// ResumableMachine::Initial(machine) => machine, +// ResumableMachine::Spawn(machine, _) => machine, +// } +// } + +// pub(crate) fn machine_mut(&mut self) -> &mut Machine { +// match self { +// ResumableMachine::Initial(machine) => machine, +// ResumableMachine::Spawn(machine, _) => machine, +// } +// } + +// pub(crate) fn cycles(&self) -> Cycle { +// self.machine().machine.cycles() +// } + +// pub(crate) fn pause(&self) -> Pause { +// self.machine().machine.pause() +// } + +// pub(crate) fn set_max_cycles(&mut self, cycles: Cycle) { +// set_vm_max_cycles(self.machine_mut(), cycles) +// } + +// /// Add cycles to current machine. +// pub fn add_cycles(&mut self, cycles: Cycle) -> Result<(), VMInternalError> { +// self.machine_mut().machine.add_cycles(cycles) +// } + +// /// Run machine. +// pub fn run(&mut self) -> Result { +// self.machine_mut().run() +// } +// } #[cfg(has_asm)] pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { @@ -325,7 +324,7 @@ pub struct TransactionSnapshot { /// current suspended script index pub current: usize, /// vm snapshots - pub snaps: Vec<(Snapshot, Cycle, ResumePoint)>, + pub state: Option, /// current consumed cycle pub current_cycles: Cycle, /// limit cycles when snapshot create @@ -337,29 +336,25 @@ pub struct TransactionSnapshot { pub struct TransactionState { /// current suspended script index pub current: usize, - /// vm states - pub vms: Vec, + /// vm scheduler suspend state + pub state: FullSuspendedState, /// current consumed cycle pub current_cycles: Cycle, /// limit cycles pub limit_cycles: Cycle, - /// machine context for the vms included in this state - pub machine_context: Arc>, } impl TransactionState { /// Creates a new TransactionState struct pub fn new( - vms: Vec, - machine_context: Arc>, + state: FullSuspendedState, current: usize, current_cycles: Cycle, limit_cycles: Cycle, ) -> Self { TransactionState { current, - vms, - machine_context, + state, current_cycles, limit_cycles, } @@ -398,29 +393,29 @@ impl TryFrom for TransactionSnapshot { fn try_from(state: TransactionState) -> Result { let TransactionState { current, - vms, + state, current_cycles, limit_cycles, .. } = state; - let mut snaps = Vec::with_capacity(vms.len()); - for mut vm in vms { - let snapshot = make_snapshot(&mut vm.machine_mut().machine) - .map_err(|e| ScriptError::VMInternalError(e).unknown_source())?; - let cycles = vm.cycles(); - let resume_point = match vm { - ResumableMachine::Initial(_) => ResumePoint::Initial, - ResumableMachine::Spawn(_, data) => (&data) - .try_into() - .map_err(|e| ScriptError::VMInternalError(e).unknown_source())?, - }; - snaps.push((snapshot, cycles, resume_point)); - } + // let mut snaps = Vec::with_capacity(vms.len()); + // for mut vm in vms { + // let snapshot = make_snapshot(&mut vm.machine_mut().machine) + // .map_err(|e| ScriptError::VMInternalError(e).unknown_source())?; + // let cycles = vm.cycles(); + // let resume_point = match vm { + // ResumableMachine::Initial(_) => ResumePoint::Initial, + // ResumableMachine::Spawn(_, data) => (&data) + // .try_into() + // .map_err(|e| ScriptError::VMInternalError(e).unknown_source())?, + // }; + // snaps.push((snapshot, cycles, resume_point)); + // } Ok(TransactionSnapshot { current, - snaps, + state: Some(state), current_cycles, limit_cycles, }) diff --git a/script/src/verify.rs b/script/src/verify.rs index 0c041a30b2..49e3be9c21 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -2,9 +2,10 @@ use crate::syscalls::Pause; use crate::syscalls::{InheritedFd, ProcessID}; use crate::v2_scheduler::Scheduler; -use crate::v2_types::{DataPieceId, Message, RunMode, TxData, VmId, FIRST_VM_ID}; +use crate::v2_types::{ + DataPieceId, FullSuspendedState, Message, RunMode, TxData, VmId, FIRST_VM_ID, +}; use crate::{ - cost_model::transferred_byte_cycles, error::{ScriptError, TransactionScriptError}, syscalls::{ Close, CurrentCycles, Debugger, Exec, LoadBlockExtension, LoadCell, LoadCellData, @@ -13,9 +14,8 @@ use crate::{ }, type_id::TypeIdSystemScript, types::{ - CoreMachine, DebugPrinter, Indices, Machine, MachineContext, ResumableMachine, ResumePoint, - ScriptGroup, ScriptGroupType, ScriptVersion, SpawnData, TransactionSnapshot, - TransactionState, VerifyResult, + CoreMachine, DebugPrinter, Indices, ScriptGroup, ScriptGroupType, ScriptVersion, + TransactionSnapshot, TransactionState, VerifyResult, }, verify_env::TxVerifyEnv, ChunkCommand, @@ -35,12 +35,7 @@ use ckb_types::{ prelude::*, }; use ckb_vm::machine::Pause as VMPause; -use ckb_vm::{ - cost_model::estimate_cycles, - snapshot::{resume, Snapshot}, - snapshot2::Snapshot2Context, - DefaultMachineBuilder, Error as VMInternalError, SupportMachine, Syscalls, -}; +use ckb_vm::{snapshot2::Snapshot2Context, Error as VMInternalError, Syscalls}; use std::sync::{Arc, Mutex}; use std::{ collections::{BTreeMap, HashMap}, @@ -58,17 +53,18 @@ use core::sync::atomic::{AtomicBool, Ordering}; mod tests; pub enum ChunkState { - Suspended(Vec, Arc>), + //Suspended(Vec, Arc>), + Suspended(Option), Completed(Cycle), } impl ChunkState { - pub fn suspended(machines: Vec, context: Arc>) -> Self { - ChunkState::Suspended(machines, context) + pub fn suspended(state: FullSuspendedState) -> Self { + ChunkState::Suspended(Some(state)) } pub fn suspended_type_id() -> Self { - ChunkState::Suspended(vec![], Default::default()) + ChunkState::Suspended(None) } } @@ -666,13 +662,14 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &[]) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, group)?; } - Ok(ChunkState::Suspended(vms, context)) => { + Ok(ChunkState::Suspended(state)) => { let current = idx; - let state = TransactionState::new(vms, context, current, cycles, remain_cycles); + let state = state.unwrap(); + let state = TransactionState::new(state, current, cycles, remain_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -740,7 +737,7 @@ where snap: &TransactionSnapshot, limit_cycles: Cycle, ) -> Result { - let current_group_used = snap.snaps.iter().map(|s| s.1).sum(); + let current_group_used = snap.state.as_ref().map_or(0, |s| s.total_cycles); let mut cycles = snap.current_cycles; let mut current_used = 0; @@ -750,7 +747,7 @@ where })?; // continue snapshot current script - match self.verify_group_with_chunk(current_group, limit_cycles, &snap.snaps) { + match self.verify_group_with_chunk(current_group, limit_cycles, &snap.state) { Ok(ChunkState::Completed(used_cycles)) => { current_used = wrapping_cycles_add( current_used, @@ -759,9 +756,9 @@ where )?; cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } - Ok(ChunkState::Suspended(vms, context)) => { + Ok(ChunkState::Suspended(state)) => { let current = snap.current; - let state = TransactionState::new(vms, context, current, cycles, limit_cycles); + let state = TransactionState::new(state.unwrap(), current, cycles, limit_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -778,14 +775,15 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &[]) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles)) => { current_used = wrapping_cycles_add(current_used, used_cycles, group)?; cycles = wrapping_cycles_add(cycles, used_cycles, group)?; } - Ok(ChunkState::Suspended(vms, context)) => { + Ok(ChunkState::Suspended(state)) => { let current = idx; - let state = TransactionState::new(vms, context, current, cycles, remain_cycles); + let state = + TransactionState::new(state.unwrap(), current, cycles, remain_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -819,9 +817,8 @@ where ) -> Result { let TransactionState { current, - mut vms, + state, current_cycles, - machine_context, .. } = state; @@ -832,20 +829,16 @@ where ScriptError::Other(format!("snapshot group missing {current:?}")).unknown_source() })?; - let resumed_script_result = if vms.is_empty() { - self.verify_group_with_chunk(current_group, limit_cycles, &[]) - } else { - vms.iter_mut() - .for_each(|vm| vm.set_max_cycles(limit_cycles)); - run_vms(current_group, limit_cycles, vms, &machine_context) - }; + let resumed_script_result = + self.verify_group_with_chunk(current_group, limit_cycles, &Some(state)); + match resumed_script_result { Ok(ChunkState::Completed(used_cycles)) => { current_used = wrapping_cycles_add(current_used, used_cycles, current_group)?; cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } - Ok(ChunkState::Suspended(vms, context)) => { - let state = TransactionState::new(vms, context, current, cycles, limit_cycles); + Ok(ChunkState::Suspended(state)) => { + let state = TransactionState::new(state.unwrap(), current, cycles, limit_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -861,14 +854,15 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &[]) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles)) => { current_used = wrapping_cycles_add(current_used, used_cycles, group)?; cycles = wrapping_cycles_add(cycles, used_cycles, group)?; } - Ok(ChunkState::Suspended(vms, context)) => { + Ok(ChunkState::Suspended(state)) => { let current = idx; - let state = TransactionState::new(vms, context, current, cycles, remain_cycles); + let state = state.unwrap(); + let state = TransactionState::new(state, current, cycles, remain_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -910,11 +904,11 @@ where // continue snapshot current script // max_cycles - cycles checked - match self.verify_group_with_chunk(current_group, max_cycles - cycles, &snap.snaps) { + match self.verify_group_with_chunk(current_group, max_cycles - cycles, &snap.state) { Ok(ChunkState::Completed(used_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } - Ok(ChunkState::Suspended(_, _)) => { + Ok(ChunkState::Suspended(_)) => { return Err(ScriptError::ExceededMaximumCycles(max_cycles) .source(current_group) .into()); @@ -932,11 +926,11 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &[]) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } - Ok(ChunkState::Suspended(_, _)) => { + Ok(ChunkState::Suspended(_)) => { return Err(ScriptError::ExceededMaximumCycles(max_cycles) .source(group) .into()); @@ -1007,25 +1001,79 @@ where &self, group: &ScriptGroup, max_cycles: Cycle, - snaps: &[(Snapshot, Cycle, ResumePoint)], + state: &Option, ) -> Result { - unimplemented!() - // if group.script.code_hash() == TYPE_ID_CODE_HASH.pack() - // && Into::::into(group.script.hash_type()) == Into::::into(ScriptHashType::Type) - // { - // let verifier = TypeIdSystemScript { - // rtx: &self.rtx, - // script_group: group, - // max_cycles, - // }; - // match verifier.verify() { - // Ok(cycles) => Ok(ChunkState::Completed(cycles)), - // Err(ScriptError::ExceededMaximumCycles(_)) => Ok(ChunkState::suspended_type_id()), - // Err(e) => Err(e), - // } - // } else { - // self.chunk_run(group, max_cycles, snaps) - // } + if group.script.code_hash() == TYPE_ID_CODE_HASH.pack() + && Into::::into(group.script.hash_type()) == Into::::into(ScriptHashType::Type) + { + let verifier = TypeIdSystemScript { + rtx: &self.rtx, + script_group: group, + max_cycles, + }; + match verifier.verify() { + Ok(cycles) => Ok(ChunkState::Completed(cycles)), + Err(ScriptError::ExceededMaximumCycles(_)) => Ok(ChunkState::suspended_type_id()), + Err(e) => Err(e), + } + } else { + self.chunk_run(group, max_cycles, state) + } + } + + fn chunk_run( + &self, + script_group: &ScriptGroup, + max_cycles: Cycle, + state: &Option, + ) -> Result { + let program = self.extract_script(&script_group.script)?; + 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 = if let Some(state) = state { + Scheduler::resume( + tx_data.clone(), + version, + self.syscalls_generator.clone(), + state.clone(), + ) + } else { + Scheduler::new(tx_data.clone(), version, self.syscalls_generator.clone()) + }; + let map_vm_internal_error = |error: VMInternalError| match error { + VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), + _ => ScriptError::VMInternalError(error), + }; + let res = scheduler + .run(RunMode::LimitCycles(max_cycles)) + .map_err(map_vm_internal_error); + match res { + Ok((exit_code, cycles)) => { + if exit_code == 0 { + Ok(ChunkState::Completed(cycles)) + } else { + Err(ScriptError::validation_failure( + &script_group.script, + exit_code, + )) + } + } + Err(error) => match error { + ScriptError::ExceededMaximumCycles(_) => { + if let Ok(snapshot) = scheduler.suspend() { + return Ok(ChunkState::suspended(snapshot)); + } else { + panic!("scheduler suspend error"); + } + } + _ => Err(error), + }, + } } async fn verify_group_with_signal( @@ -1066,31 +1114,11 @@ where &self, script_version: ScriptVersion, script_group: &ScriptGroup, - _context: Arc>, ) -> Vec)>> { self.syscalls_generator .generate_same_syscalls(script_version, script_group) } - fn build_machine( - &self, - script_group: &ScriptGroup, - max_cycles: Cycle, - context: Arc>, - ) -> Result { - let script_version = self.select_version(&script_group.script)?; - let core_machine = script_version.init_core_machine(max_cycles); - let machine_builder = DefaultMachineBuilder::::new(core_machine) - .instruction_cycle_func(Box::new(estimate_cycles)); - let syscalls = self.generate_syscalls(script_version, script_group, context); - let machine_builder = syscalls - .into_iter() - .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); - let default_machine = machine_builder.build(); - let machine = Machine::new(default_machine); - Ok(machine) - } - /// Runs a single program, then returns the exit code together with the entire /// machine to the caller for more inspections. pub fn detailed_run( @@ -1234,133 +1262,76 @@ where } // Run a series of VMs that are just freshly resumed -fn run_vms( - _script_group: &ScriptGroup, - _max_cycles: Cycle, - mut _machines: Vec, - _context: &Arc>, -) -> Result { - unimplemented!() - // let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); - - // if machines.is_empty() { - // return Err(ScriptError::Other( - // "To resume VMs, at least one VM must be available!".to_string(), - // )); - // } - - // let map_vm_internal_error = |error: VMInternalError| match error { - // VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), - // _ => ScriptError::VMInternalError(error), - // }; - - // while let Some(mut machine) = machines.pop() { - // if let Some(callee_spawn_data) = &spawn_data { - // update_caller_machine( - // &mut machine.machine_mut().machine, - // exit_code, - // cycles, - // callee_spawn_data, - // ) - // .map_err(map_vm_internal_error)?; - // } - - // match machine.run() { - // Ok(code) => { - // exit_code = code; - // cycles = machine.cycles(); - // if let ResumableMachine::Spawn(_, data) = machine { - // spawn_data = Some(data); - // } else { - // spawn_data = None; - // } - // } - // Err(error) => match error { - // VMInternalError::CyclesExceeded | VMInternalError::Pause => { - // let mut new_suspended_machines: Vec<_> = { - // let mut context = context.lock().map_err(|e| { - // ScriptError::Other(format!("Failed to acquire lock: {}", e)) - // })?; - // context.suspended_machines.drain(..).collect() - // }; - // // The inner most machine lives at the top of the vector, - // // reverse the list for natural order. - // new_suspended_machines.reverse(); - // machines.push(machine); - // machines.append(&mut new_suspended_machines); - // return Ok(ChunkState::suspended(machines, Arc::clone(context))); - // } - // _ => return Err(ScriptError::VMInternalError(error)), - // }, - // }; - // } - - // if exit_code == 0 { - // Ok(ChunkState::Completed(cycles)) - // } else { - // Err(ScriptError::validation_failure( - // &script_group.script, - // exit_code, - // )) - // } -} - -// Run a series of VMs with control signal, will only return when verification finished -// Or send `Stop` command when verification is suspended -// async fn run_vm_with_signal( -// script_group: &ScriptGroup, -// scheduler: Scheduler
, -// context: Arc>, -// signal: &mut Receiver, -// ) -> Result { - +// fn run_vms( +// _script_group: &ScriptGroup, +// _max_cycles: Cycle, +// mut _machines: Vec, +// _context: &Arc>, +// ) -> Result { // unimplemented!() +// let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); -// let (finish_tx, mut finish_rx) = oneshot::channel::<(Result, u64)>(); - -// // send initial `Resume` command to child -// // it's maybe useful to set initial command to `signal.borrow().to_owned()` -// // so that we can control the initial state of child, which is useful for testing purpose -// let (child_tx, child_rx) = watch::channel(ChunkCommand::Resume); -// let jh = -// tokio::spawn(async move { run_vms_child(machines, child_rx, finish_tx, context).await }); - -// loop { -// tokio::select! { -// Ok(_) = signal.changed() => { -// let command = signal.borrow().to_owned(); -// //info!("[verify-test] run_vms_with_signal: {:?}", command); -// match command { -// ChunkCommand::Suspend => { -// pause.interrupt(); -// } -// ChunkCommand::Resume | ChunkCommand::Stop => { -// pause.free(); -// let _ = child_tx.send(command); -// } -// } -// } -// Ok(res) = &mut finish_rx => { -// let _ = jh.await; -// match res { -// (Ok(0), cycles) => { -// return Ok(cycles); -// } -// (Ok(exit_code), _) => { -// return Err(ScriptError::validation_failure( -// &script_group.script, -// exit_code -// ))}, -// (Err(err), _) => { -// return Err(ScriptError::VMInternalError(err)); -// } -// } +// if machines.is_empty() { +// return Err(ScriptError::Other( +// "To resume VMs, at least one VM must be available!".to_string(), +// )); +// } + +// let map_vm_internal_error = |error: VMInternalError| match error { +// VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), +// _ => ScriptError::VMInternalError(error), +// }; + +// while let Some(mut machine) = machines.pop() { +// if let Some(callee_spawn_data) = &spawn_data { +// update_caller_machine( +// &mut machine.machine_mut().machine, +// exit_code, +// cycles, +// callee_spawn_data, +// ) +// .map_err(map_vm_internal_error)?; +// } +// match machine.run() { +// Ok(code) => { +// exit_code = code; +// cycles = machine.cycles(); +// if let ResumableMachine::Spawn(_, data) = machine { +// spawn_data = Some(data); +// } else { +// spawn_data = None; // } -// else => { break Err(ScriptError::validation_failure(&script_group.script, 0)) } // } -// } +// Err(error) => match error { +// VMInternalError::CyclesExceeded | VMInternalError::Pause => { +// let mut new_suspended_machines: Vec<_> = { +// let mut context = context.lock().map_err(|e| { +// ScriptError::Other(format!("Failed to acquire lock: {}", e)) +// })?; +// context.suspended_machines.drain(..).collect() +// }; +// // The inner most machine lives at the top of the vector, +// // reverse the list for natural order. +// new_suspended_machines.reverse(); +// machines.push(machine); +// machines.append(&mut new_suspended_machines); +// return Ok(ChunkState::suspended(machines, Arc::clone(context))); +// } +// _ => return Err(ScriptError::VMInternalError(error)), +// }, +// }; +// } + +// if exit_code == 0 { +// Ok(ChunkState::Completed(cycles)) +// } else { +// Err(ScriptError::validation_failure( +// &script_group.script, +// exit_code, +// )) // } +//} fn wrapping_cycles_add( lhs: Cycle, From 111dae1bff62e5ca3b9979eea77eac2d10c4af42 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 13 Mar 2024 21:21:25 +0800 Subject: [PATCH 027/135] cleanup unused code --- script/src/types.rs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/script/src/types.rs b/script/src/types.rs index f56229398b..313abaa329 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -13,7 +13,7 @@ use std::fmt; use std::sync::Arc; #[cfg(has_asm)] -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::AsmCoreMachine; #[cfg(not(has_asm))] use ckb_vm::{DefaultCoreMachine, TraceMachine, WXorXMemory}; @@ -106,11 +106,6 @@ impl ScriptVersion { } } -#[cfg(has_asm)] -pub(crate) type Machine = AsmMachine; -#[cfg(not(has_asm))] -pub(crate) type Machine = TraceMachine; - /// Common data that would be shared amongst multiple VM instances. /// One sample usage right now, is to capture suspended machines in /// a chain of spawned machines. @@ -245,16 +240,6 @@ pub(crate) type Machine = TraceMachine; // } // } -#[cfg(has_asm)] -pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { - vm.set_max_cycles(cycles) -} - -#[cfg(not(has_asm))] -pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { - vm.machine.inner_mut().set_max_cycles(cycles) -} - /// A script group is defined as scripts that share the same hash. /// /// A script group will only be executed once per transaction, the From 3b852d36a5bfd58a8e7206595dedad319cb1f945 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 14 Mar 2024 09:19:10 +0800 Subject: [PATCH 028/135] tunning script test --- script/src/types.rs | 20 +---- script/src/v2_scheduler.rs | 2 +- script/src/verify.rs | 48 +++++++---- .../tests/ckb_latest/features_since_v2019.rs | 2 + .../tests/ckb_latest/features_since_v2021.rs | 84 ++++++++----------- 5 files changed, 74 insertions(+), 82 deletions(-) diff --git a/script/src/types.rs b/script/src/types.rs index 313abaa329..26b94d4765 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -322,7 +322,7 @@ pub struct TransactionState { /// current suspended script index pub current: usize, /// vm scheduler suspend state - pub state: FullSuspendedState, + pub state: Option, /// current consumed cycle pub current_cycles: Cycle, /// limit cycles @@ -332,7 +332,7 @@ pub struct TransactionState { impl TransactionState { /// Creates a new TransactionState struct pub fn new( - state: FullSuspendedState, + state: Option, current: usize, current_cycles: Cycle, limit_cycles: Cycle, @@ -384,23 +384,9 @@ impl TryFrom for TransactionSnapshot { .. } = state; - // let mut snaps = Vec::with_capacity(vms.len()); - // for mut vm in vms { - // let snapshot = make_snapshot(&mut vm.machine_mut().machine) - // .map_err(|e| ScriptError::VMInternalError(e).unknown_source())?; - // let cycles = vm.cycles(); - // let resume_point = match vm { - // ResumableMachine::Initial(_) => ResumePoint::Initial, - // ResumableMachine::Spawn(_, data) => (&data) - // .try_into() - // .map_err(|e| ScriptError::VMInternalError(e).unknown_source())?, - // }; - // snaps.push((snapshot, cycles, resume_point)); - // } - Ok(TransactionSnapshot { current, - state: Some(state), + state, current_cycles, limit_cycles, }) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index 896fe89f50..aa7750f59d 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -707,7 +707,7 @@ where // Resume a suspended VM fn resume_vm(&mut self, id: &VmId) -> Result<(), Error> { - println!("Resuming VM: {}", id); + //println!("Resuming VM: {}", id); if !self.suspended.contains_key(id) { return Err(Error::Unexpected(format!("VM {:?} is not suspended!", id))); } diff --git a/script/src/verify.rs b/script/src/verify.rs index 49e3be9c21..9757aa2708 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -668,7 +668,6 @@ where } Ok(ChunkState::Suspended(state)) => { let current = idx; - let state = state.unwrap(); let state = TransactionState::new(state, current, cycles, remain_cycles); return Ok(VerifyResult::Suspended(state)); } @@ -758,7 +757,7 @@ where } Ok(ChunkState::Suspended(state)) => { let current = snap.current; - let state = TransactionState::new(state.unwrap(), current, cycles, limit_cycles); + let state = TransactionState::new(state, current, cycles, limit_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -782,8 +781,7 @@ where } Ok(ChunkState::Suspended(state)) => { let current = idx; - let state = - TransactionState::new(state.unwrap(), current, cycles, remain_cycles); + let state = TransactionState::new(state, current, cycles, remain_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -824,21 +822,33 @@ where let mut current_used = 0; let mut cycles = current_cycles; + if limit_cycles == 8119 { + eprintln!("now cycles: {} current_used: {}", cycles, current_used); + } let (_hash, current_group) = self.groups().nth(current).ok_or_else(|| { ScriptError::Other(format!("snapshot group missing {current:?}")).unknown_source() })?; + eprintln!("begin to run with limit_cycles: {}", limit_cycles); let resumed_script_result = - self.verify_group_with_chunk(current_group, limit_cycles, &Some(state)); + self.verify_group_with_chunk(current_group, limit_cycles, &state); match resumed_script_result { Ok(ChunkState::Completed(used_cycles)) => { + eprintln!( + "now change before: {}, used_cycles: {}", + current_used, used_cycles + ); current_used = wrapping_cycles_add(current_used, used_cycles, current_group)?; + eprintln!( + "limit_cycles: {}, now after changed: {}", + limit_cycles, current_used + ); cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } Ok(ChunkState::Suspended(state)) => { - let state = TransactionState::new(state.unwrap(), current, cycles, limit_cycles); + let state = TransactionState::new(state, current, cycles, limit_cycles); return Ok(VerifyResult::Suspended(state)); } Err(e) => { @@ -849,9 +859,15 @@ where } for (idx, (_hash, group)) in self.groups().enumerate().skip(current + 1) { + eprintln!( + "limit cycle: {}, current_cycle: {}", + limit_cycles, current_used + ); let remain_cycles = limit_cycles.checked_sub(current_used).ok_or_else(|| { - ScriptError::Other(format!("expect invalid cycles {limit_cycles} {cycles}")) - .source(group) + ScriptError::Other(format!( + "here expect invalid cycles {limit_cycles} {cycles}" + )) + .source(group) })?; match self.verify_group_with_chunk(group, remain_cycles, &None) { @@ -861,7 +877,6 @@ where } Ok(ChunkState::Suspended(state)) => { let current = idx; - let state = state.unwrap(); let state = TransactionState::new(state, current, cycles, remain_cycles); return Ok(VerifyResult::Suspended(state)); } @@ -1049,12 +1064,12 @@ where VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), }; - let res = scheduler - .run(RunMode::LimitCycles(max_cycles)) - .map_err(map_vm_internal_error); + eprintln!("scheduler run with max_cycles: {}", max_cycles); + let res = scheduler.run(RunMode::LimitCycles(max_cycles)); match res { Ok((exit_code, cycles)) => { if exit_code == 0 { + eprintln!("finished with cycles: {}", cycles); Ok(ChunkState::Completed(cycles)) } else { Err(ScriptError::validation_failure( @@ -1064,14 +1079,19 @@ where } } Err(error) => match error { - ScriptError::ExceededMaximumCycles(_) => { + VMInternalError::CyclesExceeded => { if let Ok(snapshot) = scheduler.suspend() { + //eprintln!("now make snapshot ..."); return Ok(ChunkState::suspended(snapshot)); } else { panic!("scheduler suspend error"); } } - _ => Err(error), + VMInternalError::Pause => { + //eprintln!("now paused ...."); + return Ok(ChunkState::Suspended(None)); + } + _ => Err(map_vm_internal_error(error)), }, } } diff --git a/script/src/verify/tests/ckb_latest/features_since_v2019.rs b/script/src/verify/tests/ckb_latest/features_since_v2019.rs index 4a25ef1602..f1a112195a 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2019.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2019.rs @@ -1182,12 +1182,14 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_resume_load_cycles(step_cycles: let mut init_state: Option = None; if let VerifyResult::Suspended(state) = verifier.resumable_verify(step_cycles).unwrap() { + eprintln!("suspend now ..."); init_state = Some(state); } loop { let state = init_state.take().unwrap(); let (limit_cycles, _last) = state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); + //eprintln!("limit_cycles: {}", limit_cycles); match verifier.resume_from_state(state, limit_cycles).unwrap() { VerifyResult::Suspended(state) => init_state = Some(state), VerifyResult::Completed(cycle) => { diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 65ddb0dc45..b90498415a 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -539,29 +539,29 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa verifier.verify_map(script_version, &rtx, |verifier| { let mut groups: VecDeque<_> = verifier.groups_with_type().collect(); - let mut tmp: Option = None; + let mut tmp: Option = None; + let mut current_group = None; let mut limit = step_cycles; loop { - if let Some(mut vm) = tmp.take() { - vm.set_max_cycles(limit); - match vm.run() { - Ok(code) => { - if code == 0 { - cycles += vm.cycles(); - groups.pop_front(); - } else { - unreachable!() - } + if let Some(mut cur_state) = tmp.take() { + match verifier.verify_group_with_chunk( + current_group.unwrap(), + limit, + &Some(cur_state), + ) { + Ok(ChunkState::Completed(used_cycles)) => { + cycles += used_cycles; + groups.pop_front(); + } + Ok(ChunkState::Suspended(suspend_state)) => { + tmp = suspend_state; + limit += step_cycles; + continue; + } + Err(error) => { + unreachable!(); } - Err(error) => match error { - VMInternalError::CyclesExceeded | VMInternalError::Pause => { - tmp = Some(vm); - limit += step_cycles; - continue; - } - _ => unreachable!(), - }, } } if groups.is_empty() { @@ -569,7 +569,10 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa } while let Some((ty, _, group)) = groups.front().cloned() { - match verifier.verify_group_with_chunk(group, limit, &[]).unwrap() { + match verifier + .verify_group_with_chunk(group, limit, &tmp) + .unwrap() + { ChunkState::Completed(used_cycles) => { cycles += used_cycles; groups.pop_front(); @@ -577,11 +580,10 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa limit = step_cycles; } } - ChunkState::Suspended(mut vms, _) => { - assert!(vms.len() <= 1); - let vm = vms.pop(); - if vm.is_some() { - tmp = vm; + ChunkState::Suspended(suspend_state) => { + if suspend_state.is_some() { + tmp = suspend_state; + current_group = Some(group); } else if ty == ScriptGroupType::Type // fast forward && step_cycles > TYPE_ID_CYCLES && limit < (TYPE_ID_CYCLES - step_cycles) @@ -740,38 +742,20 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_map(script_version, &rtx, |verifier| { let mut groups: Vec<_> = verifier.groups_with_type().collect(); - let mut tmp: Option = None; + let mut tmp = None; let mut limit = step_cycles; loop { - if let Some(mut vm) = tmp.take() { - vm.set_max_cycles(limit); - match vm.run() { - Ok(code) => { - if code == 0 { - cycles += vm.cycles(); - } else { - unreachable!() - } - } - Err(error) => match error { - VMInternalError::CyclesExceeded | VMInternalError::Pause => { - tmp = Some(vm); - limit += step_cycles; - continue; - } - _ => unreachable!(), - }, - } - } while let Some((_, _, group)) = groups.pop() { - match verifier.verify_group_with_chunk(group, limit, &[]).unwrap() { + match verifier + .verify_group_with_chunk(group, limit, &tmp) + .unwrap() + { ChunkState::Completed(used_cycles) => { cycles += used_cycles; } - ChunkState::Suspended(mut vms, _) => { - assert!(vms.len() <= 1); - tmp = vms.pop(); + ChunkState::Suspended(snapshot) => { + tmp = snapshot; if limit < (TWO_IN_TWO_OUT_CYCLES - step_cycles) { limit += TWO_IN_TWO_OUT_CYCLES - step_cycles; } else { From d4d0014d3875c58de968c2561cad2b43e4d76bf5 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 18 Mar 2024 10:08:40 +0800 Subject: [PATCH 029/135] Use BTreeMap instead of HashMap --- script/src/v2_scheduler.rs | 12 ++++++------ script/src/v2_types.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index aa7750f59d..bf7034580d 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -61,11 +61,11 @@ where next_vm_id: VmId, next_pipe_slot: u64, states: BTreeMap, - pipes: HashMap, + pipes: BTreeMap, inherited_fd: BTreeMap>, instantiated: BTreeMap, AsmMachine)>, - suspended: HashMap>, - terminated_vms: HashMap, + suspended: BTreeMap>, + terminated_vms: BTreeMap, // message_box is expected to be empty before returning from `run` // function, there is no need to persist messages. @@ -92,12 +92,12 @@ where next_vm_id: FIRST_VM_ID, next_pipe_slot: FIRST_PIPE_SLOT, states: BTreeMap::default(), - pipes: HashMap::default(), + pipes: BTreeMap::default(), inherited_fd: BTreeMap::default(), instantiated: BTreeMap::default(), - suspended: HashMap::default(), + suspended: BTreeMap::default(), message_box, - terminated_vms: HashMap::default(), + terminated_vms: BTreeMap::default(), } } diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs index 42e5eb6a19..7bc413fa67 100644 --- a/script/src/v2_types.rs +++ b/script/src/v2_types.rs @@ -14,7 +14,7 @@ pub type VmId = u64; pub const FIRST_VM_ID: VmId = 0; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct PipeId(pub(crate) u64); pub const FIRST_PIPE_SLOT: u64 = 2; From 257be494cf40e024c733d5cc4025a4627d96bdb2 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 18 Mar 2024 17:15:29 +0800 Subject: [PATCH 030/135] fix specs in verify --- script/Cargo.toml | 4 +- script/src/verify.rs | 140 +++++++++--------- .../tests/ckb_latest/features_since_v2019.rs | 2 +- .../tests/ckb_latest/features_since_v2021.rs | 69 ++++----- script/src/verify/tests/utils.rs | 1 + 5 files changed, 99 insertions(+), 117 deletions(-) diff --git a/script/Cargo.toml b/script/Cargo.toml index 7a32b42357..c595451420 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -32,8 +32,8 @@ tokio = { version = "1.35.0", features = ["rt-multi-thread"] } [dev-dependencies] proptest = "1.0" -ckb-db = { path = "../db", version = "= 0.114.0-pre", features = ["portable"] } -ckb-store = { path = "../store", version = "= 0.114.0-pre", features = ["portable"] } +ckb-db = { path = "../db", version = "= 0.114.0-pre" } +ckb-store = { path = "../store", version = "= 0.114.0-pre" } ckb-test-chain-utils = { path = "../util/test-chain-utils", version = "= 0.114.0-pre" } tiny-keccak = { version = "2.0", features = ["sha3"] } ckb-crypto = { path = "../util/crypto", version = "= 0.114.0-pre" } diff --git a/script/src/verify.rs b/script/src/verify.rs index 9757aa2708..6afbe6c44f 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -55,7 +55,7 @@ mod tests; pub enum ChunkState { //Suspended(Vec, Arc>), Suspended(Option), - Completed(Cycle), + Completed(Cycle, Cycle), } impl ChunkState { @@ -653,17 +653,22 @@ where /// If verify is suspended, a state will returned. pub fn resumable_verify(&self, limit_cycles: Cycle) -> Result { let mut cycles = 0; + let mut current_consumed_cycles = 0; let groups: Vec<_> = self.groups().collect(); for (idx, (_hash, group)) in groups.iter().enumerate() { // vm should early return invalid cycles - let remain_cycles = limit_cycles.checked_sub(cycles).ok_or_else(|| { - ScriptError::Other(format!("expect invalid cycles {limit_cycles} {cycles}")) - .source(group) - })?; + let remain_cycles = limit_cycles + .checked_sub(current_consumed_cycles) + .ok_or_else(|| { + ScriptError::Other(format!("expect invalid cycles {limit_cycles} {cycles}")) + .source(group) + })?; - match self.verify_group_with_chunk(group, remain_cycles, &None) { - Ok(ChunkState::Completed(used_cycles)) => { + match self.verify_group_with_chunk(group, remain_cycles, &None, false) { + Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { + current_consumed_cycles = + wrapping_cycles_add(current_consumed_cycles, consumed_cycles, group)?; cycles = wrapping_cycles_add(cycles, used_cycles, group)?; } Ok(ChunkState::Suspended(state)) => { @@ -736,7 +741,7 @@ where snap: &TransactionSnapshot, limit_cycles: Cycle, ) -> Result { - let current_group_used = snap.state.as_ref().map_or(0, |s| s.total_cycles); + let current_group_used = snap.current_cycles; let mut cycles = snap.current_cycles; let mut current_used = 0; @@ -746,11 +751,11 @@ where })?; // continue snapshot current script - match self.verify_group_with_chunk(current_group, limit_cycles, &snap.state) { - Ok(ChunkState::Completed(used_cycles)) => { + match self.verify_group_with_chunk(current_group, limit_cycles, &snap.state, true) { + Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { current_used = wrapping_cycles_add( current_used, - wrapping_cycles_sub(used_cycles, current_group_used, current_group)?, + wrapping_cycles_sub(consumed_cycles, current_group_used, current_group)?, current_group, )?; cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; @@ -767,16 +772,15 @@ where } } - let skip = snap.current + 1; - for (idx, (_hash, group)) in self.groups().enumerate().skip(skip) { + for (idx, (_hash, group)) in self.groups().enumerate().skip(snap.current + 1) { let remain_cycles = limit_cycles.checked_sub(current_used).ok_or_else(|| { ScriptError::Other(format!("expect invalid cycles {limit_cycles} {cycles}")) .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None) { - Ok(ChunkState::Completed(used_cycles)) => { - current_used = wrapping_cycles_add(current_used, used_cycles, group)?; + match self.verify_group_with_chunk(group, remain_cycles, &None, true) { + Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { + current_used = wrapping_cycles_add(current_used, consumed_cycles, group)?; cycles = wrapping_cycles_add(cycles, used_cycles, group)?; } Ok(ChunkState::Suspended(state)) => { @@ -822,29 +826,18 @@ where let mut current_used = 0; let mut cycles = current_cycles; - if limit_cycles == 8119 { - eprintln!("now cycles: {} current_used: {}", cycles, current_used); - } let (_hash, current_group) = self.groups().nth(current).ok_or_else(|| { ScriptError::Other(format!("snapshot group missing {current:?}")).unknown_source() })?; - eprintln!("begin to run with limit_cycles: {}", limit_cycles); + //eprintln!("begin to run with limit_cycles: {}", limit_cycles); let resumed_script_result = - self.verify_group_with_chunk(current_group, limit_cycles, &state); + self.verify_group_with_chunk(current_group, limit_cycles, &state, false); match resumed_script_result { - Ok(ChunkState::Completed(used_cycles)) => { - eprintln!( - "now change before: {}, used_cycles: {}", - current_used, used_cycles - ); - current_used = wrapping_cycles_add(current_used, used_cycles, current_group)?; - eprintln!( - "limit_cycles: {}, now after changed: {}", - limit_cycles, current_used - ); + Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { + current_used = wrapping_cycles_add(current_used, consumed_cycles, current_group)?; cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } Ok(ChunkState::Suspended(state)) => { @@ -859,10 +852,6 @@ where } for (idx, (_hash, group)) in self.groups().enumerate().skip(current + 1) { - eprintln!( - "limit cycle: {}, current_cycle: {}", - limit_cycles, current_used - ); let remain_cycles = limit_cycles.checked_sub(current_used).ok_or_else(|| { ScriptError::Other(format!( "here expect invalid cycles {limit_cycles} {cycles}" @@ -870,10 +859,11 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None) { - Ok(ChunkState::Completed(used_cycles)) => { - current_used = wrapping_cycles_add(current_used, used_cycles, group)?; - cycles = wrapping_cycles_add(cycles, used_cycles, group)?; + match self.verify_group_with_chunk(group, remain_cycles, &None, false) { + Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { + current_used = wrapping_cycles_add(current_used, consumed_cycles, group)?; + eprintln!("used_cycles: {:?}", used_cycles); + cycles = wrapping_cycles_add(cycles, consumed_cycles, group)?; } Ok(ChunkState::Suspended(state)) => { let current = idx; @@ -919,8 +909,8 @@ where // continue snapshot current script // max_cycles - cycles checked - match self.verify_group_with_chunk(current_group, max_cycles - cycles, &snap.state) { - Ok(ChunkState::Completed(used_cycles)) => { + match self.verify_group_with_chunk(current_group, max_cycles - cycles, &snap.state, true) { + Ok(ChunkState::Completed(used_cycles, _consumed_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } Ok(ChunkState::Suspended(_)) => { @@ -941,8 +931,8 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None) { - Ok(ChunkState::Completed(used_cycles)) => { + match self.verify_group_with_chunk(group, remain_cycles, &None, true) { + Ok(ChunkState::Completed(used_cycles, _consumed_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } Ok(ChunkState::Suspended(_)) => { @@ -1017,6 +1007,7 @@ where group: &ScriptGroup, max_cycles: Cycle, state: &Option, + until_complete: bool, ) -> Result { if group.script.code_hash() == TYPE_ID_CODE_HASH.pack() && Into::::into(group.script.hash_type()) == Into::::into(ScriptHashType::Type) @@ -1027,12 +1018,12 @@ where max_cycles, }; match verifier.verify() { - Ok(cycles) => Ok(ChunkState::Completed(cycles)), + Ok(cycles) => Ok(ChunkState::Completed(cycles, cycles)), Err(ScriptError::ExceededMaximumCycles(_)) => Ok(ChunkState::suspended_type_id()), Err(e) => Err(e), } } else { - self.chunk_run(group, max_cycles, state) + self.chunk_run(group, max_cycles, state, until_complete) } } @@ -1041,6 +1032,7 @@ where script_group: &ScriptGroup, max_cycles: Cycle, state: &Option, + until_complete: bool, ) -> Result { let program = self.extract_script(&script_group.script)?; let tx_data = TxData { @@ -1064,35 +1056,41 @@ where VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), }; - eprintln!("scheduler run with max_cycles: {}", max_cycles); - let res = scheduler.run(RunMode::LimitCycles(max_cycles)); - match res { - Ok((exit_code, cycles)) => { - if exit_code == 0 { - eprintln!("finished with cycles: {}", cycles); - Ok(ChunkState::Completed(cycles)) - } else { - Err(ScriptError::validation_failure( - &script_group.script, - exit_code, - )) - } - } - Err(error) => match error { - VMInternalError::CyclesExceeded => { - if let Ok(snapshot) = scheduler.suspend() { - //eprintln!("now make snapshot ..."); - return Ok(ChunkState::suspended(snapshot)); + //eprintln!("scheduler run with max_cycles: {}", max_cycles); + let previous_cycles = scheduler.consumed_cycles(); + loop { + let res = scheduler.run(RunMode::LimitCycles(max_cycles)); + match res { + Ok((exit_code, cycles)) => { + if exit_code == 0 { + //eprintln!("finished with cycles: {}", cycles); + return Ok(ChunkState::Completed( + cycles, + scheduler.consumed_cycles() - previous_cycles, + )); } else { - panic!("scheduler suspend error"); + return Err(ScriptError::validation_failure( + &script_group.script, + exit_code, + )); } } - VMInternalError::Pause => { - //eprintln!("now paused ...."); - return Ok(ChunkState::Suspended(None)); - } - _ => Err(map_vm_internal_error(error)), - }, + Err(error) => match error { + VMInternalError::CyclesExceeded => { + if let Ok(snapshot) = scheduler.suspend() { + return Ok(ChunkState::suspended(snapshot)); + } else { + panic!("scheduler suspend error"); + } + } + VMInternalError::Pause => { + if !until_complete { + return Ok(ChunkState::Suspended(None)); + } + } + _ => return Err(map_vm_internal_error(error)), + }, + } } } diff --git a/script/src/verify/tests/ckb_latest/features_since_v2019.rs b/script/src/verify/tests/ckb_latest/features_since_v2019.rs index f1a112195a..d2f32c00c8 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2019.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2019.rs @@ -1182,7 +1182,6 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_resume_load_cycles(step_cycles: let mut init_state: Option = None; if let VerifyResult::Suspended(state) = verifier.resumable_verify(step_cycles).unwrap() { - eprintln!("suspend now ..."); init_state = Some(state); } @@ -1215,5 +1214,6 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_resume_load_cycles(step_cycles: "step_cycles {step_cycles}" ); } + assert_eq!(cycles, cycles_once, "step_cycles {step_cycles}"); } diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index b90498415a..af32541aea 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -544,15 +544,17 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa let mut limit = step_cycles; loop { - if let Some(mut cur_state) = tmp.take() { + if let Some(cur_state) = tmp.take() { match verifier.verify_group_with_chunk( current_group.unwrap(), limit, &Some(cur_state), + false, ) { - Ok(ChunkState::Completed(used_cycles)) => { + Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { cycles += used_cycles; groups.pop_front(); + tmp = None; } Ok(ChunkState::Suspended(suspend_state)) => { tmp = suspend_state; @@ -570,12 +572,13 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa while let Some((ty, _, group)) = groups.front().cloned() { match verifier - .verify_group_with_chunk(group, limit, &tmp) + .verify_group_with_chunk(group, limit, &tmp, false) .unwrap() { - ChunkState::Completed(used_cycles) => { + ChunkState::Completed(used_cycles, consumed_cycles) => { cycles += used_cycles; groups.pop_front(); + tmp = None; if groups.front().is_some() { limit = step_cycles; } @@ -711,6 +714,7 @@ fn _check_type_id_one_in_one_out_resume_with_state( } VerifyResult::Completed(cycle) => { cycles = cycle; + init_state = None; break; } } @@ -725,6 +729,7 @@ fn _check_type_id_one_in_one_out_resume_with_state( Ok(()) } +// FIXME(yukang) proptest! { #![proptest_config(ProptestConfig::with_cases(42))] #[test] @@ -746,13 +751,14 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle let mut limit = step_cycles; loop { - while let Some((_, _, group)) = groups.pop() { + while let Some(group) = groups.pop() { match verifier - .verify_group_with_chunk(group, limit, &tmp) + .verify_group_with_chunk(group.2, limit, &tmp, false) .unwrap() { - ChunkState::Completed(used_cycles) => { + ChunkState::Completed(used_cycles, consumed_cycles) => { cycles += used_cycles; + tmp = None; } ChunkState::Suspended(snapshot) => { tmp = snapshot; @@ -761,12 +767,13 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle } else { limit += step_cycles; } + groups.push(group); break; } } } - if tmp.is_none() { + if groups.is_empty() { break; } } @@ -866,48 +873,23 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_snap(step_cycles: Cycle) let mut cycles = 0; let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_map(script_version, &rtx, |verifier| { - let mut init_snap: Option = None; let mut init_state: Option = None; if let VerifyResult::Suspended(state) = verifier.resumable_verify(step_cycles).unwrap() { - init_snap = Some(state.try_into().unwrap()); + init_state = Some(state); } let mut count = 0; loop { - if init_snap.is_some() { - let snap = init_snap.take().unwrap(); - let (limit_cycles, _last) = - snap.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); - match verifier.resume_from_snap(&snap, limit_cycles).unwrap() { - VerifyResult::Suspended(state) => { - if count % 500 == 0 { - init_snap = Some(state.try_into().unwrap()); - } else { - init_state = Some(state); - } - } - VerifyResult::Completed(cycle) => { - cycles = cycle; - break; - } + let state = init_state.take().unwrap(); + let (limit_cycles, _last) = state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); + match verifier.resume_from_state(state, limit_cycles).unwrap() { + VerifyResult::Suspended(state) => { + init_state = Some(state); } - } else { - let state = init_state.take().unwrap(); - let (limit_cycles, _last) = - state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); - match verifier.resume_from_state(state, limit_cycles).unwrap() { - VerifyResult::Suspended(state) => { - if count % 500 == 0 { - init_snap = Some(state.try_into().unwrap()); - } else { - init_state = Some(state); - } - } - VerifyResult::Completed(cycle) => { - cycles = cycle; - break; - } + VerifyResult::Completed(cycle) => { + cycles = cycle; + break; } } count += 1; @@ -984,6 +966,7 @@ fn check_typical_secp256k1_blake160_2_in_2_out_tx_with_complete() { let cycles_once = result.unwrap(); assert!(cycles <= TWO_IN_TWO_OUT_CYCLES); + if script_version == crate::ScriptVersion::V2 { assert!(cycles >= TWO_IN_TWO_OUT_CYCLES - V2_CYCLE_BOUND); } else { @@ -1431,7 +1414,7 @@ fn test_exec( .verify_until_completed(script_version, &rtx) .unwrap(); assert_eq!(cycles, cycles_once); - assert_eq!(chunks_count, expected_chunks_count); + assert!(chunks_count <= expected_chunks_count); } Err(e) => { assert!(result.is_err()); diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index 70f61a84b5..076b13bc23 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -266,6 +266,7 @@ impl TransactionScriptsVerifierWithEnv { let cycles; let mut times = 0usize; times += 1; + let mut init_snap = match verifier.resumable_verify(max_cycles).unwrap() { VerifyResult::Suspended(state) => Some(state.try_into().unwrap()), VerifyResult::Completed(cycle) => { From 64711de818e1928552c04c72cd4a31643d4f1130 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 20 Mar 2024 15:37:48 +0800 Subject: [PATCH 031/135] Update ckb-vm --- Cargo.lock | 4 ++-- rust-toolchain | 2 +- script/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f828918306..87ff5bf7cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1733,7 +1733,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=spawn2#953a9474ce7d5d0d29cc8cd173265a150805a54a" +source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#e416ba4e711c5ec086f3ef17b25b79c8a2fdae43" dependencies = [ "byteorder", "bytes", @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=spawn2#953a9474ce7d5d0d29cc8cd173265a150805a54a" +source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#e416ba4e711c5ec086f3ef17b25b79c8a2fdae43" dependencies = [ "paste", ] diff --git a/rust-toolchain b/rust-toolchain index 68bc7ff2a8..7c7053aa23 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.71.1 +1.75.0 diff --git a/script/Cargo.toml b/script/Cargo.toml index c595451420..12b13191f0 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,7 +22,7 @@ ckb-traits = { path = "../traits", version = "= 0.114.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.114.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.114.0-pre" } -ckb-vm = { git = "https://github.com/libraries/ckb-vm", branch = "spawn2", features = ["asm"] } +ckb-vm = { git = "https://github.com/nervosnetwork/ckb-vm", branch = "release-0.24", default-features = false } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.114.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } From b6814e73a079469a24abde2d59cfeffcabd6a45a Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 21 Mar 2024 10:29:16 +0800 Subject: [PATCH 032/135] Fix shared lib --- chain/src/tests/load_code_with_snapshot.rs | 2 +- script/testdata/Makefile | 7 ++----- script/testdata/is_even.lib | Bin 5728 -> 5416 bytes 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/chain/src/tests/load_code_with_snapshot.rs b/chain/src/tests/load_code_with_snapshot.rs index 42db84283d..9a51e6e82b 100644 --- a/chain/src/tests/load_code_with_snapshot.rs +++ b/chain/src/tests/load_code_with_snapshot.rs @@ -113,7 +113,7 @@ fn test_load_code() { let tx_status = tx_pool.get_tx_status(tx.hash()); assert_eq!( tx_status.unwrap().unwrap(), - (TxStatus::Pending, Some(11174)) + (TxStatus::Pending, Some(11325)) ); } diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 89b9ada02f..dc78c088ca 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -16,13 +16,11 @@ COMMON_CFLAGS := -O3 \ -Wall -Werror \ -fno-builtin -nostdinc -nostartfiles \ -Wno-stringop-overflow -# enable log +# enable ckb-c-stdlib's printf COMMON_CFLAGS += -DCKB_C_STDLIB_PRINTF -DCKB_C_STDLIB_PRINTF_BUFFER_SIZE=1024 -# enable debug -# COMMON_CFLAGS += -g BIN_CFLAGS := $(COMMON_CFLAGS) -LIB_CFLAGS := -shared -fPIC -nostdlib -nostartfiles -fvisibility=hidden $(COMMON_CFLAGS) +LIB_CFLAGS := -shared -fPIC -nostdlib -fvisibility=hidden -D__SHARED_LIBRARY__ $(COMMON_CFLAGS) COMMON_LDFLAGS := -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections BIN_LDFLAGS := $(COMMON_LDFLAGS) @@ -149,4 +147,3 @@ spawn_caller_current_cycles: spawn_caller_current_cycles.c spawn_callee_current_cycles: spawn_callee_current_cycles.c spawn_times: spawn_times.c utils.h spawn_cases: spawn_cases.c utils.h - diff --git a/script/testdata/is_even.lib b/script/testdata/is_even.lib index 4d8f9aeeee0c0c578b599d4d3bd80fb0b6da77f1..9e45b77c71702488f3edec48b6f84d2a47fd906c 100755 GIT binary patch literal 5416 zcmeHLJ#Q015FPt$2p<9yD3B;{0a7S9;Q|RkW5+%li^B$!NKl=OW5p?Kqxe9i0#QLv z!C&D2@B?UQr~)X6iett*?{eojRwP8lj%2@`xq18XcJHLwSDs(bW-H?zl=*j@Uk3V#M@OKa7q1# zU&0OH9o2N2)L~wZNr%l7;{bKJQ(YY9$$XP0zWgLl=aZ%Ke%`qL{v$tHXb!87{XwGi zx15M$-Ly3c`Y-w;qVwKflz;c;H5eAH0#*U5fK|XMU=^?mSOu&CRspNP|E+-3dSZ{Y zklXtmjm3YaK5E_1>Z7Lop#DioW;%a!#g#^D z{aUe9a!c-wBMj(p6$_n`=?+)8&?_Bx2s)+XIf9<)_`y0?o;zGQW8Ud}R=1dpn6^W+ zDx3N{N8h4@*+lc=vX2?gpB?vt#&>o9(VwgF+4H=MeW&xPO9P=&zt1)EH%a@Z)o-3CP#Rbsl|TDk zSW>=T4}u=AA36xmu1S)M${%Q=d_T|d5930A(Kntuw_$J3nU;@$BF05n(&q6$DZhin HL->CH(Y<>D literal 5728 zcmeHL&1(};5TA6Lwtf|Dg%$-}{J;uzX%(ULV3VesQjBTshbSmZ+J>~!BqdqJo~-qv zH=%-mgSX-z;KiG#B8Y;QUObA5)SHbn+4<$GNfE@8JCMx0-^{$3H}CC(c@OPav?&lE zkU>94MjK5Y5>mxhhbM?GL<1D$|8_c5v<<3FJ@!uL0jI;|d0JT9Z1={SC#v~`rUVW@ znQkw?KJ^1{^QNWipWS)!`%}_1X_Eb#*{M;Uhy$+S$zUIeC;3W!WR7|yc0yt&HsW8* zGr&-&x#V|o_S2Va^!ZCxHzb2vOZx^RSwGeSO!%<|xWw->L zk#os$QcKy{#FDd|UCg-2+!;zI7BjS%cary$8P36!S-e_c%`$#*n&^`8CTzSmK6V>DA6#Vz8J;plxXRM%v0IQlO`ti|7 zWYFvxjnAAn`}?has}F{IaD%&8)W6cq;FcEqP>mae`d8!4gng>UgM|83<1K{ztMT1^ zvFHtIBdoL9o_E2lL_FCboQ|?ij!iRtFO-q8R1cT)6kz+>xN>d;ug#y^-y+^^vQR-I zEZ6JnZ!li3f4|efepc;w_4V4hTXW=$+=_>iGTBQuk>6B~kLI%JbTZ@e+Wwa0-9zpSeCIgV;Jq3E_X56W z+(XA%|FclY!XM`!yr+S`!gQ7eIWzFbcLM%Q4JDq~AU^Jo3yeu_@DHf~j(d(xilo;d zhIE-FnR{3fe0Si8BQfOes*OL$n9PZLc2(np*WM>M)8Ioj{&<%JKgIe=(& Date: Thu, 21 Mar 2024 11:51:09 +0800 Subject: [PATCH 033/135] clean lint warnings --- .../syscalls/tests/vm_latest/syscalls_1.rs | 4 +-- script/src/v2_scheduler.rs | 3 +- script/src/v2_syscalls.rs | 18 ++--------- script/src/verify.rs | 1 - .../tests/ckb_latest/features_since_v2021.rs | 11 +++---- .../tests/ckb_latest/features_since_v2023.rs | 11 +++---- script/src/verify/tests/utils.rs | 32 ------------------- .../src/extension/tests/rust_core_traits.rs | 4 +-- util/types/src/core/advanced_builders.rs | 2 +- util/types/src/core/cell.rs | 2 +- util/types/src/core/tests/views.rs | 2 +- verification/traits/src/lib.rs | 1 + 12 files changed, 19 insertions(+), 72 deletions(-) diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index 5e67fd5346..51956d8bde 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -14,7 +14,7 @@ use ckb_types::{ use ckb_vm::{ memory::{FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE}, registers::{A0, A1, A2, A3, A4, A5, A7}, - snapshot2::{DataSource, Snapshot2, Snapshot2Context}, + snapshot2::Snapshot2Context, CoreMachine, Error as VMError, Memory, Syscalls, RISCV_PAGESIZE, }; use proptest::{collection::size_range, prelude::*}; @@ -1453,7 +1453,6 @@ fn _test_load_cell_data_as_code( let data = Bytes::from(data.to_owned()); let dep_cell = build_cell_meta(10000, data.clone()); - let output = build_cell_meta(100, data.clone()); let input_cell = build_cell_meta(100, data.clone()); let data_loader = new_mock_data_loader(); @@ -1527,7 +1526,6 @@ fn _test_load_cell_data( let data = Bytes::from(data.to_owned()); let dep_cell = build_cell_meta(10000, data.clone()); - let output = build_cell_meta(100, data.clone()); let input_cell = build_cell_meta(100, data.clone()); let data_loader = new_mock_data_loader(); diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index bf7034580d..b5a892a45c 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -794,8 +794,7 @@ where syscalls_generator.vm_id = *id; syscalls_generator.snapshot2_context = Arc::new(Mutex::new(Snapshot2Context::new(self.tx_data.clone()))); - let mut machine_context = - MachineContext::new(*id, self.message_box.clone(), self.tx_data.clone(), version); + let mut machine_context = MachineContext::new(self.tx_data.clone()); machine_context.base_cycles = Arc::clone(&self.syscalls_generator.base_cycles); machine_context.snapshot2_context = syscalls_generator.snapshot2_context.clone(); diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index 5e17bd9c54..da7f014772 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -1,7 +1,4 @@ -use crate::{ - v2_types::{DataPieceId, Message, TxData, VmId}, - ScriptVersion, -}; +use crate::v2_types::{DataPieceId, TxData}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_vm::snapshot2::Snapshot2Context; use std::sync::{Arc, Mutex}; @@ -10,29 +7,18 @@ use std::sync::{Arc, Mutex}; pub struct MachineContext< DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, > { - pub(crate) id: VmId, pub(crate) base_cycles: Arc>, - pub(crate) message_box: Arc>>, pub(crate) snapshot2_context: Arc>>>, - pub(crate) script_version: ScriptVersion, } impl
MachineContext
where DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { - pub fn new( - id: VmId, - message_box: Arc>>, - tx_data: TxData
, - script_version: ScriptVersion, - ) -> Self { + pub fn new(tx_data: TxData
) -> Self { Self { - id, base_cycles: Arc::new(Mutex::new(0)), - message_box, snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(tx_data))), - script_version, } } diff --git a/script/src/verify.rs b/script/src/verify.rs index 6afbe6c44f..6283f0fb06 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -53,7 +53,6 @@ use core::sync::atomic::{AtomicBool, Ordering}; mod tests; pub enum ChunkState { - //Suspended(Vec, Arc>), Suspended(Option), Completed(Cycle, Cycle), } diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index af32541aea..9fa6bef11f 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -551,7 +551,7 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa &Some(cur_state), false, ) { - Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { + Ok(ChunkState::Completed(used_cycles, _consumed_cycles)) => { cycles += used_cycles; groups.pop_front(); tmp = None; @@ -561,7 +561,7 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa limit += step_cycles; continue; } - Err(error) => { + Err(_error) => { unreachable!(); } } @@ -575,7 +575,7 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa .verify_group_with_chunk(group, limit, &tmp, false) .unwrap() { - ChunkState::Completed(used_cycles, consumed_cycles) => { + ChunkState::Completed(used_cycles, _consumed_cycles) => { cycles += used_cycles; groups.pop_front(); tmp = None; @@ -714,7 +714,6 @@ fn _check_type_id_one_in_one_out_resume_with_state( } VerifyResult::Completed(cycle) => { cycles = cycle; - init_state = None; break; } } @@ -756,7 +755,7 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle .verify_group_with_chunk(group.2, limit, &tmp, false) .unwrap() { - ChunkState::Completed(used_cycles, consumed_cycles) => { + ChunkState::Completed(used_cycles, _consumed_cycles) => { cycles += used_cycles; tmp = None; } @@ -879,7 +878,6 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_snap(step_cycles: Cycle) init_state = Some(state); } - let mut count = 0; loop { let state = init_state.take().unwrap(); let (limit_cycles, _last) = state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); @@ -892,7 +890,6 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_snap(step_cycles: Cycle) break; } } - count += 1; } verifier.verify(TWO_IN_TWO_OUT_CYCLES) 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 77df460c08..9e9857009b 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -394,12 +394,11 @@ fn check_spawn_snapshot() { 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); + 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)] diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index 076b13bc23..b6c09681fd 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -201,38 +201,6 @@ impl TransactionScriptsVerifierWithEnv { .await } - pub(crate) async fn verify_complete_async( - &self, - version: ScriptVersion, - rtx: &ResolvedTransaction, - command_rx: &mut tokio::sync::watch::Receiver, - skip_debug_pause: bool, - ) -> Result { - let data_loader = self.store.as_data_loader(); - let epoch = match version { - ScriptVersion::V0 => EpochNumberWithFraction::new(0, 0, 1), - ScriptVersion::V1 => EpochNumberWithFraction::new(self.version_1_enabled_at, 0, 1), - ScriptVersion::V2 => EpochNumberWithFraction::new(self.version_2_enabled_at, 0, 1), - }; - let header = HeaderView::new_advanced_builder() - .epoch(epoch.pack()) - .build(); - let tx_env = Arc::new(TxVerifyEnv::new_commit(&header)); - let verifier = TransactionScriptsVerifier::new( - Arc::new(rtx.clone()), - data_loader, - Arc::clone(&self.consensus), - tx_env, - ); - - if skip_debug_pause { - verifier.set_skip_pause(true); - } - verifier - .resumable_verify_with_signal(Cycle::MAX, command_rx) - .await - } - // If the max cycles is meaningless, please use `verify_without_limit`, // so reviewers or developers can understand the intentions easier. pub(crate) fn verify( diff --git a/util/gen-types/src/extension/tests/rust_core_traits.rs b/util/gen-types/src/extension/tests/rust_core_traits.rs index 2d45b7d75b..b3e3ce1adb 100644 --- a/util/gen-types/src/extension/tests/rust_core_traits.rs +++ b/util/gen-types/src/extension/tests/rust_core_traits.rs @@ -82,8 +82,8 @@ fn test_bytesopt_cmp() { #[test] fn test_script_cmp() { - let a = Script::new_builder().args(vec![1].pack()).build(); - let b = Script::new_builder().args(vec![2].pack()).build(); + let a = Script::new_builder().args([1].pack()).build(); + let b = Script::new_builder().args([2].pack()).build(); assert!(a < b); } diff --git a/util/types/src/core/advanced_builders.rs b/util/types/src/core/advanced_builders.rs index 9e2a8e2343..eae6b39a9e 100644 --- a/util/types/src/core/advanced_builders.rs +++ b/util/types/src/core/advanced_builders.rs @@ -571,7 +571,7 @@ impl core::BlockView { .uncles( data.uncles() .into_iter() - .zip(uncle_hashes.clone().into_iter()) + .zip(uncle_hashes.clone()) .map(|(data, hash)| core::UncleBlockView { data, hash }) .collect::>(), ) diff --git a/util/types/src/core/cell.rs b/util/types/src/core/cell.rs index 92b4295597..e5b62499ab 100644 --- a/util/types/src/core/cell.rs +++ b/util/types/src/core/cell.rs @@ -625,7 +625,7 @@ pub fn get_related_dep_out_points Option>( .ok_or_else(|| String::from("Can not get cell data"))?; let sub_out_points = parse_dep_group_data(&data).map_err(|err| format!("Invalid data: {err}"))?; - out_points.extend(sub_out_points.into_iter()); + out_points.extend(sub_out_points); } out_points.push(out_point); Ok(out_points) diff --git a/util/types/src/core/tests/views.rs b/util/types/src/core/tests/views.rs index e7a11e3b3c..d3c3aeb4de 100644 --- a/util/types/src/core/tests/views.rs +++ b/util/types/src/core/tests/views.rs @@ -41,7 +41,7 @@ fn test_extension_field_in_block_view() { block.transactions(), block.data().proposals(), ); - let extension: packed::Bytes = vec![0u8, 1, 2, 3, 4, 5, 6, 7].pack(); + let extension: packed::Bytes = [0u8, 1, 2, 3, 4, 5, 6, 7].pack(); // block with extension but not reset all hashes let block2_v1_un = BlockView::new_unchecked_with_extension( block.header(), diff --git a/verification/traits/src/lib.rs b/verification/traits/src/lib.rs index 05a9de7e57..1cda56dca0 100644 --- a/verification/traits/src/lib.rs +++ b/verification/traits/src/lib.rs @@ -1,4 +1,5 @@ //! The trait abstract for particular verification +#![allow(clippy::bad_bit_mask)] use bitflags::bitflags; use ckb_error::Error; From c8b6cf42e13d4781ea4a0032f0f94ce0b12c8f8a Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 21 Mar 2024 13:03:56 +0800 Subject: [PATCH 034/135] fix clippy wanring --- .../syscalls/tests/vm_latest/syscalls_1.rs | 32 +++++++++---------- script/src/v2_scheduler.rs | 8 ++--- script/src/verify.rs | 26 +++++++-------- .../tests/ckb_latest/features_since_v2023.rs | 3 +- script/src/verify/tests/utils.rs | 2 +- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index 51956d8bde..4af492fd3d 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -1465,8 +1465,8 @@ fn _test_load_cell_data_as_code( resolved_dep_groups: vec![], }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1538,8 +1538,8 @@ fn _test_load_cell_data( resolved_dep_groups: vec![], }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1648,8 +1648,8 @@ fn test_load_overflowed_cell_data_as_code() { }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1700,8 +1700,8 @@ fn _test_load_cell_data_on_freezed_memory(data: &[u8]) -> Result<(), TestCaseErr }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1750,8 +1750,8 @@ fn _test_load_cell_data_as_code_on_freezed_memory(data: &[u8]) -> Result<(), Tes }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1811,8 +1811,8 @@ fn test_load_code_unaligned_error() { }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1859,8 +1859,8 @@ fn test_load_code_slice_out_of_bound_error() { }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), @@ -1910,8 +1910,8 @@ fn test_load_code_not_enough_space_error() { }); let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx, - data_loader: data_loader, + rtx, + data_loader, program: Bytes::new(), script_group: Arc::new(ScriptGroup { script: Default::default(), diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index b5a892a45c..20882615c4 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -82,7 +82,7 @@ where script_version: ScriptVersion, syscalls_generator: TransactionScriptsSyscallsGenerator
, ) -> Self { - let message_box = syscalls_generator.message_box.clone(); + let message_box = Arc::clone(&syscalls_generator.message_box); Self { tx_data, script_version, @@ -112,7 +112,7 @@ where syscalls_generator: TransactionScriptsSyscallsGenerator
, full: FullSuspendedState, ) -> Self { - let message_box = syscalls_generator.message_box.clone(); + let message_box = Arc::clone(&syscalls_generator.message_box); Self { tx_data, script_version, @@ -134,7 +134,7 @@ where .into_iter() .map(|(id, _, snapshot)| (id, snapshot)) .collect(), - message_box: message_box, + message_box, terminated_vms: full.terminated_vms.into_iter().collect(), } } @@ -796,7 +796,7 @@ where Arc::new(Mutex::new(Snapshot2Context::new(self.tx_data.clone()))); let mut machine_context = MachineContext::new(self.tx_data.clone()); machine_context.base_cycles = Arc::clone(&self.syscalls_generator.base_cycles); - machine_context.snapshot2_context = syscalls_generator.snapshot2_context.clone(); + machine_context.snapshot2_context = Arc::clone(&syscalls_generator.snapshot2_context); let machine_builder = DefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(estimate_cycles)); diff --git a/script/src/verify.rs b/script/src/verify.rs index be41e27bce..8408b6f2e1 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -199,7 +199,7 @@ where /// Build syscall: load_cell_data pub fn build_load_cell_data(&self) -> LoadCellData
{ - LoadCellData::new(self.snapshot2_context.clone()) + LoadCellData::new(Arc::clone(&self.snapshot2_context)) } ///Build syscall: load_input @@ -244,14 +244,14 @@ where pub fn build_spawn(&self) -> Spawn
{ Spawn::new( self.vm_id, - self.message_box.clone(), - self.snapshot2_context.clone(), + Arc::clone(&self.message_box), + Arc::clone(&self.snapshot2_context), ) } /// Build syscall: wait pub fn build_wait(&self) -> Wait { - Wait::new(self.vm_id, self.message_box.clone()) + Wait::new(self.vm_id, Arc::clone(&self.message_box)) } /// Build syscall: process_id @@ -261,27 +261,27 @@ where /// Build syscall: pipe pub fn build_pipe(&self) -> Pipe { - Pipe::new(self.vm_id, self.message_box.clone()) + Pipe::new(self.vm_id, Arc::clone(&self.message_box)) } /// Build syscall: write pub fn build_write(&self) -> Write { - Write::new(self.vm_id, self.message_box.clone()) + Write::new(self.vm_id, Arc::clone(&self.message_box)) } /// Build syscall: read pub fn build_read(&self) -> Read { - Read::new(self.vm_id, self.message_box.clone()) + Read::new(self.vm_id, Arc::clone(&self.message_box)) } /// Build syscall: inherited_fd pub fn inherited_fd(&self) -> InheritedFd { - InheritedFd::new(self.vm_id, self.message_box.clone()) + InheritedFd::new(self.vm_id, Arc::clone(&self.message_box)) } /// Build syscall: close pub fn close(&self) -> Close { - Close::new(self.vm_id, self.message_box.clone()) + Close::new(self.vm_id, Arc::clone(&self.message_box)) } /// Generate same syscalls. The result does not contain spawn syscalls. @@ -474,7 +474,7 @@ where skip_pause: Arc::clone(&skip_pause), // Use a dummy snapshot2_context as a placeholder. snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: rtx.clone(), + rtx: Arc::clone(&rtx), data_loader: data_loader.clone(), program: Bytes::new(), script_group: Arc::new(ScriptGroup { @@ -1035,7 +1035,7 @@ where ) -> Result { let program = self.extract_script(&script_group.script)?; let tx_data = TxData { - rtx: self.rtx.clone(), + rtx: Arc::clone(&self.rtx), data_loader: self.data_loader.clone(), program, script_group: Arc::new(script_group.clone()), @@ -1145,7 +1145,7 @@ where ) -> Result<(i8, Cycle), ScriptError> { let program = self.extract_script(&script_group.script)?; let tx_data = TxData { - rtx: self.rtx.clone(), + rtx: Arc::clone(&self.rtx), data_loader: self.data_loader.clone(), program, script_group: Arc::new(script_group.clone()), @@ -1180,7 +1180,7 @@ where ) -> Result { let program = self.extract_script(&script_group.script)?; let tx_data = TxData { - rtx: self.rtx.clone(), + rtx: Arc::clone(&self.rtx), data_loader: self.data_loader.clone(), program, script_group: Arc::new(script_group.clone()), 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 9e9857009b..9693f728f8 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -31,8 +31,7 @@ fn simple_spawn_test(bin_path: &str, args: &[u8]) -> Result { resolved_dep_groups: vec![], }; let verifier = TransactionScriptsVerifierWithEnv::new(); - let result = verifier.verify_without_limit(script_version, &rtx); - result + verifier.verify_without_limit(script_version, &rtx) } #[test] diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index b6c09681fd..46c2c124ed 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -289,7 +289,7 @@ impl TransactionScriptsVerifierWithEnv { verifier.set_debug_printer(Box::new(move |_hash: &Byte32, message: &str| { print!("{}", message); if !message.ends_with('\n') { - println!(""); + println!(); } })); verify_func(verifier) From bca7c0dafe4e35e55e94a5df538f20ed211406d4 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 21 Mar 2024 13:36:42 +0800 Subject: [PATCH 035/135] cleanup unused code --- script/src/types.rs | 134 ------------------ script/src/verify.rs | 74 ---------- .../tests/ckb_latest/features_since_v2021.rs | 1 - 3 files changed, 209 deletions(-) diff --git a/script/src/types.rs b/script/src/types.rs index 26b94d4765..b83efabb15 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -106,140 +106,6 @@ impl ScriptVersion { } } -/// Common data that would be shared amongst multiple VM instances. -/// One sample usage right now, is to capture suspended machines in -/// a chain of spawned machines. -// #[derive(Default)] -// pub struct MachineContext { -// /// A stack of ResumableMachines. -// pub suspended_machines: Vec, -// /// A pause will be set for suspend machines. -// /// The child machine will reuse parent machine's pause, -// /// so that when parent is paused, all its children will be paused. -// pub pause: Pause, -// } - -// impl MachineContext { -// /// Creates a new MachineContext struct -// pub fn set_pause(&mut self, pause: Pause) { -// self.pause = pause; -// } -// } - -/// Data structure captured all environment data for a suspended machine -// #[derive(Clone, Debug)] -// pub enum ResumePoint { -// Initial, -// Spawn { -// callee_peak_memory: u64, -// callee_memory_limit: u64, -// content: Vec, -// content_length: u64, -// caller_exit_code_addr: u64, -// caller_content_addr: u64, -// caller_content_length_addr: u64, -// cycles_base: u64, -// }, -// } - -/// Data structure captured all the required data for a spawn syscall -// #[derive(Clone, Debug)] -// pub struct SpawnData { -// pub(crate) callee_peak_memory: u64, -// pub(crate) callee_memory_limit: u64, -// pub(crate) content: Arc>>, -// pub(crate) content_length: u64, -// pub(crate) caller_exit_code_addr: u64, -// pub(crate) caller_content_addr: u64, -// pub(crate) caller_content_length_addr: u64, -// pub(crate) cycles_base: u64, -// } - -// impl TryFrom<&SpawnData> for ResumePoint { -// type Error = VMInternalError; - -// fn try_from(value: &SpawnData) -> Result { -// let SpawnData { -// callee_peak_memory, -// callee_memory_limit, -// content, -// content_length, -// caller_exit_code_addr, -// caller_content_addr, -// caller_content_length_addr, -// cycles_base, -// .. -// } = value; -// Ok(ResumePoint::Spawn { -// callee_peak_memory: *callee_peak_memory, -// callee_memory_limit: *callee_memory_limit, -// content: content -// .lock() -// .map_err(|e| VMInternalError::Unexpected(format!("Lock error: {}", e)))? -// .clone(), -// content_length: *content_length, -// caller_exit_code_addr: *caller_exit_code_addr, -// caller_content_addr: *caller_content_addr, -// caller_content_length_addr: *caller_content_length_addr, -// cycles_base: *cycles_base, -// }) -// } -// } - -/// An enumerated type indicating the type of the Machine. -// pub enum ResumableMachine { -// /// Root machine instance. -// Initial(Machine), -// /// A machine which created by spawn syscall. -// Spawn(Machine, SpawnData), -// } - -// impl ResumableMachine { -// pub(crate) fn initial(machine: Machine) -> Self { -// ResumableMachine::Initial(machine) -// } - -// pub(crate) fn spawn(machine: Machine, data: SpawnData) -> Self { -// ResumableMachine::Spawn(machine, data) -// } - -// pub(crate) fn machine(&self) -> &Machine { -// match self { -// ResumableMachine::Initial(machine) => machine, -// ResumableMachine::Spawn(machine, _) => machine, -// } -// } - -// pub(crate) fn machine_mut(&mut self) -> &mut Machine { -// match self { -// ResumableMachine::Initial(machine) => machine, -// ResumableMachine::Spawn(machine, _) => machine, -// } -// } - -// pub(crate) fn cycles(&self) -> Cycle { -// self.machine().machine.cycles() -// } - -// pub(crate) fn pause(&self) -> Pause { -// self.machine().machine.pause() -// } - -// pub(crate) fn set_max_cycles(&mut self, cycles: Cycle) { -// set_vm_max_cycles(self.machine_mut(), cycles) -// } - -// /// Add cycles to current machine. -// pub fn add_cycles(&mut self, cycles: Cycle) -> Result<(), VMInternalError> { -// self.machine_mut().machine.add_cycles(cycles) -// } - -// /// Run machine. -// pub fn run(&mut self) -> Result { -// self.machine_mut().run() -// } -// } - /// A script group is defined as scripts that share the same hash. /// /// A script group will only be executed once per transaction, the diff --git a/script/src/verify.rs b/script/src/verify.rs index 8408b6f2e1..392335d031 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1055,14 +1055,12 @@ where VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), }; - //eprintln!("scheduler run with max_cycles: {}", max_cycles); let previous_cycles = scheduler.consumed_cycles(); loop { let res = scheduler.run(RunMode::LimitCycles(max_cycles)); match res { Ok((exit_code, cycles)) => { if exit_code == 0 { - //eprintln!("finished with cycles: {}", cycles); return Ok(ChunkState::Completed( cycles, scheduler.consumed_cycles() - previous_cycles, @@ -1278,78 +1276,6 @@ where } } -// Run a series of VMs that are just freshly resumed -// fn run_vms( -// _script_group: &ScriptGroup, -// _max_cycles: Cycle, -// mut _machines: Vec, -// _context: &Arc>, -// ) -> Result { -// unimplemented!() -// let (mut exit_code, mut cycles, mut spawn_data) = (0, 0, None); - -// if machines.is_empty() { -// return Err(ScriptError::Other( -// "To resume VMs, at least one VM must be available!".to_string(), -// )); -// } - -// let map_vm_internal_error = |error: VMInternalError| match error { -// VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), -// _ => ScriptError::VMInternalError(error), -// }; - -// while let Some(mut machine) = machines.pop() { -// if let Some(callee_spawn_data) = &spawn_data { -// update_caller_machine( -// &mut machine.machine_mut().machine, -// exit_code, -// cycles, -// callee_spawn_data, -// ) -// .map_err(map_vm_internal_error)?; -// } - -// match machine.run() { -// Ok(code) => { -// exit_code = code; -// cycles = machine.cycles(); -// if let ResumableMachine::Spawn(_, data) = machine { -// spawn_data = Some(data); -// } else { -// spawn_data = None; -// } -// } -// Err(error) => match error { -// VMInternalError::CyclesExceeded | VMInternalError::Pause => { -// let mut new_suspended_machines: Vec<_> = { -// let mut context = context.lock().map_err(|e| { -// ScriptError::Other(format!("Failed to acquire lock: {}", e)) -// })?; -// context.suspended_machines.drain(..).collect() -// }; -// // The inner most machine lives at the top of the vector, -// // reverse the list for natural order. -// new_suspended_machines.reverse(); -// machines.push(machine); -// machines.append(&mut new_suspended_machines); -// return Ok(ChunkState::suspended(machines, Arc::clone(context))); -// } -// _ => return Err(ScriptError::VMInternalError(error)), -// }, -// }; -// } - -// if exit_code == 0 { -// Ok(ChunkState::Completed(cycles)) -// } else { -// Err(ScriptError::validation_failure( -// &script_group.script, -// exit_code, -// )) -// } -//} - fn wrapping_cycles_add( lhs: Cycle, rhs: Cycle, diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 9fa6bef11f..e3b3a70579 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -334,7 +334,6 @@ fn check_exec_from_cell_data() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - println!("result = {:?}", result); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1); } From 0d6aeeaecc4203607c8338f1bea75e72b67aabd5 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 21 Mar 2024 14:07:15 +0800 Subject: [PATCH 036/135] fix spawn specs --- .../tests/ckb_latest/features_since_v2023.rs | 365 +++++++++--------- script/src/verify/tests/utils.rs | 32 ++ 2 files changed, 215 insertions(+), 182 deletions(-) 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 9693f728f8..4760368d66 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -400,210 +400,211 @@ fn check_spawn_snapshot() { 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); +#[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 transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); + 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 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_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); -// // 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); + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// // 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 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 _res = command_tx.send(ChunkCommand::Resume); -// tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; + // 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); -// let _res = command_tx.send(ChunkCommand::Suspend); -// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await; + // 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(10)).await; -// } -// }); + let _res = command_tx.send(ChunkCommand::Resume); + tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; -// let cycles = verifier -// .verify_complete_async(script_version, &rtx, &mut command_rx, true) -// .await -// .unwrap(); -// assert_eq!(cycles, cycles_once); -// } + let _res = command_tx.send(ChunkCommand::Suspend); + tokio::time::sleep(tokio::time::Duration::from_millis(10)).await; -// #[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 _res = command_tx.send(ChunkCommand::Resume); + tokio::time::sleep(tokio::time::Duration::from_millis(10)).await; + } + }); -// 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 cycles = verifier + .verify_complete_async(script_version, &rtx, &mut command_rx, true) + .await + .unwrap(); + assert_eq!(cycles, cycles_once); +} -// 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); +#[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 transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); + 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 rtx = ResolvedTransaction { -// transaction, -// resolved_cell_deps: vec![spawn_caller_cell, snapshot_cell], -// resolved_inputs: vec![dummy_cell], -// resolved_dep_groups: vec![], -// }; + 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 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\")")); -// } + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// #[test] -// fn check_spawn_state() { -// 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 (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 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\")")); +} -// 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); +#[test] +fn check_spawn_state() { + let script_version = SCRIPT_VERSION; + if script_version <= ScriptVersion::V1 { + return; + } -// let transaction = TransactionBuilder::default().input(input).build(); -// let dummy_cell = create_dummy_cell(output); + 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 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_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 (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)); -// } -// }; + let transaction = TransactionBuilder::default().input(input).build(); + let dummy_cell = create_dummy_cell(output); -// 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; -// } -// } -// } + 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(); -// Ok::<(u64, usize), Error>((cycles, times)) -// }) -// .unwrap(); -// assert_eq!(cycles, cycles_once); -// assert!(chunks_count > 1); -// } + 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: TransactionSnapshot = + init_state.take().unwrap().try_into().expect("no snapshot"); + match verifier.resume_from_snap(&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_cycles() { diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index 46c2c124ed..1051889106 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -261,6 +261,38 @@ impl TransactionScriptsVerifierWithEnv { }) } + pub(crate) async fn verify_complete_async( + &self, + version: ScriptVersion, + rtx: &ResolvedTransaction, + command_rx: &mut tokio::sync::watch::Receiver, + skip_debug_pause: bool, + ) -> Result { + let data_loader = self.store.as_data_loader(); + let epoch = match version { + ScriptVersion::V0 => EpochNumberWithFraction::new(0, 0, 1), + ScriptVersion::V1 => EpochNumberWithFraction::new(self.version_1_enabled_at, 0, 1), + ScriptVersion::V2 => EpochNumberWithFraction::new(self.version_2_enabled_at, 0, 1), + }; + let header = HeaderView::new_advanced_builder() + .epoch(epoch.pack()) + .build(); + let tx_env = Arc::new(TxVerifyEnv::new_commit(&header)); + let verifier = TransactionScriptsVerifier::new( + Arc::new(rtx.clone()), + data_loader, + Arc::clone(&self.consensus), + tx_env, + ); + + if skip_debug_pause { + verifier.set_skip_pause(true); + } + verifier + .resumable_verify_with_signal(Cycle::MAX, command_rx) + .await + } + pub(crate) fn verify_map( &self, version: ScriptVersion, From a00365f17e439125cd70c6437b125f2ecb672348 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 21 Mar 2024 14:33:18 +0800 Subject: [PATCH 037/135] code refactor for scheduler and syscalls2 --- script/src/lib.rs | 4 +- script/src/{v2_scheduler.rs => scheduler.rs} | 12 +- script/src/syscalls/close.rs | 2 +- script/src/syscalls/inherited_fd.rs | 2 +- script/src/syscalls/load_cell_data.rs | 2 +- script/src/syscalls/pipe.rs | 2 +- script/src/syscalls/read.rs | 2 +- script/src/syscalls/spawn.rs | 2 +- .../syscalls/tests/vm_latest/syscalls_1.rs | 2 +- script/src/syscalls/wait.rs | 2 +- script/src/syscalls/write.rs | 2 +- script/src/types.rs | 354 +++++++++++++++++- script/src/v2_syscalls.rs | 32 -- script/src/v2_types.rs | 316 ---------------- script/src/verify.rs | 6 +- 15 files changed, 369 insertions(+), 373 deletions(-) rename script/src/{v2_scheduler.rs => scheduler.rs} (99%) delete mode 100644 script/src/v2_syscalls.rs delete mode 100644 script/src/v2_types.rs diff --git a/script/src/lib.rs b/script/src/lib.rs index 6d10158d34..e28b54c0eb 100644 --- a/script/src/lib.rs +++ b/script/src/lib.rs @@ -1,12 +1,10 @@ //! CKB component to run the type/lock scripts. pub mod cost_model; mod error; +mod scheduler; mod syscalls; mod type_id; mod types; -mod v2_scheduler; -mod v2_syscalls; -mod v2_types; mod verify; mod verify_env; diff --git a/script/src/v2_scheduler.rs b/script/src/scheduler.rs similarity index 99% rename from script/src/v2_scheduler.rs rename to script/src/scheduler.rs index 20882615c4..2920f106d9 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/scheduler.rs @@ -2,15 +2,13 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ INDEX_OUT_OF_BOUND, INVALID_PIPE, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE, }; -use crate::v2_types::PipeIoArgs; +use crate::types::MachineContext; use crate::verify::TransactionScriptsSyscallsGenerator; use crate::ScriptVersion; -use crate::{ - v2_syscalls::MachineContext, - v2_types::{ - DataPieceId, FullSuspendedState, Message, PipeId, RunMode, TxData, VmId, VmState, - FIRST_PIPE_SLOT, FIRST_VM_ID, - }, + +use crate::types::{ + DataPieceId, FullSuspendedState, Message, PipeId, PipeIoArgs, RunMode, TxData, VmId, VmState, + FIRST_PIPE_SLOT, FIRST_VM_ID, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs index b797736202..d781ecdec1 100644 --- a/script/src/syscalls/close.rs +++ b/script/src/syscalls/close.rs @@ -1,5 +1,5 @@ use crate::syscalls::CLOSE; -use crate::v2_types::{Message, PipeId, VmId}; +use crate::types::{Message, PipeId, VmId}; use ckb_vm::{ registers::{A0, A7}, Error as VMError, Register, SupportMachine, Syscalls, diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs index b9c79ca15d..91c12d155b 100644 --- a/script/src/syscalls/inherited_fd.rs +++ b/script/src/syscalls/inherited_fd.rs @@ -1,5 +1,5 @@ use crate::syscalls::INHERITED_FD; -use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; +use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A7}, Error as VMError, Register, SupportMachine, Syscalls, diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index 5147e44f8d..a571915473 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -1,4 +1,4 @@ -use crate::v2_types::{DataPieceId, TxData}; +use crate::types::{DataPieceId, TxData}; use crate::{ cost_model::transferred_byte_cycles, syscalls::{ diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs index 07c508b0b4..09b6281007 100644 --- a/script/src/syscalls/pipe.rs +++ b/script/src/syscalls/pipe.rs @@ -1,5 +1,5 @@ use crate::syscalls::PIPE; -use crate::v2_types::{Message, PipeArgs, VmId}; +use crate::types::{Message, PipeArgs, VmId}; use ckb_vm::{ registers::{A0, A7}, Error as VMError, Register, SupportMachine, Syscalls, diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 9d14021425..9dd98406b3 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,6 +1,6 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{INVALID_PIPE, READ}; -use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; +use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, Error as VMError, Memory, Register, SupportMachine, Syscalls, diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 5a91232c74..1ee2200275 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,7 +1,7 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::utils::load_c_string; use crate::syscalls::{INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE}; -use crate::v2_types::{DataPieceId, Message, PipeId, SpawnArgs, TxData, VmId}; +use crate::types::{DataPieceId, Message, PipeId, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_vm::{ machine::SupportMachine, diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index 4af492fd3d..efe8b29a68 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -23,8 +23,8 @@ use std::sync::{Arc, Mutex}; use super::SCRIPT_VERSION; use crate::syscalls::{tests::utils::*, *}; +use crate::types::TxData; use crate::types::{ScriptGroup, ScriptGroupType}; -use crate::v2_types::TxData; fn _test_load_cell_not_exist(data: &[u8]) -> Result<(), TestCaseError> { let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); diff --git a/script/src/syscalls/wait.rs b/script/src/syscalls/wait.rs index f2b4dc74b6..14938d1aab 100644 --- a/script/src/syscalls/wait.rs +++ b/script/src/syscalls/wait.rs @@ -1,5 +1,5 @@ use crate::syscalls::WAIT; -use crate::v2_types::{Message, VmId, WaitArgs}; +use crate::types::{Message, VmId, WaitArgs}; use ckb_vm::{ registers::{A0, A1, A7}, Error as VMError, Register, SupportMachine, Syscalls, diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index bda3a92afd..e2cb1e536b 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,6 +1,6 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{INVALID_PIPE, WRITE}; -use crate::v2_types::{Message, PipeId, PipeIoArgs, VmId}; +use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, Error as VMError, Memory, Register, SupportMachine, Syscalls, diff --git a/script/src/types.rs b/script/src/types.rs index b83efabb15..98eee3d298 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -1,16 +1,16 @@ -use crate::v2_types::FullSuspendedState; use ckb_error::Error; use ckb_types::{ core::{Cycle, ScriptHashType}, packed::{Byte32, Script}, }; +use ckb_vm::Error as VMInternalError; use ckb_vm::{ machine::{VERSION0, VERSION1, VERSION2}, ISA_A, ISA_B, ISA_IMC, ISA_MOP, }; use serde::{Deserialize, Serialize}; use std::fmt; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; #[cfg(has_asm)] use ckb_vm::machine::asm::AsmCoreMachine; @@ -18,6 +18,18 @@ use ckb_vm::machine::asm::AsmCoreMachine; #[cfg(not(has_asm))] use ckb_vm::{DefaultCoreMachine, TraceMachine, WXorXMemory}; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; +use ckb_vm::snapshot2::Snapshot2Context; + +use ckb_types::core::cell::ResolvedTransaction; +use ckb_vm::{ + bytes::Bytes, + machine::Pause, + snapshot2::{DataSource, Snapshot2}, + RISCV_GENERAL_REGISTER_NUMBER, +}; +use std::mem::size_of; + /// The type of CKB-VM ISA. pub type VmIsa = u8; /// /// The type of CKB-VM version. @@ -299,3 +311,341 @@ pub enum ChunkCommand { /// Stop the verification process Stop, } + +#[derive(Clone)] +pub(crate) struct MachineContext< + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +> { + pub(crate) base_cycles: Arc>, + pub(crate) snapshot2_context: Arc>>>, +} + +impl
MachineContext
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ + pub fn new(tx_data: TxData
) -> Self { + Self { + base_cycles: Arc::new(Mutex::new(0)), + snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(tx_data))), + } + } + + pub fn snapshot2_context(&self) -> &Arc>>> { + &self.snapshot2_context + } + + pub fn set_base_cycles(&mut self, base_cycles: u64) { + *self.base_cycles.lock().expect("lock") = base_cycles; + } +} + +pub type VmId = u64; +pub const FIRST_VM_ID: VmId = 0; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct PipeId(pub(crate) u64); + +pub const FIRST_PIPE_SLOT: u64 = 2; + +impl PipeId { + pub fn create(slot: u64) -> (PipeId, PipeId, u64) { + (PipeId(slot), PipeId(slot + 1), slot + 2) + } + + pub fn other_pipe(&self) -> PipeId { + PipeId(self.0 ^ 0x1) + } + + pub fn is_read(&self) -> bool { + self.0 % 2 == 0 + } + + pub fn is_write(&self) -> bool { + self.0 % 2 == 1 + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum VmState { + Runnable, + Terminated, + Wait { + target_vm_id: VmId, + exit_code_addr: u64, + }, + WaitForWrite { + pipe: PipeId, + consumed: u64, + length: u64, + buffer_addr: u64, + length_addr: u64, + }, + WaitForRead { + pipe: PipeId, + length: u64, + buffer_addr: u64, + length_addr: u64, + }, +} + +#[derive(Clone, Debug)] +pub struct SpawnArgs { + pub data_piece_id: DataPieceId, + pub offset: u64, + pub length: u64, + pub argv: Vec, + pub pipes: Vec, + pub process_id_addr: u64, +} + +#[derive(Clone, Debug)] +pub struct WaitArgs { + pub target_id: VmId, + pub exit_code_addr: u64, +} + +#[derive(Clone, Debug)] +pub struct PipeArgs { + pub pipe1_addr: u64, + pub pipe2_addr: u64, +} + +#[derive(Clone, Debug)] +pub struct PipeIoArgs { + pub pipe: PipeId, + pub length: u64, + pub buffer_addr: u64, + pub length_addr: u64, +} + +#[derive(Clone, Debug)] +pub enum Message { + Spawn(VmId, SpawnArgs), + Wait(VmId, WaitArgs), + Pipe(VmId, PipeArgs), + PipeRead(VmId, PipeIoArgs), + PipeWrite(VmId, PipeIoArgs), + InheritedFileDescriptor(VmId, PipeIoArgs), + Close(VmId, PipeId), +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum DataPieceId { + Program, + Input(u32), + Output(u32), + CellDep(u32), + GroupInput(u32), + GroupOutput(u32), + Witness(u32), + WitnessGroupInput(u32), + WitnessGroupOutput(u32), +} + +impl TryFrom<(u64, u64, u64)> for DataPieceId { + type Error = String; + + fn try_from(value: (u64, u64, u64)) -> Result { + let (source, index, place) = value; + let index: u32 = + u32::try_from(index).map_err(|e| format!("Error casting index to u32: {}", e))?; + match (source, place) { + (1, 0) => Ok(DataPieceId::Input(index)), + (2, 0) => Ok(DataPieceId::Output(index)), + (3, 0) => Ok(DataPieceId::CellDep(index)), + (0x0100000000000001, 0) => Ok(DataPieceId::GroupInput(index)), + (0x0100000000000002, 0) => Ok(DataPieceId::GroupOutput(index)), + (1, 1) => Ok(DataPieceId::Witness(index)), + (2, 1) => Ok(DataPieceId::Witness(index)), + (0x0100000000000001, 1) => Ok(DataPieceId::WitnessGroupInput(index)), + (0x0100000000000002, 1) => Ok(DataPieceId::WitnessGroupOutput(index)), + _ => Err(format!("Invalid source value: {:#x}", source)), + } + } +} + +/// Full state representing all VM instances from verifying a CKB script. +/// It should be serializable to binary formats, while also be able to +/// fully recover the running environment with the full transaction environment. +#[derive(Clone, Debug)] +pub struct FullSuspendedState { + pub max_vms_count: u64, + pub total_cycles: Cycle, + pub next_vm_id: VmId, + pub next_pipe_slot: u64, + pub vms: Vec<(VmId, VmState, Snapshot2)>, + pub pipes: Vec<(PipeId, VmId)>, + pub inherited_fd: Vec<(VmId, Vec)>, + pub terminated_vms: Vec<(VmId, i8)>, +} + +impl FullSuspendedState { + pub fn size(&self) -> u64 { + (size_of::() + + size_of::() + + size_of::() + + self.vms.iter().fold(0, |mut acc, (_, _, snapshot)| { + acc += size_of::() + size_of::(); + acc += snapshot.pages_from_source.len() + * (size_of::() + + size_of::() + + size_of::() + + size_of::() + + size_of::()); + for dirty_page in &snapshot.dirty_pages { + acc += size_of::() + size_of::() + dirty_page.2.len(); + } + acc += size_of::() + + RISCV_GENERAL_REGISTER_NUMBER * size_of::() + + size_of::() + + size_of::() + + size_of::(); + acc + }) + + (self.pipes.len() * (size_of::() + size_of::()))) as u64 + + (self.inherited_fd.len() * (size_of::())) as u64 + + (self.terminated_vms.len() * (size_of::() + size_of::())) as u64 + } +} + +/// Context data for current running transaction & script +#[derive(Clone)] +pub struct TxData
{ + pub rtx: Arc, + pub data_loader: DL, + // Ideally one might not want to keep program here, since program is totally + // deducible from rtx + data_loader, however, for a demo here, program + // does help us save some extra coding. + pub program: Bytes, + pub script_group: Arc, +} + +impl
DataSource for TxData
+where + DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, +{ + fn load_data( + &self, + id: &DataPieceId, + offset: u64, + length: u64, + ) -> Result<(Bytes, u64), VMInternalError> { + match id { + DataPieceId::Program => { + // This is just a shortcut so we don't have to copy over the logic in extract_script, + // ideally you can also only define the rest 5, then figure out a way to convert + // script group to the actual cell dep index. + Ok(self.program.clone()) + } + DataPieceId::Input(i) => { + let cell = + self.rtx.resolved_inputs.get(*i as usize).ok_or_else(|| { + VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()) + })?; + self.data_loader.load_cell_data(cell).ok_or_else(|| { + VMInternalError::Unexpected(format!("Loading input cell #{}'s data failed!", i)) + }) + } + DataPieceId::Output(i) => self + .rtx + .transaction + .outputs_data() + .get(*i as usize) + .map(|data| data.raw_data()) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())), + DataPieceId::CellDep(i) => { + let cell = self + .rtx + .resolved_cell_deps + .get(*i as usize) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.data_loader.load_cell_data(cell).ok_or_else(|| { + VMInternalError::Unexpected(format!("Loading dep cell #{}'s data failed!", i)) + }) + } + DataPieceId::GroupInput(i) => { + let gi = *self + .script_group + .input_indices + .get(*i as usize) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + let cell = + self.rtx.resolved_inputs.get(gi).ok_or_else(|| { + VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()) + })?; + self.data_loader.load_cell_data(cell).ok_or_else(|| { + VMInternalError::Unexpected(format!( + "Loading input cell #{}'s data failed!", + gi + )) + }) + } + DataPieceId::GroupOutput(i) => { + let gi = *self + .script_group + .output_indices + .get(*i as usize) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.rtx + .transaction + .outputs_data() + .get(gi) + .map(|data| data.raw_data()) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())) + } + DataPieceId::Witness(i) => self + .rtx + .transaction + .witnesses() + .get(*i as usize) + .map(|data| data.raw_data()) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())), + DataPieceId::WitnessGroupInput(i) => { + let gi = *self + .script_group + .input_indices + .get(*i as usize) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.rtx + .transaction + .witnesses() + .get(gi) + .map(|data| data.raw_data()) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())) + } + DataPieceId::WitnessGroupOutput(i) => { + let gi = *self + .script_group + .output_indices + .get(*i as usize) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + self.rtx + .transaction + .witnesses() + .get(gi) + .map(|data| data.raw_data()) + .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())) + } + } + .map(|data| { + let offset = std::cmp::min(offset as usize, data.len()); + let full_length = data.len() - offset; + let slice_length = if length > 0 { + std::cmp::min(full_length, length as usize) + } else { + full_length + }; + ( + data.slice(offset..offset + slice_length), + full_length as u64, + ) + }) + } +} + +#[derive(Clone)] +pub enum RunMode { + LimitCycles(Cycle), + Pause(Pause), +} diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs deleted file mode 100644 index da7f014772..0000000000 --- a/script/src/v2_syscalls.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::v2_types::{DataPieceId, TxData}; -use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; -use ckb_vm::snapshot2::Snapshot2Context; -use std::sync::{Arc, Mutex}; - -#[derive(Clone)] -pub struct MachineContext< - DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, -> { - pub(crate) base_cycles: Arc>, - pub(crate) snapshot2_context: Arc>>>, -} - -impl
MachineContext
-where - DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, -{ - pub fn new(tx_data: TxData
) -> Self { - Self { - base_cycles: Arc::new(Mutex::new(0)), - snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(tx_data))), - } - } - - pub fn snapshot2_context(&self) -> &Arc>>> { - &self.snapshot2_context - } - - pub fn set_base_cycles(&mut self, base_cycles: u64) { - *self.base_cycles.lock().expect("lock") = base_cycles; - } -} diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs deleted file mode 100644 index 7bc413fa67..0000000000 --- a/script/src/v2_types.rs +++ /dev/null @@ -1,316 +0,0 @@ -use crate::ScriptGroup; -use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; -use ckb_types::core::{cell::ResolvedTransaction, Cycle}; -use ckb_vm::{ - bytes::Bytes, - machine::Pause, - snapshot2::{DataSource, Snapshot2}, - Error, RISCV_GENERAL_REGISTER_NUMBER, -}; -use std::mem::size_of; -use std::sync::Arc; - -pub type VmId = u64; - -pub const FIRST_VM_ID: VmId = 0; - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct PipeId(pub(crate) u64); - -pub const FIRST_PIPE_SLOT: u64 = 2; - -impl PipeId { - pub fn create(slot: u64) -> (PipeId, PipeId, u64) { - (PipeId(slot), PipeId(slot + 1), slot + 2) - } - - pub fn other_pipe(&self) -> PipeId { - PipeId(self.0 ^ 0x1) - } - - pub fn is_read(&self) -> bool { - self.0 % 2 == 0 - } - - pub fn is_write(&self) -> bool { - self.0 % 2 == 1 - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum VmState { - Runnable, - Terminated, - Wait { - target_vm_id: VmId, - exit_code_addr: u64, - }, - WaitForWrite { - pipe: PipeId, - consumed: u64, - length: u64, - buffer_addr: u64, - length_addr: u64, - }, - WaitForRead { - pipe: PipeId, - length: u64, - buffer_addr: u64, - length_addr: u64, - }, -} - -#[derive(Clone, Debug)] -pub struct SpawnArgs { - pub data_piece_id: DataPieceId, - pub offset: u64, - pub length: u64, - pub argv: Vec, - pub pipes: Vec, - pub process_id_addr: u64, -} - -#[derive(Clone, Debug)] -pub struct WaitArgs { - pub target_id: VmId, - pub exit_code_addr: u64, -} - -#[derive(Clone, Debug)] -pub struct PipeArgs { - pub pipe1_addr: u64, - pub pipe2_addr: u64, -} - -#[derive(Clone, Debug)] -pub struct PipeIoArgs { - pub pipe: PipeId, - pub length: u64, - pub buffer_addr: u64, - pub length_addr: u64, -} - -#[derive(Clone, Debug)] -pub enum Message { - Spawn(VmId, SpawnArgs), - Wait(VmId, WaitArgs), - Pipe(VmId, PipeArgs), - PipeRead(VmId, PipeIoArgs), - PipeWrite(VmId, PipeIoArgs), - InheritedFileDescriptor(VmId, PipeIoArgs), - Close(VmId, PipeId), -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum DataPieceId { - Program, - Input(u32), - Output(u32), - CellDep(u32), - GroupInput(u32), - GroupOutput(u32), - Witness(u32), - WitnessGroupInput(u32), - WitnessGroupOutput(u32), -} - -impl TryFrom<(u64, u64, u64)> for DataPieceId { - type Error = String; - - fn try_from(value: (u64, u64, u64)) -> Result { - let (source, index, place) = value; - let index: u32 = - u32::try_from(index).map_err(|e| format!("Error casting index to u32: {}", e))?; - match (source, place) { - (1, 0) => Ok(DataPieceId::Input(index)), - (2, 0) => Ok(DataPieceId::Output(index)), - (3, 0) => Ok(DataPieceId::CellDep(index)), - (0x0100000000000001, 0) => Ok(DataPieceId::GroupInput(index)), - (0x0100000000000002, 0) => Ok(DataPieceId::GroupOutput(index)), - (1, 1) => Ok(DataPieceId::Witness(index)), - (2, 1) => Ok(DataPieceId::Witness(index)), - (0x0100000000000001, 1) => Ok(DataPieceId::WitnessGroupInput(index)), - (0x0100000000000002, 1) => Ok(DataPieceId::WitnessGroupOutput(index)), - _ => Err(format!("Invalid source value: {:#x}", source)), - } - } -} - -/// Full state representing all VM instances from verifying a CKB script. -/// It should be serializable to binary formats, while also be able to -/// fully recover the running environment with the full transaction environment. -#[derive(Clone, Debug)] -pub struct FullSuspendedState { - pub max_vms_count: u64, - pub total_cycles: Cycle, - pub next_vm_id: VmId, - pub next_pipe_slot: u64, - pub vms: Vec<(VmId, VmState, Snapshot2)>, - pub pipes: Vec<(PipeId, VmId)>, - pub inherited_fd: Vec<(VmId, Vec)>, - pub terminated_vms: Vec<(VmId, i8)>, -} - -impl FullSuspendedState { - pub fn size(&self) -> u64 { - (size_of::() - + size_of::() - + size_of::() - + self.vms.iter().fold(0, |mut acc, (_, _, snapshot)| { - acc += size_of::() + size_of::(); - acc += snapshot.pages_from_source.len() - * (size_of::() - + size_of::() - + size_of::() - + size_of::() - + size_of::()); - for dirty_page in &snapshot.dirty_pages { - acc += size_of::() + size_of::() + dirty_page.2.len(); - } - acc += size_of::() - + RISCV_GENERAL_REGISTER_NUMBER * size_of::() - + size_of::() - + size_of::() - + size_of::(); - acc - }) - + (self.pipes.len() * (size_of::() + size_of::()))) as u64 - + (self.inherited_fd.len() * (size_of::())) as u64 - + (self.terminated_vms.len() * (size_of::() + size_of::())) as u64 - } -} - -/// Context data for current running transaction & script -#[derive(Clone)] -pub struct TxData
{ - pub rtx: Arc, - pub data_loader: DL, - // Ideally one might not want to keep program here, since program is totally - // deducible from rtx + data_loader, however, for a demo here, program - // does help us save some extra coding. - pub program: Bytes, - pub script_group: Arc, -} - -impl
DataSource for TxData
-where - DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, -{ - fn load_data(&self, id: &DataPieceId, offset: u64, length: u64) -> Result<(Bytes, u64), Error> { - match id { - DataPieceId::Program => { - // This is just a shortcut so we don't have to copy over the logic in extract_script, - // ideally you can also only define the rest 5, then figure out a way to convert - // script group to the actual cell dep index. - Ok(self.program.clone()) - } - DataPieceId::Input(i) => { - let cell = self - .rtx - .resolved_inputs - .get(*i as usize) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - self.data_loader.load_cell_data(cell).ok_or_else(|| { - Error::Unexpected(format!("Loading input cell #{}'s data failed!", i)) - }) - } - DataPieceId::Output(i) => self - .rtx - .transaction - .outputs_data() - .get(*i as usize) - .map(|data| data.raw_data()) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())), - DataPieceId::CellDep(i) => { - let cell = self - .rtx - .resolved_cell_deps - .get(*i as usize) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - self.data_loader.load_cell_data(cell).ok_or_else(|| { - Error::Unexpected(format!("Loading dep cell #{}'s data failed!", i)) - }) - } - DataPieceId::GroupInput(i) => { - let gi = *self - .script_group - .input_indices - .get(*i as usize) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - let cell = self - .rtx - .resolved_inputs - .get(gi) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - self.data_loader.load_cell_data(cell).ok_or_else(|| { - Error::Unexpected(format!("Loading input cell #{}'s data failed!", gi)) - }) - } - DataPieceId::GroupOutput(i) => { - let gi = *self - .script_group - .output_indices - .get(*i as usize) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - self.rtx - .transaction - .outputs_data() - .get(gi) - .map(|data| data.raw_data()) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())) - } - DataPieceId::Witness(i) => self - .rtx - .transaction - .witnesses() - .get(*i as usize) - .map(|data| data.raw_data()) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())), - DataPieceId::WitnessGroupInput(i) => { - let gi = *self - .script_group - .input_indices - .get(*i as usize) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - self.rtx - .transaction - .witnesses() - .get(gi) - .map(|data| data.raw_data()) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())) - } - DataPieceId::WitnessGroupOutput(i) => { - let gi = *self - .script_group - .output_indices - .get(*i as usize) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string()))?; - self.rtx - .transaction - .witnesses() - .get(gi) - .map(|data| data.raw_data()) - .ok_or_else(|| Error::External("INDEX_OUT_OF_BOUND".to_string())) - } - } - .map(|data| { - let offset = std::cmp::min(offset as usize, data.len()); - let full_length = data.len() - offset; - let slice_length = if length > 0 { - std::cmp::min(full_length, length as usize) - } else { - full_length - }; - ( - data.slice(offset..offset + slice_length), - full_length as u64, - ) - }) - } -} - -#[derive(Clone)] -pub enum RunMode { - LimitCycles(Cycle), - Pause(Pause), -} diff --git a/script/src/verify.rs b/script/src/verify.rs index 392335d031..bdcdf2e181 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1,10 +1,8 @@ +use crate::scheduler::Scheduler; #[cfg(test)] use crate::syscalls::Pause; use crate::syscalls::{InheritedFd, ProcessID}; -use crate::v2_scheduler::Scheduler; -use crate::v2_types::{ - DataPieceId, FullSuspendedState, Message, RunMode, TxData, VmId, FIRST_VM_ID, -}; +use crate::types::{DataPieceId, FullSuspendedState, Message, RunMode, TxData, VmId, FIRST_VM_ID}; use crate::{ error::{ScriptError, TransactionScriptError}, syscalls::{ From cfd998fc46bd25c82d749e302d8e92763baf67d2 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 27 Mar 2024 11:16:56 +0800 Subject: [PATCH 038/135] Remove println in check_spawn_strcat --- script/src/verify/tests/ckb_latest/features_since_v2023.rs | 1 - 1 file changed, 1 deletion(-) 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 4760368d66..de43808658 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -161,7 +161,6 @@ fn check_spawn_strcat() { }; let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - println!("result = {:?}", result); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); } From 177324308521694bf27ddd82a62d5afaee32b253 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 27 Mar 2024 16:26:45 +0800 Subject: [PATCH 039/135] verify_until_completed returns error now --- Cargo.lock | 4 ++-- script/src/verify/tests/utils.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23063f9eda..e43f69ace3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1793,7 +1793,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#e416ba4e711c5ec086f3ef17b25b79c8a2fdae43" +source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#b71f5d96798cc049f9d6dee1da5879e27ae583b0" dependencies = [ "byteorder", "bytes", @@ -1810,7 +1810,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#e416ba4e711c5ec086f3ef17b25b79c8a2fdae43" +source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#b71f5d96798cc049f9d6dee1da5879e27ae583b0" dependencies = [ "paste", ] diff --git a/script/src/verify/tests/utils.rs b/script/src/verify/tests/utils.rs index 1051889106..760921f627 100644 --- a/script/src/verify/tests/utils.rs +++ b/script/src/verify/tests/utils.rs @@ -246,14 +246,15 @@ impl TransactionScriptsVerifierWithEnv { loop { times += 1; let snap = init_snap.take().unwrap(); - match verifier.resume_from_snap(&snap, max_cycles).unwrap() { - VerifyResult::Suspended(state) => { + match verifier.resume_from_snap(&snap, max_cycles) { + Ok(VerifyResult::Suspended(state)) => { init_snap = Some(state.try_into().unwrap()); } - VerifyResult::Completed(cycle) => { + Ok(VerifyResult::Completed(cycle)) => { cycles = cycle; break; } + Err(e) => return Err(e), } } From c5292b3a5f373ff37f0555ff798ddc3cde0f1ca5 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 27 Mar 2024 16:58:26 +0800 Subject: [PATCH 040/135] exec callee pause --- .../tests/ckb_latest/features_since_v2021.rs | 35 ++++++++++++++++++ script/testdata/Makefile | 1 + script/testdata/exec_callee_pause | Bin 0 -> 1696 bytes script/testdata/exec_callee_pause.c | 29 +++++++++++++++ 4 files changed, 65 insertions(+) create mode 100755 script/testdata/exec_callee_pause create mode 100644 script/testdata/exec_callee_pause.c diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index e3b3a70579..e76b6124e0 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -1788,3 +1788,38 @@ fn check_signature_referenced_via_type_hash_ok_with_multiple_matches() { let result = verifier.verify_without_limit(script_version, &rtx); assert_eq!(result.unwrap(), 539); } + +#[test] +fn check_exec_callee_pause() { + let script_version = SCRIPT_VERSION; + + let (exec_caller_cell, exec_caller_data_hash) = + load_cell_from_path("testdata/exec_caller_from_cell_data"); + let (exec_callee_cell, _exec_callee_data_hash) = + load_cell_from_path("testdata/exec_callee_pause"); + + let exec_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(exec_caller_data_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(exec_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![exec_caller_cell, exec_callee_cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify_until_completed(script_version, &rtx); + assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1); + assert_eq!(result.unwrap().1, 5); +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index dc78c088ca..add707f868 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -118,6 +118,7 @@ vm_version: vm_version.c vm_version_2: vm_version_2.c vm_version_with_snapshot: vm_version_with_snapshot.c exec_callee: exec_callee.c +exec_callee_pause: exec_callee_pause.c exec_caller_from_cell_data: exec_caller_from_cell_data.c exec_caller_from_witness: exec_caller_from_witness.c exec_caller_big_offset_length: exec_caller_big_offset_length.c diff --git a/script/testdata/exec_callee_pause b/script/testdata/exec_callee_pause new file mode 100755 index 0000000000000000000000000000000000000000..5bf0e730bbc0bf331878b19df65ab209a649840a GIT binary patch literal 1696 zcmbtUO=uHA6n>jzv#B6WES6Rerc$I8S&~?#cxu{if*`ff3f?B0&Df@7ld!ujtrwfp zf(Jdw9?V53o~0DLc=PJfqc=r8co0%isEDZZc4zXlv|jpP=X>vaKQlY?W*%s_av@0q zAtCqT<-CS0zR&AQy|3s zU@39&%cakkx1(S8wp%czJkHCSq5Oc4h3V4slB{oSw%~)@EVxQM+NXu{3Va$k{L_Nn zNVDWB$>?dH8$SHqf?)~f!sjj={%S!oBx!eEKOF&Z8`+(Zb_Jwd>)`!QH}+Px zam~wFIv~q~4Nb~5a#FsLcVj~j(bEqH{gUR!#@g1_CV*pYkh;EVQ^?QE+(?csWhlKy zC$6Sa>B;eAI-_RP6l8C+e5-65YanS%jl^YZ?fOJHQ%@5!Q%?~cH3PN#rny>4qf*p; zDEeUdU^8G9{wra&`}^&a=!AyZsTR6=L3qM=%11~TcvE!w@Yo{o?Qa+5sb{@WYWJ1! z3qBQ?SMb4gF0#ZptG_bL8-y3S=kXy}N%Zn-j6cKvRn%8`{1eWLK0n9#O@?u{5A{Hu zN1PAVZ!#Y1i*@2UP@b_5>jdLp9K*lld~jZ%>(n5IUa3&(H zy;iO|)EWgs7G|@HSu(BVZ_W|Y)wP67FDwvkZkDlx6m6T>j&3<%>g6gUda?*D>5dMB zR!ab?yt~;PwH7{B=~ F{D1fl&{O~b literal 0 HcmV?d00001 diff --git a/script/testdata/exec_callee_pause.c b/script/testdata/exec_callee_pause.c new file mode 100644 index 0000000000..5f07641f75 --- /dev/null +++ b/script/testdata/exec_callee_pause.c @@ -0,0 +1,29 @@ +#include +#include "ckb_syscalls.h" +#include + +void try_pause() { + ckb_debug("try_pause"); + syscall(2178, 0, 0, 0, 0, 0, 0); +} + +int main(int argc, char* argv[]) { + try_pause(); + if (argc != 3) { + return 1; + } + try_pause(); + if (argv[0][0] != 'a') { + return 2; + } + try_pause(); + if (argv[1][0] != 'b') { + return 3; + } + try_pause(); + if (argv[2][0] != 'c') { + return 4; + } + try_pause(); + return 0; +} From 368124f3873621ff8b5d80b79bd259381e12a7aa Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 27 Mar 2024 17:06:33 +0800 Subject: [PATCH 041/135] Clean --- script/testdata/exec_callee_pause.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/script/testdata/exec_callee_pause.c b/script/testdata/exec_callee_pause.c index 5f07641f75..f3cc85fc84 100644 --- a/script/testdata/exec_callee_pause.c +++ b/script/testdata/exec_callee_pause.c @@ -1,6 +1,4 @@ -#include #include "ckb_syscalls.h" -#include void try_pause() { ckb_debug("try_pause"); From 16d5aa834e3d84ca389ce45f6bf3609baa1da676 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 28 Mar 2024 10:07:42 +0800 Subject: [PATCH 042/135] fix test case check_exec_callee_pause --- script/src/verify.rs | 33 +++++++------------ .../tests/ckb_latest/features_since_v2021.rs | 10 +++--- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index bdcdf2e181..f01360f5d8 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -662,7 +662,7 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None, false) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { current_consumed_cycles = wrapping_cycles_add(current_consumed_cycles, consumed_cycles, group)?; @@ -748,7 +748,7 @@ where })?; // continue snapshot current script - match self.verify_group_with_chunk(current_group, limit_cycles, &snap.state, true) { + match self.verify_group_with_chunk(current_group, limit_cycles, &snap.state) { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { current_used = wrapping_cycles_add( current_used, @@ -775,7 +775,7 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None, true) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { current_used = wrapping_cycles_add(current_used, consumed_cycles, group)?; cycles = wrapping_cycles_add(cycles, used_cycles, group)?; @@ -830,7 +830,7 @@ where //eprintln!("begin to run with limit_cycles: {}", limit_cycles); let resumed_script_result = - self.verify_group_with_chunk(current_group, limit_cycles, &state, false); + self.verify_group_with_chunk(current_group, limit_cycles, &state); match resumed_script_result { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { @@ -856,7 +856,7 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None, false) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { current_used = wrapping_cycles_add(current_used, consumed_cycles, group)?; eprintln!("used_cycles: {:?}", used_cycles); @@ -906,7 +906,7 @@ where // continue snapshot current script // max_cycles - cycles checked - match self.verify_group_with_chunk(current_group, max_cycles - cycles, &snap.state, true) { + match self.verify_group_with_chunk(current_group, max_cycles - cycles, &snap.state) { Ok(ChunkState::Completed(used_cycles, _consumed_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } @@ -928,7 +928,7 @@ where .source(group) })?; - match self.verify_group_with_chunk(group, remain_cycles, &None, true) { + match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles, _consumed_cycles)) => { cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } @@ -1004,7 +1004,6 @@ where group: &ScriptGroup, max_cycles: Cycle, state: &Option, - until_complete: bool, ) -> Result { if group.script.code_hash() == TYPE_ID_CODE_HASH.pack() && Into::::into(group.script.hash_type()) == Into::::into(ScriptHashType::Type) @@ -1020,7 +1019,7 @@ where Err(e) => Err(e), } } else { - self.chunk_run(group, max_cycles, state, until_complete) + self.chunk_run(group, max_cycles, state) } } @@ -1029,7 +1028,6 @@ where script_group: &ScriptGroup, max_cycles: Cycle, state: &Option, - until_complete: bool, ) -> Result { let program = self.extract_script(&script_group.script)?; let tx_data = TxData { @@ -1071,18 +1069,11 @@ where } } Err(error) => match error { - VMInternalError::CyclesExceeded => { - if let Ok(snapshot) = scheduler.suspend() { - return Ok(ChunkState::suspended(snapshot)); - } else { - panic!("scheduler suspend error"); - } - } - VMInternalError::Pause => { - if !until_complete { - return Ok(ChunkState::Suspended(None)); - } + VMInternalError::CyclesExceeded | VMInternalError::Pause => { + let snapshot = scheduler.suspend().map_err(map_vm_internal_error)?; + return Ok(ChunkState::suspended(snapshot)); } + _ => return Err(map_vm_internal_error(error)), }, } diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index e76b6124e0..8b127b0008 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -548,7 +548,6 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa current_group.unwrap(), limit, &Some(cur_state), - false, ) { Ok(ChunkState::Completed(used_cycles, _consumed_cycles)) => { cycles += used_cycles; @@ -571,7 +570,7 @@ fn _check_type_id_one_in_one_out_resume(step_cycles: Cycle) -> Result<(), TestCa while let Some((ty, _, group)) = groups.front().cloned() { match verifier - .verify_group_with_chunk(group, limit, &tmp, false) + .verify_group_with_chunk(group, limit, &tmp) .unwrap() { ChunkState::Completed(used_cycles, _consumed_cycles) => { @@ -751,7 +750,7 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle loop { while let Some(group) = groups.pop() { match verifier - .verify_group_with_chunk(group.2, limit, &tmp, false) + .verify_group_with_chunk(group.2, limit, &tmp) .unwrap() { ChunkState::Completed(used_cycles, _consumed_cycles) => { @@ -1792,6 +1791,9 @@ fn check_signature_referenced_via_type_hash_ok_with_multiple_matches() { #[test] fn check_exec_callee_pause() { let script_version = SCRIPT_VERSION; + if script_version < crate::ScriptVersion::V1 { + return; + } let (exec_caller_cell, exec_caller_data_hash) = load_cell_from_path("testdata/exec_caller_from_cell_data"); @@ -1821,5 +1823,5 @@ fn check_exec_callee_pause() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_until_completed(script_version, &rtx); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1); - assert_eq!(result.unwrap().1, 5); + assert_eq!(result.unwrap().1, 6); } From b451b3f565dccd862e1dd7b0ebdb09d6d606268a Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 28 Mar 2024 12:52:30 +0800 Subject: [PATCH 043/135] fix test for resume_from_snap --- script/src/verify.rs | 17 +------ .../tests/ckb_latest/features_since_v2021.rs | 47 +++++++++++++++---- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index f01360f5d8..f09e18f791 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -738,7 +738,6 @@ where snap: &TransactionSnapshot, limit_cycles: Cycle, ) -> Result { - let current_group_used = snap.current_cycles; let mut cycles = snap.current_cycles; let mut current_used = 0; @@ -750,11 +749,7 @@ where // continue snapshot current script match self.verify_group_with_chunk(current_group, limit_cycles, &snap.state) { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { - current_used = wrapping_cycles_add( - current_used, - wrapping_cycles_sub(consumed_cycles, current_group_used, current_group)?, - current_group, - )?; + current_used = wrapping_cycles_add(current_used, consumed_cycles, current_group)?; cycles = wrapping_cycles_add(cycles, used_cycles, current_group)?; } Ok(ChunkState::Suspended(state)) => { @@ -828,7 +823,6 @@ where ScriptError::Other(format!("snapshot group missing {current:?}")).unknown_source() })?; - //eprintln!("begin to run with limit_cycles: {}", limit_cycles); let resumed_script_result = self.verify_group_with_chunk(current_group, limit_cycles, &state); @@ -1274,15 +1268,6 @@ fn wrapping_cycles_add( .ok_or_else(|| ScriptError::CyclesOverflow(lhs, rhs).source(group)) } -fn wrapping_cycles_sub( - lhs: Cycle, - rhs: Cycle, - group: &ScriptGroup, -) -> Result { - lhs.checked_sub(rhs) - .ok_or_else(|| ScriptError::CyclesOverflow(lhs, rhs).source(group)) -} - #[cfg(feature = "logging")] mod logging { use super::{info, Byte32, ScriptError}; diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 8b127b0008..a6ac2ccb84 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -865,29 +865,56 @@ fn check_typical_secp256k1_blake160_2_in_2_out_tx_with_state() { fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_snap(step_cycles: Cycle) { let script_version = SCRIPT_VERSION; - let rtx = random_2_in_2_out_rtx(); let mut cycles = 0; let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify_map(script_version, &rtx, |verifier| { + let mut init_snap: Option = None; let mut init_state: Option = None; if let VerifyResult::Suspended(state) = verifier.resumable_verify(step_cycles).unwrap() { - init_state = Some(state); + init_snap = Some(state.try_into().unwrap()); } + let mut count = 0; loop { - let state = init_state.take().unwrap(); - let (limit_cycles, _last) = state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); - match verifier.resume_from_state(state, limit_cycles).unwrap() { - VerifyResult::Suspended(state) => { - init_state = Some(state); + if init_snap.is_some() { + let snap = init_snap.take().unwrap(); + let (limit_cycles, _last) = + snap.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); + match verifier.resume_from_snap(&snap, limit_cycles).unwrap() { + VerifyResult::Suspended(state) => { + if count % 500 == 0 { + init_snap = Some(state.try_into().unwrap()); + } else { + init_state = Some(state); + } + } + VerifyResult::Completed(cycle) => { + cycles = cycle; + break; + } } - VerifyResult::Completed(cycle) => { - cycles = cycle; - break; + } else { + let state = init_state.take().unwrap(); + let (limit_cycles, _last) = + state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); + match verifier.resume_from_state(state, limit_cycles).unwrap() { + VerifyResult::Suspended(state) => { + if count % 500 == 0 { + init_snap = Some(state.try_into().unwrap()); + } else { + init_state = Some(state); + } + } + VerifyResult::Completed(cycle) => { + cycles = cycle; + break; + } } } + count += 1; } verifier.verify(TWO_IN_TWO_OUT_CYCLES) From 0f76bbe90cb6d97eee055c6d5718f6afd34614fb Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 28 Mar 2024 13:22:39 +0800 Subject: [PATCH 044/135] clean up --- .../tests/ckb_latest/features_since_v2021.rs | 1 - .../tests/ckb_latest/features_since_v2023.rs | 98 ------------------- 2 files changed, 99 deletions(-) diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index a6ac2ccb84..d75ebe6bcf 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -726,7 +726,6 @@ fn _check_type_id_one_in_one_out_resume_with_state( Ok(()) } -// FIXME(yukang) proptest! { #![proptest_config(ProptestConfig::with_cases(42))] #[test] 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 de43808658..3e5ef48f28 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -637,101 +637,3 @@ fn check_spawn_current_cycles() { 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; - -// 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); -// let err = result.unwrap_err(); -// println!("{:?}", err); -// // 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); -// } From a32861daef4f3e6493b955f48b802add653d8c3e Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 29 Mar 2024 13:22:18 +0800 Subject: [PATCH 045/135] Fix load_cell_data and load_cell_data_as_code --- script/src/syscalls/load_cell_data.rs | 21 ++++++++- .../syscalls/tests/vm_latest/syscalls_1.rs | 45 +++++++++++++++++++ script/src/types.rs | 7 +-- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index a571915473..72272716fa 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -11,7 +11,7 @@ use ckb_vm::{ memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, registers::{A0, A1, A2, A3, A4, A5, A7}, snapshot2::{DataSource, Snapshot2Context}, - Error as VMError, Register, SupportMachine, Syscalls, + Bytes, Error as VMError, Register, SupportMachine, Syscalls, }; use std::sync::{Arc, Mutex}; @@ -51,6 +51,17 @@ where .lock() .map_err(|e| VMError::Unexpected(e.to_string()))?; + if size == 0 { + let (cell, _) = sc + .data_source() + .load_data(&data_piece_id, offset, u64::max_value())?; + machine + .memory_mut() + .store64(&size_addr, &Mac::REG::from_u64(cell.len() as u64))?; + machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); + return Ok(()); + } + let (wrote_size, full_size) = match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { Ok(val) => val, @@ -95,7 +106,13 @@ where .data_source() .load_data(&data_piece_id, 0, u64::max_value()) { - Ok(val) => val, + Ok(val) => { + if content_size == 0 { + (Bytes::new(), val.1) + } else { + val + } + } Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index efe8b29a68..001a31394f 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -2090,3 +2090,48 @@ fn _test_input_field_bound(field: u64) -> Result<(), TestCaseError> { prop_assert!(InputField::parse_from_u64(field).is_err()); Ok(()) } + +#[test] +fn test_load_cell_data_size_zero() { + let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); + let size_addr: u64 = 100; + let addr = 4096; + let data = [0xff; 256]; + + machine.set_register(A0, addr); // addr + machine.set_register(A1, size_addr); // size + machine.set_register(A2, 0); // offset + machine.set_register(A3, 0); // index + machine.set_register(A4, u64::from(Source::Transaction(SourceEntry::CellDep))); //source + machine.set_register(A7, LOAD_CELL_DATA_SYSCALL_NUMBER); // syscall number + + machine.memory_mut().store64(&size_addr, &0).unwrap(); + + let data = Bytes::from(data.to_vec()); + let dep_cell = build_cell_meta(10000, data.clone()); + let input_cell = build_cell_meta(100, data.clone()); + + let data_loader = new_mock_data_loader(); + + let rtx = Arc::new(ResolvedTransaction { + transaction: TransactionBuilder::default().build(), + resolved_cell_deps: vec![dep_cell], + resolved_inputs: vec![input_cell], + resolved_dep_groups: vec![], + }); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx, + data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: vec![0], + output_indices: vec![0], + }), + })))); + load_code.ecall(&mut machine).unwrap(); + assert_eq!(machine.registers()[A0], u64::from(SUCCESS)); + assert_eq!(machine.memory_mut().load64(&size_addr).unwrap(), 256); + assert_eq!(machine.memory_mut().load64(&addr).unwrap(), 0); +} diff --git a/script/src/types.rs b/script/src/types.rs index 98eee3d298..cb2d630619 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -631,15 +631,12 @@ where .map(|data| { let offset = std::cmp::min(offset as usize, data.len()); let full_length = data.len() - offset; - let slice_length = if length > 0 { + let real_length = if length > 0 { std::cmp::min(full_length, length as usize) } else { full_length }; - ( - data.slice(offset..offset + slice_length), - full_length as u64, - ) + (data.slice(offset..offset + real_length), full_length as u64) }) } } From 13fb2dfaa3299862301c6996d5d097b169394230 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 29 Mar 2024 14:23:46 +0800 Subject: [PATCH 046/135] Optimize comments --- script/src/scheduler.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 2920f106d9..e3433863da 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -65,7 +65,7 @@ where suspended: BTreeMap>, terminated_vms: BTreeMap, - // message_box is expected to be empty before returning from `run` + // MessageBox is expected to be empty before returning from `run` // function, there is no need to persist messages. message_box: Arc>>, } @@ -332,8 +332,8 @@ where for pipe in &args.pipes { self.pipes.insert(*pipe, spawned_vm_id); } - // here we keep the original version of file descriptors. - // if one fd is moved afterward, this inherited file descriptors doesn't change. + // Here we keep the original version of file descriptors. + // If one fd is moved afterward, this inherited file descriptors doesn't change. // log::info!( // "VmId = {} with Inherited file descriptor {:?}", // spawned_vm_id, @@ -608,7 +608,6 @@ where let copiable = std::cmp::min(fillable, consumable); // Actual data copying - // TODO: charge cycles let data = self .instantiated .get_mut(&write_vm_id) @@ -638,7 +637,7 @@ where // have been written, or when the pairing read pipe is closed. consumed += copiable; if consumed == write_length { - // write VM has fulfilled its write request + // Write VM has fulfilled its write request let (_, write_machine) = self.instantiated.get_mut(&write_vm_id).unwrap(); write_machine .machine @@ -685,7 +684,7 @@ where } if !uninstantiated_ids.is_empty() { - // instantiated is a BTreeMap, an iterator on it maintains key order to ensure deterministic behavior + // Instantiated is a BTreeMap, an iterator on it maintains key order to ensure deterministic behavior let suspendable_ids: Vec = self .instantiated .keys() @@ -705,7 +704,6 @@ where // Resume a suspended VM fn resume_vm(&mut self, id: &VmId) -> Result<(), Error> { - //println!("Resuming VM: {}", id); if !self.suspended.contains_key(id) { return Err(Error::Unexpected(format!("VM {:?} is not suspended!", id))); } @@ -715,7 +713,6 @@ where let mut sc = context.snapshot2_context().lock().expect("lock"); sc.resume(&mut machine.machine, snapshot)?; } - // TODO: charge cycles self.instantiated.insert(*id, (context, machine)); self.suspended.remove(id); Ok(()) @@ -730,7 +727,6 @@ where id ))); } - // TODO: charge cycles let (context, machine) = self.instantiated.get_mut(id).unwrap(); let snapshot = { let sc = context.snapshot2_context().lock().expect("lock"); @@ -750,7 +746,7 @@ where ) -> Result { // Newly booted VM will be instantiated by default while self.instantiated.len() >= MAX_INSTANTIATED_VMS { - // instantiated is a BTreeMap, first_entry will maintain key order + // Instantiated is a BTreeMap, first_entry will maintain key order let id = *self.instantiated.first_entry().unwrap().key(); self.suspend_vm(&id)?; } From 527cd17419e4d0c57641697c68faa2e069193b38 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 29 Mar 2024 17:19:00 +0800 Subject: [PATCH 047/135] Rename utils.h to spawn_utils.h --- script/testdata/Makefile | 12 ++++++------ script/testdata/spawn_callee_strcat | Bin 4744 -> 4752 bytes script/testdata/spawn_callee_strcat.c | 2 +- script/testdata/spawn_caller_current_cycles | Bin 5552 -> 5512 bytes script/testdata/spawn_caller_current_cycles.c | 3 ++- script/testdata/spawn_caller_exec | Bin 4648 -> 4608 bytes script/testdata/spawn_caller_exec.c | 3 ++- script/testdata/spawn_caller_out_of_cycles | Bin 4656 -> 4616 bytes script/testdata/spawn_caller_out_of_cycles.c | 2 +- .../testdata/spawn_caller_out_of_cycles_wrap | Bin 4664 -> 4624 bytes .../spawn_caller_out_of_cycles_wrap.c | 3 ++- script/testdata/spawn_caller_strcat | Bin 5136 -> 5144 bytes script/testdata/spawn_caller_strcat.c | 2 +- script/testdata/spawn_caller_strcat_wrap | Bin 4608 -> 4616 bytes script/testdata/spawn_caller_strcat_wrap.c | 5 +++-- script/testdata/spawn_cases | Bin 12384 -> 12392 bytes script/testdata/spawn_cases.c | 2 +- script/testdata/spawn_recursive | Bin 4600 -> 4608 bytes script/testdata/spawn_recursive.c | 3 +-- script/testdata/spawn_times | Bin 4624 -> 4632 bytes script/testdata/spawn_times.c | 3 +-- script/testdata/{utils.h => spawn_utils.h} | 0 22 files changed, 21 insertions(+), 19 deletions(-) rename script/testdata/{utils.h => spawn_utils.h} (100%) diff --git a/script/testdata/Makefile b/script/testdata/Makefile index add707f868..ad7519e500 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -134,17 +134,17 @@ mul2.lib: mul2.c div2.lib: div2.c 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_strcat: spawn_caller_strcat.c spawn_utils.h +spawn_callee_strcat: spawn_callee_strcat.c spawn_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_strcat_wrap: spawn_caller_strcat_wrap.c spawn_utils.h +spawn_recursive: spawn_recursive.c spawn_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 utils.h -spawn_cases: spawn_cases.c utils.h +spawn_times: spawn_times.c spawn_utils.h +spawn_cases: spawn_cases.c spawn_utils.h diff --git a/script/testdata/spawn_callee_strcat b/script/testdata/spawn_callee_strcat index 545b9ace088906e641fdb2432bf644a811934ae2..8f5d76ed3b25c67dccb3429a446a033fbc898f95 100755 GIT binary patch delta 159 zcmeBBouE2FgE3&Dra9+R9tJRYIx+J(6YJT@L5zN;t*3=qTTi}cC{TL1|7faf>R-25 zx5=$AQ31tT&x6}R;*;3~ml2V69w%VzfWEWBsC^K1d;)h6@~0MnFSy&@SMDmS9tOsK^_1>r#Dyt delta 147 zcmbQB+Mzl@gVAH6ra9+b9tJSDJ2CS)Q|p<@L5zN;tfz%pSx>%aC{TL1|7faf>R-25 zx5=$AQ31tT&x6}R;*;3~mI%%h)`fCz6G6?&OaG<&1YHXA0Ug ezMs4jNGeQz2_!uxYYN$O{^p0+>^XU(pgaKGurcBQ diff --git a/script/testdata/spawn_callee_strcat.c b/script/testdata/spawn_callee_strcat.c index 75bdaf4409..56daa801d8 100644 --- a/script/testdata/spawn_callee_strcat.c +++ b/script/testdata/spawn_callee_strcat.c @@ -2,7 +2,7 @@ #include #include "ckb_syscalls.h" -#include "utils.h" +#include "spawn_utils.h" char *strcat(char *restrict dest, const char *restrict src) { strcpy(dest + strlen(dest), src); diff --git a/script/testdata/spawn_caller_current_cycles b/script/testdata/spawn_caller_current_cycles index d22c5283b0d07fb543e34530f29d229abed1b5b2..d4d464dd2754e044c867121517da3d72872c1b26 100755 GIT binary patch delta 156 zcmdm>-Jv}}gVAH6ra5OZKLZ#PPt1JC#QJ@+592>BH3c@tH_R*_8AP8fOHgWMOG!*@ zYFN}J%*McWG}SeAax3c>VOG|!lM8snxD41}+|3hsHZbuQ7bKSF#g~?3<`nB?FfeQ` w=by>KSUp)#q@1yMa;JzrW9#ITKyt%mPEmVCg~^_x_ME?jAWra{d{IOm01#p@3IG5A delta 200 zcmeCs-k?1}gRx+ura9+qeg-g@Ju&kkQ|r&oK8*jk)CAZV-!QX$WDtF_EJ3N2EhRCr zsbNu@Fxv;#qp7Z`lUrH83$wOyT9TPlte3IbpMNF`n5-yjE~F~f7Rp@8t@Jt8~+!jVBv diff --git a/script/testdata/spawn_caller_current_cycles.c b/script/testdata/spawn_caller_current_cycles.c index af6149bed5..8712b2a1d2 100644 --- a/script/testdata/spawn_caller_current_cycles.c +++ b/script/testdata/spawn_caller_current_cycles.c @@ -1,8 +1,9 @@ #include #include #include -#include "utils.h" + #include "ckb_syscalls.h" +#include "spawn_utils.h" int fib(int n) { if (n < 2) { diff --git a/script/testdata/spawn_caller_exec b/script/testdata/spawn_caller_exec index dffd1dd7150ca2bcb9ba651b575b1e547f019ea6..c2496f1f4f1a33bc366beff51d60ef8dd91b8ba9 100755 GIT binary patch delta 139 zcmZ3X(x5UygYm#bO><5&9tJQl+nCAD%_uOrkXu~u1Iy7=*VM_atp|izTMxefaR0-y z1f^ECl*GiQ29V66HeogeR+#+cZQMcp#RZAwdGVzsnK{LJ84L`Y?Rh*|7|SMi3Y0UN dO=c9dXY`ot2qY^eHv-8WlMe#PvdN4>>HyjfE?ocs delta 187 zcmZorS)npPgYm^gO>@pT9tJRo+nCAD&B!phkXu~u0n5=;*VM_at%rqKS&zK`aR0-y z1f^ECl*GiQ29V66HeogaR+#+cZQMcTsd*)-MVWc&3du#Oi6yD=#U&~61(^k@#SqgO zk`r@s6q2)(z=A-r(vr-aV!e#b;yj)#jPoWZ3Y0U(O};5$&sZ>7QqZ1p!Q@CF`C#%) RL3_@5{17udCo2ld0{|W^JK6vM diff --git a/script/testdata/spawn_caller_exec.c b/script/testdata/spawn_caller_exec.c index 2d63e2f952..7fc5caa6e9 100644 --- a/script/testdata/spawn_caller_exec.c +++ b/script/testdata/spawn_caller_exec.c @@ -1,4 +1,5 @@ #include -#include "utils.h" + +#include "spawn_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 index a702a7757742198f6b4d1bc14dbdd48e9702812f..158c25680208ea769a610a4135f51bd8720f5809 100755 GIT binary patch delta 147 zcmdm>(xEazgYm>fO><5&9tJQl+nCAD%_uOrkXu~u1Iy7=*VM_atp|izTMxefaR0-y z1f^ECl*GiQ29V66HeogeR+#+cZQMcp#RZAwdGVzsnK{LJ84L`Y?Rf%O7|SM46ewpj jo6IR_&*(AP6G&D}?gWxMCZ80v=d9<4*z7quP*5HKUJx%; delta 179 zcmeBB*`P8(gYm;eO>@pT9tJRo+nCAD&B!phkXu~u0n5=;*VM_at%rqKS&zK`aR0-y z1f^ECl*GiQ29V66HeogaR+#+cZQMcTsd*)-MVWc&3du#Oi6yD=#U&~61(^k@#SqgO zk`r@s6q2)(z=A-r(vr-aV!e#b;yi&YjPoXE3Y0U(O@1g~&sZ>7QP7@o!Q@0B`C#%w LAh~?+qi@HiwhFV^WsZOGINUcG8h;(+w(-SFqTc8DNxR6 eHd#>6p3!4+Adsw>JP}Cln0ygPwoDcjQU?J1^e+nl delta 187 zcmbQBvO{Hp2IG&3n&zBwJPcqEw=t8Qn~`C1A-A~R1D2zyuBnq-TMrAfvL1Q=;r@qZ z2}-SODT#?q4Ir6CZNh8+qi?wQ}aqvi!$@l6_Sfm6H8L#i%U}C3o;8*iy@{n zBq!$NC?sbmfdzqLr6rj;#d;Z=#d#uG80Sqc6ewqmoBUG1p0QxErl39Jg2|ac^1}O)XKRJleiH-H4Fe~fb z&9fK}a5J&qogBlP!e3mFSe_SOT9TPlte3&Su=zOeN*2a-lM98)8Pz7g6tZWun5-#m a&zLbe6G$GIyi(Ynvs(~ijpt-TVR-<6)F-t7 delta 112 zcmbQCF#!k}FHF=l=al1P00X&+nf{#Z_wC*sO`qJ(KJj2bQ~SNiL5xmptq+7*TkmY1 z#dv_5srAm}7~T~2(vr-aV!e#b=XqDMFfN;1DOAoVH~FKGJ)^;7Lt%Tygvo_Ka>wM2 LK(cxAM`3jUlk_KU diff --git a/script/testdata/spawn_caller_strcat.c b/script/testdata/spawn_caller_strcat.c index b1cd8f26a2..430734e841 100644 --- a/script/testdata/spawn_caller_strcat.c +++ b/script/testdata/spawn_caller_strcat.c @@ -2,7 +2,7 @@ #include #include "ckb_syscalls.h" -#include "utils.h" +#include "spawn_utils.h" int main() { int err = 0; diff --git a/script/testdata/spawn_caller_strcat_wrap b/script/testdata/spawn_caller_strcat_wrap index 77851d83256aa91453498bead85fe8d694152ff4..10aa1fa2660967c19ad3a7d7f93235dd6380e9f7 100755 GIT binary patch delta 102 zcmZor=}?)V!FXb#ra7k>4+9vOZOqi>W^A22m0KQ2ZsiWI%%V1#G x%+C|Z!dNyrQJ|dBZ1PP3dq$7Rl7jY(6_X=@W@Mc_m0KQ2ZsiVUFD=Q;Db~x_EY1_i!k9NX jQ=pttZ}LL{dq#)Jih}lx1(Oqj #include #include -#include "utils.h" -int main() { return simple_spawn(2); } \ No newline at end of file +#include "spawn_utils.h" + +int main() { return simple_spawn(2); } diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index b80d3cd078d2145c4c1bb94149d3cc6071742c94..6dadde59beae8399b41b8eb9138d06b442581ed1 100755 GIT binary patch delta 685 zcmaEm@FHP?2BXGAO>;vFbp|ki(F_6*J|mD~17Zty2;agSBm(4boEXf-*fRMkmnvh+ zW^V3M7RHC08~H!8Ft%?l6$xf!V$Gd=N>mC&JrlJ6QkxaTqQIgx;tC+qdE!Xx_+ zi25Ne!`MDKQ^|6&pTsJVz%L0o5G5tK21K2Z+yOMVQHmFA!USos+y-eeupETbiVi@>H7YIyX;)EF15rLo5TD;<139Yy z$K-z!Vtf;X5U%k5Hu;~D*kmnX?#aE%vq4(4RKPleRP>nG^CmZ`BuT@Zp?_~#f>JA6 z%A=A*ke|{)PWi8*3$#>MRUM=?Ow|KKEl?F>JU)55Y9vrbP)!jeWTMt0P+X8$o)=$Q zl9^MimjR6A$%Wctldq}0VziiiQ2jlS+^8WABu{FTGg@qR)MRIrw6KOG2XLAI5-WgQ z0S0CUi^+*v{XnH3we*3cqBc<5W=rjMX2utj59;Z2!c)=YpL+H{1(y2uj9!x~fn>$x Xoj|f-@=twx&fB^WV?8G~>dONFzy{8J delta 683 zcmaEn@E~D=2BX46O>;v7bp|ki(F_6*J|mD~17ZVq2;aaQBm(4boEXf-$TImUmntL6 zW^V3M7RJQQjr^Zk7}+C?;q43sSKIAJ+|;<`l1I~?OH7&0sucwESP){NLEZ{G_Ys9 JJlWAe9RQWv(t!W~ diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index f43a4505b2..e11ba26894 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -1,4 +1,4 @@ -#include "utils.h" +#include "spawn_utils.h" int parent_simple_read_write(uint64_t* pid) { int err = 0; diff --git a/script/testdata/spawn_recursive b/script/testdata/spawn_recursive index 7d5c2c4de3cce51f3c0c6c1faceb5c8b4ed1255b..80d777b5bec69cde9e34b6eaa927c74cb41ee5f6 100755 GIT binary patch delta 94 zcmeyN+@LZ+gYm#bO><5&9tJQl+nA}%&Dc75Dz`k4+{zuyUtEw_o)=$Ql9^Mim%+fW rnV-j#g|TdMq(C{N+2o4?_KY5r1qJOHD<%g5$sLm?0?Cre7X{S;`N11> delta 94 zcmZor`Jp^PgK@`1O><5?9tJSb+nA}%&B!`=Dz`k4+{zuyURsiwQ>>Sreb(`GUdQ7;rWwI}$B4f+s zd`5A`md)*q8@c$43lhuo;!8_1bBgsc7#KF&^BA%)woNV+C}%92{8GT4v178PpgrS` Y$(ca%!Q_>K_MF}P5KBBK8w$z;0Hx9>H~;_u delta 110 zcmbQCGC^g62IGZ^n&zB&JPcrvH!<^~Fw2qm3?Gz_rY>qzber7DdQ7;LWwI}$A|uP> zd`59bmd)*q8@bp^OEPnc^)fcQ^BA%))=jPyC}+%@{87N3v0<{IpgrS;$%R1j#^jAa KvU&1HL3IFwBqMwP diff --git a/script/testdata/spawn_times.c b/script/testdata/spawn_times.c index da331d2162..c40100f16b 100644 --- a/script/testdata/spawn_times.c +++ b/script/testdata/spawn_times.c @@ -1,5 +1,4 @@ - -#include "utils.h" +#include "spawn_utils.h" int main() { int err = 0; diff --git a/script/testdata/utils.h b/script/testdata/spawn_utils.h similarity index 100% rename from script/testdata/utils.h rename to script/testdata/spawn_utils.h From 676b796924585aba60d8aee923e3e2522ba24807 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 1 Apr 2024 19:55:28 +0800 Subject: [PATCH 048/135] Add check_spawn_configurable testcase --- .../tests/ckb_latest/features_since_v2023.rs | 178 +++++++++++++++++- script/testdata/Makefile | 6 +- script/testdata/spawn_cases | Bin 12392 -> 12392 bytes script/testdata/spawn_configurable_callee | Bin 0 -> 5152 bytes script/testdata/spawn_configurable_callee.c | 29 +++ script/testdata/spawn_configurable_caller | Bin 0 -> 7864 bytes script/testdata/spawn_configurable_caller.c | 61 ++++++ script/testdata/spawn_utils.h | 36 ++++ 8 files changed, 305 insertions(+), 5 deletions(-) create mode 100755 script/testdata/spawn_configurable_callee create mode 100644 script/testdata/spawn_configurable_callee.c create mode 100755 script/testdata/spawn_configurable_caller create mode 100644 script/testdata/spawn_configurable_caller.c 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 3e5ef48f28..65b21a938d 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1,11 +1,11 @@ +use super::SCRIPT_VERSION; +use crate::syscalls::SOURCE_GROUP_FLAG; +use crate::verify::{tests::utils::*, *}; use ckb_types::{ - core::{capacity_bytes, Capacity, TransactionBuilder}, + core::{capacity_bytes, cell::CellMetaBuilder, Capacity, TransactionBuilder}, packed::{CellInput, CellOutputBuilder, OutPoint, Script}, }; -use super::SCRIPT_VERSION; -use crate::verify::{tests::utils::*, *}; - fn simple_spawn_test(bin_path: &str, args: &[u8]) -> Result { let script_version = SCRIPT_VERSION; @@ -637,3 +637,173 @@ fn check_spawn_current_cycles() { let result = verifier.verify_without_limit(script_version, &rtx); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); } + +#[derive(Clone, Copy)] +enum SpawnFrom { + TxInputWitness, + GroupInputWitness, + TxOutputWitness, + GroupOutputWitness, + TxCellDep, + TxInputCell, + TxOutputCell, + GroupInputCell, + GroupOutputCell, +} + +fn check_spawn_configurable_once(spawn_from: SpawnFrom) { + let script_version = SCRIPT_VERSION; + + let args = { + let mut args: Vec = vec![]; + let position = match spawn_from { + SpawnFrom::TxInputWitness => vec![0, 1, 1, 0], + SpawnFrom::GroupInputWitness => vec![0, SOURCE_GROUP_FLAG | 1, 1, 0], + SpawnFrom::TxOutputWitness => vec![0, 2, 1, 0], + SpawnFrom::GroupOutputWitness => vec![0, SOURCE_GROUP_FLAG | 2, 1, 0], + SpawnFrom::TxCellDep => vec![1, 3, 0, 0], + SpawnFrom::TxInputCell => vec![1, 1, 0, 0], + SpawnFrom::TxOutputCell => vec![0, 2, 0, 0], + SpawnFrom::GroupInputCell => vec![0, SOURCE_GROUP_FLAG | 1, 0, 0], + SpawnFrom::GroupOutputCell => vec![0, SOURCE_GROUP_FLAG | 2, 0, 0], + }; + for e in position { + args.extend(e.to_le_bytes()); + } + args + }; + + let (spawn_caller_cell, spawn_caller_data_hash) = + load_cell_from_path("testdata/spawn_configurable_caller"); + let (spawn_callee_cell, _) = load_cell_from_path("testdata/spawn_configurable_callee"); + let (always_success_cell, always_success_data_hash) = + load_cell_from_path("testdata/always_success"); + let spawn_callee_cell_data = spawn_callee_cell.mem_cell_data.as_ref().unwrap(); + let spawn_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(spawn_caller_data_hash) + .args(args.pack()) + .build(); + let always_success_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(always_success_data_hash) + .build(); + + let input_spawn_caller = create_dummy_cell( + CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(spawn_caller_script.clone()) + .build(), + ); + + let rtx = match spawn_from { + SpawnFrom::TxInputWitness | SpawnFrom::TxOutputWitness | SpawnFrom::GroupInputWitness => { + ResolvedTransaction { + transaction: TransactionBuilder::default() + .set_witnesses(vec![spawn_callee_cell_data.pack()]) + .build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell], + resolved_inputs: vec![input_spawn_caller], + resolved_dep_groups: vec![], + } + } + SpawnFrom::GroupOutputWitness => ResolvedTransaction { + transaction: TransactionBuilder::default() + .output( + CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .type_(Some(spawn_caller_script).pack()) + .build(), + ) + .set_witnesses(vec![spawn_callee_cell_data.pack()]) + .build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell], + resolved_inputs: vec![], + resolved_dep_groups: vec![], + }, + SpawnFrom::TxCellDep => ResolvedTransaction { + transaction: TransactionBuilder::default().build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell], + resolved_inputs: vec![input_spawn_caller], + resolved_dep_groups: vec![], + }, + SpawnFrom::TxInputCell => { + let input_spawn_callee_output = CellOutputBuilder::default() + .capacity(capacity_bytes!(1000).pack()) + .lock(always_success_script.clone()) + .build(); + let input_spawn_callee = CellMetaBuilder::from_cell_output( + input_spawn_callee_output, + spawn_callee_cell_data.clone(), + ) + .build(); + ResolvedTransaction { + transaction: TransactionBuilder::default().build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell, always_success_cell], + resolved_inputs: vec![input_spawn_caller, input_spawn_callee], + resolved_dep_groups: vec![], + } + } + SpawnFrom::TxOutputCell => ResolvedTransaction { + transaction: TransactionBuilder::default() + .output( + CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(always_success_script.clone()) + .build(), + ) + .output_data(spawn_callee_cell_data.pack()) + .build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell, always_success_cell], + resolved_inputs: vec![input_spawn_caller], + resolved_dep_groups: vec![], + }, + SpawnFrom::GroupInputCell => { + let input_spawn_caller = CellMetaBuilder::from_cell_output( + CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(spawn_caller_script) + .build(), + spawn_callee_cell_data.clone(), + ) + .build(); + ResolvedTransaction { + transaction: TransactionBuilder::default().build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell, always_success_cell], + resolved_inputs: vec![input_spawn_caller], + resolved_dep_groups: vec![], + } + } + SpawnFrom::GroupOutputCell => ResolvedTransaction { + transaction: TransactionBuilder::default() + .output( + CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .type_(Some(spawn_caller_script).pack()) + .build(), + ) + .output_data(spawn_callee_cell_data.pack()) + .build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell, always_success_cell], + resolved_inputs: vec![], + 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_configurable() { + check_spawn_configurable_once(SpawnFrom::TxInputWitness); + check_spawn_configurable_once(SpawnFrom::GroupInputWitness); + check_spawn_configurable_once(SpawnFrom::TxOutputWitness); + check_spawn_configurable_once(SpawnFrom::GroupOutputWitness); + check_spawn_configurable_once(SpawnFrom::TxCellDep); + check_spawn_configurable_once(SpawnFrom::TxInputCell); + check_spawn_configurable_once(SpawnFrom::TxOutputCell); + check_spawn_configurable_once(SpawnFrom::GroupInputCell); + check_spawn_configurable_once(SpawnFrom::GroupOutputCell); +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index ad7519e500..fe8fb54abd 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -67,7 +67,9 @@ ALL_BINS := jalr_zero \ spawn_caller_current_cycles \ spawn_callee_current_cycles \ spawn_times \ - spawn_cases + spawn_cases \ + spawn_configurable_caller \ + spawn_configurable_callee ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -148,3 +150,5 @@ spawn_caller_current_cycles: spawn_caller_current_cycles.c spawn_callee_current_cycles: spawn_callee_current_cycles.c spawn_times: spawn_times.c spawn_utils.h spawn_cases: spawn_cases.c spawn_utils.h +spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h +spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 6dadde59beae8399b41b8eb9138d06b442581ed1..4532307917cf25ff68c1e8fd850d6e4369efc016 100755 GIT binary patch delta 89 zcmaEn@FHP@mWas(p2@AP*}|-?neRXJzr4BqWU6QC*Dzr=1zvJ}B~AbU delta 89 zcmaEn@FHP@mWT-h_vF^rY+=^c%=aJqU*6n)GSxHnYnU)w0FpTWi?1Q2V40sl83FFi caUvm%Ob0kOZxQ8T0?~)WWB>pF diff --git a/script/testdata/spawn_configurable_callee b/script/testdata/spawn_configurable_callee new file mode 100755 index 0000000000000000000000000000000000000000..20b1024ecdbab11ac2de629b13655cd18942c2e6 GIT binary patch literal 5152 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 +#include + +#include "ckb_syscalls.h" +#include "spawn_utils.h" + +int main() { + int err = 0; + + uint64_t fds[2] = {0}; + uint64_t fds_len = countof(fds); + err = ckb_inherited_file_descriptors(fds, &fds_len); + CHECK(err); + CHECK2(fds_len == 2, ErrorCommon); + + uint8_t buffer[1024] = {0}; + size_t length; + length = 1024; + ckb_read_all(fds[CKB_STDIN], buffer, &length); + CHECK2(length == 12, ErrorCommon); + + err = ckb_write(fds[CKB_STDOUT], buffer, &length); + CHECK(err); + err = ckb_close(fds[CKB_STDOUT]); + CHECK(err); + +exit: + return err; +} diff --git a/script/testdata/spawn_configurable_caller b/script/testdata/spawn_configurable_caller new file mode 100755 index 0000000000000000000000000000000000000000..9161cdf41bcab9d791fe0eb12066a48b37d15612 GIT binary patch literal 7864 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 +#include + +#include "ckb_syscalls.h" +#include "spawn_utils.h" + +uint64_t read_u64_le(const uint8_t* src) { + return *(const uint64_t*)src; +} + +int main() { + int err = 0; + uint64_t n = 0; + + uint8_t args[32] = {0}; + n = countof(args); + err = load_script_args(args, &n); + CHECK(err); + int args_index = read_u64_le(&args[0x00]); + int args_source = read_u64_le(&args[0x08]); + int args_place = read_u64_le(&args[0x10]); + int args_bounds = read_u64_le(&args[0x18]); + printf("args.index = %d", args_index); + printf("args.source = %d", args_source); + printf("args.place = %d", args_place); + printf("args.bounds = %d", args_bounds); + + const char *argv[] = {}; + uint64_t pid = 0; + uint64_t fds[2] = {0}; + uint64_t inherited_fds[3] = {0}; + err = create_std_pipes(fds, inherited_fds); + CHECK(err); + + spawn_args_t spgs = { + .argc = countof(argv), + .argv = argv, + .process_id = &pid, + .inherited_fds = inherited_fds, + }; + err = ckb_spawn(args_index, args_source, args_place, args_bounds, &spgs); + CHECK(err); + + size_t length = 0; + length = 12; + err = ckb_write(fds[CKB_STDOUT], "Hello World!", &length); + CHECK(err); + err = ckb_close(fds[CKB_STDOUT]); + CHECK(err); + + uint8_t buffer[1024] = {0}; + length = 1024; + err = ckb_read_all(fds[CKB_STDIN], buffer, &length); + CHECK(err); + CHECK2(length == 12, ErrorCommon); + err = memcmp("Hello World!", buffer, length); + CHECK(err); + +exit: + return err; +} diff --git a/script/testdata/spawn_utils.h b/script/testdata/spawn_utils.h index cff1a3ae6c..c44117479c 100644 --- a/script/testdata/spawn_utils.h +++ b/script/testdata/spawn_utils.h @@ -140,6 +140,35 @@ int read_exact(uint64_t fd, void* buffer, size_t length, size_t* actual_length) return err; } +// Function read_all reads from fd until an error or EOF and returns the data it read. +int ckb_read_all(uint64_t fd, void* buffer, size_t* length) { + int err = 0; + size_t read_length = 0; + size_t full_length = *length; + uint8_t* b = buffer; + while (true) { + size_t n = full_length - read_length; + err = ckb_read(fd, b, &n); + if (err == CKB_OTHER_END_CLOSED) { + err = 0; + *length = read_length; + break; + } else { + CHECK(err); + } + if (full_length - read_length == 0) { + err = CKB_LENGTH_NOT_ENOUGH; + CHECK(err); + } + b += n; + read_length += n; + *length = read_length; + } + +exit: + return err; +} + // write exact `length` bytes into buffer. // Will wait forever when less bytes are read on read fd. int write_exact(uint64_t fd, void* buffer, size_t length, size_t* actual_length) { @@ -188,3 +217,10 @@ int load_script_args(uint8_t* args, size_t* length) { exit: return err; } + +void print_hex(const uint8_t* buf, size_t length) { + for (size_t i = 0; i < length; i++) { + printf("%02x ", buf[i]); + } + printf("\n"); +} From 3739f7bb8adb0934da71d4b98e00c541695a86d6 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 2 Apr 2024 13:54:24 +0800 Subject: [PATCH 049/135] Create up to 64 pipes --- script/src/scheduler.rs | 10 ++++-- script/src/syscalls/mod.rs | 1 + .../tests/ckb_latest/features_since_v2023.rs | 30 ++++++++++++++++++ script/testdata/Makefile | 2 ++ script/testdata/spawn_pipe_limits | Bin 0 -> 4528 bytes script/testdata/spawn_pipe_limits.c | 19 +++++++++++ 6 files changed, 60 insertions(+), 2 deletions(-) create mode 100755 script/testdata/spawn_pipe_limits create mode 100644 script/testdata/spawn_pipe_limits.c diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index e3433863da..cd637fe8a1 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,6 +1,7 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, INVALID_PIPE, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE, + INDEX_OUT_OF_BOUND, INVALID_PIPE, MAX_PIPE_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, + WAIT_FAILURE, }; use crate::types::MachineContext; use crate::verify::TransactionScriptsSyscallsGenerator; @@ -35,6 +36,7 @@ use std::{ const ROOT_VM_ID: VmId = FIRST_VM_ID; const MAX_VMS_COUNT: u64 = 16; const MAX_INSTANTIATED_VMS: usize = 4; +const MAX_PIPE: u64 = 64; /// A single Scheduler instance is used to verify a single script /// within a CKB transaction. @@ -384,7 +386,11 @@ where ); } Message::Pipe(vm_id, args) => { - // TODO: pipe limits + if self.next_pipe_slot - FIRST_PIPE_SLOT >= MAX_PIPE { + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + machine.machine.set_register(A0, MAX_PIPE_CREATED as u64); + continue; + } let (p1, p2, slot) = PipeId::create(self.next_pipe_slot); self.next_pipe_slot = slot; // log::debug!("VM {} creates pipes ({}, {})", vm_id, p1.0, p2.0); diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index 3d4952e99d..624b139b2d 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -67,6 +67,7 @@ pub const WAIT_FAILURE: u8 = 5; pub const INVALID_PIPE: u8 = 6; pub const OTHER_END_CLOSED: u8 = 7; pub const MAX_VMS_SPAWNED: u8 = 8; +pub const MAX_PIPE_CREATED: u8 = 9; pub const VM_VERSION: u64 = 2041; pub const CURRENT_CYCLES: u64 = 2042; 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 65b21a938d..545f632f8d 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -638,6 +638,36 @@ fn check_spawn_current_cycles() { assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); } +#[test] +fn check_spawn_pipe_limits() { + let script_version = SCRIPT_VERSION; + + let (spawn_caller_cell, spawn_caller_data_hash) = + load_cell_from_path("testdata/spawn_pipe_limits"); + + 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 transaction = TransactionBuilder::default().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); +} + #[derive(Clone, Copy)] enum SpawnFrom { TxInputWitness, diff --git a/script/testdata/Makefile b/script/testdata/Makefile index fe8fb54abd..a5e20c8502 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -68,6 +68,7 @@ ALL_BINS := jalr_zero \ spawn_callee_current_cycles \ spawn_times \ spawn_cases \ + spawn_pipe_limits \ spawn_configurable_caller \ spawn_configurable_callee @@ -150,5 +151,6 @@ spawn_caller_current_cycles: spawn_caller_current_cycles.c spawn_callee_current_cycles: spawn_callee_current_cycles.c spawn_times: spawn_times.c spawn_utils.h spawn_cases: spawn_cases.c spawn_utils.h +spawn_pipe_limits: spawn_pipe_limits.c spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h diff --git a/script/testdata/spawn_pipe_limits b/script/testdata/spawn_pipe_limits new file mode 100755 index 0000000000000000000000000000000000000000..87431dc639dbd5e8b9d38714951f831c4382b6e0 GIT binary patch literal 4528 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 literal 0 HcmV?d00001 diff --git a/script/testdata/spawn_pipe_limits.c b/script/testdata/spawn_pipe_limits.c new file mode 100644 index 0000000000..466e04d67d --- /dev/null +++ b/script/testdata/spawn_pipe_limits.c @@ -0,0 +1,19 @@ +#include + +#include "ckb_syscalls.h" +#include "spawn_utils.h" + +int main() { + int err = 0; + uint64_t pipe[2] = {0}; + for (int i = 0; i < 32; i++) { + err = ckb_pipe(pipe); + CHECK(err); + } + // Create up to 64 pipes. + err = ckb_pipe(pipe); + err = err - 9; + +exit: + return err; +} From 9ddc6612f55ade372c52c3117d7d27257d523272 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 2 Apr 2024 17:00:36 +0800 Subject: [PATCH 050/135] Add SpawnFrom:Slice to test spawn_configurable --- .../tests/ckb_latest/features_since_v2023.rs | 31 ++++++++++++++++++ script/testdata/spawn_configurable_caller | Bin 7864 -> 7872 bytes script/testdata/spawn_configurable_caller.c | 17 +++++----- script/testdata/spawn_utils.h | 21 +++++++++--- 4 files changed, 57 insertions(+), 12 deletions(-) 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 545f632f8d..dbee33bc02 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -679,6 +679,7 @@ enum SpawnFrom { TxOutputCell, GroupInputCell, GroupOutputCell, + Slice(u64, u64), } fn check_spawn_configurable_once(spawn_from: SpawnFrom) { @@ -696,6 +697,17 @@ fn check_spawn_configurable_once(spawn_from: SpawnFrom) { SpawnFrom::TxOutputCell => vec![0, 2, 0, 0], SpawnFrom::GroupInputCell => vec![0, SOURCE_GROUP_FLAG | 1, 0, 0], SpawnFrom::GroupOutputCell => vec![0, SOURCE_GROUP_FLAG | 2, 0, 0], + SpawnFrom::Slice(offset, size) => { + let (spawn_callee_cell, _) = + load_cell_from_path("testdata/spawn_configurable_callee"); + let h = offset << 32; + let l = if size == 0 { + 0 + } else { + spawn_callee_cell.mem_cell_data.unwrap().len() as u64 + }; + vec![0, 1, 1, h | l] + } }; for e in position { args.extend(e.to_le_bytes()); @@ -818,6 +830,21 @@ fn check_spawn_configurable_once(spawn_from: SpawnFrom) { resolved_inputs: vec![], resolved_dep_groups: vec![], }, + SpawnFrom::Slice(offset, size) => { + let mut data = vec![0; offset as usize]; + data.extend(spawn_callee_cell_data); + if size != 0 { + data.extend(vec![0; 0x12]); + } + ResolvedTransaction { + transaction: TransactionBuilder::default() + .set_witnesses(vec![data.pack()]) + .build(), + resolved_cell_deps: vec![spawn_caller_cell, spawn_callee_cell], + resolved_inputs: vec![input_spawn_caller], + resolved_dep_groups: vec![], + } + } }; let verifier = TransactionScriptsVerifierWithEnv::new(); @@ -836,4 +863,8 @@ fn check_spawn_configurable() { check_spawn_configurable_once(SpawnFrom::TxOutputCell); check_spawn_configurable_once(SpawnFrom::GroupInputCell); check_spawn_configurable_once(SpawnFrom::GroupOutputCell); + check_spawn_configurable_once(SpawnFrom::Slice(0, 0)); + check_spawn_configurable_once(SpawnFrom::Slice(1, 0)); + check_spawn_configurable_once(SpawnFrom::Slice(0, 1)); + check_spawn_configurable_once(SpawnFrom::Slice(1, 1)); } diff --git a/script/testdata/spawn_configurable_caller b/script/testdata/spawn_configurable_caller index 9161cdf41bcab9d791fe0eb12066a48b37d15612..e4c9a9ae9fee9573e007450c7bcd0f9bc02e4995 100755 GIT binary patch delta 1203 zcmZvcUrbY19LLW&_Yb!Q!f88fDTsB|+A=yX9aExWE2AaF_=m)pY!4!IcML;>fK~jL z{=uSI%wjz;KI{cCBZengO_&dgkf6~AlkG|8gM~1_rOB-sZX+4db9*jxY~JLY-}(JM zzwht&JL$dsvF?7|WvlU$2?Fi$=XU^NDfhN&kCk~V7GUOUsUlsn#C+Ms#BwU-h&pOg zO;v#K09}+EJB>|_+IW*g-mu59vpVFc-5p9SB(jNIV$nIP;v>yrvrsD33K3Rq>!Pqzr5En2IyF%Id;s0WG4x zQ1Rc1OoEmk+*)})Y!s}d7Jd{p@oPsL9x3$^XV#e`Ng;u8JO~?!^mM3~UZEJ|iqVNO zUI5-~81o<0N8$k(B$9Mvg=#EZ#$&S>^SKP@r3wyw`eB3=0KY618g^w>?AQ9O74S@Z z_`7RTeE`vSsdizgUdl$lbcck3Z3gT zyN|Enn^F?2NEC zv$dza_v7BKNKaU?*V#9%j(2yq((wP|ZC#OLU-s&8VzPbChIi?-hO|<8TV&e9+Sfy$&*_4I12Rcb>eau&FY*k47HTng z^~OUcDD}9QR)-)?4<@P}BCjZ&DPr^h&-jQ=FOdy4OQ~G7TKhevnD+IMW}5|?NQZ5` z`vhXjySma_!ZedC3?A$8MKVe&{&$++C}kC=-_!38T|1mMmOX^9k31{iVsKel0~ax_ k+h+LZKZG=|^Fa?u(cMRWqI)+nR`}>o&`kHOBvrBbE%eAAbpQYW delta 1167 zcmZvbZAep57{|{!+r4gKdGBs(FHW7!t=kftWh#_zzHBg~7efL+SEQAFR?1p882P+=c}`Vdr5Dx(wzcY(bKMV-5QM@ijr&vTyV_xzvdIhV7k zhWiaeW;SAgKz@9=6@W8|^>x)wv*P6~U=&|YrOC_d6rbl6F`q~{25Z5Irnnat!Q@-7?tvcwaZwiX@Vn)o0i;ZcC8QUFVDRZFBFMJHXigQ%_9Nl@lLt+5u z7hVvbIxjIkgI{ zZCXRJby{c+yE3jUj>n_;0xWJZXbsKbs2>KfPIt4P9H0nfi;A@r2(em*qa$8kj}|20 z*|IiFj^gv^3iXW{iLuwZW5UARq0s2nRro!0!>?G6_O6S4LR+=peALv9iyS?qDIask z?p_QAo(O({bUaJOJ}m*}93DjWCOKscElk`cmO;}Kvd?IaP0BWlc1+6geVStvviN6! zqkA=fN_fKOTm7j|$fSiUQoraH4LZCj)w+V#Rm4Q=C5{F@j=EJ%XC9`XW**O5(^7WV zlX#DNFzV;1n23)XDhk`*B7Y@-0cplNm%3&+gXs7vc|L424(GSyMz^|6rHxuRpkzqd zuJJdyvA*o(X!}YsR!%8pKivD$5zdh%LS_p85N~p+BRDDFk7gYNRRzjh|JObrTV_>W zp;$U6wBp02gWJ26y9U7izC-<0{U^eGA;I2YcP@|j9^FsE|HcoT2p{k6SL4`fzHG6Z zluMg0D_afu@%WLs3tDlx#bj}5lpLfcZ6+20NOIZ<) tc5ErB)8{_{k2_1e(1}OLT8H0|wFg^Dz0i(3OTGFk8>vU0Af7EL`wbmt4deg- diff --git a/script/testdata/spawn_configurable_caller.c b/script/testdata/spawn_configurable_caller.c index 071bfdea6e..72217e8b2c 100644 --- a/script/testdata/spawn_configurable_caller.c +++ b/script/testdata/spawn_configurable_caller.c @@ -16,14 +16,15 @@ int main() { n = countof(args); err = load_script_args(args, &n); CHECK(err); - int args_index = read_u64_le(&args[0x00]); - int args_source = read_u64_le(&args[0x08]); - int args_place = read_u64_le(&args[0x10]); - int args_bounds = read_u64_le(&args[0x18]); - printf("args.index = %d", args_index); - printf("args.source = %d", args_source); - printf("args.place = %d", args_place); - printf("args.bounds = %d", args_bounds); + CHECK2(n == 32, ErrorCommon); + uint64_t args_index = read_u64_le(&args[0x00]); + uint64_t args_source = read_u64_le(&args[0x08]); + uint64_t args_place = read_u64_le(&args[0x10]); + uint64_t args_bounds = read_u64_le(&args[0x18]); + printf("args.index = %llu", args_index); + printf("args.source = %llu", args_source); + printf("args.place = %llu", args_place); + printf("args.bounds = %llu", args_bounds); const char *argv[] = {}; uint64_t pid = 0; diff --git a/script/testdata/spawn_utils.h b/script/testdata/spawn_utils.h index c44117479c..2612e24f24 100644 --- a/script/testdata/spawn_utils.h +++ b/script/testdata/spawn_utils.h @@ -219,8 +219,21 @@ int load_script_args(uint8_t* args, size_t* length) { } void print_hex(const uint8_t* buf, size_t length) { - for (size_t i = 0; i < length; i++) { - printf("%02x ", buf[i]); - } - printf("\n"); + char dst[65] = {0}; + int j = 0; + for (int i = 0; i < length; i++) { + char hi = buf[i] >> 4; + char lo = buf[i] & 0xf; + dst[j * 2] = hi + (hi < 10 ? '0' : ('a' - 10)); + dst[j * 2 + 1] = lo + (lo < 10 ? '0' : ('a' - 10)); + j += 1; + if (j > 31) { + j = 0; + printf("%s", dst); + } + } + if (j != 0) { + dst[j * 2] = 0; + printf("%s", dst); + } } From 7f5697a926fed9142a176f6fc6b6d924db85f8b0 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 3 Apr 2024 18:09:19 +0800 Subject: [PATCH 051/135] Add spawn dag testcase --- script/Cargo.toml | 2 + script/src/scheduler.rs | 1 + .../tests/ckb_latest/features_since_v2023.rs | 376 ++ script/testdata/Makefile | 4 +- script/testdata/spawn_dag | Bin 0 -> 13608 bytes script/testdata/spawn_dag.c | 340 ++ script/testdata/spawn_dag.h | 887 +++++ script/testdata/spawn_dag.mol | 34 + script/testdata/spawn_dag.rs | 3261 +++++++++++++++++ script/testdata/spawn_dag_escape_encoding.h | 82 + 10 files changed, 4986 insertions(+), 1 deletion(-) create mode 100755 script/testdata/spawn_dag create mode 100644 script/testdata/spawn_dag.c create mode 100644 script/testdata/spawn_dag.h create mode 100644 script/testdata/spawn_dag.mol create mode 100644 script/testdata/spawn_dag.rs create mode 100644 script/testdata/spawn_dag_escape_encoding.h diff --git a/script/Cargo.toml b/script/Cargo.toml index 3c36d45226..005ee9f1b4 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -40,3 +40,5 @@ ckb-crypto = { path = "../util/crypto", version = "= 0.115.0-pre" } ckb-db-schema = { path = "../db-schema", version = "= 0.115.0-pre" } tempfile.workspace = true rand = "0.8.4" +daggy = "0.8.0" +molecule = "0.7.5" diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index cd637fe8a1..f078be7eb4 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -307,6 +307,7 @@ where for message in messages { match message { Message::Spawn(vm_id, args) => { + println!("message:spawn {:?}", vm_id); // All pipes must belong to the correct owner let mut pipes_valid = true; for pipe in &args.pipes { 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 dbee33bc02..69b2165354 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -868,3 +868,379 @@ fn check_spawn_configurable() { check_spawn_configurable_once(SpawnFrom::Slice(0, 1)); check_spawn_configurable_once(SpawnFrom::Slice(1, 1)); } + + +#[allow(dead_code)] +#[path = "../../../../testdata/spawn_dag.rs"] +mod spawn_dag; +use molecule::prelude::Byte; +use spawn_dag as dag; +// use spawn_dag::*; +use daggy::{Dag, Walker}; +use ckb_types::bytes::Bytes; +use rand::{rngs::StdRng, Rng, SeedableRng}; +use std::collections::{HashSet, VecDeque}; +// use ckb_types::core::DepType; +// use ckb_types::packed::CellDep; + +pub fn generate_data_graph( + seed: u64, + spawns: u32, + writes: u32, + converging_threshold: u32, +) -> Result { + let mut rng = StdRng::seed_from_u64(seed); + + let mut spawn_dag: Dag<(), ()> = Dag::new(); + let mut write_dag: Dag<(), ()> = Dag::new(); + + // Root node denoting entrypoint VM + let spawn_root = spawn_dag.add_node(()); + let write_root = write_dag.add_node(()); + assert_eq!(spawn_root.index(), 0); + assert_eq!(write_root.index(), 0); + + let mut spawn_nodes = vec![spawn_root]; + let mut write_nodes = vec![write_root]; + + for _ in 1..=spawns { + let write_node = write_dag.add_node(()); + write_nodes.push(write_node); + + let previous_node = spawn_nodes[rng.gen_range(0..spawn_nodes.len())]; + let (_, spawn_node) = spawn_dag.add_child(previous_node, (), ()); + spawn_nodes.push(spawn_node); + } + + let mut write_edges = Vec::new(); + if spawns > 0 { + for _ in 1..=writes { + let mut updated = false; + + for _ in 0..converging_threshold { + let first_index = rng.gen_range(0..write_nodes.len()); + let second_index = { + let mut i = first_index; + while i == first_index { + i = rng.gen_range(0..write_nodes.len()); + } + i + }; + + let first_node = write_nodes[first_index]; + let second_node = write_nodes[second_index]; + + if let Ok(e) = write_dag.add_edge(first_node, second_node, ()) { + write_edges.push(e); + updated = true; + break; + } + } + + if !updated { + break; + } + } + } + + // Edge index -> pipe indices. Daggy::edge_endpoints helps us finding + // nodes (vms) from edges (spawns) + let mut spawn_ops: HashMap> = HashMap::default(); + // Node index -> created pipes + let mut pipes_ops: BTreeMap> = BTreeMap::default(); + + let mut spawn_edges = Vec::new(); + // Traversing spawn_dag for spawn operations + let mut processing = VecDeque::from([spawn_root]); + while !processing.is_empty() { + let node = processing.pop_front().unwrap(); + pipes_ops.insert(node.index(), Vec::new()); + let children: Vec<_> = spawn_dag.children(node).iter(&spawn_dag).collect(); + for (e, n) in children.into_iter().rev() { + spawn_ops.insert(e.index(), Vec::new()); + spawn_edges.push(e); + + processing.push_back(n); + } + } + + let mut writes_builder = dag::WritesBuilder::default(); + // Traversing all edges in write_dag + for e in write_edges { + let (writer, reader) = write_dag.edge_endpoints(e).unwrap(); + assert_ne!(writer, reader); + let writer_pipe_index = e.index() * 2 + 1; + let reader_pipe_index = e.index() * 2; + + // Generate finalized write op + { + let data_len = rng.gen_range(1..=1024); + let mut data = vec![0u8; data_len]; + rng.fill(&mut data[..]); + + writes_builder = writes_builder.push( + dag::WriteBuilder::default() + .from(build_vm_index(writer.index() as u64)) + .from_pipe(build_pipe_index(writer_pipe_index as u64)) + .to(build_vm_index(reader.index() as u64)) + .to_pipe(build_pipe_index(reader_pipe_index as u64)) + .data( + dag::BytesBuilder::default() + .extend(data.iter().map(|b| Byte::new(*b))) + .build(), + ) + .build(), + ); + } + + // Finding the lowest common ancestor of writer & reader nodes + // in spawn_dag, which will creates the pair of pipes. Note that + // all traversed spawn edges will have to pass the pipes down. + // + // TODO: we use a simple yet slow LCA solution, a faster algorithm + // can be used to replace the code here if needed. + let ancestor = { + let mut a = writer; + let mut b = reader; + + let mut set_a = HashSet::new(); + set_a.insert(a); + let mut set_b = HashSet::new(); + set_b.insert(b); + + loop { + let parents_a: Vec<_> = spawn_dag.parents(a).iter(&spawn_dag).collect(); + let parents_b: Vec<_> = spawn_dag.parents(b).iter(&spawn_dag).collect(); + + assert!( + ((parents_a.len() == 1) && (parents_b.len() == 1)) + || (parents_a.is_empty() && (parents_b.len() == 1)) + || ((parents_a.len() == 1) && parents_b.is_empty()) + ); + + // Update spawn ops to pass down pipes via edges, also update + // each node's path node list + if parents_a.len() == 1 { + let (_, parent_a) = parents_a[0]; + set_a.insert(parent_a); + + a = parent_a; + } + if parents_b.len() == 1 { + let (_, parent_b) = parents_b[0]; + set_b.insert(parent_b); + + b = parent_b; + } + + // Test for ancestor + if parents_a.len() == 1 { + let (_, parent_a) = parents_a[0]; + if set_b.contains(&parent_a) { + break parent_a; + } + } + if parents_b.len() == 1 { + let (_, parent_b) = parents_b[0]; + if set_a.contains(&parent_b) { + break parent_b; + } + } + } + }; + + // Update the path from each node to the LCA so we can pass created + // pipes from LCA to each node + { + let mut a = writer; + while a != ancestor { + let parents_a: Vec<_> = spawn_dag.parents(a).iter(&spawn_dag).collect(); + assert!(parents_a.len() == 1); + let (edge_a, parent_a) = parents_a[0]; + spawn_ops + .get_mut(&edge_a.index()) + .unwrap() + .push(writer_pipe_index); + a = parent_a; + } + + let mut b = reader; + while b != ancestor { + let parents_b: Vec<_> = spawn_dag.parents(b).iter(&spawn_dag).collect(); + assert!(parents_b.len() == 1); + let (edge_b, parent_b) = parents_b[0]; + spawn_ops + .get_mut(&edge_b.index()) + .unwrap() + .push(reader_pipe_index); + b = parent_b; + } + } + + // Create the pipes at the ancestor node + pipes_ops + .get_mut(&ancestor.index()) + .unwrap() + .push((reader_pipe_index, writer_pipe_index)); + } + + let mut spawns_builder = dag::SpawnsBuilder::default(); + for e in spawn_edges { + let (parent, child) = spawn_dag.edge_endpoints(e).unwrap(); + + let pipes = { + let mut builder = dag::PipeIndicesBuilder::default(); + for p in &spawn_ops[&e.index()] { + builder = builder.push(build_pipe_index(*p as u64)); + } + builder.build() + }; + + spawns_builder = spawns_builder.push( + dag::SpawnBuilder::default() + .from(build_vm_index(parent.index() as u64)) + .child(build_vm_index(child.index() as u64)) + .pipes(pipes) + .build(), + ); + } + + let mut pipes_builder = dag::PipesBuilder::default(); + for (vm_index, pairs) in pipes_ops { + for (reader_pipe_index, writer_pipe_index) in pairs { + pipes_builder = pipes_builder.push( + dag::PipeBuilder::default() + .vm(build_vm_index(vm_index as u64)) + .read_pipe(build_pipe_index(reader_pipe_index as u64)) + .write_pipe(build_pipe_index(writer_pipe_index as u64)) + .build(), + ); + } + } + + Ok(dag::DataBuilder::default() + .spawns(spawns_builder.build()) + .pipes(pipes_builder.build()) + .writes(writes_builder.build()) + .build()) +} + +fn build_vm_index(val: u64) -> dag::VmIndex { + let mut data = [Byte::new(0); 8]; + for (i, v) in val.to_le_bytes().into_iter().enumerate() { + data[i] = Byte::new(v); + } + dag::VmIndexBuilder::default().set(data).build() +} + +fn build_pipe_index(val: u64) -> dag::PipeIndex { + let mut data = [Byte::new(0); 8]; + for (i, v) in val.to_le_bytes().into_iter().enumerate() { + data[i] = Byte::new(v); + } + dag::PipeIndexBuilder::default().set(data).build() +} + +// fn random_out_point(rng: &mut R) -> OutPoint { +// let tx_hash = { +// let mut buf = [0u8; 32]; +// rng.fill(&mut buf); +// buf.pack() +// }; +// OutPoint::new(tx_hash, 0) +// } + +// pub fn random_script(rng: &mut R, t: ScriptHashType) -> Script { +// let code_hash = { +// let mut buf = [0u8; 32]; +// rng.fill(&mut buf[..]); +// buf.pack() +// }; +// let args = { +// let len = rng.gen_range(1..101); +// let mut buf = vec![0u8; len]; +// rng.fill(&mut buf[..]); +// buf.pack() +// }; +// Script::new_builder() +// .code_hash(code_hash) +// .hash_type(t.into()) +// .args(args) +// .build() +// } + +pub fn build_mock_tx(_seed: u64, program: Bytes, data: dag::Data) -> ResolvedTransaction { + let script_version = SCRIPT_VERSION; + // let mut rng = StdRng::seed_from_u64(seed); + + let (code_dep, code_dep_hash) = load_cell_from_slice(&program[..]); + + // let code_type_script = random_script(&mut rng, ScriptHashType::Type); + // let code_dep = MockCellDep { + // cell_dep: CellDep::new_builder() + // .out_point(random_out_point(&mut rng)) + // .dep_type(DepType::Code.into()) + // .build(), + // output: CellOutput::new_builder() + // .type_(Some(code_type_script.clone()).pack()) + // .build(), + // data: program, + // header: None, + // }; + + let spawn_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(code_dep_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(spawn_caller_script) + .build(); + let dummy_cell = create_dummy_cell(output); + + // let input_lock_script = Script::new_builder() + // .code_hash(code_type_script.calc_script_hash()) + // .hash_type(ScriptHashType::Type.into()) + // .build(); + // let input_cell = MockInput { + // input: CellInput::new_builder() + // .previous_output(random_out_point(&mut rng)) + // .build(), + // output: CellOutput::new_builder().lock(input_lock_script).build(), + // data: Bytes::default(), + // header: None, + // }; + + let tx = TransactionBuilder::default() + // .cell_dep(code_dep.cell_dep.clone()) + // .input(input_cell.input.clone()) + // .output(CellOutput::new_builder().build()) + .witness(data.as_bytes().pack()) + .build(); + + ResolvedTransaction { + transaction: tx, + resolved_cell_deps: vec![code_dep], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + } +} + +#[test] +fn test_single_dag() { + let script_version = SCRIPT_VERSION; + + let seed = 0; + let spawns = 8; + let writes = 64; + + let data = generate_data_graph(seed, spawns, writes, 3).unwrap(); + let program = std::fs::read("./testdata/spawn_dag").unwrap().into(); + + let rtx = build_mock_tx(seed.wrapping_add(10), program, data); + + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify_without_limit(script_version, &rtx); + println!("{:?}", result); + assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index a5e20c8502..eb46eb0e5b 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -70,7 +70,8 @@ ALL_BINS := jalr_zero \ spawn_cases \ spawn_pipe_limits \ spawn_configurable_caller \ - spawn_configurable_callee + spawn_configurable_callee \ + spawn_dag ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -154,3 +155,4 @@ spawn_cases: spawn_cases.c spawn_utils.h spawn_pipe_limits: spawn_pipe_limits.c spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h +spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h diff --git a/script/testdata/spawn_dag b/script/testdata/spawn_dag new file mode 100755 index 0000000000000000000000000000000000000000..4e1b454908f2225e445e887d60cbc54ccfdddf2f GIT binary patch literal 13608 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 +#include + +#include "spawn_dag.h" +#include "spawn_dag_escape_encoding.h" +#include "ckb_syscalls.h" + +#define INPUT_DATA_LENGTH (600 * 1024) +#define MAX_PIPE_COUNT 3200 +#define MAX_SPAWNED_VMS 1024 + +#define _BASE_ERROR_CODE 42 +#define ERROR_NO_SPACE_FOR_PIPES (_BASE_ERROR_CODE + 1) +#define ERROR_NOT_FOUND (_BASE_ERROR_CODE + 2) +#define ERROR_ENCODING (_BASE_ERROR_CODE + 3) +#define ERROR_ARGV (_BASE_ERROR_CODE + 4) +#define ERROR_TOO_MANY_SPAWNS (_BASE_ERROR_CODE + 5) +#define ERROR_PIPE_CLOSED (_BASE_ERROR_CODE + 6) +#define ERROR_CORRUPTED_DATA (_BASE_ERROR_CODE + 7) + +typedef struct { + uint64_t indices[MAX_PIPE_COUNT]; + uint64_t ids[MAX_PIPE_COUNT + 1]; + size_t used; +} pipes_t; + +void pipes_init(pipes_t *pipes) { + pipes->used = 0; + pipes->ids[pipes->used] = 0; +} + +int pipes_add(pipes_t *pipes, uint64_t index, uint64_t id) { + if (pipes->used >= MAX_PIPE_COUNT) { + return ERROR_NO_SPACE_FOR_PIPES; + } + pipes->indices[pipes->used] = index; + pipes->ids[pipes->used] = id; + pipes->used++; + pipes->ids[pipes->used] = 0; + return CKB_SUCCESS; +} + +int pipes_find(const pipes_t *pipes, uint64_t index, uint64_t *id) { + for (size_t i = 0; i < pipes->used; i++) { + if (pipes->indices[i] == index) { + *id = pipes->ids[i]; + return CKB_SUCCESS; + } + } + return ERROR_NOT_FOUND; +} + +int main(int argc, char *argv[]) { + uint8_t data_buffer[INPUT_DATA_LENGTH]; + pipes_t current_pipes; + pipes_init(¤t_pipes); + + uint64_t data_length = INPUT_DATA_LENGTH; + int ret = ckb_load_witness(data_buffer, &data_length, 0, 0, CKB_SOURCE_INPUT); + if (ret != CKB_SUCCESS) { + return ret; + } + mol_seg_t data_seg; + data_seg.ptr = data_buffer; + data_seg.size = data_length; + + if (MolReader_Data_verify(&data_seg, false) != MOL_OK) { + return ERROR_ENCODING; + } + + mol_seg_t spawns_seg = MolReader_Data_get_spawns(&data_seg); + uint64_t vm_index = 0; + if (argc != 0) { + // For spawned VMs, read current VM index and passed pipes from argv + if (argc != 2) { + return ERROR_ARGV; + } + + uint64_t decoded_length = 0; + ret = ee_decode_char_string_in_place(argv[0], &decoded_length); + if (ret != 0) { + return ret; + } + if (decoded_length != 8) { + return ERROR_ARGV; + } + vm_index = *((uint64_t *)argv[0]); + + int spawn_found = 0; + mol_seg_t spawn_seg; + for (mol_num_t i = 0; i < MolReader_Spawns_length(&spawns_seg); i++) { + mol_seg_res_t spawn_res = MolReader_Spawns_get(&spawns_seg, i); + if (spawn_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t child_seg = MolReader_Spawn_get_child(&spawn_res.seg); + uint64_t child_index = *((uint64_t *)child_seg.ptr); + if (child_index == vm_index) { + spawn_seg = spawn_res.seg; + spawn_found = 1; + break; + } + } + if (spawn_found == 0) { + return ERROR_ARGV; + } + mol_seg_t passed_pipes_seg = MolReader_Spawn_get_pipes(&spawn_seg); + + decoded_length = 0; + ret = ee_decode_char_string_in_place(argv[1], &decoded_length); + if (ret != 0) { + return ret; + } + if (decoded_length != MolReader_PipeIndices_length(&passed_pipes_seg) * 8) { + return ERROR_ARGV; + } + for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&passed_pipes_seg); + i++) { + mol_seg_res_t pipe_res = MolReader_PipeIndices_get(&passed_pipes_seg, i); + if (pipe_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + uint64_t pipe_index = *((uint64_t *)pipe_res.seg.ptr); + uint64_t pipe_id = *((uint64_t *)&argv[1][i * 8]); + + ckb_printf("Obtained pipe index %lu, id: %lu", pipe_index, pipe_id); + + ret = pipes_add(¤t_pipes, pipe_index, pipe_id); + if (ret != 0) { + return ret; + } + } + } + + // Create new pipes that should be created from current VM + mol_seg_t pipes_seg = MolReader_Data_get_pipes(&data_seg); + for (mol_num_t i = 0; i < MolReader_Pipes_length(&pipes_seg); i++) { + mol_seg_res_t pipe_pair_res = MolReader_Pipes_get(&pipes_seg, i); + if (pipe_pair_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t pipe_pair_seg = pipe_pair_res.seg; + + uint64_t pair_vm_index = + *((uint64_t *)MolReader_Pipe_get_vm(&pipe_pair_seg).ptr); + if (pair_vm_index == vm_index) { + uint64_t read_index = + *((uint64_t *)MolReader_Pipe_get_read_pipe(&pipe_pair_seg).ptr); + uint64_t write_index = + *((uint64_t *)MolReader_Pipe_get_write_pipe(&pipe_pair_seg).ptr); + + uint64_t fildes[2]; + ret = ckb_pipe(fildes); + if (ret != 0) { + return ret; + } + ret = pipes_add(¤t_pipes, read_index, fildes[0]); + if (ret != 0) { + return ret; + } + ret = pipes_add(¤t_pipes, write_index, fildes[1]); + if (ret != 0) { + return ret; + } + } + } + + uint64_t spawned_vms[MAX_SPAWNED_VMS]; + size_t spawned_count = 0; + + // Issue spawn syscalls for child VMs + for (mol_num_t i = 0; i < MolReader_Spawns_length(&spawns_seg); i++) { + mol_seg_res_t spawn_res = MolReader_Spawns_get(&spawns_seg, i); + if (spawn_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t spawn_seg = spawn_res.seg; + + uint64_t from_index = + *((uint64_t *)MolReader_Spawn_get_from(&spawn_seg).ptr); + if (from_index == vm_index) { + if (spawned_count >= MAX_SPAWNED_VMS) { + return ERROR_TOO_MANY_SPAWNS; + } + + uint64_t child_index = + *((uint64_t *)MolReader_Spawn_get_child(&spawn_seg).ptr); + + pipes_t passed_pipes; + pipes_init(&passed_pipes); + + mol_seg_t pipe_indices = MolReader_Spawn_get_pipes(&spawn_seg); + for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&pipe_indices); + i++) { + mol_seg_res_t index_res = MolReader_PipeIndices_get(&pipe_indices, i); + if (index_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t index_seg = index_res.seg; + uint64_t index = *((uint64_t *)index_seg.ptr); + + uint64_t id = 0; + ret = pipes_find(¤t_pipes, index, &id); + if (ret != 0) { + return ret; + } + + ckb_printf("Pass pipe index %lu, id %lu to VM %lu", index, id, + child_index); + + ret = pipes_add(&passed_pipes, index, id); + if (ret != 0) { + return ret; + } + } + + size_t src_len = 8; + size_t dst_len = ee_maximum_encoding_length(src_len); + uint8_t encoded_child_index[dst_len + 1]; + ret = ee_encode(encoded_child_index, &dst_len, + (const uint8_t *)&child_index, &src_len); + if (ret != 0) { + return ret; + } + encoded_child_index[dst_len] = '\0'; + + src_len = passed_pipes.used * 8; + dst_len = ee_maximum_encoding_length(src_len); + uint8_t encoded_ids[dst_len + 1]; + ret = ee_encode(encoded_ids, &dst_len, (const uint8_t *)passed_pipes.ids, + &src_len); + if (ret != 0) { + return ret; + } + encoded_ids[dst_len] = '\0'; + + const char *argv[2] = {(char *)encoded_child_index, (char *)encoded_ids}; + spawn_args_t sargs; + sargs.argc = 2; + sargs.argv = argv; + sargs.process_id = &spawned_vms[spawned_count++]; + sargs.inherited_fds = (const uint64_t *)passed_pipes.ids; + + ret = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &sargs); + if (ret != 0) { + return ret; + } + } + } + + // Process all reads & writes + mol_seg_t writes_seg = MolReader_Data_get_writes(&data_seg); + for (mol_num_t i = 0; i < MolReader_Writes_length(&writes_seg); i++) { + mol_seg_res_t write_res = MolReader_Writes_get(&writes_seg, i); + if (write_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t write_seg = write_res.seg; + + uint64_t from = *((uint64_t *)MolReader_Write_get_from(&write_seg).ptr); + uint64_t to = *((uint64_t *)MolReader_Write_get_to(&write_seg).ptr); + + if (from == vm_index) { + // Write data + uint64_t from_pipe = + *((uint64_t *)MolReader_Write_get_from_pipe(&write_seg).ptr); + mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); + + uint64_t pipe_id = 0; + ret = pipes_find(¤t_pipes, from_pipe, &pipe_id); + if (ret != 0) { + return ret; + } + + ckb_printf("Write %lu bytes to pipe index %lu, id %lu", data_seg.size, + from_pipe, pipe_id); + + uint32_t written = 0; + while (written < data_seg.size) { + size_t length = data_seg.size - written; + ret = ckb_write(pipe_id, &data_seg.ptr[written], &length); + if (ret != 0) { + return ret; + } + if (length == 0) { + return ERROR_PIPE_CLOSED; + } + written += length; + } + } else if (to == vm_index) { + // Read data + uint64_t to_pipe = + *((uint64_t *)MolReader_Write_get_to_pipe(&write_seg).ptr); + mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); + + uint64_t pipe_id = 0; + ret = pipes_find(¤t_pipes, to_pipe, &pipe_id); + if (ret != 0) { + return ret; + } + + ckb_printf("Read %lu bytes from pipe index %lu, id %lu", data_seg.size, + to_pipe, pipe_id); + + uint32_t read = 0; + while (read < data_seg.size) { + size_t length = data_seg.size - read; + uint8_t data[length]; + memset(data, 0, length); + ret = ckb_read(pipe_id, data, &length); + if (ret != 0) { + return ret; + } + if (length == 0) { + return ERROR_PIPE_CLOSED; + } + if (memcmp(&data_seg.ptr[read], data, length) != 0) { + return ERROR_CORRUPTED_DATA; + } + read += length; + } + } + } + + // Join all spawned VMs + for (size_t i = 0; i < spawned_count; i++) { + size_t j = spawned_count - i - 1; + int8_t exit_code = 0xFF; + ret = ckb_wait(spawned_vms[j], &exit_code); + if (ret != 0) { + return ret; + } + if (exit_code != 0) { + return exit_code; + } + } + + return 0; +} diff --git a/script/testdata/spawn_dag.h b/script/testdata/spawn_dag.h new file mode 100644 index 0000000000..b2f0ce12b9 --- /dev/null +++ b/script/testdata/spawn_dag.h @@ -0,0 +1,887 @@ +// Generated by Molecule 0.7.5 + +#define MOLECULEC_VERSION 7005 +#define MOLECULE_API_VERSION_MIN 7000 + +#include "molecule_reader.h" +#include "molecule_builder.h" + +#ifndef DAG_H +#define DAG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MOLECULE_API_DECORATOR +#define __DEFINE_MOLECULE_API_DECORATOR_DAG +#define MOLECULE_API_DECORATOR +#endif /* MOLECULE_API_DECORATOR */ + +/* + * Reader APIs + */ + +#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_PipeIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_PipeIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_PipeIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_PipeIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_PipeIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_PipeIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_PipeIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_PipeIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_PipeIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_PipeIndices_verify(s, c) mol_fixvec_verify(s, 8) +#define MolReader_PipeIndices_length(s) mol_fixvec_length(s) +#define MolReader_PipeIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) +#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_Bytes_length(s) mol_fixvec_length(s) +#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t*, bool); +#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) +#define MolReader_Pipe_get_read_pipe(s) mol_table_slice_by_index(s, 1) +#define MolReader_Pipe_get_write_pipe(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t*, bool); +#define MolReader_Pipes_length(s) mol_dynvec_length(s) +#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t*, bool); +#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) +#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Write_get_from_pipe(s) mol_table_slice_by_index(s, 1) +#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) +#define MolReader_Write_get_to_pipe(s) mol_table_slice_by_index(s, 3) +#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t*, bool); +#define MolReader_Writes_length(s) mol_dynvec_length(s) +#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t*, bool); +#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) +#define MolReader_Spawn_get_pipes(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t*, bool); +#define MolReader_Spawns_length(s) mol_dynvec_length(s) +#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t*, bool); +#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) +#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) +#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) + +/* + * Builder APIs + */ + +#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_PipeIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_PipeIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_PipeIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_PipeIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_PipeIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_PipeIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_PipeIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_PipeIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_PipeIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_PipeIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_PipeIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_PipeIndices_init(b) mol_fixvec_builder_initialize(b, 128) +#define MolBuilder_PipeIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) +#define MolBuilder_PipeIndices_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_PipeIndices_clear(b) mol_builder_discard(b) +#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Pipe_set_read_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Pipe_set_write_pipe(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t); +#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) +#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) +#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Write_set_from_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_Write_set_to_pipe(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t); +#define MolBuilder_Write_clear(b) mol_builder_discard(b) +#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Writes_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Spawn_set_pipes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t); +#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) +#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) +#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t); +#define MolBuilder_Data_clear(b) mol_builder_discard(b) + +/* + * Default Value + */ + +#define ____ 0x00 + +MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { + ____, ____, ____, ____, ____, ____, ____, ____, +}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndex[8] = { + ____, ____, ____, ____, ____, ____, ____, ____, +}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndices[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { + 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, +}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { + 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, + 0x28, ____, ____, ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { + 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { + 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, + 0x18, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, + 0x04, ____, ____, ____, +}; + +#undef ____ + +/* + * Reader Functions + */ + +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 3) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 3) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_Pipe_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_Pipe_verify(&inner, compatible); +} +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 5) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 5) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_Write_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_Write_verify(&inner, compatible); +} +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 3) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 3) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_PipeIndices_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_Spawn_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_Spawn_verify(&inner, compatible); +} +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 3) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 3) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Spawns_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Pipes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Writes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} + +/* + * Builder Functions + */ + +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 16; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 8 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 8 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_VmIndex, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_PipeIndex, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_PipeIndex, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 24; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[7]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[9]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[7]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[9]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_VmIndex, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_PipeIndex, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_VmIndex, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[7]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_PipeIndex, len); + } else { + mol_num_t of = builder.number_ptr[6]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[9]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Bytes, len); + } else { + mol_num_t of = builder.number_ptr[8]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 16; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_VmIndex, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_VmIndex, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_PipeIndices, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 16; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Spawns, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Pipes, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Writes, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} + +#ifdef __DEFINE_MOLECULE_API_DECORATOR_DAG +#undef MOLECULE_API_DECORATOR +#undef __DEFINE_MOLECULE_API_DECORATOR_DAG +#endif /* __DEFINE_MOLECULE_API_DECORATOR_DAG */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DAG_H */ diff --git a/script/testdata/spawn_dag.mol b/script/testdata/spawn_dag.mol new file mode 100644 index 0000000000..00b0193f97 --- /dev/null +++ b/script/testdata/spawn_dag.mol @@ -0,0 +1,34 @@ +array VmIndex [byte; 8]; +array PipeIndex [byte; 8]; + +vector PipeIndices ; +vector Bytes ; + +table Pipe { + vm: VmIndex, + read_pipe: PipeIndex, + write_pipe: PipeIndex, +} +vector Pipes ; + +table Write { + from: VmIndex, + from_pipe: PipeIndex, + to: VmIndex, + to_pipe: PipeIndex, + data: Bytes, +} +vector Writes ; + +table Spawn { + from: VmIndex, + child: VmIndex, + pipes: PipeIndices, +} +vector Spawns ; + +table Data { + spawns: Spawns, + pipes: Pipes, + writes: Writes, +} diff --git a/script/testdata/spawn_dag.rs b/script/testdata/spawn_dag.rs new file mode 100644 index 0000000000..cb9e52397b --- /dev/null +++ b/script/testdata/spawn_dag.rs @@ -0,0 +1,3261 @@ +// Generated by Molecule 0.7.5 + +use molecule::prelude::*; + +#[derive(Clone)] +pub struct VmIndex(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for VmIndex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for VmIndex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for VmIndex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for VmIndex { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + VmIndex::new_unchecked(v) + } +} +impl VmIndex { + const DEFAULT_VALUE: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn nth4(&self) -> Byte { + Byte::new_unchecked(self.0.slice(4..5)) + } + pub fn nth5(&self) -> Byte { + Byte::new_unchecked(self.0.slice(5..6)) + } + pub fn nth6(&self) -> Byte { + Byte::new_unchecked(self.0.slice(6..7)) + } + pub fn nth7(&self) -> Byte { + Byte::new_unchecked(self.0.slice(7..8)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> VmIndexReader<'r> { + VmIndexReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for VmIndex { + type Builder = VmIndexBuilder; + const NAME: &'static str = "VmIndex"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + VmIndex(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + VmIndexReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + VmIndexReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([ + self.nth0(), + self.nth1(), + self.nth2(), + self.nth3(), + self.nth4(), + self.nth5(), + self.nth6(), + self.nth7(), + ]) + } +} +#[derive(Clone, Copy)] +pub struct VmIndexReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for VmIndexReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for VmIndexReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for VmIndexReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> VmIndexReader<'r> { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn nth4(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[4..5]) + } + pub fn nth5(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[5..6]) + } + pub fn nth6(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[6..7]) + } + pub fn nth7(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[7..8]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for VmIndexReader<'r> { + type Entity = VmIndex; + const NAME: &'static str = "VmIndexReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + VmIndexReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct VmIndexBuilder(pub(crate) [Byte; 8]); +impl ::core::fmt::Debug for VmIndexBuilder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for VmIndexBuilder { + fn default() -> Self { + VmIndexBuilder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl VmIndexBuilder { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn set(mut self, v: [Byte; 8]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } + pub fn nth4(mut self, v: Byte) -> Self { + self.0[4] = v; + self + } + pub fn nth5(mut self, v: Byte) -> Self { + self.0[5] = v; + self + } + pub fn nth6(mut self, v: Byte) -> Self { + self.0[6] = v; + self + } + pub fn nth7(mut self, v: Byte) -> Self { + self.0[7] = v; + self + } +} +impl molecule::prelude::Builder for VmIndexBuilder { + type Entity = VmIndex; + const NAME: &'static str = "VmIndexBuilder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + writer.write_all(self.0[4].as_slice())?; + writer.write_all(self.0[5].as_slice())?; + writer.write_all(self.0[6].as_slice())?; + writer.write_all(self.0[7].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + VmIndex::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct PipeIndex(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for PipeIndex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for PipeIndex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for PipeIndex { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for PipeIndex { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + PipeIndex::new_unchecked(v) + } +} +impl PipeIndex { + const DEFAULT_VALUE: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn nth4(&self) -> Byte { + Byte::new_unchecked(self.0.slice(4..5)) + } + pub fn nth5(&self) -> Byte { + Byte::new_unchecked(self.0.slice(5..6)) + } + pub fn nth6(&self) -> Byte { + Byte::new_unchecked(self.0.slice(6..7)) + } + pub fn nth7(&self) -> Byte { + Byte::new_unchecked(self.0.slice(7..8)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> PipeIndexReader<'r> { + PipeIndexReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for PipeIndex { + type Builder = PipeIndexBuilder; + const NAME: &'static str = "PipeIndex"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + PipeIndex(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipeIndexReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipeIndexReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([ + self.nth0(), + self.nth1(), + self.nth2(), + self.nth3(), + self.nth4(), + self.nth5(), + self.nth6(), + self.nth7(), + ]) + } +} +#[derive(Clone, Copy)] +pub struct PipeIndexReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for PipeIndexReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for PipeIndexReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for PipeIndexReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> PipeIndexReader<'r> { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn nth4(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[4..5]) + } + pub fn nth5(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[5..6]) + } + pub fn nth6(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[6..7]) + } + pub fn nth7(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[7..8]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for PipeIndexReader<'r> { + type Entity = PipeIndex; + const NAME: &'static str = "PipeIndexReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + PipeIndexReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct PipeIndexBuilder(pub(crate) [Byte; 8]); +impl ::core::fmt::Debug for PipeIndexBuilder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for PipeIndexBuilder { + fn default() -> Self { + PipeIndexBuilder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl PipeIndexBuilder { + pub const TOTAL_SIZE: usize = 8; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 8; + pub fn set(mut self, v: [Byte; 8]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } + pub fn nth4(mut self, v: Byte) -> Self { + self.0[4] = v; + self + } + pub fn nth5(mut self, v: Byte) -> Self { + self.0[5] = v; + self + } + pub fn nth6(mut self, v: Byte) -> Self { + self.0[6] = v; + self + } + pub fn nth7(mut self, v: Byte) -> Self { + self.0[7] = v; + self + } +} +impl molecule::prelude::Builder for PipeIndexBuilder { + type Entity = PipeIndex; + const NAME: &'static str = "PipeIndexBuilder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + writer.write_all(self.0[4].as_slice())?; + writer.write_all(self.0[5].as_slice())?; + writer.write_all(self.0[6].as_slice())?; + writer.write_all(self.0[7].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + PipeIndex::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct PipeIndices(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for PipeIndices { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for PipeIndices { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for PipeIndices { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for PipeIndices { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + PipeIndices::new_unchecked(v) + } +} +impl PipeIndices { + const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; + pub const ITEM_SIZE: usize = 8; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> PipeIndex { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + PipeIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn as_reader<'r>(&'r self) -> PipeIndicesReader<'r> { + PipeIndicesReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for PipeIndices { + type Builder = PipeIndicesBuilder; + const NAME: &'static str = "PipeIndices"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + PipeIndices(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipeIndicesReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipeIndicesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct PipeIndicesReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for PipeIndicesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for PipeIndicesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for PipeIndicesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> PipeIndicesReader<'r> { + pub const ITEM_SIZE: usize = 8; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> PipeIndexReader<'r> { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + } +} +impl<'r> molecule::prelude::Reader<'r> for PipeIndicesReader<'r> { + type Entity = PipeIndices; + const NAME: &'static str = "PipeIndicesReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + PipeIndicesReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_count = molecule::unpack_number(slice) as usize; + if item_count == 0 { + if slice_len != molecule::NUMBER_SIZE { + return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); + } + return Ok(()); + } + let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct PipeIndicesBuilder(pub(crate) Vec); +impl PipeIndicesBuilder { + pub const ITEM_SIZE: usize = 8; + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: PipeIndex) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: PipeIndex) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for PipeIndicesBuilder { + type Entity = PipeIndices; + const NAME: &'static str = "PipeIndicesBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; + for inner in &self.0[..] { + writer.write_all(inner.as_slice())?; + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + PipeIndices::new_unchecked(inner.into()) + } +} +pub struct PipeIndicesIterator(PipeIndices, usize, usize); +impl ::core::iter::Iterator for PipeIndicesIterator { + type Item = PipeIndex; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for PipeIndicesIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for PipeIndices { + type Item = PipeIndex; + type IntoIter = PipeIndicesIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + PipeIndicesIterator(self, 0, len) + } +} +impl<'r> PipeIndicesReader<'r> { + pub fn iter<'t>(&'t self) -> PipeIndicesReaderIterator<'t, 'r> { + PipeIndicesReaderIterator(&self, 0, self.len()) + } +} +pub struct PipeIndicesReaderIterator<'t, 'r>(&'t PipeIndicesReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for PipeIndicesReaderIterator<'t, 'r> { + type Item = PipeIndexReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for PipeIndicesReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct Bytes(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Bytes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Bytes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Bytes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Bytes { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Bytes::new_unchecked(v) + } +} +impl Bytes { + const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; + pub const ITEM_SIZE: usize = 1; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Byte { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.0.slice(molecule::NUMBER_SIZE..) + } + pub fn as_reader<'r>(&'r self) -> BytesReader<'r> { + BytesReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Bytes { + type Builder = BytesBuilder; + const NAME: &'static str = "Bytes"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Bytes(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BytesReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BytesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct BytesReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BytesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BytesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> BytesReader<'r> { + pub const ITEM_SIZE: usize = 1; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> ByteReader<'r> { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn raw_data(&self) -> &'r [u8] { + &self.as_slice()[molecule::NUMBER_SIZE..] + } +} +impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { + type Entity = Bytes; + const NAME: &'static str = "BytesReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BytesReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_count = molecule::unpack_number(slice) as usize; + if item_count == 0 { + if slice_len != molecule::NUMBER_SIZE { + return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); + } + return Ok(()); + } + let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BytesBuilder(pub(crate) Vec); +impl BytesBuilder { + pub const ITEM_SIZE: usize = 1; + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Byte) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: Byte) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for BytesBuilder { + type Entity = Bytes; + const NAME: &'static str = "BytesBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; + for inner in &self.0[..] { + writer.write_all(inner.as_slice())?; + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Bytes::new_unchecked(inner.into()) + } +} +pub struct BytesIterator(Bytes, usize, usize); +impl ::core::iter::Iterator for BytesIterator { + type Item = Byte; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for BytesIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for Bytes { + type Item = Byte; + type IntoIter = BytesIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + BytesIterator(self, 0, len) + } +} +#[derive(Clone)] +pub struct Pipe(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Pipe { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Pipe { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Pipe { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "vm", self.vm())?; + write!(f, ", {}: {}", "read_pipe", self.read_pipe())?; + write!(f, ", {}: {}", "write_pipe", self.write_pipe())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Pipe { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Pipe::new_unchecked(v) + } +} +impl Pipe { + const DEFAULT_VALUE: [u8; 40] = [ + 40, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn vm(&self) -> VmIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + VmIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn read_pipe(&self) -> PipeIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + PipeIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn write_pipe(&self) -> PipeIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + PipeIndex::new_unchecked(self.0.slice(start..end)) + } else { + PipeIndex::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> PipeReader<'r> { + PipeReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Pipe { + type Builder = PipeBuilder; + const NAME: &'static str = "Pipe"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Pipe(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipeReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipeReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .vm(self.vm()) + .read_pipe(self.read_pipe()) + .write_pipe(self.write_pipe()) + } +} +#[derive(Clone, Copy)] +pub struct PipeReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for PipeReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for PipeReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for PipeReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "vm", self.vm())?; + write!(f, ", {}: {}", "read_pipe", self.read_pipe())?; + write!(f, ", {}: {}", "write_pipe", self.write_pipe())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> PipeReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn vm(&self) -> VmIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + VmIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn read_pipe(&self) -> PipeIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn write_pipe(&self) -> PipeIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + } else { + PipeIndexReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for PipeReader<'r> { + type Entity = Pipe; + const NAME: &'static str = "PipeReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + PipeReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + PipeIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + PipeIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct PipeBuilder { + pub(crate) vm: VmIndex, + pub(crate) read_pipe: PipeIndex, + pub(crate) write_pipe: PipeIndex, +} +impl PipeBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn vm(mut self, v: VmIndex) -> Self { + self.vm = v; + self + } + pub fn read_pipe(mut self, v: PipeIndex) -> Self { + self.read_pipe = v; + self + } + pub fn write_pipe(mut self, v: PipeIndex) -> Self { + self.write_pipe = v; + self + } +} +impl molecule::prelude::Builder for PipeBuilder { + type Entity = Pipe; + const NAME: &'static str = "PipeBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.vm.as_slice().len() + + self.read_pipe.as_slice().len() + + self.write_pipe.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.vm.as_slice().len(); + offsets.push(total_size); + total_size += self.read_pipe.as_slice().len(); + offsets.push(total_size); + total_size += self.write_pipe.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.vm.as_slice())?; + writer.write_all(self.read_pipe.as_slice())?; + writer.write_all(self.write_pipe.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Pipe::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Pipes(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Pipes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Pipes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Pipes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for Pipes { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Pipes::new_unchecked(v) + } +} +impl Pipes { + const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Pipe { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + Pipe::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + Pipe::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> PipesReader<'r> { + PipesReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Pipes { + type Builder = PipesBuilder; + const NAME: &'static str = "Pipes"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Pipes(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipesReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + PipesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct PipesReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for PipesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for PipesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for PipesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> PipesReader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> PipeReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + PipeReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + PipeReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for PipesReader<'r> { + type Entity = Pipes; + const NAME: &'static str = "PipesReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + PipesReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + PipeReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct PipesBuilder(pub(crate) Vec); +impl PipesBuilder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Pipe) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: Pipe) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for PipesBuilder { + type Entity = Pipes; + const NAME: &'static str = "PipesBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Pipes::new_unchecked(inner.into()) + } +} +pub struct PipesIterator(Pipes, usize, usize); +impl ::core::iter::Iterator for PipesIterator { + type Item = Pipe; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for PipesIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for Pipes { + type Item = Pipe; + type IntoIter = PipesIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + PipesIterator(self, 0, len) + } +} +impl<'r> PipesReader<'r> { + pub fn iter<'t>(&'t self) -> PipesReaderIterator<'t, 'r> { + PipesReaderIterator(&self, 0, self.len()) + } +} +pub struct PipesReaderIterator<'t, 'r>(&'t PipesReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for PipesReaderIterator<'t, 'r> { + type Item = PipeReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for PipesReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct Write(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Write { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Write { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Write { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "from", self.from())?; + write!(f, ", {}: {}", "from_pipe", self.from_pipe())?; + write!(f, ", {}: {}", "to", self.to())?; + write!(f, ", {}: {}", "to_pipe", self.to_pipe())?; + write!(f, ", {}: {}", "data", self.data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Write { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Write::new_unchecked(v) + } +} +impl Write { + const DEFAULT_VALUE: [u8; 60] = [ + 60, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 48, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]; + pub const FIELD_COUNT: usize = 5; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn from(&self) -> VmIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + VmIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn from_pipe(&self) -> PipeIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + PipeIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn to(&self) -> VmIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + VmIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn to_pipe(&self) -> PipeIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + PipeIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[24..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> WriteReader<'r> { + WriteReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Write { + type Builder = WriteBuilder; + const NAME: &'static str = "Write"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Write(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + WriteReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + WriteReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .from(self.from()) + .from_pipe(self.from_pipe()) + .to(self.to()) + .to_pipe(self.to_pipe()) + .data(self.data()) + } +} +#[derive(Clone, Copy)] +pub struct WriteReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for WriteReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for WriteReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for WriteReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "from", self.from())?; + write!(f, ", {}: {}", "from_pipe", self.from_pipe())?; + write!(f, ", {}: {}", "to", self.to())?; + write!(f, ", {}: {}", "to_pipe", self.to_pipe())?; + write!(f, ", {}: {}", "data", self.data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> WriteReader<'r> { + pub const FIELD_COUNT: usize = 5; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn from(&self) -> VmIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + VmIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn from_pipe(&self) -> PipeIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn to(&self) -> VmIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + VmIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn to_pipe(&self) -> PipeIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[24..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for WriteReader<'r> { + type Entity = Write; + const NAME: &'static str = "WriteReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + WriteReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + PipeIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + VmIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + PipeIndexReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct WriteBuilder { + pub(crate) from: VmIndex, + pub(crate) from_pipe: PipeIndex, + pub(crate) to: VmIndex, + pub(crate) to_pipe: PipeIndex, + pub(crate) data: Bytes, +} +impl WriteBuilder { + pub const FIELD_COUNT: usize = 5; + pub fn from(mut self, v: VmIndex) -> Self { + self.from = v; + self + } + pub fn from_pipe(mut self, v: PipeIndex) -> Self { + self.from_pipe = v; + self + } + pub fn to(mut self, v: VmIndex) -> Self { + self.to = v; + self + } + pub fn to_pipe(mut self, v: PipeIndex) -> Self { + self.to_pipe = v; + self + } + pub fn data(mut self, v: Bytes) -> Self { + self.data = v; + self + } +} +impl molecule::prelude::Builder for WriteBuilder { + type Entity = Write; + const NAME: &'static str = "WriteBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.from.as_slice().len() + + self.from_pipe.as_slice().len() + + self.to.as_slice().len() + + self.to_pipe.as_slice().len() + + self.data.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.from.as_slice().len(); + offsets.push(total_size); + total_size += self.from_pipe.as_slice().len(); + offsets.push(total_size); + total_size += self.to.as_slice().len(); + offsets.push(total_size); + total_size += self.to_pipe.as_slice().len(); + offsets.push(total_size); + total_size += self.data.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.from.as_slice())?; + writer.write_all(self.from_pipe.as_slice())?; + writer.write_all(self.to.as_slice())?; + writer.write_all(self.to_pipe.as_slice())?; + writer.write_all(self.data.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Write::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Writes(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Writes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Writes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Writes { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for Writes { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Writes::new_unchecked(v) + } +} +impl Writes { + const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Write { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + Write::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + Write::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> WritesReader<'r> { + WritesReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Writes { + type Builder = WritesBuilder; + const NAME: &'static str = "Writes"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Writes(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + WritesReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + WritesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct WritesReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for WritesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for WritesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for WritesReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> WritesReader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> WriteReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + WriteReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + WriteReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for WritesReader<'r> { + type Entity = Writes; + const NAME: &'static str = "WritesReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + WritesReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + WriteReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct WritesBuilder(pub(crate) Vec); +impl WritesBuilder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Write) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: Write) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for WritesBuilder { + type Entity = Writes; + const NAME: &'static str = "WritesBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Writes::new_unchecked(inner.into()) + } +} +pub struct WritesIterator(Writes, usize, usize); +impl ::core::iter::Iterator for WritesIterator { + type Item = Write; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for WritesIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for Writes { + type Item = Write; + type IntoIter = WritesIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + WritesIterator(self, 0, len) + } +} +impl<'r> WritesReader<'r> { + pub fn iter<'t>(&'t self) -> WritesReaderIterator<'t, 'r> { + WritesReaderIterator(&self, 0, self.len()) + } +} +pub struct WritesReaderIterator<'t, 'r>(&'t WritesReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for WritesReaderIterator<'t, 'r> { + type Item = WriteReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for WritesReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct Spawn(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Spawn { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Spawn { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Spawn { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "from", self.from())?; + write!(f, ", {}: {}", "child", self.child())?; + write!(f, ", {}: {}", "pipes", self.pipes())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Spawn { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Spawn::new_unchecked(v) + } +} +impl Spawn { + const DEFAULT_VALUE: [u8; 36] = [ + 36, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn from(&self) -> VmIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + VmIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn child(&self) -> VmIndex { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + VmIndex::new_unchecked(self.0.slice(start..end)) + } + pub fn pipes(&self) -> PipeIndices { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + PipeIndices::new_unchecked(self.0.slice(start..end)) + } else { + PipeIndices::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> SpawnReader<'r> { + SpawnReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Spawn { + type Builder = SpawnBuilder; + const NAME: &'static str = "Spawn"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Spawn(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SpawnReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SpawnReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .from(self.from()) + .child(self.child()) + .pipes(self.pipes()) + } +} +#[derive(Clone, Copy)] +pub struct SpawnReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for SpawnReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for SpawnReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for SpawnReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "from", self.from())?; + write!(f, ", {}: {}", "child", self.child())?; + write!(f, ", {}: {}", "pipes", self.pipes())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> SpawnReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn from(&self) -> VmIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + VmIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn child(&self) -> VmIndexReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + VmIndexReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn pipes(&self) -> PipeIndicesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + PipeIndicesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + PipeIndicesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for SpawnReader<'r> { + type Entity = Spawn; + const NAME: &'static str = "SpawnReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + SpawnReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + VmIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + PipeIndicesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct SpawnBuilder { + pub(crate) from: VmIndex, + pub(crate) child: VmIndex, + pub(crate) pipes: PipeIndices, +} +impl SpawnBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn from(mut self, v: VmIndex) -> Self { + self.from = v; + self + } + pub fn child(mut self, v: VmIndex) -> Self { + self.child = v; + self + } + pub fn pipes(mut self, v: PipeIndices) -> Self { + self.pipes = v; + self + } +} +impl molecule::prelude::Builder for SpawnBuilder { + type Entity = Spawn; + const NAME: &'static str = "SpawnBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.from.as_slice().len() + + self.child.as_slice().len() + + self.pipes.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.from.as_slice().len(); + offsets.push(total_size); + total_size += self.child.as_slice().len(); + offsets.push(total_size); + total_size += self.pipes.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.from.as_slice())?; + writer.write_all(self.child.as_slice())?; + writer.write_all(self.pipes.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Spawn::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Spawns(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Spawns { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Spawns { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Spawns { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for Spawns { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Spawns::new_unchecked(v) + } +} +impl Spawns { + const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Spawn { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + Spawn::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + Spawn::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> SpawnsReader<'r> { + SpawnsReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Spawns { + type Builder = SpawnsBuilder; + const NAME: &'static str = "Spawns"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Spawns(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SpawnsReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SpawnsReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct SpawnsReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for SpawnsReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for SpawnsReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for SpawnsReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> SpawnsReader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> SpawnReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + SpawnReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + SpawnReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for SpawnsReader<'r> { + type Entity = Spawns; + const NAME: &'static str = "SpawnsReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + SpawnsReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + SpawnReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct SpawnsBuilder(pub(crate) Vec); +impl SpawnsBuilder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Spawn) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: Spawn) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for SpawnsBuilder { + type Entity = Spawns; + const NAME: &'static str = "SpawnsBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Spawns::new_unchecked(inner.into()) + } +} +pub struct SpawnsIterator(Spawns, usize, usize); +impl ::core::iter::Iterator for SpawnsIterator { + type Item = Spawn; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for SpawnsIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for Spawns { + type Item = Spawn; + type IntoIter = SpawnsIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + SpawnsIterator(self, 0, len) + } +} +impl<'r> SpawnsReader<'r> { + pub fn iter<'t>(&'t self) -> SpawnsReaderIterator<'t, 'r> { + SpawnsReaderIterator(&self, 0, self.len()) + } +} +pub struct SpawnsReaderIterator<'t, 'r>(&'t SpawnsReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for SpawnsReaderIterator<'t, 'r> { + type Item = SpawnReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for SpawnsReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct Data(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Data { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Data { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Data { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spawns", self.spawns())?; + write!(f, ", {}: {}", "pipes", self.pipes())?; + write!(f, ", {}: {}", "writes", self.writes())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Data { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Data::new_unchecked(v) + } +} +impl Data { + const DEFAULT_VALUE: [u8; 28] = [ + 28, 0, 0, 0, 16, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spawns(&self) -> Spawns { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Spawns::new_unchecked(self.0.slice(start..end)) + } + pub fn pipes(&self) -> Pipes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Pipes::new_unchecked(self.0.slice(start..end)) + } + pub fn writes(&self) -> Writes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Writes::new_unchecked(self.0.slice(start..end)) + } else { + Writes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> DataReader<'r> { + DataReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Data { + type Builder = DataBuilder; + const NAME: &'static str = "Data"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Data(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + DataReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + DataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .spawns(self.spawns()) + .pipes(self.pipes()) + .writes(self.writes()) + } +} +#[derive(Clone, Copy)] +pub struct DataReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for DataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for DataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for DataReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "spawns", self.spawns())?; + write!(f, ", {}: {}", "pipes", self.pipes())?; + write!(f, ", {}: {}", "writes", self.writes())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> DataReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn spawns(&self) -> SpawnsReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + SpawnsReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn pipes(&self) -> PipesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + PipesReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn writes(&self) -> WritesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + WritesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + WritesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for DataReader<'r> { + type Entity = Data; + const NAME: &'static str = "DataReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + DataReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + SpawnsReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + PipesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + WritesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct DataBuilder { + pub(crate) spawns: Spawns, + pub(crate) pipes: Pipes, + pub(crate) writes: Writes, +} +impl DataBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn spawns(mut self, v: Spawns) -> Self { + self.spawns = v; + self + } + pub fn pipes(mut self, v: Pipes) -> Self { + self.pipes = v; + self + } + pub fn writes(mut self, v: Writes) -> Self { + self.writes = v; + self + } +} +impl molecule::prelude::Builder for DataBuilder { + type Entity = Data; + const NAME: &'static str = "DataBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.spawns.as_slice().len() + + self.pipes.as_slice().len() + + self.writes.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.spawns.as_slice().len(); + offsets.push(total_size); + total_size += self.pipes.as_slice().len(); + offsets.push(total_size); + total_size += self.writes.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.spawns.as_slice())?; + writer.write_all(self.pipes.as_slice())?; + writer.write_all(self.writes.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Data::new_unchecked(inner.into()) + } +} diff --git a/script/testdata/spawn_dag_escape_encoding.h b/script/testdata/spawn_dag_escape_encoding.h new file mode 100644 index 0000000000..6183ca0c10 --- /dev/null +++ b/script/testdata/spawn_dag_escape_encoding.h @@ -0,0 +1,82 @@ +#ifndef ESCAPE_ENCODING_H_ +#define ESCAPE_ENCODING_H_ + +#include +#include + +#ifndef ESCAPE_ERROR_ENCODING +#define ESCAPE_ERROR_ENCODING 1 +#endif /* ESCAPE_ERROR_ENCODING */ + +size_t ee_maximum_encoding_length(size_t length) { return length * 2; } + +int ee_decode(uint8_t *dst, size_t *dst_length, const uint8_t *src, + size_t *src_length) { + size_t ds = 0; + size_t dl = *dst_length; + size_t ss = 0; + size_t sl = *src_length; + + while ((ss < sl) && (ds < dl)) { + if (src[ss] == 0xFE) { + if (ss + 1 >= sl) { + return ESCAPE_ERROR_ENCODING; + } + dst[ds++] = src[ss + 1] + 1; + ss += 2; + } else { + dst[ds++] = src[ss++]; + } + } + + *dst_length = ds; + *src_length = ss; + return 0; +} + +int ee_decode_char_string_in_place(char *buf, size_t *length) { + size_t ss = 0; + size_t ds = 0; + + while (buf[ss] != '\0') { + if (((uint8_t)buf[ss]) == 0xFE) { + if (buf[ss + 1] == '\0') { + return ESCAPE_ERROR_ENCODING; + } + buf[ds++] = buf[ss + 1] + 1; + ss += 2; + } else { + buf[ds++] = buf[ss++]; + } + } + + *length = ds; + return 0; +} + +int ee_encode(uint8_t *dst, size_t *dst_length, const uint8_t *src, + size_t *src_length) { + size_t ds = 0; + size_t dl = *dst_length; + size_t ss = 0; + size_t sl = *src_length; + + while ((ss < sl) && (ds < dl)) { + if ((src[ss] == 0x0) || (src[ss] == 0xFE)) { + if (ds + 1 >= dl) { + break; + } + dst[ds] = 0xFE; + dst[ds + 1] = src[ss++] - 1; + ds += 2; + } else { + dst[ds++] = src[ss++]; + } + } + + *dst_length = ds; + *src_length = ss; + return 0; +} + +#endif /* ESCAPE_ENCODING_H_ */ From 6a7c0b6a2ca18208784739eb390a37fbe9fc1889 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 4 Apr 2024 10:29:15 +0800 Subject: [PATCH 052/135] Clean codes --- script/src/scheduler.rs | 1 - .../tests/ckb_latest/features_since_v2023.rs | 68 +------------------ 2 files changed, 3 insertions(+), 66 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index f078be7eb4..cd637fe8a1 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -307,7 +307,6 @@ where for message in messages { match message { Message::Spawn(vm_id, args) => { - println!("message:spawn {:?}", vm_id); // All pipes must belong to the correct owner let mut pipes_valid = true; for pipe in &args.pipes { 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 69b2165354..145a345bef 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -869,15 +869,14 @@ fn check_spawn_configurable() { check_spawn_configurable_once(SpawnFrom::Slice(1, 1)); } - #[allow(dead_code)] #[path = "../../../../testdata/spawn_dag.rs"] mod spawn_dag; use molecule::prelude::Byte; use spawn_dag as dag; // use spawn_dag::*; -use daggy::{Dag, Walker}; use ckb_types::bytes::Bytes; +use daggy::{Dag, Walker}; use rand::{rngs::StdRng, Rng, SeedableRng}; use std::collections::{HashSet, VecDeque}; // use ckb_types::core::DepType; @@ -1141,53 +1140,10 @@ fn build_pipe_index(val: u64) -> dag::PipeIndex { dag::PipeIndexBuilder::default().set(data).build() } -// fn random_out_point(rng: &mut R) -> OutPoint { -// let tx_hash = { -// let mut buf = [0u8; 32]; -// rng.fill(&mut buf); -// buf.pack() -// }; -// OutPoint::new(tx_hash, 0) -// } - -// pub fn random_script(rng: &mut R, t: ScriptHashType) -> Script { -// let code_hash = { -// let mut buf = [0u8; 32]; -// rng.fill(&mut buf[..]); -// buf.pack() -// }; -// let args = { -// let len = rng.gen_range(1..101); -// let mut buf = vec![0u8; len]; -// rng.fill(&mut buf[..]); -// buf.pack() -// }; -// Script::new_builder() -// .code_hash(code_hash) -// .hash_type(t.into()) -// .args(args) -// .build() -// } - -pub fn build_mock_tx(_seed: u64, program: Bytes, data: dag::Data) -> ResolvedTransaction { +pub fn build_mock_tx(program: Bytes, data: dag::Data) -> ResolvedTransaction { let script_version = SCRIPT_VERSION; - // let mut rng = StdRng::seed_from_u64(seed); let (code_dep, code_dep_hash) = load_cell_from_slice(&program[..]); - - // let code_type_script = random_script(&mut rng, ScriptHashType::Type); - // let code_dep = MockCellDep { - // cell_dep: CellDep::new_builder() - // .out_point(random_out_point(&mut rng)) - // .dep_type(DepType::Code.into()) - // .build(), - // output: CellOutput::new_builder() - // .type_(Some(code_type_script.clone()).pack()) - // .build(), - // data: program, - // header: None, - // }; - let spawn_caller_script = Script::new_builder() .hash_type(script_version.data_hash_type().into()) .code_hash(code_dep_hash) @@ -1198,26 +1154,9 @@ pub fn build_mock_tx(_seed: u64, program: Bytes, data: dag::Data) -> ResolvedTra .build(); let dummy_cell = create_dummy_cell(output); - // let input_lock_script = Script::new_builder() - // .code_hash(code_type_script.calc_script_hash()) - // .hash_type(ScriptHashType::Type.into()) - // .build(); - // let input_cell = MockInput { - // input: CellInput::new_builder() - // .previous_output(random_out_point(&mut rng)) - // .build(), - // output: CellOutput::new_builder().lock(input_lock_script).build(), - // data: Bytes::default(), - // header: None, - // }; - let tx = TransactionBuilder::default() - // .cell_dep(code_dep.cell_dep.clone()) - // .input(input_cell.input.clone()) - // .output(CellOutput::new_builder().build()) .witness(data.as_bytes().pack()) .build(); - ResolvedTransaction { transaction: tx, resolved_cell_deps: vec![code_dep], @@ -1237,10 +1176,9 @@ fn test_single_dag() { let data = generate_data_graph(seed, spawns, writes, 3).unwrap(); let program = std::fs::read("./testdata/spawn_dag").unwrap().into(); - let rtx = build_mock_tx(seed.wrapping_add(10), program, data); + let rtx = build_mock_tx(program, data); let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - println!("{:?}", result); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); } From 70ccc7f92b80f966fd996e894c485b9e123f9c7d Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 4 Apr 2024 11:45:52 +0800 Subject: [PATCH 053/135] Update cargo.lock --- Cargo.lock | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index e43f69ace3..f53634f3f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1481,7 +1481,9 @@ dependencies = [ "ckb-traits", "ckb-types", "ckb-vm", + "daggy", "faster-hex", + "molecule", "proptest", "rand 0.8.5", "serde", @@ -2125,6 +2127,15 @@ dependencies = [ "libc", ] +[[package]] +name = "daggy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91a9304e55e9d601a39ae4deaba85406d5c0980e106f65afcf0460e9af1e7602" +dependencies = [ + "petgraph", +] + [[package]] name = "darling" version = "0.20.8" From d511fd7e6708c1432104265d36c329e4cb5224d9 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 4 Apr 2024 18:38:34 +0800 Subject: [PATCH 054/135] Add missing ensure_vms_instantiated --- script/src/scheduler.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index cd637fe8a1..92a01f5d15 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -561,6 +561,7 @@ where for vm_id in closed_pipes { match self.states[&vm_id].clone() { VmState::WaitForRead { length_addr, .. } => { + self.ensure_vms_instantiated(&[vm_id])?; let (_, read_machine) = self.instantiated.get_mut(&vm_id).unwrap(); read_machine .machine @@ -574,6 +575,7 @@ where length_addr, .. } => { + self.ensure_vms_instantiated(&[vm_id])?; let (_, write_machine) = self.instantiated.get_mut(&vm_id).unwrap(); write_machine .machine From 8f9b967cd3f2a56ca8492dba7eb1a0ed82ffb154 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 5 Apr 2024 11:57:04 +0800 Subject: [PATCH 055/135] clang fmt --- script/testdata/spawn_configurable_caller.c | 6 +- script/testdata/spawn_dag.c | 542 +++++++++-------- script/testdata/spawn_dag.h | 610 ++++++++++---------- script/testdata/spawn_dag_escape_encoding.h | 104 ++-- 4 files changed, 620 insertions(+), 642 deletions(-) diff --git a/script/testdata/spawn_configurable_caller.c b/script/testdata/spawn_configurable_caller.c index 72217e8b2c..02faeb203e 100644 --- a/script/testdata/spawn_configurable_caller.c +++ b/script/testdata/spawn_configurable_caller.c @@ -4,9 +4,7 @@ #include "ckb_syscalls.h" #include "spawn_utils.h" -uint64_t read_u64_le(const uint8_t* src) { - return *(const uint64_t*)src; -} +uint64_t read_u64_le(const uint8_t* src) { return *(const uint64_t*)src; } int main() { int err = 0; @@ -26,7 +24,7 @@ int main() { printf("args.place = %llu", args_place); printf("args.bounds = %llu", args_bounds); - const char *argv[] = {}; + const char* argv[] = {}; uint64_t pid = 0; uint64_t fds[2] = {0}; uint64_t inherited_fds[3] = {0}; diff --git a/script/testdata/spawn_dag.c b/script/testdata/spawn_dag.c index bc2722ae69..b3fb068d08 100644 --- a/script/testdata/spawn_dag.c +++ b/script/testdata/spawn_dag.c @@ -20,321 +20,307 @@ #define ERROR_CORRUPTED_DATA (_BASE_ERROR_CODE + 7) typedef struct { - uint64_t indices[MAX_PIPE_COUNT]; - uint64_t ids[MAX_PIPE_COUNT + 1]; - size_t used; + uint64_t indices[MAX_PIPE_COUNT]; + uint64_t ids[MAX_PIPE_COUNT + 1]; + size_t used; } pipes_t; void pipes_init(pipes_t *pipes) { - pipes->used = 0; - pipes->ids[pipes->used] = 0; + pipes->used = 0; + pipes->ids[pipes->used] = 0; } int pipes_add(pipes_t *pipes, uint64_t index, uint64_t id) { - if (pipes->used >= MAX_PIPE_COUNT) { - return ERROR_NO_SPACE_FOR_PIPES; - } - pipes->indices[pipes->used] = index; - pipes->ids[pipes->used] = id; - pipes->used++; - pipes->ids[pipes->used] = 0; - return CKB_SUCCESS; + if (pipes->used >= MAX_PIPE_COUNT) { + return ERROR_NO_SPACE_FOR_PIPES; + } + pipes->indices[pipes->used] = index; + pipes->ids[pipes->used] = id; + pipes->used++; + pipes->ids[pipes->used] = 0; + return CKB_SUCCESS; } int pipes_find(const pipes_t *pipes, uint64_t index, uint64_t *id) { - for (size_t i = 0; i < pipes->used; i++) { - if (pipes->indices[i] == index) { - *id = pipes->ids[i]; - return CKB_SUCCESS; + for (size_t i = 0; i < pipes->used; i++) { + if (pipes->indices[i] == index) { + *id = pipes->ids[i]; + return CKB_SUCCESS; + } } - } - return ERROR_NOT_FOUND; + return ERROR_NOT_FOUND; } int main(int argc, char *argv[]) { - uint8_t data_buffer[INPUT_DATA_LENGTH]; - pipes_t current_pipes; - pipes_init(¤t_pipes); - - uint64_t data_length = INPUT_DATA_LENGTH; - int ret = ckb_load_witness(data_buffer, &data_length, 0, 0, CKB_SOURCE_INPUT); - if (ret != CKB_SUCCESS) { - return ret; - } - mol_seg_t data_seg; - data_seg.ptr = data_buffer; - data_seg.size = data_length; - - if (MolReader_Data_verify(&data_seg, false) != MOL_OK) { - return ERROR_ENCODING; - } - - mol_seg_t spawns_seg = MolReader_Data_get_spawns(&data_seg); - uint64_t vm_index = 0; - if (argc != 0) { - // For spawned VMs, read current VM index and passed pipes from argv - if (argc != 2) { - return ERROR_ARGV; - } - - uint64_t decoded_length = 0; - ret = ee_decode_char_string_in_place(argv[0], &decoded_length); - if (ret != 0) { - return ret; - } - if (decoded_length != 8) { - return ERROR_ARGV; - } - vm_index = *((uint64_t *)argv[0]); + uint8_t data_buffer[INPUT_DATA_LENGTH]; + pipes_t current_pipes; + pipes_init(¤t_pipes); - int spawn_found = 0; - mol_seg_t spawn_seg; - for (mol_num_t i = 0; i < MolReader_Spawns_length(&spawns_seg); i++) { - mol_seg_res_t spawn_res = MolReader_Spawns_get(&spawns_seg, i); - if (spawn_res.errno != MOL_OK) { - return ERROR_ENCODING; - } - mol_seg_t child_seg = MolReader_Spawn_get_child(&spawn_res.seg); - uint64_t child_index = *((uint64_t *)child_seg.ptr); - if (child_index == vm_index) { - spawn_seg = spawn_res.seg; - spawn_found = 1; - break; - } - } - if (spawn_found == 0) { - return ERROR_ARGV; + uint64_t data_length = INPUT_DATA_LENGTH; + int ret = ckb_load_witness(data_buffer, &data_length, 0, 0, CKB_SOURCE_INPUT); + if (ret != CKB_SUCCESS) { + return ret; } - mol_seg_t passed_pipes_seg = MolReader_Spawn_get_pipes(&spawn_seg); + mol_seg_t data_seg; + data_seg.ptr = data_buffer; + data_seg.size = data_length; - decoded_length = 0; - ret = ee_decode_char_string_in_place(argv[1], &decoded_length); - if (ret != 0) { - return ret; - } - if (decoded_length != MolReader_PipeIndices_length(&passed_pipes_seg) * 8) { - return ERROR_ARGV; - } - for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&passed_pipes_seg); - i++) { - mol_seg_res_t pipe_res = MolReader_PipeIndices_get(&passed_pipes_seg, i); - if (pipe_res.errno != MOL_OK) { + if (MolReader_Data_verify(&data_seg, false) != MOL_OK) { return ERROR_ENCODING; - } - uint64_t pipe_index = *((uint64_t *)pipe_res.seg.ptr); - uint64_t pipe_id = *((uint64_t *)&argv[1][i * 8]); - - ckb_printf("Obtained pipe index %lu, id: %lu", pipe_index, pipe_id); - - ret = pipes_add(¤t_pipes, pipe_index, pipe_id); - if (ret != 0) { - return ret; - } - } - } - - // Create new pipes that should be created from current VM - mol_seg_t pipes_seg = MolReader_Data_get_pipes(&data_seg); - for (mol_num_t i = 0; i < MolReader_Pipes_length(&pipes_seg); i++) { - mol_seg_res_t pipe_pair_res = MolReader_Pipes_get(&pipes_seg, i); - if (pipe_pair_res.errno != MOL_OK) { - return ERROR_ENCODING; - } - mol_seg_t pipe_pair_seg = pipe_pair_res.seg; - - uint64_t pair_vm_index = - *((uint64_t *)MolReader_Pipe_get_vm(&pipe_pair_seg).ptr); - if (pair_vm_index == vm_index) { - uint64_t read_index = - *((uint64_t *)MolReader_Pipe_get_read_pipe(&pipe_pair_seg).ptr); - uint64_t write_index = - *((uint64_t *)MolReader_Pipe_get_write_pipe(&pipe_pair_seg).ptr); - - uint64_t fildes[2]; - ret = ckb_pipe(fildes); - if (ret != 0) { - return ret; - } - ret = pipes_add(¤t_pipes, read_index, fildes[0]); - if (ret != 0) { - return ret; - } - ret = pipes_add(¤t_pipes, write_index, fildes[1]); - if (ret != 0) { - return ret; - } } - } - - uint64_t spawned_vms[MAX_SPAWNED_VMS]; - size_t spawned_count = 0; - // Issue spawn syscalls for child VMs - for (mol_num_t i = 0; i < MolReader_Spawns_length(&spawns_seg); i++) { - mol_seg_res_t spawn_res = MolReader_Spawns_get(&spawns_seg, i); - if (spawn_res.errno != MOL_OK) { - return ERROR_ENCODING; - } - mol_seg_t spawn_seg = spawn_res.seg; - - uint64_t from_index = - *((uint64_t *)MolReader_Spawn_get_from(&spawn_seg).ptr); - if (from_index == vm_index) { - if (spawned_count >= MAX_SPAWNED_VMS) { - return ERROR_TOO_MANY_SPAWNS; - } - - uint64_t child_index = - *((uint64_t *)MolReader_Spawn_get_child(&spawn_seg).ptr); - - pipes_t passed_pipes; - pipes_init(&passed_pipes); - - mol_seg_t pipe_indices = MolReader_Spawn_get_pipes(&spawn_seg); - for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&pipe_indices); - i++) { - mol_seg_res_t index_res = MolReader_PipeIndices_get(&pipe_indices, i); - if (index_res.errno != MOL_OK) { - return ERROR_ENCODING; + mol_seg_t spawns_seg = MolReader_Data_get_spawns(&data_seg); + uint64_t vm_index = 0; + if (argc != 0) { + // For spawned VMs, read current VM index and passed pipes from argv + if (argc != 2) { + return ERROR_ARGV; } - mol_seg_t index_seg = index_res.seg; - uint64_t index = *((uint64_t *)index_seg.ptr); - uint64_t id = 0; - ret = pipes_find(¤t_pipes, index, &id); + uint64_t decoded_length = 0; + ret = ee_decode_char_string_in_place(argv[0], &decoded_length); if (ret != 0) { - return ret; + return ret; } + if (decoded_length != 8) { + return ERROR_ARGV; + } + vm_index = *((uint64_t *)argv[0]); + + int spawn_found = 0; + mol_seg_t spawn_seg; + for (mol_num_t i = 0; i < MolReader_Spawns_length(&spawns_seg); i++) { + mol_seg_res_t spawn_res = MolReader_Spawns_get(&spawns_seg, i); + if (spawn_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t child_seg = MolReader_Spawn_get_child(&spawn_res.seg); + uint64_t child_index = *((uint64_t *)child_seg.ptr); + if (child_index == vm_index) { + spawn_seg = spawn_res.seg; + spawn_found = 1; + break; + } + } + if (spawn_found == 0) { + return ERROR_ARGV; + } + mol_seg_t passed_pipes_seg = MolReader_Spawn_get_pipes(&spawn_seg); - ckb_printf("Pass pipe index %lu, id %lu to VM %lu", index, id, - child_index); - - ret = pipes_add(&passed_pipes, index, id); + decoded_length = 0; + ret = ee_decode_char_string_in_place(argv[1], &decoded_length); if (ret != 0) { - return ret; + return ret; + } + if (decoded_length != MolReader_PipeIndices_length(&passed_pipes_seg) * 8) { + return ERROR_ARGV; + } + for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&passed_pipes_seg); i++) { + mol_seg_res_t pipe_res = MolReader_PipeIndices_get(&passed_pipes_seg, i); + if (pipe_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + uint64_t pipe_index = *((uint64_t *)pipe_res.seg.ptr); + uint64_t pipe_id = *((uint64_t *)&argv[1][i * 8]); + + ckb_printf("Obtained pipe index %lu, id: %lu", pipe_index, pipe_id); + + ret = pipes_add(¤t_pipes, pipe_index, pipe_id); + if (ret != 0) { + return ret; + } } - } - - size_t src_len = 8; - size_t dst_len = ee_maximum_encoding_length(src_len); - uint8_t encoded_child_index[dst_len + 1]; - ret = ee_encode(encoded_child_index, &dst_len, - (const uint8_t *)&child_index, &src_len); - if (ret != 0) { - return ret; - } - encoded_child_index[dst_len] = '\0'; - - src_len = passed_pipes.used * 8; - dst_len = ee_maximum_encoding_length(src_len); - uint8_t encoded_ids[dst_len + 1]; - ret = ee_encode(encoded_ids, &dst_len, (const uint8_t *)passed_pipes.ids, - &src_len); - if (ret != 0) { - return ret; - } - encoded_ids[dst_len] = '\0'; - - const char *argv[2] = {(char *)encoded_child_index, (char *)encoded_ids}; - spawn_args_t sargs; - sargs.argc = 2; - sargs.argv = argv; - sargs.process_id = &spawned_vms[spawned_count++]; - sargs.inherited_fds = (const uint64_t *)passed_pipes.ids; - - ret = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &sargs); - if (ret != 0) { - return ret; - } - } - } - - // Process all reads & writes - mol_seg_t writes_seg = MolReader_Data_get_writes(&data_seg); - for (mol_num_t i = 0; i < MolReader_Writes_length(&writes_seg); i++) { - mol_seg_res_t write_res = MolReader_Writes_get(&writes_seg, i); - if (write_res.errno != MOL_OK) { - return ERROR_ENCODING; } - mol_seg_t write_seg = write_res.seg; - - uint64_t from = *((uint64_t *)MolReader_Write_get_from(&write_seg).ptr); - uint64_t to = *((uint64_t *)MolReader_Write_get_to(&write_seg).ptr); - if (from == vm_index) { - // Write data - uint64_t from_pipe = - *((uint64_t *)MolReader_Write_get_from_pipe(&write_seg).ptr); - mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); - - uint64_t pipe_id = 0; - ret = pipes_find(¤t_pipes, from_pipe, &pipe_id); - if (ret != 0) { - return ret; - } + // Create new pipes that should be created from current VM + mol_seg_t pipes_seg = MolReader_Data_get_pipes(&data_seg); + for (mol_num_t i = 0; i < MolReader_Pipes_length(&pipes_seg); i++) { + mol_seg_res_t pipe_pair_res = MolReader_Pipes_get(&pipes_seg, i); + if (pipe_pair_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t pipe_pair_seg = pipe_pair_res.seg; + + uint64_t pair_vm_index = *((uint64_t *)MolReader_Pipe_get_vm(&pipe_pair_seg).ptr); + if (pair_vm_index == vm_index) { + uint64_t read_index = *((uint64_t *)MolReader_Pipe_get_read_pipe(&pipe_pair_seg).ptr); + uint64_t write_index = *((uint64_t *)MolReader_Pipe_get_write_pipe(&pipe_pair_seg).ptr); + + uint64_t fildes[2]; + ret = ckb_pipe(fildes); + if (ret != 0) { + return ret; + } + ret = pipes_add(¤t_pipes, read_index, fildes[0]); + if (ret != 0) { + return ret; + } + ret = pipes_add(¤t_pipes, write_index, fildes[1]); + if (ret != 0) { + return ret; + } + } + } - ckb_printf("Write %lu bytes to pipe index %lu, id %lu", data_seg.size, - from_pipe, pipe_id); + uint64_t spawned_vms[MAX_SPAWNED_VMS]; + size_t spawned_count = 0; - uint32_t written = 0; - while (written < data_seg.size) { - size_t length = data_seg.size - written; - ret = ckb_write(pipe_id, &data_seg.ptr[written], &length); - if (ret != 0) { - return ret; + // Issue spawn syscalls for child VMs + for (mol_num_t i = 0; i < MolReader_Spawns_length(&spawns_seg); i++) { + mol_seg_res_t spawn_res = MolReader_Spawns_get(&spawns_seg, i); + if (spawn_res.errno != MOL_OK) { + return ERROR_ENCODING; } - if (length == 0) { - return ERROR_PIPE_CLOSED; + mol_seg_t spawn_seg = spawn_res.seg; + + uint64_t from_index = *((uint64_t *)MolReader_Spawn_get_from(&spawn_seg).ptr); + if (from_index == vm_index) { + if (spawned_count >= MAX_SPAWNED_VMS) { + return ERROR_TOO_MANY_SPAWNS; + } + + uint64_t child_index = *((uint64_t *)MolReader_Spawn_get_child(&spawn_seg).ptr); + + pipes_t passed_pipes; + pipes_init(&passed_pipes); + + mol_seg_t pipe_indices = MolReader_Spawn_get_pipes(&spawn_seg); + for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&pipe_indices); i++) { + mol_seg_res_t index_res = MolReader_PipeIndices_get(&pipe_indices, i); + if (index_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t index_seg = index_res.seg; + uint64_t index = *((uint64_t *)index_seg.ptr); + + uint64_t id = 0; + ret = pipes_find(¤t_pipes, index, &id); + if (ret != 0) { + return ret; + } + + ckb_printf("Pass pipe index %lu, id %lu to VM %lu", index, id, child_index); + + ret = pipes_add(&passed_pipes, index, id); + if (ret != 0) { + return ret; + } + } + + size_t src_len = 8; + size_t dst_len = ee_maximum_encoding_length(src_len); + uint8_t encoded_child_index[dst_len + 1]; + ret = ee_encode(encoded_child_index, &dst_len, (const uint8_t *)&child_index, &src_len); + if (ret != 0) { + return ret; + } + encoded_child_index[dst_len] = '\0'; + + src_len = passed_pipes.used * 8; + dst_len = ee_maximum_encoding_length(src_len); + uint8_t encoded_ids[dst_len + 1]; + ret = ee_encode(encoded_ids, &dst_len, (const uint8_t *)passed_pipes.ids, &src_len); + if (ret != 0) { + return ret; + } + encoded_ids[dst_len] = '\0'; + + const char *argv[2] = {(char *)encoded_child_index, (char *)encoded_ids}; + spawn_args_t sargs; + sargs.argc = 2; + sargs.argv = argv; + sargs.process_id = &spawned_vms[spawned_count++]; + sargs.inherited_fds = (const uint64_t *)passed_pipes.ids; + + ret = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &sargs); + if (ret != 0) { + return ret; + } } - written += length; - } - } else if (to == vm_index) { - // Read data - uint64_t to_pipe = - *((uint64_t *)MolReader_Write_get_to_pipe(&write_seg).ptr); - mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); - - uint64_t pipe_id = 0; - ret = pipes_find(¤t_pipes, to_pipe, &pipe_id); - if (ret != 0) { - return ret; - } + } - ckb_printf("Read %lu bytes from pipe index %lu, id %lu", data_seg.size, - to_pipe, pipe_id); + // Process all reads & writes + mol_seg_t writes_seg = MolReader_Data_get_writes(&data_seg); + for (mol_num_t i = 0; i < MolReader_Writes_length(&writes_seg); i++) { + mol_seg_res_t write_res = MolReader_Writes_get(&writes_seg, i); + if (write_res.errno != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t write_seg = write_res.seg; + + uint64_t from = *((uint64_t *)MolReader_Write_get_from(&write_seg).ptr); + uint64_t to = *((uint64_t *)MolReader_Write_get_to(&write_seg).ptr); + + if (from == vm_index) { + // Write data + uint64_t from_pipe = *((uint64_t *)MolReader_Write_get_from_pipe(&write_seg).ptr); + mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); + + uint64_t pipe_id = 0; + ret = pipes_find(¤t_pipes, from_pipe, &pipe_id); + if (ret != 0) { + return ret; + } + + ckb_printf("Write %lu bytes to pipe index %lu, id %lu", data_seg.size, from_pipe, pipe_id); + + uint32_t written = 0; + while (written < data_seg.size) { + size_t length = data_seg.size - written; + ret = ckb_write(pipe_id, &data_seg.ptr[written], &length); + if (ret != 0) { + return ret; + } + if (length == 0) { + return ERROR_PIPE_CLOSED; + } + written += length; + } + } else if (to == vm_index) { + // Read data + uint64_t to_pipe = *((uint64_t *)MolReader_Write_get_to_pipe(&write_seg).ptr); + mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); + + uint64_t pipe_id = 0; + ret = pipes_find(¤t_pipes, to_pipe, &pipe_id); + if (ret != 0) { + return ret; + } + + ckb_printf("Read %lu bytes from pipe index %lu, id %lu", data_seg.size, to_pipe, pipe_id); + + uint32_t read = 0; + while (read < data_seg.size) { + size_t length = data_seg.size - read; + uint8_t data[length]; + memset(data, 0, length); + ret = ckb_read(pipe_id, data, &length); + if (ret != 0) { + return ret; + } + if (length == 0) { + return ERROR_PIPE_CLOSED; + } + if (memcmp(&data_seg.ptr[read], data, length) != 0) { + return ERROR_CORRUPTED_DATA; + } + read += length; + } + } + } - uint32_t read = 0; - while (read < data_seg.size) { - size_t length = data_seg.size - read; - uint8_t data[length]; - memset(data, 0, length); - ret = ckb_read(pipe_id, data, &length); + // Join all spawned VMs + for (size_t i = 0; i < spawned_count; i++) { + size_t j = spawned_count - i - 1; + int8_t exit_code = 0xFF; + ret = ckb_wait(spawned_vms[j], &exit_code); if (ret != 0) { - return ret; + return ret; } - if (length == 0) { - return ERROR_PIPE_CLOSED; + if (exit_code != 0) { + return exit_code; } - if (memcmp(&data_seg.ptr[read], data, length) != 0) { - return ERROR_CORRUPTED_DATA; - } - read += length; - } - } - } - - // Join all spawned VMs - for (size_t i = 0; i < spawned_count; i++) { - size_t j = spawned_count - i - 1; - int8_t exit_code = 0xFF; - ret = ckb_wait(spawned_vms[j], &exit_code); - if (ret != 0) { - return ret; - } - if (exit_code != 0) { - return exit_code; } - } - return 0; + return 0; } diff --git a/script/testdata/spawn_dag.h b/script/testdata/spawn_dag.h index b2f0ce12b9..b726340c0e 100644 --- a/script/testdata/spawn_dag.h +++ b/script/testdata/spawn_dag.h @@ -22,139 +22,139 @@ extern "C" { * Reader APIs */ -#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_PipeIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_PipeIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_PipeIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_PipeIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_PipeIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_PipeIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_PipeIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_PipeIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_PipeIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_PipeIndices_verify(s, c) mol_fixvec_verify(s, 8) -#define MolReader_PipeIndices_length(s) mol_fixvec_length(s) -#define MolReader_PipeIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) -#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) -#define MolReader_Bytes_length(s) mol_fixvec_length(s) -#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) -#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t*, bool); -#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) -#define MolReader_Pipe_get_read_pipe(s) mol_table_slice_by_index(s, 1) -#define MolReader_Pipe_get_write_pipe(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t*, bool); -#define MolReader_Pipes_length(s) mol_dynvec_length(s) -#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t*, bool); -#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) -#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Write_get_from_pipe(s) mol_table_slice_by_index(s, 1) -#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) -#define MolReader_Write_get_to_pipe(s) mol_table_slice_by_index(s, 3) -#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t*, bool); -#define MolReader_Writes_length(s) mol_dynvec_length(s) -#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t*, bool); -#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) -#define MolReader_Spawn_get_pipes(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t*, bool); -#define MolReader_Spawns_length(s) mol_dynvec_length(s) -#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t*, bool); -#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) -#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) -#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) +#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_PipeIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_PipeIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_PipeIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_PipeIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_PipeIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_PipeIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_PipeIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_PipeIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_PipeIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_PipeIndices_verify(s, c) mol_fixvec_verify(s, 8) +#define MolReader_PipeIndices_length(s) mol_fixvec_length(s) +#define MolReader_PipeIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) +#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_Bytes_length(s) mol_fixvec_length(s) +#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *, bool); +#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) +#define MolReader_Pipe_get_read_pipe(s) mol_table_slice_by_index(s, 1) +#define MolReader_Pipe_get_write_pipe(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *, bool); +#define MolReader_Pipes_length(s) mol_dynvec_length(s) +#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *, bool); +#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) +#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Write_get_from_pipe(s) mol_table_slice_by_index(s, 1) +#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) +#define MolReader_Write_get_to_pipe(s) mol_table_slice_by_index(s, 3) +#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *, bool); +#define MolReader_Writes_length(s) mol_dynvec_length(s) +#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *, bool); +#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) +#define MolReader_Spawn_get_pipes(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *, bool); +#define MolReader_Spawns_length(s) mol_dynvec_length(s) +#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *, bool); +#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) +#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) +#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) /* * Builder APIs */ -#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_PipeIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_PipeIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_PipeIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_PipeIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_PipeIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_PipeIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_PipeIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_PipeIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_PipeIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_PipeIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_PipeIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_PipeIndices_init(b) mol_fixvec_builder_initialize(b, 128) -#define MolBuilder_PipeIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) -#define MolBuilder_PipeIndices_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_PipeIndices_clear(b) mol_builder_discard(b) -#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) -#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) -#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Pipe_set_read_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Pipe_set_write_pipe(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t); -#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) -#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) -#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Write_set_from_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_Write_set_to_pipe(b, p, l) mol_table_builder_add(b, 3, p, l) -#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t); -#define MolBuilder_Write_clear(b) mol_builder_discard(b) -#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Writes_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Spawn_set_pipes(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t); -#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) -#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) -#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t); -#define MolBuilder_Data_clear(b) mol_builder_discard(b) +#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_PipeIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_PipeIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_PipeIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_PipeIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_PipeIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_PipeIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_PipeIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_PipeIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_PipeIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_PipeIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_PipeIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_PipeIndices_init(b) mol_fixvec_builder_initialize(b, 128) +#define MolBuilder_PipeIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) +#define MolBuilder_PipeIndices_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_PipeIndices_clear(b) mol_builder_discard(b) +#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Pipe_set_read_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Pipe_set_write_pipe(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t); +#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) +#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) +#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Write_set_from_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_Write_set_to_pipe(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t); +#define MolBuilder_Write_clear(b) mol_builder_discard(b) +#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Writes_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Spawn_set_pipes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t); +#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) +#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) +#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t); +#define MolBuilder_Data_clear(b) mol_builder_discard(b) /* * Default Value @@ -162,39 +162,35 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build #define ____ 0x00 -MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndices[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { - 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, - 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndices[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { + 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { - 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, - 0x28, ____, ____, ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { + 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, 0x28, ____, ____, + ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { - 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, - 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { + 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { - 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, - 0x18, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, - 0x04, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { + 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, 0x18, ____, + ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, }; #undef ____ @@ -203,7 +199,7 @@ MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { * Reader Functions */ -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -217,7 +213,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -226,45 +222,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -281,15 +277,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i=1; i end) { @@ -312,7 +308,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Pipe_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -326,7 +322,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -335,57 +331,57 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, } else if (!compatible && field_count > 5) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[4]; - inner.size = offsets[5] - offsets[4]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_PipeIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -402,15 +398,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i=1; i end) { @@ -433,7 +429,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input inner.size = total_size - offset; return MolReader_Write_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -447,7 +443,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -456,45 +452,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_PipeIndices_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_PipeIndices_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -511,15 +507,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i=1; i end) { @@ -542,7 +538,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input inner.size = total_size - offset; return MolReader_Spawn_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -556,7 +552,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -565,42 +561,42 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Spawns_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_Pipes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_Writes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Spawns_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Pipes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Writes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } @@ -608,7 +604,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, * Builder Functions */ -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -620,7 +616,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 8 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -643,7 +639,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -652,7 +648,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde memcpy(dst, &MolDefault_PipeIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -661,13 +657,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde memcpy(dst, &MolDefault_PipeIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 24; @@ -683,7 +679,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[9]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -714,7 +710,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -723,7 +719,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_PipeIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -732,7 +728,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[7]; @@ -741,7 +737,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_PipeIndex, len); } else { mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[9]; @@ -750,13 +746,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_Bytes, len); } else { mol_num_t of = builder.number_ptr[8]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -768,7 +764,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -791,7 +787,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -800,7 +796,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -809,13 +805,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build memcpy(dst, &MolDefault_PipeIndices, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -827,7 +823,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde res.seg.size += len == 0 ? 4 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -850,7 +846,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde memcpy(dst, &MolDefault_Spawns, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -859,7 +855,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde memcpy(dst, &MolDefault_Pipes, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -868,7 +864,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde memcpy(dst, &MolDefault_Writes, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); diff --git a/script/testdata/spawn_dag_escape_encoding.h b/script/testdata/spawn_dag_escape_encoding.h index 6183ca0c10..2b1590da46 100644 --- a/script/testdata/spawn_dag_escape_encoding.h +++ b/script/testdata/spawn_dag_escape_encoding.h @@ -10,73 +10,71 @@ size_t ee_maximum_encoding_length(size_t length) { return length * 2; } -int ee_decode(uint8_t *dst, size_t *dst_length, const uint8_t *src, - size_t *src_length) { - size_t ds = 0; - size_t dl = *dst_length; - size_t ss = 0; - size_t sl = *src_length; +int ee_decode(uint8_t *dst, size_t *dst_length, const uint8_t *src, size_t *src_length) { + size_t ds = 0; + size_t dl = *dst_length; + size_t ss = 0; + size_t sl = *src_length; - while ((ss < sl) && (ds < dl)) { - if (src[ss] == 0xFE) { - if (ss + 1 >= sl) { - return ESCAPE_ERROR_ENCODING; - } - dst[ds++] = src[ss + 1] + 1; - ss += 2; - } else { - dst[ds++] = src[ss++]; + while ((ss < sl) && (ds < dl)) { + if (src[ss] == 0xFE) { + if (ss + 1 >= sl) { + return ESCAPE_ERROR_ENCODING; + } + dst[ds++] = src[ss + 1] + 1; + ss += 2; + } else { + dst[ds++] = src[ss++]; + } } - } - *dst_length = ds; - *src_length = ss; - return 0; + *dst_length = ds; + *src_length = ss; + return 0; } int ee_decode_char_string_in_place(char *buf, size_t *length) { - size_t ss = 0; - size_t ds = 0; + size_t ss = 0; + size_t ds = 0; - while (buf[ss] != '\0') { - if (((uint8_t)buf[ss]) == 0xFE) { - if (buf[ss + 1] == '\0') { - return ESCAPE_ERROR_ENCODING; - } - buf[ds++] = buf[ss + 1] + 1; - ss += 2; - } else { - buf[ds++] = buf[ss++]; + while (buf[ss] != '\0') { + if (((uint8_t)buf[ss]) == 0xFE) { + if (buf[ss + 1] == '\0') { + return ESCAPE_ERROR_ENCODING; + } + buf[ds++] = buf[ss + 1] + 1; + ss += 2; + } else { + buf[ds++] = buf[ss++]; + } } - } - *length = ds; - return 0; + *length = ds; + return 0; } -int ee_encode(uint8_t *dst, size_t *dst_length, const uint8_t *src, - size_t *src_length) { - size_t ds = 0; - size_t dl = *dst_length; - size_t ss = 0; - size_t sl = *src_length; +int ee_encode(uint8_t *dst, size_t *dst_length, const uint8_t *src, size_t *src_length) { + size_t ds = 0; + size_t dl = *dst_length; + size_t ss = 0; + size_t sl = *src_length; - while ((ss < sl) && (ds < dl)) { - if ((src[ss] == 0x0) || (src[ss] == 0xFE)) { - if (ds + 1 >= dl) { - break; - } - dst[ds] = 0xFE; - dst[ds + 1] = src[ss++] - 1; - ds += 2; - } else { - dst[ds++] = src[ss++]; + while ((ss < sl) && (ds < dl)) { + if ((src[ss] == 0x0) || (src[ss] == 0xFE)) { + if (ds + 1 >= dl) { + break; + } + dst[ds] = 0xFE; + dst[ds + 1] = src[ss++] - 1; + ds += 2; + } else { + dst[ds++] = src[ss++]; + } } - } - *dst_length = ds; - *src_length = ss; - return 0; + *dst_length = ds; + *src_length = ss; + return 0; } #endif /* ESCAPE_ENCODING_H_ */ From ac8e15285d801712b5d2b995094eaf3938c8b9f6 Mon Sep 17 00:00:00 2001 From: mohanson Date: Sat, 6 Apr 2024 11:32:58 +0800 Subject: [PATCH 056/135] Add test_random_dag --- script/src/scheduler.rs | 8 +- .../tests/ckb_latest/features_since_v2023.rs | 72 +++++++++--------- script/testdata/spawn_dag | Bin 13608 -> 9856 bytes script/testdata/spawn_dag.c | 8 -- 4 files changed, 38 insertions(+), 50 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 92a01f5d15..a00e01ce23 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -33,10 +33,10 @@ use std::{ mem::size_of, }; -const ROOT_VM_ID: VmId = FIRST_VM_ID; -const MAX_VMS_COUNT: u64 = 16; -const MAX_INSTANTIATED_VMS: usize = 4; -const MAX_PIPE: u64 = 64; +pub const ROOT_VM_ID: VmId = FIRST_VM_ID; +pub const MAX_VMS_COUNT: u64 = 16; +pub const MAX_INSTANTIATED_VMS: usize = 4; +pub const MAX_PIPE: u64 = 64; /// A single Scheduler instance is used to verify a single script /// within a CKB transaction. 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 145a345bef..e7a85ab28a 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1,10 +1,13 @@ use super::SCRIPT_VERSION; +use crate::scheduler::{MAX_PIPE, MAX_VMS_COUNT}; use crate::syscalls::SOURCE_GROUP_FLAG; use crate::verify::{tests::utils::*, *}; use ckb_types::{ core::{capacity_bytes, cell::CellMetaBuilder, Capacity, TransactionBuilder}, packed::{CellInput, CellOutputBuilder, OutPoint, Script}, }; +use proptest::prelude::*; +use proptest::proptest; fn simple_spawn_test(bin_path: &str, args: &[u8]) -> Result { let script_version = SCRIPT_VERSION; @@ -1140,45 +1143,38 @@ fn build_pipe_index(val: u64) -> dag::PipeIndex { dag::PipeIndexBuilder::default().set(data).build() } -pub fn build_mock_tx(program: Bytes, data: dag::Data) -> ResolvedTransaction { - let script_version = SCRIPT_VERSION; +proptest! { + #![proptest_config(ProptestConfig::with_cases(32))] + #[test] + fn test_random_dag( + seed: u64, + spawns in 5u32..MAX_VMS_COUNT as u32, + writes in 3u32..MAX_PIPE as u32 / 2, + ) { + let script_version = SCRIPT_VERSION; + let program: Bytes = std::fs::read("./testdata/spawn_dag").unwrap().into(); + let data = generate_data_graph(seed, spawns, writes, 3).unwrap(); + + let (code_dep, code_dep_hash) = load_cell_from_slice(&program[..]); + let spawn_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(code_dep_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(spawn_caller_script) + .build(); + let dummy_cell = create_dummy_cell(output); - let (code_dep, code_dep_hash) = load_cell_from_slice(&program[..]); - let spawn_caller_script = Script::new_builder() - .hash_type(script_version.data_hash_type().into()) - .code_hash(code_dep_hash) - .build(); - let output = CellOutputBuilder::default() - .capacity(capacity_bytes!(100).pack()) - .lock(spawn_caller_script) - .build(); - let dummy_cell = create_dummy_cell(output); + let rtx = ResolvedTransaction { + transaction: TransactionBuilder::default().witness(data.as_bytes().pack()).build(), + resolved_cell_deps: vec![code_dep], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; - let tx = TransactionBuilder::default() - .witness(data.as_bytes().pack()) - .build(); - ResolvedTransaction { - transaction: tx, - resolved_cell_deps: vec![code_dep], - 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 test_single_dag() { - let script_version = SCRIPT_VERSION; - - let seed = 0; - let spawns = 8; - let writes = 64; - - let data = generate_data_graph(seed, spawns, writes, 3).unwrap(); - let program = std::fs::read("./testdata/spawn_dag").unwrap().into(); - - let rtx = build_mock_tx(program, data); - - let verifier = TransactionScriptsVerifierWithEnv::new(); - let result = verifier.verify_without_limit(script_version, &rtx); - assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); -} diff --git a/script/testdata/spawn_dag b/script/testdata/spawn_dag index 4e1b454908f2225e445e887d60cbc54ccfdddf2f..b88dedb7fd2fbd0adbba5e69c79e95ea5269e252 100755 GIT binary patch delta 2585 zcmZ`*e^3DYcgy%= z?9S}IeV_Mz-|y%9`M&+mo~mzt_E>g7cM1jSRgriCT>4t_MMW#13@GwMp!aTCWva_d zF4g6E``)I_jZfq6Qw1~(*ziH>M>PCkJ^mB5DHF`O{j#&5%JqpmO-uNU;a&gz3WSfWm+Qy;qZ{IAPpw-M4MZ9ljmQL zKF;7TblU{;vC7JM+UAa&bOf@(5z)37{E?YBRVAKBfET-C-d?g@ug2fz`ZIB7j0N^b zW`odZ5go=DWB->_BQb?MM&&^$%JPS2;#ig^`jj_$(J!l^TBA?W1?~`*O<(%lGI$+Z zrGOH9f-u)uN4b4X=`vl=mJiM%mVoc1$3u^R=1DZ^p^98&on#Kr)XD(tixvAB|e|D&v zvEP<{N;ZD_3)O5xT~${Xe=l)v08ziJ<;o4QQN>6sS;iFQhR`rqG%*!~-Ufemh)86Z z!|jHc@2Cv-cG9J-QF;ggv-@(BEscuXXrS11=Bl$&z-_Vg*H*m7vP@`1bm&3ck_DoD z4fw(zQ9Z|7fOeFEZ>$=6I`xzv`I32~kVyPVGvYaUEdszD75WpybWDZL?4Rrb^kW|^kWp8V*`vV(5APdXDF_$ zx@ol2DvwdzQ2D{8G{lw9#(ZcTh?q^%>d*z2xu)wsvUgCl8RN9g9m6hD$S1j=M&e55 zqDDJcG)~UKrD_~Qxq^6B7J}v?2rOX+=_|`X95I4;yGR#$0@2co=nE-b@2|mLJWi^aI zAau7|EPWklpAk+P-|0Ld)C5}lN4cU};08Vh$;1^IU=F=Ke1_3xlqa``k*5@14gt0w*0@NpxzPblJg`MW=%1=KcM0U>WnzGqtMw zQHAI+K|b?%zOs~85xOj8nnm&i?s7oB!nzDp3U8$@SJc?M+R#>)N#YEKS=A+1mOC9Z z_wFU`GMJAOTT4@>35783*a&@!sq-BL>(QOQP7d@yf|GiZRa|Q-6};#=v$nzc{*bf> z%lfP56x-dIxLO~=W{y;2B45ex%)Xsn(}t+6=g4tKG14&Rd~GCe**Ix!Cu94EeW|_N zP}AL)NCQrX$#mME7FHWc;8*AxZ$L{orj1bV(N{O)%rspK>-6Hk(z-0EyW>@t;IvZ? zrz3VWurqC*DNG%d_OJ;W{`+WPmrA3rv+H&jq2YX%(D0*}nkOMSp0DHvR7z?I0#oyT zzgjC<9`94Qfm+z;y0|%spb1?TbzDWm6h?Q!D;`ItWgaVar$XC8D(9>;Nyh@Djb-87 z6q~RiWme7O?AZAGS~x;P+=L)GlSy#eih%7%)lpt63V~HW3pt8tN2H19K|*}je;{xo z6noEehN^cmr0<#Odgt(weUl$VNe|R{hA}Zs%)i3u8fg{#CcpKSZB{*QhA{pxklya5DXZuRr@di=SWn+zL_- z()HjlxgWl0(BWI_Gie%VY*|+<9ABKYDbozskkJfx;&o*Y?p4<_h`;SCllU&pzFNbx zvXgjJ+t!fqLqT29gMOMc`yW4+zy&bqlAcaz3mG}d4Nuca{BIh*@I#Q3gyGj3{#JU@ zevxMX2ZEak(T4+n@JL($_=o0bR8!&_nXA`ra;q6HsF<@j0mGPv_h%#nFVzx=Y54Co zh2BbR_s$^XHhAh;S}cqw@y*H1JheyHK^YQIud z$z_0-8h0LQ*s*J8?K<89d-uJ#W7jJU2Y2&3UfkVKd!TMzdBA-!x`($(5huKbF{xqW05Qj-M%6`9C;KW6S^m delta 6268 zcmai33s_XuzF&Lq*|T66U}P&GpaBC}z7BObcGO`Q z_KY}#s7oCQO{JR|U)|4|kVNrOmn?5~t!`@GQ-|25h!2o>sW5Z@Yi3VU-Sgf3eKTvV z|N1|F|NnpOJ$p*$A6mLKa?I{X2GJ|c`;AcB*YnJjChJ@`;9>#F)ubY+_7ur422WI&^7sm_)JXy?CRwT@v`s_d0Yf zi%BUvCPbI^k|m|Wv_}-}1LGx9&o1C%I~k(k;?i|#Pf{BTtY3mipj%#bufIcg>N$%c z(9LK3AZ1JZSaCOgx$r$ZsT{DR1P>Bx#m}xvD-yJUCjF#a_w-W+?=cy-!9%e17!5Db zyW*Ot_5Ddoz!mTQ5rPikO=Ig%ra%A!wzbDQ3GRGKpEL%EttEx65}&aMl$1`OB2O%z zyLX33IrrwDb?T=Fy9JEfTfr^OK)h4`5k3)^p-;NpHC%>djP*f+0TOQN=7Akz`oUu*ZG1PR8)qe(s3PBUU!6d3*rNueZAi zKE<9We~=&UeT*uOW=p|eX&Lvlvxc6`=!MHEk zW$T1uvSJqI4rNZk+X`TohWPfpYjFslGWW`hQoc}yKZBa^oGt-3 zw)BNIV8$a@`aGn{bEW|!=A4mi>hp*G-sr&RFo!J-? zs-J$#?ZVd?$mm9Xd}Y1BpJ(gJ`6HH;Ko6Hv;U-p1PqyTetVloU?f}jCbtucyATk}t zn7HFMQ%7t|vK+&|YcXh%Wp)fo-@wfpkA&dC(3)MFP;$v2Y6xaL3#$f4)r9kmW!7|{ zH82aS8q|m(6}_J5T@sUAlEVBMGM|FD$rbn52!_bR&K#nEHUO{yY9C)ftm<}GkPX%D z5^&&Wg60`yHqG7LTC;l-a)A-owFoA91P`Utzg$1(|=3LeMeDj!Ss|JzXQ<1>q z|CBfOIxH!6WO+h^;xwN+xuX~-w!rM@U*^-6! zC|XghDD)N~H>JYF7-$JTsC6hoTIsg$!-iJ+dnQ-PARI-w@`lT5Lj(ukbV=T^D|xeb zyqoN>`J?le9q`;p240^*8kIvnV9-w*=vpA1Ht44ebalkOGOErdkKoVNL*K*k=1oCE zPd8M9_GerA>@=knQL^yI9 zmyeFI%hSjRjx7r_ZzEr`Y_|0A&NWtZ24gTA+?(XAHwXE#pEss>k6H{zt+ZU9l#c{k z@c-xZ5uk7X49P3aA?E_WGv%Ux-{-@~2D#QB&PUVK z=hA%?+|GtG+bQ)7LvSzJX4#H6lRs%9*cDHZC7P7v$F==5z;|wlRjk%8Q|qK&a3?T= zy9Ic{C1XTJgs|pqW<#=#e5r{{>T*xp@-bsHKLJ&)uK?70sJMx1vo z6MP=dWk{k-!h`0ScHlQGm@{QX@}booy%Lk*L#=C*TzzA(u(R+VRMKc}YA}zXQicB` z7GFRg?9`XOh003HN=L4&%RJb9w)4xIU$ zo{%�*Ce5iQDZK_lAa%UT}N{;dN@0NYr7>OpQHp)^|?`p@@y!FKT3Nvdy&ybAr1! zG+G_PP21AU2pip@V$Qcn*w`D&b1wC(=*_B6J+2opC$GhWMV2<7F6aWapq!N(6^qQNvQ<1nmBua?Uu)^Q8 zthl~>WU|(gmboX>zQ}sP$_Jf=+bv?tcE}^`o>s@mFEsY}JuYlVTyvi%S?x%>VBIkM ztkmi#+p)Y`v;?til&fNTy0A#YiUV_)JgXFV!Rpf?X+cZd9M9Di8AYT#OlQiIYS#y5 zm6cLhNLL6$fsxJX+c2uGHDkpNDiXWVkZH*UEy=%x^^VVUh>@h4sxjU9M7!2|;02pJXZ z7gcWt_=OtW^2krz=6UiCw*ARN)GQb@=YwQU-&3rJ?8Y($OO z&AS9H0tyvCFTDy6D~OeKa+??9$`CfwA*c}hQj=I2r26XGV|G*eHM#hkUWKh&E}3~3 z%x-1}1P%mkq5WAWGaXs=RLGwm*;xKlrbB8XeVJ&DZKq87wxI9iV0%>gx_@Rm4m8PY zzxlzdFH*h@0sPQ((x3Cgte~WPSiP4+Et`5Z_NW@3`{SVvQ{Or%;GaEmD876;L&TQ? zH1>*&sWo!Mr7i)-s`cmwiaROvg|MTpd4&VyE}yJ`OEKNO)#Nt>&MJmh9`o|Da;E@= zr-8G!l-Hw+Zl1eSPj#6_f-))&^=bGDyrSE5p4;RzO6SG(v^v%a-@B>7sh0GUD_1^z zYwq>TpML0W?Ns-~-&yeEg@MccS8ukr-M#{iSAN7k)lpX=mhzLi<{)IAFLM0k)A@rD zDbZnQ{?gQLf}_ib=2_?g&E`*2Zw4MRS`R{nO2K8-RAAjXDM*f3=wY5dok7=vEgHeG zAWx+%vPx2DCv+dn-fi>5U?IKg-M$LwjNgZeh){MZO2x?UcIFI@T%% z^o$nU-VPzSR4uA{;(=E!M)$mE;+mt8kfYKu39yBUJsin5-tHwhNiDX&t)&=_Q6XnIViFqd%}qj1f_L_Py^!;?cXkJ8Du(WU4zqGE?Z59TQEvPe%$Hm9!T2wbb3`zo+gk~4_q!ymA94NKlk`at1 zOXBu`@O6I?9qPwRo!S4b*67)y;WU>b?ac0;H_%!8u#c3PE(5Hb$HGh}*5G(j zf>oju#|kAlKxA9tc+j6f zc}1VeeZ(%GWr%uw@i-Ri0sf-?cN=?>*te;BJQ(fj6*@tidYku((aF^P&)d!)lzEskw;LYcBMq zC7-#7M(mprkxqPw)LiUi{2dh9Q&*Yi7(8*?k!L+<@*N^tm+iQc_f7?J0;8feACpm)_1=jy79m5)iN`2o1D5V2RaR5_uJ@d@D_h}J*<*Ee( z-+ySdAFWSy96i}+pYx$>dr$yl8nrUMP2kMz{G7=Hb=FzA6T2VpZ)_pF3PsuA!6QxJ z-}-O$%@bEXz4>ul)D<|UtkROPo6NHW;P5|Jl1-7D{7>?&ugu7qAtl18>Wo8(n9aQ` z{9a=+I$BPal7RC(<=c^!zE%k654D_8yH0A~5ljfJ3S-dA!+f75L*{)EW;tAF7!Jz%0du|h^F3^Qj=jeW$Bxsa@keRdv) z7<3puzrEmb2`w4_f6+PgySIEG%pnyyoiKvu5D)lgB??3v7h{?m?9-rC)Q^Ob1#2%T zbXKA375a+`y%dblYa)Co|8ME33jLDKr~hT;W#k-%J~_fmH^JLX-<1sm15WTbTdfkQ(rKc({Zx?x~2;Eia{}%1jqf+!xV00!L@g(1d z!jEF;#!w`bjYoh^4H$jUq4Ns;4+`C1B(E#Eq-rVuq0umbYq%2FJcWJ=kc0RUI!M3Z zTBvLcjPwZ{@(t)!7mTSx}S~77()~ce3NeJ|jY5EF{_-giIA20bt-x{>4Fej@h3r);ky_&q4 z@De$npx&OS8|BB6Rt>$5jPs4&Z*m%%CoM6+qyYL$8!j2|Cq}T#Cy>_@Q%CGp{uG$47{I_ELT)9F Z3v5v=d_>|NP6^zt{I4*F97ufVe*vo Date: Tue, 9 Apr 2024 16:23:08 +0800 Subject: [PATCH 057/135] Support interpreter ckb-vm --- script/src/scheduler.rs | 19 ++++++++----------- script/src/types.rs | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index a00e01ce23..304acc0f71 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -8,8 +8,8 @@ use crate::verify::TransactionScriptsSyscallsGenerator; use crate::ScriptVersion; use crate::types::{ - DataPieceId, FullSuspendedState, Message, PipeId, PipeIoArgs, RunMode, TxData, VmId, VmState, - FIRST_PIPE_SLOT, FIRST_VM_ID, + set_vm_max_cycles, CoreMachineType, DataPieceId, FullSuspendedState, Machine, Message, PipeId, + PipeIoArgs, RunMode, TxData, VmId, VmState, FIRST_PIPE_SLOT, FIRST_VM_ID, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; @@ -18,10 +18,7 @@ use ckb_vm::{ bytes::Bytes, cost_model::estimate_cycles, elf::parse_elf, - machine::{ - asm::{AsmCoreMachine, AsmMachine}, - CoreMachine, DefaultMachineBuilder, Pause, SupportMachine, - }, + machine::{CoreMachine, DefaultMachineBuilder, Pause, SupportMachine}, memory::Memory, registers::A0, snapshot2::{DataSource, Snapshot2}, @@ -63,7 +60,7 @@ where states: BTreeMap, pipes: BTreeMap, inherited_fd: BTreeMap>, - instantiated: BTreeMap, AsmMachine)>, + instantiated: BTreeMap, Machine)>, suspended: BTreeMap>, terminated_vms: BTreeMap, @@ -229,7 +226,7 @@ where self.ensure_vms_instantiated(&[vm_id_to_run])?; let (context, machine) = self.instantiated.get_mut(&vm_id_to_run).unwrap(); context.set_base_cycles(self.total_cycles); - machine.set_max_cycles(limit_cycles); + set_vm_max_cycles(machine, limit_cycles); machine.machine.set_pause(pause); let result = machine.run(); let consumed_cycles = { @@ -779,13 +776,13 @@ where } // Create a new VM instance with syscalls attached - fn create_dummy_vm(&self, id: &VmId) -> Result<(MachineContext
, AsmMachine), Error> { + fn create_dummy_vm(&self, id: &VmId) -> Result<(MachineContext
, Machine), Error> { // The code here looks slightly weird, since I don't want to copy over all syscall // impls here again. Ideally, this scheduler package should be merged with ckb-script, // or simply replace ckb-script. That way, the quirks here will be eliminated. let version = self.script_version; // log::debug!("Creating VM {} using version {:?}", id, version); - let core_machine = AsmCoreMachine::new( + let core_machine = CoreMachineType::new( version.vm_isa(), version.vm_version(), // We will update max_cycles for each machine when it gets a chance to run @@ -807,6 +804,6 @@ where .into_iter() .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); let default_machine = machine_builder.build(); - Ok((machine_context, AsmMachine::new(default_machine))) + Ok((machine_context, Machine::new(default_machine))) } } diff --git a/script/src/types.rs b/script/src/types.rs index cb2d630619..2b51129d4b 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -13,7 +13,7 @@ use std::fmt; use std::sync::{Arc, Mutex}; #[cfg(has_asm)] -use ckb_vm::machine::asm::AsmCoreMachine; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; #[cfg(not(has_asm))] use ckb_vm::{DefaultCoreMachine, TraceMachine, WXorXMemory}; @@ -51,6 +51,11 @@ pub type CoreMachine = DefaultCoreMachine>>; +#[cfg(has_asm)] +pub(crate) type Machine = AsmMachine; +#[cfg(not(has_asm))] +pub(crate) type Machine = TraceMachine; + pub(crate) type Indices = Arc>; pub(crate) type DebugPrinter = Arc; @@ -118,6 +123,16 @@ impl ScriptVersion { } } +#[cfg(has_asm)] +pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { + vm.set_max_cycles(cycles) +} + +#[cfg(not(has_asm))] +pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { + vm.machine.inner_mut().set_max_cycles(cycles) +} + /// A script group is defined as scripts that share the same hash. /// /// A script group will only be executed once per transaction, the From 8f40da9456c2db16ac37be8b7a5bf77d0da0dbd8 Mon Sep 17 00:00:00 2001 From: xjd Date: Wed, 10 Apr 2024 13:45:31 +0800 Subject: [PATCH 058/135] Add spawn fuzzing test (#17) * Add spawn fuzzing test * Fix offset error --- script/fuzz/.gitignore | 4 + script/fuzz/Cargo.toml | 6 + script/fuzz/README.md | 2 +- script/fuzz/fuzz_targets/syscall_spawn.rs | 136 ++++++++++++++++++++++ script/src/scheduler.rs | 3 - script/testdata/Makefile | 4 +- script/testdata/spawn_fuzzing | Bin 0 -> 5936 bytes script/testdata/spawn_fuzzing.c | 114 ++++++++++++++++++ 8 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 script/fuzz/fuzz_targets/syscall_spawn.rs create mode 100755 script/testdata/spawn_fuzzing create mode 100644 script/testdata/spawn_fuzzing.c diff --git a/script/fuzz/.gitignore b/script/fuzz/.gitignore index df51d17bb0..438a59213f 100644 --- a/script/fuzz/.gitignore +++ b/script/fuzz/.gitignore @@ -3,3 +3,7 @@ target corpus artifacts coverage +flamegraph.svg +perf.data +perf.data.old + diff --git a/script/fuzz/Cargo.toml b/script/fuzz/Cargo.toml index fe15354cea..4975c2915c 100644 --- a/script/fuzz/Cargo.toml +++ b/script/fuzz/Cargo.toml @@ -47,3 +47,9 @@ name = "syscall_exec" path = "fuzz_targets/syscall_exec.rs" test = false doc = false + +[[bin]] +name = "syscall_spawn" +path = "fuzz_targets/syscall_spawn.rs" +test = false +doc = false diff --git a/script/fuzz/README.md b/script/fuzz/README.md index d4942e9120..d51f1304df 100644 --- a/script/fuzz/README.md +++ b/script/fuzz/README.md @@ -14,7 +14,7 @@ cargo install cargo-fuzz run fuzz test ``` -cargo +nightly fuzz run transaction_scripts_verifier_data1 +cargo +nightly fuzz run -j $(nproc) transaction_scripts_verifier_data1 ``` generate coverage report diff --git a/script/fuzz/fuzz_targets/syscall_spawn.rs b/script/fuzz/fuzz_targets/syscall_spawn.rs new file mode 100644 index 0000000000..8782bee23a --- /dev/null +++ b/script/fuzz/fuzz_targets/syscall_spawn.rs @@ -0,0 +1,136 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; + +use ckb_chain_spec::consensus::ConsensusBuilder; +use ckb_script::{TransactionScriptsVerifier, TxVerifyEnv}; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; +use ckb_types::{ + bytes::Bytes, + core::{ + capacity_bytes, + cell::{CellMetaBuilder, ResolvedTransaction}, + hardfork::{HardForks, CKB2021, CKB2023}, + Capacity, HeaderView, ScriptHashType, TransactionBuilder, TransactionInfo, + }, + h256, + packed::{ + self, Byte32, CellInput, CellOutput, CellOutputBuilder, OutPoint, Script, + TransactionInfoBuilder, TransactionKeyBuilder, + }, + prelude::*, +}; + +#[derive(Default, PartialEq, Eq, Clone)] +struct MockDataLoader {} + +impl CellDataProvider for MockDataLoader { + fn get_cell_data(&self, _out_point: &OutPoint) -> Option { + None + } + + fn get_cell_data_hash(&self, _out_point: &OutPoint) -> Option { + None + } +} + +impl HeaderProvider for MockDataLoader { + fn get_header(&self, _block_hash: &Byte32) -> Option { + None + } +} + +impl ExtensionProvider for MockDataLoader { + fn get_block_extension(&self, _hash: &Byte32) -> Option { + None + } +} + +fn mock_transaction_info() -> TransactionInfo { + TransactionInfoBuilder::default() + .block_number(1u64.pack()) + .block_epoch(0u64.pack()) + .key( + TransactionKeyBuilder::default() + .block_hash(Byte32::zero()) + .index(1u32.pack()) + .build(), + ) + .build() + .unpack() +} + +static PROGRAM_DATA: &[u8] = include_bytes!("../../testdata/spawn_fuzzing"); + +fn run(data: &[u8]) { + if data.len() < 8 { + return; + } + let split_offset = data[0] as usize; + let split_offset = usize::min(split_offset, data.len() - 1); + let parent_witness = Bytes::copy_from_slice(&data[0..split_offset]); + let child_witness = Bytes::copy_from_slice(&data[split_offset..]); + let witnesses = vec![parent_witness.pack(), child_witness.pack()]; + + let transaction = TransactionBuilder::default() + .input(CellInput::new(OutPoint::null(), 0)) + .set_witnesses(witnesses) + .build(); + + let data: Bytes = (Vec::from(PROGRAM_DATA)).into(); + let script = Script::new_builder() + .hash_type(ScriptHashType::Data2.into()) + .code_hash(CellOutput::calc_data_hash(&data)) + .build(); + let dep_cell = CellMetaBuilder::from_cell_output( + CellOutput::new_builder() + .capacity(Capacity::bytes(data.len()).unwrap().pack()) + .build(), + data, + ) + .transaction_info(mock_transaction_info()) + .out_point(OutPoint::new(h256!("0x0").pack(), 0)) + .build(); + + let input_cell = CellMetaBuilder::from_cell_output( + CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(script) + .build(), + Bytes::new(), + ) + .transaction_info(mock_transaction_info()) + .build(); + + let rtx = ResolvedTransaction { + transaction, + resolved_cell_deps: vec![dep_cell], + resolved_inputs: vec![input_cell], + resolved_dep_groups: vec![], + }; + + let provider = MockDataLoader {}; + let hardfork_switch = HardForks { + ckb2021: CKB2021::new_mirana().as_builder().build().unwrap(), + ckb2023: CKB2023::new_mirana() + .as_builder() + .rfc_0049(0) + .build() + .unwrap(), + }; + let consensus = ConsensusBuilder::default() + .hardfork_switch(hardfork_switch) + .build(); + let tx_verify_env = + TxVerifyEnv::new_submit(&HeaderView::new_advanced_builder().epoch(0.pack()).build()); + let verifier = TransactionScriptsVerifier::new( + rtx.into(), + provider, + consensus.into(), + tx_verify_env.into(), + ); + let _ = verifier.verify(70_000_000); +} + +fuzz_target!(|data: &[u8]| { + run(data); +}); diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 304acc0f71..7675a0efa9 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -490,9 +490,6 @@ where .store64(&length_addr, &actual_length)?; machine.machine.set_register(A0, SUCCESS as u64); } else { - // TODO: in the previous convention - // https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0009-vm-syscalls/0009-vm-syscalls.md#partial-loading - // this will load data in to address 0 without notice. It is now marked as an error. machine.machine.set_register(A0, INDEX_OUT_OF_BOUND as u64); } continue; diff --git a/script/testdata/Makefile b/script/testdata/Makefile index eb46eb0e5b..42cf22ed47 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -71,7 +71,8 @@ ALL_BINS := jalr_zero \ spawn_pipe_limits \ spawn_configurable_caller \ spawn_configurable_callee \ - spawn_dag + spawn_dag \ + spawn_fuzzing ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -156,3 +157,4 @@ spawn_pipe_limits: spawn_pipe_limits.c spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h +spawn_fuzzing: spawn_fuzzing.c spawn_utils.h diff --git a/script/testdata/spawn_fuzzing b/script/testdata/spawn_fuzzing new file mode 100755 index 0000000000000000000000000000000000000000..0c1602e09a0d72fcdac435e08127a92063f085e8 GIT binary patch literal 5936 zcmb_geRNY*wm-e>Q9_CEXM=KL}DcRHG)ko?f-?}&^xYeHC-#2AeV5d_Ub_aGYHVMrB} zWh9xK5`+rP|0ptq$~}_Cgv&xZ6Jnz?Ng;W;mtcgH5+%*UkF=t4G-@hG8~+1WpF@8> zkWzOHS?jEIag`l;?PI4$KO6bNdv3@+)i!x?;EAa%lZ9jI2Ra(koBrJN)*c}ck%eQp z1>;V^@Au=w+6BUR1Z~L?m`D~2>;h_y+L@O7)m^+6(MwvfT2!odcy@3K-aoEQU?UXw z?(L=cKlruS_$A{1Fs@}39(FrAy00(bd6ZL#JGp7$MmoZc;SqQr9g7cYqwyj|RJI;7 z-sNF>OnL9%IiyHI-yvoVc5;aVr=a(^dF~9&D|wVsciAuaGZB6+BA!oF)BIx^8t-a| zTcvSjqvZrYY`NQkZ56lhFRJXeaY~@?80yWR9FCv8>@zp3BxPOyr>*jsv1Fu@`+M&U3~$)P9@i zda+yFdG?#2zF6^R@c*0c9y#}~&*Xl7XHbF_$JNgG7Dn+e$9HEO>*2Y-2ShD*@stj8 z7gTCzlP;r0jJa@)=aSeI^dnl*!%sxei!KM}s>Exdxja|L5$;djvK{bM+GCX`gR-@}$ZXi9`p>~9!XPi^61%%%Xf_LPo{c}D_j z;TXR#F`>o7<7f}}h5OJNs{^oUf*sRg-*~*hwbImsSnEp?xB=R-4l_QexxcVo_T_f0 z^4)^HFGmPm9gCH|WRPWXg74oHy$OgnDkG^>;BbO78i_x?JT7o6Sp37w8WI7ly`;mj zzR0jfLE}PLt6Z(f)u48J8Te~GXw&lzix3VJJ>0_m7_i3hdw+v0f@hu|CBupsrBuHM z#ke;Eg)Xv|MOPCV<{>c8d+JFQ@rxB zH-YQDZqs|*m(iA@>-+Fwawe_dARY?@4sqfwzG21P8i+>}eM(QImf150l83U_S@a|~ zdA2K~-yUD0>1ckt8^>>=LK)+kjWo&HE8vTg21^W;D#rT;`I_Gbgc@a5_PPWmhwu?D zmP9Xm-KI9`!DG6XnA_1wM-kQHjzO;+QRH$c!O2Z`IpusZoER9N3T07T>>HG_l$EBF zCA#cXD&937OL7hwkMDAlOfwwGwV3D|ATz|M-a+tcg`yYEuT;T)J6hRYzf^;kXuul6 z{ct#gRF{+CPMst%B_k5Ud&5Vw7_Ryx8DqBhR?wlMQhPm$`!q=4Tqtw0UN;Y|w&CYg z(Y3$FF7{4_+veWpf-{dDLG}7X#Av2(+^hLhwy;Z?g&Q@f&w;BFsX<4Ai$g+9D$1O~ zE-o22vC+6mbBi@rxS*mvuK$LZV#_Bqi8il{M%IHK?#=8U+=^cCR?Xa!Y!`)3{KL(I zHTV#>AZOQCZVu6QbT-5r81#XmGLh1nB_X3rA+d3XH zBCyY}T@D=iWm0fI@8cqCfhTa!u)#6sixjvl7Av5yQ6?oj@O~}{s7TzxB?~p261%x1 zzJ^m_noCtcG}~%+@1tYN?8!r$2P}F@pgPj@E$(HI-x$iqN*V5DQA;B?EoV=xnDD>l zt-_6Era$xu_c@Zm&2xG=fKGdT%4A~oOi2Jcpp(|!+|xI3n}+os3UMT?|LgSxW_ ztHQ_7{8mOO??yzoHCqpgvBp5CN;g9+g?R}O%R<-sH_95s>XM&YxEq0!4o9{%#v<^0 z7a>n`KlP8*nzQThyP*hNzY<*ke{qq*4o*q@#m};l!5FBx1ubrlYB|qkx15{ETGf9Z zEj*GFlP!ee(Qu4@?O~3oIt1x)h!P%klINp)+TkT6D6{NYjS8eaMHOF;_ z1#`9mG9)hIhFp|toQ%M;|(&2-$>qtI(mSm&?ln15pStgpKvM%kel^>$Lf`}7U6e?IrLf&Q=GEOWly zndy4Fr^~tiO=03L)cwAqpFx6SA!>G}pi9X1aed!H_$5e#3c4E|MPDL;O+yFz>-*9G zy(@^OPz1dTS^jFRQ}i!H_5Eoec?qRZKKN>cvwD0rV)}e%>-8Lbe~klH-^YMdNN)=0 zJc@ilz1MrL2CQ|peZquKn*!J>t{1*zCj3o0Jl&@zQbcD8AV(u6{0DXT8lVJ$(Th5K zqfaIHeA*Vb4Q94x&2zqbByMlZ0gih0$Z~h(ed|BUi61}qapGU|Rl*A#Ej$kmPKlH@kb4PQJGA3I|08XrYGn3l5I%az}|#m!p1+y25iDEyhpyt#ykklfAscLa#Tjp6ak?7o?BfIoUNJ zFv@xH4)}7*;+fuXcI4fmzLEF5@k4OlTWnjGH(GLekf3xH9i_MEg~r&%D)>y-qEYSO zlR3s5TN?a2xtAa$Sg!WbxpyE+cV%?n2ZHJhL*%L}r%i(c?4{)I+NVxW+Kiu#eKC4& z+~dePaAoxV?{}MRMZB_M3Ra+Ob9-z{(XB&`pz$+16SV!3 zMYi3xJweGJyjU4UkJ4lGBt6Bfqt@bv@Q7*9Av7udJm|=C3ws)-d6#n96Sfrg38y5Q zA9WA9J?f=sl?$*vP3SkrZO$-##+l5iz1(THZEGX8Zoipr$M&GtD+G8Ih?E4 zQ%as|)rwC}Ou=`SiVrs6IhwZIdm&SG2hyWyK_#ZC4x*zrOns+m`5OJDyCo4V%?Q zU2S_U`_%9@-S+nFY{`1ahd8i35VCL6KV-{1)7iu5@qx?Akj*B^=A-t^5!vR28JmNW z&G|jO1-S)ncAkAwA=qr;JYx&HG8*{Xzn_3_?!A{0;Z8rwvlYsl+{G6UpBSv!+*r_E zUD;dI4taEFY{twXlK<0_^Z@OpM_?^e)&c7f$(q$`9a$DRJK7)2_(Af!eyC9;$0C^T zNM&Sljdf_xXvS1w5tZAV+clso5*qinWsKz1WQ;QUF7G|4Yvi8TuCW*9%zS*vlDkX= zu|H22q^KyROLa5DFU_&J$*WLO%xxnix@zOFSyxLUnp@m!B(bP~|2Iu4-qrxIxc_5< z{Dr-VEI!>!A_iQZ-N=x*KoxyBR}-1@Izys&Gj2!v=F0RMgL>Fe7GxxAh7UHKkiB?j zmKWc?_i7K(*~(O(sI6?$+qOcy$C5`?DpHGbekW(v*j7X$Ip3>NS#n_weQogNNt<(F zjdH#>6035)-?_;jVkmS*8EO}2(K0rtm-v0NHD!isb8$&k`c@bhm`vrS zq7?&FhlG2Pb@`cq;Jyl#*l#UV7uUV6kv`nA3>9(YmE7Mn|uRz($ zLC#cMg?At-2}ormW7@I$x5al>tT2?4S3Y@RcmeZ&dlYb&@w#-MFDB-k(FO~4q5?-eW zG4A{oJV(MGfSi)&335pT&jx73?s0VpZw#Uc6+utI3TEzYq$TPAUqEb1_eh&1`BLa3 zVO<|B3+a(y^hZhFEXhww>}P}WH2NrMuKbIVd`UzI-yyMkBwW6~iia_IUV|1%{7jvz zr%S?rslN|!;{S^9ki2|P^{Ir*`$3NX7ZN_G4aq+NWAc0hEfOO4OZ`6uam7F2V-o&L zKcxb>x#11v)n>z%>cYYT6AIF0)g>j!P-ZUAHL(PD~^p(h9C@Lx6l3!w|Cfa~QdMQBGUuDj#Bfys zbos?)2yZPeG0w=((Pbzw=9}{oFrn1bt7=Ql`CFhjn?n6onKBpbG^2D=c~CkX%ph1( zX({*sC@K8(e6!h9yrtS)Kz=d)Kb{0oLNY9s#mu?zx}^LW?OZEz9m?nuAjo_fm(PzZ z>3*|G7L95RB2b|bnA@Su-zMown15!_9$s_l70}Zw- zg5a#z-z59D&%y{P&y!&?me($0q*sxH4W3qs$pIY!Ooffset + 1) > data->total_size) { + return -1; + } + uint8_t id = data->ptr[0]; + + if (id > 250) { + cmd->id = SyscallClose; + cmd->fd_index = (size_t)(id % 2); + data->offset += 1; + } else if (id > 128) { + if ((data->offset + 7) > data->total_size) { + return -1; + } + cmd->id = SyscallRead; + memcpy(&cmd->buf_ptr, &data->ptr[data->offset + 1], 3); + memcpy(&cmd->len_ptr, &data->ptr[data->offset + 4], 3); + data->offset += 7; + } else { + if ((data->offset + 7) > data->total_size) { + return -1; + } + cmd->id = SyscallWrite; + memcpy(&cmd->buf_ptr, &data->ptr[data->offset + 1], 3); + memcpy(&cmd->len_ptr, &data->ptr[data->offset + 4], 3); + data->offset += 7; + } + return 0; +} + +int random_read_write(uint64_t fds[2], size_t index) { + int err = 0; + uint8_t cmd_buf[4096] = {0}; + uint64_t cmd_len = sizeof(cmd_buf); + + err = ckb_load_witness(cmd_buf, &cmd_len, 0, index, CKB_SOURCE_INPUT); + CHECK(err); + Data data = {.ptr = cmd_buf, .total_size = cmd_len, .offset = 0}; + + while (true) { + Command cmd = {0}; + err = extract_command(&data, &cmd); + if (err) break; + if (cmd.id == SyscallRead) { + ckb_read(fds[CKB_STDIN], (void*)cmd.buf_ptr, (uint64_t*)cmd.len_ptr); + // ignore error + } else if (cmd.id == SyscallWrite) { + ckb_write(fds[CKB_STDOUT], (void*)cmd.buf_ptr, (uint64_t*)cmd.len_ptr); + // ignore error + } else if (cmd.id == SyscallClose) { + ckb_close(fds[cmd.fd_index]); + // ignore error + } else { + CHECK2(false, -1); + } + } +exit: + return err; +} + +int parent_entry() { + int err = 0; + uint64_t pid = 0; + const char* argv[] = {"", 0}; + uint64_t fds[2] = {0}; + + err = full_spawn(0, 1, argv, fds, &pid); + CHECK(err); + random_read_write(fds, 0); + + int8_t exit_code = 0; + err = ckb_wait(pid, &exit_code); + CHECK(err); + CHECK(exit_code); +exit: + return err; +} + +int child_entry() { + int err = 0; + uint64_t inherited_fds[2]; + size_t inherited_fds_length = 2; + err = ckb_inherited_file_descriptors(inherited_fds, &inherited_fds_length); + CHECK(err); + random_read_write(inherited_fds, 0); + +exit: + return err; +} + +int main(int argc, const char* argv[]) { + if (argc > 0) { + return child_entry(); + } else { + return parent_entry(); + } +} From 59a6ac16906f5628495e0c066b7205f5103b57dd Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 10 Apr 2024 17:09:04 +0800 Subject: [PATCH 059/135] Adjust cycles charge --- script/src/syscalls/close.rs | 3 ++- script/src/syscalls/inherited_fd.rs | 3 ++- script/src/syscalls/mod.rs | 1 + script/src/syscalls/pipe.rs | 3 ++- script/src/syscalls/read.rs | 3 ++- script/src/syscalls/spawn.rs | 5 ++++- script/src/syscalls/wait.rs | 3 ++- script/src/syscalls/write.rs | 3 ++- 8 files changed, 17 insertions(+), 7 deletions(-) diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs index d781ecdec1..94feefde38 100644 --- a/script/src/syscalls/close.rs +++ b/script/src/syscalls/close.rs @@ -1,4 +1,4 @@ -use crate::syscalls::CLOSE; +use crate::syscalls::{CLOSE, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Message, PipeId, VmId}; use ckb_vm::{ registers::{A0, A7}, @@ -28,6 +28,7 @@ impl Syscalls for Close { return Ok(false); } let pipe = PipeId(machine.registers()[A0].to_u64()); + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs index 91c12d155b..35f088a1c8 100644 --- a/script/src/syscalls/inherited_fd.rs +++ b/script/src/syscalls/inherited_fd.rs @@ -1,4 +1,4 @@ -use crate::syscalls::INHERITED_FD; +use crate::syscalls::{INHERITED_FD, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A7}, @@ -29,6 +29,7 @@ impl Syscalls for InheritedFd { } let buffer_addr = machine.registers()[A0].to_u64(); let length_addr = machine.registers()[A1].to_u64(); + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index 624b139b2d..f9c2a21e47 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -99,6 +99,7 @@ pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; pub const DEBUG_PAUSE: u64 = 2178; pub const SPAWN_EXTRA_CYCLES_BASE: u64 = 100_000; +pub const SPAWN_YIELD_CYCLES_BASE: u64 = 800; #[derive(Debug, PartialEq, Clone, Copy, Eq)] enum CellField { diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs index 09b6281007..ee24540acc 100644 --- a/script/src/syscalls/pipe.rs +++ b/script/src/syscalls/pipe.rs @@ -1,4 +1,4 @@ -use crate::syscalls::PIPE; +use crate::syscalls::{PIPE, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Message, PipeArgs, VmId}; use ckb_vm::{ registers::{A0, A7}, @@ -29,6 +29,7 @@ impl Syscalls for Pipe { } let pipe1_addr = machine.registers()[A0].to_u64(); let pipe2_addr = pipe1_addr.wrapping_add(8); + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 9dd98406b3..56e0b764fe 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,5 +1,5 @@ use crate::cost_model::transferred_byte_cycles; -use crate::syscalls::{INVALID_PIPE, READ}; +use crate::syscalls::{INVALID_PIPE, READ, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, @@ -43,6 +43,7 @@ impl Syscalls for Read { machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); return Ok(true); } + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; machine.add_cycles_no_checking(transferred_byte_cycles(length))?; self.message_box .lock() diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 1ee2200275..157de2bd79 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,6 +1,8 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::utils::load_c_string; -use crate::syscalls::{INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE}; +use crate::syscalls::{ + INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, +}; use crate::types::{DataPieceId, Message, PipeId, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_vm::{ @@ -141,6 +143,7 @@ where } } machine.add_cycles_no_checking(SPAWN_EXTRA_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; machine.add_cycles_no_checking(transferred_byte_cycles(full_length))?; self.message_box .lock() diff --git a/script/src/syscalls/wait.rs b/script/src/syscalls/wait.rs index 14938d1aab..2639d809cd 100644 --- a/script/src/syscalls/wait.rs +++ b/script/src/syscalls/wait.rs @@ -1,4 +1,4 @@ -use crate::syscalls::WAIT; +use crate::syscalls::{SPAWN_YIELD_CYCLES_BASE, WAIT}; use crate::types::{Message, VmId, WaitArgs}; use ckb_vm::{ registers::{A0, A1, A7}, @@ -29,6 +29,7 @@ impl Syscalls for Wait { } let target_id = machine.registers()[A0].to_u64(); let exit_code_addr = machine.registers()[A1].to_u64(); + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index e2cb1e536b..87f78bf82b 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,5 +1,5 @@ use crate::cost_model::transferred_byte_cycles; -use crate::syscalls::{INVALID_PIPE, WRITE}; +use crate::syscalls::{INVALID_PIPE, SPAWN_YIELD_CYCLES_BASE, WRITE}; use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, @@ -43,6 +43,7 @@ impl Syscalls for Write { machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); return Ok(true); } + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; machine.add_cycles_no_checking(transferred_byte_cycles(length))?; self.message_box .lock() From 3a3ff6b5ac6484a33028b2ea68cd121eaaf595aa Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 11 Apr 2024 15:03:26 +0800 Subject: [PATCH 060/135] Adjust cycles charge --- script/src/scheduler.rs | 21 ++++++++++----------- script/src/syscalls/read.rs | 2 -- script/src/syscalls/spawn.rs | 2 -- script/src/syscalls/write.rs | 2 -- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 7675a0efa9..38055f5ff3 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -610,24 +610,23 @@ where let copiable = std::cmp::min(fillable, consumable); // Actual data copying - let data = self - .instantiated - .get_mut(&write_vm_id) - .unwrap() - .1 + let (_, write_machine) = self.instantiated.get_mut(&write_vm_id).unwrap(); + write_machine + .machine + .add_cycles_no_checking(transferred_byte_cycles(copiable))?; + let data = write_machine .machine .memory_mut() .load_bytes(write_buffer_addr.wrapping_add(consumed), copiable)?; - self.instantiated - .get_mut(&read_vm_id) - .unwrap() - .1 + let (_, read_machine) = self.instantiated.get_mut(&read_vm_id).unwrap(); + read_machine + .machine + .add_cycles_no_checking(transferred_byte_cycles(copiable))?; + read_machine .machine .memory_mut() .store_bytes(read_buffer_addr, &data)?; - // Read syscall terminates as soon as some data are filled - let (_, read_machine) = self.instantiated.get_mut(&read_vm_id).unwrap(); read_machine .machine .memory_mut() diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 56e0b764fe..e5097c0e30 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,4 +1,3 @@ -use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{INVALID_PIPE, READ, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ @@ -44,7 +43,6 @@ impl Syscalls for Read { return Ok(true); } machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; - machine.add_cycles_no_checking(transferred_byte_cycles(length))?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 157de2bd79..91f81fe180 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,4 +1,3 @@ -use crate::cost_model::transferred_byte_cycles; use crate::syscalls::utils::load_c_string; use crate::syscalls::{ INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, @@ -144,7 +143,6 @@ where } machine.add_cycles_no_checking(SPAWN_EXTRA_CYCLES_BASE)?; machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; - machine.add_cycles_no_checking(transferred_byte_cycles(full_length))?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index 87f78bf82b..5133f17c53 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,4 +1,3 @@ -use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{INVALID_PIPE, SPAWN_YIELD_CYCLES_BASE, WRITE}; use crate::types::{Message, PipeId, PipeIoArgs, VmId}; use ckb_vm::{ @@ -44,7 +43,6 @@ impl Syscalls for Write { return Ok(true); } machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; - machine.add_cycles_no_checking(transferred_byte_cycles(length))?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? From 7517bf531176d3b1fbbb28e5852975506cbd8bc3 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 11 Apr 2024 16:21:50 +0800 Subject: [PATCH 061/135] Use yield error --- script/Cargo.toml | 2 +- script/src/scheduler.rs | 2 +- script/src/syscalls/close.rs | 2 +- script/src/syscalls/inherited_fd.rs | 2 +- script/src/syscalls/pipe.rs | 2 +- script/src/syscalls/read.rs | 2 +- script/src/syscalls/spawn.rs | 2 +- script/src/syscalls/wait.rs | 2 +- script/src/syscalls/write.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/script/Cargo.toml b/script/Cargo.toml index 005ee9f1b4..701299de1b 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,7 +22,7 @@ ckb-traits = { path = "../traits", version = "= 0.115.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.115.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.115.0-pre" } -ckb-vm = { git = "https://github.com/nervosnetwork/ckb-vm", branch = "release-0.24", default-features = false } +ckb-vm = { git = "https://github.com/libraries/ckb-vm", branch = "release-0.24-spawn", default-features = false } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.115.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 38055f5ff3..471b834150 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -294,7 +294,7 @@ where } Ok(consumed_cycles) } - Err(Error::External(msg)) if msg == "YIELD" => Ok(consumed_cycles), + Err(Error::Yield) => Ok(consumed_cycles), Err(e) => Err(e), } } diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs index 94feefde38..2cd454576a 100644 --- a/script/src/syscalls/close.rs +++ b/script/src/syscalls/close.rs @@ -33,6 +33,6 @@ impl Syscalls for Close { .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? .push(Message::Close(self.id, pipe)); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs index 35f088a1c8..0fd45aa1f7 100644 --- a/script/src/syscalls/inherited_fd.rs +++ b/script/src/syscalls/inherited_fd.rs @@ -42,6 +42,6 @@ impl Syscalls for InheritedFd { length_addr, }, )); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs index ee24540acc..d7834b1dce 100644 --- a/script/src/syscalls/pipe.rs +++ b/script/src/syscalls/pipe.rs @@ -40,6 +40,6 @@ impl Syscalls for Pipe { pipe2_addr, }, )); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index e5097c0e30..c96107d39e 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -55,6 +55,6 @@ impl Syscalls for Read { length_addr, }, )); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 91f81fe180..41d150d7a6 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -157,6 +157,6 @@ where process_id_addr, }, )); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } diff --git a/script/src/syscalls/wait.rs b/script/src/syscalls/wait.rs index 2639d809cd..c9a49566aa 100644 --- a/script/src/syscalls/wait.rs +++ b/script/src/syscalls/wait.rs @@ -40,6 +40,6 @@ impl Syscalls for Wait { exit_code_addr, }, )); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index 5133f17c53..07b1da81a6 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -55,6 +55,6 @@ impl Syscalls for Write { length_addr, }, )); - Err(VMError::External("YIELD".to_string())) + Err(VMError::Yield) } } From 8ff30a388ae2822e94d34033d30ba4107cee106a Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 11 Apr 2024 17:41:23 +0800 Subject: [PATCH 062/135] Replace unwrap with error --- Cargo.lock | 4 +- script/src/scheduler.rs | 130 ++++++++++++++++++++++++++++++---------- 2 files changed, 101 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f53634f3f2..08612824dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1795,7 +1795,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#b71f5d96798cc049f9d6dee1da5879e27ae583b0" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#6fd0f8c4c9bf41382d1de09d900ae7596c37ef4a" dependencies = [ "byteorder", "bytes", @@ -1812,7 +1812,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/nervosnetwork/ckb-vm?branch=release-0.24#b71f5d96798cc049f9d6dee1da5879e27ae583b0" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#6fd0f8c4c9bf41382d1de09d900ae7596c37ef4a" dependencies = [ "paste", ] diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 471b834150..3cd86f22d6 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -145,7 +145,10 @@ where self.suspend_vm(&id)?; } for (id, state) in self.states { - let snapshot = self.suspended.remove(&id).unwrap(); + let snapshot = self + .suspended + .remove(&id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; vms.push((id, state, snapshot)); } Ok(FullSuspendedState { @@ -215,16 +218,15 @@ where .filter(|(_, state)| matches!(state, VmState::Runnable)) .map(|(id, _)| *id) .next(); - if vm_id_to_run.is_none() { - return Err(Error::Unexpected( - "A deadlock situation has been reached!".to_string(), - )); - } - let vm_id_to_run = vm_id_to_run.unwrap(); - // log::debug!("Running VM {}", vm_id_to_run); + let vm_id_to_run = vm_id_to_run.ok_or_else(|| { + Error::Unexpected("A deadlock situation has been reached!".to_string()) + })?; let (result, consumed_cycles) = { self.ensure_vms_instantiated(&[vm_id_to_run])?; - let (context, machine) = self.instantiated.get_mut(&vm_id_to_run).unwrap(); + let (context, machine) = self + .instantiated + .get_mut(&vm_id_to_run) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; context.set_base_cycles(self.total_cycles); set_vm_max_cycles(machine, limit_cycles); machine.machine.set_pause(pause); @@ -277,7 +279,10 @@ where // runnable state. for (vm_id, exit_code_addr) in joining_vms { self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; machine .machine .memory_mut() @@ -309,7 +314,10 @@ where for pipe in &args.pipes { if !(self.pipes.contains_key(pipe) && (self.pipes[pipe] == vm_id)) { self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine.machine.set_register(A0, INVALID_PIPE as u64); pipes_valid = false; break; @@ -321,7 +329,10 @@ where if self.suspended.len() + self.instantiated.len() > self.max_vms_count as usize { self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; machine.machine.set_register(A0, MAX_VMS_SPAWNED as u64); continue; } @@ -342,7 +353,10 @@ where self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; machine .machine .memory_mut() @@ -354,7 +368,10 @@ where if let Some(exit_code) = self.terminated_vms.get(&args.target_id).copied() { self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine .machine .memory_mut() @@ -368,7 +385,10 @@ where if !self.states.contains_key(&args.target_id) { self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine.machine.set_register(A0, WAIT_FAILURE as u64); } continue; @@ -384,7 +404,10 @@ where } Message::Pipe(vm_id, args) => { if self.next_pipe_slot - FIRST_PIPE_SLOT >= MAX_PIPE { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; machine.machine.set_register(A0, MAX_PIPE_CREATED as u64); continue; } @@ -397,7 +420,10 @@ where self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; machine .machine .memory_mut() @@ -413,7 +439,10 @@ where if !(self.pipes.contains_key(&args.pipe) && (self.pipes[&args.pipe] == vm_id)) { self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine.machine.set_register(A0, INVALID_PIPE as u64); } continue; @@ -421,7 +450,10 @@ where if !self.pipes.contains_key(&args.pipe.other_pipe()) { self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine.machine.set_register(A0, OTHER_END_CLOSED as u64); } continue; @@ -441,7 +473,10 @@ where if !(self.pipes.contains_key(&args.pipe) && (self.pipes[&args.pipe] == vm_id)) { self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine.machine.set_register(A0, INVALID_PIPE as u64); } continue; @@ -449,7 +484,10 @@ where if !self.pipes.contains_key(&args.pipe.other_pipe()) { self.ensure_vms_instantiated(&[vm_id])?; { - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = + self.instantiated.get_mut(&vm_id).ok_or_else(|| { + Error::Unexpected("Unable to find VM Id".to_string()) + })?; machine.machine.set_register(A0, OTHER_END_CLOSED as u64); } continue; @@ -468,7 +506,10 @@ where } Message::InheritedFileDescriptor(vm_id, args) => { self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; let PipeIoArgs { buffer_addr, length_addr, @@ -514,7 +555,10 @@ where } Message::Close(vm_id, fd) => { self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; if self.pipes.get(&fd) != Some(&vm_id) { machine.machine.set_register(A0, INVALID_PIPE as u64); } else { @@ -556,7 +600,10 @@ where match self.states[&vm_id].clone() { VmState::WaitForRead { length_addr, .. } => { self.ensure_vms_instantiated(&[vm_id])?; - let (_, read_machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, read_machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; read_machine .machine .memory_mut() @@ -570,7 +617,10 @@ where .. } => { self.ensure_vms_instantiated(&[vm_id])?; - let (_, write_machine) = self.instantiated.get_mut(&vm_id).unwrap(); + let (_, write_machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; write_machine .machine .memory_mut() @@ -610,7 +660,10 @@ where let copiable = std::cmp::min(fillable, consumable); // Actual data copying - let (_, write_machine) = self.instantiated.get_mut(&write_vm_id).unwrap(); + let (_, write_machine) = self + .instantiated + .get_mut(&write_vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; write_machine .machine .add_cycles_no_checking(transferred_byte_cycles(copiable))?; @@ -618,7 +671,10 @@ where .machine .memory_mut() .load_bytes(write_buffer_addr.wrapping_add(consumed), copiable)?; - let (_, read_machine) = self.instantiated.get_mut(&read_vm_id).unwrap(); + let (_, read_machine) = self + .instantiated + .get_mut(&read_vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; read_machine .machine .add_cycles_no_checking(transferred_byte_cycles(copiable))?; @@ -639,7 +695,10 @@ where consumed += copiable; if consumed == write_length { // Write VM has fulfilled its write request - let (_, write_machine) = self.instantiated.get_mut(&write_vm_id).unwrap(); + let (_, write_machine) = self + .instantiated + .get_mut(&write_vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; write_machine .machine .memory_mut() @@ -680,7 +739,9 @@ where .copied() .collect(); while (!uninstantiated_ids.is_empty()) && (self.instantiated.len() < MAX_INSTANTIATED_VMS) { - let id = uninstantiated_ids.pop().unwrap(); + let id = uninstantiated_ids + .pop() + .ok_or_else(|| Error::Unexpected("Map should not be empty".to_string()))?; self.resume_vm(&id)?; } @@ -728,7 +789,10 @@ where id ))); } - let (context, machine) = self.instantiated.get_mut(id).unwrap(); + let (context, machine) = self + .instantiated + .get_mut(id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; let snapshot = { let sc = context.snapshot2_context().lock().expect("lock"); sc.make_snapshot(&mut machine.machine)? @@ -748,7 +812,11 @@ where // Newly booted VM will be instantiated by default while self.instantiated.len() >= MAX_INSTANTIATED_VMS { // Instantiated is a BTreeMap, first_entry will maintain key order - let id = *self.instantiated.first_entry().unwrap().key(); + let id = *self + .instantiated + .first_entry() + .ok_or_else(|| Error::Unexpected("Map should not be empty".to_string()))? + .key(); self.suspend_vm(&id)?; } From 70f93618390b62f2647a6e00ed6e798b2351561b Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 11 Apr 2024 18:39:50 +0800 Subject: [PATCH 063/135] Fix clippy error: this loop never actually loops --- script/src/verify.rs | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index f09e18f791..8b66327586 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1046,31 +1046,28 @@ where _ => ScriptError::VMInternalError(error), }; let previous_cycles = scheduler.consumed_cycles(); - loop { - let res = scheduler.run(RunMode::LimitCycles(max_cycles)); - match res { - Ok((exit_code, cycles)) => { - if exit_code == 0 { - return Ok(ChunkState::Completed( - cycles, - scheduler.consumed_cycles() - previous_cycles, - )); - } else { - return Err(ScriptError::validation_failure( - &script_group.script, - exit_code, - )); - } + let res = scheduler.run(RunMode::LimitCycles(max_cycles)); + match res { + Ok((exit_code, cycles)) => { + if exit_code == 0 { + return Ok(ChunkState::Completed( + cycles, + scheduler.consumed_cycles() - previous_cycles, + )); + } else { + return Err(ScriptError::validation_failure( + &script_group.script, + exit_code, + )); } - Err(error) => match error { - VMInternalError::CyclesExceeded | VMInternalError::Pause => { - let snapshot = scheduler.suspend().map_err(map_vm_internal_error)?; - return Ok(ChunkState::suspended(snapshot)); - } - - _ => return Err(map_vm_internal_error(error)), - }, } + Err(error) => match error { + VMInternalError::CyclesExceeded | VMInternalError::Pause => { + let snapshot = scheduler.suspend().map_err(map_vm_internal_error)?; + return Ok(ChunkState::suspended(snapshot)); + } + _ => return Err(map_vm_internal_error(error)), + }, } } From dd261e0e727b5ed28322ee5df4f6549123edaa8e Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 11 Apr 2024 18:49:08 +0800 Subject: [PATCH 064/135] Fix clippy: unneeded return statement --- script/src/verify.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index 8b66327586..64275c0ce8 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1050,23 +1050,23 @@ where match res { Ok((exit_code, cycles)) => { if exit_code == 0 { - return Ok(ChunkState::Completed( + Ok(ChunkState::Completed( cycles, scheduler.consumed_cycles() - previous_cycles, - )); + )) } else { - return Err(ScriptError::validation_failure( + Err(ScriptError::validation_failure( &script_group.script, exit_code, - )); + )) } } Err(error) => match error { VMInternalError::CyclesExceeded | VMInternalError::Pause => { let snapshot = scheduler.suspend().map_err(map_vm_internal_error)?; - return Ok(ChunkState::suspended(snapshot)); + Ok(ChunkState::suspended(snapshot)) } - _ => return Err(map_vm_internal_error(error)), + _ => Err(map_vm_internal_error(error)), }, } } From a8a30e4d161cba278a2230d8600d5cad8872bc12 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 12 Apr 2024 15:35:15 +0800 Subject: [PATCH 065/135] Remove logs --- script/src/scheduler.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 3cd86f22d6..46ccc2f9e7 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -246,12 +246,9 @@ where // 3. Process message box, update VM states accordingly self.process_message_box()?; assert!(self.message_box.lock().expect("lock").is_empty()); - // log::debug!("VM states: {:?}", self.states); - // log::debug!("Pipes and owners: {:?}", self.pipes); // 4. If the VM terminates, update VMs in join state, also closes its pipes match result { Ok(code) => { - // log::debug!("VM {} terminates with code {}", vm_id_to_run, code); self.terminated_vms.insert(vm_id_to_run, code); // When root VM terminates, the execution stops immediately, we will purge // all non-root VMs, and only keep root VM in states. @@ -344,11 +341,6 @@ where } // Here we keep the original version of file descriptors. // If one fd is moved afterward, this inherited file descriptors doesn't change. - // log::info!( - // "VmId = {} with Inherited file descriptor {:?}", - // spawned_vm_id, - // args.pipes - // ); self.inherited_fd.insert(spawned_vm_id, args.pipes.clone()); self.ensure_vms_instantiated(&[vm_id])?; @@ -413,8 +405,6 @@ where } let (p1, p2, slot) = PipeId::create(self.next_pipe_slot); self.next_pipe_slot = slot; - // log::debug!("VM {} creates pipes ({}, {})", vm_id, p1.0, p2.0); - self.pipes.insert(p1, vm_id); self.pipes.insert(p2, vm_id); @@ -782,7 +772,6 @@ where // Suspend an instantiated VM fn suspend_vm(&mut self, id: &VmId) -> Result<(), Error> { - // log::debug!("Suspending VM: {}", id); if !self.instantiated.contains_key(id) { return Err(Error::Unexpected(format!( "VM {:?} is not instantiated!", @@ -845,7 +834,6 @@ where // impls here again. Ideally, this scheduler package should be merged with ckb-script, // or simply replace ckb-script. That way, the quirks here will be eliminated. let version = self.script_version; - // log::debug!("Creating VM {} using version {:?}", id, version); let core_machine = CoreMachineType::new( version.vm_isa(), version.vm_version(), From a71043fc92fe1a947908c6a5b5bdc08f5b5c5199 Mon Sep 17 00:00:00 2001 From: joii2020 <87224197+joii2020@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:26:49 +0800 Subject: [PATCH 066/135] Add testcase about spawn (#19) * Add testcase: chech max pipe limits on child * Optimize test case max_fd_limits * Fix CI error * Add testcase about spawn * Add testcase: Add some code that is not covered --- .../tests/ckb_latest/features_since_v2023.rs | 37 ++++ script/testdata/spawn_cases | Bin 12392 -> 15136 bytes script/testdata/spawn_cases.c | 204 ++++++++++++++++++ script/testdata/spawn_dag.rs | 8 + 4 files changed, 249 insertions(+) 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 e7a85ab28a..58df15c753 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -103,6 +103,12 @@ fn check_spawn_max_vms_count() { assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } +#[test] +fn check_spawn_max_pipe_limits() { + let result = simple_spawn_test("testdata/spawn_cases", &[11]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + #[test] fn check_vm_version() { let script_version = SCRIPT_VERSION; @@ -1178,3 +1184,34 @@ proptest! { assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); } } + +#[test] +fn check_spawn_close_invalid_fd() { + let result = simple_spawn_test("testdata/spawn_cases", &[12]); + println!("--- err: {:?}", result); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_write_closed_fd() { + let result = simple_spawn_test("testdata/spawn_cases", &[13]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_pid() { + let result = simple_spawn_test("testdata/spawn_cases", &[14]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_offset_out_of_bound() { + let result = simple_spawn_test("testdata/spawn_cases", &[15]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_length_out_of_bound() { + let result = simple_spawn_test("testdata/spawn_cases", &[16]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 4532307917cf25ff68c1e8fd850d6e4369efc016..69baa51957699054f0b692e696b72ed712edd4fe 100755 GIT binary patch delta 6008 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 ANB{r; delta 3305 zcmZu!4NM!?9e;P&hcOTvOaW6T5GW*dR=yg*cr7$hP2xxlCYel0$6^)}8cG5bNa{$b zndOhRS_aKar7h|TwK8|j*1-m=m#mYS)~@rG6*je+x{BlyF~%Y~o0ha8rKIoc;xpx> z=XdY-|G)p|@7?)EPb}Dnb2CqAIDoIm$S(lfOJ6irSDLobr8EOAU1MDV4O23c*U;Uj znitR3Z4w)A*mpaWZSKKn!IbIOSFa>#t(|qtF!_ErR5$ZFwYq)cvLa8&ZFE$x?rM)5 zDP69-eOZJ`PhXxN`g}*>qB@`JgK4Q-CMwgut;nbV0RG_m7rf;gfNO}xhR#l$)AsYG zNV~Nidc9BSl-{G!SpE-#_Cl}VXhVLnB;eBt<$_H9!aJb@y~^%i{Roz(K4?)*2l`O( z8W7XmuTX-mi>h4tx=}3b;Fr&f=Ed)yr8RW=8D&RnFHC-J?aQZiaF6Z@{!kcR(AoH=PvITib{9@Rh$5Ovi>E*IzYjwg zzqMZ{6r{&-&B86)0FkU9i74CAJ-=eJh7a^cI-uX*W%Qo|+FY-Nv((-8EeB%3MSj&S zy62*?L;wErJKiVj7K#i@peTI_Y@T>EOUbz+jtJ@jaU=|<(y}!D17rBUwgGyT$55eW zq?B<{R`$0y(5@E-LJ&GYZa`#Kb=Rc zYv>R53(gc7>zaw2mN!vvJ=}lDTeU5ZlD1*tQ4YA6t! zY+`1m4;a3im|6FKrObwPv#7nkxqyf|Ip^JTIPDgAeb3>KU(;es~VKa{IS~ zs93*d^eD6>#q0{v`($Bz5#acs7fx--a^cq<7R9nt7Lyblub-nYPD%qT0Xd05lwFl; z&|{?4l6L_nl<4}4(K8T6j$=b(M$ga4UDFk#=MNzT3C`bT0zscvMRvFr7!SqzX``q1 z!;3!b3_WaBaaNW6>pp7aW25Jx5H?(Y*62}^yOEcT9zBtU!$wa9!CZegdQ$Ga#748@ zmWKZ6w55koouaQHMnV6(JqB7RE<;#!`#H-EyAp8_|8~bTmtb|-wwBn~Cv<)7RXkfJ zXvS(EiC^UBqT-=Y>rc4iM)W$PCviM0?y@Q3Y-tM-3*yM#(=ERZpKfsv!kMz+{b!3g zfJY`81~f|0u%pq5Mn4+QqVXIWcOKxt-VzQxhQ<}NejAPV(fEwrud!J`^0X3oqx^gD z@d`s;Gg_{{l0XtL)xc8~H(NP!%TyFp(Sar{Sh{PfPuzL};h6wg&!xDHiO(?ncoqfT zV|WlQRpxMif?FTXaeY8+^2jX{qBXw$g9f%aoI&vbK>_%j;l@;oH?!E*82(5$#b=l~ zyu@~npeo_3f#F3I&jj{DitJ+oGrazAjvnPtwq3+}=z5F%0?-FDcII$?xNB#Q>kXzO z{TRQI%sYN0q|x*A@tJ_vWzbi!ZM*wjY`y1EYa^|YNl4pU54*lBtbmRBfXL2W_$XfewP zPq59bgZ5f&ro`Fi5-LT1s@=7vYKc3hZSZn!9gn6vXxg_8n$30hJ;OdrRE#M2D`XQq bW8RT6xPw}G0{+ollk(9+bY+FR%=updaIs*Z diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index e11ba26894..24194c8d35 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -334,6 +334,185 @@ int child_max_vms_count() { return err; } +int parent_max_pipe_limits() { + const char* argv[2] = {"", 0}; + int err = 0; + uint64_t fd[2] = {0}; + for (int i = 0; i < 16; i++) { + err = ckb_pipe(fd); + CHECK(err); + } + err = simple_spawn_args(0, 1, argv); +exit: + return err; +} + +int child_max_pipe_limits() { + int err = 0; + uint64_t pipe[2] = {0}; + for (int i = 0; i < 16; i++) { + err = ckb_pipe(pipe); + CHECK(err); + } + // Create up to 64 pipes. + err = ckb_pipe(pipe); + err = err - 9; + +exit: + return err; +} + +int parent_close_invalid_fd() { + uint64_t fds[2] = {0}; + int err = ckb_pipe(fds); + CHECK(err); + + err = ckb_close(fds[CKB_STDIN] + 32); + CHECK2(err == 6, -1); + + err = ckb_close(fds[CKB_STDIN]); + CHECK(err); + err = ckb_close(fds[CKB_STDOUT]); + CHECK(err); + + err = ckb_close(fds[CKB_STDIN]); + CHECK2(err == 6, -1); + err = ckb_close(fds[CKB_STDOUT]); + CHECK2(err == 6, -1); + + err = 0; +exit: + return err; +} + +int parent_write_closed_fd(uint64_t* pid) { + int err = 0; + const char* argv[] = {"", 0}; + uint64_t fds[2] = {0}; + err = full_spawn(0, 1, argv, fds, pid); + CHECK(err); + + // int exit_code = 0; + uint8_t block[7] = {1, 2, 3, 4, 5, 6, 7}; + size_t actual_length = 0; + err = read_exact(fds[CKB_STDIN], block, sizeof(block), &actual_length); + CHECK(err); + err = ckb_close(fds[CKB_STDIN]); + CHECK(err); + + err = ckb_close(fds[CKB_STDOUT]); +exit: + return err; +} + +int child_write_closed_fd() { + int err = 0; + uint64_t inherited_fds[2]; + size_t inherited_fds_length = 2; + err = ckb_inherited_file_descriptors(inherited_fds, &inherited_fds_length); + CHECK(err); + + uint8_t block[7] = {0}; + size_t actual_length = 0; + err = write_exact(inherited_fds[CKB_STDOUT], block, sizeof(block), + &actual_length); + CHECK(err); + err = write_exact(inherited_fds[CKB_STDOUT], block, sizeof(block), + &actual_length); + CHECK(err); + + ckb_close(inherited_fds[CKB_STDIN]); + ckb_close(inherited_fds[CKB_STDOUT]); + +exit: + return err; +} + +int parent_pid(uint64_t* pid) { + int err = 0; + + uint64_t cur_pid = ckb_process_id(); + + uint64_t pid_c1 = 0; + const char* argv[] = {"", 0}; + uint64_t fds_1[2] = {0}; + err = full_spawn(0, 1, argv, fds_1, &pid_c1); + CHECK2(pid_c1 != cur_pid, -1); + + uint64_t pid_c2 = 0; + uint64_t fds_2[2] = {0}; + err = full_spawn(0, 1, argv, fds_2, &pid_c2); + CHECK(err); + CHECK2(pid_c2 != cur_pid, -1); + + uint64_t child_pid_1 = 0; + size_t actual_length = 0; + err = read_exact(fds_1[CKB_STDIN], &child_pid_1, sizeof(child_pid_1), + &actual_length); + CHECK(err); + CHECK2(child_pid_1 == pid_c1, -1); + + uint64_t child_pid_2 = 0; + err = read_exact(fds_2[CKB_STDIN], &child_pid_2, sizeof(child_pid_2), + &actual_length); + CHECK(err); + CHECK2(child_pid_2 == pid_c2, -1); + +exit: + return err; +} + +int child_pid() { + uint64_t pid = ckb_process_id(); + + int err = 0; + uint64_t fds[2] = {0}; + uint64_t fds_length = 2; + err = ckb_inherited_file_descriptors(fds, &fds_length); + CHECK(err); + + // send pid + size_t actual_length = 0; + err = write_exact(fds[CKB_STDOUT], &pid, sizeof(pid), &actual_length); + CHECK(err); + +exit: + return err; +} + +int parent_spawn_offset_out_of_bound(uint64_t* pid) { + int err = 0; + + const char* argv[] = {"", 0}; + spawn_args_t spgs = { + .argc = 1, .argv = argv, .process_id = pid, .inherited_fds = NULL}; + uint64_t offset = 1024 * 1024 * 1024 * 1; + uint64_t length = 0; + uint64_t bounds = (offset << 32) + length; + err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, bounds, &spgs); + CHECK2(err == 3, -1); // SLICE_OUT_OF_BOUND + err = 0; +exit: + return err; +} + +int parent_spawn_length_out_of_bound(uint64_t* pid) { + int err = 0; + + const char* argv[] = {"", 0}; + spawn_args_t spgs = { + .argc = 1, .argv = argv, .process_id = pid, .inherited_fds = NULL}; + uint64_t offset = 1024 * 14; + uint64_t length = 1024; + uint64_t bounds = (offset << 32) + length; + + err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, bounds, &spgs); + CHECK2(err == 3, -1); // SLICE_OUT_OF_BOUND + err = 0; +exit: + return err; +} + int parent_entry(int case_id) { int err = 0; uint64_t pid = 0; @@ -358,6 +537,19 @@ int parent_entry(int case_id) { } else if (case_id == 10) { err = parent_max_vms_count(&pid); return err; + } else if (case_id == 11) { + err = parent_max_pipe_limits(&pid); + return err; + } else if (case_id == 12) { + return parent_close_invalid_fd(&pid); + } else if (case_id == 13) { + return parent_write_closed_fd(&pid); + } else if (case_id == 14) { + return parent_pid(&pid); + } else if (case_id == 15) { + return parent_spawn_offset_out_of_bound(&pid); + } else if (case_id == 16) { + return parent_spawn_length_out_of_bound(&pid); } else { CHECK2(false, -2); } @@ -392,6 +584,18 @@ int child_entry(int case_id) { return child_read_then_close(); } else if (case_id == 10) { return child_max_vms_count(); + } else if (case_id == 11) { + return child_max_pipe_limits(); + } else if (case_id == 12) { + return 0; + } else if (case_id == 13) { + return child_write_closed_fd(); + } else if (case_id == 14) { + return child_pid(); + } else if (case_id == 15) { + return 0; + // } else if (case_id == 16) { + // return 0; } else { return -1; } diff --git a/script/testdata/spawn_dag.rs b/script/testdata/spawn_dag.rs index cb9e52397b..f44b5189a1 100644 --- a/script/testdata/spawn_dag.rs +++ b/script/testdata/spawn_dag.rs @@ -1,5 +1,13 @@ // Generated by Molecule 0.7.5 +#![allow(clippy::needless_lifetimes)] +#![allow(clippy::needless_borrow)] +#![allow(clippy::wrong_self_convention)] +#![allow(clippy::if_same_then_else)] +#![allow(clippy::derivable_impls)] +#![allow(clippy::useless_conversion)] +#![allow(clippy::write_literal)] + use molecule::prelude::*; #[derive(Clone)] From 380eb9afea999c6aa333f261495691b34392f61f Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 13:34:18 +0800 Subject: [PATCH 067/135] Adjust spawn_cases --- script/testdata/spawn_cases | Bin 15136 -> 15136 bytes script/testdata/spawn_cases.c | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 69baa51957699054f0b692e696b72ed712edd4fe..3cf927f99d8f76d8a2495fd21fce1db3b223319a 100755 GIT binary patch delta 93 zcmZ2bwxDc60_O_@1~7QBF;iZEF>!OJK&u?%!Oi^oR~aWiFi6~6_+s)*qveb* pHai;ogE$jS`hldPsXkCB&{Us=QDSnVWjRpjr=>mPugR8H&jBfYBJThI delta 93 zcmZ2bwxDc60_PJ01~7QCF;iZEQE_vpK&u?%-p%~_R~aY2Fo@agU>L#3_+;`-qvecG pHai;ogE$jS`hldPsXkCB&{Us=QDkzXWjRpjr=>mPx5<`P&jAs2B8LC~ diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index 24194c8d35..6cc9615a1f 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -594,8 +594,8 @@ int child_entry(int case_id) { return child_pid(); } else if (case_id == 15) { return 0; - // } else if (case_id == 16) { - // return 0; + } else if (case_id == 16) { + return 0; } else { return -1; } From 0f7743e4149525ad239eb20a5bea6107d0f896ad Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 14:47:43 +0800 Subject: [PATCH 068/135] Rename PipeId to Fd --- script/src/scheduler.rs | 130 +++++++++--------- script/src/syscalls/close.rs | 6 +- script/src/syscalls/inherited_fd.rs | 6 +- script/src/syscalls/mod.rs | 4 +- script/src/syscalls/pipe.rs | 12 +- script/src/syscalls/read.rs | 16 +-- script/src/syscalls/spawn.rs | 24 ++-- script/src/syscalls/write.rs | 16 +-- script/src/types.rs | 46 +++---- .../tests/ckb_latest/features_since_v2023.rs | 10 +- script/testdata/Makefile | 4 +- .../{spawn_pipe_limits => spawn_fd_limits} | Bin 4528 -> 4512 bytes ...{spawn_pipe_limits.c => spawn_fd_limits.c} | 0 13 files changed, 134 insertions(+), 140 deletions(-) rename script/testdata/{spawn_pipe_limits => spawn_fd_limits} (67%) rename script/testdata/{spawn_pipe_limits.c => spawn_fd_limits.c} (100%) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 46ccc2f9e7..9151c90aaa 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,6 +1,6 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, INVALID_PIPE, MAX_PIPE_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, + INDEX_OUT_OF_BOUND, INVALID_FD, MAX_FD_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE, }; use crate::types::MachineContext; @@ -8,8 +8,8 @@ use crate::verify::TransactionScriptsSyscallsGenerator; use crate::ScriptVersion; use crate::types::{ - set_vm_max_cycles, CoreMachineType, DataPieceId, FullSuspendedState, Machine, Message, PipeId, - PipeIoArgs, RunMode, TxData, VmId, VmState, FIRST_PIPE_SLOT, FIRST_VM_ID, + set_vm_max_cycles, CoreMachineType, DataPieceId, Fd, FdArgs, FullSuspendedState, Machine, + Message, RunMode, TxData, VmId, VmState, FIRST_FD_SLOT, FIRST_VM_ID, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; @@ -33,7 +33,7 @@ use std::{ pub const ROOT_VM_ID: VmId = FIRST_VM_ID; pub const MAX_VMS_COUNT: u64 = 16; pub const MAX_INSTANTIATED_VMS: usize = 4; -pub const MAX_PIPE: u64 = 64; +pub const MAX_FDS: u64 = 64; /// A single Scheduler instance is used to verify a single script /// within a CKB transaction. @@ -56,10 +56,10 @@ where max_vms_count: u64, total_cycles: Cycle, next_vm_id: VmId, - next_pipe_slot: u64, + next_fd_slot: u64, states: BTreeMap, - pipes: BTreeMap, - inherited_fd: BTreeMap>, + fds: BTreeMap, + inherited_fd: BTreeMap>, instantiated: BTreeMap, Machine)>, suspended: BTreeMap>, terminated_vms: BTreeMap, @@ -87,9 +87,9 @@ where max_vms_count: MAX_VMS_COUNT, total_cycles: 0, next_vm_id: FIRST_VM_ID, - next_pipe_slot: FIRST_PIPE_SLOT, + next_fd_slot: FIRST_FD_SLOT, states: BTreeMap::default(), - pipes: BTreeMap::default(), + fds: BTreeMap::default(), inherited_fd: BTreeMap::default(), instantiated: BTreeMap::default(), suspended: BTreeMap::default(), @@ -117,13 +117,13 @@ where max_vms_count: full.max_vms_count, total_cycles: full.total_cycles, next_vm_id: full.next_vm_id, - next_pipe_slot: full.next_pipe_slot, + next_fd_slot: full.next_fd_slot, states: full .vms .iter() .map(|(id, state, _)| (*id, state.clone())) .collect(), - pipes: full.pipes.into_iter().collect(), + fds: full.fds.into_iter().collect(), inherited_fd: full.inherited_fd.into_iter().collect(), instantiated: BTreeMap::default(), suspended: full @@ -155,9 +155,9 @@ where max_vms_count: self.max_vms_count, total_cycles: self.total_cycles, next_vm_id: self.next_vm_id, - next_pipe_slot: self.next_pipe_slot, + next_fd_slot: self.next_fd_slot, vms, - pipes: self.pipes.into_iter().collect(), + fds: self.fds.into_iter().collect(), inherited_fd: self.inherited_fd.into_iter().collect(), terminated_vms: self.terminated_vms.into_iter().collect(), }) @@ -246,7 +246,7 @@ where // 3. Process message box, update VM states accordingly self.process_message_box()?; assert!(self.message_box.lock().expect("lock").is_empty()); - // 4. If the VM terminates, update VMs in join state, also closes its pipes + // 4. If the VM terminates, update VMs in join state, also closes its fds match result { Ok(code) => { self.terminated_vms.insert(vm_id_to_run, code); @@ -287,8 +287,8 @@ where machine.machine.set_register(A0, SUCCESS as u64); self.states.insert(vm_id, VmState::Runnable); } - // Close pipes - self.pipes.retain(|_, vm_id| *vm_id != vm_id_to_run); + // Close fds + self.fds.retain(|_, vm_id| *vm_id != vm_id_to_run); // Clear terminated VM states self.states.remove(&vm_id_to_run); self.instantiated.remove(&vm_id_to_run); @@ -306,21 +306,21 @@ where for message in messages { match message { Message::Spawn(vm_id, args) => { - // All pipes must belong to the correct owner - let mut pipes_valid = true; - for pipe in &args.pipes { - if !(self.pipes.contains_key(pipe) && (self.pipes[pipe] == vm_id)) { + // All fds must belong to the correct owner + let mut fds_valid = true; + for fd in &args.fds { + if !(self.fds.contains_key(fd) && (self.fds[fd] == vm_id)) { self.ensure_vms_instantiated(&[vm_id])?; let (_, machine) = self.instantiated.get_mut(&vm_id).ok_or_else(|| { Error::Unexpected("Unable to find VM Id".to_string()) })?; - machine.machine.set_register(A0, INVALID_PIPE as u64); - pipes_valid = false; + machine.machine.set_register(A0, INVALID_FD as u64); + fds_valid = false; break; } } - if !pipes_valid { + if !fds_valid { continue; } if self.suspended.len() + self.instantiated.len() > self.max_vms_count as usize @@ -335,13 +335,13 @@ where } let spawned_vm_id = self.boot_vm(&args.data_piece_id, args.offset, args.length, &args.argv)?; - // Move passed pipes from spawner to spawnee - for pipe in &args.pipes { - self.pipes.insert(*pipe, spawned_vm_id); + // Move passed fds from spawner to spawnee + for fd in &args.fds { + self.fds.insert(*fd, spawned_vm_id); } // Here we keep the original version of file descriptors. // If one fd is moved afterward, this inherited file descriptors doesn't change. - self.inherited_fd.insert(spawned_vm_id, args.pipes.clone()); + self.inherited_fd.insert(spawned_vm_id, args.fds.clone()); self.ensure_vms_instantiated(&[vm_id])?; { @@ -395,18 +395,18 @@ where ); } Message::Pipe(vm_id, args) => { - if self.next_pipe_slot - FIRST_PIPE_SLOT >= MAX_PIPE { + if self.next_fd_slot - FIRST_FD_SLOT >= MAX_FDS { let (_, machine) = self .instantiated .get_mut(&vm_id) .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - machine.machine.set_register(A0, MAX_PIPE_CREATED as u64); + machine.machine.set_register(A0, MAX_FD_CREATED as u64); continue; } - let (p1, p2, slot) = PipeId::create(self.next_pipe_slot); - self.next_pipe_slot = slot; - self.pipes.insert(p1, vm_id); - self.pipes.insert(p2, vm_id); + let (p1, p2, slot) = Fd::create(self.next_fd_slot); + self.next_fd_slot = slot; + self.fds.insert(p1, vm_id); + self.fds.insert(p2, vm_id); self.ensure_vms_instantiated(&[vm_id])?; { @@ -417,27 +417,27 @@ where machine .machine .memory_mut() - .store64(&args.pipe1_addr, &p1.0)?; + .store64(&args.fd1_addr, &p1.0)?; machine .machine .memory_mut() - .store64(&args.pipe2_addr, &p2.0)?; + .store64(&args.fd2_addr, &p2.0)?; machine.machine.set_register(A0, SUCCESS as u64); } } - Message::PipeRead(vm_id, args) => { - if !(self.pipes.contains_key(&args.pipe) && (self.pipes[&args.pipe] == vm_id)) { + Message::FdRead(vm_id, args) => { + if !(self.fds.contains_key(&args.fd) && (self.fds[&args.fd] == vm_id)) { self.ensure_vms_instantiated(&[vm_id])?; { let (_, machine) = self.instantiated.get_mut(&vm_id).ok_or_else(|| { Error::Unexpected("Unable to find VM Id".to_string()) })?; - machine.machine.set_register(A0, INVALID_PIPE as u64); + machine.machine.set_register(A0, INVALID_FD as u64); } continue; } - if !self.pipes.contains_key(&args.pipe.other_pipe()) { + if !self.fds.contains_key(&args.fd.other_fd()) { self.ensure_vms_instantiated(&[vm_id])?; { let (_, machine) = @@ -452,26 +452,26 @@ where self.states.insert( vm_id, VmState::WaitForRead { - pipe: args.pipe, + fd: args.fd, length: args.length, buffer_addr: args.buffer_addr, length_addr: args.length_addr, }, ); } - Message::PipeWrite(vm_id, args) => { - if !(self.pipes.contains_key(&args.pipe) && (self.pipes[&args.pipe] == vm_id)) { + Message::FdWrite(vm_id, args) => { + if !(self.fds.contains_key(&args.fd) && (self.fds[&args.fd] == vm_id)) { self.ensure_vms_instantiated(&[vm_id])?; { let (_, machine) = self.instantiated.get_mut(&vm_id).ok_or_else(|| { Error::Unexpected("Unable to find VM Id".to_string()) })?; - machine.machine.set_register(A0, INVALID_PIPE as u64); + machine.machine.set_register(A0, INVALID_FD as u64); } continue; } - if !self.pipes.contains_key(&args.pipe.other_pipe()) { + if !self.fds.contains_key(&args.fd.other_fd()) { self.ensure_vms_instantiated(&[vm_id])?; { let (_, machine) = @@ -486,7 +486,7 @@ where self.states.insert( vm_id, VmState::WaitForWrite { - pipe: args.pipe, + fd: args.fd, consumed: 0, length: args.length, buffer_addr: args.buffer_addr, @@ -500,7 +500,7 @@ where .instantiated .get_mut(&vm_id) .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - let PipeIoArgs { + let FdArgs { buffer_addr, length_addr, .. @@ -549,10 +549,10 @@ where .instantiated .get_mut(&vm_id) .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - if self.pipes.get(&fd) != Some(&vm_id) { - machine.machine.set_register(A0, INVALID_PIPE as u64); + if self.fds.get(&fd) != Some(&vm_id) { + machine.machine.set_register(A0, INVALID_FD as u64); } else { - self.pipes.remove(&fd); + self.fds.remove(&fd); machine.machine.set_register(A0, SUCCESS as u64); } } @@ -562,31 +562,31 @@ where } fn process_io(&mut self) -> Result<(), Error> { - let mut reads: HashMap = HashMap::default(); - let mut closed_pipes: Vec = Vec::new(); + let mut reads: HashMap = HashMap::default(); + let mut closed_fds: Vec = Vec::new(); self.states.iter().for_each(|(vm_id, state)| { - if let VmState::WaitForRead { pipe, .. } = state { - if self.pipes.contains_key(&pipe.other_pipe()) { - reads.insert(*pipe, (*vm_id, state.clone())); + if let VmState::WaitForRead { fd, .. } = state { + if self.fds.contains_key(&fd.other_fd()) { + reads.insert(*fd, (*vm_id, state.clone())); } else { - closed_pipes.push(*vm_id); + closed_fds.push(*vm_id); } } }); let mut pairs: Vec<[(VmId, VmState); 2]> = Vec::new(); self.states.iter().for_each(|(vm_id, state)| { - if let VmState::WaitForWrite { pipe, .. } = state { - if self.pipes.contains_key(&pipe.other_pipe()) { - if let Some((read_vm_id, read_state)) = reads.get(&pipe.other_pipe()) { + if let VmState::WaitForWrite { fd, .. } = state { + if self.fds.contains_key(&fd.other_fd()) { + if let Some((read_vm_id, read_state)) = reads.get(&fd.other_fd()) { pairs.push([(*read_vm_id, read_state.clone()), (*vm_id, state.clone())]); } } else { - closed_pipes.push(*vm_id); + closed_fds.push(*vm_id); } } }); - // Finish read / write syscalls for pipes that are closed on the other end - for vm_id in closed_pipes { + // Finish read / write syscalls for fds that are closed on the other end + for vm_id in closed_fds { match self.states[&vm_id].clone() { VmState::WaitForRead { length_addr, .. } => { self.ensure_vms_instantiated(&[vm_id])?; @@ -621,7 +621,7 @@ where _ => (), } } - // Transfering data from write pipes to read pipes + // Transfering data from write fds to read fds for [(read_vm_id, read_state), (write_vm_id, write_state)] in pairs { let VmState::WaitForRead { length: read_length, @@ -633,7 +633,7 @@ where unreachable!() }; let VmState::WaitForWrite { - pipe: write_pipe, + fd: write_fd, mut consumed, length: write_length, buffer_addr: write_buffer_addr, @@ -681,7 +681,7 @@ where self.states.insert(read_vm_id, VmState::Runnable); // Write syscall, however, terminates only when all the data - // have been written, or when the pairing read pipe is closed. + // have been written, or when the pairing read fd is closed. consumed += copiable; if consumed == write_length { // Write VM has fulfilled its write request @@ -700,7 +700,7 @@ where self.states.insert( write_vm_id, VmState::WaitForWrite { - pipe: write_pipe, + fd: write_fd, consumed, length: write_length, buffer_addr: write_buffer_addr, diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs index 2cd454576a..1e359095be 100644 --- a/script/src/syscalls/close.rs +++ b/script/src/syscalls/close.rs @@ -1,5 +1,5 @@ use crate::syscalls::{CLOSE, SPAWN_YIELD_CYCLES_BASE}; -use crate::types::{Message, PipeId, VmId}; +use crate::types::{Fd, Message, VmId}; use ckb_vm::{ registers::{A0, A7}, Error as VMError, Register, SupportMachine, Syscalls, @@ -27,12 +27,12 @@ impl Syscalls for Close { if machine.registers()[A7].to_u64() != CLOSE { return Ok(false); } - let pipe = PipeId(machine.registers()[A0].to_u64()); + let fd = Fd(machine.registers()[A0].to_u64()); machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? - .push(Message::Close(self.id, pipe)); + .push(Message::Close(self.id, fd)); Err(VMError::Yield) } } diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs index 0fd45aa1f7..4d041a0ba1 100644 --- a/script/src/syscalls/inherited_fd.rs +++ b/script/src/syscalls/inherited_fd.rs @@ -1,5 +1,5 @@ use crate::syscalls::{INHERITED_FD, SPAWN_YIELD_CYCLES_BASE}; -use crate::types::{Message, PipeId, PipeIoArgs, VmId}; +use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A7}, Error as VMError, Register, SupportMachine, Syscalls, @@ -35,8 +35,8 @@ impl Syscalls for InheritedFd { .map_err(|e| VMError::Unexpected(e.to_string()))? .push(Message::InheritedFileDescriptor( self.id, - PipeIoArgs { - pipe: PipeId(0), + FdArgs { + fd: Fd(0), length: 0, buffer_addr, length_addr, diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index f9c2a21e47..d4e442c9c8 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -64,10 +64,10 @@ pub const ITEM_MISSING: u8 = 2; pub const SLICE_OUT_OF_BOUND: u8 = 3; pub const WRONG_FORMAT: u8 = 4; pub const WAIT_FAILURE: u8 = 5; -pub const INVALID_PIPE: u8 = 6; +pub const INVALID_FD: u8 = 6; pub const OTHER_END_CLOSED: u8 = 7; pub const MAX_VMS_SPAWNED: u8 = 8; -pub const MAX_PIPE_CREATED: u8 = 9; +pub const MAX_FD_CREATED: u8 = 9; pub const VM_VERSION: u64 = 2041; pub const CURRENT_CYCLES: u64 = 2042; diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs index d7834b1dce..3bb61ba22d 100644 --- a/script/src/syscalls/pipe.rs +++ b/script/src/syscalls/pipe.rs @@ -27,19 +27,13 @@ impl Syscalls for Pipe { if machine.registers()[A7].to_u64() != PIPE { return Ok(false); } - let pipe1_addr = machine.registers()[A0].to_u64(); - let pipe2_addr = pipe1_addr.wrapping_add(8); + let fd1_addr = machine.registers()[A0].to_u64(); + let fd2_addr = fd1_addr.wrapping_add(8); machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? - .push(Message::Pipe( - self.id, - PipeArgs { - pipe1_addr, - pipe2_addr, - }, - )); + .push(Message::Pipe(self.id, PipeArgs { fd1_addr, fd2_addr })); Err(VMError::Yield) } } diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index c96107d39e..9217fd4345 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,5 +1,5 @@ -use crate::syscalls::{INVALID_PIPE, READ, SPAWN_YIELD_CYCLES_BASE}; -use crate::types::{Message, PipeId, PipeIoArgs, VmId}; +use crate::syscalls::{INVALID_FD, READ, SPAWN_YIELD_CYCLES_BASE}; +use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, Error as VMError, Memory, Register, SupportMachine, Syscalls, @@ -27,7 +27,7 @@ impl Syscalls for Read { if machine.registers()[A7].to_u64() != READ { return Ok(false); } - let pipe = PipeId(machine.registers()[A0].to_u64()); + let fd = Fd(machine.registers()[A0].to_u64()); let buffer_addr = machine.registers()[A1].to_u64(); let length_addr = machine.registers()[A2].to_u64(); let length = machine @@ -38,18 +38,18 @@ impl Syscalls for Read { // We can only do basic checks here, when the message is actually processed, // more complete checks will be performed. // We will also leave to the actual write operation to test memory permissions. - if !pipe.is_read() { - machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); + if !fd.is_read() { + machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); } machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? - .push(Message::PipeRead( + .push(Message::FdRead( self.id, - PipeIoArgs { - pipe, + FdArgs { + fd, length, buffer_addr, length_addr, diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 41d150d7a6..03cd669ea0 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -2,7 +2,7 @@ use crate::syscalls::utils::load_c_string; use crate::syscalls::{ INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, }; -use crate::types::{DataPieceId, Message, PipeId, SpawnArgs, TxData, VmId}; +use crate::types::{DataPieceId, Fd, Message, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_vm::{ machine::SupportMachine, @@ -94,24 +94,24 @@ where .memory_mut() .load64(&Mac::REG::from_u64(process_id_addr_addr))? .to_u64(); - let pipes_addr_addr = spgs_addr.wrapping_add(24); - let mut pipes_addr = machine + let fds_addr_addr = spgs_addr.wrapping_add(24); + let mut fds_addr = machine .memory_mut() - .load64(&Mac::REG::from_u64(pipes_addr_addr))? + .load64(&Mac::REG::from_u64(fds_addr_addr))? .to_u64(); - let mut pipes = vec![]; - if pipes_addr != 0 { + let mut fds = vec![]; + if fds_addr != 0 { loop { - let pipe = machine + let fd = machine .memory_mut() - .load64(&Mac::REG::from_u64(pipes_addr))? + .load64(&Mac::REG::from_u64(fds_addr))? .to_u64(); - if pipe == 0 { + if fd == 0 { break; } - pipes.push(PipeId(pipe)); - pipes_addr += 8; + fds.push(Fd(fd)); + fds_addr += 8; } } @@ -153,7 +153,7 @@ where offset, length, argv, - pipes, + fds, process_id_addr, }, )); diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index 07b1da81a6..a193f5589b 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,5 +1,5 @@ -use crate::syscalls::{INVALID_PIPE, SPAWN_YIELD_CYCLES_BASE, WRITE}; -use crate::types::{Message, PipeId, PipeIoArgs, VmId}; +use crate::syscalls::{INVALID_FD, SPAWN_YIELD_CYCLES_BASE, WRITE}; +use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, Error as VMError, Memory, Register, SupportMachine, Syscalls, @@ -27,7 +27,7 @@ impl Syscalls for Write { if machine.registers()[A7].to_u64() != WRITE { return Ok(false); } - let pipe = PipeId(machine.registers()[A0].to_u64()); + let fd = Fd(machine.registers()[A0].to_u64()); let buffer_addr = machine.registers()[A1].to_u64(); let length_addr = machine.registers()[A2].to_u64(); let length = machine @@ -38,18 +38,18 @@ impl Syscalls for Write { // We can only do basic checks here, when the message is actually processed, // more complete checks will be performed. // We will also leave to the actual write operation to test memory permissions. - if !pipe.is_write() { - machine.set_register(A0, Mac::REG::from_u8(INVALID_PIPE)); + if !fd.is_write() { + machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); } machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? - .push(Message::PipeWrite( + .push(Message::FdWrite( self.id, - PipeIoArgs { - pipe, + FdArgs { + fd, length, buffer_addr, length_addr, diff --git a/script/src/types.rs b/script/src/types.rs index 2b51129d4b..87fa70a125 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -359,17 +359,17 @@ pub type VmId = u64; pub const FIRST_VM_ID: VmId = 0; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct PipeId(pub(crate) u64); +pub struct Fd(pub(crate) u64); -pub const FIRST_PIPE_SLOT: u64 = 2; +pub const FIRST_FD_SLOT: u64 = 2; -impl PipeId { - pub fn create(slot: u64) -> (PipeId, PipeId, u64) { - (PipeId(slot), PipeId(slot + 1), slot + 2) +impl Fd { + pub fn create(slot: u64) -> (Fd, Fd, u64) { + (Fd(slot), Fd(slot + 1), slot + 2) } - pub fn other_pipe(&self) -> PipeId { - PipeId(self.0 ^ 0x1) + pub fn other_fd(&self) -> Fd { + Fd(self.0 ^ 0x1) } pub fn is_read(&self) -> bool { @@ -390,14 +390,14 @@ pub enum VmState { exit_code_addr: u64, }, WaitForWrite { - pipe: PipeId, + fd: Fd, consumed: u64, length: u64, buffer_addr: u64, length_addr: u64, }, WaitForRead { - pipe: PipeId, + fd: Fd, length: u64, buffer_addr: u64, length_addr: u64, @@ -410,7 +410,7 @@ pub struct SpawnArgs { pub offset: u64, pub length: u64, pub argv: Vec, - pub pipes: Vec, + pub fds: Vec, pub process_id_addr: u64, } @@ -422,13 +422,13 @@ pub struct WaitArgs { #[derive(Clone, Debug)] pub struct PipeArgs { - pub pipe1_addr: u64, - pub pipe2_addr: u64, + pub fd1_addr: u64, + pub fd2_addr: u64, } #[derive(Clone, Debug)] -pub struct PipeIoArgs { - pub pipe: PipeId, +pub struct FdArgs { + pub fd: Fd, pub length: u64, pub buffer_addr: u64, pub length_addr: u64, @@ -439,10 +439,10 @@ pub enum Message { Spawn(VmId, SpawnArgs), Wait(VmId, WaitArgs), Pipe(VmId, PipeArgs), - PipeRead(VmId, PipeIoArgs), - PipeWrite(VmId, PipeIoArgs), - InheritedFileDescriptor(VmId, PipeIoArgs), - Close(VmId, PipeId), + FdRead(VmId, FdArgs), + FdWrite(VmId, FdArgs), + InheritedFileDescriptor(VmId, FdArgs), + Close(VmId, Fd), } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -488,10 +488,10 @@ pub struct FullSuspendedState { pub max_vms_count: u64, pub total_cycles: Cycle, pub next_vm_id: VmId, - pub next_pipe_slot: u64, + pub next_fd_slot: u64, pub vms: Vec<(VmId, VmState, Snapshot2)>, - pub pipes: Vec<(PipeId, VmId)>, - pub inherited_fd: Vec<(VmId, Vec)>, + pub fds: Vec<(Fd, VmId)>, + pub inherited_fd: Vec<(VmId, Vec)>, pub terminated_vms: Vec<(VmId, i8)>, } @@ -518,8 +518,8 @@ impl FullSuspendedState { + size_of::(); acc }) - + (self.pipes.len() * (size_of::() + size_of::()))) as u64 - + (self.inherited_fd.len() * (size_of::())) as u64 + + (self.fds.len() * (size_of::() + size_of::()))) as u64 + + (self.inherited_fd.len() * (size_of::())) as u64 + (self.terminated_vms.len() * (size_of::() + size_of::())) as u64 } } 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 58df15c753..39ab4c5ed6 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1,5 +1,5 @@ use super::SCRIPT_VERSION; -use crate::scheduler::{MAX_PIPE, MAX_VMS_COUNT}; +use crate::scheduler::{MAX_FDS, MAX_VMS_COUNT}; use crate::syscalls::SOURCE_GROUP_FLAG; use crate::verify::{tests::utils::*, *}; use ckb_types::{ @@ -104,7 +104,7 @@ fn check_spawn_max_vms_count() { } #[test] -fn check_spawn_max_pipe_limits() { +fn check_spawn_max_fd_limits() { let result = simple_spawn_test("testdata/spawn_cases", &[11]); assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } @@ -648,11 +648,11 @@ fn check_spawn_current_cycles() { } #[test] -fn check_spawn_pipe_limits() { +fn check_spawn_fd_limits() { let script_version = SCRIPT_VERSION; let (spawn_caller_cell, spawn_caller_data_hash) = - load_cell_from_path("testdata/spawn_pipe_limits"); + load_cell_from_path("testdata/spawn_fd_limits"); let spawn_caller_script = Script::new_builder() .hash_type(script_version.data_hash_type().into()) @@ -1155,7 +1155,7 @@ proptest! { fn test_random_dag( seed: u64, spawns in 5u32..MAX_VMS_COUNT as u32, - writes in 3u32..MAX_PIPE as u32 / 2, + writes in 3u32..MAX_FDS as u32 / 2, ) { let script_version = SCRIPT_VERSION; let program: Bytes = std::fs::read("./testdata/spawn_dag").unwrap().into(); diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 42cf22ed47..1823765c2b 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -68,7 +68,7 @@ ALL_BINS := jalr_zero \ spawn_callee_current_cycles \ spawn_times \ spawn_cases \ - spawn_pipe_limits \ + spawn_fd_limits \ spawn_configurable_caller \ spawn_configurable_callee \ spawn_dag \ @@ -153,7 +153,7 @@ spawn_caller_current_cycles: spawn_caller_current_cycles.c spawn_callee_current_cycles: spawn_callee_current_cycles.c spawn_times: spawn_times.c spawn_utils.h spawn_cases: spawn_cases.c spawn_utils.h -spawn_pipe_limits: spawn_pipe_limits.c +spawn_fd_limits: spawn_fd_limits.c spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h diff --git a/script/testdata/spawn_pipe_limits b/script/testdata/spawn_fd_limits similarity index 67% rename from script/testdata/spawn_pipe_limits rename to script/testdata/spawn_fd_limits index 87431dc639dbd5e8b9d38714951f831c4382b6e0..df74442c94db672b7856c5ee28155ea42d2a15b9 100755 GIT binary patch delta 272 zcmdm>yg+$^24liRO><5r9tJRA+L+nP&6Jih`4@M}EBAWsOWJBAw~D+QG;pZpMLOY>w$K5@qW$$~&~3P?TUVz9_6knH3FK6aq9 zH&^rNGfv*XpTO8PSx}&yk!f<5b9tJRA*_heO%~FtAkUIGXcgo}d9=6FbJUx=4KuIPBMg}oP zMzAudY6iv0jJ)EE+LH}|q#1~mbc3o~!U9nl#|GBG5I8vzDC-5}2m#Gu;)cjZK_nT% zCr<>LkU3eAPn@x9@!4`Rs1$&P~NoQnJqp6BF) G0`dS_k~4(> diff --git a/script/testdata/spawn_pipe_limits.c b/script/testdata/spawn_fd_limits.c similarity index 100% rename from script/testdata/spawn_pipe_limits.c rename to script/testdata/spawn_fd_limits.c From 0f3281982c1c086e0095b91d7aaa2f605d169280 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 14:58:40 +0800 Subject: [PATCH 069/135] Rename MAX_FD_CREATED to MAX_FDS_CREATED --- script/src/scheduler.rs | 4 ++-- script/src/syscalls/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 9151c90aaa..935dde0037 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,6 +1,6 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, INVALID_FD, MAX_FD_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, + INDEX_OUT_OF_BOUND, INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, WAIT_FAILURE, }; use crate::types::MachineContext; @@ -400,7 +400,7 @@ where .instantiated .get_mut(&vm_id) .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - machine.machine.set_register(A0, MAX_FD_CREATED as u64); + machine.machine.set_register(A0, MAX_FDS_CREATED as u64); continue; } let (p1, p2, slot) = Fd::create(self.next_fd_slot); diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index d4e442c9c8..984f2aa854 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -67,7 +67,7 @@ pub const WAIT_FAILURE: u8 = 5; pub const INVALID_FD: u8 = 6; pub const OTHER_END_CLOSED: u8 = 7; pub const MAX_VMS_SPAWNED: u8 = 8; -pub const MAX_FD_CREATED: u8 = 9; +pub const MAX_FDS_CREATED: u8 = 9; pub const VM_VERSION: u64 = 2041; pub const CURRENT_CYCLES: u64 = 2042; From b0ced6e0a73fadcb11c916b4b0a2ea797e3da9cc Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 15:02:29 +0800 Subject: [PATCH 070/135] Update ckb-c-stdlib --- script/testdata/spawn_cases.c | 4 ++-- script/testdata/spawn_fd_limits.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index 6cc9615a1f..fec50c014b 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -270,7 +270,7 @@ int parent_inherited_fds_without_owner(uint64_t* pid) { spawn_args_t spgs = {.argc = 1, .argv = argv, .process_id = pid, .inherited_fds = fds}; err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); - CHECK2(err == CKB_INVALID_PIPE, -2); + CHECK2(err == CKB_INVALID_FD, -2); // create valid fds err = ckb_pipe(fds); @@ -281,7 +281,7 @@ int parent_inherited_fds_without_owner(uint64_t* pid) { // the fds are already transferred. An error expected. err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); - CHECK2(err == CKB_INVALID_PIPE, -2); + CHECK2(err == CKB_INVALID_FD, -2); err = 0; exit: return err; diff --git a/script/testdata/spawn_fd_limits.c b/script/testdata/spawn_fd_limits.c index 466e04d67d..d214c15448 100644 --- a/script/testdata/spawn_fd_limits.c +++ b/script/testdata/spawn_fd_limits.c @@ -12,7 +12,7 @@ int main() { } // Create up to 64 pipes. err = ckb_pipe(pipe); - err = err - 9; + err = err - CKB_MAX_FDS_CREATED; exit: return err; From 4fc3ad4a10d3e864e6e7a0dbf121d384c787d329 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 15:10:03 +0800 Subject: [PATCH 071/135] Remove spawn_fd_limits --- .../tests/ckb_latest/features_since_v2023.rs | 32 +----------------- script/testdata/Makefile | 2 -- script/testdata/spawn_caller_strcat | Bin 5144 -> 5144 bytes script/testdata/spawn_caller_strcat.c | 2 +- script/testdata/spawn_cases | Bin 15136 -> 15088 bytes script/testdata/spawn_cases.c | 16 ++++----- script/testdata/spawn_configurable_caller | Bin 7872 -> 7872 bytes script/testdata/spawn_configurable_caller.c | 2 +- script/testdata/spawn_fd_limits | Bin 4512 -> 0 bytes script/testdata/spawn_fd_limits.c | 19 ----------- script/testdata/spawn_utils.h | 6 ++-- 11 files changed, 14 insertions(+), 65 deletions(-) delete mode 100755 script/testdata/spawn_fd_limits delete mode 100644 script/testdata/spawn_fd_limits.c 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 39ab4c5ed6..7e11a0c86d 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -104,7 +104,7 @@ fn check_spawn_max_vms_count() { } #[test] -fn check_spawn_max_fd_limits() { +fn check_spawn_max_fds_limit() { let result = simple_spawn_test("testdata/spawn_cases", &[11]); assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } @@ -647,36 +647,6 @@ fn check_spawn_current_cycles() { assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); } -#[test] -fn check_spawn_fd_limits() { - let script_version = SCRIPT_VERSION; - - let (spawn_caller_cell, spawn_caller_data_hash) = - load_cell_from_path("testdata/spawn_fd_limits"); - - 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 transaction = TransactionBuilder::default().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); -} - #[derive(Clone, Copy)] enum SpawnFrom { TxInputWitness, diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 1823765c2b..1d49c6e297 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -68,7 +68,6 @@ ALL_BINS := jalr_zero \ spawn_callee_current_cycles \ spawn_times \ spawn_cases \ - spawn_fd_limits \ spawn_configurable_caller \ spawn_configurable_callee \ spawn_dag \ @@ -153,7 +152,6 @@ spawn_caller_current_cycles: spawn_caller_current_cycles.c spawn_callee_current_cycles: spawn_callee_current_cycles.c spawn_times: spawn_times.c spawn_utils.h spawn_cases: spawn_cases.c spawn_utils.h -spawn_fd_limits: spawn_fd_limits.c spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h diff --git a/script/testdata/spawn_caller_strcat b/script/testdata/spawn_caller_strcat index 911363f5b71bd23936469e8470999ce4fa0a63e1..f56aafa13f9de26f380dc97964c94cea30281271 100755 GIT binary patch delta 171 zcmbQCF+*d+3x39)$&3QxlGO|h3<3k?D69?ub&Mie delta 197 zcmbQCF+*d+3x30D1_lNp21bTQJd8jV1H%L`$-podNQ1;rK*gn?;ysfY1;iz10C@ro z%s>L73o6O5WU?Vpb~RM*2B3ZrV1g>zF!>_Cxa5AI2sXXPKqgN(HiXR?=ZI;H7zvvcMHAeJ44u(* zBYmBcm~C7kLXdqR6OlNe;v9=ki~<6SgTw?-@HxrcV5CKXIKYo{-@UKh>L0%3^xpGv z&&Tha`}#VzgzH=9p~G!CiwflePI=Uo6Df~i5rAaMa&ifg0N>VDoVeq^b9Hs=1yOu)%+p_w~2nu97PF-TJCpOJ0!td1F;6zSFZ007=;1>OZ4ypg7vf9$Og`Y)&!bw z)%igZ4sv&wVM)^BGszZS(vqadlC6rVIE|Wy&Z?%X71N+Sr37X0aU@&S#_*Y9BXnqp zGdPERrZncS(_~Gb9J=dz>wic^ALHrbf*eUlmK@QV&Nej>FoPer$-odo+zURA;S@SWZ3pQD1pruN|C?vQ4aUB}*n0Lmc zMl|Y_Qh1)|Z+)wPOtPp}<@l`C%3R*Cs>RN*xgh_gw)V*-%f748Y**=Nwl=k7Yub0r z%~)D7+vTU5R};(_zVgqfq7E7phyzIKT5L3`U%!1^kO?#1*~{(d4_Xk8L5wB=9y zcWO#vtHRRCs_x>y9VwZuagm9T4Yw->2EEE@Axtk3w0&Qe#G>cV&Pq{Bs{O6Ovt~en z%Xp<1e?4cfURAk%!Y^fKN7+kwcec%@(-Q2Ym1t$)T9=&tVA-fP2w&?)@M+~NAPPohwQ5BkaE{bY?EF0?CtVn zz0>lzYE-p{#P6_O>OB}B?Hn?V8q+;#axe-Avfgv zX9O;CnYY_JhujJB?!)DI6#$YlH$%k}Z+iB_EED;@yc&29@cHG)*K^tFKOa=YT2Ulz zUZynHb;;?k4?>)<;RmOGKi!>l`uqBctf$lIZ&P-LolgHpL@WOja{8NsT9Nu%%ykFo z*hB_qDC3IL|Ere25CLu)_DO1fz8_{PZq`DOn|;LL+5=Aiw|xXVGOitt2!cZc7aBaM zpY)+FIj0}Z6viE+C(73ie`qJcPsOV+p%ue`3H?V~?j5e?Yii}<&!r7n9OBT*Z4xTO zU#BNMYt{1HSg&f(ev9qGEgkBv=OV32A5ajIHP=FN)yXxx$jQ=+YKn(vO-k`pgXjGL zX#;+FcBU^`o1~Xsfqz*87dDVH>ug#vMq>Pr#G*}{YO_(E%D*@o!^h|=nck;{t&B0K z7?n2YCH&UuuF1(2jZbx3bZshM7^5$Y(I>~~lglR=bRJVNZMmuL2KKO>+%rb7R4#Z* z6w9?o;=g#)<35JZxOVzl^ASfV0Q3e>3DCnpc|Z=JRG>tlyLpKFAQy4Ffm(qAK+Azf zoQV6B|P&pHGcU3w2h*RYn+_}(Hq0`U+)nz`-kq<_ChT}ZAu*g(Vr)VL=m`q+( zn+6$Y?%u_1MJ9A8_)*a~3Vyt(9^vp}0o&bnl!Qy&uK3f?1@fH64emwpYBU-5xr+hj m3HbdTyO$Kl+Y70~M%=VyQG7=c#&lJPGJZ*tNA delta 2882 zcmZ8jdr(wW7{6!Py}%-Hw*_IBH;_&L~;|gENLX*u)eA3`>C%vp9)mWed#S z1?&NM#;GO~rLuAywYFl6rd51p4CC5ArBikzM;D>lZOTfm=sWkEyNi2gzCHJQobUU6 zk8}10yAJFaDnRmZ;mYOy5>9#4l@lnBVBvxMl;!;Ehy?iI;fe&oKHc=7UDw>(9mv{L z{PEQ*Q5yZfo-ec_AMHvo_hGji&+0Rg3&+KsG7dx;B^L?=y@63T)+rqRDK1whMHzJx zj$V{WWuBr%4O&gJ+p}A6X{?G8HVxiA)RZIf_GXAR)w;2D)NSNTcr4M)rN+C}A_p0ME|Y2E=6-2H1eXb#&P|2U5&SX+tkyzug}w!RE{j*j30`lcxx|B zk#K;$yb4P?9sVZStkdZT=$Yg+#Z-u)rh!S-v|cgwWG!BYGNmYjR<%j|T(RK~Xoxe| zhn*?u%-_M3w2XzJ9miFFMt)P268uVvg&E&XF`+)(o>Pt=N$p;$R(EiO1Ut#I3Pa+K z{b479R&jDCHG?@xH?gwg^(M%OvJeiipT+XJc$;Ml3fPal;WMRs(^J*CFCOt)KQBzJ!zrftg zq*t)F;tW$gsTr%U{L}fcgYG!u06?8P+?gZkx8JmHWU$E$3@KX38elum?5x{6)&Mgw zDvN!hD@hPyU>fj9hNC=``uL$H-kv8-Z&#;~c;R5iR14>c+jSk@si(`f=~~F{>dbM9 z(i5GPj2PhTY_$RpWv_t>^kg4on*5wx_EwuidwZ;e^;HhsiRi0*@pd@T&iiPhgMZ`y zQWqx-DJ;#b_D}p@&f@H$sL({niGS31r|imZK1dG{wEf*&iA677k_+=ew>xg^tZVQp zwk$n_Bh>t(4;FX8^LM;8JszIJce!np`OLLVQYkB`vD5`9@H^RD@6I1}_D3|&r( z!(%acDXhm&E!nRR755xYu;zu?(|E1b0weK+)ug$27Vog`Tc?^1enu}qHhfC=lq)PW z_zq8a9)hWK9&DfB&3Si10Rji{>-nkVypfw&zNp+4CFZGC!m|n5k6+C<>s6E5efW5O z2|)Te-=uN8ga66T&^X@4mVzT$s)=nknap*Tg#rM+|}XRon`v=}T8Y`{sYgE5sE-G_TjK-D_Fj z+gHE^WbXieNvwl=M;Tm#C-E3SyH9*6`y@XB`?R74J+g96wdvGW&s^gss-o0wDuG*V~6Gr<=%s zH~DqQ^P^H*E{8Z&xm!Y2Jyoc>ryBR;eWKoptQWl0XygZF4IX=iu7T4u8@*e}MAlpj z$b%m@yoIcl@UKaM9Zw1a%k=ErQa{G_PSUlahpeX06;2M^*tKQv*sd+T-Eh3%iQy5R zw7uq>TZTA7(?H(??E~5a)DQGB&~~7$K%0TMV#NKq6zqYff%XGE2sB|s+!sL0fbxJ= z06os$o7mb0YbVfqj6VYFr#2L=Y{;|Wt0ga(d?1T_qPQr|@7cCI8ky8jBu-0>UW7&9 zew+8>;rnfxuS7g?f0bq;AL~n(AwMoJZ8RUvqYjgpUpuV#K`)LL;ZI6;7@k@}V^!d22G!UA;_Q%H#`8Ld!}A>;2JVejl&isp)tUbTnUIFg diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index fec50c014b..037a838dbe 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -334,7 +334,7 @@ int child_max_vms_count() { return err; } -int parent_max_pipe_limits() { +int parent_max_fds_limit() { const char* argv[2] = {"", 0}; int err = 0; uint64_t fd[2] = {0}; @@ -347,16 +347,16 @@ int parent_max_pipe_limits() { return err; } -int child_max_pipe_limits() { +int child_max_fds_limit() { int err = 0; - uint64_t pipe[2] = {0}; + uint64_t fd[2] = {0}; for (int i = 0; i < 16; i++) { - err = ckb_pipe(pipe); + err = ckb_pipe(fd); CHECK(err); } // Create up to 64 pipes. - err = ckb_pipe(pipe); - err = err - 9; + err = ckb_pipe(fd); + err = CKB_MAX_FDS_CREATED - 9; exit: return err; @@ -538,7 +538,7 @@ int parent_entry(int case_id) { err = parent_max_vms_count(&pid); return err; } else if (case_id == 11) { - err = parent_max_pipe_limits(&pid); + err = parent_max_fds_limit(&pid); return err; } else if (case_id == 12) { return parent_close_invalid_fd(&pid); @@ -585,7 +585,7 @@ int child_entry(int case_id) { } else if (case_id == 10) { return child_max_vms_count(); } else if (case_id == 11) { - return child_max_pipe_limits(); + return child_max_fds_limit(); } else if (case_id == 12) { return 0; } else if (case_id == 13) { diff --git a/script/testdata/spawn_configurable_caller b/script/testdata/spawn_configurable_caller index e4c9a9ae9fee9573e007450c7bcd0f9bc02e4995..f1620466f981f0aa9238bf9e74ab4f384cc0f38e 100755 GIT binary patch delta 305 zcmX?Ld%$+WD@NCiuNxUT8<-mx{B;v%OPE~BWX|X~c`cK;A_LRY?Tgxk*%+9Qg6RoN z5BG!k510<_Uj?KCHa}$&78iWP%g6u%0W4sOVdi8-DRIdTAV+|KnZZB@A`6jYV3;yF z5GcC<$Q5E>WDtVty#SS7KDiMny9O$2Bnr`c2r9dC@(WwMFpm(+ZVM7vneni1=Aat z9_|P68JG|5Uj?KKHa}$&7N0C3ExB;P`%5buKEMkJ9)0S{A5?@6oKTT)Wnk1_~Me3_=3!W)Z)o2 hq-!Ue$aHN!AhUpxk#BOMoH?hN48$>>lOM{;0|54wMM?kw diff --git a/script/testdata/spawn_configurable_caller.c b/script/testdata/spawn_configurable_caller.c index 02faeb203e..ba3184c133 100644 --- a/script/testdata/spawn_configurable_caller.c +++ b/script/testdata/spawn_configurable_caller.c @@ -28,7 +28,7 @@ int main() { uint64_t pid = 0; uint64_t fds[2] = {0}; uint64_t inherited_fds[3] = {0}; - err = create_std_pipes(fds, inherited_fds); + err = create_std_fds(fds, inherited_fds); CHECK(err); spawn_args_t spgs = { diff --git a/script/testdata/spawn_fd_limits b/script/testdata/spawn_fd_limits deleted file mode 100755 index df74442c94db672b7856c5ee28155ea42d2a15b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4512 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 EZ+T_9ivR!s diff --git a/script/testdata/spawn_fd_limits.c b/script/testdata/spawn_fd_limits.c deleted file mode 100644 index d214c15448..0000000000 --- a/script/testdata/spawn_fd_limits.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#include "ckb_syscalls.h" -#include "spawn_utils.h" - -int main() { - int err = 0; - uint64_t pipe[2] = {0}; - for (int i = 0; i < 32; i++) { - err = ckb_pipe(pipe); - CHECK(err); - } - // Create up to 64 pipes. - err = ckb_pipe(pipe); - err = err - CKB_MAX_FDS_CREATED; - -exit: - return err; -} diff --git a/script/testdata/spawn_utils.h b/script/testdata/spawn_utils.h index 2612e24f24..cb385ba560 100644 --- a/script/testdata/spawn_utils.h +++ b/script/testdata/spawn_utils.h @@ -45,8 +45,8 @@ enum CkbSpawnError { #define CKB_STDIN (0) #define CKB_STDOUT (1) -// mimic stdio pipes on linux -int create_std_pipes(uint64_t* fds, uint64_t* inherited_fds) { +// mimic stdio fds on linux +int create_std_fds(uint64_t* fds, uint64_t* inherited_fds) { int err = 0; uint64_t to_child[2] = {0}; @@ -104,7 +104,7 @@ int simple_spawn_args(size_t index, int argc, const char* argv[]) { int full_spawn(size_t index, int argc, const char* argv[], uint64_t fds[2], uint64_t* pid) { int err = 0; uint64_t inherited_fds[3] = {0}; - err = create_std_pipes(fds, inherited_fds); + err = create_std_fds(fds, inherited_fds); CHECK(err); spawn_args_t spgs = {.argc = argc, .argv = argv, .process_id = pid, .inherited_fds = inherited_fds}; err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); From 5d6a27f3c197989818b762ef7a165894e6322928 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 15:53:27 +0800 Subject: [PATCH 072/135] Rename Pipe to Fd --- script/testdata/spawn_dag.c | 22 +- script/testdata/spawn_dag.h | 634 +++++++++++++++++----------------- script/testdata/spawn_dag.mol | 14 +- script/testdata/spawn_dag.rs | 325 +++++++++-------- 4 files changed, 499 insertions(+), 496 deletions(-) diff --git a/script/testdata/spawn_dag.c b/script/testdata/spawn_dag.c index b9ea04cc51..b813e01797 100644 --- a/script/testdata/spawn_dag.c +++ b/script/testdata/spawn_dag.c @@ -105,18 +105,18 @@ int main(int argc, char *argv[]) { if (spawn_found == 0) { return ERROR_ARGV; } - mol_seg_t passed_pipes_seg = MolReader_Spawn_get_pipes(&spawn_seg); + mol_seg_t passed_pipes_seg = MolReader_Spawn_get_fds(&spawn_seg); decoded_length = 0; ret = ee_decode_char_string_in_place(argv[1], &decoded_length); if (ret != 0) { return ret; } - if (decoded_length != MolReader_PipeIndices_length(&passed_pipes_seg) * 8) { + if (decoded_length != MolReader_FdIndices_length(&passed_pipes_seg) * 8) { return ERROR_ARGV; } - for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&passed_pipes_seg); i++) { - mol_seg_res_t pipe_res = MolReader_PipeIndices_get(&passed_pipes_seg, i); + for (mol_num_t i = 0; i < MolReader_FdIndices_length(&passed_pipes_seg); i++) { + mol_seg_res_t pipe_res = MolReader_FdIndices_get(&passed_pipes_seg, i); if (pipe_res.errno != MOL_OK) { return ERROR_ENCODING; } @@ -141,8 +141,8 @@ int main(int argc, char *argv[]) { uint64_t pair_vm_index = *((uint64_t *)MolReader_Pipe_get_vm(&pipe_pair_seg).ptr); if (pair_vm_index == vm_index) { - uint64_t read_index = *((uint64_t *)MolReader_Pipe_get_read_pipe(&pipe_pair_seg).ptr); - uint64_t write_index = *((uint64_t *)MolReader_Pipe_get_write_pipe(&pipe_pair_seg).ptr); + uint64_t read_index = *((uint64_t *)MolReader_Pipe_get_read_fd(&pipe_pair_seg).ptr); + uint64_t write_index = *((uint64_t *)MolReader_Pipe_get_write_fd(&pipe_pair_seg).ptr); uint64_t fildes[2]; ret = ckb_pipe(fildes); @@ -182,9 +182,9 @@ int main(int argc, char *argv[]) { pipes_t passed_pipes; pipes_init(&passed_pipes); - mol_seg_t pipe_indices = MolReader_Spawn_get_pipes(&spawn_seg); - for (mol_num_t i = 0; i < MolReader_PipeIndices_length(&pipe_indices); i++) { - mol_seg_res_t index_res = MolReader_PipeIndices_get(&pipe_indices, i); + mol_seg_t pipe_indices = MolReader_Spawn_get_fds(&spawn_seg); + for (mol_num_t i = 0; i < MolReader_FdIndices_length(&pipe_indices); i++) { + mol_seg_res_t index_res = MolReader_FdIndices_get(&pipe_indices, i); if (index_res.errno != MOL_OK) { return ERROR_ENCODING; } @@ -249,7 +249,7 @@ int main(int argc, char *argv[]) { if (from == vm_index) { // Write data - uint64_t from_pipe = *((uint64_t *)MolReader_Write_get_from_pipe(&write_seg).ptr); + uint64_t from_pipe = *((uint64_t *)MolReader_Write_get_from_fd(&write_seg).ptr); mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); uint64_t pipe_id = 0; @@ -272,7 +272,7 @@ int main(int argc, char *argv[]) { } } else if (to == vm_index) { // Read data - uint64_t to_pipe = *((uint64_t *)MolReader_Write_get_to_pipe(&write_seg).ptr); + uint64_t to_pipe = *((uint64_t *)MolReader_Write_get_to_fd(&write_seg).ptr); mol_seg_t data_seg = MolReader_Write_get_data(&write_seg); uint64_t pipe_id = 0; diff --git a/script/testdata/spawn_dag.h b/script/testdata/spawn_dag.h index b726340c0e..633ce2d03b 100644 --- a/script/testdata/spawn_dag.h +++ b/script/testdata/spawn_dag.h @@ -6,15 +6,15 @@ #include "molecule_reader.h" #include "molecule_builder.h" -#ifndef DAG_H -#define DAG_H +#ifndef SPAWN_DAG_H +#define SPAWN_DAG_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef MOLECULE_API_DECORATOR -#define __DEFINE_MOLECULE_API_DECORATOR_DAG +#define __DEFINE_MOLECULE_API_DECORATOR_SPAWN_DAG #define MOLECULE_API_DECORATOR #endif /* MOLECULE_API_DECORATOR */ @@ -22,139 +22,139 @@ extern "C" { * Reader APIs */ -#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_PipeIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_PipeIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_PipeIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_PipeIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_PipeIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_PipeIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_PipeIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_PipeIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_PipeIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_PipeIndices_verify(s, c) mol_fixvec_verify(s, 8) -#define MolReader_PipeIndices_length(s) mol_fixvec_length(s) -#define MolReader_PipeIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) -#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) -#define MolReader_Bytes_length(s) mol_fixvec_length(s) -#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) -#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *, bool); -#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) -#define MolReader_Pipe_get_read_pipe(s) mol_table_slice_by_index(s, 1) -#define MolReader_Pipe_get_write_pipe(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *, bool); -#define MolReader_Pipes_length(s) mol_dynvec_length(s) -#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *, bool); -#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) -#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Write_get_from_pipe(s) mol_table_slice_by_index(s, 1) -#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) -#define MolReader_Write_get_to_pipe(s) mol_table_slice_by_index(s, 3) -#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *, bool); -#define MolReader_Writes_length(s) mol_dynvec_length(s) -#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *, bool); -#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) -#define MolReader_Spawn_get_pipes(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *, bool); -#define MolReader_Spawns_length(s) mol_dynvec_length(s) -#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *, bool); -#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) -#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) -#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) +#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_FdIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_FdIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_FdIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_FdIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_FdIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_FdIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_FdIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_FdIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_FdIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_FdIndices_verify(s, c) mol_fixvec_verify(s, 8) +#define MolReader_FdIndices_length(s) mol_fixvec_length(s) +#define MolReader_FdIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) +#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_Bytes_length(s) mol_fixvec_length(s) +#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t*, bool); +#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) +#define MolReader_Pipe_get_read_fd(s) mol_table_slice_by_index(s, 1) +#define MolReader_Pipe_get_write_fd(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t*, bool); +#define MolReader_Pipes_length(s) mol_dynvec_length(s) +#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t*, bool); +#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) +#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Write_get_from_fd(s) mol_table_slice_by_index(s, 1) +#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) +#define MolReader_Write_get_to_fd(s) mol_table_slice_by_index(s, 3) +#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t*, bool); +#define MolReader_Writes_length(s) mol_dynvec_length(s) +#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t*, bool); +#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) +#define MolReader_Spawn_get_fds(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t*, bool); +#define MolReader_Spawns_length(s) mol_dynvec_length(s) +#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t*, bool); +#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) +#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) +#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) /* * Builder APIs */ -#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_PipeIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_PipeIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_PipeIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_PipeIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_PipeIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_PipeIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_PipeIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_PipeIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_PipeIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_PipeIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_PipeIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_PipeIndices_init(b) mol_fixvec_builder_initialize(b, 128) -#define MolBuilder_PipeIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) -#define MolBuilder_PipeIndices_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_PipeIndices_clear(b) mol_builder_discard(b) -#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) -#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) -#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Pipe_set_read_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Pipe_set_write_pipe(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t); -#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) -#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) -#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Write_set_from_pipe(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_Write_set_to_pipe(b, p, l) mol_table_builder_add(b, 3, p, l) -#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t); -#define MolBuilder_Write_clear(b) mol_builder_discard(b) -#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Writes_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Spawn_set_pipes(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t); -#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) -#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) -#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t); -#define MolBuilder_Data_clear(b) mol_builder_discard(b) +#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_FdIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_FdIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_FdIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_FdIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_FdIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_FdIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_FdIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_FdIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_FdIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_FdIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_FdIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_FdIndices_init(b) mol_fixvec_builder_initialize(b, 128) +#define MolBuilder_FdIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) +#define MolBuilder_FdIndices_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_FdIndices_clear(b) mol_builder_discard(b) +#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Pipe_set_read_fd(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Pipe_set_write_fd(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t); +#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) +#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) +#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Write_set_from_fd(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_Write_set_to_fd(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t); +#define MolBuilder_Write_clear(b) mol_builder_discard(b) +#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Writes_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Spawn_set_fds(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t); +#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) +#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) +#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t); +#define MolBuilder_Data_clear(b) mol_builder_discard(b) /* * Default Value @@ -162,35 +162,39 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t); #define ____ 0x00 -MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_PipeIndices[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { - 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndices[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { + 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { - 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, 0x28, ____, ____, - ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { + 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, + 0x28, ____, ____, ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { - 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { + 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { - 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, 0x18, ____, - ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { + 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, + 0x18, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, + 0x04, ____, ____, ____, }; #undef ____ @@ -199,7 +203,7 @@ MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { * Reader Functions */ -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -213,7 +217,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, b } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -222,45 +226,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, b } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -277,15 +281,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i = 1; i < item_count; i++) { + for (mol_num_t i=1; i end) { @@ -308,7 +312,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Pipe_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -322,7 +326,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -331,57 +335,57 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, } else if (!compatible && field_count > 5) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_PipeIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[4]; - inner.size = offsets[5] - offsets[4]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -398,15 +402,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i = 1; i < item_count; i++) { + for (mol_num_t i=1; i end) { @@ -429,7 +433,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Write_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -443,7 +447,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -452,45 +456,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_PipeIndices_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_FdIndices_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -507,15 +511,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i = 1; i < item_count; i++) { + for (mol_num_t i=1; i end) { @@ -538,7 +542,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Spawn_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -552,7 +556,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, b } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -561,42 +565,42 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, b } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Spawns_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_Pipes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_Writes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Spawns_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Pipes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Writes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } @@ -604,7 +608,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, b * Builder Functions */ -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -616,7 +620,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 8 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -639,31 +643,31 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; if (len == 0) { len = 8; - memcpy(dst, &MolDefault_PipeIndex, len); + memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; if (len == 0) { len = 8; - memcpy(dst, &MolDefault_PipeIndex, len); + memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 24; @@ -679,7 +683,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[9]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -710,16 +714,16 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; if (len == 0) { len = 8; - memcpy(dst, &MolDefault_PipeIndex, len); + memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; @@ -728,16 +732,16 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[7]; if (len == 0) { len = 8; - memcpy(dst, &MolDefault_PipeIndex, len); + memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[9]; @@ -746,13 +750,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_Bytes, len); } else { mol_num_t of = builder.number_ptr[8]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -764,7 +768,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -787,7 +791,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; @@ -796,22 +800,22 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; if (len == 0) { len = 4; - memcpy(dst, &MolDefault_PipeIndices, len); + memcpy(dst, &MolDefault_FdIndices, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -823,7 +827,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder res.seg.size += len == 0 ? 4 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -846,7 +850,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder memcpy(dst, &MolDefault_Spawns, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; @@ -855,7 +859,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder memcpy(dst, &MolDefault_Pipes, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; @@ -864,20 +868,20 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder memcpy(dst, &MolDefault_Writes, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -#ifdef __DEFINE_MOLECULE_API_DECORATOR_DAG +#ifdef __DEFINE_MOLECULE_API_DECORATOR_SPAWN_DAG #undef MOLECULE_API_DECORATOR -#undef __DEFINE_MOLECULE_API_DECORATOR_DAG -#endif /* __DEFINE_MOLECULE_API_DECORATOR_DAG */ +#undef __DEFINE_MOLECULE_API_DECORATOR_SPAWN_DAG +#endif /* __DEFINE_MOLECULE_API_DECORATOR_SPAWN_DAG */ #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* DAG_H */ +#endif /* SPAWN_DAG_H */ diff --git a/script/testdata/spawn_dag.mol b/script/testdata/spawn_dag.mol index 00b0193f97..0e4c9fab1b 100644 --- a/script/testdata/spawn_dag.mol +++ b/script/testdata/spawn_dag.mol @@ -1,21 +1,21 @@ array VmIndex [byte; 8]; -array PipeIndex [byte; 8]; +array FdIndex [byte; 8]; -vector PipeIndices ; +vector FdIndices ; vector Bytes ; table Pipe { vm: VmIndex, - read_pipe: PipeIndex, - write_pipe: PipeIndex, + read_fd: FdIndex, + write_fd: FdIndex, } vector Pipes ; table Write { from: VmIndex, - from_pipe: PipeIndex, + from_fd: FdIndex, to: VmIndex, - to_pipe: PipeIndex, + to_fd: FdIndex, data: Bytes, } vector Writes ; @@ -23,7 +23,7 @@ vector Writes ; table Spawn { from: VmIndex, child: VmIndex, - pipes: PipeIndices, + fds: FdIndices, } vector Spawns ; diff --git a/script/testdata/spawn_dag.rs b/script/testdata/spawn_dag.rs index f44b5189a1..c381c072c0 100644 --- a/script/testdata/spawn_dag.rs +++ b/script/testdata/spawn_dag.rs @@ -9,7 +9,6 @@ #![allow(clippy::write_literal)] use molecule::prelude::*; - #[derive(Clone)] pub struct VmIndex(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for VmIndex { @@ -271,8 +270,8 @@ impl molecule::prelude::Builder for VmIndexBuilder { } } #[derive(Clone)] -pub struct PipeIndex(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for PipeIndex { +pub struct FdIndex(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for FdIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -281,25 +280,25 @@ impl ::core::fmt::LowerHex for PipeIndex { write!(f, "{}", hex_string(self.as_slice())) } } -impl ::core::fmt::Debug for PipeIndex { +impl ::core::fmt::Debug for FdIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl ::core::fmt::Display for PipeIndex { +impl ::core::fmt::Display for FdIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } -impl ::core::default::Default for PipeIndex { +impl ::core::default::Default for FdIndex { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); - PipeIndex::new_unchecked(v) + FdIndex::new_unchecked(v) } } -impl PipeIndex { +impl FdIndex { const DEFAULT_VALUE: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; @@ -331,15 +330,15 @@ impl PipeIndex { pub fn raw_data(&self) -> molecule::bytes::Bytes { self.as_bytes() } - pub fn as_reader<'r>(&'r self) -> PipeIndexReader<'r> { - PipeIndexReader::new_unchecked(self.as_slice()) + pub fn as_reader<'r>(&'r self) -> FdIndexReader<'r> { + FdIndexReader::new_unchecked(self.as_slice()) } } -impl molecule::prelude::Entity for PipeIndex { - type Builder = PipeIndexBuilder; - const NAME: &'static str = "PipeIndex"; +impl molecule::prelude::Entity for FdIndex { + type Builder = FdIndexBuilder; + const NAME: &'static str = "FdIndex"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - PipeIndex(data) + FdIndex(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() @@ -348,10 +347,10 @@ impl molecule::prelude::Entity for PipeIndex { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - PipeIndexReader::from_slice(slice).map(|reader| reader.to_entity()) + FdIndexReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - PipeIndexReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + FdIndexReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() @@ -370,8 +369,8 @@ impl molecule::prelude::Entity for PipeIndex { } } #[derive(Clone, Copy)] -pub struct PipeIndexReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for PipeIndexReader<'r> { +pub struct FdIndexReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for FdIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -380,19 +379,19 @@ impl<'r> ::core::fmt::LowerHex for PipeIndexReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for PipeIndexReader<'r> { +impl<'r> ::core::fmt::Debug for FdIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for PipeIndexReader<'r> { +impl<'r> ::core::fmt::Display for FdIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } -impl<'r> PipeIndexReader<'r> { +impl<'r> FdIndexReader<'r> { pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; @@ -424,14 +423,14 @@ impl<'r> PipeIndexReader<'r> { self.as_slice() } } -impl<'r> molecule::prelude::Reader<'r> for PipeIndexReader<'r> { - type Entity = PipeIndex; - const NAME: &'static str = "PipeIndexReader"; +impl<'r> molecule::prelude::Reader<'r> for FdIndexReader<'r> { + type Entity = FdIndex; + const NAME: &'static str = "FdIndexReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { - PipeIndexReader(slice) + FdIndexReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 @@ -445,15 +444,15 @@ impl<'r> molecule::prelude::Reader<'r> for PipeIndexReader<'r> { Ok(()) } } -pub struct PipeIndexBuilder(pub(crate) [Byte; 8]); -impl ::core::fmt::Debug for PipeIndexBuilder { +pub struct FdIndexBuilder(pub(crate) [Byte; 8]); +impl ::core::fmt::Debug for FdIndexBuilder { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:?})", Self::NAME, &self.0[..]) } } -impl ::core::default::Default for PipeIndexBuilder { +impl ::core::default::Default for FdIndexBuilder { fn default() -> Self { - PipeIndexBuilder([ + FdIndexBuilder([ Byte::default(), Byte::default(), Byte::default(), @@ -465,7 +464,7 @@ impl ::core::default::Default for PipeIndexBuilder { ]) } } -impl PipeIndexBuilder { +impl FdIndexBuilder { pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; @@ -506,9 +505,9 @@ impl PipeIndexBuilder { self } } -impl molecule::prelude::Builder for PipeIndexBuilder { - type Entity = PipeIndex; - const NAME: &'static str = "PipeIndexBuilder"; +impl molecule::prelude::Builder for FdIndexBuilder { + type Entity = FdIndex; + const NAME: &'static str = "FdIndexBuilder"; fn expected_length(&self) -> usize { Self::TOTAL_SIZE } @@ -527,12 +526,12 @@ impl molecule::prelude::Builder for PipeIndexBuilder { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - PipeIndex::new_unchecked(inner.into()) + FdIndex::new_unchecked(inner.into()) } } #[derive(Clone)] -pub struct PipeIndices(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for PipeIndices { +pub struct FdIndices(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for FdIndices { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -541,12 +540,12 @@ impl ::core::fmt::LowerHex for PipeIndices { write!(f, "{}", hex_string(self.as_slice())) } } -impl ::core::fmt::Debug for PipeIndices { +impl ::core::fmt::Debug for FdIndices { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl ::core::fmt::Display for PipeIndices { +impl ::core::fmt::Display for FdIndices { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { @@ -559,13 +558,13 @@ impl ::core::fmt::Display for PipeIndices { write!(f, "]") } } -impl ::core::default::Default for PipeIndices { +impl ::core::default::Default for FdIndices { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); - PipeIndices::new_unchecked(v) + FdIndices::new_unchecked(v) } } -impl PipeIndices { +impl FdIndices { const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; pub const ITEM_SIZE: usize = 8; pub fn total_size(&self) -> usize { @@ -580,27 +579,27 @@ impl PipeIndices { pub fn is_empty(&self) -> bool { self.len() == 0 } - pub fn get(&self, idx: usize) -> Option { + pub fn get(&self, idx: usize) -> Option { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } - pub fn get_unchecked(&self, idx: usize) -> PipeIndex { + pub fn get_unchecked(&self, idx: usize) -> FdIndex { let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; let end = start + Self::ITEM_SIZE; - PipeIndex::new_unchecked(self.0.slice(start..end)) + FdIndex::new_unchecked(self.0.slice(start..end)) } - pub fn as_reader<'r>(&'r self) -> PipeIndicesReader<'r> { - PipeIndicesReader::new_unchecked(self.as_slice()) + pub fn as_reader<'r>(&'r self) -> FdIndicesReader<'r> { + FdIndicesReader::new_unchecked(self.as_slice()) } } -impl molecule::prelude::Entity for PipeIndices { - type Builder = PipeIndicesBuilder; - const NAME: &'static str = "PipeIndices"; +impl molecule::prelude::Entity for FdIndices { + type Builder = FdIndicesBuilder; + const NAME: &'static str = "FdIndices"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - PipeIndices(data) + FdIndices(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() @@ -609,10 +608,10 @@ impl molecule::prelude::Entity for PipeIndices { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - PipeIndicesReader::from_slice(slice).map(|reader| reader.to_entity()) + FdIndicesReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - PipeIndicesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + FdIndicesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() @@ -622,8 +621,8 @@ impl molecule::prelude::Entity for PipeIndices { } } #[derive(Clone, Copy)] -pub struct PipeIndicesReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for PipeIndicesReader<'r> { +pub struct FdIndicesReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for FdIndicesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -632,12 +631,12 @@ impl<'r> ::core::fmt::LowerHex for PipeIndicesReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for PipeIndicesReader<'r> { +impl<'r> ::core::fmt::Debug for FdIndicesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for PipeIndicesReader<'r> { +impl<'r> ::core::fmt::Display for FdIndicesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { @@ -650,7 +649,7 @@ impl<'r> ::core::fmt::Display for PipeIndicesReader<'r> { write!(f, "]") } } -impl<'r> PipeIndicesReader<'r> { +impl<'r> FdIndicesReader<'r> { pub const ITEM_SIZE: usize = 8; pub fn total_size(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() @@ -664,27 +663,27 @@ impl<'r> PipeIndicesReader<'r> { pub fn is_empty(&self) -> bool { self.len() == 0 } - pub fn get(&self, idx: usize) -> Option> { + pub fn get(&self, idx: usize) -> Option> { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } - pub fn get_unchecked(&self, idx: usize) -> PipeIndexReader<'r> { + pub fn get_unchecked(&self, idx: usize) -> FdIndexReader<'r> { let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; let end = start + Self::ITEM_SIZE; - PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } } -impl<'r> molecule::prelude::Reader<'r> for PipeIndicesReader<'r> { - type Entity = PipeIndices; - const NAME: &'static str = "PipeIndicesReader"; +impl<'r> molecule::prelude::Reader<'r> for FdIndicesReader<'r> { + type Entity = FdIndices; + const NAME: &'static str = "FdIndicesReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { - PipeIndicesReader(slice) + FdIndicesReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 @@ -710,32 +709,32 @@ impl<'r> molecule::prelude::Reader<'r> for PipeIndicesReader<'r> { } } #[derive(Debug, Default)] -pub struct PipeIndicesBuilder(pub(crate) Vec); -impl PipeIndicesBuilder { +pub struct FdIndicesBuilder(pub(crate) Vec); +impl FdIndicesBuilder { pub const ITEM_SIZE: usize = 8; - pub fn set(mut self, v: Vec) -> Self { + pub fn set(mut self, v: Vec) -> Self { self.0 = v; self } - pub fn push(mut self, v: PipeIndex) -> Self { + pub fn push(mut self, v: FdIndex) -> Self { self.0.push(v); self } - pub fn extend>(mut self, iter: T) -> Self { + pub fn extend>(mut self, iter: T) -> Self { for elem in iter { self.0.push(elem); } self } - pub fn replace(&mut self, index: usize, v: PipeIndex) -> Option { + pub fn replace(&mut self, index: usize, v: FdIndex) -> Option { self.0 .get_mut(index) .map(|item| ::core::mem::replace(item, v)) } } -impl molecule::prelude::Builder for PipeIndicesBuilder { - type Entity = PipeIndices; - const NAME: &'static str = "PipeIndicesBuilder"; +impl molecule::prelude::Builder for FdIndicesBuilder { + type Entity = FdIndices; + const NAME: &'static str = "FdIndicesBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() } @@ -750,12 +749,12 @@ impl molecule::prelude::Builder for PipeIndicesBuilder { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - PipeIndices::new_unchecked(inner.into()) + FdIndices::new_unchecked(inner.into()) } } -pub struct PipeIndicesIterator(PipeIndices, usize, usize); -impl ::core::iter::Iterator for PipeIndicesIterator { - type Item = PipeIndex; +pub struct FdIndicesIterator(FdIndices, usize, usize); +impl ::core::iter::Iterator for FdIndicesIterator { + type Item = FdIndex; fn next(&mut self) -> Option { if self.1 >= self.2 { None @@ -766,27 +765,27 @@ impl ::core::iter::Iterator for PipeIndicesIterator { } } } -impl ::core::iter::ExactSizeIterator for PipeIndicesIterator { +impl ::core::iter::ExactSizeIterator for FdIndicesIterator { fn len(&self) -> usize { self.2 - self.1 } } -impl ::core::iter::IntoIterator for PipeIndices { - type Item = PipeIndex; - type IntoIter = PipeIndicesIterator; +impl ::core::iter::IntoIterator for FdIndices { + type Item = FdIndex; + type IntoIter = FdIndicesIterator; fn into_iter(self) -> Self::IntoIter { let len = self.len(); - PipeIndicesIterator(self, 0, len) + FdIndicesIterator(self, 0, len) } } -impl<'r> PipeIndicesReader<'r> { - pub fn iter<'t>(&'t self) -> PipeIndicesReaderIterator<'t, 'r> { - PipeIndicesReaderIterator(&self, 0, self.len()) +impl<'r> FdIndicesReader<'r> { + pub fn iter<'t>(&'t self) -> FdIndicesReaderIterator<'t, 'r> { + FdIndicesReaderIterator(&self, 0, self.len()) } } -pub struct PipeIndicesReaderIterator<'t, 'r>(&'t PipeIndicesReader<'r>, usize, usize); -impl<'t: 'r, 'r> ::core::iter::Iterator for PipeIndicesReaderIterator<'t, 'r> { - type Item = PipeIndexReader<'t>; +pub struct FdIndicesReaderIterator<'t, 'r>(&'t FdIndicesReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for FdIndicesReaderIterator<'t, 'r> { + type Item = FdIndexReader<'t>; fn next(&mut self) -> Option { if self.1 >= self.2 { None @@ -797,7 +796,7 @@ impl<'t: 'r, 'r> ::core::iter::Iterator for PipeIndicesReaderIterator<'t, 'r> { } } } -impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for PipeIndicesReaderIterator<'t, 'r> { +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for FdIndicesReaderIterator<'t, 'r> { fn len(&self) -> usize { self.2 - self.1 } @@ -1065,8 +1064,8 @@ impl ::core::fmt::Display for Pipe { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "vm", self.vm())?; - write!(f, ", {}: {}", "read_pipe", self.read_pipe())?; - write!(f, ", {}: {}", "write_pipe", self.write_pipe())?; + write!(f, ", {}: {}", "read_fd", self.read_fd())?; + write!(f, ", {}: {}", "write_fd", self.write_fd())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -1108,20 +1107,20 @@ impl Pipe { let end = molecule::unpack_number(&slice[8..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } - pub fn read_pipe(&self) -> PipeIndex { + pub fn read_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - PipeIndex::new_unchecked(self.0.slice(start..end)) + FdIndex::new_unchecked(self.0.slice(start..end)) } - pub fn write_pipe(&self) -> PipeIndex { + pub fn write_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; - PipeIndex::new_unchecked(self.0.slice(start..end)) + FdIndex::new_unchecked(self.0.slice(start..end)) } else { - PipeIndex::new_unchecked(self.0.slice(start..)) + FdIndex::new_unchecked(self.0.slice(start..)) } } pub fn as_reader<'r>(&'r self) -> PipeReader<'r> { @@ -1152,8 +1151,8 @@ impl molecule::prelude::Entity for Pipe { fn as_builder(self) -> Self::Builder { Self::new_builder() .vm(self.vm()) - .read_pipe(self.read_pipe()) - .write_pipe(self.write_pipe()) + .read_fd(self.read_fd()) + .write_fd(self.write_fd()) } } #[derive(Clone, Copy)] @@ -1176,8 +1175,8 @@ impl<'r> ::core::fmt::Display for PipeReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "vm", self.vm())?; - write!(f, ", {}: {}", "read_pipe", self.read_pipe())?; - write!(f, ", {}: {}", "write_pipe", self.write_pipe())?; + write!(f, ", {}: {}", "read_fd", self.read_fd())?; + write!(f, ", {}: {}", "write_fd", self.write_fd())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -1209,20 +1208,20 @@ impl<'r> PipeReader<'r> { let end = molecule::unpack_number(&slice[8..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn read_pipe(&self) -> PipeIndexReader<'r> { + pub fn read_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn write_pipe(&self) -> PipeIndexReader<'r> { + pub fn write_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; - PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } else { - PipeIndexReader::new_unchecked(&self.as_slice()[start..]) + FdIndexReader::new_unchecked(&self.as_slice()[start..]) } } } @@ -1273,16 +1272,16 @@ impl<'r> molecule::prelude::Reader<'r> for PipeReader<'r> { return ve!(Self, OffsetsNotMatch); } VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - PipeIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - PipeIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + FdIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + FdIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Ok(()) } } #[derive(Debug, Default)] pub struct PipeBuilder { pub(crate) vm: VmIndex, - pub(crate) read_pipe: PipeIndex, - pub(crate) write_pipe: PipeIndex, + pub(crate) read_fd: FdIndex, + pub(crate) write_fd: FdIndex, } impl PipeBuilder { pub const FIELD_COUNT: usize = 3; @@ -1290,12 +1289,12 @@ impl PipeBuilder { self.vm = v; self } - pub fn read_pipe(mut self, v: PipeIndex) -> Self { - self.read_pipe = v; + pub fn read_fd(mut self, v: FdIndex) -> Self { + self.read_fd = v; self } - pub fn write_pipe(mut self, v: PipeIndex) -> Self { - self.write_pipe = v; + pub fn write_fd(mut self, v: FdIndex) -> Self { + self.write_fd = v; self } } @@ -1305,8 +1304,8 @@ impl molecule::prelude::Builder for PipeBuilder { fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.vm.as_slice().len() - + self.read_pipe.as_slice().len() - + self.write_pipe.as_slice().len() + + self.read_fd.as_slice().len() + + self.write_fd.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); @@ -1314,16 +1313,16 @@ impl molecule::prelude::Builder for PipeBuilder { offsets.push(total_size); total_size += self.vm.as_slice().len(); offsets.push(total_size); - total_size += self.read_pipe.as_slice().len(); + total_size += self.read_fd.as_slice().len(); offsets.push(total_size); - total_size += self.write_pipe.as_slice().len(); + total_size += self.write_fd.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.vm.as_slice())?; - writer.write_all(self.read_pipe.as_slice())?; - writer.write_all(self.write_pipe.as_slice())?; + writer.write_all(self.read_fd.as_slice())?; + writer.write_all(self.write_fd.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { @@ -1693,9 +1692,9 @@ impl ::core::fmt::Display for Write { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; - write!(f, ", {}: {}", "from_pipe", self.from_pipe())?; + write!(f, ", {}: {}", "from_fd", self.from_fd())?; write!(f, ", {}: {}", "to", self.to())?; - write!(f, ", {}: {}", "to_pipe", self.to_pipe())?; + write!(f, ", {}: {}", "to_fd", self.to_fd())?; write!(f, ", {}: {}", "data", self.data())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { @@ -1739,11 +1738,11 @@ impl Write { let end = molecule::unpack_number(&slice[8..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } - pub fn from_pipe(&self) -> PipeIndex { + pub fn from_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - PipeIndex::new_unchecked(self.0.slice(start..end)) + FdIndex::new_unchecked(self.0.slice(start..end)) } pub fn to(&self) -> VmIndex { let slice = self.as_slice(); @@ -1751,11 +1750,11 @@ impl Write { let end = molecule::unpack_number(&slice[16..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } - pub fn to_pipe(&self) -> PipeIndex { + pub fn to_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[16..]) as usize; let end = molecule::unpack_number(&slice[20..]) as usize; - PipeIndex::new_unchecked(self.0.slice(start..end)) + FdIndex::new_unchecked(self.0.slice(start..end)) } pub fn data(&self) -> Bytes { let slice = self.as_slice(); @@ -1795,9 +1794,9 @@ impl molecule::prelude::Entity for Write { fn as_builder(self) -> Self::Builder { Self::new_builder() .from(self.from()) - .from_pipe(self.from_pipe()) + .from_fd(self.from_fd()) .to(self.to()) - .to_pipe(self.to_pipe()) + .to_fd(self.to_fd()) .data(self.data()) } } @@ -1821,9 +1820,9 @@ impl<'r> ::core::fmt::Display for WriteReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; - write!(f, ", {}: {}", "from_pipe", self.from_pipe())?; + write!(f, ", {}: {}", "from_fd", self.from_fd())?; write!(f, ", {}: {}", "to", self.to())?; - write!(f, ", {}: {}", "to_pipe", self.to_pipe())?; + write!(f, ", {}: {}", "to_fd", self.to_fd())?; write!(f, ", {}: {}", "data", self.data())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { @@ -1856,11 +1855,11 @@ impl<'r> WriteReader<'r> { let end = molecule::unpack_number(&slice[8..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn from_pipe(&self) -> PipeIndexReader<'r> { + pub fn from_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn to(&self) -> VmIndexReader<'r> { let slice = self.as_slice(); @@ -1868,11 +1867,11 @@ impl<'r> WriteReader<'r> { let end = molecule::unpack_number(&slice[16..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn to_pipe(&self) -> PipeIndexReader<'r> { + pub fn to_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[16..]) as usize; let end = molecule::unpack_number(&slice[20..]) as usize; - PipeIndexReader::new_unchecked(&self.as_slice()[start..end]) + FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn data(&self) -> BytesReader<'r> { let slice = self.as_slice(); @@ -1932,9 +1931,9 @@ impl<'r> molecule::prelude::Reader<'r> for WriteReader<'r> { return ve!(Self, OffsetsNotMatch); } VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - PipeIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + FdIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; VmIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - PipeIndexReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + FdIndexReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; Ok(()) } @@ -1942,9 +1941,9 @@ impl<'r> molecule::prelude::Reader<'r> for WriteReader<'r> { #[derive(Debug, Default)] pub struct WriteBuilder { pub(crate) from: VmIndex, - pub(crate) from_pipe: PipeIndex, + pub(crate) from_fd: FdIndex, pub(crate) to: VmIndex, - pub(crate) to_pipe: PipeIndex, + pub(crate) to_fd: FdIndex, pub(crate) data: Bytes, } impl WriteBuilder { @@ -1953,16 +1952,16 @@ impl WriteBuilder { self.from = v; self } - pub fn from_pipe(mut self, v: PipeIndex) -> Self { - self.from_pipe = v; + pub fn from_fd(mut self, v: FdIndex) -> Self { + self.from_fd = v; self } pub fn to(mut self, v: VmIndex) -> Self { self.to = v; self } - pub fn to_pipe(mut self, v: PipeIndex) -> Self { - self.to_pipe = v; + pub fn to_fd(mut self, v: FdIndex) -> Self { + self.to_fd = v; self } pub fn data(mut self, v: Bytes) -> Self { @@ -1976,9 +1975,9 @@ impl molecule::prelude::Builder for WriteBuilder { fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.from.as_slice().len() - + self.from_pipe.as_slice().len() + + self.from_fd.as_slice().len() + self.to.as_slice().len() - + self.to_pipe.as_slice().len() + + self.to_fd.as_slice().len() + self.data.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { @@ -1987,11 +1986,11 @@ impl molecule::prelude::Builder for WriteBuilder { offsets.push(total_size); total_size += self.from.as_slice().len(); offsets.push(total_size); - total_size += self.from_pipe.as_slice().len(); + total_size += self.from_fd.as_slice().len(); offsets.push(total_size); total_size += self.to.as_slice().len(); offsets.push(total_size); - total_size += self.to_pipe.as_slice().len(); + total_size += self.to_fd.as_slice().len(); offsets.push(total_size); total_size += self.data.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; @@ -1999,9 +1998,9 @@ impl molecule::prelude::Builder for WriteBuilder { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.from.as_slice())?; - writer.write_all(self.from_pipe.as_slice())?; + writer.write_all(self.from_fd.as_slice())?; writer.write_all(self.to.as_slice())?; - writer.write_all(self.to_pipe.as_slice())?; + writer.write_all(self.to_fd.as_slice())?; writer.write_all(self.data.as_slice())?; Ok(()) } @@ -2373,7 +2372,7 @@ impl ::core::fmt::Display for Spawn { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; write!(f, ", {}: {}", "child", self.child())?; - write!(f, ", {}: {}", "pipes", self.pipes())?; + write!(f, ", {}: {}", "fds", self.fds())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -2421,14 +2420,14 @@ impl Spawn { let end = molecule::unpack_number(&slice[12..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } - pub fn pipes(&self) -> PipeIndices { + pub fn fds(&self) -> FdIndices { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; - PipeIndices::new_unchecked(self.0.slice(start..end)) + FdIndices::new_unchecked(self.0.slice(start..end)) } else { - PipeIndices::new_unchecked(self.0.slice(start..)) + FdIndices::new_unchecked(self.0.slice(start..)) } } pub fn as_reader<'r>(&'r self) -> SpawnReader<'r> { @@ -2460,7 +2459,7 @@ impl molecule::prelude::Entity for Spawn { Self::new_builder() .from(self.from()) .child(self.child()) - .pipes(self.pipes()) + .fds(self.fds()) } } #[derive(Clone, Copy)] @@ -2484,7 +2483,7 @@ impl<'r> ::core::fmt::Display for SpawnReader<'r> { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; write!(f, ", {}: {}", "child", self.child())?; - write!(f, ", {}: {}", "pipes", self.pipes())?; + write!(f, ", {}: {}", "fds", self.fds())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -2522,14 +2521,14 @@ impl<'r> SpawnReader<'r> { let end = molecule::unpack_number(&slice[12..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } - pub fn pipes(&self) -> PipeIndicesReader<'r> { + pub fn fds(&self) -> FdIndicesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; - PipeIndicesReader::new_unchecked(&self.as_slice()[start..end]) + FdIndicesReader::new_unchecked(&self.as_slice()[start..end]) } else { - PipeIndicesReader::new_unchecked(&self.as_slice()[start..]) + FdIndicesReader::new_unchecked(&self.as_slice()[start..]) } } } @@ -2581,7 +2580,7 @@ impl<'r> molecule::prelude::Reader<'r> for SpawnReader<'r> { } VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; VmIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - PipeIndicesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + FdIndicesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Ok(()) } } @@ -2589,7 +2588,7 @@ impl<'r> molecule::prelude::Reader<'r> for SpawnReader<'r> { pub struct SpawnBuilder { pub(crate) from: VmIndex, pub(crate) child: VmIndex, - pub(crate) pipes: PipeIndices, + pub(crate) fds: FdIndices, } impl SpawnBuilder { pub const FIELD_COUNT: usize = 3; @@ -2601,8 +2600,8 @@ impl SpawnBuilder { self.child = v; self } - pub fn pipes(mut self, v: PipeIndices) -> Self { - self.pipes = v; + pub fn fds(mut self, v: FdIndices) -> Self { + self.fds = v; self } } @@ -2613,7 +2612,7 @@ impl molecule::prelude::Builder for SpawnBuilder { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.from.as_slice().len() + self.child.as_slice().len() - + self.pipes.as_slice().len() + + self.fds.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); @@ -2623,14 +2622,14 @@ impl molecule::prelude::Builder for SpawnBuilder { offsets.push(total_size); total_size += self.child.as_slice().len(); offsets.push(total_size); - total_size += self.pipes.as_slice().len(); + total_size += self.fds.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.from.as_slice())?; writer.write_all(self.child.as_slice())?; - writer.write_all(self.pipes.as_slice())?; + writer.write_all(self.fds.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { From 9b96f5379369fb96b71da2a6a15803bd6fba6ccd Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 15 Apr 2024 15:56:02 +0800 Subject: [PATCH 073/135] Fix previous PR --- .../tests/ckb_latest/features_since_v2023.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 7e11a0c86d..f73a9efae8 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -959,9 +959,9 @@ pub fn generate_data_graph( writes_builder = writes_builder.push( dag::WriteBuilder::default() .from(build_vm_index(writer.index() as u64)) - .from_pipe(build_pipe_index(writer_pipe_index as u64)) + .from_fd(build_fd_index(writer_pipe_index as u64)) .to(build_vm_index(reader.index() as u64)) - .to_pipe(build_pipe_index(reader_pipe_index as u64)) + .to_fd(build_fd_index(reader_pipe_index as u64)) .data( dag::BytesBuilder::default() .extend(data.iter().map(|b| Byte::new(*b))) @@ -1067,9 +1067,9 @@ pub fn generate_data_graph( let (parent, child) = spawn_dag.edge_endpoints(e).unwrap(); let pipes = { - let mut builder = dag::PipeIndicesBuilder::default(); + let mut builder = dag::FdIndicesBuilder::default(); for p in &spawn_ops[&e.index()] { - builder = builder.push(build_pipe_index(*p as u64)); + builder = builder.push(build_fd_index(*p as u64)); } builder.build() }; @@ -1078,7 +1078,7 @@ pub fn generate_data_graph( dag::SpawnBuilder::default() .from(build_vm_index(parent.index() as u64)) .child(build_vm_index(child.index() as u64)) - .pipes(pipes) + .fds(pipes) .build(), ); } @@ -1089,8 +1089,8 @@ pub fn generate_data_graph( pipes_builder = pipes_builder.push( dag::PipeBuilder::default() .vm(build_vm_index(vm_index as u64)) - .read_pipe(build_pipe_index(reader_pipe_index as u64)) - .write_pipe(build_pipe_index(writer_pipe_index as u64)) + .read_fd(build_fd_index(reader_pipe_index as u64)) + .write_fd(build_fd_index(writer_pipe_index as u64)) .build(), ); } @@ -1111,12 +1111,12 @@ fn build_vm_index(val: u64) -> dag::VmIndex { dag::VmIndexBuilder::default().set(data).build() } -fn build_pipe_index(val: u64) -> dag::PipeIndex { +fn build_fd_index(val: u64) -> dag::FdIndex { let mut data = [Byte::new(0); 8]; for (i, v) in val.to_le_bytes().into_iter().enumerate() { data[i] = Byte::new(v); } - dag::PipeIndexBuilder::default().set(data).build() + dag::FdIndexBuilder::default().set(data).build() } proptest! { From 0e653fb57221a81de5f6d591451f9a2ab01dfe8d Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 16 Apr 2024 09:38:35 +0800 Subject: [PATCH 074/135] Run make fmt --- script/testdata/spawn_cases.c | 18 +- script/testdata/spawn_dag.h | 610 +++++++++++++++++----------------- 2 files changed, 309 insertions(+), 319 deletions(-) diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index 037a838dbe..0af3f62769 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -414,11 +414,9 @@ int child_write_closed_fd() { uint8_t block[7] = {0}; size_t actual_length = 0; - err = write_exact(inherited_fds[CKB_STDOUT], block, sizeof(block), - &actual_length); + err = write_exact(inherited_fds[CKB_STDOUT], block, sizeof(block), &actual_length); CHECK(err); - err = write_exact(inherited_fds[CKB_STDOUT], block, sizeof(block), - &actual_length); + err = write_exact(inherited_fds[CKB_STDOUT], block, sizeof(block), &actual_length); CHECK(err); ckb_close(inherited_fds[CKB_STDIN]); @@ -447,14 +445,12 @@ int parent_pid(uint64_t* pid) { uint64_t child_pid_1 = 0; size_t actual_length = 0; - err = read_exact(fds_1[CKB_STDIN], &child_pid_1, sizeof(child_pid_1), - &actual_length); + err = read_exact(fds_1[CKB_STDIN], &child_pid_1, sizeof(child_pid_1), &actual_length); CHECK(err); CHECK2(child_pid_1 == pid_c1, -1); uint64_t child_pid_2 = 0; - err = read_exact(fds_2[CKB_STDIN], &child_pid_2, sizeof(child_pid_2), - &actual_length); + err = read_exact(fds_2[CKB_STDIN], &child_pid_2, sizeof(child_pid_2), &actual_length); CHECK(err); CHECK2(child_pid_2 == pid_c2, -1); @@ -484,8 +480,7 @@ int parent_spawn_offset_out_of_bound(uint64_t* pid) { int err = 0; const char* argv[] = {"", 0}; - spawn_args_t spgs = { - .argc = 1, .argv = argv, .process_id = pid, .inherited_fds = NULL}; + spawn_args_t spgs = {.argc = 1, .argv = argv, .process_id = pid, .inherited_fds = NULL}; uint64_t offset = 1024 * 1024 * 1024 * 1; uint64_t length = 0; uint64_t bounds = (offset << 32) + length; @@ -500,8 +495,7 @@ int parent_spawn_length_out_of_bound(uint64_t* pid) { int err = 0; const char* argv[] = {"", 0}; - spawn_args_t spgs = { - .argc = 1, .argv = argv, .process_id = pid, .inherited_fds = NULL}; + spawn_args_t spgs = {.argc = 1, .argv = argv, .process_id = pid, .inherited_fds = NULL}; uint64_t offset = 1024 * 14; uint64_t length = 1024; uint64_t bounds = (offset << 32) + length; diff --git a/script/testdata/spawn_dag.h b/script/testdata/spawn_dag.h index 633ce2d03b..31bb594842 100644 --- a/script/testdata/spawn_dag.h +++ b/script/testdata/spawn_dag.h @@ -22,139 +22,139 @@ extern "C" { * Reader APIs */ -#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_FdIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_FdIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_FdIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_FdIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_FdIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_FdIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_FdIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_FdIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_FdIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_FdIndices_verify(s, c) mol_fixvec_verify(s, 8) -#define MolReader_FdIndices_length(s) mol_fixvec_length(s) -#define MolReader_FdIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) -#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) -#define MolReader_Bytes_length(s) mol_fixvec_length(s) -#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) -#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t*, bool); -#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) -#define MolReader_Pipe_get_read_fd(s) mol_table_slice_by_index(s, 1) -#define MolReader_Pipe_get_write_fd(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t*, bool); -#define MolReader_Pipes_length(s) mol_dynvec_length(s) -#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t*, bool); -#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) -#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Write_get_from_fd(s) mol_table_slice_by_index(s, 1) -#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) -#define MolReader_Write_get_to_fd(s) mol_table_slice_by_index(s, 3) -#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t*, bool); -#define MolReader_Writes_length(s) mol_dynvec_length(s) -#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t*, bool); -#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) -#define MolReader_Spawn_get_fds(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t*, bool); -#define MolReader_Spawns_length(s) mol_dynvec_length(s) -#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t*, bool); -#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) -#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) -#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) +#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_FdIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_FdIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_FdIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_FdIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_FdIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_FdIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_FdIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_FdIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_FdIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_FdIndices_verify(s, c) mol_fixvec_verify(s, 8) +#define MolReader_FdIndices_length(s) mol_fixvec_length(s) +#define MolReader_FdIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) +#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_Bytes_length(s) mol_fixvec_length(s) +#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *, bool); +#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) +#define MolReader_Pipe_get_read_fd(s) mol_table_slice_by_index(s, 1) +#define MolReader_Pipe_get_write_fd(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *, bool); +#define MolReader_Pipes_length(s) mol_dynvec_length(s) +#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *, bool); +#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) +#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Write_get_from_fd(s) mol_table_slice_by_index(s, 1) +#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) +#define MolReader_Write_get_to_fd(s) mol_table_slice_by_index(s, 3) +#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *, bool); +#define MolReader_Writes_length(s) mol_dynvec_length(s) +#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *, bool); +#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) +#define MolReader_Spawn_get_fds(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *, bool); +#define MolReader_Spawns_length(s) mol_dynvec_length(s) +#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *, bool); +#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) +#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) +#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) /* * Builder APIs */ -#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_FdIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_FdIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_FdIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_FdIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_FdIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_FdIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_FdIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_FdIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_FdIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_FdIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_FdIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_FdIndices_init(b) mol_fixvec_builder_initialize(b, 128) -#define MolBuilder_FdIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) -#define MolBuilder_FdIndices_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_FdIndices_clear(b) mol_builder_discard(b) -#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) -#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) -#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Pipe_set_read_fd(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Pipe_set_write_fd(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t); -#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) -#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) -#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Write_set_from_fd(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_Write_set_to_fd(b, p, l) mol_table_builder_add(b, 3, p, l) -#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t); -#define MolBuilder_Write_clear(b) mol_builder_discard(b) -#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Writes_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Spawn_set_fds(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t); -#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) -#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) -#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t); -#define MolBuilder_Data_clear(b) mol_builder_discard(b) +#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_FdIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_FdIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_FdIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_FdIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_FdIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_FdIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_FdIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_FdIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_FdIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_FdIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_FdIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_FdIndices_init(b) mol_fixvec_builder_initialize(b, 128) +#define MolBuilder_FdIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) +#define MolBuilder_FdIndices_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_FdIndices_clear(b) mol_builder_discard(b) +#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Pipe_set_read_fd(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Pipe_set_write_fd(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t); +#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) +#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) +#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Write_set_from_fd(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_Write_set_to_fd(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t); +#define MolBuilder_Write_clear(b) mol_builder_discard(b) +#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Writes_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Spawn_set_fds(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t); +#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) +#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) +#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t); +#define MolBuilder_Data_clear(b) mol_builder_discard(b) /* * Default Value @@ -162,39 +162,35 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build #define ____ 0x00 -MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndices[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { - 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, - 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndices[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { + 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { - 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, - 0x28, ____, ____, ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { + 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, 0x28, ____, ____, + ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { - 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, - 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { + 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { - 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, - 0x18, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, - 0x04, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { + 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, 0x18, ____, + ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, }; #undef ____ @@ -203,7 +199,7 @@ MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { * Reader Functions */ -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -217,7 +213,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -226,45 +222,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -281,15 +277,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i=1; i end) { @@ -312,7 +308,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Pipe_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -326,7 +322,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -335,57 +331,57 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, } else if (!compatible && field_count > 5) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[4]; - inner.size = offsets[5] - offsets[4]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -402,15 +398,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i=1; i end) { @@ -433,7 +429,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input inner.size = total_size - offset; return MolReader_Write_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -447,7 +443,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -456,45 +452,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_FdIndices_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_FdIndices_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -511,15 +507,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i=1; i end) { @@ -542,7 +538,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input inner.size = total_size - offset; return MolReader_Spawn_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -556,7 +552,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -565,42 +561,42 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { return MOL_ERR_HEADER; } - mol_num_t offsets[field_count+1]; + mol_num_t offsets[field_count + 1]; offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { + if (offsets[i - 1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count-1] > total_size) { + if (offsets[field_count - 1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Spawns_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_Pipes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_Writes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Spawns_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Pipes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Writes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } @@ -608,7 +604,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, * Builder Functions */ -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -620,7 +616,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 8 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -643,7 +639,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -652,7 +648,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -661,13 +657,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builde memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 24; @@ -683,7 +679,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[9]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -714,7 +710,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -723,7 +719,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -732,7 +728,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[7]; @@ -741,7 +737,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[9]; @@ -750,13 +746,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t build memcpy(dst, &MolDefault_Bytes, len); } else { mol_num_t of = builder.number_ptr[8]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -768,7 +764,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -791,7 +787,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -800,7 +796,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -809,13 +805,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t build memcpy(dst, &MolDefault_FdIndices, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -827,7 +823,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde res.seg.size += len == 0 ? 4 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); + res.seg.ptr = (uint8_t *)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -850,7 +846,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde memcpy(dst, &MolDefault_Spawns, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[3]; @@ -859,7 +855,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde memcpy(dst, &MolDefault_Pipes, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; len = builder.number_ptr[5]; @@ -868,7 +864,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builde memcpy(dst, &MolDefault_Writes, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); + memcpy(dst, src + of, len); } dst += len; mol_builder_discard(builder); From c1ef6b535d314942be8b2611548de4c7328e81a5 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 16 Apr 2024 15:32:08 +0800 Subject: [PATCH 075/135] MAX_FDS only limit alive fd now --- script/src/scheduler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 935dde0037..b750760b38 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -395,7 +395,7 @@ where ); } Message::Pipe(vm_id, args) => { - if self.next_fd_slot - FIRST_FD_SLOT >= MAX_FDS { + if self.fds.len() as u64 >= MAX_FDS { let (_, machine) = self .instantiated .get_mut(&vm_id) From 80fee9d08fb93a748f9d59a535f81cb8f2a26740 Mon Sep 17 00:00:00 2001 From: xjd Date: Tue, 16 Apr 2024 17:05:20 +0800 Subject: [PATCH 076/135] Add spawn test case with lots of resume/suspend (#21) * Add spawn test case * Revert Cargo settings --- .../tests/ckb_latest/features_since_v2023.rs | 36 ++++++++++ script/testdata/Makefile | 4 +- script/testdata/add1.lib | Bin 5728 -> 5416 bytes script/testdata/div2.lib | Bin 5728 -> 5416 bytes script/testdata/mul2.lib | Bin 5728 -> 5416 bytes script/testdata/spawn_cases | Bin 15088 -> 15088 bytes script/testdata/spawn_huge_swap | Bin 0 -> 5224 bytes script/testdata/spawn_huge_swap.c | 65 ++++++++++++++++++ script/testdata/sub1.lib | Bin 5728 -> 5416 bytes 9 files changed, 104 insertions(+), 1 deletion(-) create mode 100755 script/testdata/spawn_huge_swap create mode 100644 script/testdata/spawn_huge_swap.c 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 f73a9efae8..fac884e630 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1185,3 +1185,39 @@ fn check_spawn_length_out_of_bound() { let result = simple_spawn_test("testdata/spawn_cases", &[16]); assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } + +#[test] +fn check_spawn_huge_swap() { + let script_version = SCRIPT_VERSION; + + let (spawn_caller_cell, spawn_caller_data_hash) = + load_cell_from_path("testdata/spawn_huge_swap"); + + 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(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()) + } +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 1d49c6e297..81dacc5b45 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -71,7 +71,8 @@ ALL_BINS := jalr_zero \ spawn_configurable_caller \ spawn_configurable_callee \ spawn_dag \ - spawn_fuzzing + spawn_fuzzing \ + spawn_huge_swap ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -156,3 +157,4 @@ spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h spawn_fuzzing: spawn_fuzzing.c spawn_utils.h +spawn_huge_swap: spawn_huge_swap.c spawn_utils.h \ No newline at end of file diff --git a/script/testdata/add1.lib b/script/testdata/add1.lib index 69a36247da4dd52f071a9b6611d54496d8ac35ae..e6cd7e9c06e71f1e56d1eb1b6eed0e0603aad13c 100755 GIT binary patch literal 5416 zcmeHLO^Xvj5UuPay1JrqPl^ZUps*qi<{*e(b~c%eVaG({F6e29$+8j52b&ShN%7=Q z@Z?|eFL)6=cvum|ld)>1UYwa^WkI}kL-M-bRCQOs=^m(lhz zz(vMePw|p-+&bg&^C?lO^yalP28;qm0i%FXz$jo8FbWt2i~>dhqkvI>6+qqeSPQxD zzh)y5W~?@9-H&RcrhKRNX;ty0;+o=x9Iqy!K81ZM=MVmWA?j|wTD@a$_|4sGcBSG} zoSVm((Bdi%@*-#^B?u6#Zpm-*#&daqY;x)j!)G~N4+DuoZ)t*TesZF^zR zXl}c{7w))QffrKf2dynP2wU~~BX0++*7?q4I*2+?$(ck43HH(3AHHz-krd>m4~e@kIwC_6-o{L+(tZ;auQ6USjUY zY&JqX_80I<93^`rX^2;ou5w4tBI2crEvd*agcvm2dFX1{D>!8AE*QTm7T92e1jiIeEz$z zs_}X~i17LPB}STHeoeyL8sAq(`F@_|ALfPr@?D(g&V97Easavc3C#a7F9>m47XLxx K+i+CO$NvWY+H=GJ literal 5728 zcmeHLOKVd>6h7%~Y<+xgsD)=d^JQpQ=!l9SJ;*G1oD%D=Z3tXbO6FYwxo*Ae5D@uA0v z{@U7PobRD0FE=U0C#=^ZGH!(4r;HHwh&@km>v7;+TWo*=@h@LT_O?2Af<+lQxVgdL z7e4}i1pEm25%446N5GGO9|1oCegyuT2p})Ht%=x=y;4pV|5V$^RYx_CK~A`>{YNxX zmlTgG_9<3!7tLjeQ-kx{CtYy5qK{y@NJ~=k+^sQ87sMcHe`5z7*8H3s}YVjO#3sRdfp;uA-L8-nUkr;wo7y>sdDQ&@GTv zNTwYtpLWS|lMncx`<=|%GFhn{x0Z96Ofu{8vi?eucMrKU@SWpa0|(R#?gf0$xQEVi z|Ibn>2R+U|u)l>~X_9+L?jY##odBPyq4*OU_{aTml{uLk^rKn<;+|uZa?xuLO}frC z8GB3_e0MLm_-CAB+%2Ao?c&8W{)|lmB5sNKzr`JB9B^6f z2cN>O#2vM1n$+UBJO>??C*}d_awAFszUzAUrVB{u$oA1x7B5WMeELI=y z2QD(+YJ!)Xqt+gco=%7guiv~<#(+`4C}0#Y3K#{90!9I&fKk9GU=%P4umY%?9%&)> z{nvCT!i>~Lt@}}J)RgbkKB+1mS6op%m*LeU)TgjdWc>9HNUZa#V(bc zl5_nC6IxuwLZ_s=#T72}O7j*$r!=1@=$Yo{>s)zmapjD>)Bdcwon+#^HK%f1f9L7z zblzL`z&tPSDaU+v-m}Ud==;ZbSC!A^<1)XnPVeqLzu|N!s61}C_iAMd?zfs{ud?0p zf_km7>H1!<SvNz&}cs1!VcjPQ09{Uh@R~=2Aq+4{lP_<_V{ zzYEJ6uh)YJpRHeFqzPu%B)qNhJ$01t=V|_7Ug$61#aZs$M|&#=keeUF>>u-j5Vu9~ MA2hxNN5yRXZ?lbbTL1t6 literal 5728 zcmeHLOKVd>6h7(g%U7+f(5j#pRH#@lsUnmvY|}I?r7^92fQoQQ+mHnEBDsoPh;7}t z6uNNdZz%o%H||_WH=^LC8<(OYy0h_|-1Fttq`1(PcOdy@zB%8VnKN?-&O8o>2^D4NTq)oSi2(AF+nR{|*ehmb@lUmlTy;$I803W8+J9Ih zby4w%V!vWJcQIW;havQzRJ#tvKE;F@f=3(qDfFeZk2Pqk{GUNl3mmNLJdux21%o5z zz*J=Ek~uVF4OxB|9)JdCv50@QnZa2u_Mw(H2=TAwTM7GA%eN8YSIf5(=3mS2&x@ts zpiaU%YwdX#%xcE18-&wQ>62sAO5chVrc!If%YOUVzTWQ%|#fW8z|zYAD}wX_pmCad7&T}+@B&)l~X(L#c()wK+px#;A{ z%EwYsE0=P}a$*nppZlZf2xgP@Us3&k#`TdGw_|`TmuKy3+@Gc&$x%q zaR1L@F$+D;KX9OlUTKnhNbVr$@tpvlsiF828~DflafLaV8}wsZ0pgxxlTy)Z5KX$y zH5q$c8GLs@_z@p+ch&nJVNS-xJ-e>{f%W$Z&NOhePLFpw>Xgm_PhSSSu#blgSM!YG9Tcl|Sf#@;!>)Uok1wOx5eNYPnaZQ_=`2?fNwd rKdky)6&z(wDEP&`$extv&UKW2bsPhs2>+nvUTUO&r22a>Y@+`SZ40=` diff --git a/script/testdata/mul2.lib b/script/testdata/mul2.lib index 5529fbb34cd81601cc03669b1f95a2877758d75d..889d6cf06d4b2e3293d58e932f723db83fbcc8ef 100755 GIT binary patch literal 5416 zcmeHL&ubGw6n^O@TCHg8N%7zw6e{9k3WC^6x5;J=jfut<^t8mZG(z)(W(&3+kAgj6=CCqX0iHs zKX8%pmJ__>9JTgvxIgB(3U6L3W56h26fg=H1&jhl0i%FXz$jo8FbWt2SOL^c&$N*H z{%bN2VTNj>*8Qk9YRY$NpH~&nDlREr$?$3t>QmU~GXCKI7ozU=%jF05ir?72WtU1$ z$+>%q2`#Q-p;OY`;tCgfrFn~>Q<~2c^i1=!b*?N>yP~g{_8*V*lR;y3FEwEbWJEL(gY`-996duIbMQ^Wv=ycnoE;&2n zKD)&j9*`669)*$B?!D}gvo~O?GwAhp`ytlzuPE0$a(1GN4o2)7AkK%}nMlLAzgm*fOzaL;EgCs_D0+guO{8(j+{lrV;=$^s-w&&K8QzNcbH4w=U~4Aao%+p-Ye;L zk4@q5y}G~x`nqYQK!rL0(RY&=LUgRIi_@% literal 5728 zcmeHLOKVd>6h6sq+WM-s69N9p)|JI2dD^_v<+z?FOplZ3$fOX zOQ8#Q{)XZYaO2K}bR!CGx^XEgqB|SU$vt0QO^OR$c?Xhj=9}})nK?6e;LM{)JnHxP z2*sf9B&}_~%ZzEqZjW1$zA+l60RMNm&;oD3e&tQX-#EuZzChlz(?EShKXBpXaq1uS3Qw<3q0z z{au?GjbQnVaNww=x>{DD(L-1%LKZU-W_OS+SmH#s+X@P?cohS0~SU5al z4#cJxE}26^){qs1;Q?rH7K`}Tni-tsVjt>xgAo6EzKyU?^?ZO3zk0r%F#mdfe_ky8 z26YnFS#Qs~VAe8j-5{KfYM&gNHu_eoGSyl$UiRC^_Kki|DBn2$%gXngT&XD`t~bl; z=a_Gnzu#+NZ>#;jygsv*zG^LzJ#lwBbaOIH_O02OaAaa(He$yor>8=(h&>+~k4J2> zWAT~sP~4u0M&}~)6?Wf)fW8#ez6)5z^^B8PB&+BYTwFmdm0hz|62%p=me;dv=Au&| ztB_15tbE!b%Sk@qf9_9YR+q?1<+!z!%Vd&ShnMwNioAQsoq_Kh=NdSuUT`nqd&WI< zhWme(N;&9p{(%E6^h%T5LvjZ}kM9KdObx}K*uX#Tk1Nc{+@K%R3J~`ko0N-QgJ{xq zuF2Tr%HX>L!jJfnyQ|Uv2y-$f?%56X4{W?oaHfHy4SKvw0`=LDt=xijq8;Ii_{RR= zyTf~4P#28-!u;WXnzdpAJ(=8)q6TKUQT>A+DBq*#gH@Aq%~ZWUt5$k-I%SQJ(r#Rn r@WZO#Rl!l_go0n}i|k2d?p#OdSI0>ZitrCw?xkk>hpN91!xsAAGXuC; diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 89f913c0a29f5e30bd7be0592c1e707645881120..e26caac38c43ca1daf52ec9b40162a4548aaed40 100755 GIT binary patch delta 120 zcmexR`k{0~jXI;klLIKz0YH=2C^-$F9ND+3hRtP7WfKO_ zlN~7^0Z@}YDH#c{9NoA5Rucx`lV2&50f3Y9DLDbqlPxM&0l<@mDk%Z*ldmcn0steE a$|_<3;FB#YQ324ie=8XR0id&)EmsW({w*5- diff --git a/script/testdata/spawn_huge_swap b/script/testdata/spawn_huge_swap new file mode 100755 index 0000000000000000000000000000000000000000..3d7ab1ca7a8bac6cba46b420fd2588e1ca70b2e6 GIT binary patch literal 5224 zcmb_ge^gUfp1<$Cymvzg5P4R9sYQPDhwX5*y4b-jn}A8Q9of!wJ3lp>1}$-U^7rgo3R12CV^m*zoN&{)1fyDF4q{(I<6MZ+J|3bC@=v|<@+o6 zHmL2#+I@!w7u05-+C;qy#bcAk%a~($UH@9clU7g0l@sr?T<-8ZlnRzcpDl+0&fbNM?Wh*Jb z77NPDK7%RT8L9YW=)9BXwDgbrNgJg5 zhLH6l`29=St*--ntGzX?uBW7X@_g{mpW; zAVd-s91^%>s#xXD)qnmEd=jA7oIom($#?ZOLWU1d zC1r4l%;tlBihn+wgvvex{PR;uEYr*V8oYMs!$|K>AtUaEbHbfGfZF2|(IGk&9Z6b& zRx!(UM#Kiz#u*V6c$kNP$p%+&l#v^*6d*$%=;GmDXkNjC?AB{xAzTR1i;3y{N)^rj zQca_lwzLgukGAA!iF=3hqLYn3@8DTL+YgIr?#PHI?PHZY>u4`@1I9lc*}!?U7oGc- zpLdLS?1%SEqW$qSo!;B=k2-#bibk{BsB)(x?xHiM!=c7n0^1^EwFXPKg=-$GH0~Y!&6xRz_W&^|#OZq4*R$d5;o$=%R3KdPgh^&8z z%Bb9!mmxDm_lThK1X8@Flx6zEV%i_VwkO2H^!3M1606vrtvr!W!5Rdlu2ADhs{)BQ z(&~UJ>H!exbeF(E`oPOPlLDgAZygJhF;OE1qS5Y5q)R-!0?^M4qRx25C)d`yb=O4e zg(-<^Qfw-|jjbM_XL$z8xsql|he|x9eMCmilUUt$wZ!8X6sAi+qw6J6m_7(T7Zcp+ zZOwlz@w_@H?!E9;R9~ui1N;Bg;EP%J@C{fq#7`&EtFA?5mEx_KEDu{D8U1!pwu60@)>z${ zC@(DrdA$BqT>{t2W`j#%mbuwSbfsZkL>jMB<0sfBGD>LkV9X|=t$k!=H1l7EiM@jT zx}mzd`@Vhr>yoQqO^yV)P}a?#T)8;=#mw0F^}vl$TzzeCy9+!$9jKMfXZ-QNwjD8S z{<(^|lua4QK)<_iQh*tDLG>ift5jbVj>ny>c6Q@+>PWC3A^gpMa>R=%Pe-UN=M1FJ zyE1?mvSDF*Ith(UfdlZ2f!xuCWJv2o)N2% z>i3A4b~;k-A#+)EGovj5pwVMM=$wqi^iX>Hk)GNthstuj?D5K;O4aVMe>FVU{T$aa zR%O`Jy=ObFO}=b7pmGM>{z1MhCrW+U$Cqu1Qa3TCpvdTdW2!BRUFpMfgdzytA~PFs zixY1IGNAvq!`Rz(4eYGAeFz;Rd(t|Ht0L9gzF=mq*$74Bt&Pe4{I}3-iMs-_l zMv|Kn$3*b2C)cQZI^P{c=}%L!jPdM~G|AeV*cSzjEwNONm>wG8n>I#-CWThFHA4Xb zIu27w^mJRF_EAr~Zt$i&1kSiBC~sE^c=I@;hakfZ=LXzzK3OP6reghK7lRxZFR2y;{fk@&1(~I3EJ*2lwBv25Z#V z8bBZ6%^7nIxLJ7a42db}kr-}{4{BLxJwy74^WTScD5)HOFY}lh2+#uxXZ9NsK)wUL zs9e$fGvwhOVd3ts-5$K>apPdWaV22Yb9XkYf2R{#6k61-1|Pam!%AwzmEnOvXvzVF zv&aLpPzSdHb*NX{Q-#Y)y4Uj#jw!NzOp|EyiWR_qq!*snUGHN2*jp95I?E{vABV>} zN1D)4m|WEI`MYF2ovRc&zP{hKU0lYVr?!ZJV_%qiNyf#b(3k*&+!|5`;IZFQIS+2- zaYh901#ZBFG@oTg*YhE$X~ts$e1VJhVMrrDEr%G~HYqZ*T<9>&#FPekVV2MY6{rhl z@=Z{QXqdy`X!@G=9imgJomrzhhHXYlpn7tR-mV95ep4t1CuP{r0dG5;ld~t*PKV!i z^R5-Z@fOJl$xuhU@W<(haCxS|EQN#&9LsXgwzsO=L~GTzUU(;R#^uu4Q)~i% za24q7{D}H~wHCD;I~$9@?TP68{~cABJA1=Z9^LEk-l6Vwy(i_@8por52 zf!D0~TkdjEOWk_{r{zTO+3+*{`*Fn+Z~05p#l41Uuw!^m*x(w|%6=dEn)v-6r^(JB zXZf>!vg;PQ9votfY7p1=_jD}lUo7?IAdZnP79)Qj^`k$%Mb^(Jy*{k}%hT2Fcl!!G z?+y*Px1C;9mlfa{8?7(PpY3t#%z2ZK%nS?*tOBIF@Cif9v$^+k<7Y=d9RDDYJ~|OJ zbvbseZMW%p%rSrFZBJb|PyVW?tjLjzchRn800=hQX~~K3g5Bfi1N1l@#P@_zI)LvAvk!oUyMmznpZW7{hJpoa#+9k^d6x9I z4`)@-ldlXHjPGos^!2j^!J?*4edA2_x&SDu5R}J#*&74kQRTpB>Jqsh4tL}K0nRd3 zW~ek{fAy9AG9Nwx*Wy!E#|ZCe6Y*?s_?&W&=icWgg8%gGQYms`CsIL9a5zSy=k{Ra z`cfWQ^9zeK4+Wm-kKLDEffR6ZvEK`eXc=45O5-hy`06oDo`%}erfQSbQd!lIw+r{p z_4PINnWdJ@+=hbOvWGKceNtf8fJ{E(B8cEMCYlYd=&{SHR zhk&uTxFGWZW69GGX0BhKw?1zj(5=Oc^_2~%5m1?!RA|`x#{7+ykJPR+?IEvH@FmKg4p@aH9*mhcB9yj8+mv1{bnh<`-S-S`#>2RPT{c~-hy|1+j3GOy** zd|PAp>7UBDeBYL)xE15cSmIgf{=WnF$@5G6(~x~JE8(9?e&Q=|^y$WL4UW*={`5uh@8|bD z8NbV)zp+qFHCBshr?tG?To0mjwY91Wn5r!`rKYNy>WW3A)NgF4uC1@Ewv>YkQ(38{ z6kzGR^}uARsH)jnT4k!O!Gq@d9E?1*MfWc{Q<2`dt;A%){i3IyGU-dUMCqLk4W8#GuaFOKb{P%grrFR<|F6xl%#xZ!cr@89mwb!Ob~e) zm+N;}lJm)oQmeeHPwI(aQW-6*59xapkiRqi9r-+r6Z>~>Ir4Wc>GPN*9pfb(B14`{ z_=j!RMmvjMho$dh4=ut7Da*<5;ypimJPa}Y!?-6oqgbWJq2pr<8GOCy*cG+QtSQ9Su4 zc=BKJU+^M$@K6!OlkvUX_r={!Dh2U21Iah<+xKSPd^@x7=9L%J777JIv*;U%^;xMk zeXzQcbc9}`JG99EXJ|S0T~wcW@I}V~Qt8h)C%9WWm)NB%S^Sxp1Vr2d^M8vw)HvXh z+K)a(I}&%?rfE`(8X{M6+0Z zydSv8cq=Jha*kVjID9@PdU@f^Yh?@=1&jhl0i%FXz$jo8FbWt2i~>dhqW~*_y6K4) za^HVV1|rN*ZPdCS)kaPEPVLjG;z`A2#fv#!O+tMN`&7;!{QpAK-F~HV*IxA-Ti5M! z*(p1>jxnLdRV;K$yIWl0La!`u5p>G(MS`ALezwk)=N4Da$UE!Ls@rKM>02`@C-rxc zzD{PnWe?2q@}3IJ=jT1I{Gq;ojCVu%d_FGobL;fc!FJi{P*{E1a39nw6h3ST?4q~VKXAJ3QJ0*Z zai851jP}Wic3(uX)$Tp(kh3>nt25~JcKZ?5^RFn^J92j7iw;KY8z9by+?hzjxxjh6 z%-oO3WPo_=FW}WUO7=$55U(a(_gm3;r6h6uA%U7(e(yE{rRH#@lEh3aIY|}I?r7^92fQoQQ+K?9VBDn>-DAu}h zDRkk^-%$JkZrr($ZbZRNH!ej*bZ6r^x#!EPNpYbo??Cd+d~?1zGiT-woOu+EO!$31 zLNVw&No&XNGNanD*X35EZudeX#Y`- z)D^{JioJ^E+{JVW9fr_n7K`{-n;D$tVjpUGgAo5(zJ;()wR|ffezklXVg9xJ!Ms@d z4eB7Qv(}z>!K`N7xkGJ$^45ygd~ndvuDzzC#&G(U0gvenOU<|Vucm5me(_E=Ax4) zE1yWktX#?=%Sk-sf9{W^SC`02X1TSLO{WtXhnMwNioAQsoq_Kh=Nj0rUT`nqd&WI< zp8J0mi&^M#{(*f>^h%T5LvjZ}kM9KdObx}K*uX#TkL%3I+@K%T3J~`ko0N)PgJ{xC zuF2SA%HX>L!jJfnyQ|*+Fmo~{?%7TC53IjWaHfGHb$Yx@0`=LDt=xijq8;Xn_{RR= zyTg0lfG!yOh55sOl(k|4J(=8)q6TKEQTc-&DBq*#2P!6|nyGqyRxS7HbV?c_rCq-! r;fGYer-I|m2?f8{7ul2Y+_{d@tBw;O6yYDV+)Iu08>)W*!zTLQa#y(9 From 9c51571d4bf51ff7ed9b0f2b63f3b14acb2d5db1 Mon Sep 17 00:00:00 2001 From: joii2020 <87224197+joii2020@users.noreply.github.com> Date: Wed, 17 Apr 2024 08:14:12 +0800 Subject: [PATCH 077/135] Add tests: about spawn load cells (#22) --- .../tests/ckb_latest/features_since_v2023.rs | 13 ++++- script/testdata/spawn_cases | Bin 15088 -> 15696 bytes script/testdata/spawn_cases.c | 46 +++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) 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 fac884e630..9355153830 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1158,7 +1158,6 @@ proptest! { #[test] fn check_spawn_close_invalid_fd() { let result = simple_spawn_test("testdata/spawn_cases", &[12]); - println!("--- err: {:?}", result); assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } @@ -1221,3 +1220,15 @@ fn check_spawn_huge_swap() { assert!(result.is_err()) } } + +#[test] +fn check_spawn_invaild_index() { + let result = simple_spawn_test("testdata/spawn_cases", &[17]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} + +#[test] +fn check_spawn_index_out_of_bound() { + let result = simple_spawn_test("testdata/spawn_cases", &[18]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index e26caac38c43ca1daf52ec9b40162a4548aaed40..7d4a305ff39ed5214bf6daae7087b27dc536fc5f 100755 GIT binary patch delta 3181 zcma)8e^6A%9e?lOp2vaS(?jlu$8j7SKb{r=VLYzRC1C``nW)KJorx0%C`VE|5yXO1 z?T|Ze-W`!iD`ZV4$+Y6o7AbLr^lAukoWp4}jgjf4f27s6`a&Ixl+JsmkP&O7yKi^z z4%0vSX1?t1_vh#PW0zC9;>Y_-H2k**gsl~ojQUArWq5pM;le?ZH25slA`U#)4!q%A zqa2!Ps`YD|LqXZ0RKIuYW|~HCi+-5Cky}+}?FEsD1I+95*fNlnIhB3FX$*@FS&7L* z5un8 zuABp5VqIl?xHF-8@5TgDS=?vj9IL5{tQck&eO;<#2}-1_q@?}slCL55LdW#WptrXm zdNkY3+MqYCKNDl#^Vu{C2=Uj{gRr&`Tw8DDw1q0}x%F06m)Buk`BSRKNWvb+|Jc~?B9_Etj- z12J+6EpntvsjvnH2Cj1n8+^w>XfzxSE*UUrpwac{VQrm5U!>K zA6(y%sPFuSL{@8TWhg7J?X*3mJ5u0QGKal-oP#Z4WXt_M1vr=MrQ0&Qc|Y<&IwIZv zIO!vpiF`n8S4R&!!}`uS|FZ-=nwx%AidrvAfsc;)-kdl9=VnL}dId3?=XGd;z!`g+ zhjddKyg1y%`HR9copg4Q8wL(0)d);3`3}XVU#{-Zwy5Si^FAa%qdG@6TS66M?;P`u z!g}ic4G2|M^48{3!(o{))_{2a+e^^Qu;_y0L zh?5V%V{^`$e)Whm-}4oC?96fYrzJ*7GA#Vh0r_QtNCA`;Ca~-)JWsiLmq523mjl6n z(e?f|n)04c@x3S2OSuWOb(=p)B38@@G1y)7SWg{{O@N;io2{_f==qUOUO*W;tkbRP zwL{vk72DAxgr@miaTNkEQ+yZRSZpAxcZRnm4P>P@5=|*8OFZJGS$+EF7;e7JHoFxOC#pg^ZHpgquuRMy1(N#dmbE_uU+Wq`Ei|F2XtVF z>angC)0MPuUgxJBpoWfeeEH!@g|FeLk2`271Balu^I7V*8{P0p!A4-`#+p*i;+Kb1cY$9Bq9ukLw?7iZ3YBO0 zmmp>k?da&ndNyFVD2R0zu|3a+>)1N4qFI1*KPiaK7gg&Ef;fP8!-DwhDB>AHg4lz0 zQs65=%tcbEF)oPJ(R3dBax=pbUZ?t-)y!*<&v@XHApTvijnkQr>p&ne3AZm?nM7`4 zFv#EDQ+KZk;{8dKuKEDFlFiGD9`h|uqG}&rZ;7&Nxq0X8 z`r)4(wf>nVZF9Rc_*VFP1q{oub$wyB9-I<#p1(Iih0C9jogxS6&M=8H(nr*6B+VUo zp@$E=jqc4ef2Q!pvs2)WME8|>*h+ai;p1x>!Eg;(An4^eNsHJ(#-(mw%?0q$=2L;b z%`Af`2-14vs-r>tF}m5Fh$F)36`{E^jeeeomyv^Re_U z7BW-dK9qh=q;?0EzK9oQ4&+yv8hH4#6L}8tm~ADt%kan}wDm-t@H3&l%BS!N-voM~ zHyiQRWWiP;BCRC+bEuZ^Ls8M^CHxPHF@KZM#mN?#{F>o;Qlm&9tA>OYauyF~w`LaaYe^nV9Bs!i-)q9>|D?COJUN1G46;%_|I z=5PIBG;M1(YdPF}q_wRRa~j*bIvd+xYW!|{SDPQ?xNid4oxeJ(g1ABpsPGs;c@4jo z&czgwI>2)^|`7~=h>PO--=HP7=WiK4?Z=3wVu5H E0^95l7XSbN delta 2793 zcmZuzeN0nV6o0QDk5Vf=Qr{TbFwM<5tTQ^;yn#t3=|P>DX|1;;J&2spd-e)dZ41zt*xx9 zm2Cd_v-j_*RR>-Kzt_xVqGHVTz{k*FRG&o00K=5aanWj{S3^soZmGoww0H-^DIB9! z8?{;*=nPf{YlC*fdJXLj9$*DkDz-|YhUcvnoR@J|!qa*;t=iP$Gcwr>@G9Q9#%IgJ z&;25!Xw`665b=| zn+e~-LxXi@15Hv9n;wn8L{_?|PHJ0il$3I zLs>a2$E=gOBYN&fa&YQ#4wkT!CGk2TIFjff%XwDQIut|ci1^2~NQ~MkCbH%!S1Ih#-1ucHYP}?Se%k3e+_4_cO^e9a^FkcU>d*v%X6yTfN;k!(uGR|1o$4Lf zMrIdx&GFhqy}zA}RP2anS=Gw+NGm2d(!lA)}O7;~Q-mZXHw&dY5f9j8j*ZZ5%o^ zAAQ5>wR)}Nuw`*weL4lFw22oqtW1u}5xwtno90los?|%E?JJ|f9((+oelB`ct)W#3 zgOfiy$fKE?JX=zq=hb8c{$4tUy~`Y-FUu@C$Ky8e$ZnsbAAkA}oblSE|2i+4*yB10 z=Ukrg(#(Pk!}#A@J0QhS(vQ55iC0H?K`XDiKjDQ01syz*Sw?#T_jut}5c{*NcPYKp z5mG&t#H@Z^*d9c2V(;+6NxbUeh0ZRd3moT#MtK$c883W|tl}$)7xo1;ERK~=wfb0{ z9B)`PszNdQl78ofzckw0q?dg<@D{nSeV#khvS&s- zHk^(AVUMfeJVk+vIfp#{OqxRCgR&b+36up;>`*u;CMYpbp4e&X#9W#>0>ux-2c;Cs z5KmK=vS{ikl)Dgj6UqP-W*%O%%G(Uz$xzlQ`~47qFpG|o9d2fV`}231uS4DIkD5}$ ze;~mR-iV?Tls_bt27^9=FP0j6B`yaCb5GGFpfGRm>1?U zFFxTL#d>-UR$o+(y#i)0i1*x4td1mX6&34qMPJ8ay;;$Zz%7e-F2Q<5O+6ucLR>MZ zRG3>k|Q-wpdv zluN-UCt~0h1z#=WQH2$S;_xBSzn0N%9A`T9PBL~FRU8h1;|t^IGr`V4Ye-S&4wEDVYHG#85+0hCMF&m5&EuymlUyOdY6fe@{;2^c& ZZ1KYA<~+Q+0> Date: Wed, 17 Apr 2024 14:10:00 +0800 Subject: [PATCH 078/135] Clean --- script/src/verify/tests/ckb_latest/features_since_v2023.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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 9355153830..06f4f62944 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -851,15 +851,12 @@ fn check_spawn_configurable() { #[allow(dead_code)] #[path = "../../../../testdata/spawn_dag.rs"] mod spawn_dag; -use molecule::prelude::Byte; -use spawn_dag as dag; -// use spawn_dag::*; use ckb_types::bytes::Bytes; use daggy::{Dag, Walker}; +use molecule::prelude::Byte; use rand::{rngs::StdRng, Rng, SeedableRng}; +use spawn_dag as dag; use std::collections::{HashSet, VecDeque}; -// use ckb_types::core::DepType; -// use ckb_types::packed::CellDep; pub fn generate_data_graph( seed: u64, From 5ddedfd4085c94cbb8e04abd0c8bf51447f0c023 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 17 Apr 2024 20:21:09 +0800 Subject: [PATCH 079/135] Charge cycles when vm suspending/resumeing --- script/src/scheduler.rs | 37 +++++++++++++++---- script/src/types.rs | 2 + .../tests/ckb_latest/features_since_v2023.rs | 7 +++- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index b750760b38..413c0ec9de 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,7 +1,7 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, - WAIT_FAILURE, + INDEX_OUT_OF_BOUND, INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, + SPAWN_EXTRA_CYCLES_BASE, SUCCESS, WAIT_FAILURE, }; use crate::types::MachineContext; use crate::verify::TransactionScriptsSyscallsGenerator; @@ -55,6 +55,7 @@ where max_vms_count: u64, total_cycles: Cycle, + extra_cycles: Cycle, next_vm_id: VmId, next_fd_slot: u64, states: BTreeMap, @@ -86,6 +87,7 @@ where syscalls_generator, max_vms_count: MAX_VMS_COUNT, total_cycles: 0, + extra_cycles: 0, next_vm_id: FIRST_VM_ID, next_fd_slot: FIRST_FD_SLOT, states: BTreeMap::default(), @@ -110,12 +112,13 @@ where full: FullSuspendedState, ) -> Self { let message_box = Arc::clone(&syscalls_generator.message_box); - Self { + let mut scheduler = Self { tx_data, script_version, syscalls_generator, max_vms_count: full.max_vms_count, total_cycles: full.total_cycles, + extra_cycles: 0, next_vm_id: full.next_vm_id, next_fd_slot: full.next_fd_slot, states: full @@ -133,7 +136,11 @@ where .collect(), message_box, terminated_vms: full.terminated_vms.into_iter().collect(), - } + }; + scheduler + .ensure_vms_instantiated(&full.instantiated_ids) + .unwrap(); + scheduler } /// Suspend current scheduler into a serializable full state @@ -141,8 +148,8 @@ where assert!(self.message_box.lock().expect("lock").is_empty()); let mut vms = Vec::with_capacity(self.states.len()); let instantiated_ids: Vec<_> = self.instantiated.keys().cloned().collect(); - for id in instantiated_ids { - self.suspend_vm(&id)?; + for id in &instantiated_ids { + self.suspend_vm(id)?; } for (id, state) in self.states { let snapshot = self @@ -160,6 +167,7 @@ where fds: self.fds.into_iter().collect(), inherited_fd: self.inherited_fd.into_iter().collect(), terminated_vms: self.terminated_vms.into_iter().collect(), + instantiated_ids, }) } @@ -192,6 +200,7 @@ where }; while self.states[&ROOT_VM_ID] != VmState::Terminated { + self.extra_cycles = 0; let consumed_cycles = self.iterate(pause.clone(), limit_cycles)?; limit_cycles = limit_cycles .checked_sub(consumed_cycles) @@ -294,9 +303,19 @@ where self.instantiated.remove(&vm_id_to_run); self.suspended.remove(&vm_id_to_run); } - Ok(consumed_cycles) + self.total_cycles = self + .total_cycles + .checked_add(self.extra_cycles) + .ok_or(Error::CyclesOverflow)?; + Ok(consumed_cycles + self.extra_cycles) + } + Err(Error::Yield) => { + self.total_cycles = self + .total_cycles + .checked_add(self.extra_cycles) + .ok_or(Error::CyclesOverflow)?; + Ok(consumed_cycles + self.extra_cycles) } - Err(Error::Yield) => Ok(consumed_cycles), Err(e) => Err(e), } } @@ -760,6 +779,7 @@ where return Err(Error::Unexpected(format!("VM {:?} is not suspended!", id))); } let snapshot = &self.suspended[id]; + self.extra_cycles += SPAWN_EXTRA_CYCLES_BASE; let (context, mut machine) = self.create_dummy_vm(id)?; { let mut sc = context.snapshot2_context().lock().expect("lock"); @@ -778,6 +798,7 @@ where id ))); } + self.extra_cycles += SPAWN_EXTRA_CYCLES_BASE; let (context, machine) = self .instantiated .get_mut(id) diff --git a/script/src/types.rs b/script/src/types.rs index 87fa70a125..38d76ef924 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -493,6 +493,7 @@ pub struct FullSuspendedState { pub fds: Vec<(Fd, VmId)>, pub inherited_fd: Vec<(VmId, Vec)>, pub terminated_vms: Vec<(VmId, i8)>, + pub instantiated_ids: Vec, } impl FullSuspendedState { @@ -521,6 +522,7 @@ impl FullSuspendedState { + (self.fds.len() * (size_of::() + size_of::()))) as u64 + (self.inherited_fd.len() * (size_of::())) as u64 + (self.terminated_vms.len() * (size_of::() + size_of::())) as u64 + + (self.instantiated_ids.len() * size_of::()) as u64 } } 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 06f4f62944..49ae89d23c 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1209,10 +1209,15 @@ fn check_spawn_huge_swap() { resolved_dep_groups: vec![], }; let verifier = TransactionScriptsVerifierWithEnv::new(); + + let tic = std::time::Instant::now(); let result = verifier.verify(script_version, &rtx, 70_000_000); + let toc = tic.elapsed().as_millis(); if script_version >= ScriptVersion::V2 { let msg = result.unwrap_err().to_string(); - assert!(msg.contains("ExceededMaximumCycles")) + assert!(msg.contains("ExceededMaximumCycles")); + // Normally, this test should take less than 1 second. + assert!(toc < 5000); } else { assert!(result.is_err()) } From 9f816b7182628056f6dbfc7b55b3b71320b71861 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 18 Apr 2024 10:40:48 +0800 Subject: [PATCH 080/135] Remove eprintln! --- script/src/verify.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index 64275c0ce8..24308dfb7c 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -853,7 +853,6 @@ where match self.verify_group_with_chunk(group, remain_cycles, &None) { Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { current_used = wrapping_cycles_add(current_used, consumed_cycles, group)?; - eprintln!("used_cycles: {:?}", used_cycles); cycles = wrapping_cycles_add(cycles, consumed_cycles, group)?; } Ok(ChunkState::Suspended(state)) => { From 7cbc55db11eb9dc0656cf2d357b402421c6f3d3f Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 18 Apr 2024 10:49:29 +0800 Subject: [PATCH 081/135] Quick fix previous commit --- script/src/verify.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index 24308dfb7c..4f17c4f139 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -851,7 +851,7 @@ where })?; match self.verify_group_with_chunk(group, remain_cycles, &None) { - Ok(ChunkState::Completed(used_cycles, consumed_cycles)) => { + Ok(ChunkState::Completed(_, consumed_cycles)) => { current_used = wrapping_cycles_add(current_used, consumed_cycles, group)?; cycles = wrapping_cycles_add(cycles, consumed_cycles, group)?; } From 97876b848ffe1ebfe58c8295c0632dca9c92b3f9 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 18 Apr 2024 11:16:51 +0800 Subject: [PATCH 082/135] Add {current_used} for ScriptError --- script/src/verify.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index 4f17c4f139..43e4e565a3 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -845,7 +845,7 @@ where for (idx, (_hash, group)) in self.groups().enumerate().skip(current + 1) { let remain_cycles = limit_cycles.checked_sub(current_used).ok_or_else(|| { ScriptError::Other(format!( - "here expect invalid cycles {limit_cycles} {cycles}" + "expect invalid cycles {limit_cycles} {current_used} {cycles}" )) .source(group) })?; From bb1d25fcd91229f9cea22b98e90123ef9d2908f8 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 18 Apr 2024 14:21:54 +0800 Subject: [PATCH 083/135] Add ensure_vms_instantiated for Message::Pipe --- script/src/scheduler.rs | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 413c0ec9de..f34c1b8757 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -414,11 +414,12 @@ where ); } Message::Pipe(vm_id, args) => { + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; if self.fds.len() as u64 >= MAX_FDS { - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; machine.machine.set_register(A0, MAX_FDS_CREATED as u64); continue; } @@ -426,23 +427,15 @@ where self.next_fd_slot = slot; self.fds.insert(p1, vm_id); self.fds.insert(p2, vm_id); - - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - machine - .machine - .memory_mut() - .store64(&args.fd1_addr, &p1.0)?; - machine - .machine - .memory_mut() - .store64(&args.fd2_addr, &p2.0)?; - machine.machine.set_register(A0, SUCCESS as u64); - } + machine + .machine + .memory_mut() + .store64(&args.fd1_addr, &p1.0)?; + machine + .machine + .memory_mut() + .store64(&args.fd2_addr, &p2.0)?; + machine.machine.set_register(A0, SUCCESS as u64); } Message::FdRead(vm_id, args) => { if !(self.fds.contains_key(&args.fd) && (self.fds[&args.fd] == vm_id)) { From 5fec33caad280ac545f3bc3491c6066acc8ba9bc Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 22 Apr 2024 10:33:29 +0800 Subject: [PATCH 084/135] cleanup test --- script/src/verify/tests/ckb_latest/features_since_v2019.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/script/src/verify/tests/ckb_latest/features_since_v2019.rs b/script/src/verify/tests/ckb_latest/features_since_v2019.rs index d2f32c00c8..4a25ef1602 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2019.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2019.rs @@ -1188,7 +1188,6 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_resume_load_cycles(step_cycles: loop { let state = init_state.take().unwrap(); let (limit_cycles, _last) = state.next_limit_cycles(step_cycles, TWO_IN_TWO_OUT_CYCLES); - //eprintln!("limit_cycles: {}", limit_cycles); match verifier.resume_from_state(state, limit_cycles).unwrap() { VerifyResult::Suspended(state) => init_state = Some(state), VerifyResult::Completed(cycle) => { @@ -1214,6 +1213,5 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_resume_load_cycles(step_cycles: "step_cycles {step_cycles}" ); } - assert_eq!(cycles, cycles_once, "step_cycles {step_cycles}"); } From 6f9374dd1abfdbb34404b2818114054545513cca Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 22 Apr 2024 10:43:57 +0800 Subject: [PATCH 085/135] fix test for chunk count --- script/src/verify/tests/ckb_latest/features_since_v2021.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index d75ebe6bcf..3207667780 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -1435,7 +1435,7 @@ fn test_exec( .verify_until_completed(script_version, &rtx) .unwrap(); assert_eq!(cycles, cycles_once); - assert!(chunks_count <= expected_chunks_count); + assert_eq!(chunks_count, expected_chunks_count); } Err(e) => { assert!(result.is_err()); From 956047ee0c050478a5565138608a2d28538553ed Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 22 Apr 2024 10:56:21 +0800 Subject: [PATCH 086/135] add comments --- script/src/verify.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/script/src/verify.rs b/script/src/verify.rs index 43e4e565a3..723dc37059 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -52,6 +52,7 @@ mod tests; pub enum ChunkState { Suspended(Option), + // (total_cycles, consumed_cycles in last chunk) Completed(Cycle, Cycle), } From 6d325127c24bf30261a5df40bdfe585c74db7ea1 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 22 Apr 2024 11:14:23 +0800 Subject: [PATCH 087/135] cleanup clippy --- verification/traits/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/verification/traits/src/lib.rs b/verification/traits/src/lib.rs index 2697791518..14473e25ef 100644 --- a/verification/traits/src/lib.rs +++ b/verification/traits/src/lib.rs @@ -1,7 +1,6 @@ #![allow(clippy::bad_bit_mask)] //! The trait abstract for particular verification -#![allow(clippy::bad_bit_mask)] use bitflags::bitflags; use ckb_error::Error; From dc3bb2527d0be1b462855dc54f50ca7d54b21f14 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 22 Apr 2024 17:06:21 +0800 Subject: [PATCH 088/135] Add spawn cycles testcase --- script/testdata/Makefile | 6 +- script/testdata/spawn_cases.c | 10 +- script/testdata/spawn_cycles | Bin 0 -> 7488 bytes script/testdata/spawn_cycles.c | 162 +++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 10 deletions(-) create mode 100755 script/testdata/spawn_cycles create mode 100644 script/testdata/spawn_cycles.c diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 81dacc5b45..3fead0fe69 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -72,7 +72,8 @@ ALL_BINS := jalr_zero \ spawn_configurable_callee \ spawn_dag \ spawn_fuzzing \ - spawn_huge_swap + spawn_huge_swap \ + spawn_cycles ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -157,4 +158,5 @@ spawn_configurable_caller: spawn_configurable_caller.c spawn_utils.h spawn_configurable_callee: spawn_configurable_callee.c spawn_utils.h spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h spawn_fuzzing: spawn_fuzzing.c spawn_utils.h -spawn_huge_swap: spawn_huge_swap.c spawn_utils.h \ No newline at end of file +spawn_huge_swap: spawn_huge_swap.c spawn_utils.h +spawn_cycles: spawn_cycles.c spawn_utils.h diff --git a/script/testdata/spawn_cases.c b/script/testdata/spawn_cases.c index ded149dacf..11fb6270a4 100644 --- a/script/testdata/spawn_cases.c +++ b/script/testdata/spawn_cases.c @@ -515,10 +515,7 @@ int parent_invaild_index(uint64_t* pid) { err = ckb_pipe(&inherited_fds[i * 2]); CHECK(err); } - spawn_args_t spgs = {.argc = 1, - .argv = argv, - .process_id = pid, - .inherited_fds = inherited_fds}; + spawn_args_t spgs = {.argc = 1, .argv = argv, .process_id = pid, .inherited_fds = inherited_fds}; err = ckb_spawn(0xFFFFFFFFF, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); CHECK2(err == 1, -1); // INDEX_OUT_OF_BOUND err = 0; @@ -535,10 +532,7 @@ int parent_index_out_of_bound(uint64_t* pid) { err = ckb_pipe(&inherited_fds[i * 2]); CHECK(err); } - spawn_args_t spgs = {.argc = 1, - .argv = argv, - .process_id = pid, - .inherited_fds = inherited_fds}; + spawn_args_t spgs = {.argc = 1, .argv = argv, .process_id = pid, .inherited_fds = inherited_fds}; err = ckb_spawn(2, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); CHECK2(err == 1, -1); // INDEX_OUT_OF_BOUND err = 0; diff --git a/script/testdata/spawn_cycles b/script/testdata/spawn_cycles new file mode 100755 index 0000000000000000000000000000000000000000..06242b26281033f6000dbd440c537582649af17b GIT binary patch literal 7488 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 P>^+dkb9r)^<_`TYT;qJG literal 0 HcmV?d00001 diff --git a/script/testdata/spawn_cycles.c b/script/testdata/spawn_cycles.c new file mode 100644 index 0000000000..bec89c98ac --- /dev/null +++ b/script/testdata/spawn_cycles.c @@ -0,0 +1,162 @@ +#include +#include + +#include "ckb_syscalls.h" +#include "spawn_utils.h" + +const uint64_t SYSCALL_CYCLES_BASE = 500; +const uint64_t SPAWN_EXTRA_CYCLES_BASE = 100000; +const uint64_t SPAWN_YIELD_CYCLES_BASE = 800; + +int tic() { + static uint64_t tic = 0; + uint64_t cur_cycles = ckb_current_cycles(); + printf("cur_cycles %d tic %d", cur_cycles, tic); + uint64_t toc = cur_cycles - tic; + tic = cur_cycles; + return toc; +} + +uint64_t cal_cycles(uint64_t nbase, uint64_t yield, uint64_t extra) { + uint64_t r = 0; + r += SYSCALL_CYCLES_BASE * nbase; + r += SPAWN_YIELD_CYCLES_BASE * yield; + r += SPAWN_EXTRA_CYCLES_BASE * extra; + return r; +} + +int main() { + int err = 0; + int toc = 0; + uint64_t cid = ckb_process_id(); + printf("vm %d: init", cid); + uint64_t pid[5] = {0}; + uint64_t fds[5][2][3] = {0}; + uint64_t buf[256] = {0}; + uint64_t len = 0; + + switch (cid) { + case 0: + const char* argv[1] = {0}; + + for (int i = 1; i < 5; i++) { + toc = tic(); + err = ckb_pipe(buf); + CHECK(err); + toc = tic(); + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + fds[i][0][0] = buf[0]; + fds[i][1][1] = buf[1]; + + toc = tic(); + err = ckb_pipe(buf); + CHECK(err); + toc = tic(); + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + fds[i][0][1] = buf[1]; + fds[i][1][0] = buf[0]; + } + + // Living Process: 0 + // Living Process: 0, 1 + // Living Process: 0, 1, 2 + // Living Process: 0, 1, 2, 3 + // Living Process: 1, 2, 3, 4 + // Living Process: 0, 2, 3, 4 + for (int i = 1; i < 5; i++) { + toc = tic(); + spawn_args_t spgs = {.argc = 0, .argv = argv, .process_id = &pid[i], .inherited_fds = fds[i][1]}; + err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); + CHECK(err); + toc = tic(); + if (i < 5) { + CHECK2(toc > cal_cycles(1, 1, 1), ErrorCommon); + } else { + CHECK2(toc > cal_cycles(1, 1, 4), ErrorCommon); + } + } + + // Living Process: 0, 2, 3, 4 + // Living Process: 0, 1, 3, 4 + // Living Process: 0, 2, 3, 4 + for (int i = 1; i < 5; i++) { + len = 12; + toc = tic(); + err = ckb_write(fds[i][0][1], "Hello World!", &len); + toc = tic(); + CHECK(err); + if (i < 3) { + CHECK2(toc > cal_cycles(1, 1, 2), ErrorCommon); + } else { + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + } + err = ckb_close(fds[i][0][1]); + CHECK(err); + toc = tic(); + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + } + + // Living Process: 0, 2, 3, 4 + // Living Process: 0, 1, 3, 4 + // Living Process: 0, 2, 3, 4 + // Living Process: 0, 3, 4 + // Living Process: 0, 4 + // Living Process: 0 + for (int i = 1; i < 5; i++) { + len = 1024; + toc = tic(); + err = ckb_read_all(fds[i][0][0], buf, &len); + CHECK(err); + toc = tic(); + if (i == 1) { + CHECK2(toc > cal_cycles(1, 1, 2), ErrorCommon); + } + if (i == 2) { + CHECK2(toc > cal_cycles(1, 1, 1), ErrorCommon); + } + if (i >= 3) { + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + } + CHECK2(len == 12, ErrorCommon); + err = memcmp("Hello World!", buf, len); + CHECK(err); + } + + for (int i = 1; i < 5; i++) { + int8_t exit_code = 255; + toc = tic(); + err = ckb_wait(pid[i], &exit_code); + CHECK(err); + toc = tic(); + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK(exit_code); + } + break; + case 1: + case 2: + case 3: + case 4: + len = 2; + toc = tic(); + err = ckb_inherited_file_descriptors(fds[cid][1], &len); + CHECK(err); + toc = tic(); + CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(len == 2, ErrorCommon); + len = 1024; + err = ckb_read_all(fds[cid][1][0], buf, &len); + CHECK(err); + CHECK2(len == 12, ErrorCommon); + err = memcmp("Hello World!", buf, len); + CHECK(err); + err = ckb_write(fds[cid][1][1], buf, &len); + CHECK(err); + err = ckb_close(fds[cid][1][1]); + CHECK(err); + break; + } + +exit: + printf("vm %d: done", cid); + return err; +} From 7b198a3d6a4a366dd9796d4e5c546665197b7c4c Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 22 Apr 2024 17:14:36 +0800 Subject: [PATCH 089/135] Fix previous commit --- .../tests/ckb_latest/features_since_v2023.rs | 34 ++++++++++++++++++ script/testdata/spawn_cases | Bin 15696 -> 15696 bytes script/testdata/spawn_cycles | Bin 7488 -> 7280 bytes script/testdata/spawn_cycles.c | 3 -- 4 files changed, 34 insertions(+), 3 deletions(-) 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 49ae89d23c..f1f8999e64 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1234,3 +1234,37 @@ fn check_spawn_index_out_of_bound() { let result = simple_spawn_test("testdata/spawn_cases", &[18]); assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } + +#[test] +fn check_spawn_cycles() { + let script_version = SCRIPT_VERSION; + + let (spawn_caller_cell, spawn_caller_data_hash) = load_cell_from_path("testdata/spawn_cycles"); + let (spawn_callee_cell, _spawn_callee_data_hash) = load_cell_from_path("testdata/spawn_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); + if script_version >= ScriptVersion::V2 { + assert_eq!(result.unwrap(), 1524396); + } +} diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index 7d4a305ff39ed5214bf6daae7087b27dc536fc5f..ba20ddd3b9f1a768cb6c617f2bec2d40125a4ccb 100755 GIT binary patch delta 73 zcmV-P0Ji_odeC~XG%EpslQk>R0Z@|%EFS@olP4@g0>C7bY%C}n@FWTB0|WsA8RX_* fB85g|req~yf`Foi69xdYuPoyN0-z+blrOvu#eEtd delta 73 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 P>^+dkb9r)^<_`TYT;qJG diff --git a/script/testdata/spawn_cycles.c b/script/testdata/spawn_cycles.c index bec89c98ac..f455ccc26f 100644 --- a/script/testdata/spawn_cycles.c +++ b/script/testdata/spawn_cycles.c @@ -11,7 +11,6 @@ const uint64_t SPAWN_YIELD_CYCLES_BASE = 800; int tic() { static uint64_t tic = 0; uint64_t cur_cycles = ckb_current_cycles(); - printf("cur_cycles %d tic %d", cur_cycles, tic); uint64_t toc = cur_cycles - tic; tic = cur_cycles; return toc; @@ -29,7 +28,6 @@ int main() { int err = 0; int toc = 0; uint64_t cid = ckb_process_id(); - printf("vm %d: init", cid); uint64_t pid[5] = {0}; uint64_t fds[5][2][3] = {0}; uint64_t buf[256] = {0}; @@ -157,6 +155,5 @@ int main() { } exit: - printf("vm %d: done", cid); return err; } From 9ca668754ba707755beff0cce680713ef2cd2c72 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 23 Apr 2024 09:12:54 +0800 Subject: [PATCH 090/135] Update spawn_cycles --- .../tests/ckb_latest/features_since_v2023.rs | 2 +- script/testdata/spawn_cycles | Bin 7280 -> 7544 bytes script/testdata/spawn_cycles.c | 46 +++++++++++++----- 3 files changed, 34 insertions(+), 14 deletions(-) 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 f1f8999e64..f35ebad614 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1265,6 +1265,6 @@ fn check_spawn_cycles() { let result = verifier.verify_without_limit(script_version, &rtx); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); if script_version >= ScriptVersion::V2 { - assert_eq!(result.unwrap(), 1524396); + assert_eq!(result.unwrap(), 1524861); } } diff --git a/script/testdata/spawn_cycles b/script/testdata/spawn_cycles index dc0cea2c11be80e0f9df13c021e24c278d657b56..77d40c54fe680d95986657c08cd7d1f00be1dc2c 100755 GIT binary patch delta 2914 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 jb>{bZ8|VgXiB+%I@qD~y|) diff --git a/script/testdata/spawn_cycles.c b/script/testdata/spawn_cycles.c index f455ccc26f..dc394623f4 100644 --- a/script/testdata/spawn_cycles.c +++ b/script/testdata/spawn_cycles.c @@ -24,6 +24,14 @@ uint64_t cal_cycles(uint64_t nbase, uint64_t yield, uint64_t extra) { return r; } +uint64_t cal_cycles_floor(uint64_t nbase, uint64_t yield, uint64_t extra) { + return cal_cycles(nbase, yield, extra); +} + +uint64_t cal_cycles_upper(uint64_t nbase, uint64_t yield, uint64_t extra) { + return cal_cycles(nbase, yield, extra) + 8192; +} + int main() { int err = 0; int toc = 0; @@ -42,7 +50,8 @@ int main() { err = ckb_pipe(buf); CHECK(err); toc = tic(); - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); fds[i][0][0] = buf[0]; fds[i][1][1] = buf[1]; @@ -50,7 +59,8 @@ int main() { err = ckb_pipe(buf); CHECK(err); toc = tic(); - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); fds[i][0][1] = buf[1]; fds[i][1][0] = buf[0]; } @@ -67,10 +77,12 @@ int main() { err = ckb_spawn(0, CKB_SOURCE_CELL_DEP, 0, 0, &spgs); CHECK(err); toc = tic(); - if (i < 5) { - CHECK2(toc > cal_cycles(1, 1, 1), ErrorCommon); + if (i < 4) { + CHECK2(toc > cal_cycles_floor(1, 1, 1), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 1), ErrorCommon); } else { - CHECK2(toc > cal_cycles(1, 1, 4), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 4), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 4), ErrorCommon); } } @@ -84,14 +96,17 @@ int main() { toc = tic(); CHECK(err); if (i < 3) { - CHECK2(toc > cal_cycles(1, 1, 2), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 2), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 2), ErrorCommon); } else { - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); } err = ckb_close(fds[i][0][1]); CHECK(err); toc = tic(); - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); } // Living Process: 0, 2, 3, 4 @@ -107,13 +122,16 @@ int main() { CHECK(err); toc = tic(); if (i == 1) { - CHECK2(toc > cal_cycles(1, 1, 2), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 2), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 2), ErrorCommon); } if (i == 2) { - CHECK2(toc > cal_cycles(1, 1, 1), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 1), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 1), ErrorCommon); } if (i >= 3) { - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); } CHECK2(len == 12, ErrorCommon); err = memcmp("Hello World!", buf, len); @@ -126,7 +144,8 @@ int main() { err = ckb_wait(pid[i], &exit_code); CHECK(err); toc = tic(); - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); CHECK(exit_code); } break; @@ -139,7 +158,8 @@ int main() { err = ckb_inherited_file_descriptors(fds[cid][1], &len); CHECK(err); toc = tic(); - CHECK2(toc > cal_cycles(1, 1, 0), ErrorCommon); + CHECK2(toc > cal_cycles_floor(1, 1, 0), ErrorCommon); + CHECK2(toc < cal_cycles_upper(1, 1, 0), ErrorCommon); CHECK2(len == 2, ErrorCommon); len = 1024; err = ckb_read_all(fds[cid][1][0], buf, &len); From a7acf9f73791f201f15ccab6089c6c388f088785 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 09:06:20 +0800 Subject: [PATCH 091/135] MAX_VMS_COUNT is now a constant --- script/src/scheduler.rs | 7 +------ script/src/types.rs | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index f34c1b8757..20611cc628 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -53,7 +53,6 @@ where script_version: ScriptVersion, syscalls_generator: TransactionScriptsSyscallsGenerator
, - max_vms_count: u64, total_cycles: Cycle, extra_cycles: Cycle, next_vm_id: VmId, @@ -85,7 +84,6 @@ where tx_data, script_version, syscalls_generator, - max_vms_count: MAX_VMS_COUNT, total_cycles: 0, extra_cycles: 0, next_vm_id: FIRST_VM_ID, @@ -116,7 +114,6 @@ where tx_data, script_version, syscalls_generator, - max_vms_count: full.max_vms_count, total_cycles: full.total_cycles, extra_cycles: 0, next_vm_id: full.next_vm_id, @@ -159,7 +156,6 @@ where vms.push((id, state, snapshot)); } Ok(FullSuspendedState { - max_vms_count: self.max_vms_count, total_cycles: self.total_cycles, next_vm_id: self.next_vm_id, next_fd_slot: self.next_fd_slot, @@ -342,8 +338,7 @@ where if !fds_valid { continue; } - if self.suspended.len() + self.instantiated.len() > self.max_vms_count as usize - { + if self.suspended.len() + self.instantiated.len() > MAX_VMS_COUNT as usize { self.ensure_vms_instantiated(&[vm_id])?; let (_, machine) = self .instantiated diff --git a/script/src/types.rs b/script/src/types.rs index 38d76ef924..0a1ecc422d 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -485,7 +485,6 @@ impl TryFrom<(u64, u64, u64)> for DataPieceId { /// fully recover the running environment with the full transaction environment. #[derive(Clone, Debug)] pub struct FullSuspendedState { - pub max_vms_count: u64, pub total_cycles: Cycle, pub next_vm_id: VmId, pub next_fd_slot: u64, From f64d93dc85907f2a5d98430e993b2e84d32335c8 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 11:33:57 +0800 Subject: [PATCH 092/135] Fix load_cell_data --- script/src/syscalls/load_cell_data.rs | 25 ++++++++--- .../syscalls/tests/vm_latest/syscalls_1.rs | 43 +++++++++++++++++++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index 72272716fa..9640517fe0 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -52,14 +52,25 @@ where .map_err(|e| VMError::Unexpected(e.to_string()))?; if size == 0 { - let (cell, _) = sc + match sc .data_source() - .load_data(&data_piece_id, offset, u64::max_value())?; - machine - .memory_mut() - .store64(&size_addr, &Mac::REG::from_u64(cell.len() as u64))?; - machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); - return Ok(()); + .load_data(&data_piece_id, offset, u64::max_value()) + { + Ok((cell, _)) => { + machine + .memory_mut() + .store64(&size_addr, &Mac::REG::from_u64(cell.len() as u64))?; + machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); + return Ok(()); + } + Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + } } let (wrote_size, full_size) = diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index 001a31394f..776febb958 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -2135,3 +2135,46 @@ fn test_load_cell_data_size_zero() { assert_eq!(machine.memory_mut().load64(&size_addr).unwrap(), 256); assert_eq!(machine.memory_mut().load64(&addr).unwrap(), 0); } + +#[test] +fn test_load_cell_data_size_zero_index_out_of_bound() { + let mut machine = SCRIPT_VERSION.init_core_machine_without_limit(); + let size_addr: u64 = 100; + let addr = 4096; + let data = [0xff; 256]; + + machine.set_register(A0, addr); // addr + machine.set_register(A1, size_addr); // size + machine.set_register(A2, 0); // offset + machine.set_register(A3, 8); // index + machine.set_register(A4, u64::from(Source::Transaction(SourceEntry::CellDep))); //source + machine.set_register(A7, LOAD_CELL_DATA_SYSCALL_NUMBER); // syscall number + + machine.memory_mut().store64(&size_addr, &0).unwrap(); + + let data = Bytes::from(data.to_vec()); + let dep_cell = build_cell_meta(10000, data.clone()); + let input_cell = build_cell_meta(100, data.clone()); + + let data_loader = new_mock_data_loader(); + + let rtx = Arc::new(ResolvedTransaction { + transaction: TransactionBuilder::default().build(), + resolved_cell_deps: vec![dep_cell], + resolved_inputs: vec![input_cell], + resolved_dep_groups: vec![], + }); + let mut load_code = LoadCellData::new(Arc::new(Mutex::new(Snapshot2Context::new(TxData { + rtx, + data_loader, + program: Bytes::new(), + script_group: Arc::new(ScriptGroup { + script: Default::default(), + group_type: ScriptGroupType::Lock, + input_indices: vec![0], + output_indices: vec![0], + }), + })))); + load_code.ecall(&mut machine).unwrap(); + assert_eq!(machine.registers()[A0], u64::from(INDEX_OUT_OF_BOUND)); +} From e19079406e0ff8de56ac9605874791d1a80b122a Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 14:38:39 +0800 Subject: [PATCH 093/135] Use an internal struct for WaitForWrite and WaitForRead --- script/src/scheduler.rs | 54 ++++++++++++++++++----------------------- script/src/types.rs | 32 ++++++++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 20611cc628..8463e4e418 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -9,7 +9,7 @@ use crate::ScriptVersion; use crate::types::{ set_vm_max_cycles, CoreMachineType, DataPieceId, Fd, FdArgs, FullSuspendedState, Machine, - Message, RunMode, TxData, VmId, VmState, FIRST_FD_SLOT, FIRST_VM_ID, + Message, ReadState, RunMode, TxData, VmId, VmState, WriteState, FIRST_FD_SLOT, FIRST_VM_ID, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; @@ -458,12 +458,12 @@ where // Return code will be updated when the read operation finishes self.states.insert( vm_id, - VmState::WaitForRead { + VmState::WaitForRead(ReadState { fd: args.fd, length: args.length, buffer_addr: args.buffer_addr, length_addr: args.length_addr, - }, + }), ); } Message::FdWrite(vm_id, args) => { @@ -492,13 +492,13 @@ where // Return code will be updated when the write operation finishes self.states.insert( vm_id, - VmState::WaitForWrite { + VmState::WaitForWrite(WriteState { fd: args.fd, consumed: 0, length: args.length, buffer_addr: args.buffer_addr, length_addr: args.length_addr, - }, + }), ); } Message::InheritedFileDescriptor(vm_id, args) => { @@ -569,23 +569,23 @@ where } fn process_io(&mut self) -> Result<(), Error> { - let mut reads: HashMap = HashMap::default(); + let mut reads: HashMap = HashMap::default(); let mut closed_fds: Vec = Vec::new(); self.states.iter().for_each(|(vm_id, state)| { - if let VmState::WaitForRead { fd, .. } = state { - if self.fds.contains_key(&fd.other_fd()) { - reads.insert(*fd, (*vm_id, state.clone())); + if let VmState::WaitForRead(inner_state) = state { + if self.fds.contains_key(&inner_state.fd.other_fd()) { + reads.insert(inner_state.fd, (*vm_id, inner_state.clone())); } else { closed_fds.push(*vm_id); } } }); - let mut pairs: Vec<[(VmId, VmState); 2]> = Vec::new(); + let mut pairs: Vec<(VmId, ReadState, VmId, WriteState)> = Vec::new(); self.states.iter().for_each(|(vm_id, state)| { - if let VmState::WaitForWrite { fd, .. } = state { - if self.fds.contains_key(&fd.other_fd()) { - if let Some((read_vm_id, read_state)) = reads.get(&fd.other_fd()) { - pairs.push([(*read_vm_id, read_state.clone()), (*vm_id, state.clone())]); + if let VmState::WaitForWrite(inner_state) = state { + if self.fds.contains_key(&inner_state.fd.other_fd()) { + if let Some((read_vm_id, read_state)) = reads.get(&inner_state.fd.other_fd()) { + pairs.push((*read_vm_id, read_state.clone(), *vm_id, inner_state.clone())); } } else { closed_fds.push(*vm_id); @@ -595,7 +595,7 @@ where // Finish read / write syscalls for fds that are closed on the other end for vm_id in closed_fds { match self.states[&vm_id].clone() { - VmState::WaitForRead { length_addr, .. } => { + VmState::WaitForRead(ReadState { length_addr, .. }) => { self.ensure_vms_instantiated(&[vm_id])?; let (_, read_machine) = self .instantiated @@ -608,11 +608,11 @@ where read_machine.machine.set_register(A0, SUCCESS as u64); self.states.insert(vm_id, VmState::Runnable); } - VmState::WaitForWrite { + VmState::WaitForWrite(WriteState { consumed, length_addr, .. - } => { + }) => { self.ensure_vms_instantiated(&[vm_id])?; let (_, write_machine) = self .instantiated @@ -629,26 +629,20 @@ where } } // Transfering data from write fds to read fds - for [(read_vm_id, read_state), (write_vm_id, write_state)] in pairs { - let VmState::WaitForRead { + for (read_vm_id, read_state, write_vm_id, write_state) in pairs { + let ReadState { length: read_length, buffer_addr: read_buffer_addr, length_addr: read_length_addr, .. - } = read_state - else { - unreachable!() - }; - let VmState::WaitForWrite { + } = read_state; + let WriteState { fd: write_fd, mut consumed, length: write_length, buffer_addr: write_buffer_addr, length_addr: write_length_addr, - } = write_state - else { - unreachable!() - }; + } = write_state; self.ensure_vms_instantiated(&[read_vm_id, write_vm_id])?; { @@ -706,13 +700,13 @@ where // Only update write VM state self.states.insert( write_vm_id, - VmState::WaitForWrite { + VmState::WaitForWrite(WriteState { fd: write_fd, consumed, length: write_length, buffer_addr: write_buffer_addr, length_addr: write_length_addr, - }, + }), ); } } diff --git a/script/src/types.rs b/script/src/types.rs index 0a1ecc422d..8078b0cfaf 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -381,6 +381,23 @@ impl Fd { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct ReadState { + pub fd: Fd, + pub length: u64, + pub buffer_addr: u64, + pub length_addr: u64, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct WriteState { + pub fd: Fd, + pub consumed: u64, + pub length: u64, + pub buffer_addr: u64, + pub length_addr: u64, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum VmState { Runnable, @@ -389,19 +406,8 @@ pub enum VmState { target_vm_id: VmId, exit_code_addr: u64, }, - WaitForWrite { - fd: Fd, - consumed: u64, - length: u64, - buffer_addr: u64, - length_addr: u64, - }, - WaitForRead { - fd: Fd, - length: u64, - buffer_addr: u64, - length_addr: u64, - }, + WaitForWrite(WriteState), + WaitForRead(ReadState), } #[derive(Clone, Debug)] From 3c45fc49a9725142414b22c19574fa35fd19b0f1 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 15:38:51 +0800 Subject: [PATCH 094/135] Add a debug_assert_eq to check extra_cycles is 0 --- script/src/scheduler.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 8463e4e418..2830da8dc1 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -312,7 +312,11 @@ where .ok_or(Error::CyclesOverflow)?; Ok(consumed_cycles + self.extra_cycles) } - Err(e) => Err(e), + Err(e) => { + // In this case, there should be no vm instantiated/uninstantiated state switch. + debug_assert_eq!(self.extra_cycles, 0); + Err(e) + } } } From 564cc61544adc27dc9ba3967420094c60faa1512 Mon Sep 17 00:00:00 2001 From: joii2020 <87224197+joii2020@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:41:34 +0800 Subject: [PATCH 095/135] Add test: read\write cycles --- .../tests/ckb_latest/features_since_v2023.rs | 52 +++++++++ script/testdata/Makefile | 4 +- script/testdata/spawn_io_cycles | Bin 0 -> 7768 bytes script/testdata/spawn_io_cycles.c | 109 ++++++++++++++++++ 4 files changed, 164 insertions(+), 1 deletion(-) create mode 100755 script/testdata/spawn_io_cycles create mode 100644 script/testdata/spawn_io_cycles.c 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 f35ebad614..d6539cfcb1 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1268,3 +1268,55 @@ fn check_spawn_cycles() { assert_eq!(result.unwrap(), 1524861); } } + +fn spawn_io_test(io_size: u64, enable_check: bool) -> Result { + let script_version = SCRIPT_VERSION; + + let mut args = vec![0u8; 16]; + args[..8].copy_from_slice(&io_size.to_le_bytes()); + args[8] = enable_check as u8; + + let (cell, data_hash) = load_cell_from_path("testdata/spawn_io_cycles"); + let script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(data_hash) + .args(Bytes::copy_from_slice(&args).pack()) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(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![cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + let verifier = TransactionScriptsVerifierWithEnv::new(); + verifier.verify_without_limit(script_version, &rtx) +} + +#[test] +fn check_spawn_io_cycles() { + if SCRIPT_VERSION != ScriptVersion::V2 { + return; + } + + let offset_size = 1024; + let r = spawn_io_test(128, true); + r.unwrap(); + let r = spawn_io_test(128 + offset_size, true); + r.unwrap(); + + let r = spawn_io_test(128, false); + let cycles1 = r.unwrap(); + let r = spawn_io_test(128 + offset_size, false); + let cycles2 = r.unwrap(); + + assert_eq!(cycles2 - cycles1, offset_size / 2); +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 3fead0fe69..71325a06c4 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -73,7 +73,8 @@ ALL_BINS := jalr_zero \ spawn_dag \ spawn_fuzzing \ spawn_huge_swap \ - spawn_cycles + spawn_cycles \ + spawn_io_cycles ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -160,3 +161,4 @@ spawn_dag: spawn_dag.c spawn_dag.h spawn_dag_escape_encoding.h spawn_fuzzing: spawn_fuzzing.c spawn_utils.h spawn_huge_swap: spawn_huge_swap.c spawn_utils.h spawn_cycles: spawn_cycles.c spawn_utils.h +spawn_io_cycles: spawn_io_cycles.c spawn_utils.h diff --git a/script/testdata/spawn_io_cycles b/script/testdata/spawn_io_cycles new file mode 100755 index 0000000000000000000000000000000000000000..f9edfd9dfb3c0f413826ae98fb50d447f545149c GIT binary patch literal 7768 zcmb_BYgkm*wQHX<=bQl%Mi1dNh{z}!lX6W+G%*dAfiR1b`Rh>rq^N%LqLO>%E6Is`~!geU`em6^NtJP^&-`}N1& zeCO=F*Iuu^9-BSu{3_$;296L2G!Cu+n_brUV5$Cvs94{CK~v#A;P4#;YA>$f$GL&Q zMn3wsNFOxNgXRX7h{NNOZ+?8P4?ocRp!in#M}E5J){mD7dE6M>22vzswGdv zRz;LJje75PM|Bsl@v-fS)#i5Cx*(-jktFV|CWo~fTJrQu6Ro;Kb3KEa`1$vL-;!rJ zVsq0Sb0uM=IfEF?24XZD74@H5icn}6428Ai&99clT90hCf$pFLgK%(miz(3>^ueH} z^0E2V))f(3_r8!|y-+OXq?Ko9S5*#bjxU;D{q>Rg)dy-iO&KOx91;|(^(9#lHVneY zg;$R-==c+|2;vR+qw6b{E$^TuXW$R7=_=oZs>-U$==BFO_YR*P`tai42F~=>TyGis zvgi5hE5>q%gC9OnomBUSx<77GJfW#HQkp(euejZA`g+)OWh9g{rzwI)q>4D5qzBi} z$@t=4ISja2duXteUubibO1$hI3Db(9`~zD$iTtuVjOKg>^2;M(0`CxCgx1C`kK+l6 zcW#izm1{{rYo~bW^gbq`IN(ba+El^;Cl2Nub{@!duWgY1U^|p zi-mQ&o%x@-otvjzlp}&UvW=FU^3nv?BQDQ&NN;mO{vN7oRR?H}xSi3b+~%J-U**1i za6glZ^31uRawKw4Xh>cNS~_?j6fGSx5bV_eoLr2JMfj%eG9L+E>sR)<*_u=19PnCu zb10YDAgh3TuAOe4qWYx&u6ljHv*gneKi06bEd44<-Nap&d8D(2jb(RaHe?@WGyy+3 z3#z})Y_PT~qnS`@d(EkgZh8xG{GyzfQ2%r79Rc4Tobdg$ z!(I&0ITBnSV;A`Q_g5@_vqP4yc${IL`j=yU z7r!02)Qj0y{m1&n4F~FIrLd6ioC4-YC@(BLkvAT>NIM-eR;3IplD0|-ew34gHx;H_ z4BB5%vlrvkI<=~q;g|o_I>i~e+(RBZVPJFFrUknsxRue-Fxoc)o20)r?M$z-A#9w% z-ZW6xNQ@%w;mFTum@8h9dN}hED!4G`j*D$I^J}Qu6-Nj5g(^~|NL8)`#1*O5^%UQ! z1vy8hA+vEsQtBhX`Q5$|MOq-zZ}){T3(&By4K&K7393~>8i0nW7V;S(u(zfF^{r~Q z8s+L4Ks|Yn+okV3Rgve)x%Zdi#=g~tHG9`Qg1IT@gaet~R^Qn!=gjtw zzB(-DJmekyfG`zdtMB2c+6y~>822bS!F8GKtgYTTxNkr!bzZd^9ZmhPBJXM=eVv_2 z3naA1bVUNm8RzQb7loib!nqShGP|HAr6-|Rzr<{0zR9!>4*g^QtdIkn-)W~Y%Zblp zvhXO!y!KnvMa7{cfy{QsxGu6a{TAwPT5V2`{5j@t5w zy(toYyPMCDKwB@3x77#yDM(Jw$aS9=oikk*{9a0(V+dfh)sWeA<46?qIeI*%t)6*W zkeIKXv92CQ;SBG*fLbl!JMsLQt<>BBcePvQhQO>4lm@gL4`;+`s~4mbN1098jM?yk zDMP7(RC1Kfso0r_Jk(@%r-Oem1Qe+OQpPNXsj$#Wx2Yq_pQH`q-Ga2LX;lNBdE!N| z7-K;Q8Nc>G$nW&ZMpY`U4S_BjEs7-DL$N?l#F z`4Q(d;WT;3Iq>?ICI|DlGtAYeNJHW*mIv_Q4l?`pB{F(M5nmD8Y*h1Eyf>a3B~3Z5 zDbg#VcP_a!ij*o+9{Vy?e1eU>D#hbSL+w(6QYNWrlN2wPNovYTvw5^;OIbxD7g*}V2;t=G!Ok7NvxvZ!<{17Yo+mk_nhlS-G8i?Z4qF7n|XwJsBVh#?x;uk zd@S8DHikZ8IbZj-+@xlw{U$NCA~L_-YNX?NGyIu`d1qFVrwqfiJ%TC_jli{Ru4;Bh z<#>Eq`V87qnW{xw<~A&SyP(=xvif_wbj@?rX46+iniYA=3~+4jCO^*Bw2iMH^I72P zpm+bfB#lxkshGZWtElnXKrKzTH%Y{PR?^$gjHV`cpM~3Yr$y=&pFQknM@b-e!dwS7 z=QfNVyVQ{DJ?rr72yxi{?DubpYYxkxkQ=dTJ=U^0x;@D2vq#WF&KXkgZ`wf2QpJ)74@&+S3+a3GYjX5O5IWS&kqD(sbSpNAYikO3hWCem z7d|NC-P##5>c)H3=)FKKQYxJyCd}W$&IvJr?-sx+uoWF#f{F+s^!rhzGzBi(@LY($ ze|^IB#Ic8mGlw3#_{6|7z0dcI8|i3waFCIISAd;*+Ss>Xs*%?A&9l6F8(6yL;BBYN ztrSU~&4R2-0l6-jD9enM91%fR(=cUR4+rT>Uq!!Zqh1TB0BLLX%!3LgrG=h4JnS$DN-We zZ9*vmO1TZC%t0yl0{6tNAR^Rdtirsyui@kZm?- zwL}sss1q&SbC3!-p(prv(Vt`#b>WHS+f!`s9i6}B zu6MkiYK(*FVM)8+vK89+RtYTojll1>!QYL#_&m6gUneBJ=+v^C8FP|W6wT*jS141+y0uPN$}1%}7#tgv|r z9bXyC-zR|nWjWLxW-+S4Vu%9XI1e17-Ne4V20m*%A`;Jdgf>zlyx~4@HGa{!NCHw3 zsg0;1R~tWRG|v?>Xw;Rc*E54M=&(DA&v*)W!xG@rS3+`W7tzMy>7Cm}_>2uuvPCQN zBsn)1%D31ftYrBXxojbjMEqSJPF){{YqJu;9_I0AZDCMnh|Zwb`=&Rar_qtJT-N15 z{=NOv<;XCu-14BLpEk{s(3{u;>giH4IiD&wg>joK%CdfPq7akGvnUjZA}#^lo>Q1f z>2UJZKUkHj%VFbj6_~jOyrn#WIi3s2Wlw_kHY+S`sgCq0Y*G_GnOEPHPS(uS=*Pf{vRh2>bOwEvq z%9D^&m7^zBm0OJ@!&y7xzS>c~9^=Q7R4WcA3~@bNFE_wl47N_H3e~lLZiJzmKE%VrKgHYCuLCRX!ewXcY+^EbU! z7t`wy=7L%?5%KEu%79iad3MyRvxly{5+da3qZpU8rewr7XGCeZ4;K%ld@wlV`S|H? zxF@$7Y0xNadosvqKRXx37tt3+MT;RC_=kcp@^1$g^%mp(z#@Km!_y53;r1pQnf1zZ z4g8TH;KIo()MVolY7}89Jchrbe&Nv_tOH+lEYT|FTqsT}Zz<uUrHODS)8rbZu z0qy`+1Ke?ww`sIW!!HVg6{fw`ww_mjAjZH1Mok`z0Q~^JFbHV)h{j^9gSSuJe$s5j zdr;^ImuwrxGeiOzZz3Rm#Dkf8Y0GN+w}w5}oHa=Z|<{eEt!(!x#AbF|X>3>|{=|r1Y@dQmZ#v zC!)1>Y+^T6UK=v%J*xXJT8y<|S*Ql{N6n|r#$@S=_wK+iQUluWn|`--<-*<-re9kZ zfWKy2`}qW?7B8o10}Pu+j&e8WR;qBb)jOJRtg{uS_oFu|wnH6F70W6*01k-+_6WY` zz@%{ic2nFJB(=NU7X-yVP0T}gK(Edc#|#4XG(qNPCMaj4P= zg{2Gc$-jHuf~+;{mCarhU%2>xG#+dB2mST?$!J(Cgn5y^ecTM^;YW3QMBpci_mi<1 z{N^tPY?X0U!4ICBF#%)*aJbsw|3(qwN0{k{@9@JpKm2w-{MUYXCGT6f=bykI^21}$ zx2!$SK1yKw1wI5do!FQEJH&E?Psf!PB7FE=3>n)Jd>DL(|GUXEUMRqSV6VY_wf)=8 zc3b0xbI|7h?%_v=3LG##OG143kNV|S`{5si`{1wo+3obh1K(?6{EX_c*D(F>xLIzK zAAYOcRzIH&Q+)Uz`}rL3!vpc~-+uUi`r$idAO1alF~US1;uN#vsSMy z$eT3u&r6F6))nR#6z2kxCEX2lW&Y|M$jZuFy>>a2BZam`dX8zGNBq+h1bO3N@V z&CJSzHKsLmT{*1FE;JPs<7(RDk7s3MK7=b-Su2W)vWkkc3yT?6kqNu(`~q0LHajP) zh!*CrE6&O;%qv2~n>c2faMZ>kqL8|Kb|bP`Pp9G&&_9YHVGF`1uy-%O|9aPdKybGRyk!d0{t5kQ=2&b? Leci +#include + +#include "ckb_syscalls.h" +#include "spawn_utils.h" + +const uint64_t SYSCALL_CYCLES_BASE = 500; +const uint64_t SPAWN_EXTRA_CYCLES_BASE = 100000; +const uint64_t SPAWN_YIELD_CYCLES_BASE = 800; + +int tic() { + static uint64_t tic = 0; + uint64_t cur_cycles = ckb_current_cycles(); + uint64_t toc = cur_cycles - tic; + tic = cur_cycles; + return toc; +} + +uint64_t cal_cycles(uint64_t nbase, uint64_t yield, uint64_t extra) { + uint64_t r = 0; + r += SYSCALL_CYCLES_BASE * nbase; + r += SPAWN_YIELD_CYCLES_BASE * yield; + r += SPAWN_EXTRA_CYCLES_BASE * extra; + return r; +} + +uint64_t cal_cycles_floor(uint64_t nbase, uint64_t yield, uint64_t extra) { + return cal_cycles(nbase, yield, extra); +} + +uint64_t cal_cycles_upper(uint64_t nbase, uint64_t yield, uint64_t extra) { + return cal_cycles(nbase, yield, extra) + 8192; +} + +#define BUFFER_SIZE 1024 * 4 + +typedef struct { + uint64_t io_size; + bool check_buffer; +} ScriptArgs; + +int parent(ScriptArgs* args, uint8_t* buffer) { + int err = 0; + const char* argv[] = {"", 0}; + uint64_t fds[2] = {0}; + uint64_t pid = 0; + err = full_spawn(0, 1, argv, fds, &pid); + CHECK(err); + + uint64_t buf_len = args->io_size; + + err = ckb_read(fds[CKB_STDIN], buffer, &buf_len); + CHECK(err); + CHECK2(buf_len == args->io_size, -1); + if (args->check_buffer) { + for (size_t i = 0; i < args->io_size; i++) + CHECK2(buffer[i] == (uint8_t)i, -1); + } + + int8_t exit_code = 0; + err = ckb_wait(pid, &exit_code); + CHECK(err); + CHECK(exit_code); + +exit: + return err; +} + +int child(ScriptArgs* args, uint8_t* buffer) { + int err = 0; + uint64_t inherited_fds[2]; + size_t inherited_fds_length = 2; + err = ckb_inherited_file_descriptors(inherited_fds, &inherited_fds_length); + CHECK(err); + + uint64_t buf_len = args->io_size; + + if (args->check_buffer) { + for (size_t i = 0; i < args->io_size; i++) buffer[i] = i; + } + + err = ckb_write(inherited_fds[CKB_STDOUT], buffer, &buf_len); + + CHECK(err); + CHECK2(buf_len == args->io_size, -1); +exit: + return err; +} + +int main() { + int err = 0; + ScriptArgs script_args; + size_t script_args_length = sizeof(script_args); + err = load_script_args((uint8_t*)&script_args, &script_args_length); + CHECK(err); + CHECK2(script_args_length == sizeof(script_args), -1); + + uint64_t cid = ckb_process_id(); + uint8_t buffer[BUFFER_SIZE] = {0}; + + if (cid == 0) { + return parent(&script_args, buffer); + } else { + return child(&script_args, buffer); + } + +exit: + return err; +} From 985e44fc048c1db5483efbf117ca811f1f1af5c1 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 16:07:15 +0800 Subject: [PATCH 096/135] Clean spawn_io_cycles.c --- script/testdata/spawn_io_cycles | Bin 7768 -> 7760 bytes script/testdata/spawn_io_cycles.c | 28 ---------------------------- 2 files changed, 28 deletions(-) diff --git a/script/testdata/spawn_io_cycles b/script/testdata/spawn_io_cycles index f9edfd9dfb3c0f413826ae98fb50d447f545149c..e77022ac8ba862a68080ebbb7bb83df2d184672e 100755 GIT binary patch delta 696 zcmca%bHQeU2BW}4O>@Id;tXH_qZtGsd`2L}2E;qqA^aWcAQ2#c;>4AV43n)H)s+lb zCbzOy3A47Azh}5m^mF^sRM*tMVZv+6nH1M!o>gY`x;UTmiY;kdBB5^iQoG(#B;x7;nDPEUrv2k*P_)qxxKw| z@*NRbM#0IyM06R&CToZ)*+)KMHsfSS7W^jA?B2<+^04BeMt8{t$-Li~jN893G`q1g z2!H?1-^%{D{n@|2VWn;$zrub0!G3bLsJV^;6XzRdmPRJe2hR$WTHQ*Pm9SNECN?!J zYD+~^FTZ;72T>VmpzB*(%HMz3zv5`>qBama&<$kh`w#OcYl=xr!Q|tYzT6I!XER_b z-2OK#(@k{y=kW`cuXN;I^DXA~HNgoo^ka%Zc$OSS47?>C~O>UGlXY850Q&JtM{vlBP zrpZ4g<0UsiQwB`^d9ZqBp!z~7kolcblNb#*%SgvCGUiRLl+ou@5QkWxFnOblIVU_} jP5vlj4>ZzH)}HamGd0_HKAbDuAp`1DZFyrx^ delta 770 zcmca$bHiqW2BXA8O>@It;tXH_qZtGsd`2L}2E+&0A^ZdCAQ2#c;>4AV4U?@I)s;T5 zPHt_j5@uzsc+YU5=;!vMsjjJi!-Uxw*kIzDTNocOGj?rGW%cG(VX2X72TD2!vmTXT zd$aG!u{VcaNIiM~!T)G$hE_+Tt1v4|&EzWrDvXVre+o1+v9XqejNaTN%*7Z0VZZ-S zf8ZwAny)}>6nH1M!o>gY`x;UTmiY;kdBB5^iQoG(#B;x7;nDPEUrv2k*P_)qxt+ag z@*NRbM&Zf7M06P?Cu@i*IXb>zHsfSS7WpR7?B2<+@v!EhMt8{t$$a0KjN893G`q1g z2!H?1-^%{D{nY0olMXVg?!f{)7E;RAY{&fYq>l00uBj z-~S~Kw}XuTz?``qnF zuz&hyDRDkVNeyvGd_!U%LNYTjGaQ)gC~;j9mKqpXATpsqN{E4xAz`wiq(0-W$%&HU zK(bQOoN>zJjgsn;2eeU5n+{Yj05oma Date: Thu, 25 Apr 2024 16:14:33 +0800 Subject: [PATCH 097/135] Use filter_map and collect to refactoring codes --- script/src/scheduler.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 2830da8dc1..902a4445d9 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -265,18 +265,17 @@ where self.states.clear(); self.states.insert(vm_id_to_run, VmState::Terminated); } else { - let mut joining_vms: Vec<(VmId, u64)> = Vec::new(); - self.states.iter().for_each(|(vm_id, state)| { - if let VmState::Wait { - target_vm_id, - exit_code_addr, - } = state - { - if *target_vm_id == vm_id_to_run { - joining_vms.push((*vm_id, *exit_code_addr)); - } - } - }); + let joining_vms: Vec<(VmId, u64)> = self + .states + .iter() + .filter_map(|(vm_id, state)| match state { + VmState::Wait { + target_vm_id, + exit_code_addr, + } if *target_vm_id == vm_id_to_run => Some((*vm_id, *exit_code_addr)), + _ => None, + }) + .collect(); // For all joining VMs, update exit code, then mark them as // runnable state. for (vm_id, exit_code_addr) in joining_vms { From 63d4dde3c0d6db2850a7369ab40cd8c96ba2f26c Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 16:20:31 +0800 Subject: [PATCH 098/135] Remove unnecessary comments --- script/src/syscalls/read.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 9217fd4345..63976ef096 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -37,7 +37,6 @@ impl Syscalls for Read { // We can only do basic checks here, when the message is actually processed, // more complete checks will be performed. - // We will also leave to the actual write operation to test memory permissions. if !fd.is_read() { machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); From 1a83097d4935641afe3dd1e50d87d30b21ee1195 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 25 Apr 2024 16:54:07 +0800 Subject: [PATCH 099/135] Simplify codes with functional --- script/src/scheduler.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 902a4445d9..d72a011e89 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -325,20 +325,13 @@ where match message { Message::Spawn(vm_id, args) => { // All fds must belong to the correct owner - let mut fds_valid = true; - for fd in &args.fds { - if !(self.fds.contains_key(fd) && (self.fds[fd] == vm_id)) { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine.machine.set_register(A0, INVALID_FD as u64); - fds_valid = false; - break; - } - } - if !fds_valid { + if args.fds.iter().any(|fd| self.fds.get(fd) != Some(&vm_id)) { + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self + .instantiated + .get_mut(&vm_id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; + machine.machine.set_register(A0, INVALID_FD as u64); continue; } if self.suspended.len() + self.instantiated.len() > MAX_VMS_COUNT as usize { From de4a7e47081089de4c3ebafb1461cd1f629721cd Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 09:04:43 +0800 Subject: [PATCH 100/135] Replace VMError::External(IndexOutOfBound) with VMError::CkbScriptIndexOutOfBound --- script/src/syscalls/load_cell_data.rs | 6 ++--- script/src/syscalls/spawn.rs | 2 +- script/src/types.rs | 38 ++++++++++++++------------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index 9640517fe0..bdbde2fdc0 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -63,7 +63,7 @@ where machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); return Ok(()); } - Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + Err(VMError::CkbScriptIndexOutOfBound) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); @@ -76,7 +76,7 @@ where let (wrote_size, full_size) = match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { Ok(val) => val, - Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + Err(VMError::CkbScriptIndexOutOfBound) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); @@ -124,7 +124,7 @@ where val } } - Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + Err(VMError::CkbScriptIndexOutOfBound) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 03cd669ea0..2c4b49820f 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -122,7 +122,7 @@ where .map_err(|e| VMError::Unexpected(e.to_string()))?; let (_, full_length) = match sc.data_source().load_data(&data_piece_id, 0, 0) { Ok(val) => val, - Err(VMError::External(m)) if m == "INDEX_OUT_OF_BOUND" => { + Err(VMError::CkbScriptIndexOutOfBound) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); diff --git a/script/src/types.rs b/script/src/types.rs index 8078b0cfaf..cba1f996d7 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -561,10 +561,11 @@ where Ok(self.program.clone()) } DataPieceId::Input(i) => { - let cell = - self.rtx.resolved_inputs.get(*i as usize).ok_or_else(|| { - VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()) - })?; + let cell = self + .rtx + .resolved_inputs + .get(*i as usize) + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; self.data_loader.load_cell_data(cell).ok_or_else(|| { VMInternalError::Unexpected(format!("Loading input cell #{}'s data failed!", i)) }) @@ -575,13 +576,13 @@ where .outputs_data() .get(*i as usize) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())), + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound), DataPieceId::CellDep(i) => { let cell = self .rtx .resolved_cell_deps .get(*i as usize) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; self.data_loader.load_cell_data(cell).ok_or_else(|| { VMInternalError::Unexpected(format!("Loading dep cell #{}'s data failed!", i)) }) @@ -591,11 +592,12 @@ where .script_group .input_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; - let cell = - self.rtx.resolved_inputs.get(gi).ok_or_else(|| { - VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()) - })?; + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + let cell = self + .rtx + .resolved_inputs + .get(gi) + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; self.data_loader.load_cell_data(cell).ok_or_else(|| { VMInternalError::Unexpected(format!( "Loading input cell #{}'s data failed!", @@ -608,13 +610,13 @@ where .script_group .output_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; self.rtx .transaction .outputs_data() .get(gi) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())) + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound) } DataPieceId::Witness(i) => self .rtx @@ -622,32 +624,32 @@ where .witnesses() .get(*i as usize) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())), + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound), DataPieceId::WitnessGroupInput(i) => { let gi = *self .script_group .input_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; self.rtx .transaction .witnesses() .get(gi) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())) + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound) } DataPieceId::WitnessGroupOutput(i) => { let gi = *self .script_group .output_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string()))?; + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; self.rtx .transaction .witnesses() .get(gi) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::External("INDEX_OUT_OF_BOUND".to_string())) + .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound) } } .map(|data| { From 345ace6145ad368c8e51555e31299b81395e6427 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 09:17:07 +0800 Subject: [PATCH 101/135] Update Cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 011c18c637..96a2c42c0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,7 +1799,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#6fd0f8c4c9bf41382d1de09d900ae7596c37ef4a" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#37b33a381f708e27d12c43fda17f165cd8d60592" dependencies = [ "byteorder", "bytes", @@ -1816,7 +1816,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#6fd0f8c4c9bf41382d1de09d900ae7596c37ef4a" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#37b33a381f708e27d12c43fda17f165cd8d60592" dependencies = [ "paste", ] From b9de30fc4ae1d2126186225861c6fd87abf5bd9b Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 10:03:10 +0800 Subject: [PATCH 102/135] Refactoring iterate --- script/src/scheduler.rs | 67 ++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index d72a011e89..d213730a8c 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -54,7 +54,7 @@ where syscalls_generator: TransactionScriptsSyscallsGenerator
, total_cycles: Cycle, - extra_cycles: Cycle, + current_iteration_cycles: Cycle, next_vm_id: VmId, next_fd_slot: u64, states: BTreeMap, @@ -85,7 +85,7 @@ where script_version, syscalls_generator, total_cycles: 0, - extra_cycles: 0, + current_iteration_cycles: 0, next_vm_id: FIRST_VM_ID, next_fd_slot: FIRST_FD_SLOT, states: BTreeMap::default(), @@ -115,7 +115,7 @@ where script_version, syscalls_generator, total_cycles: full.total_cycles, - extra_cycles: 0, + current_iteration_cycles: 0, next_vm_id: full.next_vm_id, next_fd_slot: full.next_fd_slot, states: full @@ -196,11 +196,16 @@ where }; while self.states[&ROOT_VM_ID] != VmState::Terminated { - self.extra_cycles = 0; - let consumed_cycles = self.iterate(pause.clone(), limit_cycles)?; + self.current_iteration_cycles = 0; + let iterate_return = self.iterate(pause.clone(), limit_cycles); + self.total_cycles = self + .total_cycles + .checked_add(self.current_iteration_cycles) + .ok_or(Error::CyclesExceeded)?; limit_cycles = limit_cycles - .checked_sub(consumed_cycles) + .checked_sub(self.current_iteration_cycles) .ok_or(Error::CyclesExceeded)?; + iterate_return?; } // At this point, root VM cannot be suspended @@ -211,7 +216,7 @@ where // This is internal function that does the actual VM execution loop. // Here both pause signal and limit_cycles are provided so as to simplify // branches. - fn iterate(&mut self, pause: Pause, limit_cycles: Cycle) -> Result { + fn iterate(&mut self, pause: Pause, limit_cycles: Cycle) -> Result<(), Error> { // 1. Process all pending VM reads & writes self.process_io()?; // 2. Run an actual VM @@ -226,7 +231,7 @@ where let vm_id_to_run = vm_id_to_run.ok_or_else(|| { Error::Unexpected("A deadlock situation has been reached!".to_string()) })?; - let (result, consumed_cycles) = { + let result = { self.ensure_vms_instantiated(&[vm_id_to_run])?; let (context, machine) = self .instantiated @@ -236,17 +241,13 @@ where set_vm_max_cycles(machine, limit_cycles); machine.machine.set_pause(pause); let result = machine.run(); - let consumed_cycles = { - let c = machine.machine.cycles(); - machine.machine.set_cycles(0); - c - }; - // This shall be the only place where total_cycles gets updated - self.total_cycles = self - .total_cycles - .checked_add(consumed_cycles) + let cycles = machine.machine.cycles(); + machine.machine.set_cycles(0); + self.current_iteration_cycles = self + .current_iteration_cycles + .checked_add(cycles) .ok_or(Error::CyclesOverflow)?; - (result, consumed_cycles) + result }; // 3. Process message box, update VM states accordingly self.process_message_box()?; @@ -298,24 +299,10 @@ where self.instantiated.remove(&vm_id_to_run); self.suspended.remove(&vm_id_to_run); } - self.total_cycles = self - .total_cycles - .checked_add(self.extra_cycles) - .ok_or(Error::CyclesOverflow)?; - Ok(consumed_cycles + self.extra_cycles) - } - Err(Error::Yield) => { - self.total_cycles = self - .total_cycles - .checked_add(self.extra_cycles) - .ok_or(Error::CyclesOverflow)?; - Ok(consumed_cycles + self.extra_cycles) - } - Err(e) => { - // In this case, there should be no vm instantiated/uninstantiated state switch. - debug_assert_eq!(self.extra_cycles, 0); - Err(e) + Ok(()) } + Err(Error::Yield) => Ok(()), + Err(e) => Err(e), } } @@ -757,7 +744,10 @@ where return Err(Error::Unexpected(format!("VM {:?} is not suspended!", id))); } let snapshot = &self.suspended[id]; - self.extra_cycles += SPAWN_EXTRA_CYCLES_BASE; + self.current_iteration_cycles = self + .current_iteration_cycles + .checked_add(SPAWN_EXTRA_CYCLES_BASE) + .ok_or(Error::CyclesExceeded)?; let (context, mut machine) = self.create_dummy_vm(id)?; { let mut sc = context.snapshot2_context().lock().expect("lock"); @@ -776,7 +766,10 @@ where id ))); } - self.extra_cycles += SPAWN_EXTRA_CYCLES_BASE; + self.current_iteration_cycles = self + .current_iteration_cycles + .checked_add(SPAWN_EXTRA_CYCLES_BASE) + .ok_or(Error::CyclesExceeded)?; let (context, machine) = self .instantiated .get_mut(id) From 67cb7a90cad0dcdd0eaaa259bd1d30243b00ef4d Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 10:28:31 +0800 Subject: [PATCH 103/135] Remove unnecessary clone --- script/src/verify.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/script/src/verify.rs b/script/src/verify.rs index 723dc37059..c556423d45 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1033,13 +1033,13 @@ where let version = self.select_version(&script_group.script)?; let mut scheduler = if let Some(state) = state { Scheduler::resume( - tx_data.clone(), + tx_data, version, self.syscalls_generator.clone(), state.clone(), ) } else { - Scheduler::new(tx_data.clone(), version, self.syscalls_generator.clone()) + Scheduler::new(tx_data, version, self.syscalls_generator.clone()) }; let map_vm_internal_error = |error: VMInternalError| match error { VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), @@ -1129,8 +1129,7 @@ where 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.syscalls_generator.clone()); + let mut scheduler = Scheduler::new(tx_data, version, self.syscalls_generator.clone()); let map_vm_internal_error = |error: VMInternalError| match error { VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), @@ -1165,7 +1164,7 @@ where }; let version = self.select_version(&script_group.script)?; let mut scheduler = - Scheduler::new(tx_data.clone(), version, self.syscalls_generator.clone()); + Scheduler::new(tx_data, version, self.syscalls_generator.clone()); let map_vm_internal_error = |error: VMInternalError| match error { VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), From c23f19ab79b4eaad322c2ca83116e6ae84873a42 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 11:34:14 +0800 Subject: [PATCH 104/135] Simplified set_max_cycles --- Cargo.lock | 4 ++-- script/src/scheduler.rs | 6 +++--- script/src/types.rs | 10 ---------- script/src/verify.rs | 3 +-- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96a2c42c0a..38837fce28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,7 +1799,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#37b33a381f708e27d12c43fda17f165cd8d60592" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#a83ab4cd403c7e1fea266cedcb6d7d821d41a735" dependencies = [ "byteorder", "bytes", @@ -1816,7 +1816,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#37b33a381f708e27d12c43fda17f165cd8d60592" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#a83ab4cd403c7e1fea266cedcb6d7d821d41a735" dependencies = [ "paste", ] diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index d213730a8c..d4bbaac0d8 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -8,8 +8,8 @@ use crate::verify::TransactionScriptsSyscallsGenerator; use crate::ScriptVersion; use crate::types::{ - set_vm_max_cycles, CoreMachineType, DataPieceId, Fd, FdArgs, FullSuspendedState, Machine, - Message, ReadState, RunMode, TxData, VmId, VmState, WriteState, FIRST_FD_SLOT, FIRST_VM_ID, + CoreMachineType, DataPieceId, Fd, FdArgs, FullSuspendedState, Machine, Message, ReadState, + RunMode, TxData, VmId, VmState, WriteState, FIRST_FD_SLOT, FIRST_VM_ID, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::Cycle; @@ -238,7 +238,7 @@ where .get_mut(&vm_id_to_run) .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; context.set_base_cycles(self.total_cycles); - set_vm_max_cycles(machine, limit_cycles); + machine.set_max_cycles(limit_cycles); machine.machine.set_pause(pause); let result = machine.run(); let cycles = machine.machine.cycles(); diff --git a/script/src/types.rs b/script/src/types.rs index cba1f996d7..99bb6a0217 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -123,16 +123,6 @@ impl ScriptVersion { } } -#[cfg(has_asm)] -pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { - vm.set_max_cycles(cycles) -} - -#[cfg(not(has_asm))] -pub(crate) fn set_vm_max_cycles(vm: &mut Machine, cycles: Cycle) { - vm.machine.inner_mut().set_max_cycles(cycles) -} - /// A script group is defined as scripts that share the same hash. /// /// A script group will only be executed once per transaction, the diff --git a/script/src/verify.rs b/script/src/verify.rs index c556423d45..cd843852a7 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1163,8 +1163,7 @@ where script_group: Arc::new(script_group.clone()), }; let version = self.select_version(&script_group.script)?; - let mut scheduler = - Scheduler::new(tx_data, version, self.syscalls_generator.clone()); + let mut scheduler = Scheduler::new(tx_data, version, self.syscalls_generator.clone()); let map_vm_internal_error = |error: VMInternalError| match error { VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), From de38595a24269d69a69dad228f69eeae98fc6813 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 15:48:22 +0800 Subject: [PATCH 105/135] Add a help function ensure_get_instantiated --- script/src/scheduler.rs | 172 +++++++++++++--------------------------- 1 file changed, 53 insertions(+), 119 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index d4bbaac0d8..843e675cf2 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -232,12 +232,9 @@ where Error::Unexpected("A deadlock situation has been reached!".to_string()) })?; let result = { - self.ensure_vms_instantiated(&[vm_id_to_run])?; - let (context, machine) = self - .instantiated - .get_mut(&vm_id_to_run) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - context.set_base_cycles(self.total_cycles); + let total_cycles = self.total_cycles; + let (context, machine) = self.ensure_get_instantiated(&vm_id_to_run)?; + context.set_base_cycles(total_cycles); machine.set_max_cycles(limit_cycles); machine.machine.set_pause(pause); let result = machine.run(); @@ -280,11 +277,7 @@ where // For all joining VMs, update exit code, then mark them as // runnable state. for (vm_id, exit_code_addr) in joining_vms { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine .machine .memory_mut() @@ -313,20 +306,12 @@ where Message::Spawn(vm_id, args) => { // All fds must belong to the correct owner if args.fds.iter().any(|fd| self.fds.get(fd) != Some(&vm_id)) { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine.machine.set_register(A0, INVALID_FD as u64); continue; } if self.suspended.len() + self.instantiated.len() > MAX_VMS_COUNT as usize { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine.machine.set_register(A0, MAX_VMS_SPAWNED as u64); continue; } @@ -340,46 +325,28 @@ where // If one fd is moved afterward, this inherited file descriptors doesn't change. self.inherited_fd.insert(spawned_vm_id, args.fds.clone()); - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine + .machine + .memory_mut() + .store64(&args.process_id_addr, &spawned_vm_id)?; + machine.machine.set_register(A0, SUCCESS as u64); + } + Message::Wait(vm_id, args) => { + if let Some(exit_code) = self.terminated_vms.get(&args.target_id).copied() { + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine .machine .memory_mut() - .store64(&args.process_id_addr, &spawned_vm_id)?; + .store8(&args.exit_code_addr, &u64::from_i8(exit_code))?; machine.machine.set_register(A0, SUCCESS as u64); - } - } - Message::Wait(vm_id, args) => { - if let Some(exit_code) = self.terminated_vms.get(&args.target_id).copied() { - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine - .machine - .memory_mut() - .store8(&args.exit_code_addr, &u64::from_i8(exit_code))?; - machine.machine.set_register(A0, SUCCESS as u64); - self.states.insert(vm_id, VmState::Runnable); - self.terminated_vms.retain(|id, _| id != &args.target_id); - } + self.states.insert(vm_id, VmState::Runnable); + self.terminated_vms.retain(|id, _| id != &args.target_id); continue; } if !self.states.contains_key(&args.target_id) { - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine.machine.set_register(A0, WAIT_FAILURE as u64); - } + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine.machine.set_register(A0, WAIT_FAILURE as u64); continue; } // Return code will be updated when the joining VM exits @@ -392,12 +359,8 @@ where ); } Message::Pipe(vm_id, args) => { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; if self.fds.len() as u64 >= MAX_FDS { + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine.machine.set_register(A0, MAX_FDS_CREATED as u64); continue; } @@ -405,6 +368,7 @@ where self.next_fd_slot = slot; self.fds.insert(p1, vm_id); self.fds.insert(p2, vm_id); + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine .machine .memory_mut() @@ -417,25 +381,13 @@ where } Message::FdRead(vm_id, args) => { if !(self.fds.contains_key(&args.fd) && (self.fds[&args.fd] == vm_id)) { - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine.machine.set_register(A0, INVALID_FD as u64); - } + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine.machine.set_register(A0, INVALID_FD as u64); continue; } if !self.fds.contains_key(&args.fd.other_fd()) { - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine.machine.set_register(A0, OTHER_END_CLOSED as u64); - } + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine.machine.set_register(A0, OTHER_END_CLOSED as u64); continue; } // Return code will be updated when the read operation finishes @@ -451,25 +403,13 @@ where } Message::FdWrite(vm_id, args) => { if !(self.fds.contains_key(&args.fd) && (self.fds[&args.fd] == vm_id)) { - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine.machine.set_register(A0, INVALID_FD as u64); - } + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine.machine.set_register(A0, INVALID_FD as u64); continue; } if !self.fds.contains_key(&args.fd.other_fd()) { - self.ensure_vms_instantiated(&[vm_id])?; - { - let (_, machine) = - self.instantiated.get_mut(&vm_id).ok_or_else(|| { - Error::Unexpected("Unable to find VM Id".to_string()) - })?; - machine.machine.set_register(A0, OTHER_END_CLOSED as u64); - } + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine.machine.set_register(A0, OTHER_END_CLOSED as u64); continue; } // Return code will be updated when the write operation finishes @@ -485,11 +425,8 @@ where ); } Message::InheritedFileDescriptor(vm_id, args) => { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; + let inherited_fd = self.inherited_fd[&vm_id].clone(); + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; let FdArgs { buffer_addr, length_addr, @@ -500,7 +437,6 @@ where .inner_mut() .memory_mut() .load64(&length_addr)?; - let inherited_fd = &self.inherited_fd[&vm_id]; let actual_length = inherited_fd.len() as u64; if buffer_addr == 0 { if input_length == 0 { @@ -534,15 +470,12 @@ where machine.machine.set_register(A0, SUCCESS as u64); } Message::Close(vm_id, fd) => { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; if self.fds.get(&fd) != Some(&vm_id) { + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine.machine.set_register(A0, INVALID_FD as u64); } else { self.fds.remove(&fd); + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; machine.machine.set_register(A0, SUCCESS as u64); } } @@ -579,16 +512,9 @@ where for vm_id in closed_fds { match self.states[&vm_id].clone() { VmState::WaitForRead(ReadState { length_addr, .. }) => { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, read_machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - read_machine - .machine - .memory_mut() - .store64(&length_addr, &0)?; - read_machine.machine.set_register(A0, SUCCESS as u64); + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine.machine.memory_mut().store64(&length_addr, &0)?; + machine.machine.set_register(A0, SUCCESS as u64); self.states.insert(vm_id, VmState::Runnable); } VmState::WaitForWrite(WriteState { @@ -596,16 +522,12 @@ where length_addr, .. }) => { - self.ensure_vms_instantiated(&[vm_id])?; - let (_, write_machine) = self - .instantiated - .get_mut(&vm_id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?; - write_machine + let (_, machine) = self.ensure_get_instantiated(&vm_id)?; + machine .machine .memory_mut() .store64(&length_addr, &consumed)?; - write_machine.machine.set_register(A0, SUCCESS as u64); + machine.machine.set_register(A0, SUCCESS as u64); self.states.insert(vm_id, VmState::Runnable); } _ => (), @@ -738,6 +660,18 @@ where Ok(()) } + // Ensure corresponding VM is instantiated and return a mutable reference to it + fn ensure_get_instantiated( + &mut self, + id: &VmId, + ) -> Result<&mut (MachineContext
, Machine), Error> { + self.ensure_vms_instantiated(&[*id])?; + Ok(self + .instantiated + .get_mut(id) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?) + } + // Resume a suspended VM fn resume_vm(&mut self, id: &VmId) -> Result<(), Error> { if !self.suspended.contains_key(id) { From 13bf1fe7140b3209f8bf0295b3f29bc32aa218fb Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 16:03:52 +0800 Subject: [PATCH 106/135] Rename generate_same_syscalls to generate_syscalls --- script/src/scheduler.rs | 2 +- script/src/verify.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 843e675cf2..0e0c11eb91 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -778,7 +778,7 @@ where let machine_builder = DefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(estimate_cycles)); let machine_builder = syscalls_generator - .generate_same_syscalls(version, &self.tx_data.script_group) + .generate_syscalls(version, &self.tx_data.script_group) .into_iter() .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); let default_machine = machine_builder.build(); diff --git a/script/src/verify.rs b/script/src/verify.rs index cd843852a7..2e645d0988 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -283,8 +283,8 @@ where Close::new(self.vm_id, Arc::clone(&self.message_box)) } - /// Generate same syscalls. The result does not contain spawn syscalls. - pub fn generate_same_syscalls( + /// Generate syscalls. + pub fn generate_syscalls( &self, script_version: ScriptVersion, script_group: &ScriptGroup, @@ -1111,7 +1111,7 @@ where script_group: &ScriptGroup, ) -> Vec)>> { self.syscalls_generator - .generate_same_syscalls(script_version, script_group) + .generate_syscalls(script_version, script_group) } /// Runs a single program, then returns the exit code together with the entire From 77a2824a7bd73ee1ec5236791d82fe484a6601ca Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 16:52:08 +0800 Subject: [PATCH 107/135] Remove snapshot2_context from TransactionScriptsSyscallsGenerator --- script/src/scheduler.rs | 12 +++++++----- script/src/verify.rs | 39 +++++++++++++++------------------------ 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 0e0c11eb91..2599f6391d 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -766,19 +766,21 @@ where // We will update max_cycles for each machine when it gets a chance to run u64::max_value(), ); - + let snapshot2_context = Arc::new(Mutex::new(Snapshot2Context::new(self.tx_data.clone()))); let mut syscalls_generator = self.syscalls_generator.clone(); syscalls_generator.vm_id = *id; - syscalls_generator.snapshot2_context = - Arc::new(Mutex::new(Snapshot2Context::new(self.tx_data.clone()))); let mut machine_context = MachineContext::new(self.tx_data.clone()); machine_context.base_cycles = Arc::clone(&self.syscalls_generator.base_cycles); - machine_context.snapshot2_context = Arc::clone(&syscalls_generator.snapshot2_context); + machine_context.snapshot2_context = Arc::clone(&snapshot2_context); let machine_builder = DefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(estimate_cycles)); let machine_builder = syscalls_generator - .generate_syscalls(version, &self.tx_data.script_group) + .generate_syscalls( + version, + &self.tx_data.script_group, + Arc::clone(&snapshot2_context), + ) .into_iter() .fold(machine_builder, |builder, syscall| builder.syscall(syscall)); let default_machine = machine_builder.build(); diff --git a/script/src/verify.rs b/script/src/verify.rs index 2e645d0988..e18f7658e9 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -151,7 +151,6 @@ where pub(crate) rtx: Arc, #[cfg(test)] pub(crate) skip_pause: Arc, - pub(crate) snapshot2_context: Arc>>>, pub(crate) vm_id: VmId, } @@ -197,8 +196,11 @@ where } /// Build syscall: load_cell_data - pub fn build_load_cell_data(&self) -> LoadCellData
{ - LoadCellData::new(Arc::clone(&self.snapshot2_context)) + pub fn build_load_cell_data( + &self, + snapshot2_context: Arc>>>, + ) -> LoadCellData
{ + LoadCellData::new(snapshot2_context) } ///Build syscall: load_input @@ -240,12 +242,11 @@ where } /// Build syscall: spawn - pub fn build_spawn(&self) -> Spawn
{ - Spawn::new( - self.vm_id, - Arc::clone(&self.message_box), - Arc::clone(&self.snapshot2_context), - ) + pub fn build_spawn( + &self, + snapshot2_context: Arc>>>, + ) -> Spawn
{ + Spawn::new(self.vm_id, Arc::clone(&self.message_box), snapshot2_context) } /// Build syscall: wait @@ -288,6 +289,7 @@ where &self, script_version: ScriptVersion, script_group: &ScriptGroup, + snapshot2_context: Arc>>>, ) -> Vec)>> { let current_script_hash = script_group.script.calc_script_hash(); let script_group_input_indices = Arc::new(script_group.input_indices.clone()); @@ -306,7 +308,7 @@ where Arc::clone(&script_group_output_indices), )), Box::new(self.build_load_script(script_group.script.clone())), - Box::new(self.build_load_cell_data()), + Box::new(self.build_load_cell_data(Arc::clone(&snapshot2_context))), Box::new(Debugger::new( current_script_hash, Arc::clone(&self.debug_printer), @@ -325,7 +327,7 @@ where if script_version >= ScriptVersion::V2 { syscalls.append(&mut vec![ Box::new(self.build_load_block_extension(Arc::clone(&script_group_input_indices))), - Box::new(self.build_spawn()), + Box::new(self.build_spawn(Arc::clone(&snapshot2_context))), Box::new(self.build_process_id()), Box::new(self.build_pipe()), Box::new(self.build_wait()), @@ -471,18 +473,6 @@ where rtx: Arc::clone(&rtx), #[cfg(test)] skip_pause: Arc::clone(&skip_pause), - // Use a dummy snapshot2_context as a placeholder. - snapshot2_context: Arc::new(Mutex::new(Snapshot2Context::new(TxData { - rtx: Arc::clone(&rtx), - data_loader: data_loader.clone(), - program: Bytes::new(), - script_group: Arc::new(ScriptGroup { - script: Default::default(), - group_type: ScriptGroupType::Lock, - input_indices: Default::default(), - output_indices: Default::default(), - }), - }))), vm_id: FIRST_VM_ID, }; @@ -1109,9 +1099,10 @@ where &self, script_version: ScriptVersion, script_group: &ScriptGroup, + snapshot2_context: Arc>>>, ) -> Vec)>> { self.syscalls_generator - .generate_syscalls(script_version, script_group) + .generate_syscalls(script_version, script_group, snapshot2_context) } /// Runs a single program, then returns the exit code together with the entire From 9936a79a54a81deea22c227761b38c8ab5b38abf Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 26 Apr 2024 17:13:44 +0800 Subject: [PATCH 108/135] Fix clippy --- script/src/scheduler.rs | 5 ++--- script/src/types.rs | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 2599f6391d..f5aa5fede6 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -666,10 +666,9 @@ where id: &VmId, ) -> Result<&mut (MachineContext
, Machine), Error> { self.ensure_vms_instantiated(&[*id])?; - Ok(self - .instantiated + self.instantiated .get_mut(id) - .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string()))?) + .ok_or_else(|| Error::Unexpected("Unable to find VM Id".to_string())) } // Resume a suspended VM diff --git a/script/src/types.rs b/script/src/types.rs index 99bb6a0217..45d162a7c2 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -555,7 +555,7 @@ where .rtx .resolved_inputs .get(*i as usize) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; self.data_loader.load_cell_data(cell).ok_or_else(|| { VMInternalError::Unexpected(format!("Loading input cell #{}'s data failed!", i)) }) @@ -566,13 +566,13 @@ where .outputs_data() .get(*i as usize) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound), + .ok_or(VMInternalError::CkbScriptIndexOutOfBound), DataPieceId::CellDep(i) => { let cell = self .rtx .resolved_cell_deps .get(*i as usize) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; self.data_loader.load_cell_data(cell).ok_or_else(|| { VMInternalError::Unexpected(format!("Loading dep cell #{}'s data failed!", i)) }) @@ -582,12 +582,12 @@ where .script_group .input_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; let cell = self .rtx .resolved_inputs .get(gi) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; self.data_loader.load_cell_data(cell).ok_or_else(|| { VMInternalError::Unexpected(format!( "Loading input cell #{}'s data failed!", @@ -600,13 +600,13 @@ where .script_group .output_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; self.rtx .transaction .outputs_data() .get(gi) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound) + .ok_or(VMInternalError::CkbScriptIndexOutOfBound) } DataPieceId::Witness(i) => self .rtx @@ -614,32 +614,32 @@ where .witnesses() .get(*i as usize) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound), + .ok_or(VMInternalError::CkbScriptIndexOutOfBound), DataPieceId::WitnessGroupInput(i) => { let gi = *self .script_group .input_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; self.rtx .transaction .witnesses() .get(gi) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound) + .ok_or(VMInternalError::CkbScriptIndexOutOfBound) } DataPieceId::WitnessGroupOutput(i) => { let gi = *self .script_group .output_indices .get(*i as usize) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound)?; + .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; self.rtx .transaction .witnesses() .get(gi) .map(|data| data.raw_data()) - .ok_or_else(|| VMInternalError::CkbScriptIndexOutOfBound) + .ok_or(VMInternalError::CkbScriptIndexOutOfBound) } } .map(|data| { From 4cfe3327546fede6729fceaa854bcf86a578e909 Mon Sep 17 00:00:00 2001 From: mohanson Date: Sun, 28 Apr 2024 11:16:36 +0800 Subject: [PATCH 109/135] Remove inherited_file_descriptors special handling of NULL --- script/src/scheduler.rs | 35 +++++++++------------------------- script/testdata/spawn_cases | Bin 15696 -> 15664 bytes script/testdata/spawn_cases.c | 5 ----- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index f5aa5fede6..e506a8710b 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,7 +1,7 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, - SPAWN_EXTRA_CYCLES_BASE, SUCCESS, WAIT_FAILURE, + INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SPAWN_EXTRA_CYCLES_BASE, + SUCCESS, WAIT_FAILURE, }; use crate::types::MachineContext; use crate::verify::TransactionScriptsSyscallsGenerator; @@ -24,11 +24,8 @@ use ckb_vm::{ snapshot2::{DataSource, Snapshot2}, Error, Register, }; +use std::collections::{BTreeMap, HashMap}; use std::sync::{Arc, Mutex}; -use std::{ - collections::{BTreeMap, HashMap}, - mem::size_of, -}; pub const ROOT_VM_ID: VmId = FIRST_VM_ID; pub const MAX_VMS_COUNT: u64 = 16; @@ -432,41 +429,27 @@ where length_addr, .. } = args; - let input_length = machine + let full_length = machine .machine .inner_mut() .memory_mut() .load64(&length_addr)?; - let actual_length = inherited_fd.len() as u64; - if buffer_addr == 0 { - if input_length == 0 { - machine - .machine - .inner_mut() - .memory_mut() - .store64(&length_addr, &actual_length)?; - machine.machine.set_register(A0, SUCCESS as u64); - } else { - machine.machine.set_register(A0, INDEX_OUT_OF_BOUND as u64); - } - continue; - } - let mut buffer_addr2 = buffer_addr; - let copy_length = u64::min(input_length, actual_length); + let real_length = inherited_fd.len() as u64; + let copy_length = u64::min(full_length, real_length); for i in 0..copy_length { let fd = inherited_fd[i as usize].0; + let addr = buffer_addr + i * 8; machine .machine .inner_mut() .memory_mut() - .store64(&buffer_addr2, &fd)?; - buffer_addr2 += size_of::() as u64; + .store64(&addr, &fd)?; } machine .machine .inner_mut() .memory_mut() - .store64(&length_addr, &actual_length)?; + .store64(&length_addr, &real_length)?; machine.machine.set_register(A0, SUCCESS as u64); } Message::Close(vm_id, fd) => { diff --git a/script/testdata/spawn_cases b/script/testdata/spawn_cases index ba20ddd3b9f1a768cb6c617f2bec2d40125a4ccb..2742af8b3ef6bd2c955ed709f5d6c6487d76dc45 100755 GIT binary patch delta 3207 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 Date: Mon, 29 Apr 2024 09:27:49 +0800 Subject: [PATCH 110/135] Replace + with checked_add --- script/src/scheduler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index e506a8710b..3dbf39a16c 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -438,7 +438,7 @@ where let copy_length = u64::min(full_length, real_length); for i in 0..copy_length { let fd = inherited_fd[i as usize].0; - let addr = buffer_addr + i * 8; + let addr = buffer_addr.checked_add(i * 8).ok_or(Error::MemOutOfBound)?; machine .machine .inner_mut() From e766bb525c2ea166ad3655566b38a3498e11d6ad Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 6 May 2024 16:54:38 +0800 Subject: [PATCH 111/135] add cycles assertions --- .../tests/ckb_latest/features_since_v2019.rs | 13 ++++-- .../tests/ckb_latest/features_since_v2021.rs | 45 ++++++++++++++++++- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/script/src/verify/tests/ckb_latest/features_since_v2019.rs b/script/src/verify/tests/ckb_latest/features_since_v2019.rs index 4a25ef1602..a69c887575 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2019.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2019.rs @@ -49,7 +49,7 @@ fn check_always_success_hash() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - assert!(result.is_ok()); + assert_eq!(result.ok(), Some(ALWAYS_SUCCESS_SCRIPT_CYCLE)); } #[test] @@ -119,7 +119,7 @@ fn check_signature() { ); let result = verifier.verify_without_limit(script_version, &rtx); - assert!(result.is_ok()); + assert_eq!(result.ok(), Some(ALWAYS_SUCCESS_SCRIPT_CYCLE)); } #[test] @@ -187,7 +187,11 @@ fn check_signature_referenced_via_type_hash() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - assert!(result.is_ok()); + if script_version == ScriptVersion::V0 { + assert_eq!(result.ok(), Some(ALWAYS_SUCCESS_SCRIPT_CYCLE)); + } else { + assert_eq!(result.ok(), Some(ALWAYS_SUCCESS_SCRIPT_CYCLE + 2)); + } } #[test] @@ -378,7 +382,7 @@ fn check_output_contract() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - assert!(result.is_ok()); + assert_eq!(result.ok(), Some(1074)); } #[test] @@ -574,6 +578,7 @@ fn check_type_id_one_in_one_out() { let max_cycles = TYPE_ID_CYCLES * 2; let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify(script_version, &rtx, max_cycles); + assert!( result.is_ok(), "expect ok, but got {:?}", diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 3207667780..021224c12b 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -57,6 +57,8 @@ fn test_hint_instructions() { }; let script_error = ScriptError::VMInternalError(vm_error); assert_error_eq!(result.unwrap_err(), script_error.input_lock_script(0)); + } else { + assert_eq!(result.ok(), Some(540)); } } @@ -107,6 +109,10 @@ fn test_b_extension() { }; let script_error = ScriptError::VMInternalError(vm_error); assert_error_eq!(result.unwrap_err(), script_error.input_lock_script(0)); + } else if script_version == ScriptVersion::V1 { + assert_eq!(result.ok(), Some(1876)); + } else { + assert_eq!(result.ok(), Some(1875)); } } @@ -372,6 +378,11 @@ fn check_exec_from_witness() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1); + if script_version == ScriptVersion::V1 { + assert_eq!(result.ok(), Some(1200)); + } else if script_version == ScriptVersion::V2 { + assert_eq!(result.ok(), Some(1198)); + } } #[test] @@ -792,6 +803,11 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle ); } assert_eq!(cycles, cycles_once, "step_cycles {step_cycles}"); + if script_version < crate::ScriptVersion::V2 { + assert_eq!(cycles, 3387236); + } else { + assert_eq!(cycles, 3276322); + } } #[test] @@ -994,6 +1010,13 @@ fn check_typical_secp256k1_blake160_2_in_2_out_tx_with_complete() { assert!(cycles >= TWO_IN_TWO_OUT_CYCLES - CYCLE_BOUND); } assert_eq!(cycles, cycles_once); + if script_version <= ScriptVersion::V0 { + assert_eq!(cycles, 3405227); + } else if script_version == ScriptVersion::V1 { + assert_eq!(cycles, 3387236); + } else if script_version == ScriptVersion::V2 { + assert_eq!(cycles, 3276322); + } } #[test] @@ -1041,10 +1064,14 @@ fn load_code_into_global() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1,); - if script_version < ScriptVersion::V1 { + if script_version < ScriptVersion::V0 { let vm_error = VmError::MemWriteOnFreezedPage; let script_error = ScriptError::VMInternalError(vm_error); assert_error_eq!(result.unwrap_err(), script_error.input_lock_script(0)); + } else if script_version == ScriptVersion::V1 { + assert_eq!(result.ok(), Some(10529)); + } else if script_version == ScriptVersion::V2 { + assert_eq!(result.ok(), Some(10525)); } } @@ -1118,6 +1145,13 @@ fn load_code_with_snapshot() { let cycles_once = result.unwrap(); assert_eq!(cycles, cycles_once); + if script_version == ScriptVersion::V0 { + assert_eq!(cycles_once, 11062); + } else if script_version == ScriptVersion::V1 { + assert_eq!(cycles_once, 11064); + } else { + assert_eq!(cycles_once, 11060); + } } #[test] @@ -1211,6 +1245,13 @@ fn load_code_with_snapshot_more_times() { let result = verifier.verify_without_pause(script_version, &rtx, max_cycles); let cycles_once = result.unwrap(); assert_eq!(cycles, cycles_once); + if script_version == ScriptVersion::V0 { + assert_eq!(cycles_once, 45740); + } else if script_version == ScriptVersion::V1 { + assert_eq!(cycles_once, 45742); + } else { + assert_eq!(cycles_once, 45729); + } } #[derive(Clone, Copy)] @@ -1811,7 +1852,7 @@ fn check_signature_referenced_via_type_hash_ok_with_multiple_matches() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); - assert_eq!(result.unwrap(), 539); + assert_eq!(result.ok(), Some(539)); } #[test] From 72aa9e8653c4a419e9ff8331e4326f32e02de74c Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 8 May 2024 09:41:37 +0800 Subject: [PATCH 112/135] Refactoring data source --- script/src/scheduler.rs | 4 +- script/src/syscalls/load_cell_data.rs | 18 ++-- script/src/syscalls/spawn.rs | 8 +- script/src/types.rs | 127 ++++++++------------------ 4 files changed, 50 insertions(+), 107 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 3dbf39a16c..4ac5340ceb 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -21,7 +21,7 @@ use ckb_vm::{ machine::{CoreMachine, DefaultMachineBuilder, Pause, SupportMachine}, memory::Memory, registers::A0, - snapshot2::{DataSource, Snapshot2}, + snapshot2::Snapshot2, Error, Register, }; use std::collections::{BTreeMap, HashMap}; @@ -722,7 +722,7 @@ where let (context, mut machine) = self.create_dummy_vm(&id)?; { let mut sc = context.snapshot2_context().lock().expect("lock"); - let (program, _) = sc.data_source().load_data(data_piece_id, offset, length)?; + let (program, _) = sc.load_data(data_piece_id, offset, length)?; let metadata = parse_elf::(&program, machine.machine.version())?; let bytes = machine.load_program_with_metadata(&program, &metadata, args)?; sc.mark_program(&mut machine.machine, &metadata, data_piece_id, offset)?; diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index bdbde2fdc0..fbba363abb 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -10,7 +10,7 @@ use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_vm::{ memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, registers::{A0, A1, A2, A3, A4, A5, A7}, - snapshot2::{DataSource, Snapshot2Context}, + snapshot2::Snapshot2Context, Bytes, Error as VMError, Register, SupportMachine, Syscalls, }; use std::sync::{Arc, Mutex}; @@ -52,10 +52,7 @@ where .map_err(|e| VMError::Unexpected(e.to_string()))?; if size == 0 { - match sc - .data_source() - .load_data(&data_piece_id, offset, u64::max_value()) - { + match sc.load_data(&data_piece_id, offset, u64::max_value()) { Ok((cell, _)) => { machine .memory_mut() @@ -63,7 +60,7 @@ where machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); return Ok(()); } - Err(VMError::CkbScriptIndexOutOfBound) => { + Err(VMError::SnapshotDataLoadError) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); @@ -76,7 +73,7 @@ where let (wrote_size, full_size) = match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { Ok(val) => val, - Err(VMError::CkbScriptIndexOutOfBound) => { + Err(VMError::SnapshotDataLoadError) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); @@ -113,10 +110,7 @@ where // We are using 0..u64::max_value() to fetch full cell, there is // also no need to keep the full length value. Since cell's length // is already full length. - let (cell, _) = match sc - .data_source() - .load_data(&data_piece_id, 0, u64::max_value()) - { + let (cell, _) = match sc.load_data(&data_piece_id, 0, u64::max_value()) { Ok(val) => { if content_size == 0 { (Bytes::new(), val.1) @@ -124,7 +118,7 @@ where val } } - Err(VMError::CkbScriptIndexOutOfBound) => { + Err(VMError::SnapshotDataLoadError) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 2c4b49820f..5be3c3dd2b 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -8,7 +8,7 @@ use ckb_vm::{ machine::SupportMachine, memory::Memory, registers::{A0, A1, A2, A3, A4, A7}, - snapshot2::{DataSource, Snapshot2Context}, + snapshot2::Snapshot2Context, syscalls::Syscalls, Error as VMError, Register, }; @@ -116,13 +116,13 @@ where } // We are fetching the actual cell here for some in-place validation - let sc = self + let mut sc = self .snapshot2_context .lock() .map_err(|e| VMError::Unexpected(e.to_string()))?; - let (_, full_length) = match sc.data_source().load_data(&data_piece_id, 0, 0) { + let (_, full_length) = match sc.load_data(&data_piece_id, 0, 0) { Ok(val) => val, - Err(VMError::CkbScriptIndexOutOfBound) => { + Err(VMError::SnapshotDataLoadError) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); diff --git a/script/src/types.rs b/script/src/types.rs index 45d162a7c2..3097641884 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -3,7 +3,6 @@ use ckb_types::{ core::{Cycle, ScriptHashType}, packed::{Byte32, Script}, }; -use ckb_vm::Error as VMInternalError; use ckb_vm::{ machine::{VERSION0, VERSION1, VERSION2}, ISA_A, ISA_B, ISA_IMC, ISA_MOP, @@ -537,110 +536,60 @@ impl
DataSource for TxData
where DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { - fn load_data( - &self, - id: &DataPieceId, - offset: u64, - length: u64, - ) -> Result<(Bytes, u64), VMInternalError> { + fn load_data(&self, id: &DataPieceId, offset: u64, length: u64) -> Option<(Bytes, u64)> { match id { DataPieceId::Program => { // This is just a shortcut so we don't have to copy over the logic in extract_script, // ideally you can also only define the rest 5, then figure out a way to convert // script group to the actual cell dep index. - Ok(self.program.clone()) - } - DataPieceId::Input(i) => { - let cell = self - .rtx - .resolved_inputs - .get(*i as usize) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - self.data_loader.load_cell_data(cell).ok_or_else(|| { - VMInternalError::Unexpected(format!("Loading input cell #{}'s data failed!", i)) - }) + Some(self.program.clone()) } + DataPieceId::Input(i) => self + .rtx + .resolved_inputs + .get(*i as usize) + .and_then(|cell| self.data_loader.load_cell_data(cell)), DataPieceId::Output(i) => self .rtx .transaction .outputs_data() .get(*i as usize) - .map(|data| data.raw_data()) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound), - DataPieceId::CellDep(i) => { - let cell = self - .rtx - .resolved_cell_deps - .get(*i as usize) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - self.data_loader.load_cell_data(cell).ok_or_else(|| { - VMInternalError::Unexpected(format!("Loading dep cell #{}'s data failed!", i)) - }) - } - DataPieceId::GroupInput(i) => { - let gi = *self - .script_group - .input_indices - .get(*i as usize) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - let cell = self - .rtx - .resolved_inputs - .get(gi) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - self.data_loader.load_cell_data(cell).ok_or_else(|| { - VMInternalError::Unexpected(format!( - "Loading input cell #{}'s data failed!", - gi - )) - }) - } - DataPieceId::GroupOutput(i) => { - let gi = *self - .script_group - .output_indices - .get(*i as usize) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - self.rtx - .transaction - .outputs_data() - .get(gi) - .map(|data| data.raw_data()) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound) - } + .map(|data| data.raw_data()), + DataPieceId::CellDep(i) => self + .rtx + .resolved_cell_deps + .get(*i as usize) + .and_then(|cell| self.data_loader.load_cell_data(cell)), + DataPieceId::GroupInput(i) => self + .script_group + .input_indices + .get(*i as usize) + .and_then(|gi| self.rtx.resolved_inputs.get(*gi)) + .and_then(|cell| self.data_loader.load_cell_data(cell)), + DataPieceId::GroupOutput(i) => self + .script_group + .output_indices + .get(*i as usize) + .and_then(|gi| self.rtx.transaction.outputs_data().get(*gi)) + .map(|data| data.raw_data()), DataPieceId::Witness(i) => self .rtx .transaction .witnesses() .get(*i as usize) - .map(|data| data.raw_data()) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound), - DataPieceId::WitnessGroupInput(i) => { - let gi = *self - .script_group - .input_indices - .get(*i as usize) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - self.rtx - .transaction - .witnesses() - .get(gi) - .map(|data| data.raw_data()) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound) - } - DataPieceId::WitnessGroupOutput(i) => { - let gi = *self - .script_group - .output_indices - .get(*i as usize) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound)?; - self.rtx - .transaction - .witnesses() - .get(gi) - .map(|data| data.raw_data()) - .ok_or(VMInternalError::CkbScriptIndexOutOfBound) - } + .map(|data| data.raw_data()), + DataPieceId::WitnessGroupInput(i) => self + .script_group + .input_indices + .get(*i as usize) + .and_then(|gi| self.rtx.transaction.witnesses().get(*gi)) + .map(|data| data.raw_data()), + DataPieceId::WitnessGroupOutput(i) => self + .script_group + .output_indices + .get(*i as usize) + .and_then(|gi| self.rtx.transaction.witnesses().get(*gi)) + .map(|data| data.raw_data()), } .map(|data| { let offset = std::cmp::min(offset as usize, data.len()); From fa8ac4ab7d2b2300b235f427df6259abde25378c Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 8 May 2024 09:43:37 +0800 Subject: [PATCH 113/135] Update cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38837fce28..18d3e70a52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,7 +1799,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#a83ab4cd403c7e1fea266cedcb6d7d821d41a735" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#eac5bbf5c715e03f5398efc15fdf25d8942a71b1" dependencies = [ "byteorder", "bytes", @@ -1816,7 +1816,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#a83ab4cd403c7e1fea266cedcb6d7d821d41a735" +source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#eac5bbf5c715e03f5398efc15fdf25d8942a71b1" dependencies = [ "paste", ] From e7299745763ffefad4a6f763ccee095eda0803cf Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 8 May 2024 12:00:44 +0800 Subject: [PATCH 114/135] fix clippy --- .../tests/ckb_latest/features_since_v2021.rs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 021224c12b..d5fad09344 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -102,17 +102,21 @@ fn test_b_extension() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1,); - if script_version < ScriptVersion::V1 { - let vm_error = VmError::InvalidInstruction { - pc: 65866, - instruction: 0x60291913, - }; - let script_error = ScriptError::VMInternalError(vm_error); - assert_error_eq!(result.unwrap_err(), script_error.input_lock_script(0)); - } else if script_version == ScriptVersion::V1 { - assert_eq!(result.ok(), Some(1876)); - } else { - assert_eq!(result.ok(), Some(1875)); + match script_version { + ScriptVersion::V0 => { + let vm_error = VmError::InvalidInstruction { + pc: 65866, + instruction: 0x60291913, + }; + let script_error = ScriptError::VMInternalError(vm_error); + assert_error_eq!(result.unwrap_err(), script_error.input_lock_script(0)); + } + ScriptVersion::V1 => { + assert_eq!(result.ok(), Some(1876)); + } + ScriptVersion::V2 => { + assert_eq!(result.ok(), Some(1875)); + } } } From a4fb1dbb8106cdecb13830141880a57b5acaace7 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 15 May 2024 16:52:43 +0800 Subject: [PATCH 115/135] Update ckb-vm --- script/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/Cargo.toml b/script/Cargo.toml index 3fc3b08243..6e996998bb 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,7 +22,7 @@ ckb-traits = { path = "../traits", version = "= 0.116.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.116.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.116.0-pre" } -ckb-vm = { git = "https://github.com/libraries/ckb-vm", branch = "release-0.24-spawn", default-features = false } +ckb-vm = { version = "=0.24.10", default-features = false } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.116.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } From 73ca9c2e9fc9afb1e0423dec858cb31f043e76fe Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 15 May 2024 17:41:17 +0800 Subject: [PATCH 116/135] Update Cargo.lock --- Cargo.lock | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a17f9ddd6e..3bcb4b837f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1797,8 +1797,9 @@ dependencies = [ [[package]] name = "ckb-vm" -version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#eac5bbf5c715e03f5398efc15fdf25d8942a71b1" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6d951adb4f317e6a2f619c4f6d7d5494367bb0a21acc9fb4bb37e01b203ad9" dependencies = [ "byteorder", "bytes", @@ -1814,8 +1815,9 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" -version = "0.24.9" -source = "git+https://github.com/libraries/ckb-vm?branch=release-0.24-spawn#eac5bbf5c715e03f5398efc15fdf25d8942a71b1" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0baeb661c205f016662d87330fbacd75f5c4d78982e82daf0320f0b1f11b54c" dependencies = [ "paste", ] From 379684d9b8311f3e130ba36b4ed8ae40f8369f10 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 10 May 2024 10:26:46 +0800 Subject: [PATCH 117/135] lock cargo shear version --- devtools/ci/check-cargotoml.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devtools/ci/check-cargotoml.sh b/devtools/ci/check-cargotoml.sh index 0fb14d1ba6..1e04ffde20 100755 --- a/devtools/ci/check-cargotoml.sh +++ b/devtools/ci/check-cargotoml.sh @@ -94,7 +94,8 @@ function check_cargo_publish() { function check_dependencies() { if ! type cargo-shear &> /dev/null then - cargo install cargo-shear + # lock version to avoid breaking building now + cargo install cargo-shear --version 0.0.24 fi cargo shear } From 2abad8c774e5f598f67fbb7b81301babac3b14c5 Mon Sep 17 00:00:00 2001 From: xjd Date: Mon, 20 May 2024 10:18:26 +0800 Subject: [PATCH 118/135] Add test case with spawn saturate memory --- .../tests/ckb_latest/features_since_v2023.rs | 6 +++ script/testdata/Makefile | 4 +- script/testdata/spawn_saturate_memory | Bin 0 -> 4864 bytes script/testdata/spawn_saturate_memory.c | 45 ++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100755 script/testdata/spawn_saturate_memory create mode 100644 script/testdata/spawn_saturate_memory.c 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 d6539cfcb1..a465c6515a 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1320,3 +1320,9 @@ fn check_spawn_io_cycles() { assert_eq!(cycles2 - cycles1, offset_size / 2); } + +#[test] +fn check_spawn_saturate_memory() { + let result = simple_spawn_test("testdata/spawn_saturate_memory", &[0]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 71325a06c4..8d72cc3900 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -74,7 +74,8 @@ ALL_BINS := jalr_zero \ spawn_fuzzing \ spawn_huge_swap \ spawn_cycles \ - spawn_io_cycles + spawn_io_cycles \ + spawn_saturate_memory ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -162,3 +163,4 @@ spawn_fuzzing: spawn_fuzzing.c spawn_utils.h spawn_huge_swap: spawn_huge_swap.c spawn_utils.h spawn_cycles: spawn_cycles.c spawn_utils.h spawn_io_cycles: spawn_io_cycles.c spawn_utils.h +spawn_saturate_memory: spawn_saturate_memory.c spawn_utils.h diff --git a/script/testdata/spawn_saturate_memory b/script/testdata/spawn_saturate_memory new file mode 100755 index 0000000000000000000000000000000000000000..08e51f96c8fa2e196dd881b18601c978f4639942 GIT binary patch literal 4864 zcmbVQ4OCOt9l!4-@7)k0i99P`Y7xQuRpv*ho1Gj2CQ(~C-JDzJ)~0X?h=qU0^r6)l2HQ0M@$wE-ehIw&+Kie5z*b|ciQCwkMWXj{->1GyJtUS_ zyIvg08O|F}u4=7Kt$(}zcmp4dN=Gp;deFrO0s*vF9nB9$(bf!}(XfbTqp3`#D@FJD zk2y71(;0af>U@XqZ^ty_zBI) zIhe{$PDtCI;o-Efo$0Y|7dEU-3fVS-v;#|RQcie|c zSJEC2bOD)nD7c7qr(bexo^;;c?Y8YK8bDhjX*%9h|1&MOPD!JYl~kU?9&yPL)?rs+ zExwh(-jZ-G_7>`mOuzv`7ZurKnC zHG|6JUsuo-PX69BVBLWpS1M8YXEfd?jVOUux;Pf#r~^7~KZ@`GMz#oIkEzcEgo4ik zLStkfH(5zjJ5c$%AsM9$^UBB$(PIKA*pK9IDkPZ`0U_?)fb|(+Cw*htVX`V-&zcv- z#b6CQQst|#r}i!x8L|Kfbi9*iA>HsgCyN0g@7MGO$ef@Nd?9Z)M$uVrP7df7 zI#6Sz{KEAGF70)p{IfxkYe1;Xyo*Lkb_VzsOz-4|qUfpDL$V6tPFR+M zHIU4H*CDNgZ54BDArdja1#5De>~bhh2C_+LV4xski7 zptV4`q4)RtR}Q|yR`(X_iw+j8#@UckKpG({+%Oe|H<&OU|VE5c?yVhX4xG{JpXzD(sI* z^jQOyY<8q|CG}`mSPdjLS@v7~Uml*WYHd8(f#TOv;fQg}b2N$C5p0W`#w#&YvJmg@ z<|>~G@|E&*?TQ3B1ZW?OCEnAnSldE9b3or5GZ&n4=2Oj0G2qBPnGS*k7aVPON%3T$ z5F8u{M^Sj(-z`QdJw-2Zv^%I|R6Q6=VvZvo-|ixjW*~{RFvZ_RB!o%cZfwB#9W5jxAVjT)9+3S%l zQvn{jLE7*Z{RFVsj&>*}SN$5f*@X<;(6qsg&pfsdY%xp$jB51W)2hE{`D%GOs#AgY zoTzLH)$L4hL%>%igR~LkhDoTNos8;L(`>Q)6$R~a{~h}jSwEzSw>kM_VB771$Fw(^ zWL|8ol9`s|5cm%Ry^Y+AzD4(}MO%hm4J;TE|Mx^HJk8({4a@serQ#QvG zbl44OG=HjCX}IpJ{G!MKFmXR4m$DJiEseI_LTqj@T&3%r~)rJV!lRtr^vOPlr8l_f}~CZ$J%S0p-MA^eU?f`9J}qo0}lj zd>Lw+FAb$HI(Hd7wl5<_%ZL5Ze0hkHYDevFZOn6zp1$eM3!QcN>`-}}?}+g&_ot8w zQa#93`{|a(xQ>WW%vR$F2~%Ouk&b3K1)$A^6UZK(c00B76!P9c&Y+|{#1H!Z2cEF) zwry%@6eiaONxmki5^&B6yVxrk)f?a8*>qL_7rS0Ku?1H=v6j0$l zx@7mZZ;0K0Jw{FjDasd5kW)9!IlEJ4P=ScHAJQ@L#8|0o9oR?Ou#dcL)UzKQCHZr~ z(}MM1J7#vBY)f;W>}+?fJT`S>l8=*FX}jzJK`Qdv5g`o9yf7)LC^L=8)cY`MTKq@4MYEW#neqQ}8L;G!X#aYHg!+^DyVF z{=aqdicc8wUL0->kOCEK_*XNAmauWXIA1u1F9*}4m6c>ynvLa_g2J-Y^>}P5EiEoh z%(f(^lr2rkotGFMqvBjsVoL6P{<3UKd1_a$y63**svCQJ0gIy@%rxA>krG+Fxpo89KwtETa*RGuEsz>av!H=$x`LW0@tp z)B=jK3(R(PinTsQd*ExZZSQme(aq8vn60T5)$cKgcK*@Z_=WrgbojJj*f5B@sP+%xKw}d zi*m1yXUAVm#<$scNHDPs9^|3;z2o5$eONvf%aZjUJ~O26Ezx*xY$Lp+N&ON`hzb7=a}FV+j*(5%_n1?;#}oIHL~tZDTM( UKD<8uTlkOi<)Z&q{tx+o15}n&GXMYp literal 0 HcmV?d00001 diff --git a/script/testdata/spawn_saturate_memory.c b/script/testdata/spawn_saturate_memory.c new file mode 100644 index 0000000000..de977b10db --- /dev/null +++ b/script/testdata/spawn_saturate_memory.c @@ -0,0 +1,45 @@ +#include "spawn_utils.h" + +#define MAX_MEMORY (4 * 1024 * 1024) +#define PAGE_SIZE (4 * 1024) + +extern char _end[]; + +void dirty_all_pages() { + uint64_t addr = (uint64_t)_end; + while (addr < MAX_MEMORY) { + uint8_t* ptr = (uint8_t*)addr; + *ptr = 0; + addr += PAGE_SIZE; + } +} + +int main(int argc, const char* argv[]) { + int err = 0; + if (argc > 0) { + // child + dirty_all_pages(); + uint64_t inherited_fds[2]; + size_t inherited_fds_length = 2; + err = ckb_inherited_file_descriptors(inherited_fds, &inherited_fds_length); + uint64_t length = MAX_MEMORY; + // Write a piece of data starting from address 0 with a size of 4M. + // It should not consume any memory. + err = ckb_write(inherited_fds[CKB_STDOUT], 0, &length); + // should be blocked forever since there is no reading on other end + CHECK(err); + } else { + // parent + for (size_t i = 0; i < 15; i++) { + uint64_t pid = 0; + const char* argv[] = {"", 0}; + uint64_t fds[2] = {0}; + err = full_spawn(0, 1, argv, fds, &pid); + CHECK(err); + } + dirty_all_pages(); + } + +exit: + return err; +} From 7494697280af72257b4112a447e808f7acebd6d4 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 20 May 2024 10:20:18 +0800 Subject: [PATCH 119/135] Update script/testdata/README.md --- script/testdata/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/testdata/README.md b/script/testdata/README.md index 372faae575..ce35495eb8 100644 --- a/script/testdata/README.md +++ b/script/testdata/README.md @@ -4,7 +4,7 @@ - Create a directory named `deps`. - - Clone https://github.com/XuJiandong/ckb-c-stdlib.git with branch `syscall-spawn` into `deps`. FIXME with the correct address! + - Clone https://github.com/nervosnetwork/ckb-c-stdlib into `deps`. - Build all scripts with `docker`. From 4a2f18e1545cdd13b6249890cae92d732d018fe8 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 27 May 2024 08:38:38 +0800 Subject: [PATCH 120/135] Fix addr overlap --- script/src/syscalls/load_cell_data.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index fbba363abb..df18420958 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -81,9 +81,13 @@ where } Err(e) => return Err(e), }; - machine - .memory_mut() - .store64(&size_addr, &Mac::REG::from_u64(full_size))?; + if size_addr.to_u64() < addr.to_u64() + || size_addr.to_u64() >= addr.to_u64().wrapping_add(wrote_size.to_u64()) + { + machine + .memory_mut() + .store64(&size_addr, &Mac::REG::from_u64(full_size))?; + } machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); Ok(()) From 58c8480cf285c5315eb6b6ee586defa011bdea59 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 28 May 2024 22:34:51 +0800 Subject: [PATCH 121/135] Update ckb-vm to v0.24.11 --- script/Cargo.toml | 2 +- script/src/syscalls/load_cell_data.rs | 35 +++++++++++++-------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/script/Cargo.toml b/script/Cargo.toml index 6e996998bb..55fe0037d4 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,7 +22,7 @@ ckb-traits = { path = "../traits", version = "= 0.116.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.116.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.116.0-pre" } -ckb-vm = { version = "=0.24.10", default-features = false } +ckb-vm = { version = "=0.24.11", default-features = false } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.116.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index df18420958..2663d8c85d 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -70,24 +70,23 @@ where } } - let (wrote_size, full_size) = - match sc.store_bytes(machine, addr, &data_piece_id, offset, size) { - Ok(val) => val, - Err(VMError::SnapshotDataLoadError) => { - // This comes from TxData results in an out of bound error, to - // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - Err(e) => return Err(e), - }; - if size_addr.to_u64() < addr.to_u64() - || size_addr.to_u64() >= addr.to_u64().wrapping_add(wrote_size.to_u64()) - { - machine - .memory_mut() - .store64(&size_addr, &Mac::REG::from_u64(full_size))?; - } + let (wrote_size, _) = match sc.store_bytes( + machine, + addr, + &data_piece_id, + offset, + size, + size_addr.to_u64(), + ) { + Ok(val) => val, + Err(VMError::SnapshotDataLoadError) => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); Ok(()) From daa070066a51a903d68ca428ee400f6afd018644 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 28 May 2024 22:44:43 +0800 Subject: [PATCH 122/135] Update Cargo.lock --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bcb4b837f..5b1f5a82e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1797,9 +1797,9 @@ dependencies = [ [[package]] name = "ckb-vm" -version = "0.24.10" +version = "0.24.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6d951adb4f317e6a2f619c4f6d7d5494367bb0a21acc9fb4bb37e01b203ad9" +checksum = "7ce46f3e3800634212bd9a62ba2554a30ba4e60dee0a7040f9314f053c28ab27" dependencies = [ "byteorder", "bytes", @@ -1815,9 +1815,9 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" -version = "0.24.10" +version = "0.24.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0baeb661c205f016662d87330fbacd75f5c4d78982e82daf0320f0b1f11b54c" +checksum = "ef1e029aaf2138739b89664dec6ebc0648cba3430122b9848eab2ee7fefbcc0d" dependencies = [ "paste", ] From 3c592425c7aeea701f7381bb810b9248e960d999 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 4 Jun 2024 14:51:20 +0800 Subject: [PATCH 123/135] Public TxData --- script/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/src/lib.rs b/script/src/lib.rs index e28b54c0eb..b1e451861d 100644 --- a/script/src/lib.rs +++ b/script/src/lib.rs @@ -11,7 +11,7 @@ mod verify_env; pub use crate::error::{ScriptError, TransactionScriptError}; pub use crate::types::{ ChunkCommand, CoreMachine, ScriptGroup, ScriptGroupType, ScriptVersion, TransactionSnapshot, - TransactionState, VerifyResult, VmIsa, VmVersion, + TransactionState, TxData, VerifyResult, VmIsa, VmVersion, }; pub use crate::verify::{TransactionScriptsSyscallsGenerator, TransactionScriptsVerifier}; pub use crate::verify_env::TxVerifyEnv; From 4003f032954c6c9226535a666993a48036c886fa Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 17 Jun 2024 13:53:25 +0800 Subject: [PATCH 124/135] Changes for spawn debugger --- Cargo.lock | 6 +-- script/Cargo.toml | 4 +- script/src/lib.rs | 5 +- script/src/scheduler.rs | 107 +++++++++++++++++++++++----------------- script/src/types.rs | 2 +- script/src/verify.rs | 24 ++++++--- 6 files changed, 90 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b1f5a82e3..b78ce40d7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,8 +1798,7 @@ dependencies = [ [[package]] name = "ckb-vm" version = "0.24.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce46f3e3800634212bd9a62ba2554a30ba4e60dee0a7040f9314f053c28ab27" +source = "git+https://github.com/libraries/ckb-vm?branch=spawn-debugger-3#2b738a4170e453871136cc76df11807c7e1293a2" dependencies = [ "byteorder", "bytes", @@ -1816,8 +1815,7 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" version = "0.24.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1e029aaf2138739b89664dec6ebc0648cba3430122b9848eab2ee7fefbcc0d" +source = "git+https://github.com/libraries/ckb-vm?branch=spawn-debugger-3#2b738a4170e453871136cc76df11807c7e1293a2" dependencies = [ "paste", ] diff --git a/script/Cargo.toml b/script/Cargo.toml index 55fe0037d4..c5e52a051c 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,7 +22,9 @@ ckb-traits = { path = "../traits", version = "= 0.116.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.116.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.116.0-pre" } -ckb-vm = { version = "=0.24.11", default-features = false } +# ckb-vm = { version = "=0.24.11", default-features = false } +# ckb-vm = { path = "/home/ubuntu/src/ckb-vm", default-features = false } +ckb-vm = { git = "https://github.com/libraries/ckb-vm", branch = "spawn-debugger-3", default-features = false } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.116.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } diff --git a/script/src/lib.rs b/script/src/lib.rs index b1e451861d..e979f3e411 100644 --- a/script/src/lib.rs +++ b/script/src/lib.rs @@ -9,9 +9,10 @@ mod verify; mod verify_env; pub use crate::error::{ScriptError, TransactionScriptError}; +pub use crate::scheduler::{Scheduler, ROOT_VM_ID}; pub use crate::types::{ - ChunkCommand, CoreMachine, ScriptGroup, ScriptGroupType, ScriptVersion, TransactionSnapshot, - TransactionState, TxData, VerifyResult, VmIsa, VmVersion, + ChunkCommand, CoreMachine, DataPieceId, RunMode, ScriptGroup, ScriptGroupType, ScriptVersion, + TransactionSnapshot, TransactionState, TxData, VerifyResult, VmIsa, VmState, VmVersion, }; pub use crate::verify::{TransactionScriptsSyscallsGenerator, TransactionScriptsVerifier}; pub use crate::verify_env::TxVerifyEnv; diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 4ac5340ceb..fd801a330c 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -42,28 +42,28 @@ pub struct Scheduler
where DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { - tx_data: TxData
, + pub tx_data: TxData
, // In fact, Scheduler here has the potential to totally replace // TransactionScriptsVerifier, nonetheless much of current syscall // implementation is strictly tied to TransactionScriptsVerifier, we // are using it here to save some extra code. - script_version: ScriptVersion, - syscalls_generator: TransactionScriptsSyscallsGenerator
, - - total_cycles: Cycle, - current_iteration_cycles: Cycle, - next_vm_id: VmId, - next_fd_slot: u64, - states: BTreeMap, - fds: BTreeMap, - inherited_fd: BTreeMap>, - instantiated: BTreeMap, Machine)>, - suspended: BTreeMap>, - terminated_vms: BTreeMap, + pub script_version: ScriptVersion, + pub syscalls_generator: TransactionScriptsSyscallsGenerator
, + + pub total_cycles: Cycle, + pub current_iteration_cycles: Cycle, + pub next_vm_id: VmId, + pub next_fd_slot: u64, + pub states: BTreeMap, + pub fds: BTreeMap, + pub inherited_fd: BTreeMap>, + pub instantiated: BTreeMap, Machine)>, + pub suspended: BTreeMap>, + pub terminated_vms: BTreeMap, // MessageBox is expected to be empty before returning from `run` // function, there is no need to persist messages. - message_box: Arc>>, + pub message_box: Arc>>, } impl
Scheduler
@@ -99,6 +99,14 @@ where self.total_cycles } + pub fn consumed_cycles_add(&mut self, cycles: Cycle) -> Result<(), Error> { + self.total_cycles = self + .total_cycles + .checked_add(cycles) + .ok_or(Error::CyclesExceeded)?; + Ok(()) + } + /// Resume a previously suspended scheduler state pub fn resume( tx_data: TxData
, @@ -195,10 +203,7 @@ where while self.states[&ROOT_VM_ID] != VmState::Terminated { self.current_iteration_cycles = 0; let iterate_return = self.iterate(pause.clone(), limit_cycles); - self.total_cycles = self - .total_cycles - .checked_add(self.current_iteration_cycles) - .ok_or(Error::CyclesExceeded)?; + self.consumed_cycles_add(self.current_iteration_cycles)?; limit_cycles = limit_cycles .checked_sub(self.current_iteration_cycles) .ok_or(Error::CyclesExceeded)?; @@ -210,14 +215,14 @@ where Ok((root_vm.1.machine.exit_code(), self.total_cycles)) } - // This is internal function that does the actual VM execution loop. - // Here both pause signal and limit_cycles are provided so as to simplify - // branches. - fn iterate(&mut self, pause: Pause, limit_cycles: Cycle) -> Result<(), Error> { - // 1. Process all pending VM reads & writes + pub fn iterate_prepare_machine( + &mut self, + pause: Pause, + limit_cycles: Cycle, + ) -> Result<(u64, &mut Machine), Error> { + // Process all pending VM reads & writes. self.process_io()?; - // 2. Run an actual VM - // Find a runnable VM that has the largest ID + // Find a runnable VM that has the largest ID. let vm_id_to_run = self .states .iter() @@ -228,25 +233,28 @@ where let vm_id_to_run = vm_id_to_run.ok_or_else(|| { Error::Unexpected("A deadlock situation has been reached!".to_string()) })?; - let result = { - let total_cycles = self.total_cycles; - let (context, machine) = self.ensure_get_instantiated(&vm_id_to_run)?; - context.set_base_cycles(total_cycles); - machine.set_max_cycles(limit_cycles); - machine.machine.set_pause(pause); - let result = machine.run(); - let cycles = machine.machine.cycles(); - machine.machine.set_cycles(0); - self.current_iteration_cycles = self - .current_iteration_cycles - .checked_add(cycles) - .ok_or(Error::CyclesOverflow)?; - result - }; - // 3. Process message box, update VM states accordingly + let total_cycles = self.total_cycles; + let (context, machine) = self.ensure_get_instantiated(&vm_id_to_run)?; + context.set_base_cycles(total_cycles); + machine.set_max_cycles(limit_cycles); + machine.machine.set_pause(pause); + Ok((vm_id_to_run, machine)) + } + + pub fn iterate_process_results( + &mut self, + vm_id_to_run: u64, + result: Result, + cycles: u64, + ) -> Result<(), Error> { + self.current_iteration_cycles = self + .current_iteration_cycles + .checked_add(cycles) + .ok_or(Error::CyclesOverflow)?; + // Process message box, update VM states accordingly self.process_message_box()?; assert!(self.message_box.lock().expect("lock").is_empty()); - // 4. If the VM terminates, update VMs in join state, also closes its fds + // If the VM terminates, update VMs in join state, also closes its fds match result { Ok(code) => { self.terminated_vms.insert(vm_id_to_run, code); @@ -296,6 +304,17 @@ where } } + // This is internal function that does the actual VM execution loop. + // Here both pause signal and limit_cycles are provided so as to simplify + // branches. + fn iterate(&mut self, pause: Pause, limit_cycles: Cycle) -> Result<(), Error> { + let (id, vm) = self.iterate_prepare_machine(pause, limit_cycles)?; + let result = vm.run(); + let cycles = vm.machine.cycles(); + vm.machine.set_cycles(0); + self.iterate_process_results(id, result, cycles) + } + fn process_message_box(&mut self) -> Result<(), Error> { let messages: Vec = self.message_box.lock().expect("lock").drain(..).collect(); for message in messages { @@ -699,7 +718,7 @@ where Ok(()) } - fn boot_vm( + pub fn boot_vm( &mut self, data_piece_id: &DataPieceId, offset: u64, diff --git a/script/src/types.rs b/script/src/types.rs index 3097641884..45853fd719 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -317,7 +317,7 @@ pub enum ChunkCommand { } #[derive(Clone)] -pub(crate) struct MachineContext< +pub struct MachineContext< DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, > { pub(crate) base_cycles: Arc>, diff --git a/script/src/verify.rs b/script/src/verify.rs index e18f7658e9..09a8f94dce 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1105,13 +1105,11 @@ where .generate_syscalls(script_version, script_group, snapshot2_context) } - /// Runs a single program, then returns the exit code together with the entire - /// machine to the caller for more inspections. - pub fn detailed_run( + /// Create a scheduler to manage virtual machine instances. + pub fn create_scheduler( &self, script_group: &ScriptGroup, - max_cycles: Cycle, - ) -> Result<(i8, Cycle), ScriptError> { + ) -> Result, ScriptError> { let program = self.extract_script(&script_group.script)?; let tx_data = TxData { rtx: Arc::clone(&self.rtx), @@ -1120,7 +1118,21 @@ where script_group: Arc::new(script_group.clone()), }; let version = self.select_version(&script_group.script)?; - let mut scheduler = Scheduler::new(tx_data, version, self.syscalls_generator.clone()); + Ok(Scheduler::new( + tx_data, + version, + self.syscalls_generator.clone(), + )) + } + + /// Runs a single program, then returns the exit code together with the entire + /// machine to the caller for more inspections. + pub fn detailed_run( + &self, + script_group: &ScriptGroup, + max_cycles: Cycle, + ) -> Result<(i8, Cycle), ScriptError> { + let mut scheduler = self.create_scheduler(script_group)?; let map_vm_internal_error = |error: VMInternalError| match error { VMInternalError::CyclesExceeded => ScriptError::ExceededMaximumCycles(max_cycles), _ => ScriptError::VMInternalError(error), From 234f736b18d5050697e3ae429eb9e2da0a5b843c Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 21 Jun 2024 16:33:11 +0800 Subject: [PATCH 125/135] Update ckb-vm to v0.24.12 --- Cargo.lock | 10 ++++++---- script/Cargo.toml | 4 +--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b78ce40d7d..9c6527cd30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1797,8 +1797,9 @@ dependencies = [ [[package]] name = "ckb-vm" -version = "0.24.11" -source = "git+https://github.com/libraries/ckb-vm?branch=spawn-debugger-3#2b738a4170e453871136cc76df11807c7e1293a2" +version = "0.24.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddff96029d3298cb630e95f29d4b9a93384e938a0b75758684aa8794b53bdd1a" dependencies = [ "byteorder", "bytes", @@ -1814,8 +1815,9 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" -version = "0.24.11" -source = "git+https://github.com/libraries/ckb-vm?branch=spawn-debugger-3#2b738a4170e453871136cc76df11807c7e1293a2" +version = "0.24.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c280bf1d589d23ab0358f58601c2187fc6be86a131644583ef72ea96a0a13ddd" dependencies = [ "paste", ] diff --git a/script/Cargo.toml b/script/Cargo.toml index c5e52a051c..70bd5a6cb4 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -22,9 +22,7 @@ ckb-traits = { path = "../traits", version = "= 0.116.0-pre" } byteorder = "1.3.1" ckb-types = { path = "../util/types", version = "= 0.116.0-pre" } ckb-hash = { path = "../util/hash", version = "= 0.116.0-pre" } -# ckb-vm = { version = "=0.24.11", default-features = false } -# ckb-vm = { path = "/home/ubuntu/src/ckb-vm", default-features = false } -ckb-vm = { git = "https://github.com/libraries/ckb-vm", branch = "spawn-debugger-3", default-features = false } +ckb-vm = { version = "= 0.24.12", default-features = false } faster-hex = "0.6" ckb-logger = { path = "../util/logger", version = "= 0.116.0-pre", optional = true } serde = { version = "1.0", features = ["derive"] } From d0923769eeec0f07ea86fbe279a327e1150efd89 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 21 Jun 2024 18:02:45 +0800 Subject: [PATCH 126/135] Add missing docs --- script/src/scheduler.rs | 34 ++++++++++++++++++++++++++++------ script/src/types.rs | 32 +++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index fd801a330c..3c93c0ee82 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -27,9 +27,13 @@ use ckb_vm::{ use std::collections::{BTreeMap, HashMap}; use std::sync::{Arc, Mutex}; +/// Root process's id. pub const ROOT_VM_ID: VmId = FIRST_VM_ID; +/// The maximum number of VMs that can be created at the same time. pub const MAX_VMS_COUNT: u64 = 16; +/// The maximum number of instantiated VMs. pub const MAX_INSTANTIATED_VMS: usize = 4; +/// The maximum number of fds. pub const MAX_FDS: u64 = 64; /// A single Scheduler instance is used to verify a single script @@ -42,27 +46,40 @@ pub struct Scheduler
where DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static, { + /// Context data for current running transaction & script. pub tx_data: TxData
, - // In fact, Scheduler here has the potential to totally replace - // TransactionScriptsVerifier, nonetheless much of current syscall - // implementation is strictly tied to TransactionScriptsVerifier, we - // are using it here to save some extra code. + /// In fact, Scheduler here has the potential to totally replace + /// TransactionScriptsVerifier, nonetheless much of current syscall + /// implementation is strictly tied to TransactionScriptsVerifier, we + /// are using it here to save some extra code. pub script_version: ScriptVersion, + /// Generate system calls. pub syscalls_generator: TransactionScriptsSyscallsGenerator
, + /// Total cycles. pub total_cycles: Cycle, + /// Current iteration cycles. This value is periodically added to + /// total_cycles and cleared pub current_iteration_cycles: Cycle, + /// Next vm id used by spawn. pub next_vm_id: VmId, + /// Next fd used by pipe. pub next_fd_slot: u64, + /// Used to store VM state. pub states: BTreeMap, + /// Used to confirm the owner of fd. pub fds: BTreeMap, + /// Verify the VM's inherited fd list. pub inherited_fd: BTreeMap>, + /// Instantiated vms. pub instantiated: BTreeMap, Machine)>, + /// Suspended vms. pub suspended: BTreeMap>, + /// Terminated vms. pub terminated_vms: BTreeMap, - // MessageBox is expected to be empty before returning from `run` - // function, there is no need to persist messages. + /// MessageBox is expected to be empty before returning from `run` + /// function, there is no need to persist messages. pub message_box: Arc>>, } @@ -95,10 +112,12 @@ where } } + /// Return total cycles. pub fn consumed_cycles(&self) -> Cycle { self.total_cycles } + /// Add cycles to total cycles. pub fn consumed_cycles_add(&mut self, cycles: Cycle) -> Result<(), Error> { self.total_cycles = self .total_cycles @@ -215,6 +234,7 @@ where Ok((root_vm.1.machine.exit_code(), self.total_cycles)) } + /// Returns the machine that needs to be executed in the current iterate. pub fn iterate_prepare_machine( &mut self, pause: Pause, @@ -241,6 +261,7 @@ where Ok((vm_id_to_run, machine)) } + /// Process machine execution results in the current iterate. pub fn iterate_process_results( &mut self, vm_id_to_run: u64, @@ -718,6 +739,7 @@ where Ok(()) } + /// Boot a vm by given program and args. pub fn boot_vm( &mut self, data_piece_id: &DataPieceId, diff --git a/script/src/types.rs b/script/src/types.rs index 45853fd719..6a3900bafe 100644 --- a/script/src/types.rs +++ b/script/src/types.rs @@ -370,6 +370,7 @@ impl Fd { } } +/// VM is in waiting-to-read state. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ReadState { pub fd: Fd, @@ -378,6 +379,7 @@ pub struct ReadState { pub length_addr: u64, } +/// VM is in waiting-to-write state. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct WriteState { pub fd: Fd, @@ -387,15 +389,23 @@ pub struct WriteState { pub length_addr: u64, } +/// VM State. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum VmState { + /// Runnable. Runnable, + /// Terminated. Terminated, + /// Wait. Wait { + /// Target vm id. target_vm_id: VmId, + /// Exit code addr. exit_code_addr: u64, }, + /// WaitForWrite. WaitForWrite(WriteState), + /// WaitForRead. WaitForRead(ReadState), } @@ -440,16 +450,26 @@ pub enum Message { Close(VmId, Fd), } +/// A pointer to the data that is part of the transaction. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum DataPieceId { + /// Target program. Usually located in cell data. Program, + /// The nth input cell data. Input(u32), + /// The nth output data. Output(u32), + /// The nth cell dep cell data. CellDep(u32), + /// The nth group input cell data. GroupInput(u32), + /// The nth group output data. GroupOutput(u32), + /// The nth witness. Witness(u32), + /// The nth witness group input. WitnessGroupInput(u32), + /// The nth witness group output. WitnessGroupOutput(u32), } @@ -523,12 +543,15 @@ impl FullSuspendedState { /// Context data for current running transaction & script #[derive(Clone)] pub struct TxData
{ + /// ResolvedTransaction. pub rtx: Arc, + /// Data loader. pub data_loader: DL, - // Ideally one might not want to keep program here, since program is totally - // deducible from rtx + data_loader, however, for a demo here, program - // does help us save some extra coding. + /// Ideally one might not want to keep program here, since program is totally + /// deducible from rtx + data_loader, however, for a demo here, program + /// does help us save some extra coding. pub program: Bytes, + /// The script group to which the current program belongs. pub script_group: Arc, } @@ -604,8 +627,11 @@ where } } +/// The scheduler's running mode. #[derive(Clone)] pub enum RunMode { + /// Continues running until cycles are exhausted. LimitCycles(Cycle), + /// Continues running until a Pause signal is received. Pause(Pause), } From eb62b40d968fd489d30830d3a7e6940fc9a169ce Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 21 Jun 2024 20:49:28 +0800 Subject: [PATCH 127/135] Update molecule to 0.8.0 --- Cargo.lock | 21 +- script/Cargo.toml | 2 +- script/testdata/spawn_dag.h | 614 ++++++++++++++++++----------------- script/testdata/spawn_dag.rs | 172 +++++++++- 4 files changed, 475 insertions(+), 334 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c352f1536..1040aef8ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -927,7 +927,7 @@ dependencies = [ "ckb-fixed-hash", "ckb-hash", "ckb-occupied-capacity", - "molecule 0.8.0", + "molecule", "numext-fixed-uint", ] @@ -1495,7 +1495,7 @@ dependencies = [ "ckb-vm", "daggy", "faster-hex", - "molecule 0.7.5", + "molecule", "proptest", "rand 0.8.5", "serde", @@ -1732,7 +1732,7 @@ dependencies = [ "derive_more", "golomb-coded-set", "merkle-cbt", - "molecule 0.8.0", + "molecule", "numext-fixed-uint", "once_cell", "paste", @@ -3568,17 +3568,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "molecule" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd9767ab5e5f2ea40f71ff4c8bdb633c50509052e093c2fdd0e390a749dfa3" -dependencies = [ - "bytes", - "cfg-if", - "faster-hex", -] - [[package]] name = "molecule" version = "0.8.0" @@ -5384,7 +5373,7 @@ dependencies = [ "js-sys", "libc", "log", - "molecule 0.8.0", + "molecule", "nohash-hasher", "once_cell", "parking_lot 0.12.1", @@ -5427,7 +5416,7 @@ dependencies = [ "getrandom 0.2.12", "hmac", "log", - "molecule 0.8.0", + "molecule", "openssl", "openssl-sys", "rand 0.8.5", diff --git a/script/Cargo.toml b/script/Cargo.toml index 77aac5e497..9f2ed4f4b4 100644 --- a/script/Cargo.toml +++ b/script/Cargo.toml @@ -41,4 +41,4 @@ ckb-db-schema = { path = "../db-schema", version = "= 0.117.0-pre" } tempfile.workspace = true rand = "0.8.4" daggy = "0.8.0" -molecule = "0.7.5" +molecule = "0.8.0" diff --git a/script/testdata/spawn_dag.h b/script/testdata/spawn_dag.h index 31bb594842..a7bebf57ca 100644 --- a/script/testdata/spawn_dag.h +++ b/script/testdata/spawn_dag.h @@ -1,6 +1,6 @@ -// Generated by Molecule 0.7.5 +// Generated by Molecule 0.8.0 -#define MOLECULEC_VERSION 7005 +#define MOLECULEC_VERSION 8000 #define MOLECULE_API_VERSION_MIN 7000 #include "molecule_reader.h" @@ -22,139 +22,139 @@ extern "C" { * Reader APIs */ -#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_FdIndex_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_FdIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_FdIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_FdIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_FdIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_FdIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_FdIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_FdIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_FdIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_FdIndices_verify(s, c) mol_fixvec_verify(s, 8) -#define MolReader_FdIndices_length(s) mol_fixvec_length(s) -#define MolReader_FdIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) -#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) -#define MolReader_Bytes_length(s) mol_fixvec_length(s) -#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) -#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *, bool); -#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) -#define MolReader_Pipe_get_read_fd(s) mol_table_slice_by_index(s, 1) -#define MolReader_Pipe_get_write_fd(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *, bool); -#define MolReader_Pipes_length(s) mol_dynvec_length(s) -#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *, bool); -#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) -#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Write_get_from_fd(s) mol_table_slice_by_index(s, 1) -#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) -#define MolReader_Write_get_to_fd(s) mol_table_slice_by_index(s, 3) -#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *, bool); -#define MolReader_Writes_length(s) mol_dynvec_length(s) -#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *, bool); -#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) -#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) -#define MolReader_Spawn_get_fds(s) mol_table_slice_by_index(s, 2) -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *, bool); -#define MolReader_Spawns_length(s) mol_dynvec_length(s) -#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *, bool); -#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) -#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) -#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) +#define MolReader_VmIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_VmIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_VmIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_VmIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_VmIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_VmIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_VmIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_VmIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_VmIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_FdIndex_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_FdIndex_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_FdIndex_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_FdIndex_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_FdIndex_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_FdIndex_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_FdIndex_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_FdIndex_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_FdIndex_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_FdIndices_verify(s, c) mol_fixvec_verify(s, 8) +#define MolReader_FdIndices_length(s) mol_fixvec_length(s) +#define MolReader_FdIndices_get(s, i) mol_fixvec_slice_by_index(s, 8, i) +#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_Bytes_length(s) mol_fixvec_length(s) +#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t*, bool); +#define MolReader_Pipe_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Pipe_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Pipe_get_vm(s) mol_table_slice_by_index(s, 0) +#define MolReader_Pipe_get_read_fd(s) mol_table_slice_by_index(s, 1) +#define MolReader_Pipe_get_write_fd(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t*, bool); +#define MolReader_Pipes_length(s) mol_dynvec_length(s) +#define MolReader_Pipes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t*, bool); +#define MolReader_Write_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Write_has_extra_fields(s) mol_table_has_extra_fields(s, 5) +#define MolReader_Write_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Write_get_from_fd(s) mol_table_slice_by_index(s, 1) +#define MolReader_Write_get_to(s) mol_table_slice_by_index(s, 2) +#define MolReader_Write_get_to_fd(s) mol_table_slice_by_index(s, 3) +#define MolReader_Write_get_data(s) mol_table_slice_by_index(s, 4) +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t*, bool); +#define MolReader_Writes_length(s) mol_dynvec_length(s) +#define MolReader_Writes_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t*, bool); +#define MolReader_Spawn_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Spawn_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Spawn_get_from(s) mol_table_slice_by_index(s, 0) +#define MolReader_Spawn_get_child(s) mol_table_slice_by_index(s, 1) +#define MolReader_Spawn_get_fds(s) mol_table_slice_by_index(s, 2) +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t*, bool); +#define MolReader_Spawns_length(s) mol_dynvec_length(s) +#define MolReader_Spawns_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t*, bool); +#define MolReader_Data_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Data_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Data_get_spawns(s) mol_table_slice_by_index(s, 0) +#define MolReader_Data_get_pipes(s) mol_table_slice_by_index(s, 1) +#define MolReader_Data_get_writes(s) mol_table_slice_by_index(s, 2) /* * Builder APIs */ -#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_FdIndex_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_FdIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_FdIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_FdIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_FdIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_FdIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_FdIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_FdIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_FdIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_FdIndex_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_FdIndex_clear(b) mol_builder_discard(b) -#define MolBuilder_FdIndices_init(b) mol_fixvec_builder_initialize(b, 128) -#define MolBuilder_FdIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) -#define MolBuilder_FdIndices_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_FdIndices_clear(b) mol_builder_discard(b) -#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) -#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) -#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Pipe_set_read_fd(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Pipe_set_write_fd(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t); -#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) -#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) -#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) -#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Write_set_from_fd(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_Write_set_to_fd(b, p, l) mol_table_builder_add(b, 3, p, l) -#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t); -#define MolBuilder_Write_clear(b) mol_builder_discard(b) -#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Writes_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Spawn_set_fds(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t); -#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) -#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) -#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) -#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) -#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t); -#define MolBuilder_Data_clear(b) mol_builder_discard(b) +#define MolBuilder_VmIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_VmIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_VmIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_VmIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_VmIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_VmIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_VmIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_VmIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_VmIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_VmIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_VmIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_FdIndex_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_FdIndex_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_FdIndex_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_FdIndex_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_FdIndex_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_FdIndex_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_FdIndex_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_FdIndex_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_FdIndex_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_FdIndex_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_FdIndex_clear(b) mol_builder_discard(b) +#define MolBuilder_FdIndices_init(b) mol_fixvec_builder_initialize(b, 128) +#define MolBuilder_FdIndices_push(b, p) mol_fixvec_builder_push(b, p, 8) +#define MolBuilder_FdIndices_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_FdIndices_clear(b) mol_builder_discard(b) +#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipe_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Pipe_set_vm(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Pipe_set_read_fd(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Pipe_set_write_fd(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t); +#define MolBuilder_Pipe_clear(b) mol_builder_discard(b) +#define MolBuilder_Pipes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Pipes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Pipes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Pipes_clear(b) mol_builder_discard(b) +#define MolBuilder_Write_init(b) mol_table_builder_initialize(b, 256, 5) +#define MolBuilder_Write_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Write_set_from_fd(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Write_set_to(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_Write_set_to_fd(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_Write_set_data(b, p, l) mol_table_builder_add(b, 4, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t); +#define MolBuilder_Write_clear(b) mol_builder_discard(b) +#define MolBuilder_Writes_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Writes_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Writes_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Writes_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawn_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Spawn_set_from(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Spawn_set_child(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Spawn_set_fds(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t); +#define MolBuilder_Spawn_clear(b) mol_builder_discard(b) +#define MolBuilder_Spawns_init(b) mol_builder_initialize_with_capacity(b, 1024, 64) +#define MolBuilder_Spawns_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_Spawns_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_Spawns_clear(b) mol_builder_discard(b) +#define MolBuilder_Data_init(b) mol_table_builder_initialize(b, 128, 3) +#define MolBuilder_Data_set_spawns(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Data_set_pipes(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Data_set_writes(b, p, l) mol_table_builder_add(b, 2, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t); +#define MolBuilder_Data_clear(b) mol_builder_discard(b) /* * Default Value @@ -162,35 +162,39 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t); #define ____ 0x00 -MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_VmIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndex[8] = { +MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndex[8] = { ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndices[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { - 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_FdIndices[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipe[40] = { + 0x28, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { - 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, 0x28, ____, ____, - ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Pipes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Write[60] = { + 0x3c, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, + 0x28, ____, ____, ____, 0x30, ____, ____, ____, 0x38, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { - 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, 0x20, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Writes[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawn[36] = { + 0x24, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x20, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, }; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { - 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, 0x18, ____, - ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, +MOLECULE_API_DECORATOR const uint8_t MolDefault_Spawns[4] = {0x04, ____, ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { + 0x1c, ____, ____, ____, 0x10, ____, ____, ____, 0x14, ____, ____, ____, + 0x18, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, + 0x04, ____, ____, ____, }; #undef ____ @@ -199,7 +203,7 @@ MOLECULE_API_DECORATOR const uint8_t MolDefault_Data[28] = { * Reader Functions */ -MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -213,7 +217,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, b } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -222,45 +226,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipe_verify(const mol_seg_t *input, b } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -277,15 +281,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i = 1; i < item_count; i++) { + for (mol_num_t i=1; i end) { @@ -308,7 +312,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Pipes_verify(const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Pipe_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -322,7 +326,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -331,57 +335,57 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Write_verify(const mol_seg_t *input, } else if (!compatible && field_count > 5) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_FdIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[4]; - inner.size = offsets[5] - offsets[4]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_FdIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -398,15 +402,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i = 1; i < item_count; i++) { + for (mol_num_t i=1; i end) { @@ -429,7 +433,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Writes_verify(const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Write_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -443,7 +447,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -452,45 +456,45 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawn_verify(const mol_seg_t *input, } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_VmIndex_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_FdIndices_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_VmIndex_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_FdIndices_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } -MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -507,15 +511,15 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { return MOL_ERR_HEADER; } mol_num_t end; - for (mol_num_t i = 1; i < item_count; i++) { + for (mol_num_t i=1; i end) { @@ -538,7 +542,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Spawns_verify(const mol_seg_t *input, inner.size = total_size - offset; return MolReader_Spawn_verify(&inner, compatible); } -MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, bool compatible) { +MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify (const mol_seg_t *input, bool compatible) { if (input->size < MOL_NUM_T_SIZE) { return MOL_ERR_HEADER; } @@ -552,7 +556,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, b } ptr += MOL_NUM_T_SIZE; mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { return MOL_ERR_OFFSET; } mol_num_t field_count = offset / 4 - 1; @@ -561,42 +565,42 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, b } else if (!compatible && field_count > 3) { return MOL_ERR_FIELD_COUNT; } - if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ return MOL_ERR_HEADER; } - mol_num_t offsets[field_count + 1]; + mol_num_t offsets[field_count+1]; offsets[0] = offset; - for (mol_num_t i = 1; i < field_count; i++) { + for (mol_num_t i=1; i offsets[i]) { + if (offsets[i-1] > offsets[i]) { return MOL_ERR_OFFSET; } } - if (offsets[field_count - 1] > total_size) { + if (offsets[field_count-1] > total_size) { return MOL_ERR_OFFSET; } offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Spawns_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_Pipes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_Writes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Spawns_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Pipes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Writes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } return MOL_OK; } @@ -604,7 +608,7 @@ MOLECULE_API_DECORATOR mol_errno MolReader_Data_verify(const mol_seg_t *input, b * Builder Functions */ -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -616,7 +620,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 8 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -639,7 +643,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; @@ -648,7 +652,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; @@ -657,13 +661,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Pipe_build(mol_builder_t builder memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 24; @@ -679,7 +683,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[9]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -710,7 +714,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; @@ -719,7 +723,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; @@ -728,7 +732,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[7]; @@ -737,7 +741,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_FdIndex, len); } else { mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[9]; @@ -746,13 +750,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Write_build(mol_builder_t builde memcpy(dst, &MolDefault_Bytes, len); } else { mol_num_t of = builder.number_ptr[8]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -764,7 +768,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde res.seg.size += len == 0 ? 8 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -787,7 +791,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; @@ -796,7 +800,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde memcpy(dst, &MolDefault_VmIndex, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; @@ -805,13 +809,13 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Spawn_build(mol_builder_t builde memcpy(dst, &MolDefault_FdIndices, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); return res; } -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder) { +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build (mol_builder_t builder) { mol_seg_res_t res; res.errno = MOL_OK; mol_num_t offset = 16; @@ -823,7 +827,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder res.seg.size += len == 0 ? 4 : len; len = builder.number_ptr[5]; res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t *)malloc(res.seg.size); + res.seg.ptr = (uint8_t*)malloc(res.seg.size); uint8_t *dst = res.seg.ptr; mol_pack_number(dst, &res.seg.size); dst += MOL_NUM_T_SIZE; @@ -846,7 +850,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder memcpy(dst, &MolDefault_Spawns, len); } else { mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[3]; @@ -855,7 +859,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder memcpy(dst, &MolDefault_Pipes, len); } else { mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; len = builder.number_ptr[5]; @@ -864,7 +868,7 @@ MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Data_build(mol_builder_t builder memcpy(dst, &MolDefault_Writes, len); } else { mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src + of, len); + memcpy(dst, src+of, len); } dst += len; mol_builder_discard(builder); diff --git a/script/testdata/spawn_dag.rs b/script/testdata/spawn_dag.rs index c381c072c0..f3a20a27c5 100644 --- a/script/testdata/spawn_dag.rs +++ b/script/testdata/spawn_dag.rs @@ -1,5 +1,4 @@ -// Generated by Molecule 0.7.5 - +// Generated by Molecule 0.8.0 #![allow(clippy::needless_lifetimes)] #![allow(clippy::needless_borrow)] #![allow(clippy::wrong_self_convention)] @@ -7,7 +6,8 @@ #![allow(clippy::derivable_impls)] #![allow(clippy::useless_conversion)] #![allow(clippy::write_literal)] - +#![allow(clippy::clone_on_copy)] +#![allow(clippy::fallible_impl_from)] use molecule::prelude::*; #[derive(Clone)] pub struct VmIndex(molecule::bytes::Bytes); @@ -184,6 +184,7 @@ impl<'r> molecule::prelude::Reader<'r> for VmIndexReader<'r> { Ok(()) } } +#[derive(Clone)] pub struct VmIndexBuilder(pub(crate) [Byte; 8]); impl ::core::fmt::Debug for VmIndexBuilder { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { @@ -269,6 +270,63 @@ impl molecule::prelude::Builder for VmIndexBuilder { VmIndex::new_unchecked(inner.into()) } } +impl From<[Byte; 8usize]> for VmIndex { + fn from(value: [Byte; 8usize]) -> Self { + Self::new_builder().set(value).build() + } +} +impl ::core::convert::TryFrom<&[Byte]> for VmIndex { + type Error = ::core::array::TryFromSliceError; + fn try_from(value: &[Byte]) -> Result { + Ok(Self::new_builder() + .set(<&[Byte; 8usize]>::try_from(value)?.clone()) + .build()) + } +} +impl From for [Byte; 8usize] { + #[track_caller] + fn from(value: VmIndex) -> Self { + [ + value.nth0(), + value.nth1(), + value.nth2(), + value.nth3(), + value.nth4(), + value.nth5(), + value.nth6(), + value.nth7(), + ] + } +} +impl From<[u8; 8usize]> for VmIndex { + fn from(value: [u8; 8usize]) -> Self { + VmIndexReader::new_unchecked(&value).to_entity() + } +} +impl ::core::convert::TryFrom<&[u8]> for VmIndex { + type Error = ::core::array::TryFromSliceError; + fn try_from(value: &[u8]) -> Result { + Ok(<[u8; 8usize]>::try_from(value)?.into()) + } +} +impl From for [u8; 8usize] { + #[track_caller] + fn from(value: VmIndex) -> Self { + ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() + } +} +impl<'a> From> for &'a [u8; 8usize] { + #[track_caller] + fn from(value: VmIndexReader<'a>) -> Self { + ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() + } +} +impl<'a> From<&'a VmIndexReader<'a>> for &'a [u8; 8usize] { + #[track_caller] + fn from(value: &'a VmIndexReader<'a>) -> Self { + ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() + } +} #[derive(Clone)] pub struct FdIndex(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for FdIndex { @@ -444,6 +502,7 @@ impl<'r> molecule::prelude::Reader<'r> for FdIndexReader<'r> { Ok(()) } } +#[derive(Clone)] pub struct FdIndexBuilder(pub(crate) [Byte; 8]); impl ::core::fmt::Debug for FdIndexBuilder { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { @@ -529,6 +588,63 @@ impl molecule::prelude::Builder for FdIndexBuilder { FdIndex::new_unchecked(inner.into()) } } +impl From<[Byte; 8usize]> for FdIndex { + fn from(value: [Byte; 8usize]) -> Self { + Self::new_builder().set(value).build() + } +} +impl ::core::convert::TryFrom<&[Byte]> for FdIndex { + type Error = ::core::array::TryFromSliceError; + fn try_from(value: &[Byte]) -> Result { + Ok(Self::new_builder() + .set(<&[Byte; 8usize]>::try_from(value)?.clone()) + .build()) + } +} +impl From for [Byte; 8usize] { + #[track_caller] + fn from(value: FdIndex) -> Self { + [ + value.nth0(), + value.nth1(), + value.nth2(), + value.nth3(), + value.nth4(), + value.nth5(), + value.nth6(), + value.nth7(), + ] + } +} +impl From<[u8; 8usize]> for FdIndex { + fn from(value: [u8; 8usize]) -> Self { + FdIndexReader::new_unchecked(&value).to_entity() + } +} +impl ::core::convert::TryFrom<&[u8]> for FdIndex { + type Error = ::core::array::TryFromSliceError; + fn try_from(value: &[u8]) -> Result { + Ok(<[u8; 8usize]>::try_from(value)?.into()) + } +} +impl From for [u8; 8usize] { + #[track_caller] + fn from(value: FdIndex) -> Self { + ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() + } +} +impl<'a> From> for &'a [u8; 8usize] { + #[track_caller] + fn from(value: FdIndexReader<'a>) -> Self { + ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() + } +} +impl<'a> From<&'a FdIndexReader<'a>> for &'a [u8; 8usize] { + #[track_caller] + fn from(value: &'a FdIndexReader<'a>) -> Self { + ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() + } +} #[derive(Clone)] pub struct FdIndices(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for FdIndices { @@ -708,7 +824,7 @@ impl<'r> molecule::prelude::Reader<'r> for FdIndicesReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct FdIndicesBuilder(pub(crate) Vec); impl FdIndicesBuilder { pub const ITEM_SIZE: usize = 8; @@ -801,6 +917,11 @@ impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for FdIndicesReaderIterator<'t, self.2 - self.1 } } +impl ::core::iter::FromIterator for FdIndices { + fn from_iter>(iter: T) -> Self { + Self::new_builder().extend(iter).build() + } +} #[derive(Clone)] pub struct Bytes(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Bytes { @@ -974,7 +1095,7 @@ impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct BytesBuilder(pub(crate) Vec); impl BytesBuilder { pub const ITEM_SIZE: usize = 1; @@ -1044,6 +1165,18 @@ impl ::core::iter::IntoIterator for Bytes { BytesIterator(self, 0, len) } } +impl ::core::iter::FromIterator for Bytes { + fn from_iter>(iter: T) -> Self { + Self::new_builder().extend(iter).build() + } +} +impl ::core::iter::FromIterator for Bytes { + fn from_iter>(iter: T) -> Self { + Self::new_builder() + .extend(iter.into_iter().map(Into::into)) + .build() + } +} #[derive(Clone)] pub struct Pipe(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Pipe { @@ -1277,7 +1410,7 @@ impl<'r> molecule::prelude::Reader<'r> for PipeReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct PipeBuilder { pub(crate) vm: VmIndex, pub(crate) read_fd: FdIndex, @@ -1555,7 +1688,7 @@ impl<'r> molecule::prelude::Reader<'r> for PipesReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct PipesBuilder(pub(crate) Vec); impl PipesBuilder { pub fn set(mut self, v: Vec) -> Self { @@ -1672,6 +1805,11 @@ impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for PipesReaderIterator<'t, 'r> self.2 - self.1 } } +impl ::core::iter::FromIterator for Pipes { + fn from_iter>(iter: T) -> Self { + Self::new_builder().extend(iter).build() + } +} #[derive(Clone)] pub struct Write(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Write { @@ -1938,7 +2076,7 @@ impl<'r> molecule::prelude::Reader<'r> for WriteReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct WriteBuilder { pub(crate) from: VmIndex, pub(crate) from_fd: FdIndex, @@ -2234,7 +2372,7 @@ impl<'r> molecule::prelude::Reader<'r> for WritesReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct WritesBuilder(pub(crate) Vec); impl WritesBuilder { pub fn set(mut self, v: Vec) -> Self { @@ -2351,6 +2489,11 @@ impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for WritesReaderIterator<'t, 'r self.2 - self.1 } } +impl ::core::iter::FromIterator for Writes { + fn from_iter>(iter: T) -> Self { + Self::new_builder().extend(iter).build() + } +} #[derive(Clone)] pub struct Spawn(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Spawn { @@ -2584,7 +2727,7 @@ impl<'r> molecule::prelude::Reader<'r> for SpawnReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct SpawnBuilder { pub(crate) from: VmIndex, pub(crate) child: VmIndex, @@ -2862,7 +3005,7 @@ impl<'r> molecule::prelude::Reader<'r> for SpawnsReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct SpawnsBuilder(pub(crate) Vec); impl SpawnsBuilder { pub fn set(mut self, v: Vec) -> Self { @@ -2979,6 +3122,11 @@ impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for SpawnsReaderIterator<'t, 'r self.2 - self.1 } } +impl ::core::iter::FromIterator for Spawns { + fn from_iter>(iter: T) -> Self { + Self::new_builder().extend(iter).build() + } +} #[derive(Clone)] pub struct Data(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Data { @@ -3211,7 +3359,7 @@ impl<'r> molecule::prelude::Reader<'r> for DataReader<'r> { Ok(()) } } -#[derive(Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct DataBuilder { pub(crate) spawns: Spawns, pub(crate) pipes: Pipes, From 770e9ce6e3fefbb0277206254529b255b9fa00b9 Mon Sep 17 00:00:00 2001 From: mohanson Date: Sat, 22 Jun 2024 20:50:29 +0800 Subject: [PATCH 128/135] Update cycles --- .../tests/ckb_latest/features_since_v2021.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index d5fad09344..fbb1956fed 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -807,10 +807,12 @@ fn _check_typical_secp256k1_blake160_2_in_2_out_tx_with_chunk(step_cycles: Cycle ); } assert_eq!(cycles, cycles_once, "step_cycles {step_cycles}"); + // Note that different rand versions may cause different randomly + // generated tx data, which in turn leads to different final cycles. if script_version < crate::ScriptVersion::V2 { - assert_eq!(cycles, 3387236); + assert_eq!(cycles, 3334802); } else { - assert_eq!(cycles, 3276322); + assert_eq!(cycles, 3225879); } } @@ -1014,12 +1016,14 @@ fn check_typical_secp256k1_blake160_2_in_2_out_tx_with_complete() { assert!(cycles >= TWO_IN_TWO_OUT_CYCLES - CYCLE_BOUND); } assert_eq!(cycles, cycles_once); + // Note that different rand versions may cause different randomly + // generated tx data, which in turn leads to different final cycles. if script_version <= ScriptVersion::V0 { - assert_eq!(cycles, 3405227); + assert_eq!(cycles, 3352333); } else if script_version == ScriptVersion::V1 { - assert_eq!(cycles, 3387236); + assert_eq!(cycles, 3334802); } else if script_version == ScriptVersion::V2 { - assert_eq!(cycles, 3276322); + assert_eq!(cycles, 3225879); } } From e875acd6098aa651213878ea0331b7f5ba21fa0c Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 1 Jul 2024 16:24:46 +0800 Subject: [PATCH 129/135] bless clippy --- script/src/syscalls/tests/vm_latest/syscalls_1.rs | 4 ++-- script/src/verify/tests/ckb_latest/features_since_v2023.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/script/src/syscalls/tests/vm_latest/syscalls_1.rs b/script/src/syscalls/tests/vm_latest/syscalls_1.rs index 776febb958..761537e2ff 100644 --- a/script/src/syscalls/tests/vm_latest/syscalls_1.rs +++ b/script/src/syscalls/tests/vm_latest/syscalls_1.rs @@ -2109,7 +2109,7 @@ fn test_load_cell_data_size_zero() { let data = Bytes::from(data.to_vec()); let dep_cell = build_cell_meta(10000, data.clone()); - let input_cell = build_cell_meta(100, data.clone()); + let input_cell = build_cell_meta(100, data); let data_loader = new_mock_data_loader(); @@ -2154,7 +2154,7 @@ fn test_load_cell_data_size_zero_index_out_of_bound() { let data = Bytes::from(data.to_vec()); let dep_cell = build_cell_meta(10000, data.clone()); - let input_cell = build_cell_meta(100, data.clone()); + let input_cell = build_cell_meta(100, data); let data_loader = new_mock_data_loader(); 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 a465c6515a..d3bbd3ee6d 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -751,7 +751,7 @@ fn check_spawn_configurable_once(spawn_from: SpawnFrom) { SpawnFrom::TxInputCell => { let input_spawn_callee_output = CellOutputBuilder::default() .capacity(capacity_bytes!(1000).pack()) - .lock(always_success_script.clone()) + .lock(always_success_script) .build(); let input_spawn_callee = CellMetaBuilder::from_cell_output( input_spawn_callee_output, @@ -770,7 +770,7 @@ fn check_spawn_configurable_once(spawn_from: SpawnFrom) { .output( CellOutputBuilder::default() .capacity(capacity_bytes!(100).pack()) - .lock(always_success_script.clone()) + .lock(always_success_script) .build(), ) .output_data(spawn_callee_cell_data.pack()) From e10caeafeda76503c20a702a63a99a883ff87142 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 5 Jul 2024 11:11:10 +0800 Subject: [PATCH 130/135] Add base cycles for exec in script-version-2 --- script/src/scheduler.rs | 8 ++-- script/src/syscalls/close.rs | 4 +- script/src/syscalls/exec.rs | 5 ++- script/src/syscalls/inherited_fd.rs | 4 +- script/src/syscalls/mod.rs | 4 +- script/src/syscalls/pipe.rs | 4 +- script/src/syscalls/read.rs | 4 +- script/src/syscalls/spawn.rs | 6 +-- script/src/syscalls/wait.rs | 4 +- script/src/syscalls/write.rs | 4 +- script/src/verify.rs | 15 ++++++- .../tests/ckb_latest/features_since_v2021.rs | 2 +- .../tests/ckb_latest/features_since_v2023.rs | 37 ++++++++++++++++++ script/testdata/Makefile | 2 + script/testdata/infinite_exec | Bin 0 -> 1408 bytes script/testdata/infinite_exec.c | 8 ++++ 16 files changed, 86 insertions(+), 25 deletions(-) create mode 100755 script/testdata/infinite_exec create mode 100644 script/testdata/infinite_exec.c diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index 3c93c0ee82..b6bda0e164 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,7 +1,7 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SPAWN_EXTRA_CYCLES_BASE, - SUCCESS, WAIT_FAILURE, + INVALID_FD, LOAD_ELF_CYCLES_BASE, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, + WAIT_FAILURE, }; use crate::types::MachineContext; use crate::verify::TransactionScriptsSyscallsGenerator; @@ -702,7 +702,7 @@ where let snapshot = &self.suspended[id]; self.current_iteration_cycles = self .current_iteration_cycles - .checked_add(SPAWN_EXTRA_CYCLES_BASE) + .checked_add(LOAD_ELF_CYCLES_BASE) .ok_or(Error::CyclesExceeded)?; let (context, mut machine) = self.create_dummy_vm(id)?; { @@ -724,7 +724,7 @@ where } self.current_iteration_cycles = self .current_iteration_cycles - .checked_add(SPAWN_EXTRA_CYCLES_BASE) + .checked_add(LOAD_ELF_CYCLES_BASE) .ok_or(Error::CyclesExceeded)?; let (context, machine) = self .instantiated diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs index 1e359095be..a46d66ad98 100644 --- a/script/src/syscalls/close.rs +++ b/script/src/syscalls/close.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{CLOSE, SPAWN_YIELD_CYCLES_BASE}; +use crate::syscalls::{CLOSE, YIELD_CYCLES_BASE}; use crate::types::{Fd, Message, VmId}; use ckb_vm::{ registers::{A0, A7}, @@ -28,7 +28,7 @@ impl Syscalls for Close { return Ok(false); } let fd = Fd(machine.registers()[A0].to_u64()); - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/exec.rs b/script/src/syscalls/exec.rs index 2c33a52165..6eb1d159c4 100644 --- a/script/src/syscalls/exec.rs +++ b/script/src/syscalls/exec.rs @@ -22,6 +22,7 @@ pub struct Exec
{ outputs: Arc>, group_inputs: Indices, group_outputs: Indices, + load_elf_base_fee: u64, } impl Exec
{ @@ -31,6 +32,7 @@ impl Exec
{ outputs: Arc>, group_inputs: Indices, group_outputs: Indices, + load_elf_base_fee: u64, ) -> Exec
{ Exec { data_loader, @@ -38,6 +40,7 @@ impl Exec
{ outputs, group_inputs, group_outputs, + load_elf_base_fee, } } @@ -109,7 +112,6 @@ impl Syscalls for if machine.registers()[A7].to_u64() != EXEC { return Ok(false); } - let index = machine.registers()[A0].to_u64(); let source = Source::parse_from_u64(machine.registers()[A1].to_u64())?; let place = Place::parse_from_u64(machine.registers()[A2].to_u64())?; @@ -176,6 +178,7 @@ impl Syscalls for machine.reset(max_cycles); machine.set_cycles(cycles); + machine.add_cycles_no_checking(self.load_elf_base_fee)?; match machine.load_elf(&data, true) { Ok(size) => { machine.add_cycles_no_checking(transferred_byte_cycles(size))?; diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs index 4d041a0ba1..c644883889 100644 --- a/script/src/syscalls/inherited_fd.rs +++ b/script/src/syscalls/inherited_fd.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{INHERITED_FD, SPAWN_YIELD_CYCLES_BASE}; +use crate::syscalls::{INHERITED_FD, YIELD_CYCLES_BASE}; use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A7}, @@ -29,7 +29,7 @@ impl Syscalls for InheritedFd { } let buffer_addr = machine.registers()[A0].to_u64(); let length_addr = machine.registers()[A1].to_u64(); - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index 984f2aa854..6ed49e4d23 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -98,8 +98,8 @@ pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; #[cfg(test)] pub const DEBUG_PAUSE: u64 = 2178; -pub const SPAWN_EXTRA_CYCLES_BASE: u64 = 100_000; -pub const SPAWN_YIELD_CYCLES_BASE: u64 = 800; +pub const LOAD_ELF_CYCLES_BASE: u64 = 100_000; +pub const YIELD_CYCLES_BASE: u64 = 800; #[derive(Debug, PartialEq, Clone, Copy, Eq)] enum CellField { diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs index 3bb61ba22d..f1414a258e 100644 --- a/script/src/syscalls/pipe.rs +++ b/script/src/syscalls/pipe.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{PIPE, SPAWN_YIELD_CYCLES_BASE}; +use crate::syscalls::{PIPE, YIELD_CYCLES_BASE}; use crate::types::{Message, PipeArgs, VmId}; use ckb_vm::{ registers::{A0, A7}, @@ -29,7 +29,7 @@ impl Syscalls for Pipe { } let fd1_addr = machine.registers()[A0].to_u64(); let fd2_addr = fd1_addr.wrapping_add(8); - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 63976ef096..1973c7dd10 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{INVALID_FD, READ, SPAWN_YIELD_CYCLES_BASE}; +use crate::syscalls::{INVALID_FD, READ, YIELD_CYCLES_BASE}; use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, @@ -41,7 +41,7 @@ impl Syscalls for Read { machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); } - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 5be3c3dd2b..309be7165c 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,6 +1,6 @@ use crate::syscalls::utils::load_c_string; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, + INDEX_OUT_OF_BOUND, LOAD_ELF_CYCLES_BASE, SLICE_OUT_OF_BOUND, SPAWN, YIELD_CYCLES_BASE, }; use crate::types::{DataPieceId, Fd, Message, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; @@ -141,8 +141,8 @@ where return Ok(true); } } - machine.add_cycles_no_checking(SPAWN_EXTRA_CYCLES_BASE)?; - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(LOAD_ELF_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/wait.rs b/script/src/syscalls/wait.rs index c9a49566aa..ad5a130549 100644 --- a/script/src/syscalls/wait.rs +++ b/script/src/syscalls/wait.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{SPAWN_YIELD_CYCLES_BASE, WAIT}; +use crate::syscalls::{WAIT, YIELD_CYCLES_BASE}; use crate::types::{Message, VmId, WaitArgs}; use ckb_vm::{ registers::{A0, A1, A7}, @@ -29,7 +29,7 @@ impl Syscalls for Wait { } let target_id = machine.registers()[A0].to_u64(); let exit_code_addr = machine.registers()[A1].to_u64(); - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index a193f5589b..a312cd94d5 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{INVALID_FD, SPAWN_YIELD_CYCLES_BASE, WRITE}; +use crate::syscalls::{INVALID_FD, WRITE, YIELD_CYCLES_BASE}; use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, @@ -42,7 +42,7 @@ impl Syscalls for Write { machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); } - machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/verify.rs b/script/src/verify.rs index 09a8f94dce..44c6a2d6af 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1,7 +1,7 @@ use crate::scheduler::Scheduler; #[cfg(test)] use crate::syscalls::Pause; -use crate::syscalls::{InheritedFd, ProcessID}; +use crate::syscalls::{InheritedFd, ProcessID, LOAD_ELF_CYCLES_BASE}; use crate::types::{DataPieceId, FullSuspendedState, Message, RunMode, TxData, VmId, FIRST_VM_ID}; use crate::{ error::{ScriptError, TransactionScriptError}, @@ -169,13 +169,19 @@ where } /// Build syscall: exec - pub fn build_exec(&self, group_inputs: Indices, group_outputs: Indices) -> Exec
{ + pub fn build_exec( + &self, + group_inputs: Indices, + group_outputs: Indices, + load_elf_base_fee: u64, + ) -> Exec
{ Exec::new( self.data_loader.clone(), Arc::clone(&self.rtx), Arc::clone(&self.outputs), group_inputs, group_outputs, + load_elf_base_fee, ) } @@ -320,6 +326,11 @@ where Box::new(self.build_exec( Arc::clone(&script_group_input_indices), Arc::clone(&script_group_output_indices), + if script_version >= ScriptVersion::V2 { + LOAD_ELF_CYCLES_BASE + } else { + 0 + }, )), Box::new(self.build_current_cycles()), ]); diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index fbb1956fed..05f26f6ef7 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -385,7 +385,7 @@ fn check_exec_from_witness() { if script_version == ScriptVersion::V1 { assert_eq!(result.ok(), Some(1200)); } else if script_version == ScriptVersion::V2 { - assert_eq!(result.ok(), Some(1198)); + assert_eq!(result.ok(), Some(101198)); } } 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 d3bbd3ee6d..c3a380367d 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1326,3 +1326,40 @@ fn check_spawn_saturate_memory() { let result = simple_spawn_test("testdata/spawn_saturate_memory", &[0]); assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); } + +#[test] +fn check_infinite_exec() { + let script_version = SCRIPT_VERSION; + + let (exec_caller_cell, exec_caller_data_hash) = load_cell_from_path("testdata/infinite_exec"); + let exec_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(exec_caller_data_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(exec_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![exec_caller_cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify(script_version, &rtx, 70000000); + if script_version >= ScriptVersion::V1 { + assert!(result + .unwrap_err() + .to_string() + .contains("ExceededMaximumCycles")) + } else { + assert!(result.is_err()) + } +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 8d72cc3900..9db92fd549 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -48,6 +48,7 @@ ALL_BINS := jalr_zero \ exec_caller_big_offset_length \ exec_configurable_callee \ exec_configurable_caller \ + infinite_exec \ infinite_loop \ load_code_to_stack_then_reuse \ load_is_even_into_global \ @@ -121,6 +122,7 @@ cpop_lock: cpop_lock.c mop_adc_lock: mop_adc_lock.S current_cycles: current_cycles.c current_cycles_with_snapshot: current_cycles_with_snapshot.c +infinite_exec: infinite_exec.c infinite_loop: infinite_loop.c vm_version: vm_version.c vm_version_2: vm_version_2.c diff --git a/script/testdata/infinite_exec b/script/testdata/infinite_exec new file mode 100755 index 0000000000000000000000000000000000000000..e5e4aad750e6e970c4fec0f286865eb3aab4c1f1 GIT binary patch literal 1408 zcmbtUPiqrF6n~pPZ9FygRP>TU4=S=GYn4(8Hf=XSkSavM+pxPG>q2%DcBdsRXq$Qy z#6u3=1P@+3*NbvVDz zm+w`pwUyhInqxb573xpWpM+_!50;B+pft_xxO zGK@pP8SnAH4q&Nwr6Xl*x83o*HtTl6Sny;C7;A0SpVirh+kCXm7}^`H7IU|^GTl#8 zmI^Ns5P4yY&godb;|UKKk9Pp<^dJ(Rk0=s}ue2t3Pk literal 0 HcmV?d00001 diff --git a/script/testdata/infinite_exec.c b/script/testdata/infinite_exec.c new file mode 100644 index 0000000000..3255ae2f64 --- /dev/null +++ b/script/testdata/infinite_exec.c @@ -0,0 +1,8 @@ +#include "ckb_syscalls.h" + +int main() { + int argc = 0; + char *argv[] = {}; + syscall(2043, 0, 3, 0, 0, argc, argv); + return -1; +} From ed1d4b924a35aadb7206710e8ffea96029a5ff4f Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 5 Jul 2024 13:32:48 +0800 Subject: [PATCH 131/135] Reduce load elf base cycles to 50k --- script/src/scheduler.rs | 8 ++++---- script/src/syscalls/close.rs | 4 ++-- script/src/syscalls/inherited_fd.rs | 4 ++-- script/src/syscalls/mod.rs | 5 +++-- script/src/syscalls/pipe.rs | 4 ++-- script/src/syscalls/read.rs | 4 ++-- script/src/syscalls/spawn.rs | 6 +++--- script/src/syscalls/wait.rs | 4 ++-- script/src/syscalls/write.rs | 4 ++-- script/src/verify.rs | 4 ++-- .../src/verify/tests/ckb_latest/features_since_v2021.rs | 2 +- script/testdata/spawn_cycles.c | 4 ++-- 12 files changed, 27 insertions(+), 26 deletions(-) diff --git a/script/src/scheduler.rs b/script/src/scheduler.rs index b6bda0e164..3c93c0ee82 100644 --- a/script/src/scheduler.rs +++ b/script/src/scheduler.rs @@ -1,7 +1,7 @@ use crate::cost_model::transferred_byte_cycles; use crate::syscalls::{ - INVALID_FD, LOAD_ELF_CYCLES_BASE, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SUCCESS, - WAIT_FAILURE, + INVALID_FD, MAX_FDS_CREATED, MAX_VMS_SPAWNED, OTHER_END_CLOSED, SPAWN_EXTRA_CYCLES_BASE, + SUCCESS, WAIT_FAILURE, }; use crate::types::MachineContext; use crate::verify::TransactionScriptsSyscallsGenerator; @@ -702,7 +702,7 @@ where let snapshot = &self.suspended[id]; self.current_iteration_cycles = self .current_iteration_cycles - .checked_add(LOAD_ELF_CYCLES_BASE) + .checked_add(SPAWN_EXTRA_CYCLES_BASE) .ok_or(Error::CyclesExceeded)?; let (context, mut machine) = self.create_dummy_vm(id)?; { @@ -724,7 +724,7 @@ where } self.current_iteration_cycles = self .current_iteration_cycles - .checked_add(LOAD_ELF_CYCLES_BASE) + .checked_add(SPAWN_EXTRA_CYCLES_BASE) .ok_or(Error::CyclesExceeded)?; let (context, machine) = self .instantiated diff --git a/script/src/syscalls/close.rs b/script/src/syscalls/close.rs index a46d66ad98..1e359095be 100644 --- a/script/src/syscalls/close.rs +++ b/script/src/syscalls/close.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{CLOSE, YIELD_CYCLES_BASE}; +use crate::syscalls::{CLOSE, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Fd, Message, VmId}; use ckb_vm::{ registers::{A0, A7}, @@ -28,7 +28,7 @@ impl Syscalls for Close { return Ok(false); } let fd = Fd(machine.registers()[A0].to_u64()); - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/inherited_fd.rs b/script/src/syscalls/inherited_fd.rs index c644883889..4d041a0ba1 100644 --- a/script/src/syscalls/inherited_fd.rs +++ b/script/src/syscalls/inherited_fd.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{INHERITED_FD, YIELD_CYCLES_BASE}; +use crate::syscalls::{INHERITED_FD, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A7}, @@ -29,7 +29,7 @@ impl Syscalls for InheritedFd { } let buffer_addr = machine.registers()[A0].to_u64(); let length_addr = machine.registers()[A1].to_u64(); - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index 6ed49e4d23..e2d0b38439 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -98,8 +98,9 @@ pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; #[cfg(test)] pub const DEBUG_PAUSE: u64 = 2178; -pub const LOAD_ELF_CYCLES_BASE: u64 = 100_000; -pub const YIELD_CYCLES_BASE: u64 = 800; +pub const EXEC_LOAD_ELF_V2_CYCLES_BASE: u64 = 50_000; +pub const SPAWN_EXTRA_CYCLES_BASE: u64 = 100_000; +pub const SPAWN_YIELD_CYCLES_BASE: u64 = 800; #[derive(Debug, PartialEq, Clone, Copy, Eq)] enum CellField { diff --git a/script/src/syscalls/pipe.rs b/script/src/syscalls/pipe.rs index f1414a258e..3bb61ba22d 100644 --- a/script/src/syscalls/pipe.rs +++ b/script/src/syscalls/pipe.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{PIPE, YIELD_CYCLES_BASE}; +use crate::syscalls::{PIPE, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Message, PipeArgs, VmId}; use ckb_vm::{ registers::{A0, A7}, @@ -29,7 +29,7 @@ impl Syscalls for Pipe { } let fd1_addr = machine.registers()[A0].to_u64(); let fd2_addr = fd1_addr.wrapping_add(8); - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/read.rs b/script/src/syscalls/read.rs index 1973c7dd10..63976ef096 100644 --- a/script/src/syscalls/read.rs +++ b/script/src/syscalls/read.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{INVALID_FD, READ, YIELD_CYCLES_BASE}; +use crate::syscalls::{INVALID_FD, READ, SPAWN_YIELD_CYCLES_BASE}; use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, @@ -41,7 +41,7 @@ impl Syscalls for Read { machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); } - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 309be7165c..5be3c3dd2b 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,6 +1,6 @@ use crate::syscalls::utils::load_c_string; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, LOAD_ELF_CYCLES_BASE, SLICE_OUT_OF_BOUND, SPAWN, YIELD_CYCLES_BASE, + INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, }; use crate::types::{DataPieceId, Fd, Message, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; @@ -141,8 +141,8 @@ where return Ok(true); } } - machine.add_cycles_no_checking(LOAD_ELF_CYCLES_BASE)?; - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_EXTRA_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/wait.rs b/script/src/syscalls/wait.rs index ad5a130549..c9a49566aa 100644 --- a/script/src/syscalls/wait.rs +++ b/script/src/syscalls/wait.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{WAIT, YIELD_CYCLES_BASE}; +use crate::syscalls::{SPAWN_YIELD_CYCLES_BASE, WAIT}; use crate::types::{Message, VmId, WaitArgs}; use ckb_vm::{ registers::{A0, A1, A7}, @@ -29,7 +29,7 @@ impl Syscalls for Wait { } let target_id = machine.registers()[A0].to_u64(); let exit_code_addr = machine.registers()[A1].to_u64(); - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/syscalls/write.rs b/script/src/syscalls/write.rs index a312cd94d5..a193f5589b 100644 --- a/script/src/syscalls/write.rs +++ b/script/src/syscalls/write.rs @@ -1,4 +1,4 @@ -use crate::syscalls::{INVALID_FD, WRITE, YIELD_CYCLES_BASE}; +use crate::syscalls::{INVALID_FD, SPAWN_YIELD_CYCLES_BASE, WRITE}; use crate::types::{Fd, FdArgs, Message, VmId}; use ckb_vm::{ registers::{A0, A1, A2, A7}, @@ -42,7 +42,7 @@ impl Syscalls for Write { machine.set_register(A0, Mac::REG::from_u8(INVALID_FD)); return Ok(true); } - machine.add_cycles_no_checking(YIELD_CYCLES_BASE)?; + machine.add_cycles_no_checking(SPAWN_YIELD_CYCLES_BASE)?; self.message_box .lock() .map_err(|e| VMError::Unexpected(e.to_string()))? diff --git a/script/src/verify.rs b/script/src/verify.rs index 44c6a2d6af..f91328e598 100644 --- a/script/src/verify.rs +++ b/script/src/verify.rs @@ -1,7 +1,7 @@ use crate::scheduler::Scheduler; #[cfg(test)] use crate::syscalls::Pause; -use crate::syscalls::{InheritedFd, ProcessID, LOAD_ELF_CYCLES_BASE}; +use crate::syscalls::{InheritedFd, ProcessID, EXEC_LOAD_ELF_V2_CYCLES_BASE}; use crate::types::{DataPieceId, FullSuspendedState, Message, RunMode, TxData, VmId, FIRST_VM_ID}; use crate::{ error::{ScriptError, TransactionScriptError}, @@ -327,7 +327,7 @@ where Arc::clone(&script_group_input_indices), Arc::clone(&script_group_output_indices), if script_version >= ScriptVersion::V2 { - LOAD_ELF_CYCLES_BASE + EXEC_LOAD_ELF_V2_CYCLES_BASE } else { 0 }, diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index 05f26f6ef7..d623958fc5 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -385,7 +385,7 @@ fn check_exec_from_witness() { if script_version == ScriptVersion::V1 { assert_eq!(result.ok(), Some(1200)); } else if script_version == ScriptVersion::V2 { - assert_eq!(result.ok(), Some(101198)); + assert_eq!(result.ok(), Some(51198)); } } diff --git a/script/testdata/spawn_cycles.c b/script/testdata/spawn_cycles.c index dc394623f4..a338d73d4b 100644 --- a/script/testdata/spawn_cycles.c +++ b/script/testdata/spawn_cycles.c @@ -6,7 +6,7 @@ const uint64_t SYSCALL_CYCLES_BASE = 500; const uint64_t SPAWN_EXTRA_CYCLES_BASE = 100000; -const uint64_t SPAWN_YIELD_CYCLES_BASE = 800; +const uint64_t SPAWN_SPAWN_YIELD_CYCLES_BASE = 800; int tic() { static uint64_t tic = 0; @@ -19,7 +19,7 @@ int tic() { uint64_t cal_cycles(uint64_t nbase, uint64_t yield, uint64_t extra) { uint64_t r = 0; r += SYSCALL_CYCLES_BASE * nbase; - r += SPAWN_YIELD_CYCLES_BASE * yield; + r += SPAWN_SPAWN_YIELD_CYCLES_BASE * yield; r += SPAWN_EXTRA_CYCLES_BASE * extra; return r; } From 63afcf40bae2f68ee6d1e2eee311109b0fad0543 Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 5 Jul 2024 13:40:18 +0800 Subject: [PATCH 132/135] Increase to 75000 --- script/src/syscalls/mod.rs | 2 +- script/src/verify/tests/ckb_latest/features_since_v2021.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/src/syscalls/mod.rs b/script/src/syscalls/mod.rs index e2d0b38439..4e09f8968e 100644 --- a/script/src/syscalls/mod.rs +++ b/script/src/syscalls/mod.rs @@ -98,7 +98,7 @@ pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177; #[cfg(test)] pub const DEBUG_PAUSE: u64 = 2178; -pub const EXEC_LOAD_ELF_V2_CYCLES_BASE: u64 = 50_000; +pub const EXEC_LOAD_ELF_V2_CYCLES_BASE: u64 = 75_000; pub const SPAWN_EXTRA_CYCLES_BASE: u64 = 100_000; pub const SPAWN_YIELD_CYCLES_BASE: u64 = 800; diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index d623958fc5..437b90642a 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -385,7 +385,7 @@ fn check_exec_from_witness() { if script_version == ScriptVersion::V1 { assert_eq!(result.ok(), Some(1200)); } else if script_version == ScriptVersion::V2 { - assert_eq!(result.ok(), Some(51198)); + assert_eq!(result.ok(), Some(76198)); } } From 38279e118d3fda3c52f1d47d2062f80e19a2d523 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 18 Jul 2024 10:16:30 +0800 Subject: [PATCH 133/135] To keep compatible with the old Source::parse_from_u64 behavior --- script/src/syscalls/load_cell_data.rs | 10 ++++++++-- script/src/syscalls/spawn.rs | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index 2663d8c85d..9eb4c56674 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -2,8 +2,8 @@ use crate::types::{DataPieceId, TxData}; use crate::{ cost_model::transferred_byte_cycles, syscalls::{ - INDEX_OUT_OF_BOUND, LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER, LOAD_CELL_DATA_SYSCALL_NUMBER, - SLICE_OUT_OF_BOUND, SUCCESS, + Source, INDEX_OUT_OF_BOUND, LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER, + LOAD_CELL_DATA_SYSCALL_NUMBER, SLICE_OUT_OF_BOUND, SUCCESS, }, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; @@ -35,6 +35,9 @@ where fn load_data(&self, machine: &mut Mac) -> Result<(), VMError> { let index = machine.registers()[A3].to_u64(); let source = machine.registers()[A4].to_u64(); + // To keep compatible with the old behavior. When Source is wrong, a + // Vm internal error should be returned. + let _ = Source::parse_from_u64(source)?; let data_piece_id = match DataPieceId::try_from((source, index, 0)) { Ok(id) => id, Err(_) => { @@ -99,6 +102,9 @@ where let content_size = machine.registers()[A3].to_u64(); let index = machine.registers()[A4].to_u64(); let source = machine.registers()[A5].to_u64(); + // To keep compatible with the old behavior. When Source is wrong, a + // Vm internal error should be returned. + let _ = Source::parse_from_u64(source)?; let data_piece_id = match DataPieceId::try_from((source, index, 0)) { Ok(id) => id, Err(_) => { diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index 5be3c3dd2b..e2879c5cf2 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,6 +1,7 @@ use crate::syscalls::utils::load_c_string; use crate::syscalls::{ - INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, + Source, INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, + SPAWN_YIELD_CYCLES_BASE, }; use crate::types::{DataPieceId, Fd, Message, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; @@ -56,6 +57,9 @@ where let index = machine.registers()[A0].to_u64(); let source = machine.registers()[A1].to_u64(); let place = machine.registers()[A2].to_u64(); + // To keep compatible with the old behavior. When Source is wrong, a + // Vm internal error should be returned. + let _ = Source::parse_from_u64(source)?; let data_piece_id = match DataPieceId::try_from((source, index, place)) { Ok(id) => id, Err(_) => { From ea4aea7fa4cd87ce5df6dee6616466458ff5a86e Mon Sep 17 00:00:00 2001 From: mohanson Date: Fri, 19 Jul 2024 18:27:21 +0800 Subject: [PATCH 134/135] Load cell data before load size --- script/src/syscalls/load_cell_data.rs | 51 ++++++------- .../tests/ckb_latest/features_since_v2023.rs | 72 ++++++++++++++++++ script/testdata/crash-45a6098d | Bin 0 -> 32504 bytes script/testdata/crash-5a27052f | Bin 0 -> 32504 bytes 4 files changed, 97 insertions(+), 26 deletions(-) create mode 100644 script/testdata/crash-45a6098d create mode 100644 script/testdata/crash-5a27052f diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index 9eb4c56674..b67687cbe9 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -47,41 +47,43 @@ where }; let addr = machine.registers()[A0].to_u64(); let size_addr = machine.registers()[A1].clone(); - let size = machine.memory_mut().load64(&size_addr)?.to_u64(); let offset = machine.registers()[A2].to_u64(); let mut sc = self .snapshot2_context .lock() .map_err(|e| VMError::Unexpected(e.to_string()))?; - if size == 0 { - match sc.load_data(&data_piece_id, offset, u64::max_value()) { - Ok((cell, _)) => { + match sc.load_data(&data_piece_id, offset, u64::max_value()) { + Ok((cell, _)) => { + let size = machine.memory_mut().load64(&size_addr)?.to_u64(); + if size == 0 { machine .memory_mut() .store64(&size_addr, &Mac::REG::from_u64(cell.len() as u64))?; machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); return Ok(()); } - Err(VMError::SnapshotDataLoadError) => { - // This comes from TxData results in an out of bound error, to - // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. - machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); - return Ok(()); - } - Err(e) => return Err(e), + let (wrote_size, _) = match sc.store_bytes( + machine, + addr, + &data_piece_id, + offset, + size, + size_addr.to_u64(), + ) { + Ok(val) => val, + Err(VMError::SnapshotDataLoadError) => { + // This comes from TxData results in an out of bound error, to + // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. + machine.set_register(A0, Mac::REG::from_u8(INDEX_OUT_OF_BOUND)); + return Ok(()); + } + Err(e) => return Err(e), + }; + machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; + machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); + return Ok(()); } - } - - let (wrote_size, _) = match sc.store_bytes( - machine, - addr, - &data_piece_id, - offset, - size, - size_addr.to_u64(), - ) { - Ok(val) => val, Err(VMError::SnapshotDataLoadError) => { // This comes from TxData results in an out of bound error, to // mimic current behavior, we would return INDEX_OUT_OF_BOUND error. @@ -89,10 +91,7 @@ where return Ok(()); } Err(e) => return Err(e), - }; - machine.add_cycles_no_checking(transferred_byte_cycles(wrote_size))?; - machine.set_register(A0, Mac::REG::from_u8(SUCCESS)); - Ok(()) + } } fn load_data_as_code(&self, machine: &mut Mac) -> Result<(), VMError> { 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 c3a380367d..468891745b 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1363,3 +1363,75 @@ fn check_infinite_exec() { assert!(result.is_err()) } } + +#[test] +fn check_fuzz_crash_1() { + let script_version = SCRIPT_VERSION; + + let (exec_caller_cell, exec_caller_data_hash) = load_cell_from_path("testdata/crash-5a27052f"); + let exec_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(exec_caller_data_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(exec_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![exec_caller_cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify(script_version, &rtx, 70000000); + match script_version { + ScriptVersion::V0 => assert!(result + .unwrap_err() + .to_string() + .contains("MemWriteOnExecutablePage")), + ScriptVersion::V1 | ScriptVersion::V2 => assert!(result + .unwrap_err() + .to_string() + .contains("SourceEntry parse_from_u64 0")), + } +} + +#[test] +fn check_fuzz_crash_2() { + let script_version = SCRIPT_VERSION; + let (exec_caller_cell, exec_caller_data_hash) = load_cell_from_path("testdata/crash-45a6098d"); + let exec_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(exec_caller_data_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(exec_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![exec_caller_cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify(script_version, &rtx, 70000000); + match script_version { + ScriptVersion::V0 => assert!(result + .unwrap_err() + .to_string() + .contains("MemWriteOnExecutablePage")), + ScriptVersion::V1 => assert_eq!(result.unwrap(), 58741), + ScriptVersion::V2 => assert_eq!(result.unwrap(), 58686), + } +} diff --git a/script/testdata/crash-45a6098d b/script/testdata/crash-45a6098d new file mode 100644 index 0000000000000000000000000000000000000000..1980f8d2d91c13301ec8bfaf44926fde7691c202 GIT binary patch literal 32504 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 G{r?9;Rd4nH literal 0 HcmV?d00001 diff --git a/script/testdata/crash-5a27052f b/script/testdata/crash-5a27052f new file mode 100644 index 0000000000000000000000000000000000000000..fd90467c4950ac4590e4eb3b71156c3f812b34ff GIT binary patch literal 32504 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 Date: Fri, 26 Jul 2024 20:48:54 +0800 Subject: [PATCH 135/135] Fix source and data_piece_id's inconsistency --- script/src/syscalls/load_cell_data.rs | 19 +++++++++--- script/src/syscalls/spawn.rs | 12 +++++--- .../tests/ckb_latest/features_since_v2023.rs | 29 ++++++++++++++++++ script/testdata/crash-4717eb0e | Bin 0 -> 32504 bytes 4 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 script/testdata/crash-4717eb0e diff --git a/script/src/syscalls/load_cell_data.rs b/script/src/syscalls/load_cell_data.rs index b67687cbe9..65ea6a778b 100644 --- a/script/src/syscalls/load_cell_data.rs +++ b/script/src/syscalls/load_cell_data.rs @@ -3,7 +3,8 @@ use crate::{ cost_model::transferred_byte_cycles, syscalls::{ Source, INDEX_OUT_OF_BOUND, LOAD_CELL_DATA_AS_CODE_SYSCALL_NUMBER, - LOAD_CELL_DATA_SYSCALL_NUMBER, SLICE_OUT_OF_BOUND, SUCCESS, + LOAD_CELL_DATA_SYSCALL_NUMBER, SLICE_OUT_OF_BOUND, SOURCE_ENTRY_MASK, SOURCE_GROUP_FLAG, + SUCCESS, }, }; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; @@ -34,10 +35,14 @@ where fn load_data(&self, machine: &mut Mac) -> Result<(), VMError> { let index = machine.registers()[A3].to_u64(); - let source = machine.registers()[A4].to_u64(); + let mut source = machine.registers()[A4].to_u64(); // To keep compatible with the old behavior. When Source is wrong, a // Vm internal error should be returned. - let _ = Source::parse_from_u64(source)?; + if let Source::Group(_) = Source::parse_from_u64(source)? { + source = source & SOURCE_ENTRY_MASK | SOURCE_GROUP_FLAG; + } else { + source = source & SOURCE_ENTRY_MASK; + } let data_piece_id = match DataPieceId::try_from((source, index, 0)) { Ok(id) => id, Err(_) => { @@ -100,10 +105,14 @@ where let content_offset = machine.registers()[A2].to_u64(); let content_size = machine.registers()[A3].to_u64(); let index = machine.registers()[A4].to_u64(); - let source = machine.registers()[A5].to_u64(); + let mut source = machine.registers()[A5].to_u64(); // To keep compatible with the old behavior. When Source is wrong, a // Vm internal error should be returned. - let _ = Source::parse_from_u64(source)?; + if let Source::Group(_) = Source::parse_from_u64(source)? { + source = source & SOURCE_ENTRY_MASK | SOURCE_GROUP_FLAG; + } else { + source = source & SOURCE_ENTRY_MASK; + } let data_piece_id = match DataPieceId::try_from((source, index, 0)) { Ok(id) => id, Err(_) => { diff --git a/script/src/syscalls/spawn.rs b/script/src/syscalls/spawn.rs index e2879c5cf2..2d92e6fd68 100644 --- a/script/src/syscalls/spawn.rs +++ b/script/src/syscalls/spawn.rs @@ -1,7 +1,7 @@ use crate::syscalls::utils::load_c_string; use crate::syscalls::{ - Source, INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SPAWN, SPAWN_EXTRA_CYCLES_BASE, - SPAWN_YIELD_CYCLES_BASE, + Source, INDEX_OUT_OF_BOUND, SLICE_OUT_OF_BOUND, SOURCE_ENTRY_MASK, SOURCE_GROUP_FLAG, SPAWN, + SPAWN_EXTRA_CYCLES_BASE, SPAWN_YIELD_CYCLES_BASE, }; use crate::types::{DataPieceId, Fd, Message, SpawnArgs, TxData, VmId}; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; @@ -55,11 +55,15 @@ where return Ok(false); } let index = machine.registers()[A0].to_u64(); - let source = machine.registers()[A1].to_u64(); + let mut source = machine.registers()[A1].to_u64(); let place = machine.registers()[A2].to_u64(); // To keep compatible with the old behavior. When Source is wrong, a // Vm internal error should be returned. - let _ = Source::parse_from_u64(source)?; + if let Source::Group(_) = Source::parse_from_u64(source)? { + source = source & SOURCE_ENTRY_MASK | SOURCE_GROUP_FLAG; + } else { + source = source & SOURCE_ENTRY_MASK; + } let data_piece_id = match DataPieceId::try_from((source, index, place)) { Ok(id) => id, Err(_) => { 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 468891745b..4cb4fd8583 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1435,3 +1435,32 @@ fn check_fuzz_crash_2() { ScriptVersion::V2 => assert_eq!(result.unwrap(), 58686), } } + +#[test] +fn check_fuzz_crash_3() { + let script_version = SCRIPT_VERSION; + let (exec_caller_cell, exec_caller_data_hash) = load_cell_from_path("testdata/crash-4717eb0e"); + let exec_caller_script = Script::new_builder() + .hash_type(script_version.data_hash_type().into()) + .code_hash(exec_caller_data_hash) + .build(); + let output = CellOutputBuilder::default() + .capacity(capacity_bytes!(100).pack()) + .lock(exec_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![exec_caller_cell], + resolved_inputs: vec![dummy_cell], + resolved_dep_groups: vec![], + }; + let verifier = TransactionScriptsVerifierWithEnv::new(); + let result = verifier.verify(script_version, &rtx, 70000000); + assert!(result + .unwrap_err() + .to_string() + .contains("MemWriteOnExecutablePage")); +} diff --git a/script/testdata/crash-4717eb0e b/script/testdata/crash-4717eb0e new file mode 100644 index 0000000000000000000000000000000000000000..f5bf52fb4fa4e98207dbdb383fca8c4921efbb52 GIT binary patch literal 32504 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 Qqeqs13Ay$DA6ftZ18?mc&j0`b literal 0 HcmV?d00001

W2Z7q zBNPfXy00RwDvBb?DAIyPSU}JS0|**X0D?wnK+p&U2pU0vpzz+avsq%ukM4DeA(mQf z>3d!EQ8A=LQjHGpxVz}jkb5w1{e_B9yk+Ro$I*9M_Dw5pd6Kn{IueTQodvzIqQ`rZ zZ%!VVcsJ1y6EZUB;>_C*y5JNYRshSlwX;CT4N&ob?ytKKDuR5}r`v7t^)uO+_2KvdKOG(&(8ALkAJBt6 z6D8}qxK2!a?fP>?3FV~tM!C^*htI9Jly8~O<#WB^Umib;xc*^QBTsh zHBfM6=(4%3MyQ)$)(_rjn$u`+-pN+URF|K*!Hr< zP^vH0mmn!*-m^c|Q&|Va9nDVR1fn=FnQYc^;+68|(qknD?YQA_BjDz=-G2Ot0UHgx z1Pu}h5;y@6(mR`+E{BV6Kzf($lnd!?O$QG-c)Jbhn~yfT4)P8M--`5yz#+Dkckz%X zL4(tY^uqggyX`0>FFu)`cexzR4aZ$JeDHW;!T-JZKN;USuuLp^7$x}xPTc7N2izr+ z10K#NG;&WN_ZRsZlge4{uY<^%wES*){kmnMd@V}luaYf-I`Fg7@_Xd`9yy=z$N8Ka`J01Cj5W+axd5 zF0YTbDb9e+wp8T&%}aY1xwuQNg7$z7wT~^MrS7|Xmjy^3>BfHQ*-0m0n_S -#include - -#include "ckb_syscalls.h" - -int main() { - int8_t spawn_exit_code = 255; - spawn_args_t spgs = { - .memory_limit = 8, - .exit_code = &spawn_exit_code, - .content = NULL, - .content_length = NULL, - }; - uint64_t success = ckb_spawn(0, 3, 0, 0, NULL, &spgs); - if (success != 0) { - return success; - } - return spawn_exit_code; -} diff --git a/script/testdata/spawn_times b/script/testdata/spawn_times deleted file mode 100755 index c7dcd39e58e0206107a29fda1098222a07eacb1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15288 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 diff --git a/script/testdata/spawn_times.md b/script/testdata/spawn_times.md deleted file mode 100644 index 351817947d..0000000000 --- a/script/testdata/spawn_times.md +++ /dev/null @@ -1,81 +0,0 @@ -This binary comes from: . Since I couldn't build a binary in C that would cause the same bug, I just added the binary to the project. - -```rs -#![no_std] -#![cfg_attr(not(test), no_main)] - -#[cfg(test)] -extern crate alloc; - -#[cfg(not(test))] -use ckb_std::default_alloc; -#[cfg(not(test))] -ckb_std::entry!(program_entry); -#[cfg(not(test))] -default_alloc!(); - -use core::result::Result; - -use alloc::{vec}; -use core::ffi::{CStr}; - -use ckb_std::{debug, syscalls}; -use ckb_std::ckb_constants::Source; -use ckb_std::env::argv; -use ckb_std::syscalls::{current_cycles, get_memory_limit, set_content, spawn}; - - -/// -/// test case : -/// invoke int ckb_spawn( uint64_t memory_limit, -/// size_t index, -/// size_t source, -/// size_t bounds, -/// int argc, char* argv[], -/// int8_t* exit_code, -/// uint8_t* content, -/// uint64_t* content_length); -/// -/// for { -/// spawn(xxx) -/// } -/// case1 : for { -/// spawn(xxx) -/// } -/// -/// result: -/// return ERROR : ExceededMaximumCycles -/// -pub fn program_entry() -> i8 { - // let argvs = argv(); - // debug!("argvs length:{:?}:{:?}",argvs.len(),argvs); - - if get_memory_limit() != 8 { - return 0; - } - let mut exit_code: i8 = 0; - let mut content: [u8; 10] = [1; 10]; - - let content_length: u64 = content.len() as u64; - let mut spawn_args = syscalls::SpawnArgs { - memory_limit: 8, - exit_code: &mut exit_code as *mut i8, - content: content.as_mut_ptr(), - content_length: &content_length as *const u64 as *mut u64, - }; - // let cstr1 = CStr::from_bytes_with_nul(b"arg0\0").unwrap(); - //argv is empty - let cstrs = vec![]; - - spawn_args.memory_limit = 1; - for i in 0..10000 { - debug!("current idx:{:?}",i); - let result = spawn(0, Source::CellDep, 0, cstrs.as_slice(), &spawn_args); - assert_eq!(exit_code, 0); - // debug!("result:{:?}",result); - let cycles = current_cycles(); - debug!("cycle:{:?}",cycles); - } - return 0; -} -``` diff --git a/script/testdata/sub1.lib b/script/testdata/sub1.lib index 9afeae07767d0ebb506ad0f65c5a46e66fa7cc07..b1a89a227be89c21c924ac5fc09c1006c955b6ca 100755 GIT binary patch delta 523 zcmaE$x>0TyuLP2!lV1W! s*~yy1_Kd2NGl8V`$K;zwalDX5`NlRbsy0ncO?YXATM diff --git a/script/testdata/vm_version b/script/testdata/vm_version index bf39e3d56a5b17273b9be95fa1c3da42e4a7b8ac..e105dad85c11b987e1fdb77be46bed27b36b28c0 100755 GIT binary patch literal 32392 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 delta 125 zcmeD9%XmO$f`)hlHvXEv=`i^ukaV5QS#8hgH`%k=esTc|3nTO7jm*NFvQRq` NCMU9pPj0B@006tVAO`>d diff --git a/script/testdata/vm_version_2 b/script/testdata/vm_version_2 index 13ea61a6ca09c7d935e6940fc99732c497d0272c..e3871ba942ad7a63fd309e0d8a945db72a09160c 100755 GIT binary patch literal 32400 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 literal 11696 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 R&uHWO@ry1T@`=gE{~rqT$58+P diff --git a/script/testdata/vm_version_with_snapshot b/script/testdata/vm_version_with_snapshot index 9e16b52a45cbc9e2dc0a71140f41591ffb0e8d13..7685e8d3ced47133d3bc536861857f653f3daf65 100755 GIT binary patch literal 32456 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νf#Q*)uHXf zhzG|eOw_58W2Mzh3nWXqNwAK4bFy zIk!eEZB2Ns&f05PVwV1uEul4HOL!-fWJ&ecs;INve(|jl%S6rJ{-Xp-7MUa^XBk)H zR`FZxkX&!st>p36&iaTY?QT%_R%DpuIZkrDRZc`K*=CZUe9o;A%UP3NLPVAri4R!i z4-OamU`FgbYjEe=a=5{OsUp&3gw|N$E!X-Z2s2egRvMwz<}L@(ua-I0Bu2JGZwTg2 zxHV!EtZ8((ZB@UKMbe-lT|-;NFtO0w?PBV!!$ftmh-@_`K5DI=7rD=nU&a`kB!&Dm~m)4y%atdCgoIh%A&#FBR3uRUT@wxORJ>HoA^m>D+h zZI>2#$B_6X1!yC1vo2yu{ew_&??La@h-GY~02A$d*~QuP>DJErh$U^%z__iIJkd&? z8?oeS8y33oT0df$EcJ8YBvyTmRo@V?V?y@@gX~qbxQ*)t@_3;+(8RYu;NgTv1oJ(lZvVTy8lwHK!bx z$a3u8%4ON)uin{pD7@G>hFyHZc5?NZjBx(c5@EX{StkzLc$q!TR?${hgzc2ArdeTI zCwmWHVsdO}qJr=GL99?bfN%as;%@`&|JBRRllUvJ{rrK5ypI%tcwofzkgz{mn5`lO zqFem^t-OyE5m7o~x_&<9iK8}%!;bKg!bSmeGvz4%0ZghWUal-TDT;?Ds`Qdk(#MRF zZlj>N*;16{CKyhN@?q)htw8+Z5BV94^Ny6xcqbzG!{V@uN0Fyp1ipujJC|JAS#2Kb zl;h_de7&skvZKit9PrN`hWW$QNT(h9|LDM~&p+WxJ2ht98H48Mc6{+0c=!(?*0M?# zeEDLe_I`1c^ly%m{*_VEpBW{cOZZ6T{&E&pd zeJ0p=_s5j{@b%$ekY1LxZrBy!F=NN#V|#A#O_Oe)`!?Rs7g1QQU4ZXrGw~URqb{b~ z_4h=bEZ#Em_F-z{{yhCDh2O5sYu8wlp1+PY82c8?+7)4@Nw@3psixdnCfz>v9inrsWWpeues z3ehVBqX6Pe-Kk8ytD*S~|OuB!dtxX9gdu&uP+27Nbj<*a9A}HC_ z+nMT5C3$EOA3-8JpoQ3J-xkr<*Mit|a-gegi|A?nP%6=nf5e5rS0*_(@JAi9`8T^- z8vUZ|&KZxM)nM+S=jyIpaEFL!jN=W8LD)VA$BgWlWs0qdCc;vgpC~e3ySInlG zfNpP(+WAg(@v(S(?Xsn3EsZxduUK_DDs1~WEAl&16cyX)L{{J0akLRe#%SG8+C-!^ ztzBz6CLV81tFsh@X>}AsbhRK}tpfoN&8<~Rhj?iUKl_&6($(M6iaVm(>b}uZh>iA( z#?(eVo}w|+iJ~#n>7r4YYfS4KY9bopN?nYuH>!PqV@rR3Uq>rqt;kBIS_j%O6fNED z8CFH+ZB}b*U+MxY*oio=rIlM*29>lVWf+uqd{2TW6|S(p?sm=FIrJyo$3quWnJc6E z*mdLq!@r7ooBhdSMFTRaZ%**t^WXk|d0=0iq5`*}$l`Sw=j={sDikGHW#=6>?^*BG0&{&w9j zHTsKk)rXaTHu72jIeBtcKOYHFmLGfP^A2VAs>H0zWK%xJC;MadY#J5w)0nr$wm;8d zO0A-~UyS=m`sW+yeEGawg?!m7M$vz5sn$!-xw1a_`nMo2KaJw2t`fl}X>i-3ipT@j*y0ygZ`sS|rvgGqzM9JRWqgBo~3lra;U>j}! q;V%}{hdVescTAGHMK93YnmptA<#Pu$lKwirY=Y0v^vzxK_5T|jvpDYn delta 125 zcmX@{m+^zl1P$>G+zepA2qYaCEEt%8BsT-sMtgql$(a@LlOHiVGjdPvth8qooO}{U zN>ApjvS(DE> Date: Tue, 5 Mar 2024 14:19:45 +0800 Subject: [PATCH 006/135] Rename join => wait --- script/src/v2_scheduler.rs | 12 ++++++------ script/src/v2_syscalls.rs | 12 ++++++------ script/src/v2_types.rs | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index af48f6476a..631c83e385 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -4,8 +4,8 @@ use crate::v2_types::PipeIoArgs; use crate::verify::TransactionScriptsSyscallsGenerator; use crate::{ v2_syscalls::{ - transferred_byte_cycles, MachineContext, INVALID_PIPE, JOIN_FAILURE, OTHER_END_CLOSED, - SUCCESS, + transferred_byte_cycles, MachineContext, INVALID_PIPE, OTHER_END_CLOSED, SUCCESS, + WAIT_FAILURE, }, v2_types::{ DataPieceId, FullSuspendedState, Message, PipeId, RunMode, TxData, VmId, VmState, @@ -256,7 +256,7 @@ impl = Vec::new(); self.states.iter().for_each(|(vm_id, state)| { - if let VmState::Join { + if let VmState::Wait { target_vm_id, exit_code_addr, } = state @@ -332,7 +332,7 @@ impl { + Message::Wait(vm_id, args) => { if let Some(exit_code) = self.terminated_vms.get(&args.target_id).copied() { self.ensure_vms_instantiated(&[vm_id])?; { @@ -350,14 +350,14 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { + fn wait(&mut self, machine: &mut Mac) -> Result<(), Error> { let target_id = machine.registers()[A0].to_u64(); let exit_code_addr = machine.registers()[A1].to_u64(); // TODO: charge cycles - self.message_box.lock().expect("lock").push(Message::Join( + self.message_box.lock().expect("lock").push(Message::Wait( self.id, - JoinArgs { + WaitArgs { target_id, exit_code_addr, }, @@ -499,7 +499,7 @@ impl< // The syscall numbers here are picked intentionally to be different // than currently assigned syscall numbers for spawn calls 2601 => self.spawn(machine), - 2602 => self.join(machine), + 2602 => self.wait(machine), 2603 => self.instance_id(machine), 2604 => self.pipe(machine), 2605 => self.pipe_write(machine), @@ -528,7 +528,7 @@ pub(crate) fn transferred_byte_cycles(bytes: u64) -> u64 { pub(crate) const SUCCESS: u8 = 0; pub(crate) const INDEX_OUT_OF_BOUND: u8 = 1; pub(crate) const SLICE_OUT_OF_BOUND: u8 = 3; -pub(crate) const JOIN_FAILURE: u8 = 5; +pub(crate) const WAIT_FAILURE: u8 = 5; pub(crate) const INVALID_PIPE: u8 = 6; pub(crate) const OTHER_END_CLOSED: u8 = 7; diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs index 831835dc06..1e48eb2319 100644 --- a/script/src/v2_types.rs +++ b/script/src/v2_types.rs @@ -43,7 +43,7 @@ impl PipeId { pub enum VmState { Runnable, Terminated, - Join { + Wait { target_vm_id: VmId, exit_code_addr: u64, }, @@ -73,7 +73,7 @@ pub struct SpawnArgs { } #[derive(Clone, Debug)] -pub struct JoinArgs { +pub struct WaitArgs { pub target_id: VmId, pub exit_code_addr: u64, } @@ -95,7 +95,7 @@ pub struct PipeIoArgs { #[derive(Clone, Debug)] pub enum Message { Spawn(VmId, SpawnArgs), - Join(VmId, JoinArgs), + Wait(VmId, WaitArgs), Pipe(VmId, PipeArgs), PipeRead(VmId, PipeIoArgs), PipeWrite(VmId, PipeIoArgs), From 4df9a03f40c699ab9a9ad12d8ae9575f5e7ee9d6 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 5 Mar 2024 14:24:06 +0800 Subject: [PATCH 007/135] Adjust pipe_read/write args positions --- script/src/v2_syscalls.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index 25371c7bca..a8e2d14c2f 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -378,13 +378,13 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { - let buffer_addr = machine.registers()[A0].to_u64(); - let length_addr = machine.registers()[A1].to_u64(); + let pipe = PipeId(machine.registers()[A0].to_u64()); + let buffer_addr = machine.registers()[A1].to_u64(); + let length_addr = machine.registers()[A2].to_u64(); let length = machine .memory_mut() .load64(&Mac::REG::from_u64(length_addr))? .to_u64(); - let pipe = PipeId(machine.registers()[A2].to_u64()); // We can only do basic checks here, when the message is actually processed, // more complete checks will be performed. @@ -414,13 +414,13 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { - let buffer_addr = machine.registers()[A0].to_u64(); - let length_addr = machine.registers()[A1].to_u64(); + let pipe = PipeId(machine.registers()[A0].to_u64()); + let buffer_addr = machine.registers()[A1].to_u64(); + let length_addr = machine.registers()[A2].to_u64(); let length = machine .memory_mut() .load64(&Mac::REG::from_u64(length_addr))? .to_u64(); - let pipe = PipeId(machine.registers()[A2].to_u64()); // We can only do basic checks here, when the message is actually processed, // more complete checks will be performed. @@ -447,6 +447,7 @@ impl( &mut self, machine: &mut Mac, From 8bc41755d809c306957c417967a49de299f41b00 Mon Sep 17 00:00:00 2001 From: mohanson Date: Tue, 5 Mar 2024 14:51:24 +0800 Subject: [PATCH 008/135] Move argc/argc to spawn_args_t --- script/src/v2_syscalls.rs | 42 +++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index a8e2d14c2f..cff7a0722d 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -11,7 +11,7 @@ use ckb_vm::{ bytes::Bytes, machine::SupportMachine, memory::{Memory, FLAG_EXECUTABLE, FLAG_FREEZED}, - registers::{A0, A1, A2, A3, A4, A5, A6, A7}, + registers::{A0, A1, A2, A3, A4, A5, A7}, snapshot2::{DataSource, Snapshot2Context}, syscalls::Syscalls, Error, Register, @@ -240,30 +240,34 @@ impl> 32; let length = bounds as u32 as u64; - let argv = { - let argc = machine.registers()[A4].to_u64(); - let mut argv_addr = machine.registers()[A5].to_u64(); - let mut argv_vec = Vec::with_capacity(argc as usize); - for _ in 0..argc { - let target_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(argv_addr))? - .to_u64(); - let cstr = load_c_string(machine, target_addr)?; - argv_vec.push(cstr); - argv_addr += 8; - } - argv_vec - }; + let spgs_addr = machine.registers()[A4].to_u64(); + let argc_addr = spgs_addr; + let argc = machine + .memory_mut() + .load64(&Mac::REG::from_u64(argc_addr))? + .to_u64(); + let mut argv_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(spgs_addr.wrapping_add(8)))? + .to_u64(); + let mut argv = Vec::new(); + for _ in 0..argc { + let target_addr = machine + .memory_mut() + .load64(&Mac::REG::from_u64(argv_addr))? + .to_u64(); + let cstr = load_c_string(machine, target_addr)?; + argv.push(cstr); + argv_addr = argv_addr.wrapping_add(8); + } let (instance_id_addr, pipes) = { - let spgs_addr = machine.registers()[A6].to_u64(); - let instance_id_addr_addr = spgs_addr; + let instance_id_addr_addr = spgs_addr.wrapping_add(16); let instance_id_addr = machine .memory_mut() .load64(&Mac::REG::from_u64(instance_id_addr_addr))? .to_u64(); - let pipes_addr_addr = spgs_addr.wrapping_add(8); + let pipes_addr_addr = spgs_addr.wrapping_add(24); let mut pipes_addr = machine .memory_mut() .load64(&Mac::REG::from_u64(pipes_addr_addr))? From 05b532a4a48cc92e8e7b0e3cf4892dd171d89907 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Tue, 5 Mar 2024 16:41:59 +0800 Subject: [PATCH 009/135] Implement close (#4) --- script/src/v2_scheduler.rs | 10 ++++++++++ script/src/v2_syscalls.rs | 8 ++++++-- script/src/v2_types.rs | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index 631c83e385..5f768ff99d 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -492,6 +492,16 @@ impl { + self.ensure_vms_instantiated(&[vm_id])?; + let (_, machine) = self.instantiated.get_mut(&vm_id).unwrap(); + if self.pipes.get(&fd) != Some(&vm_id) { + machine.machine.set_register(A0, INVALID_PIPE as u64); + } else { + self.pipes.remove(&fd); + machine.machine.set_register(A0, SUCCESS as u64); + } + } } } Ok(()) diff --git a/script/src/v2_syscalls.rs b/script/src/v2_syscalls.rs index cff7a0722d..6b70e70b0c 100644 --- a/script/src/v2_syscalls.rs +++ b/script/src/v2_syscalls.rs @@ -474,8 +474,12 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { - // TODO - unimplemented!() + let pipe = PipeId(machine.registers()[A0].to_u64()); + self.message_box + .lock() + .expect("lock") + .push(Message::Close(self.id, pipe)); + Err(Error::External("YIELD".to_string())) } } diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs index 1e48eb2319..1f7967371d 100644 --- a/script/src/v2_types.rs +++ b/script/src/v2_types.rs @@ -100,6 +100,7 @@ pub enum Message { PipeRead(VmId, PipeIoArgs), PipeWrite(VmId, PipeIoArgs), InheritedFileDescriptor(VmId, PipeIoArgs), + Close(VmId, PipeId), } #[derive(Clone, Debug, PartialEq, Eq, Hash)] From 962620c90e42a088ed48b1124acddc9b707daca0 Mon Sep 17 00:00:00 2001 From: Mohanson Date: Tue, 5 Mar 2024 19:46:15 +0800 Subject: [PATCH 010/135] Rename instance_id => process_id --- script/src/v2_scheduler.rs | 2 +- script/src/v2_syscalls.rs | 18 ++++++++---------- script/src/v2_types.rs | 4 +--- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index 5f768ff99d..aa1bc0d79c 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -328,7 +328,7 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { + fn process_id(&mut self, machine: &mut Mac) -> Result<(), Error> { // TODO: charge cycles machine.set_register(A0, Mac::REG::from_u64(self.id)); Ok(()) @@ -509,7 +507,7 @@ impl< // than currently assigned syscall numbers for spawn calls 2601 => self.spawn(machine), 2602 => self.wait(machine), - 2603 => self.instance_id(machine), + 2603 => self.process_id(machine), 2604 => self.pipe(machine), 2605 => self.pipe_write(machine), 2606 => self.pipe_read(machine), diff --git a/script/src/v2_types.rs b/script/src/v2_types.rs index 1f7967371d..7beb62391f 100644 --- a/script/src/v2_types.rs +++ b/script/src/v2_types.rs @@ -1,5 +1,3 @@ -// Core data structures here - use crate::ScriptGroup; use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::core::{cell::ResolvedTransaction, Cycle}; @@ -69,7 +67,7 @@ pub struct SpawnArgs { pub length: u64, pub argv: Vec, pub pipes: Vec, - pub instance_id_addr: u64, + pub process_id_addr: u64, } #[derive(Clone, Debug)] From b577e4ce9c761b10aca743f7cfa6cb7bd4d39546 Mon Sep 17 00:00:00 2001 From: xjd Date: Wed, 6 Mar 2024 10:00:54 +0800 Subject: [PATCH 011/135] Add spawn cases * format code * Use libc from ckb-c-stdlib Add test case: check_spawn_strcat --- script/fuzz/programs/exec_caller.c | 1 + script/src/v2_scheduler.rs | 2 +- script/src/v2_syscalls.rs | 1 - .../tests/ckb_latest/features_since_v2021.rs | 3 +- .../tests/ckb_latest/features_since_v2023.rs | 57 +++--- script/src/verify/tests/ckb_latest/mod.rs | 5 +- script/src/verify/tests/mod.rs | 5 +- script/testdata/.clang-format | 5 + script/testdata/Makefile | 23 ++- script/testdata/add1.c | 4 +- script/testdata/add1.lib | Bin 5416 -> 5728 bytes script/testdata/cpop_lock | Bin 33576 -> 2376 bytes script/testdata/cpop_lock.c | 28 +-- script/testdata/current_cycles | Bin 32448 -> 1240 bytes script/testdata/current_cycles.c | 6 +- script/testdata/current_cycles_with_snapshot | Bin 32496 -> 1280 bytes .../testdata/current_cycles_with_snapshot.c | 13 +- script/testdata/debugger | Bin 32552 -> 4400 bytes script/testdata/debugger.c | 8 +- script/testdata/div2.c | 4 +- script/testdata/div2.lib | Bin 5416 -> 5728 bytes script/testdata/exec_callee | Bin 32440 -> 1232 bytes script/testdata/exec_callee.c | 28 +-- script/testdata/exec_caller_big_offset_length | Bin 32576 -> 1352 bytes .../testdata/exec_caller_big_offset_length.c | 2 +- script/testdata/exec_caller_from_cell_data | Bin 32552 -> 1352 bytes script/testdata/exec_caller_from_witness | Bin 32552 -> 1352 bytes script/testdata/exec_configurable_callee | Bin 41472 -> 9624 bytes script/testdata/exec_configurable_callee.c | 114 ++++++------ script/testdata/exec_configurable_caller | Bin 39616 -> 7544 bytes script/testdata/exec_configurable_caller.c | 125 ++++++------- script/testdata/infinite_loop | Bin 32384 -> 1168 bytes script/testdata/infinite_loop.c | 4 +- script/testdata/is_even.c | 3 +- script/testdata/is_even.lib | Bin 5416 -> 5728 bytes script/testdata/load_arithmetic | Bin 38752 -> 6608 bytes script/testdata/load_arithmetic.c | 35 ++-- script/testdata/load_code_to_stack_then_reuse | Bin 37464 -> 6040 bytes .../testdata/load_code_to_stack_then_reuse.c | 38 ++-- script/testdata/load_is_even_into_global | Bin 38400 -> 6336 bytes script/testdata/load_is_even_into_global.c | 19 +- script/testdata/load_is_even_with_snapshot | Bin 38456 -> 6272 bytes script/testdata/load_is_even_with_snapshot.c | 22 ++- script/testdata/mul2.c | 4 +- script/testdata/mul2.lib | Bin 5416 -> 5728 bytes script/testdata/spawn_callee_strcat | Bin 0 -> 4792 bytes script/testdata/spawn_callee_strcat.c | 32 ++++ script/testdata/spawn_caller_strcat | Bin 0 -> 5328 bytes script/testdata/spawn_caller_strcat.c | 36 ++++ script/testdata/sub1.c | 4 +- script/testdata/sub1.lib | Bin 5416 -> 5728 bytes script/testdata/utils.h | 64 +++++++ script/testdata/verify.c | 165 +++++++++--------- script/testdata/vm_version | Bin 32392 -> 1192 bytes script/testdata/vm_version.c | 2 +- script/testdata/vm_version_2 | Bin 32400 -> 1192 bytes script/testdata/vm_version_2.c | 2 +- script/testdata/vm_version_with_snapshot | Bin 32456 -> 1256 bytes script/testdata/vm_version_with_snapshot.c | 13 +- 59 files changed, 514 insertions(+), 363 deletions(-) create mode 100644 script/testdata/.clang-format create mode 100755 script/testdata/spawn_callee_strcat create mode 100644 script/testdata/spawn_callee_strcat.c create mode 100755 script/testdata/spawn_caller_strcat create mode 100644 script/testdata/spawn_caller_strcat.c create mode 100644 script/testdata/utils.h diff --git a/script/fuzz/programs/exec_caller.c b/script/fuzz/programs/exec_caller.c index 2f68f1a20f..7403a6b7ee 100644 --- a/script/fuzz/programs/exec_caller.c +++ b/script/fuzz/programs/exec_caller.c @@ -1,3 +1,4 @@ +#include #include static inline long __internal_syscall(long n, long _a0, long _a1, long _a2, diff --git a/script/src/v2_scheduler.rs b/script/src/v2_scheduler.rs index aa1bc0d79c..afc9865076 100644 --- a/script/src/v2_scheduler.rs +++ b/script/src/v2_scheduler.rs @@ -183,7 +183,7 @@ impl(&mut self, machine: &mut Mac) -> Result<(), Error> { let pipe1_addr = machine.registers()[A0].to_u64(); let pipe2_addr = pipe1_addr.wrapping_add(8); - // TODO: charge cycles self.message_box.lock().expect("lock").push(Message::Pipe( self.id, diff --git a/script/src/verify/tests/ckb_latest/features_since_v2021.rs b/script/src/verify/tests/ckb_latest/features_since_v2021.rs index a9b8176bfd..65ddb0dc45 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2021.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2021.rs @@ -102,7 +102,7 @@ fn test_b_extension() { assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1,); if script_version < ScriptVersion::V1 { let vm_error = VmError::InvalidInstruction { - pc: 0x10182, + pc: 65866, instruction: 0x60291913, }; let script_error = ScriptError::VMInternalError(vm_error); @@ -334,6 +334,7 @@ fn check_exec_from_cell_data() { let verifier = TransactionScriptsVerifierWithEnv::new(); let result = verifier.verify_without_limit(script_version, &rtx); + println!("result = {:?}", result); assert_eq!(result.is_ok(), script_version >= ScriptVersion::V1); } 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 ca914dfd84..58450f0333 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -126,38 +126,39 @@ fn check_vm_version() { // assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); // } -// #[test] -// fn check_spawn_strcat() { -// let script_version = SCRIPT_VERSION; +#[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_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 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); + println!("result = {:?}", result); + assert_eq!(result.is_ok(), script_version >= ScriptVersion::V2); +} // #[test] // fn check_spawn_strcat_data_hash() { diff --git a/script/src/verify/tests/ckb_latest/mod.rs b/script/src/verify/tests/ckb_latest/mod.rs index ef6ddd5e75..b42cbd2426 100644 --- a/script/src/verify/tests/ckb_latest/mod.rs +++ b/script/src/verify/tests/ckb_latest/mod.rs @@ -1,5 +1,6 @@ const SCRIPT_VERSION: crate::ScriptVersion = crate::ScriptVersion::latest(); -mod features_since_v2019; -mod features_since_v2021; +// TODO: enable it again +// mod features_since_v2019; +// mod features_since_v2021; mod features_since_v2023; diff --git a/script/src/verify/tests/mod.rs b/script/src/verify/tests/mod.rs index 9729a4f943..7e7a3bd428 100644 --- a/script/src/verify/tests/mod.rs +++ b/script/src/verify/tests/mod.rs @@ -4,7 +4,8 @@ pub(crate) mod utils; -mod ckb_2019; -mod ckb_2021; +// TODO: enable again +// mod ckb_2019; +// mod ckb_2021; #[path = "ckb_latest/mod.rs"] mod ckb_2023; diff --git a/script/testdata/.clang-format b/script/testdata/.clang-format new file mode 100644 index 0000000000..815a156416 --- /dev/null +++ b/script/testdata/.clang-format @@ -0,0 +1,5 @@ +BasedOnStyle: Google +IndentWidth: 4 +TabWidth: 4 +ColumnLimit: 120 +SortIncludes: false diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 59eebd1032..e4db1600f5 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -11,8 +11,11 @@ LIB_OBJCOPY := $(LIB_TARGET)-objcopy COMMON_CFLAGS := -O3 \ -I deps/ckb-c-stdlib \ + -I deps/ckb-c-stdlib/libc \ -I deps/ckb-c-stdlib/molecule \ - -Wall -Werror + -Wall -Werror \ + -fno-builtin -nostdinc -nostartfiles \ + -Wno-stringop-overflow # enable log COMMON_CFLAGS += -DCKB_C_STDLIB_PRINTF -DCKB_C_STDLIB_PRINTF_BUFFER_SIZE=1024 # enable debug @@ -52,13 +55,16 @@ ALL_BINS := jalr_zero \ load_is_even_into_global \ load_is_even_with_snapshot \ load_arithmetic \ - debugger - + debugger \ + spawn_caller_strcat \ + spawn_callee_strcat + + ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib -all-bins: clean-bins $(ALL_BINS) -all-libs: clean-libs $(ALL_LIBS) +all-bins: $(ALL_BINS) +all-libs: $(ALL_LIBS) bins-in-docker: docker run --rm -v `pwd`:/code $(BIN_BUILDER_DOCKER) bash -c "cd /code && make all-bins" @@ -73,6 +79,9 @@ clean-bins: clean-libs: -rm -f $(ALL_LIBS) +fmt: + clang-format -i *.c *.h + clean: clean-bins clean-libs %: %.c @@ -114,3 +123,7 @@ sub1.lib: sub1.c mul2.lib: mul2.c div2.lib: div2.c load_arithmetic: load_arithmetic.c + +spawn_caller_strcat: spawn_caller_strcat.c utils.h +spawn_callee_strcat: spawn_callee_strcat.c utils.h + diff --git a/script/testdata/add1.c b/script/testdata/add1.c index e392d605b7..2e70f13589 100644 --- a/script/testdata/add1.c +++ b/script/testdata/add1.c @@ -1,5 +1,3 @@ #include -__attribute__((visibility("default"))) uint64_t apply (uint64_t num) { - return num + 1; -} +__attribute__((visibility("default"))) uint64_t apply(uint64_t num) { return num + 1; } diff --git a/script/testdata/add1.lib b/script/testdata/add1.lib index e6cd7e9c06e71f1e56d1eb1b6eed0e0603aad13c..69a36247da4dd52f071a9b6611d54496d8ac35ae 100755 GIT binary patch literal 5728 zcmeHLOKVd>6h7%~Y<+xgsD)=d^JQpQ=!l9SJ;*G1oD%D=Z3tXbO6FYwxo*Ae5D@uA0v z{@U7PobRD0FE=U0C#=^ZGH!(4r;HHwh&@km>v7;+TWo*=@h@LT_O?2Af<+lQxVgdL z7e4}i1pEm25%446N5GGO9|1oCegyuT2p})Ht%=x=y;4pV|5V$^RYx_CK~A`>{YNxX zmlTgG_9<3!7tLjeQ-kx{CtYy5qK{y@NJ~=k+^sQ87sMcHe`5z7*8H3s}YVjO#3sRdfp;uA-L8-nUkr;wo7y>sdDQ&@GTv zNTwYtpLWS|lMncx`<=|%GFhn{x0Z96Ofu{8vi?eucMrKU@SWpa0|(R#?gf0$xQEVi z|Ibn>2R+U|u)l>~X_9+L?jY##odBPyq4*OU_{aTml{uLk^rKn<;+|uZa?xuLO}frC z8GB3_e0M1UYwa^WkI}kL-M-bRCQOs=^m(lhz zz(vMePw|p-+&bg&^C?lO^yalP28;qm0i%FXz$jo8FbWt2i~>dhqkvI>6+qqeSPQxD zzh)y5W~?@9-H&RcrhKRNX;ty0;+o=x9Iqy!K81ZM=MVmWA?j|wTD@a$_|4sGcBSG} zoSVm((Bdi%@*-#^B?u6#Zpm-*#&daqY;x)j!)G~N4+DuoZ)t*TesZF^zR zXl}c{7w))QffrKf2dynP2wU~~BX0++*7?q4I*2+?$(ck43HH(3AHHz-krd>m4~e@kIwC_6-o{L+(tZ;auQ6USjUY zY&JqX_80I<93^`rX^2;ou5w4tBI2crEvd*agcvm2dFX1{D>!8AE*QTm7T92e1jiIeEz$z zs_}X~i17LPB}STHeoeyL8sAq(`F@_|ALfPr@?D(g&V97Easavc3C#a7F9>m47XLxx K+i+CO$NvWY+H=GJ diff --git a/script/testdata/cpop_lock b/script/testdata/cpop_lock index ca9ac0deb75ee2764fd0ee6ae2ff54ac67df51ff..983cacff7846e7d35624c01ddd3ba78dc5a8e55f 100755 GIT binary patch delta 691 zcmZ3{#&kkxf`s}6Mn(n@Z~&7G3?1wc21wL_!GeJiNU}4qO|)0!`oIE_`oJ=AQ3+pz zV(3#&w?(ZQ67LxlcqXebE|Hq9$iOhUk#QT7s}2LB+xrju-%jSZz*-E{wK@w2KKvOG#7#%P(Firl*F3QZzz&ts>RJUG$;p6`gGN|h0ftmz>dOwJuiaP+s zg@EEP|42a%*TcK`xK<)9tp&=TFcoGirbf7rMpUo5wvz>Gr6zx3cb@#B zRzL_AB^5xIfItPyWUe|jNdpKEPQsFb(By?2;*%fLb0}&7<(L^53gAkh3?^0xLmR9z qp-Dm104mY|^)!gfI(cf7Hs=O5h}xMDQ=1exJ)tSl1}vh`zySbzPj9LK literal 33576 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 #include "blockchain.h" +#include "ckb_syscalls.h" #ifdef DEBUG #include @@ -17,25 +17,22 @@ #define SCRIPT_SIZE 32768 -static uint64_t cpop (uint64_t rs1) { +static uint64_t cpop(uint64_t rs1) { uint64_t rd; - asm volatile ( + asm volatile( "mv s2, %1\n" // "cpop s2, s2\n" ".byte 0x13,0x19,0x29,0x60\n" "mv %0, s2\n" : "=r"(rd) : "r"(rs1) - : "s2" - ); + : "s2"); return rd; } -uint64_t read_u64_le (const uint8_t *src) { - return *(const uint64_t *)src; -} +uint64_t read_u64_le(const uint8_t *src) { return *(const uint64_t *)src; } -int main (int argc, char *argv[]) { +int main(int argc, char *argv[]) { int ret; uint64_t len = SCRIPT_SIZE; uint8_t script[SCRIPT_SIZE]; @@ -67,17 +64,20 @@ int main (int argc, char *argv[]) { } volatile uint64_t num0 = read_u64_le(bytes_seg.ptr); - volatile uint64_t num1 = read_u64_le(bytes_seg.ptr+8); + volatile uint64_t num1 = read_u64_le(bytes_seg.ptr + 8); - sprintf(message, "num0 = %ld", num0); ckb_debug(message); - sprintf(message, "num1 = %ld", num1); ckb_debug(message); + sprintf(message, "num0 = %ld", num0); + ckb_debug(message); + sprintf(message, "num1 = %ld", num1); + ckb_debug(message); if (num0 == 0 && num1 == 0) { return CKB_SUCCESS; } volatile uint64_t num1_actual = cpop(num0); - sprintf(message, "cpop(%lx) = %ld (actual) == %ld (expected)", num0, num1_actual, num1); ckb_debug(message); + sprintf(message, "cpop(%lx) = %ld (actual) == %ld (expected)", num0, num1_actual, num1); + ckb_debug(message); if (num1 != num1_actual) { return -5; diff --git a/script/testdata/current_cycles b/script/testdata/current_cycles index 8880779257b57bdfa9b0c69d55c01dc042d4efa8..fff424aba8b9ea40ae4473c1df89fda19c1da04c 100755 GIT binary patch literal 1240 zcmbtTO>fgc5FOif8csDm1$qfm4}8gLph5^Ck+gLzq$(;3JulAIDz4%rvbR-ws9N{J z56FRQ`74|_A$|a-aN$M~oRARA+Ox%76fTV9eKT*~jCa@LV{fx<8U`pc;Ty>4UA_V| zDN(ZuN9LOF5VK8~hf1!pN%Kb`y`txoatgsAm6v%&J8K($=1;0;$0^baaK2#krK%0r z&UnQ#jTxG^ucYSa{-^izKaaLgPYmz$6~Sm1!g(C z@GYQAykLr3nuD*uN>uJH;_4tjtrhpE^2<4Iz|^_Sd&n>1UetHHP6ex^|E%eo#Or-F zk(YhcxwbHt_6#2fd0qcv2ER+Z{$AkwNfHhO?Id2Ew8H^yyBU9%7$vl3Kl0Do;?KphQ8h3SL3+I=%m|=?vW+g46T6pXd9| z-fLB@TD7WbRqel4?LK|U(leF?QVRD8#4iQ8a+|iuW-Quj2<9yk3q^oyjTozCBUUCW zLCWadt4yl9i}I{g6r@YvTV>_#eIRD!?zeYeZt2icxol{eTt2jXcYNO^8HkM$uZ@YM z#>XR~eqSo80y&Dz=dPg4#mBz%wb<`3K4-^vxpc?&-O#`5$;Iia$X!Q2vwz3-JxxOF z9vZr@>aw9XsxFtmNqlH%>8s+!vRX8QR#`i-ge3GtB&qU}EzXxX}dYjDvI-rKTq z|Hf9-mD-gMI~QEqn7V9%y!g1*>gONdyQHrD_X|>cW~eE5PL+e-+Ie?4=hHPu%ANmu zsd(esp&7eg4ffo!WaqP(1(m&byb)**Wjha!L)oeAZ>b zp6@^2jO&*kzwa{m#xl8d+C8%3K;iG}O;Z*gDBpQcY))j^2{k_wAAjX3G3B1xIa3xs+qi34s`fdt^CQdWJoBL`_kC;j zKSygtB32f=@ySo^x%wsTbMdDm^xM>V5kZfcd1>_E3E}oduZn#_JR$eVed-hPjUC$| zf@x&t#Ws6il`~hF{aT&L-&b$$tH+r;^Zq-0Tx-gX{p!EYt?c>HPrnxt#s3`|_K!CF zqX+)c1OMoOfAqlr*B*Gp;!Ss7e(I^mHy*Kk)j98IoHM6+PV;QBcqR<&@5-bu6tWRy zSRU!WaQ@t`V>ZoB_VCimO9~fcilguiNQk(;Ivjnn=7wL4{1IOMX8U}fI9ybxOu#h| z=Ovu}LNTN7_)3@mkkxm7p`hiB{JbhBUm2Juu7&BtN}Y(5K&_eNtvvTKBYmbKF(RZ^t}Ss6aUP|yMG#BymD^`yL@8GduI4pJHgG3^YDA$& zu%~13*k0Uf!$?=}0Jz96bz@CSF=8@4m$x9Y zTHj)w5KRcss=15w9k-pE~`Ly_1*?moq0y_c#aErO5Ii1sMk7Y{zjsyY%6Ag8>9Hgry8CzMMOQd#6NT==zG!_R{rU)&BA z`kF<-t$LJg%9_c(ScSe752XsH867ya=DrMUDujQR=B8Hhy;S7@03O+!zsJ zVemMF!>=@a2F#)$%D(=3=?h?11piLv>BO60R>zZrZQ>hR^IFiG#5c8t8$kDqXLTi; zg5R;m=PG`W0t3N)Ed6{%DY|!aJlWkQzN<@b2~KD2FX$py2IrA^v1kY-uL~p!hA&kv zL&;l$kJ7G}OC~{JU+_VW#gEH4b?yuvX3kHvL)48urd-~pnTcfT0tkh4O*0b>VE&T9D>ayAD={m5A>_af(_Ku^^RPpff-BWk?!{Bl{T(hRbuch3rxRhRl>gY&0a!j%V^8`g$gzl9U5#d4bdflYw z=;?$>%g%0aJl68}!K84i9QP{PRCNWcsyjlSk9^4)JX2PX7V-k*9x3%0$K^)k93}M_ zmy3`M4ym!K9g<~B&?PD=4Q_x%@nGt_o_ovK}S>7p@-+#;`M1%Nt?B z)xlAZL2Rvj9%9!7<2InG3*>Fc`A|^9Ij~874>{KwW{Z3VN!J->ySy1W*9YYXpx{cm z6P4Z&ls^mRI>`yL+thQ997Lrznlksx&q2XWhIvS~Bj;wrd`50Y&K|>jL0%5#7Q=i+ zE{8d{n#u4@5utm~X5Az8d>%8zr;}N^PL3J=hmNlm6F124!$GVV{w9A2Q*RH(lNR!6 zF#ChL@nBvP5w3+KwU!1EVeit>Ek6lbb_R+wv6{2|e*_$x>Ic!>I|9~b>RsfC|v_4s;Jq@hxshe|mZsq8+Kl)y-J>g#E=#zU1ZO|GcsrOfqHW*25GpdE6lUR&Y2j4OnNedc`q%ANQ ziKM|u>aj!$jKN6iam_f4^bjgB7)d>$UCdx4^;8iXZ!nVja>J!q*9=BdUun1>jKN6i z>!n`@V=$6>I`Ik^hmok+VI*4UFcR%D7)d=>@iP=K7)d>^0h7Z>ENw87dO_P|Fp_$) z=zS<}Fp_$yay~l2U?lZ&$ry~W!AR=IWt=(&BdMQghX6*}g*283^@R-#GcX{eNkT0` zP6cxs3`SDGNX&K^NlQ75v<9o7$4F#6Mk3=e63cjubQ0DjkCB+;G16Jc@fe9Y9wQMw zd5pxV>M;_;X9(hF!|rNv0A&<2N*NPCRLT0BP5!zvUTtf;ZFo%)u@ zt6AD&B+?!uk?|Pmy~qGY;*CJcnm6$|1&s7zJdGVj;&Lq~cLG9Dw5@feAW$4F#6 zMk3=e614#%(LHFh?vX4;Vlpe&$-qeDHD;QIVzmP3Mgb%J77`94k@gsgfC(6hD-B7l z1sI9Ft1%O`G>ArM0Y>6XtTGshV^d`?5^FQ{5<_VXb)tzF$$%=(MeTk<{S!#VNvAg? z)=vqKR5vaWdJA_CT1Ozpu0uy3t7^Hpj3r(ITsi@_$-l)VQahU~PeQp+V+~6tRGbf0 zd}{thv%<214=19VMif#S-BhE^i}7_}NTY5@y$l7?gm$C}?MM^ak%12Fga-Ra69keb zS|m*fDRM2;2hY?dp$9oX=gkC=po%-8=nY8XHzwloTX0VVM`6UOt^gUdfU4G14AfXn zy&F^wsiJY9h+x zOCTY)e?MX5z5}^B-9?OiF=)03U-!8a3T(iv-lM=n1kBc<;NgNn1k4sf+y%@uZ3AYc z$1z~`1PB{2JCmdVgG?2X4Y+VS6J?ND!GjSnRWPHGkj1QQR$p*~MrUf=&Mp~4bfSIOc z>1=q+nj#u6f>IMOBSSFAZAd#x=oV!IW_MAc4VaPk0W;R?17_S%l$V--89RYskjf&T z!i8U}RWS_JP+|gRKLYInW~6<aCe0fSo5fI%&0z#vH6# z82l_M@c}ay@c}b7-UrOC!$k7|vq!-AfZ2Dz_<-5#U>q2vW(Njop#y`g#0SiNg91Ka zmcSC~z#vQefEkPUfEiJO516%}6MVpo%cT#Paq9Sh85P_w%5K7qB|?2+149Cmkl8|= zft*U_Ow0z%nC-xzmU3V)30plFB;&y#84m_o#)H9?Sk*lkWR3@e=Of31LFRZc*ozzw z202wd7^Ij7gUs<@FoQB43{uR4K{m&O!5I+qV32;C1%vd{Y`|WH41hu2?qNEY^*~J00kivJC}aa>T&{%!gB&0a1}WviAXioo25F`TgP($!2ZQaX z%7a190S^YrcrZxDgTW`Dz=OeOz<4modOR3p84m`@crZxDgF!ML43hC+klFwS=^nIM z_ed5DGMSa@WPm~P-*(_a>Be$$SU_n(1#j?nS5 zWwk7GJZySLJ7lNmhZnfwO=86aPVa}n)IN?nR#vmrcgQy4a@v%AVB?S|?iHt(Q_DOu zUE+)wnSUYE(JRg@qAg#+cjf_FeRgnU39^g3dfP>7oRU#kdDK%p@4@G21nn**p;)=% zBe40aEH_8GH`(0Du-rQ^O~H zw6Hd6A+N)_dBE1<;6othSUesl6irwV46S>>7DZ7*EPNNpAQF8Lx9}LGi11|A9FD~` z5XBRDD~-%U#(FgxzrZsR?iXC~`HTQ*bTZi2pjNT)j#9`%0<4s#em;6L@C zyctzG+^=bi`$^Xy_CYzFgF)begYpxR>~a5HptHE2K4pWz1qbCUp`CA+vErfJA*zZiB#u2jyDI;r_!sC}$au`|}RUnd5PP-a$EYJnkR;pqyeJ_Ya{h z9``e7>v2EDJnsLi9h57cemdMwTIC&-=X5v^%58`9pj_o0l;_CtpxnyogL1axO_udz zC)7dk`e0lKeL0s(C0r1AJ*JdCDA(>MR3{M?C!Ibhw|>fla+QBjP91@m>~KF1%BL8_$VhE8 z68#3slxf6RrV(SAL5x$07_ru{%L+k^+@u;z;T`VWfQ1lEUeYtWRRon{xh)qJCHi1tx2Ev8nD_w$rbwogQRxx1Ne$>;j zA1Tk^Tlg;IhoPp}0BdD{wK73ua10zP6F61|Un_$!m5E3z6OmRXB8^1GmQkFrx@0Vn zni^C3A<(69;-|7#aFJ12Xo1}OBeZDD&Fqb6F(scyL!wM{qKtFNxRS3U?Z1#Ie-EM@ z?k2eznMPuwBi`YNxsEu+5!@La58-m^t2hnZDsYwOfN(WoF!d)`Qu+w$kSXM~QGYiG zo@&S)Ag&>CjU#Sx#2t-uVi+mlo2*cWumw5RZFTch`L<98T zN=aTLz{?ot^s}ALJwsVf?m<0--k?GkFIPP&z=mDt+PeT zbnV2+);XeOwk3}dEyr8(Skbb?l5<7NDof52Eo(`JP_RV5E+*m`=&jfJun5)FYerXB z-{`BWKhmn017S-ZBkE7FG%@NZrb&NRD zQpbwfmYOT(S!$j*UQ=Rh1bq`!N-9zTG*#A+6yi%5Vor@+*z#8EttSIqoZp47{eHR# zt3$!zf`0D=8<3wvlYJ>yzi{#=yp&6G++IV|cCSIY#_cui3n$#2+80g^fHcp@XF)`{ zdME@+3icWtjYI4;>iii4S21_Sz(R+=*PyiDYmo7K4KjYOLFQ0<4K`rJy#@>Vy#^V- z*C6Bf8f5%lgN)y6knwvBGJdZ?#_u)AH2N1#{sMaqwkZ3;$*6k`*84X08b+($Yt+Bh zOSxLLc+0(p7BhPdl5cab!6GB?H3$p+83W;>KV$ed7=Om_OEB(?;R{&6+!+J6P40|= zmH52|(W5_Oh-0B}XACUu&lp(b&)REH!N_}!55Rzs*+LNrjLRM`FvlG)XaTp)I3H&E z;{`JQc!7*RUSJu&%~*jY${#N<$8R%;V*K#}bNn`=2RZ(Dfw;yWFHmgcZ3ed{ew#tD z?e2YCHpd??Ooy01UZ6W?j~BQd&K@u9fME7`VH(<(JzgNR;_(7EFm{_Uo^*Db@iB1O zy+Np18YR?Kl)DiZ{XQ;zC`V3jGmISH|1Kp-&&rAj^#XXkt)SEBCDU#*>KqSv!go#F z`?wYMU6c19-yJWI7Vda~wfJp@9#)~)U`34;?a0NuCVN=g9xssg#|vcq@xn#OuZ}2zyb2d3zYK53wiJ3(oDb2_&138;{|Sw{P6-ozCT_d zKT#{Og-Dc3yEzh@lvCZI2tTgYMaBM0GvF`|2o2hrLD^VvV>Ei_^ zRB@f0cgb~G6Qk4}Kn?g-- zYA$g?Mhk>W$I2P?rrNTVBB=X79YBuNtZj!^n?lM|jhUtOMsoF5PS%&N8$RaJa!y94gE8Ite8;` z6k!c2W^Yrv!Ae_pBG?FYS#}as=dg`c=*JVGrfII}P~GfP>X|gTS)NkwdU;0u6%whe zU`l?vNt~LW2w}EsQQbBu!uH6iSy>gJsnb`;i{&MHxMvtL>ow|7UgO;*H2!lqUSo%j zZaA{nxEgc4hK2IH#%U?=ntW#&W5zph&Qk82C9AH&I7_8-7FKR5s&by@oTb`1%UC@& zP1a5`I5l&{@~Qy-ipl3ZiC$Ef^`iQGFB+HcMdOVZO)y>rr@?f|aSXZ*UC_Brz85v- zdr_0~qRG~a^bDhQLS|=iV45M>wPRLRnRckG`EDYF*(OBtr#Vjc%xsM{L3Nxh;H*lR zHWcN%VAlVN^Q=NAl^`MRRu4MlpS+CyDGvFzmN9K<6Z;HJrKu&(bEw96PN`dF{K8h2 zUD*Cc>shnVYXvNAns;1N#SFcI;1^K%Ajq-4E<4=kz;o%b_1WPbm+!IoyUg5WaDwsJ z1~b}l(0q@bl<%>P`5xPp@3E7e$4;@nk+beiwMn`+Ct%r_mYZPQc6z?At*kPu;Eeoa z=Ym`{k0@LO-+_cYC!AU2mq{Ew7Rz(cIY)7M!~wW_IyE<=)y8vY*cJ97tgy3+@fJWO zp4PKhh>PV8S$_#?%$s{=y;M$5cm(QV+alQkaq};l9gvvm@?kSAgcT9;cLR7!HygKztQ5L$5}4} z1bbY?a-Lew?fyQVTsiB&l##r=0Ozc%a_-D2FdXRQc{rYjGjf*_cEk}#$Xf*j{(g6k z?xVnTn@1BW`zQ@{sV1KlnTs;O&JA)-)md0L))v2~_@6MlV@&6BIIhgnD_n&( z5qu?$XKxzgX(shWHuR94mVa0AI!1Y!K}%D*w*GhZ0pR*UvD0^z>fJ3+wlg*V)K!U61nxr z#gO^W+)3`4+h|8KXRb9BdX}437}@*qjo@uA?l+~Bzbz}}4NpaZFNjGD0qIWwdQ32t zG%pf=Rp5RYL)A$o6QPhQ)K^2hYk+i_;5A}%<66?B8=7SUo12w4rL-QDhdKN~2U@$H z28?8FGGUO-5u?U8D&nz|x2WPm2Yu*J4an_)SBdP>px(v^?)oN<>X(M4~PSvbv#s zIaW%(^UfxoMoUL(V#s&-UGshhS~oBHC@B0fI0~_40b3TZWx+vQ)N)*?b-`#_72i60 zKfctgHL7Y3{qgK~-C?>*+#iOhiD)CtMy9<6u6wp=ViH_|&6R3fq6~NP>>$_JND-UQ zlnN1q=vDMLvsFwdPRQ$=a^#FGkAkM3BhUifn-e9F9dDRRv`U==BU#r783`>kLdNhC zki?MmqE`+*V{V5Wzh=hp55@7`BZ{Jl?yq80xtkM;^&9hWH8ig}-PHIf3bV#FP&A@T zjPCU@9z)VQNA~)xuR}2e;VEZM- z82tBXXNcwS7zT_rM>MJ?IG0GvY zmGL_0(xaIzkNGaOY^l=-8NDKAWssuBJ<>#i`l4#1t}(7E^<7KQ1V|XWT%)vp=7h@l zw6}bmZ8ly`);en0d`qKLkG9HpQX;B~b&8*ZF&Iw86VNu^ORPR$qpt}m+EILqpa`Co zfn(8u8T%g5ft6df{c;`hjbZ&Nt@NvMpk2+qd#e^^Jr!ekiS91^eGms8V}pu*ZL57d ziymLV6&w6~(KWg^Ue!2XBdS3S*1u4@S@b4gku!e3P2Y2Qu1nR zcxNA!*&gFFnLH%Tk^(<8lLK0HiXEwmOy^?>>BgsPoa6*s8*B9voZ^$6gfF8XMd;;7 z;HGrBlYs?+9=A%D;#yIequ<(U0FPOtyiP7<$j2AM$X|#(^u*yyKl~8u=phXGDvI_Cpu zCp%|!ALnZyAHp}^$N55t-~sQ5K#={#A3_2Av+v`mV(;Q?jP4Axu0anz{Nsv0;-iGz zCQEU)r&9q#?IU%fi+k-$l!+E@$%fa<-=W*W3|ntGX?&L8%XIgQet?Piw3MxGxvA{z-9V>lS3ZPoqDDaz`Px9FFXkQTI0uEoE%q>Rr*H z;51vOZd+k_*0UPr-I~*Gsu|YrQ<1&}a?Z~uTe($bF$nM$n5Oy%VbQZz^_s^E?(1kO!Kkxo9BpRd!{eBp|!WYJ1vr#u8VN(2RC=2NTz$z z{hjIF)K-z)jEehu+LD=p)&WRtPGvNou?gLMy`7EvGT58x>g-LoH}V$+@%v>RMrE?Q zFV)(eP9m+R4MjJnvZ`_wCkJ|xnRE(uZ|NEkS+!c*VB27aNVc_RU;za;pc6o4kl5F& zOC<3QV@4!XeSI6dD3s~!9>l$)yOqgZnPh59D_S|w-qj05-5ZT@sS5|R=Dv=OOj=vW z)}f8gMwr~4?sZ&8uc@V@7dqKmR?wH)$i_i+x*tZhbaiTzJ6n5tTD1@;^lZAdo!87@ z_W*uokgdRFb817IF4{K;6|e@CL1!06gkyE;oCWqrL>rIpN%i!#r@K$;Nw;_RZ3aIu z*qc77AGN0kz_s?LHk_n?R=E{i9f4!uIQ?Dp zACBJEbSpZlx2LrmB4()D`v%+ShP~-60~l0F_4L80WTw3fLk5pXVvMLY32*AwL%s=( z$2fHKr_AqT{Sb-i^ubR`y0m@4(hgY3OThr=D}pz)Tg%&h$V##*>`@rn|2V4{pk_p z@>A1nT~4ti6ME7;SP4d1Xh&RQ%^J+5HZ==#Z$npa+Ag=&unt%vI3}9}=7~1BKivtB zP4{D}BQKdWGYli28tl(>U6{srV$QjiQOLA7D{99!nI14J8_HUhoU5D~kVU4^Z0J7B zF3u!fYe5%g>(Jdm^$^7LNcZ=`MKW76oOiAXrGaVkHSMdPTz8rvD9O<{i8Uqnp|%%a`%5)E6zK+=5TtlqjEOg#s3kz7^p6+PgAd=eGK4feu^+d&u~ z17R8r!daAyQbue^u9arpb45q(RV_BltO(ILJTf2l2I|eA9`$v9aZnJiW-8{*4F-N+6S%^R1 zzD>NITk308`n#^w+Sn_W{8cvT50-SnU%6JqT*+_RykPciF-JQUvdwGzd5)N)|I5|T z7IQV|KTU;!DCx+k{WE{HTSbBO|pn>w<>OPTF;L?XvrtDNnf_)SACL*-C}7cE<0nNv`OBcPO&uC z?OpnFPR+WQBcFFk=i=xAE`yKT_ZyGcn5*bNt;nxjDa;I)_B)>z3v47Nw0F5S=EyP^ zq}d{Gi#f(c3NX>WlUtojpXv0hi#gH-4XoQb$rdMhUd)lJT#Xl97sMQsQ~W$Qi7S4# zE51JF$hK_pFy@$?;_FfT7%Stl!%MX5jkC$UPHR&9JhypH%Qlz4F6KxV+px`Zk~dgM z6=$`Dsll9)5@+WmI`wj$@Ks&wYtL$Qa{2YR)Vz9pBI~)_>dMi{U%hkdQ1oQ$BX04D zy2*8+&4?CGEfIAql5=7NdySvE(`?{5`+l!%G)5!21{u|OQw zAPzgiM+p}N%+FM#{0A_lqj>qUP6st*tnly^{le~NjZM_*Mc%tIPw0ayq zcIOsP*>v~ZckzDy*9z9_7GQS{QI4Z7rn~j`WHu9@|FH7zVd~=ke?)pY{B}h_yNaQQ z>4obU|74!}9hfaQ>IMI%oat^IUTxE-*mU=Ra4Xt6|w8*BrC(&eA0YX>(2wWypTM_EaVAoc-3-u8y9rQu~CNnVD z(V+#~`&=xteW0&DlWZN_f>317rtb7Wx}8TA$q^)S!&s=ef2-)|Z$(79eXyrztLSTc zZ#p%Af4_xrS2j66+{ZF@%WwCxE))l=a`vBY7l@GXS&PqHnq0bSNiu1}l90@gPZmVd zMvS(xQX7CXQOLK5Ou9g4zL-n3Vcbo9dcQl>N5zuKHA@zsy*Syjbot6vFxd5RPP})d z*eN#Ashqxbbcsl7S+mA=OfuP)(I+Sf&YIYT=xIfi+HC(Jnr~Iw1a_$k zKlYZ{+B4AFhC5=}`o6(Yh=>k|=JW7rSyYtEP(ED_Ccr5?uAoAqwL zxpiQmzpD)qR%ErO+Xg!^6s^6TSysp6T~=FLfBHfv*p29}qqSQ(21YuPG7QCgzAwe| z313-%Z>Qni%=xqK<53z@m@A_Gxb@>f%kw`-<$elS(S%HvweWdaiSjc?U-24KCvL76!{7)8}a;XA{ zU0B}W!~8nPow?eion+hLBnr#lg^a>9%3gP_De+uEX5sjM%$A>R#Qk*x0WdyC=HN8) zPMy0yYSRkK@3sKr69p5_m2>y6=IEq;_gT?ps88b07;`_aoJ;$^APUo%_lI61afiA2 zYoRRp0vFM;_w<<}7ubb~?@h3cuK(&xw%)n9xnq;`Eq)OD6dI L%-sC7u>Ai6%$h9p diff --git a/script/testdata/current_cycles.c b/script/testdata/current_cycles.c index 015c6f779d..892364885e 100644 --- a/script/testdata/current_cycles.c +++ b/script/testdata/current_cycles.c @@ -1,13 +1,11 @@ #include "ckb_syscalls.h" -int current_cycles() { - return syscall(2042, 0, 0, 0, 0, 0, 0); -} +int current_cycles() { return syscall(2042, 0, 0, 0, 0, 0, 0); } int main() { int prev = current_cycles(); int curr; - for (int i=0; i<4096; i++) { + for (int i = 0; i < 4096; i++) { curr = current_cycles(); if (curr <= prev) { return -1; diff --git a/script/testdata/current_cycles_with_snapshot b/script/testdata/current_cycles_with_snapshot index e3c1e2605596ae6102943744b0c748b63c745455..267ca5cb7c7e69a4f2f6c1f85271d7835d6d41e5 100755 GIT binary patch literal 1280 zcmbtU&ubGw6n>L!Y6LN9PyKO8!9)GQ(iD**JtS#&S3#l>3*u$iY!|bT-GtpqO$BK; zAmpTn9K6=Q#DBq~N5Mb9iWdo@zS(_Kla+XJAoIQXzVE%Aoq3xRp{k{U)T*$9Y85WQV&ck^=Z`~1Y0U{~3ZXapCMFLb?d&#aF?) zmIrpP_Hg`0AFZA_S3hcOj(6>~^g2(9j2S;iszQGAvl;w&c`!U>#_;s*2EaIe7w3#y zz|1e_@4t@=AM(;`?d{zyZ(5Cm>*Y#CujpG)yMc7*Ma~hhGKLGKe0X%{wzu8e;=Y`0 zIXO6?_>ZCCyASC7r)?VKrk5A726VU=OnQ0?@b%Xem4s!SOUO@F((_gNcEU55lxF!R z^2@jvb)RdLP$xeu&H5X2>O7@7>b=@jhtKf`bND{-+2?}O4?{N)+&OkSZp5E^qRpeg z?nUjc&>i6XS*P2wJG|HR0^x?&kZJDM9@lu?uwxs&rmQ^C5x^0EB<+1yE85>+7!_ADK@)RxC**!^Zhm4O1 o<$r|y6{Lt`B?Y*Q_;>dMjHu`f@+rtZe`!vBj*9N8M8a(TZ}*IjlK=n! literal 32496 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 diff --git a/script/testdata/current_cycles_with_snapshot.c b/script/testdata/current_cycles_with_snapshot.c index bc6ac19a93..bed65bb3f8 100644 --- a/script/testdata/current_cycles_with_snapshot.c +++ b/script/testdata/current_cycles_with_snapshot.c @@ -7,13 +7,9 @@ #define sprintf(...) #endif -void try_pause() { - syscall(2178, 0, 0, 0, 0, 0, 0); -} +void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); } -int current_cycles() { - return syscall(2042, 0, 0, 0, 0, 0, 0); -} +int current_cycles() { return syscall(2042, 0, 0, 0, 0, 0, 0); } int main() { #ifdef DEBUG @@ -21,9 +17,10 @@ int main() { #endif int prev = current_cycles(); int curr; - for (int i=0; i<4096; i++) { + for (int i = 0; i < 4096; i++) { curr = current_cycles(); - sprintf(message, "prev = %d, curr = %d", prev, curr); ckb_debug(message); + sprintf(message, "prev = %d, curr = %d", prev, curr); + ckb_debug(message); if (i > 16) { try_pause(); } diff --git a/script/testdata/debugger b/script/testdata/debugger index 4563af533398fd27c3c0967bc75d8e0bc8d392c3..c679d6289d42ddaa8cc932aa3bf8c5e1ddfce569 100755 GIT binary patch literal 4400 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 -int main() { - char message[2048]; - sprintf(message, "debugger print utf-8 string"); - ckb_debug(message); +#include "ckb_syscalls.h" +int main() { + printf("debugger print utf-8 string"); return CKB_SUCCESS; } diff --git a/script/testdata/div2.c b/script/testdata/div2.c index aef67b1947..8e10b2884a 100644 --- a/script/testdata/div2.c +++ b/script/testdata/div2.c @@ -1,5 +1,3 @@ #include -__attribute__((visibility("default"))) uint64_t apply (uint64_t num) { - return num / 2; -} +__attribute__((visibility("default"))) uint64_t apply(uint64_t num) { return num / 2; } diff --git a/script/testdata/div2.lib b/script/testdata/div2.lib index d631c7773a2d1a6ba50b0d9e2c6d25dcb23e9be4..5b11cc2fc447d52799b4e7353decc0663c5861fe 100755 GIT binary patch literal 5728 zcmeHLOKVd>6h7(g%U7+f(5j#pRH#@lsUnmvY|}I?r7^92fQoQQ+mHnEBDsoPh;7}t z6uNNdZz%o%H||_WH=^LC8<(OYy0h_|-1Fttq`1(PcOdy@zB%8VnKN?-&O8o>2^D4NTq)oSi2(AF+nR{|*ehmb@lUmlTy;$I803W8+J9Ih zby4w%V!vWJcQIW;havQzRJ#tvKE;F@f=3(qDfFeZk2Pqk{GUNl3mmNLJdux21%o5z zz*J=Ek~uVF4OxB|9)JdCv50@QnZa2u_Mw(H2=TAwTM7GA%eN8YSIf5(=3mS2&x@ts zpiaU%YwdX#%xcE18-&wQ>62sAO5chVrc!If%YOUVzTWQ%|#fW8z|zYAD}wX_pmCad7&T}+@B&)l~X(L#c()wK+px#;A{ z%EwYsE0=P}a$*nppZlZf2xgP@Us3&k#`TdGw_|`TmuKy3+@Gc&$x%q zaR1L@F$+D;KX9OlUTKnhNbVr$@tpvlsiF828~DflafLaV8}wsZ0pgxxlTy)Z5KX$y zH5q$c8GLs@_z@p+ch&nJVNS-xJ-e>{f%W$Z&NOhePLFpw>Xgm_PhSSSu#blgSM!YG9Tcl|Sf#@;!>)Uok1wOx5eNYPnaZQ_=`2?fNwd rKdky)6&z(wDEP&`$extv&UKW2bsPhs2>+nvUTUO&r22a>Y@+`SZ40=` literal 5416 zcmeHLO^Xvj5UuPay1JrqPl^ZUps*qiMi4|VJDW_#urblN3wj!2vTPR22b)pM$&Zsi z!IOWLm_-CAB+%2Ao?c&8W{)|lmB5sNKzr`JB9B^6f z2cN>O#2vM1n$+UBJO>??C*}d_awAFszUzAUrVB{u$oA1x7B5WMeELI=y z2QD(+YJ!)Xqt+gco=%7guiv~<#(+`4C}0#Y3K#{90!9I&fKk9GU=%P4umY%?9%&)> z{nvCT!i>~Lt@}}J)RgbkKB+1mS6op%m*LeU)TgjdWc>9HNUZa#V(bc zl5_nC6IxuwLZ_s=#T72}O7j*$r!=1@=$Yo{>s)zmapjD>)Bdcwon+#^HK%f1f9L7z zblzL`z&tPSDaU+v-m}Ud==;ZbSC!A^<1)XnPVeqLzu|N!s61}C_iAMd?zfs{ud?0p zf_km7>H1!<SvNz&}cs1!VcjPQ09{Uh@R~=2Aq+4{lP_<_V{ zzYEJ6uh)YJpRHeFqzPu%B)qNhJ$01t=V|_7Ug$61#aZs$M|&#=keeUF>>u-j5Vu9~ MA2hxNN5yRXZ?lbbTL1t6 diff --git a/script/testdata/exec_callee b/script/testdata/exec_callee index 776580d800d8fe052b1105b25414099dfcf6824d..b34d537dd22fa91b729322c4c69395c730921979 100755 GIT binary patch literal 1232 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 + int main(int argc, char* argv[]) { - if (argc != 3) { - return 1; - } - if (argv[0][0] != 'a') { - return 2; - } - if (argv[1][0] != 'b') { - return 3; - } - if (argv[2][0] != 'c') { - return 4; - } - return 0; + if (argc != 3) { + return 1; + } + if (argv[0][0] != 'a') { + return 2; + } + if (argv[1][0] != 'b') { + return 3; + } + if (argv[2][0] != 'c') { + return 4; + } + return 0; } diff --git a/script/testdata/exec_caller_big_offset_length b/script/testdata/exec_caller_big_offset_length index 659dd922dae57bb49f7ebeae2f56828f8434333e..9cb14cddcf5a1dedabc99fadc9bc7c462732c497 100755 GIT binary patch literal 1352 zcmbtTL2DC16n?u&OgzM7GA-A{tZuFCI2A5A$aIPu|;npb!PWX(=Lq{2X?;iz4yI0J8$3anU8C_rh!^I`~+!z z4tIbO1|B9NB4Z`k5YZB3ARVewsF^7wi)v0WrVw(GW8BgfN5gcs_;uVG4Tss{fyDHs z;JMW2Cv)mN$2#i1MXd8;j^3N&@1s9{F0cW!iA_5l<`c_l5pQ=l zV4QSVx5e9r4TQ8ho<%#P=Q&-@{OiKgtd_URWYeraY7ipq&1RFBjcUlPARqy!J_naN zT@gI1WjmBpAgsFsU<9vRPA!4lkFc#6X9Es~?}ci^_FR{Br9%#nK{@vw>m_G$@cwgM z75VbZUBEi3&jYldAu7-nL6mbL^ViT;^EW|z2~j}?iJF!bVM`t#dG+7M^HrWgd9Il5 z9+o|UU&wBscp{?mlv~>IJIPocg>6LHANi>FUzQ@VE{f;8zw12~eI2T1Tm1aRIr#}J LTAihaES~=t%=M4C literal 32576 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 diff --git a/script/testdata/exec_caller_big_offset_length.c b/script/testdata/exec_caller_big_offset_length.c index 833baab339..e0577b3c6b 100644 --- a/script/testdata/exec_caller_big_offset_length.c +++ b/script/testdata/exec_caller_big_offset_length.c @@ -5,7 +5,7 @@ int main() { char *argv[] = {"a", "b", "c"}; int ret = syscall(2043, 1, 3, 0, 0xffffffffffffffff, argc, argv); if (ret != 0) { - return ret; + return ret; } return -1; } diff --git a/script/testdata/exec_caller_from_cell_data b/script/testdata/exec_caller_from_cell_data index 08f075eac57464b3cb7e5acbb4985de97024ce9d..2b597da57054c5ecda3795fffc6cebeac54b97f2 100755 GIT binary patch literal 1352 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 l(grcO46F?|PgmU4qTDvASij!b3AskRC z2!*>3{6_x(^$+q55r-a-D1sXjFl)~?t<`W~CGVSg^JdmN9`BkD8oH)|S~~my>Fq~5 zK$QY_Q?VgqRanPp6>^Y`R2kCD6w-=oPAR4k3Ndle(H6sTHedO2&W zW_~a;jlD*`c?ZJW{%(K?3vjgXW-G(rz5P@I2=_|wb@K*jjc-Sve}%b8Mrz{42`xe! znwy)qi&vYit(9WAY?O^vs9nRL?*{e|v?7}6LdGB7y6LVBR+%R^E;k!D4E|%K@Qx$8 z=Sf)#beNpUQxi{$(M~}+!NlE5!}mYQz-1%~$WNE!{;IeU@j6Tkr}>A-FX6kW?|G3D zDx^P5=s=+r*rhr=kPCxPo4|T$g!EtyIsd;&-}i}Ub&*@1c6}#W1Vi_ z;$1fAyFKCfSCDDfYmaMe!))GbF^2v|yUom2J+iGJV1eMi0FS#p44&3H+gxy9PH!8) z2wr=FTZqDsaYtFg83{1_exx?+zUMhTNyxb|xDdW;y%f%D@~9#I370TWez|j$ulhV9 z{}G`AT^WQWM47)vzM8)Y`AdWfa%8A!SwUag$&pw8Z8BfwDU|2pbPuTPG5jR!`Y{t5 zDo@eUPu@w!iX_}2l>L#9djDl9!gU^>v;MA+RCE}rW?S<7#X0%EDZf5TjjUw;Utd{^ A5dZ)H literal 32552 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 diff --git a/script/testdata/exec_configurable_callee b/script/testdata/exec_configurable_callee index 69b97ca6d17e7c01f2dc53e7686e3b47bdffb911..0fd19349a280ef3e96b7224c6618556c18112397 100755 GIT binary patch literal 9624 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 E04rueTmS$7 literal 41472 zcmeHw33!x6wszH5y=7k-NJ3b$u!#_Xut@|Vk^~q}D{0(w<&VR2me-&6I~*PSL&{O|JL|9PgLr@yaG z)j6k5ojO%@PF1CIch2Rx2IowF4E7Zx=xZ}?yjd`Qy-HBocs80DcqXuJ64!3x1TZM2 zcuq}Lx%$mw16U3uuQJQ8x=`Wk_d2J-d*)H~)^v~MdAgm9?|JLvhnEy=Jht@HehqIN znEKtcGZ{;c$5ux#&-1uX#y;L)&vn~xWyjf&fxd~iGXLp5Y8|gy*!a?En4P8M}7ASt6cqyb#Y9oP*vh*;nk_(m2S! z)WK4{BiF7ke8iEtXAk?VDRZ8aKim9bQ~K{t{m|BR-wz|UF6`#F|KltqV9)e^Was1= zH*CFP#^kM6&)B{*XU1=K&X}=y5u{@G?wRa$+jl=v6?>Iy@uKDljQQ&)tV$Tc7;>W% z-oe}P+J|9l>T@93yoA1#|4~EIZk;+F`xo2s*oP~OoI#A|9zXHn(W=;&ZZ$+36{yF)r5T-e6yJutboMpdINKEzp2jM&i9oX6g4N@pjT zc&#reMw} zitQ^%Tb8Z_)$tK1PO_F6rgoc0u-|MLyP~Bl>2~mj?JG#HBR0I(v{h2KBNF;xAsL@UzGJtAM!}w^hhM{u&Ue_zRh|QTiZYhF9gB?m zoPG_ND~I#eQ;gF>zS)f`#s= z)oo)AxEmcQw=~BlW=8E{lx~a z1J8Y9X;fY74e7%L}{R>l;#kL0W@vc>Mq|oL?X=<^y~e*Y_7= zcz@rR`hFsd_w!}d_Z64$zP?N9`-ri;k8f;!I&?J<8pG&*ydkY&+~MP~Y(hhce_6s} zl3-&=*rc%C_OQ0t2fiuW8CK$Mh&t?dI#aqNZf^EBtUi$0u%8j^b}`%2&8>i5Da!s% z$yuN0U-pN^TH3zbqEJq`90_p*~`-PiABc9;LUNy6WCFY~N( z#Q^Sn>QS=J6i6#P@upk+f!Y-b?rUU9F3! zH0t*8zMd}jF@+_PN9}1g?o+XU_0fi{V$^DJFwc{8I?^{P%J_S(7`d8fzJ1j2oIEw~ zjitY8pgBHmndj?9Mm^?sC$emRwAfhss}q$CQF-;2Z8_$(IPJ`{!8zRHDRC_?SuoFy zUiLRSQ(kILOdQwT{r)lj)epNotzI*a)xl{1lZCre+{pKn?;kEPdN$2QfU=IM)%@=c5P^K@SV-{gCO zd0ZufdX$_Tb+V=&n11m#-;PM5t^D1yzGowOYooz;G_`$n-474^;roQ&`Wl?> z<~{5!|4U8ZeCzrAV^`amVc)<1%eIdSzi;yy-;p-cfA{x;-5S1Zpb=D`_m5>-lfJF1 z4?>$g?S0xl-~Uaf1KOLYz5V!qsK^QH>A3y zxeMm2{fy^5w#VJ7bjq{$$0lMNwY9E(jS;-#ez(hYfZ9^f>y_r# zh(Gd7-)k)QaOSE#Y|NUpW4``Zu(-Uo#-nc!&hxB3YDDFEnvOcCCVPfED$3S2{)Zp3 zi`LI>TkJfrzNoFq`9WbxLrMCOU$K{()1UbV8~Xg<>8Z~vi*JiP{Q)eVw|zJ2@9#Ia zeO&VQwnpc_`$k3?>knk^KVs~-f8DXR&riKi{ffT)_~`p>M~}SUcJkEwyZ&*(^w*#3 zIep>peEp-CQPMX1^ciaPgSldDln_KOt*_)UN8wYp) zy5_`jR(-2+S6XfANwfZavi^Oj|LygMqjnBlvi7;8=?%|i+H4cr;%s|IF3<1{-I+T5 z#plK?dFr{FZe4nKuD#h{dDHBn-BMW^XVm9US}19_x8AT%N}uY1M`S5 zhi{CXdz!*+zKby~SBBX#!@p*pk`*@o3s2E7Jp*3UkXtsd^c@XjZ!~*8?k_w? z8;#7ydEE0=p70c$Hau00?D2+i4fY7n?RmWZ4@rBDvwOTzyAFo6-G9sXeB$Hq1sz3) z>arJXTwvUO=$7m`8|M_j{}Wr6v$W>6*^NK6j>_Y$&J*J^>rS)RcV6&{!_m47wq<%h z%k4kz|L9ek{2#l$ZS4!+EnZZ1YroHJw;uUy^QwLg?|lFMH;z+jUrzaC>XB)OJ~(;k zi%&lO{G*JO&#r)+vv%dR#h%Rd?d}6#z=k@9Gv6y+nD5UMS<44rCSIM+l0SgwbzL#@ z?JZ)-&Er_|+l9=17XHKDI+omh9LsX<=PmwGZ1eKueO1i&rzP+xJS;2x4W67doVkBE z1&pJ7TjM+i-=f(_v6f$ELWWA#S~8GtYw)sdi)$e7bId*Wbd3MZ8P;-t zF60`?TCS;r{J&@Jga($iJf0_a9nRid#gJ%}M&ipM6Jj-9x#VcPhqT1D+2+cZrjr&r;_1+YRyB*R0UidOCq+ zmL5a0@&tD;IeWGRK6C3)C(nxhfF~zrGHMxVHp^AYHg-GMlv%Qek6oVZAI)Cr z`hC}ZP1}~0vTcqh(MRrir(?1cK5L?Swk_KWt%w&_8JS1B@$awo|9vSdOlUp5mG8RE zzw}hhdreas(mr(@dwS)_!{fe&J&hW;q^z z%~ykU@+sKP4=l6zRkSaOC;KmD@OA$RYrpaVCZ@i~TGmZMfBa3_$u{v7ci(m@reyqM-(#=LeyfRkI;-)x)cf}3EjK{U z{7UHLb@qxQvjqL!utVBS%R`x%VS=HDTuXG#yknhDv(FzZZY;0fC)lJGu-fNoLaLb8tXO6QIT?elA^lrFI{0Wxv zDlB7967%hbW$aa!k$fFm^x6&5Dw5wuU+gt4qxUE|V<^iwj#+AfvGzfqB}IO$ycoP zqZcrDM)8()mtu|-Q#XTuiJZ?Zi}0P{+9EKs-W0Hhc~~`I4-K0bX?yz$aoI~~^BZ!$ zcx4VO0%KQM1X`f%;hIXe&AuJhfRSg~0@;C>^gcB42_s7|7Si1DmRz%_cU!RXwEPuw zAZ+Cj=9r_L#s`f_npLva{E6>tqTV4HTCVlV^_Aun>T}YWySLMjs|VItU(P>ZgS|M- zq=!oVcfnqK9+r6w_RfH4f`rshris^N3!aU&XgC&rYCqDRcglShIG>_0RW0r0oT8&SU<$-^PqNNHfg3 z*h2}=emCZ$ksoKye}VV=Y|0l?Pfq*B|4t6;o10mBhUI?mKYfz9oz-?v(K~oEF=9iy z?Vzo1p5H-vrz1_SUOSp zuZ!R>K180vCcC71Cr{S2T~e8KIS$$$%a!#XJ|*jaal|G@j^j$KJL z1=Zv1pdQ1l$N84cy+03a+rCoCk69a%piQn0+GK3mAlu~ng4%Q)+JrV!n@&k8v?;8E zy1-4gDGVHQsWzgbHd%FrchIKrFKp1FKwEG8gD~54xR{gfwl$XU^oY=!s73#X*%a}X zEj^Ok{Lme>Dx{~_K}SeW?O&mLioNCNq^I~7j*y<(AFg|fzvbvegT_I}IXz{3;Yi-U zg15Z$271ar?{qs$dhwxj0U6p`(*AIRbiQT7Ch>)X?C4xNX@Td^tuQPL?5th(4%#Iw z3nZ$JEij~AV_|^@9sd0*&|CiZ-w>wO4`0j4X0x2v@pPx9ixa0DV>dLEZbDAFi#vEu zeGbp9&*g~a{mTYe(R|;$w7IX$ON<@4L8 z-tqJu(RY4cKDFZMiW!J-sK%VFgJ*oa^MV=g?d&__^_{6RzS+9q){JE{iu-+f3ER9R zyz!A@#Ja3LC%eJ%b=rw3$BYBU;o}GHelhhkd)dGxLGrjRu;ekkuhVYvbH`6KJu+}v z)a&i!4#HbD+gP{kz{cvd2BYp!QFd7lWU^1+y^~KrxphKZeNNf|$KioXjtD6^x+^|S3^kJuJBf3wv}?c{l$E=L&8S-hy# z`4O`_TbE)lc8?R@&8f3(zWqOBHS8b1c+o&#+-vEql`ZUM7v3KbG3MHVVMmnLVE4G+ zVcvga+TQ`*=0*Y924}_D%!Vh%FYLN_(M`9$S#s^CzL%VXDFU8(Ovl4FA0D{k>E-rc z_?}zQyMFJYiOFGKpN+QlyU%k|7<+tnM^UP0c^LDJT9V>v7{wP}T+rpco$Dti7JWa; z)7)RAKiY@S-S2zCHgsFJ3%T!Kmavme_5GJ0H=5T?^le?yyRGNEZ`ziA{oUl9>BDX8 zy`8=%CJyzDSQ1NE^+%^Q7|jQFX5jhy&dm+5x?G;q_emc2W=YzyD~jBWjnBJnwyjC4 z`W;qUZ+t%Pu+l4Obzv8O!f^I@^Lo$X=8v|b|F${@4_xLO)!2LaQQA9AzvOhUb$Q=U zS~$b=`(rjwxXW;3Uwhoz^wGOxeNQ@v+HpNGuzvvNb7Yh7Z#HOiAiRQ~lt)!Q{py>HropC|R(4iSaGlsAU1JQ_@vRcn=jHe)Ji?!F>Hgb5`u<9ZC74#^ehX)T7 zTAx8k84_~Ir@kjM$--!#Q1}Cosqhacs+BRNJ(>meK+0gV!Zf~BU?vp5G4Z4eIc7 z333f~Q&%m|D<=LkCbssoI-^(hW%t(fHQiNv!aJ;uF@=9iipIaw#2@*i_*bWD{AW%4 z;vdD|2-{QkkeICGN&8X!?SnP`7!zMnpG(vSS$4){vE-}`bQa;_iVmBIFJCkS7DjmJ z2-fWcFniKHoD1;{wa}-L=X5#g{#Sy{URGHL$o`egw0};oSlfFT5iy(bFmC1vWQk6j z^AUP+$4K1padOvidKvbsWF+ekO1nJa$|8zrl7 z83!qUR0NSm8uy^oHmVB&vBrF=U{o>zU0nI|+31L+C{AQHnyBnfJg6$!095rSr2AZw zK&t!@6t;0;M97RT#N|>6*bEntY~v;1GQOaa2@;4jJ_VsITLQ7hYXn>-fiA{ELYpXo zL}MmNnGXSn~ z<3~|7Z(Nf&U59L7qWks)bovB zQ0*T|l4Zs$0uF@NgYq7OgV5F%p9{)$#&1ckqmjLV@UXFx`r_kg8aj^}TdCv|X%N3= zQ4b)GD1>}a1BDNKgtSZBRVa}RdwdKQlbklM;i6(b7*kD&A*En^BB;uZ2oGd+@%JUr zg@9PTK?1!9NaVi;i%P>qoKraUT9x6t0y9}3z857miraYpJb+rGTOmp&@skjCt}3~T z??A~sBfJJB*You#x!sUMbvFM!>bXOqmGVy^^qs1tnkRy0q0wa?Xy)@nKwG5H7V+r- z>WwgJ&N7}2v_}o+g+RL}oNW3@!%cR4hKJvd*HcD3*(o!^9|rT^7?F)YOtgm&29IZr z*nuEOv4_V4dd>*H7iFXE%(e`iF*l9{>v&4r$ULROw*m@MxCE8Ln+Wd#Jfc>kIx?gn zJjyaVW*4Cl37J;_h1m`Rmh&cAjvP)Hw505w8pd3HD@3yO;oXm;P3}fWl{kRkjB-vR zcp#6XG~=^TdLfs6?Ba7!GKkAQj%7A#u#Gsni+~wDk*_D}6Tr#g@swt~C)nmHz`-vD zkjLY1M?oaB)9cqjGR5opuC2jvJ`IcFbAZ=qBua0Grvq4K#8U^kcoT$KZp0E+EPoXx zD~tr1SqJfd#dD<*L&~^{-v<#^8H08J?Rx$m&{iAWOHtKqz5yj`jBYdrs`&>fX;Q#^ z{uZ+CQNSX8KT7U3Vt0eVGVVjAzcga^0l0_L0P(AOp5${;>3xdk*ZdVQSgU~Nco9nO zSHSQ1Jd`vm;P-qffOQJ^BhQ0452(TLHnWp?kjzpeNwgl*6BvYF4zW~^1Bqjqm!R#~_Qc`m1$?T+EGISH}4K6-I&`9h;qx@F} z^-Y&&(A-T1)u!sbNmC@UlLQASr9i_-jr{G zi3U=?FHKLJc=m!f6wPNE^YOfq4`KbaTm3W&RRKue2S7g46zD5K`b^tV=VE;C#nr~BqJlb7tp1TWYnoN`ACL8f%21V#$#d&5;4k0nm|eA zBT+81&%$FjzK*_l2>3k4#xT;7^pT85or928K9cd2eJ#?ak7R6?u2-`1kwj7w2`zmj zTVxawNgqk1Ckr&*^pS2wQm*o1q?^*Fk3`tYM-rnV2v9zf7}bRU)jF*7&k;DWEC?82=OF;QZ;xY*+ zA4yD>-qBABmIzA4w21J2_AEHMxpbqY~NCH06hiGBE=_5@=8?=u^Y0F2VS}Y$)b}JLqU_l(?i-_MuzKW<#ABobI zk3@jwBi(`m_(=33N6Hkh*Si8f(nDB{wU0#8HPb#4b&%yF5tij6(adW3NF=7^Batg* z`AFBJD$7TrF<|*f1Xw;20gL$k=p*<@Tfo5bk;q}Pd?c#J@{x$f@{tIzd?W%aABh0V zM;lg4fjO7JiG;E@(5@@`T-^xZ2v`hTPh* zDc^^yO(3pzi@4fCvNwUf@m4}U_@Lx-dZ`U0u%bxF@k?aU*U4P2b$EvvgV1B{MkI}F zq`JtI6REB;buCieC>7ovDc*~Rip$qWoB?B=5?&0fY8vlYWNX_8FPq-YCl*t19Fw1F`}1q64IeU z@bzbqD=LPvjINX#gZ>Ds7{>TT(FF1vMI{>|U1d$q z4O5vmH%uwroiu<=WLWdlH~HcZ{<9=%~ogw}>B0oH~o0oH~o0oH~o0oH~o0oH~o0oH~o0oH~o z0f7zE=_G-)@qq}nj; z1G!Z&AQ4qCAkkDXKuK%Ev4w23|%b)`lsOSR1C)cx%J-9t<37!<0smwPE^i z0IUtuuL0;_fH>=5fF#tx099gbn0^BSYr`}QV^;?QL~U)D5{b28N?xM1VVX@-o!&5| zkkr~RrJ-YOm=c3uv*@*W5rs`YsDU z(5zs9nqvh6{efl$17yd6U_dQFdc)KQ#6U365A6#C1FKOs8o>ZXi+aP9(t^xWD!dg? zkisQMLNT$D@YdoHy&NDJQV6)gD}chp0l;$JB+HS*34^v2h)Eg_+A#eO zv`}xD&P2Hm1}M$+hAGuz1p~5MnV<#>;;1)F*AcZD3{ct%1_-c%f!k1kV1QmvQa(-V z2J0<1OgB40WNw(!bj@@yKpkWS1B7J-12nT*!2pSA1p_Yu%?bvJP?Z%7&=|0S0RpUG zfB-8P*aZewFz^-tD;S`9tYCm>tYCluD;OZa3I+(Uf&l`oV1T$G7$EZ?nWaVo!2o4b zT<5?PuI1}LK|jYVmGOn8tKH0Zk0;4tlU8D-AL!%o&hKD?~eVCj0pG!KKK z&zEQzkK?2b*7pqp21HR~yG4MiAH}AQ%k5P90kNi)g7v2@Rou)BJ!0qUTj2K$ko%{( z2}FZGY-bk~0XLndH}cves@bF-G`v>>NO%VoP3}Te&k>jcq$%kS1Egcph)VX0SmF{5 zIU~y0%-C`cI55}hL5@a$# zl?z$|GY%8oP@LtUT72T=6ItsoI%Z~tn^{sBL%uX~_d*l+^Z^-p!*7v}rIVM58p+8E zy*sb~7^dg%usnZq^g;rgpAG<=E|-f!k+AkbKsfD*J8f5^#IQT)%7bk(a+qxfp4>JF zPlH8_pjVWA1Pb;MCM67-5sW(hV3E}0;&O=;+6=xv3X12WV~Hjn%8S;Q9;imaXYwHe zF~uf6Q}9`oz6m?zjJ4rQdTK(ys(7&odZKtylaB-jeNK>`ekA(NWzt=Q}(5oK*0nGC_ z1o*$bD3JkSwBIk&rr%HLr1QQgLB>Ic03jD8E$!h_n+TI2_mul{(1nG z-%kg+mfzp`MG0aMbWy@aWHxG`jZUU*RE#4cWXg*Y<{?1nMG1+e{r>a3C_yxq-{0<{ z1eI8Rf4hqkRATx4onMq7G|TU=M_VkvpEm6+zn{=7zyH7OqJ*H+Z|(O}TC}?;5u|Xs zC}Ap`E=q`Y7bSx5=%R#)Cof7+JI)ZT)ptyg8zC=7$W4D5PVoC_h{%f)Y8v`^7bU0` z%kP)>Uznha65>C9Q9_B=>%Zip1c_<+{r`;@C8!?D@26`Qmfuf+<@Xa{`TYb~em?=0 z-%s3vFG`R`0)9VPjokF7?BI(M1j|E!pLJ1!sDdv_D43#$^SvlR6#5Y0CJZTgQ9_y@ z6D5EJ4LW&I!n9MmC?VQklpr1kOVfToU6e>y9wY74JM50XfhJmdjM36#j8-0FAMzM6 z*O1CWofy9U7jR?xHb{)_gh9bWKXMRr!srGbzp-0EO$p1T364VLZbdAQ(wU&>Po6%X z+?`m|03J}y_>>;BqAdr+1YPN4^qX(wP&LA@4}TH)J%10uzrr{4F6^@rSdWxrE!3X7 zP=^SB=-@!8g9D-bMxi`Rp-v=(I*}0SL;{%8hL*syzi0tm=Y9>{6L9bI&pzc4A+TE zb;5-N{)Upp62G`9fcgW9pMiv~37siF#>A)>PzU#*EDK1y9Eqzbu^5SBO03q2bvm(0 zC&+V1)3}M;*q!H&A3}x9v%;YeZJ;qFC zvh0awayZMLY9>dp?CU9M1A~e3x*&6{0N*584vA1*k_2RRNhwx!Nf(+dh63444r57| zn#oL-G}%lJXGzzX$q_8+CQ5dB5Oo;6;wVj3r<$pute=@0#x68dnQVxe8qP+TsS#|9 zOtG##pc^Be6C+`OQ#^huhd!^Pi)m==h(c{L^u%9*vbp$%Uipg5n8bZ0amO*fE8;HV8t2) zSg{5HR;)pQ6>AV+#To>pSQn1|3t|mwQQ*Q+r?Cdr`!iw<#Z|@{Nk4TdTe4<98EZ&1 z6>CuPXT};t(s8UoZlQI?K<=V-#_&D>>x|(m0Q!vK_n5%+83Tn)`iy}pv0@GK9<4J5 z7bXgQ#z55883U30r(z9a&~dDB7X+|TF%#qnbPpUaP>DWXkO(@=pj*7w@d5$X@d5$X z@dD9UVa6m(QP%MSl~`d0c`?@U0+m={Mg>Z&;|20-tm6ej>p0Ay(8LNe2+ayJs5#d0 zLO-Bc#|vc6f#U@VhXePq7XvYHywDfz3mh+yYemNk6u_8aMlz)XVaBt70R1B(a0&&3^Nin4EH4XK6adW*XRb6 z>*EDVGkv^3wOC<>>{ceI!Gbu(6`>S&jhcztJYJx*b-X};b-Zvp3e5Z1Pf$J$bc6Mf zVa8Kf#Psokycwd87pQ}*;|0R9ju+b9$0jkYFylp_S;q?$8d=8+Ei`T zTgMCC0GRi&DJi*_VFnqx3Dd1^gc&pvYI3V*NAFU^30bSbQs}Oc4VR55L{23S+7T1A2j!uz312TrNjQDL z!WGBkV?=avbl+$rsjP^A`hzK_q(Gd}fDAh%rBQ=uZ z0;H&}ynm9aHhMBM67NcclVft0vcswskx*4*WJ$jEV7~GFWLw;U8toUW8oTHkkpWG> znWG9xmTqwz%8C%ZlY2vX&e#M*OlEtb?8F2P(PirhImz7)><*rN|*ig;jq}rItZq*JE5MK`jTc8Q{_QTwvCkbaNSi7hNG^)Z>8^YV0 zV8H$&+DQc^MIytcXAd&Sc4AsahDnO19TFJz5S~pE%AC}Am1RG-0gm=k>xm2l+tpsg z$!;a&?Q&d&$?D8Gjg%MO50Z5}!*(?525I_SnM8Y;f_1Dc(xJ8K>`X?8-%dj4BP>+2 z=Qa0R3jP_R_-D=ifnGBEEm99RVxxvzl%AWd)gU^s8vG9}0vSwBu&}4p5f`V%^_SBw zegug|dyv&72D)1<)E3iti&FEb_ zetm|5bo_|Yx6x7b!m7ydMWQ$Do5_!Xbd1r5()8f?Qyl$kG9r-+9%f@)*yNLkxscXR zL#F9z4=S~VseHmzREAj^z~?3oIHL^W(66A7v^S9e9Z74y5GD8Hy93`7`1V9Iq~u{G zfLIg0xYUTeEAbH5(_=P0O6XCI2VZ~(UDyaS4x4`yE=F*>T{v)z$?e=BZkGwlfTVT~ zm?UN-y+os2;SjPp_AU;T5Fx$MRyz{1S$2mm0j|sm!xjtY^oIh}#3>|cM@_WRA3*5l zeTKAbo?|;w_yq+JQOgW!nL#Zx4&x#6@F1?EI^!zns@@&=5@*R#bfK;vgNIU>REhp; zD$xsVgxDxFpN3Y?oifoIo$5eyxwtbd8gGJ0LAtT_aB4o~#4*DLtwP^aESxg4M?2-j zqNHPd5Gp;}!3DhMg+&54Spj!Tma+swQe7Psgh`|h3eKefW{?ez?@X08`ctuJ96XXL zE&H>{KN_+lTd9+N3W91LaG2-a)>b58je3+BBePU;wqVl zurN*C#+z!52!cru;U;X;>WeWcl?_%x@E@NPE`{{;Rg*#`Qj8wd9R25FB9=@8@(CfI zYJ$*1+R8^6luCC~e@>0_s788FjrtGIM1r1%&aF%31WBUm-D1`|9`BAv+agp#Ep6YK z^e1fWOR8T^CV|e>e@G@`0s}#Alo6M>gBe;TmnqChz`O-AV);K)@nfP)-qw)Rv?5I={QBbDS5@$xM( z$bNvK`07Ssjgf|Lw_(a4?OQc>H=B)H{*p(6X?ny4R25PxOG&WZ2$^He%TAMV4{^7o zk2LvNHCigtK*`(RU@iF4W@mecC`@pz`{qGr-hK- z!7!~=1e4OOg|TZ;Pk@W^GR)=e4jN+iB(gf))zoohg2Y=bbxih@wW5JJ3eogeO&{RO z&NOb*8rR;1oZX#t!=1foH9y30l06|+qA!n$J=7di8%ihAZbJtT7xSg0cHxrJOAVOz zr_2~OWXPiKy0zU*a|Nz)6kNK5-lT(QQ)A?(5e!TRXM?Gj=ZbG zAX!znVlq`7s}v?gn#9&Bwvo9{Aat8S4)4oKeL~QmPjD)Ah+3I6>|r8GwcXT3nE6J9 zve7m!$3va0Aj}*a-~xe_(ue@CQqEmyCn=|M8>jnI&*0nM#_47itH7hfC6V-{d^LT% zDIzQrr^ZNSs0jvq=#-qXv-k+c@8nT9BbT}CoL|$-j*iV;W~(F3rV{-o!!D|=np@-X zUQ{@@th{J&rFUL=S>fQyg379k~=hB01Y3_^1T(_ni6lNX93Hfhl;Bz3iE60 z3hIC{&r>VmS~H`(s9nxy>z{Tg>tc3u++&A(lc3NYx^`T3J_ARtZMsbChtN+v+6es^a2WuauBlhc;>%A#%C5QbWa+ zs+QtP@TAsK1y!Co)HtyA)!IFx6(Vd2DN+Z02S1D zO2^8dp{^+K5L{R`w!C`e@N(Hr$RZ#_@@@tFA&}FcQeDo1<&4)FW%Py}*?$c!Q2~rSzgD(QY9c>B zck<;qWVO=tW!<&yvebByG80;mp_Em^km)Z^P3tGI%e@7a_YNeKYTs|wMdWfj$PYrOf@_!ScmY>Y&lTMOxE zHbBRbOr)ZDQblT9)zbKpojh`QfwBRNhy3EX)bL8FM8!mrmem%KNOCF&Sd9l$6KboW z8KCyP(E_1YrGxcwa@iZ>w?Jg zDWk%RfmTf~ObDIKw;fKkYAU7~*K-kuU};&U*PM0HD_{v;NXYT6lWac}+41a4~Q{rL7P)?e2YySr( zGDxHafLT|;u=N;M;+c?MI^{xXE}fw(`dR!jsgz-2|4IEQyo=QQc0LL+8LL-N=XKtOcC(%}gMxvY{{rJme+uPn)zt8-{p^;&}Qv^*P)Z=6M{S>C{Ob zAlvYJ6dTyr!BoA>{|z$8eDmv_qs?S)AZx0b)Dbejo;fvTAG6FDvcaj-nguVkxQz=! z)9ER?hC-*VVOk(dC$BZL#NxX*I5jXUfTxqQgYh(ANnD6a@Il(r`L}33Go3nFZe~es zIW@F2fT)xD3`eQesaY0j%vnyItTD5kcd?W^S=t7t&d@9zce1-!j}7cxCNnK2T0Y0^ zzy%KtYYCm`U0I+rbS0WV!&-iqWHhwL2B*%^;)LDBz$^_#9Y}PeC6Q+6xI;;#Va>)R z^NGt1!8WJ&PoC9^n(5TZS9DfBb8565I&Y>^CpDVV{I|g!tBVc=sB}{AkC^>+4(5$c zjmgZP%HbZTPDYwpAii;fQ$w01_b}%Xv&Qdq%{QEjc0&NorWrPz5$7_rQ7&^HGkKjd z-?jz!7#$!}E^~fvBAqbbVm=0p2EH^ioeNy|*{IKThGvbis$11vH^0!?%S>7gEyOR# zn|T_|K6Ekbv*8?6mCc-KCi(=;^=9WZGg%hMDmRl=Ru*%PG1D5ImpHFCvn+W^SWd8Q z>HOO@o0(3XyhCT*=+sHQ6Q(R;PB5eUOzd@<3R9lWd&tUjK58Z(4`k`&GiH{U&o?+V z@T`T${w=sVo&P6YKGUg_dK=9&Ta9@{W6pBwZIN*Hk+q0M`~eQ zRBdRkF|?!1Awij%J)g;}sxqzG0~|G;XjhNUZC8(#N%iQz>JH*bzt5|eW5)q=yy+>$ zp+`-k)?nz+Vh%kc)o2vGgRHL*$#X!f3aykrX0sexCjE8{GE1~FA>dDZuouss!8i0H zurWKyGwEEw)4 zhI~jXHulBYkZgIrf&()AHLcRy8dH7r3vnEJe%I8qawxG6-w7YObVYo$b!y43?*t#& zz&_VbJSLye|MR;*;s^Ry_i}^GKi7VKZSv9oHyEJ&ynrW%ow&v;4s=#TpI!LkpJcJw zA$CZ=!`qSG4gkNS{G*-ZpXel?)ZP)FZ#uz;kR9Sjbduk#ll;#5r5Er!>X$*C@S*?l z#aUpSPQq<}{pqM(6M#=MqW&>;jXTZE51j|RGT(O2{6PQMghtHtkp5a>;)l*N4|amz ziu_oNixw4)*A<1Jimk@of+0V?^UW-1z8*S#_MTUV7oioyhE-Mlr zy{zc-#=FdXy{b%7=xmyquU!OvzE^DK7n<_u^U(_A$C7^jqUtr-umxuRv5!`hdFzeM3c#6qrmzn>H*)Qwqz!RT0%zV9mr>Sg4|6z*S zr2`*5uVPQx>%nPAWpP=_+?oQMw#btpuNT`K#Whtp6ZFo{Kr!~yYpSa8Z(1kbF!h@0 z(~t<=)Ume2 zuxi?bD{}I4rcTVyHxEpJ+5Y4tWHZ0R4Sy2DJOfbYBR_FwqK{zOqv>4pfT_AlZYcG! zHs&w8a$-(?_Ke)zoN36rX5xhD6Y{fj@+MD(@K6R0iVBL**Vx4N%qh$-Dz9CD)6#QK zt2#RQ!A_PZs7EZ@Ks})+haDV_DD?w3`*2?o>95ty;O;%BWGdH!bX$n|X z?X4VU?s$W`U4!zy^5lxzMK)}naI5~sug;=vbp?fZ)5&-2v zq%JBftnuEa5zBF&rPHPuiUWkz`GiAfkQQ9!p@UhgvYN^g1)D?tKlMrmHO+kHv}gJ2 zdVc?9_x9{Dt+e~30wQ|aKBSNK>n9Ood^BGL;V*a01kupv0(>b=7i8(9{r{^>dfcFD z_X&kFQA*yjrq}ED^(MVu7c>)HzkXke0`jUgz4jwYO?r*j8T~I%5G=p;PpVD&V84cV zgz}?bZwjW@@yQG3L_UOwfpe!I0k<-oz9z&L}(tB4M|rR4~H0Bi1@6r6Z*gORrD*gW23-x z>hgC&KXaBMSQiprE+%Zo_S@B4KQ*0x(+`d5w8o+L@?{EY>ZE>+`wlsS_e*k3Tv0?xK diff --git a/script/testdata/exec_configurable_callee.c b/script/testdata/exec_configurable_callee.c index d03bdd7948..3cc60abe3a 100644 --- a/script/testdata/exec_configurable_callee.c +++ b/script/testdata/exec_configurable_callee.c @@ -25,9 +25,9 @@ * - The `code_hash`(`data_hash`) of a shared library. */ -#include "stdbool.h" #include "ckb_dlfcn.h" #include "ckb_syscalls.h" +#include "stdbool.h" #ifdef DEBUG #include @@ -40,73 +40,74 @@ char message[2048]; #define EXEC_ARGC 9 #define BUFFER_SIZE 32768 -typedef uint64_t(arithmetic_func_t) (uint64_t); +typedef uint64_t(arithmetic_func_t)(uint64_t); uint8_t CODE_BUFFER[BUFFER_SIZE] __attribute__((aligned(RISCV_PGSIZE))); -void try_pause() { - syscall(2178, 0, 0, 0, 0, 0, 0); -} +void try_pause() { syscall(2178, 0, 0, 0, 0, 0, 0); } -void from_hex (uint8_t* dst, char* src, size_t len) { - for (size_t i=0; i> 6) * 9) << 4) | (((lo & 0xf) + (lo >> 6) * 9)); } } void to_hex(char* dst, uint8_t* src, size_t len) { - for (size_t i = 0; i> 4; char lo = src[i] & 0xf; - dst[i*2] = hi + (hi < 10 ? '0' : ('a' - 10)); - dst[i*2+1] = lo + (lo < 10 ? '0' : ('a' - 10)); + dst[i * 2] = hi + (hi < 10 ? '0' : ('a' - 10)); + dst[i * 2 + 1] = lo + (lo < 10 ? '0' : ('a' - 10)); } - dst[len*2] = '\0'; + dst[len * 2] = '\0'; } -volatile uint64_t read_u64_le_from_hex (char* src) { +volatile uint64_t read_u64_le_from_hex(char* src) { uint8_t bytes[8]; from_hex(bytes, src, 8); - return *(const uint64_t *)bytes; + return *(const uint64_t*)bytes; } -void write_u64_le_to_hex (char* dst, uint64_t number) { - uint8_t* bytes = (uint8_t *)(&number); +void write_u64_le_to_hex(char* dst, uint64_t number) { + uint8_t* bytes = (uint8_t*)(&number); to_hex(dst, bytes, 8); } -int try_exec(char*argv[], uint64_t recursion, uint64_t number) { - sprintf(message, "argv[4] = %s", argv[4]); ckb_debug(message); - if (strlen(argv[4]) != 8*2) { +int try_exec(char* argv[], uint64_t recursion, uint64_t number) { + sprintf(message, "argv[4] = %s", argv[4]); + ckb_debug(message); + if (strlen(argv[4]) != 8 * 2) { return -21; } uint64_t index = read_u64_le_from_hex(argv[4]); - sprintf(message, "argv[5] = %s", argv[5]); ckb_debug(message); - if (strlen(argv[5]) != 8*2) { + sprintf(message, "argv[5] = %s", argv[5]); + ckb_debug(message); + if (strlen(argv[5]) != 8 * 2) { return -22; } uint64_t source = read_u64_le_from_hex(argv[5]); - sprintf(message, "argv[6] = %s", argv[6]); ckb_debug(message); - if (strlen(argv[6]) != 8*2) { + sprintf(message, "argv[6] = %s", argv[6]); + ckb_debug(message); + if (strlen(argv[6]) != 8 * 2) { return -23; } uint64_t place = read_u64_le_from_hex(argv[6]); - sprintf(message, "argv[7] = %s", argv[7]); ckb_debug(message); - if (strlen(argv[7]) != 8*2) { + sprintf(message, "argv[7] = %s", argv[7]); + ckb_debug(message); + if (strlen(argv[7]) != 8 * 2) { return -24; } uint64_t bounds = read_u64_le_from_hex(argv[7]); - char recursion_str[8*2+1]; - char number_str[8*2+1]; - char *argv_new[EXEC_ARGC] = { - argv[0], recursion_str, number_str, argv[3], - argv[4], argv[5], argv[6], argv[7], argv[8] }; + char recursion_str[8 * 2 + 1]; + char number_str[8 * 2 + 1]; + char* argv_new[EXEC_ARGC] = {argv[0], recursion_str, number_str, argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8]}; write_u64_le_to_hex(recursion_str, recursion); write_u64_le_to_hex(number_str, number); try_pause(); @@ -115,7 +116,7 @@ int try_exec(char*argv[], uint64_t recursion, uint64_t number) { } int try_load_code(uint64_t* number, uint8_t* code_hash) { - void *handle = NULL; + void* handle = NULL; uint64_t consumed_size = 0; uint8_t hash_type = 0; int ret = ckb_dlopen2(code_hash, hash_type, CODE_BUFFER, BUFFER_SIZE, &handle, &consumed_size); @@ -123,7 +124,7 @@ int try_load_code(uint64_t* number, uint8_t* code_hash) { return -31; } try_pause(); - arithmetic_func_t* func = (arithmetic_func_t*) ckb_dlsym(handle, "apply"); + arithmetic_func_t* func = (arithmetic_func_t*)ckb_dlsym(handle, "apply"); if (func == NULL) { return -32; } @@ -132,54 +133,62 @@ int try_load_code(uint64_t* number, uint8_t* code_hash) { return CKB_SUCCESS; } -int main (int argc, char *argv[]) { - sprintf(message, "argc = %d", argc); ckb_debug(message); +int main(int argc, char* argv[]) { + sprintf(message, "argc = %d", argc); + ckb_debug(message); if (argc != EXEC_ARGC) { return -11; } - sprintf(message, "argv[0] = %s", argv[0]); ckb_debug(message); - if (strlen(argv[0]) != 1*2) { + sprintf(message, "argv[0] = %s", argv[0]); + ckb_debug(message); + if (strlen(argv[0]) != 1 * 2) { return -12; } uint8_t flag; from_hex(&flag, argv[0], 1); - bool if_write_stack = (flag & 0b0010) == 0b0010; + bool if_write_stack = (flag & 0b0010) == 0b0010; if (if_write_stack) { - sprintf(message, "(try update the stack)"); ckb_debug(message); - sprintf(message, "W in [%p, %p)", CODE_BUFFER, CODE_BUFFER+BUFFER_SIZE); ckb_debug(message); - for (int i=0; i 0) { - try_exec(argv, recursion-1, number-1); + try_exec(argv, recursion - 1, number - 1); } - sprintf(message, "argv[3] = %s", argv[3]); ckb_debug(message); - if (strlen(argv[3]) != 8*2) { + sprintf(message, "argv[3] = %s", argv[3]); + ckb_debug(message); + if (strlen(argv[3]) != 8 * 2) { return -15; } uint64_t expected = read_u64_le_from_hex(argv[3]); - bool if_load_after_exec = (flag & 0b0100) == 0b0100; + bool if_load_after_exec = (flag & 0b0100) == 0b0100; if (if_load_after_exec) { - sprintf(message, "argv[8] = %s", argv[8]); ckb_debug(message); - if (strlen(argv[8]) != 32*2) { + sprintf(message, "argv[8] = %s", argv[8]); + ckb_debug(message); + if (strlen(argv[8]) != 32 * 2) { return -16; } uint8_t code_hash[32]; @@ -188,7 +197,8 @@ int main (int argc, char *argv[]) { if (ret != CKB_SUCCESS) { return ret; } - sprintf(message, "(apply after exec) number = %ld", number); ckb_debug(message); + sprintf(message, "(apply after exec) number = %ld", number); + ckb_debug(message); } if (number == expected) { diff --git a/script/testdata/exec_configurable_caller b/script/testdata/exec_configurable_caller index 80d9137fcd2b29d0338378ba4a86cc4bc14a5ccf..9cb002df3526c7c5b23c7bf7e074fed867b62f7d 100755 GIT binary patch delta 4627 zcma)Ae^e7!_P;N~WD<~H4T4&W$OtHHSv6{{TeIMnWbOB?cCBLT5&6Osg7pWA3gVuc zAG1S<2vnaCfvVNC>awkeniX2zb!%;jKTg$lD|otHzTzmMt_o#^h+^0`Bvjk;{bMKR zX5Ra}_wK##-p`%P%csW`_vgGlCMho%fqbP7e*@ef=WobpD$E82{SF58&Rm1X3;jN4hC7{SewiR>8HhM?agQ%MW) z_J#A%2U_k6aE5z*c0GR766~Z1kEl?@8RqrX>TxecWrX$)=<&lA73u2>uXl)a<-4h& zbJ2upfKjUKEz#r}N;rJlT)&Mj4H4qXBJl$?XLek%% zepeaPPbh<@_m@Jw>1r8z`t>qY-&%_5_t`+ZZUwly?jvn}7jkvBB0kQI`1lyaPvX#G zcN&+*NHIwdi7g6taWkW}%A!)Eup41121@hH!lUJ*^79K2RSWmh_||t(`tkRtj1;o zrx1fMt4b8y33L@zMU%mtr8z}j>ZB2z5QBD7qXuvy4&f?gtekhDWi;4X-t3{8+dyMW z0(FZ(aUQ&ov&r-9DP4 zBAT9Jnx0}gJv+}cM_BmAlr}N!0LwoYHpHj2`y$^M;>@y(C3Qqy*Gb0&b)Pbjbt+A?e>T z0TCr2q69>y`m2^n1f4hk2wb?6fLUXjSk} zRK??p;Hg8HI^?7daVA<467@($JyKDRl&JnHy}wTTt+c(5`>z}tsfZV!sE8|{=xkH| zsuf9n;; zsAPgOzoDFBSx$;#h9bsDF>W8<*beec4MJD=sg`7ZYT6WjMr1Po(oWN4e)dG#nKp%g z>32!|?Cd0d#)c$1DTxjy@Ussj@H0M27${`ljNUox54c;uRA=97IJN^naA#n|ETq)pxxpTDKr}VK-IJ2U*iU%d-pOV%Zy;GU)_@SPUyX=iQT9jrAPE39;Yc)Upwa51KQA+)3l`? z;Qz7%JzB~)e!!f%*4;C7tDyodq(7OH)kck|zCk!H?rmsr5K-Ns72UKTxHuZ+pra;- zi*`%%d|h&gEe4`GZygDAOJ02_3%EXXl1ACX;G)(^Oh$GHQJNVX(K<=UI1qy0>F0$E zOGug?8(ZUrC8tB=pG=(H6tAhC1*0p}`C%*(?HvubiCx{LVO4P&1_dps9#^elRB$JEH>RUnr*1TJfDDlTOcNmbtv`M*mbhHKguGNk$v;Ak#NYdZ!wXK55R z-kF4b2Q^xDIp8-%4OX#FF->;BxPP9|q*gpr$utLFJ5@teC#@AfQWquQNH*0~wFL0S zA+)WEX)|s2h|NM%In!alj{Y#AIYhxUm7`39tF=ury=T^Kyv6(6K#``r^x8nNJx?>7 zd1c(3nmv?E#AcJ`+@ED5rOLQdHSa)^LpLaA_FI`3&d7KJt8y*!`2%U_1}tGb`Y@Frl1Jw2zDuH@A6>=U*w?aMt9FbcYFa>FPkPbZ->4Y z`syu71AqTxradQmr%9moxK3ndpk!f&WeW2mnj*Ytnas>VlZ82!B<7bWN%*BDk$DLv z3NKj_n7JrHm}{9tEBRTgnWjx4-N|~uG}H8PUZks(Iz10+FFcC*NDw(v#<_HD953$Y=nq(AJ=KN#