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

Add test: read\write cycles #23

Merged
merged 3 commits into from
Apr 25, 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
52 changes: 52 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 @@ -1268,3 +1268,55 @@ fn check_spawn_cycles() {
assert_eq!(result.unwrap(), 1524861);
}
}

fn spawn_io_test(io_size: u64, enable_check: bool) -> Result<u64, Error> {
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);
}
4 changes: 3 additions & 1 deletion script/testdata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Binary file added script/testdata/spawn_io_cycles
Binary file not shown.
109 changes: 109 additions & 0 deletions script/testdata/spawn_io_cycles.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <stdint.h>
#include <string.h>

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