Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite some syscalls #10

Merged
merged 7 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions script/src/syscalls/close.rs
Original file line number Diff line number Diff line change
@@ -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<Mutex<Vec<Message>>>,
}

impl Close {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
}
}

impl<Mac: SupportMachine> Syscalls<Mac> for Close {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}

fn ecall(&mut self, machine: &mut Mac) -> Result<bool, VMError> {
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()))
}
}
7 changes: 5 additions & 2 deletions script/src/syscalls/current_cycles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Mutex<u64>>,
}

impl CurrentCycles {
pub fn new(base: u64) -> Self {
pub fn new(base: Arc<Mutex<u64>>) -> Self {
Self { base }
}
}
Expand All @@ -26,6 +27,8 @@ impl<Mac: SupportMachine> Syscalls<Mac> 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));
Expand Down
46 changes: 46 additions & 0 deletions script/src/syscalls/inherited_fd.rs
Original file line number Diff line number Diff line change
@@ -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<Mutex<Vec<Message>>>,
}

impl InheritedFd {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
}
}

impl<Mac: SupportMachine> Syscalls<Mac> for InheritedFd {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}

fn ecall(&mut self, machine: &mut Mac) -> Result<bool, VMError> {
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()))
}
}
25 changes: 23 additions & 2 deletions script/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,22 +14,29 @@ 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;

#[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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)]
Expand Down
44 changes: 44 additions & 0 deletions script/src/syscalls/pipe.rs
Original file line number Diff line number Diff line change
@@ -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<Mutex<Vec<Message>>>,
}

impl Pipe {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
}
}

impl<Mac: SupportMachine> Syscalls<Mac> for Pipe {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}

fn ecall(&mut self, machine: &mut Mac) -> Result<bool, VMError> {
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()))
}
}
30 changes: 30 additions & 0 deletions script/src/syscalls/process_id.rs
Original file line number Diff line number Diff line change
@@ -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<Mac: SupportMachine> Syscalls<Mac> for ProcessID {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}

fn ecall(&mut self, machine: &mut Mac) -> Result<bool, VMError> {
if machine.registers()[A7].to_u64() != PROCESS_ID {
return Ok(false);
}
machine.set_register(A0, Mac::REG::from_u64(self.id));
Ok(true)
}
}
62 changes: 62 additions & 0 deletions script/src/syscalls/read.rs
Original file line number Diff line number Diff line change
@@ -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<Mutex<Vec<Message>>>,
}

impl Read {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
}
}

impl<Mac: SupportMachine> Syscalls<Mac> for Read {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}

fn ecall(&mut self, machine: &mut Mac) -> Result<bool, VMError> {
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()))
}
}
5 changes: 2 additions & 3 deletions script/src/syscalls/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
));
Expand Down
2 changes: 1 addition & 1 deletion script/src/syscalls/tests/vm_latest/syscalls_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
44 changes: 44 additions & 0 deletions script/src/syscalls/wait.rs
Original file line number Diff line number Diff line change
@@ -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<Mutex<Vec<Message>>>,
}

impl Wait {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
}
}

impl<Mac: SupportMachine> Syscalls<Mac> for Wait {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}

fn ecall(&mut self, machine: &mut Mac) -> Result<bool, VMError> {
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()))
}
}
Loading
Loading