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