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

feat(script): add current_memory syscall #4063

Merged
merged 2 commits into from
Jul 10, 2023
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
30 changes: 30 additions & 0 deletions script/src/syscalls/current_memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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<Mac: SupportMachine> Syscalls<Mac> for CurrentMemory {
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() != CURRENT_MEMORY {
return Ok(false);
}
machine.set_register(A0, Mac::REG::from_u64(self.value));
Ok(true)
}
}
3 changes: 3 additions & 0 deletions script/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod current_cycles;
mod current_memory;
mod debugger;
mod exec;
mod get_memory_limit;
Expand All @@ -23,6 +24,7 @@ mod pause;
mod tests;

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;
Expand Down Expand Up @@ -77,6 +79,7 @@ pub const SPAWN: u64 = 2101;
pub const GET_MEMORY_LIMIT: u64 = 2102;
pub const SET_CONTENT: u64 = 2103;
pub const LOAD_EXTENSION: u64 = 2104;
pub const CURRENT_MEMORY: u64 = 2105;
pub const DEBUG_PRINT_SYSCALL_NUMBER: u64 = 2177;
#[cfg(test)]
pub const DEBUG_PAUSE: u64 = 2178;
Expand Down
3 changes: 3 additions & 0 deletions script/src/syscalls/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ pub fn build_child_machine<
*callee_peak_memory,
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)
Expand Down
12 changes: 9 additions & 3 deletions script/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::{
error::{ScriptError, TransactionScriptError},
syscalls::{
spawn::{build_child_machine, update_caller_machine},
CurrentCycles, Debugger, Exec, GetMemoryLimit, LoadCell, LoadCellData, LoadExtension,
LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, LoadWitness, SetContent, Spawn,
VMVersion,
CurrentCycles, CurrentMemory, Debugger, Exec, GetMemoryLimit, LoadCell, LoadCellData,
LoadExtension, LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, LoadWitness,
SetContent, Spawn, VMVersion,
},
type_id::TypeIdSystemScript,
types::{
Expand Down Expand Up @@ -257,6 +257,11 @@ impl<DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + C
)
}

/// Build syscall: current_memory
pub fn build_current_memory(&self, current_memory: u64) -> CurrentMemory {
CurrentMemory::new(current_memory)
}

/// Generate same syscalls. The result does not contain spawn syscalls.
pub fn generate_same_syscalls(
&self,
Expand Down Expand Up @@ -323,6 +328,7 @@ impl<DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + C
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, Arc::clone(&context))),
Box::new(self.build_current_memory(8)),
])
}
syscalls
Expand Down
32 changes: 32 additions & 0 deletions script/src/verify/tests/ckb_latest/features_since_v2023.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::verify::{tests::utils::*, *};
// check_peak_memory_2m_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.

#[test]
fn check_vm_version() {
Expand Down Expand Up @@ -679,3 +680,34 @@ fn check_spawn_state() {
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);
}
4 changes: 3 additions & 1 deletion script/testdata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ ALL_BINS := jalr_zero \
spawn_caller_strcat_wrap \
spawn_caller_strcat \
spawn_caller_strcat_data_hash \
spawn_recursive
spawn_recursive \
spawn_current_memory
ALL_LIBS := is_even.lib \
add1.lib sub1.lib mul2.lib div2.lib

Expand Down Expand Up @@ -154,3 +155,4 @@ spawn_caller_strcat_data_hash: spawn_caller_strcat_data_hash.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
Binary file added script/testdata/spawn_current_memory
Binary file not shown.
28 changes: 28 additions & 0 deletions script/testdata/spawn_current_memory.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <stdint.h>
#include <string.h>

#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;
}
}
Loading