Skip to content

Commit

Permalink
Upgrade for new spawn (#86)
Browse files Browse the repository at this point in the history
* Upgrade for new spawn

* Fix make test
  • Loading branch information
mohanson authored May 15, 2024
1 parent 252afa9 commit d63fe58
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 142 deletions.
7 changes: 4 additions & 3 deletions contracts/spawn-callee/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ use ckb_std::syscalls;
use core::result::Result;

pub fn main() -> Result<(), Error> {
assert_eq!(syscalls::get_memory_limit(), 8);
let argv = ckb_std::env::argv();
ckb_std::debug!("argv: {:?}", argv);
let mut std_fds: [u64; 2] = [0; 2];
syscalls::inherited_file_descriptors(&mut std_fds);
let mut out = vec![];
for arg in argv {
out.extend_from_slice(arg.to_bytes());
}
syscalls::set_content(&out)?;
let len = syscalls::write(std_fds[1], &out)?;
assert_eq!(len, 10);
Ok(())
}
16 changes: 10 additions & 6 deletions contracts/spawn-callee/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ pub enum Error {
ItemMissing,
LengthNotEnough,
Encoding,
SpawnExceededMaxContentLength,
SpawnWrongMemoryLimit,
SpawnExceededMaxPeakMemory,
WaitFailure,
InvalidFd,
OtherEndClosed,
MaxVmsSpawned,
MaxFdsCreated,
}

impl From<SysError> for Error {
Expand All @@ -20,9 +22,11 @@ impl From<SysError> for Error {
ItemMissing => Self::ItemMissing,
LengthNotEnough(_) => Self::LengthNotEnough,
Encoding => Self::Encoding,
SpawnExceededMaxContentLength => Self::SpawnExceededMaxContentLength,
SpawnWrongMemoryLimit => Self::SpawnWrongMemoryLimit,
SpawnExceededMaxPeakMemory => Self::SpawnExceededMaxPeakMemory,
WaitFailure => Self::WaitFailure,
InvalidFd => Self::InvalidFd,
OtherEndClosed => Self::OtherEndClosed,
MaxVmsSpawned => Self::MaxVmsSpawned,
MaxFdsCreated => Self::MaxFdsCreated,
Unknown(err_code) => panic!("unexpected sys error {}", err_code),
}
}
Expand Down
39 changes: 22 additions & 17 deletions contracts/spawn-caller-by-code-hash/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
// Import from `core` instead of from `std` since we are in no-std mode
use crate::error::Error;
use alloc::vec;
use ckb_std::ckb_constants::Source;
use ckb_std::ckb_types::core::ScriptHashType;
use ckb_std::high_level::{load_script, spawn_cell};
use ckb_std::syscalls;
use core::ffi::CStr;
use core::result::Result;

pub fn main() -> Result<(), Error> {
let arg1 = CStr::from_bytes_with_nul(b"hello\0").unwrap();
let arg2 = CStr::from_bytes_with_nul(b"world\0").unwrap();
let argv = [
CStr::from_bytes_with_nul(b"hello\0").unwrap(),
CStr::from_bytes_with_nul(b"world\0").unwrap(),
];
let mut std_fds: [u64; 2] = [0, 0];
let mut son_fds: [u64; 3] = [0, 0, 0];
let (r0, w0) = syscalls::pipe()?;
std_fds[0] = r0;
son_fds[1] = w0;
let (r1, w1) = syscalls::pipe()?;
std_fds[1] = w1;
son_fds[0] = r1;
let code_hash = load_script().unwrap().args().raw_data();
ckb_std::debug!("code_hash: {:?}", code_hash);

let mut content = vec![0; 80];
let ret = spawn_cell(
&code_hash[..],
ScriptHashType::Data1,
&[arg1, arg2][..],
8,
&mut content,
spawn_cell(&code_hash[..], ScriptHashType::Data1, &argv, &son_fds)?;
let mut buf: [u8; 256] = [0; 256];
let len = syscalls::read(std_fds[0], &mut buf)?;
assert_eq!(len, 10);
buf[len] = 0;
assert_eq!(
CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(),
"helloworld"
);
assert!(ret == Ok(0));
assert!(content.len() == 10);
content.resize(content.len() + 1, 0);
let c_str = CStr::from_bytes_until_nul(&content).unwrap();
assert_eq!(c_str.to_str().unwrap(), "helloworld");
Ok(())
}
16 changes: 10 additions & 6 deletions contracts/spawn-caller-by-code-hash/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ pub enum Error {
ItemMissing,
LengthNotEnough,
Encoding,
SpawnExceededMaxContentLength,
SpawnWrongMemoryLimit,
SpawnExceededMaxPeakMemory,
WaitFailure,
InvalidFd,
OtherEndClosed,
MaxVmsSpawned,
MaxFdsCreated,
}

impl From<SysError> for Error {
Expand All @@ -20,9 +22,11 @@ impl From<SysError> for Error {
ItemMissing => Self::ItemMissing,
LengthNotEnough(_) => Self::LengthNotEnough,
Encoding => Self::Encoding,
SpawnExceededMaxContentLength => Self::SpawnExceededMaxContentLength,
SpawnWrongMemoryLimit => Self::SpawnWrongMemoryLimit,
SpawnExceededMaxPeakMemory => Self::SpawnExceededMaxPeakMemory,
WaitFailure => Self::WaitFailure,
InvalidFd => Self::InvalidFd,
OtherEndClosed => Self::OtherEndClosed,
MaxVmsSpawned => Self::MaxVmsSpawned,
MaxFdsCreated => Self::MaxFdsCreated,
Unknown(err_code) => panic!("unexpected sys error {}", err_code),
}
}
Expand Down
46 changes: 30 additions & 16 deletions contracts/spawn-caller/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,36 @@ use core::ffi::CStr;
use core::result::Result;

pub fn main() -> Result<(), Error> {
let arg1 = CStr::from_bytes_with_nul(b"hello\0").unwrap();
let arg2 = CStr::from_bytes_with_nul(b"world\0").unwrap();

let mut spgs_exit_code: i8 = 0;
let mut spgs_content = [0u8; 80];
let mut spgs_content_length: u64 = 80;
let spgs = syscalls::SpawnArgs {
memory_limit: 8,
exit_code: &mut spgs_exit_code as *mut i8,
content: &mut spgs_content as *mut u8,
content_length: &mut spgs_content_length as *mut u64,
let argc: u64 = 2;
let argv = {
let mut argv = alloc::vec![core::ptr::null(); argc as usize + 1];
argv[0] = CStr::from_bytes_with_nul(b"hello\0").unwrap().as_ptr();
argv[1] = CStr::from_bytes_with_nul(b"world\0").unwrap().as_ptr();
argv
};
let mut std_fds: [u64; 2] = [0, 0];
let mut son_fds: [u64; 3] = [0, 0, 0];
let (r0, w0) = syscalls::pipe()?;
std_fds[0] = r0;
son_fds[1] = w0;
let (r1, w1) = syscalls::pipe()?;
std_fds[1] = w1;
son_fds[0] = r1;
let mut pid: u64 = 0;
let mut spgs = syscalls::SpawnArgs {
argc: argc,
argv: argv.as_ptr(),
process_id: &mut pid as *mut u64,
inherited_fds: son_fds.as_ptr(),
};
let ret = syscalls::spawn(1, Source::CellDep, 0, &[arg1, arg2][..], &spgs);
assert!(ret == 0);
assert!(spgs_exit_code == 0);
let c_str = CStr::from_bytes_until_nul(&spgs_content).unwrap();
assert_eq!(c_str.to_str().unwrap(), "helloworld");
syscalls::spawn(1, Source::CellDep, 0, 0, &mut spgs)?;
let mut buf: [u8; 256] = [0; 256];
let len = syscalls::read(std_fds[0], &mut buf)?;
assert_eq!(len, 10);
buf[len] = 0;
assert_eq!(
CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(),
"helloworld"
);
Ok(())
}
16 changes: 10 additions & 6 deletions contracts/spawn-caller/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ pub enum Error {
ItemMissing,
LengthNotEnough,
Encoding,
SpawnExceededMaxContentLength,
SpawnWrongMemoryLimit,
SpawnExceededMaxPeakMemory,
WaitFailure,
InvalidFd,
OtherEndClosed,
MaxVmsSpawned,
MaxFdsCreated,
}

impl From<SysError> for Error {
Expand All @@ -20,9 +22,11 @@ impl From<SysError> for Error {
ItemMissing => Self::ItemMissing,
LengthNotEnough(_) => Self::LengthNotEnough,
Encoding => Self::Encoding,
SpawnExceededMaxContentLength => Self::SpawnExceededMaxContentLength,
SpawnWrongMemoryLimit => Self::SpawnWrongMemoryLimit,
SpawnExceededMaxPeakMemory => Self::SpawnExceededMaxPeakMemory,
WaitFailure => Self::WaitFailure,
InvalidFd => Self::InvalidFd,
OtherEndClosed => Self::OtherEndClosed,
MaxVmsSpawned => Self::MaxVmsSpawned,
MaxFdsCreated => Self::MaxFdsCreated,
Unknown(err_code) => panic!("unexpected sys error {}", err_code),
}
}
Expand Down
18 changes: 13 additions & 5 deletions src/ckb_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,23 @@ pub const SYS_LOAD_CELL_DATA_AS_CODE: u64 = 2091;
pub const SYS_LOAD_CELL_DATA: u64 = 2092;
pub const SYS_DEBUG: u64 = 2177;
#[cfg(feature = "ckb2023")]
pub const SYS_SPAWN: u64 = 2101;
pub const SYS_SPAWN: u64 = 2601;
#[cfg(feature = "ckb2023")]
pub const SYS_GET_MEMORY_LIMIT: u64 = 2102;
pub const SYS_WAIT: u64 = 2602;
#[cfg(feature = "ckb2023")]
pub const SYS_SET_CONTENT: u64 = 2103;
pub const SYS_PROCESS_ID: u64 = 2603;
#[cfg(feature = "ckb2023")]
pub const SYS_LOAD_BLOCK_EXTENSION: u64 = 2104;
pub const SYS_PIPE: u64 = 2604;
#[cfg(feature = "ckb2023")]
pub const SYS_WRITE: u64 = 2605;
#[cfg(feature = "ckb2023")]
pub const SYS_READ: u64 = 2606;
#[cfg(feature = "ckb2023")]
pub const SYS_CURRENT_MEMORY: u64 = 2105;
pub const SYS_INHERITED_FD: u64 = 2607;
#[cfg(feature = "ckb2023")]
pub const SYS_CLOSE: u64 = 2608;
#[cfg(feature = "ckb2023")]
pub const SYS_LOAD_BLOCK_EXTENSION: u64 = 2104;

pub const CKB_SUCCESS: u64 = 0;
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
Expand Down
18 changes: 12 additions & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ pub enum SysError {
/// Data encoding error
Encoding,

/// Failed to wait. Its value is 5.
#[cfg(feature = "ckb2023")]
/// Content Length must be less than 256K.
SpawnExceededMaxContentLength,
WaitFailure,
/// Invalid file descriptor. Its value is 6.
#[cfg(feature = "ckb2023")]
/// MemoryLimit is between 1 and 8.
SpawnWrongMemoryLimit,
InvalidFd,
/// Reading from or writing to file descriptor failed due to other end closed. Its value is 7.
#[cfg(feature = "ckb2023")]
/// There is a maximum call depth limit by peak memory.
SpawnExceededMaxPeakMemory,
OtherEndClosed,
/// Max vms has been spawned. Its value is 8.
#[cfg(feature = "ckb2023")]
MaxVmsSpawned,
/// Max fds has been spawned. Its value is 9.
#[cfg(feature = "ckb2023")]
MaxFdsCreated,

/// Unknown syscall error number
Unknown(u64),
Expand Down
45 changes: 16 additions & 29 deletions src/high_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,40 +680,27 @@ pub fn exec_cell(
/// - CString::new("arg0").unwrap().as_c_str();
/// - if you want to pass a piece of bytes data, you may encode it to hexadecimal string or other format:
/// - high_level::encode_hex(&vec![0xff, 0xfe, 0xfd]);
/// * `memory_limit` - a number between 1 and 8.
/// - note each tick represents an additional 0.5M of memory.
/// * `content` - a buffer to saving the output by sub script.
/// - note the size of content will be shrinked after call.
/// * `inherited_fds` - the fd list to be passed to the child process.
#[cfg(feature = "ckb2023")]
pub fn spawn_cell(
code_hash: &[u8],
hash_type: ScriptHashType,
argv: &[&CStr],
memory_limit: u64,
content: &mut Vec<u8>,
) -> Result<i8, SysError> {
inherited_fds: &[u64],
) -> Result<u64, SysError> {
let index = look_for_dep_with_hash2(code_hash, hash_type)?;
let mut content_length = content.len() as u64;
let mut exit_code = 0i8;
let spgs = syscalls::SpawnArgs {
memory_limit,
exit_code: &mut exit_code as *mut i8,
content: content.as_mut_ptr(),
content_length: &mut content_length as *mut u64,
};
let ret = syscalls::spawn(index, Source::CellDep, 0, argv, &spgs);
match ret {
0 => {
content.truncate(content_length as usize);
Ok(exit_code)
}
1 => Err(SysError::IndexOutOfBound),
2 => Err(SysError::ItemMissing),
3 => Err(SysError::LengthNotEnough(content.len())),
4 => Err(SysError::Encoding),
5 => Err(SysError::SpawnExceededMaxContentLength),
6 => Err(SysError::SpawnWrongMemoryLimit),
7 => Err(SysError::SpawnExceededMaxPeakMemory),
r => Err(SysError::Unknown(r)),
let argc = argv.len();
let mut process_id: u64 = 0;
let mut argv_ptr = alloc::vec![core::ptr::null(); argc + 1];
for (idx, cstr) in argv.into_iter().enumerate() {
argv_ptr[idx] = cstr.as_ptr();
}
let mut spgs = syscalls::SpawnArgs {
argc: argc as u64,
argv: argv_ptr.as_ptr(),
process_id: &mut process_id as *mut u64,
inherited_fds: inherited_fds.as_ptr(),
};
syscalls::spawn(index, Source::CellDep, 0, 0, &mut spgs)?;
Ok(process_id)
}
Loading

0 comments on commit d63fe58

Please sign in to comment.