Skip to content

Commit

Permalink
Merge pull request #4803 from xxuejie/ckb-script-overhaul
Browse files Browse the repository at this point in the history
refactor: ckb-script package overhaul
  • Loading branch information
zhangsoledad authored Feb 17, 2025
2 parents 6621462 + 8b6654a commit 75e7b7e
Show file tree
Hide file tree
Showing 34 changed files with 1,327 additions and 1,278 deletions.
3 changes: 2 additions & 1 deletion script/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ mod verify_env;

pub use crate::error::{ScriptError, TransactionScriptError};
pub use crate::scheduler::{Scheduler, ROOT_VM_ID};
pub use crate::syscalls::generator::generate_ckb_syscalls;
pub use crate::types::{
ChunkCommand, CoreMachine, DataPieceId, RunMode, ScriptGroup, ScriptGroupType, ScriptVersion,
TransactionState, TxData, VerifyResult, VmIsa, VmState, VmVersion,
};
pub use crate::verify::{TransactionScriptsSyscallsGenerator, TransactionScriptsVerifier};
pub use crate::verify::TransactionScriptsVerifier;
pub use crate::verify_env::TxVerifyEnv;
237 changes: 130 additions & 107 deletions script/src/scheduler.rs

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions script/src/syscalls/close.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::syscalls::{CLOSE, SPAWN_YIELD_CYCLES_BASE};
use crate::types::{Fd, Message, VmId};
use crate::types::{Fd, Message, VmContext, VmId};
use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
use ckb_vm::{
registers::{A0, A7},
Error as VMError, Register, SupportMachine, Syscalls,
Expand All @@ -13,8 +14,14 @@ pub struct Close {
}

impl Close {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
pub fn new<DL>(vm_id: &VmId, vm_context: &VmContext<DL>) -> Self
where
DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
{
Self {
id: *vm_id,
message_box: Arc::clone(&vm_context.message_box),
}
}
}

Expand Down
22 changes: 15 additions & 7 deletions script/src/syscalls/current_cycles.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
use crate::syscalls::CURRENT_CYCLES;
use crate::{syscalls::CURRENT_CYCLES, types::VmContext};
use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
use ckb_vm::{
registers::{A0, A7},
Error as VMError, Register, SupportMachine, Syscalls,
};
use std::sync::{Arc, Mutex};
use std::sync::{
atomic::{AtomicU64, Ordering},
Arc,
};

#[derive(Debug, Default)]
pub struct CurrentCycles {
base: Arc<Mutex<u64>>,
base: Arc<AtomicU64>,
}

impl CurrentCycles {
pub fn new(base: Arc<Mutex<u64>>) -> Self {
Self { base }
pub fn new<DL>(vm_context: &VmContext<DL>) -> Self
where
DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
{
Self {
base: Arc::clone(&vm_context.base_cycles),
}
}
}

Expand All @@ -27,8 +36,7 @@ impl<Mac: SupportMachine> Syscalls<Mac> for CurrentCycles {
}
let cycles = self
.base
.lock()
.map_err(|e| VMError::Unexpected(e.to_string()))?
.load(Ordering::Acquire)
.checked_add(machine.cycles())
.ok_or(VMError::CyclesOverflow)?;
machine.set_register(A0, Mac::REG::from_u64(cycles));
Expand Down
17 changes: 11 additions & 6 deletions script/src/syscalls/debugger.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
use crate::types::DebugPrinter;
use crate::types::{
DebugContext, DebugPrinter, {SgData, SgInfo},
};
use crate::{cost_model::transferred_byte_cycles, syscalls::DEBUG_PRINT_SYSCALL_NUMBER};
use ckb_types::packed::Byte32;
use ckb_vm::{
registers::{A0, A7},
Error as VMError, Memory, Register, SupportMachine, Syscalls,
};
use std::sync::Arc;

pub struct Debugger {
hash: Byte32,
sg_info: Arc<SgInfo>,
printer: DebugPrinter,
}

impl Debugger {
pub fn new(hash: Byte32, printer: DebugPrinter) -> Debugger {
Debugger { hash, printer }
pub fn new<DL>(sg_data: &SgData<DL>, debug_context: &DebugContext) -> Debugger {
Debugger {
sg_info: Arc::clone(&sg_data.sg_info),
printer: Arc::clone(&debug_context.debug_printer),
}
}
}

Expand Down Expand Up @@ -46,7 +51,7 @@ impl<Mac: SupportMachine> Syscalls<Mac> for Debugger {
machine.add_cycles_no_checking(transferred_byte_cycles(buffer.len() as u64))?;
let s = String::from_utf8(buffer)
.map_err(|e| VMError::External(format!("String from buffer {e:?}")))?;
(self.printer)(&self.hash, s.as_str());
(self.printer)(&self.sg_info.script_hash, s.as_str());

Ok(true)
}
Expand Down
66 changes: 29 additions & 37 deletions script/src/syscalls/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::syscalls::{
Place, Source, SourceEntry, EXEC, INDEX_OUT_OF_BOUND, MAX_ARGV_LENGTH, SLICE_OUT_OF_BOUND,
WRONG_FORMAT,
};
use crate::types::Indices;
use crate::types::SgData;
use ckb_traits::CellDataProvider;
use ckb_types::core::cell::{CellMeta, ResolvedTransaction};
use ckb_types::core::cell::CellMeta;
use ckb_types::core::error::ARGV_TOO_LONG_TEXT;
use ckb_types::packed::{Bytes as PackedBytes, BytesVec};
use ckb_vm::memory::load_c_string_byte_by_byte;
Expand All @@ -15,62 +15,49 @@ use ckb_vm::{
Error as VMError, Register, SupportMachine, Syscalls,
};
use ckb_vm::{DEFAULT_STACK_SIZE, RISCV_MAX_MEMORY};
use std::sync::Arc;

#[derive(Debug)]
pub struct Exec<DL> {
data_loader: DL,
rtx: Arc<ResolvedTransaction>,
outputs: Arc<Vec<CellMeta>>,
group_inputs: Indices,
group_outputs: Indices,
sg_data: SgData<DL>,
}

impl<DL: CellDataProvider> Exec<DL> {
pub fn new(
data_loader: DL,
rtx: Arc<ResolvedTransaction>,
outputs: Arc<Vec<CellMeta>>,
group_inputs: Indices,
group_outputs: Indices,
) -> Exec<DL> {
impl<DL: CellDataProvider + Clone> Exec<DL> {
pub fn new(sg_data: &SgData<DL>) -> Exec<DL> {
Exec {
data_loader,
rtx,
outputs,
group_inputs,
group_outputs,
sg_data: sg_data.clone(),
}
}

#[inline]
fn resolved_inputs(&self) -> &Vec<CellMeta> {
&self.rtx.resolved_inputs
&self.sg_data.rtx.resolved_inputs
}

#[inline]
fn resolved_cell_deps(&self) -> &Vec<CellMeta> {
&self.rtx.resolved_cell_deps
&self.sg_data.rtx.resolved_cell_deps
}

#[inline]
fn witnesses(&self) -> BytesVec {
self.rtx.transaction.witnesses()
self.sg_data.rtx.transaction.witnesses()
}

fn fetch_cell(&self, source: Source, index: usize) -> Result<&CellMeta, u8> {
let cell_opt = match source {
Source::Transaction(SourceEntry::Input) => self.resolved_inputs().get(index),
Source::Transaction(SourceEntry::Output) => self.outputs.get(index),
Source::Transaction(SourceEntry::Output) => self.sg_data.outputs().get(index),
Source::Transaction(SourceEntry::CellDep) => self.resolved_cell_deps().get(index),
Source::Group(SourceEntry::Input) => self
.group_inputs
.sg_data
.group_inputs()
.get(index)
.and_then(|actual_index| self.resolved_inputs().get(*actual_index)),
Source::Group(SourceEntry::Output) => self
.group_outputs
.sg_data
.group_outputs()
.get(index)
.and_then(|actual_index| self.outputs.get(*actual_index)),
.and_then(|actual_index| self.sg_data.outputs().get(*actual_index)),
Source::Transaction(SourceEntry::HeaderDep)
| Source::Group(SourceEntry::CellDep)
| Source::Group(SourceEntry::HeaderDep) => {
Expand All @@ -84,11 +71,13 @@ impl<DL: CellDataProvider> Exec<DL> {
fn fetch_witness(&self, source: Source, index: usize) -> Result<PackedBytes, u8> {
let witness_opt = match source {
Source::Group(SourceEntry::Input) => self
.group_inputs
.sg_data
.group_inputs()
.get(index)
.and_then(|actual_index| self.witnesses().get(*actual_index)),
Source::Group(SourceEntry::Output) => self
.group_outputs
.sg_data
.group_outputs()
.get(index)
.and_then(|actual_index| self.witnesses().get(*actual_index)),
Source::Transaction(SourceEntry::Input) => self.witnesses().get(index),
Expand All @@ -102,7 +91,7 @@ impl<DL: CellDataProvider> Exec<DL> {
}
}

impl<Mac: SupportMachine, DL: CellDataProvider + Send + Sync> Syscalls<Mac> for Exec<DL> {
impl<Mac: SupportMachine, DL: CellDataProvider + Send + Sync + Clone> Syscalls<Mac> for Exec<DL> {
fn initialize(&mut self, _machine: &mut Mac) -> Result<(), VMError> {
Ok(())
}
Expand All @@ -126,12 +115,15 @@ impl<Mac: SupportMachine, DL: CellDataProvider + Send + Sync> Syscalls<Mac> for
return Ok(true);
}
let cell = cell.unwrap();
self.data_loader.load_cell_data(cell).ok_or_else(|| {
VMError::Unexpected(format!(
"Unexpected load_cell_data failed {}",
cell.out_point,
))
})?
self.sg_data
.data_loader()
.load_cell_data(cell)
.ok_or_else(|| {
VMError::Unexpected(format!(
"Unexpected load_cell_data failed {}",
cell.out_point,
))
})?
}
Place::Witness => {
let witness = self.fetch_witness(source, index as usize);
Expand Down
10 changes: 7 additions & 3 deletions script/src/syscalls/exec_v2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::syscalls::{EXEC, INDEX_OUT_OF_BOUND};
use crate::types::{DataLocation, DataPieceId, ExecV2Args, Message, VmId};
use crate::types::{DataLocation, DataPieceId, ExecV2Args, Message, VmContext, VmId};
use ckb_traits::CellDataProvider;
use ckb_vm::{
registers::{A0, A1, A2, A3, A4, A5, A7},
Error as VMError, Register, SupportMachine, Syscalls,
Expand All @@ -12,8 +13,11 @@ pub struct ExecV2 {
}

impl ExecV2 {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> ExecV2 {
ExecV2 { id, message_box }
pub fn new<DL: CellDataProvider>(vm_id: &VmId, vm_context: &VmContext<DL>) -> ExecV2 {
ExecV2 {
id: *vm_id,
message_box: Arc::clone(&vm_context.message_box),
}
}
}

Expand Down
62 changes: 62 additions & 0 deletions script/src/syscalls/generator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::{
syscalls::{
Close, CurrentCycles, Debugger, Exec, ExecV2, InheritedFd, LoadBlockExtension, LoadCell,
LoadCellData, LoadHeader, LoadInput, LoadScript, LoadScriptHash, LoadTx, LoadWitness, Pipe,
ProcessID, Read, Spawn, VMVersion, Wait, Write,
},
types::{CoreMachine, DebugContext, ScriptVersion, SgData, VmContext, VmId},
};
use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
use ckb_vm::Syscalls;

/// Generate RISC-V syscalls in CKB environment
pub fn generate_ckb_syscalls<DL>(
vm_id: &VmId,
sg_data: &SgData<DL>,
vm_context: &VmContext<DL>,
debug_context: &DebugContext,
) -> Vec<Box<(dyn Syscalls<CoreMachine>)>>
where
DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
{
let mut syscalls: Vec<Box<(dyn Syscalls<CoreMachine>)>> = vec![
Box::new(LoadScriptHash::new(sg_data)),
Box::new(LoadTx::new(sg_data)),
Box::new(LoadCell::new(sg_data)),
Box::new(LoadInput::new(sg_data)),
Box::new(LoadHeader::new(sg_data)),
Box::new(LoadWitness::new(sg_data)),
Box::new(LoadScript::new(sg_data)),
Box::new(LoadCellData::new(vm_context)),
Box::new(Debugger::new(sg_data, debug_context)),
];
let script_version = &sg_data.sg_info.script_version;
if script_version >= &ScriptVersion::V1 {
syscalls.append(&mut vec![
Box::new(VMVersion::new()),
Box::new(CurrentCycles::new(vm_context)),
]);
}
if script_version == &ScriptVersion::V1 {
syscalls.push(Box::new(Exec::new(sg_data)));
}
if script_version >= &ScriptVersion::V2 {
syscalls.append(&mut vec![
Box::new(ExecV2::new(vm_id, vm_context)),
Box::new(LoadBlockExtension::new(sg_data)),
Box::new(Spawn::new(vm_id, vm_context)),
Box::new(ProcessID::new(vm_id)),
Box::new(Pipe::new(vm_id, vm_context)),
Box::new(Wait::new(vm_id, vm_context)),
Box::new(Write::new(vm_id, vm_context)),
Box::new(Read::new(vm_id, vm_context)),
Box::new(InheritedFd::new(vm_id, vm_context)),
Box::new(Close::new(vm_id, vm_context)),
]);
}
#[cfg(test)]
syscalls.push(Box::new(crate::syscalls::Pause::new(
std::sync::Arc::clone(&debug_context.skip_pause),
)));
syscalls
}
13 changes: 10 additions & 3 deletions script/src/syscalls/inherited_fd.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::syscalls::{INHERITED_FD, SPAWN_YIELD_CYCLES_BASE};
use crate::types::{Fd, FdArgs, Message, VmId};
use crate::types::{Fd, FdArgs, Message, VmContext, VmId};
use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
use ckb_vm::{
registers::{A0, A1, A7},
Error as VMError, Register, SupportMachine, Syscalls,
Expand All @@ -13,8 +14,14 @@ pub struct InheritedFd {
}

impl InheritedFd {
pub fn new(id: VmId, message_box: Arc<Mutex<Vec<Message>>>) -> Self {
Self { id, message_box }
pub fn new<DL>(vm_id: &VmId, vm_context: &VmContext<DL>) -> Self
where
DL: CellDataProvider + HeaderProvider + ExtensionProvider + Send + Sync + Clone + 'static,
{
Self {
id: *vm_id,
message_box: Arc::clone(&vm_context.message_box),
}
}
}

Expand Down
Loading

0 comments on commit 75e7b7e

Please sign in to comment.