Skip to content

Commit

Permalink
Implemented syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
mqxf committed Jan 13, 2024
1 parent 47eb254 commit 6649ec2
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 85 deletions.
120 changes: 54 additions & 66 deletions core-backend/src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ use gear_core::{
use gear_core_errors::{MessageError, ReplyCode, SignalCode};
use gear_sandbox::{default_executor::Caller, ReturnValue, Value};
use gear_sandbox_env::{HostError, WasmReturnValue};
use gear_wasm_instrument::syscalls::UserBreakKind;
use gear_wasm_instrument::SystemBreakCode;
use gear_wasm_instrument::{syscalls::UserBreakKind, SystemBreakCode};
use gsys::{
BlockNumberWithHash, ErrorBytes, ErrorWithBlockNumberAndValue, ErrorWithGas, ErrorWithHandle,
ErrorWithHash, ErrorWithReplyCode, ErrorWithSignalCode, ErrorWithTwoHashes, Gas, Hash,
Expand Down Expand Up @@ -593,12 +592,13 @@ where
})
}

pub fn exit(inheritor_id_ptr: u32) -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::Exit, move |ctx: &mut CallerWrap<Ext>| {
let read_inheritor_id = ctx.manager.register_read_decoded(inheritor_id_ptr);
let inheritor_id = ctx.read_decoded(read_inheritor_id)?;
Err(ActorTerminationReason::Exit(inheritor_id).into())
})
pub fn exit(
ctx: &mut CallerWrap<Ext>,
inheritor_id_ptr: u32,
) -> Result<(), UndefinedTerminationReason> {
let read_inheritor_id = ctx.manager.register_read_decoded(inheritor_id_ptr);
let inheritor_id = ctx.read_decoded(read_inheritor_id)?;
Err(ActorTerminationReason::Exit(inheritor_id).into())
}

pub fn reply_code() -> impl Syscall<Ext> {
Expand Down Expand Up @@ -1033,21 +1033,21 @@ where
)
}

pub fn panic(data_ptr: u32, data_len: u16) -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::Null, move |ctx: &mut CallerWrap<Ext>| {
let read_data = ctx.manager.register_read(data_ptr, data_len as u32);
let data = ctx.read(read_data).unwrap_or_default();
pub fn panic(
ctx: &mut CallerWrap<Ext>,
data_ptr: u32,
data_len: u16,
) -> Result<(), UndefinedTerminationReason> {
let read_data = ctx.manager.register_read(data_ptr, data_len as u32);
let data = ctx.read(read_data).unwrap_or_default();

let s = String::from_utf8_lossy(&data).to_string();
let s = String::from_utf8_lossy(&data).to_string();

Err(ActorTerminationReason::Trap(TrapExplanation::Panic(s.into())).into())
})
Err(ActorTerminationReason::Trap(TrapExplanation::Panic(s.into())).into())
}

pub fn oom_panic() -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::Null, |_ctx: &mut CallerWrap<Ext>| {
Err(ActorTerminationReason::Trap(TrapExplanation::ProgramAllocOutOfBounds).into())
})
pub fn oom_panic() -> Result<(), UndefinedTerminationReason> {
Err(ActorTerminationReason::Trap(TrapExplanation::ProgramAllocOutOfBounds).into())
}

pub fn reserve_gas(gas_value: u64, duration: u32) -> impl Syscall<Ext> {
Expand Down Expand Up @@ -1184,35 +1184,33 @@ where
)
}

pub fn leave() -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::Leave, move |_ctx: &mut CallerWrap<Ext>| {
Err(ActorTerminationReason::Leave.into())
})
pub fn leave() -> Result<(), UndefinedTerminationReason> {
Err(ActorTerminationReason::Leave.into())
}

pub fn wait() -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::Wait, move |ctx: &mut CallerWrap<Ext>| {
ctx.ext_mut().wait()?;
Err(ActorTerminationReason::Wait(None, MessageWaitedType::Wait).into())
})
pub fn wait(ctx: &mut CallerWrap<Ext>) -> Result<(), UndefinedTerminationReason> {
ctx.ext_mut().wait()?;
Err(ActorTerminationReason::Wait(None, MessageWaitedType::Wait).into())
}

pub fn wait_for(duration: u32) -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::WaitFor, move |ctx: &mut CallerWrap<Ext>| {
ctx.ext_mut().wait_for(duration)?;
Err(ActorTerminationReason::Wait(Some(duration), MessageWaitedType::WaitFor).into())
})
pub fn wait_for(
ctx: &mut CallerWrap<Ext>,
duration: u32,
) -> Result<(), UndefinedTerminationReason> {
ctx.ext_mut().wait_for(duration)?;
Err(ActorTerminationReason::Wait(Some(duration), MessageWaitedType::WaitFor).into())
}

pub fn wait_up_to(duration: u32) -> impl Syscall<Ext> {
InfallibleSyscall::new(RuntimeCosts::WaitUpTo, move |ctx: &mut CallerWrap<Ext>| {
let waited_type = if ctx.ext_mut().wait_up_to(duration)? {
MessageWaitedType::WaitUpToFull
} else {
MessageWaitedType::WaitUpTo
};
Err(ActorTerminationReason::Wait(Some(duration), waited_type).into())
})
pub fn wait_up_to(
ctx: &mut CallerWrap<Ext>,
duration: u32,
) -> Result<(), UndefinedTerminationReason> {
let waited_type = if ctx.ext_mut().wait_up_to(duration)? {
MessageWaitedType::WaitUpToFull
} else {
MessageWaitedType::WaitUpTo
};
Err(ActorTerminationReason::Wait(Some(duration), waited_type).into())
}

pub fn wake(message_id_ptr: u32, delay: u32) -> impl Syscall<Ext> {
Expand Down Expand Up @@ -1357,32 +1355,22 @@ where
let break_kind = raw_data[0].try_into();
// We do this instead of 2..6 since this gives a fixed length array
let data32 = u32::from_le_bytes([raw_data[2], raw_data[3], raw_data[4], raw_data[5]]);
match break_kind {
Ok(UserBreakKind::Exit) => {
FuncsHandler::exit(data32)
}
Ok(UserBreakKind::Leave) => {
FuncsHandler::leave()
}
Ok(UserBreakKind::Wait) => {
FuncsHandler::wait()
}
Ok(UserBreakKind::WaitFor) => {
FuncsHandler::wait_for(data32)
}
Ok(UserBreakKind::WaitUpTo) => {
FuncsHandler::wait_up_to(data32)
}
let cost = break_kind.map(Into::into).unwrap_or(RuntimeCosts::Null);
InfallibleSyscall::new(cost, move |ctx: &mut CallerWrap<Ext>| match break_kind {
Ok(UserBreakKind::Exit) => FuncsHandler::exit(ctx, data32),
Ok(UserBreakKind::Leave) => FuncsHandler::<Ext>::leave(),
Ok(UserBreakKind::Wait) => FuncsHandler::wait(ctx),
Ok(UserBreakKind::WaitFor) => FuncsHandler::wait_for(ctx, data32),
Ok(UserBreakKind::WaitUpTo) => FuncsHandler::wait_up_to(ctx, data32),
Ok(UserBreakKind::Panic) => {
let data16 = u16::from_le_bytes([raw_data[6], raw_data[7]]);
FuncsHandler::panic(data32, data16)
FuncsHandler::panic(ctx, data32, data16)
}
Ok(UserBreakKind::OomPanic) => {
FuncsHandler::oom_panic()
}
_ => {
Err(ActorTerminationReason::Trap(TrapExplanation::Panic("Unknown user_break syscall codec".to_string().into())).into())
}
}
Ok(UserBreakKind::OomPanic) => FuncsHandler::<Ext>::oom_panic(),
_ => Err(ActorTerminationReason::Trap(TrapExplanation::Panic(
"Unknown user_break syscall codec".to_string().into(),
))
.into()),
})
}
}
14 changes: 14 additions & 0 deletions core/src/costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

use crate::{gas::Token, pages::PageU32Size};
use core::{fmt::Debug, marker::PhantomData};
use gear_wasm_instrument::syscalls::UserBreakKind;
use paste::paste;
use scale_info::scale::{Decode, Encode};

Expand Down Expand Up @@ -549,3 +550,16 @@ impl RuntimeCosts {
RuntimeToken { weight }
}
}

impl From<UserBreakKind> for RuntimeCosts {
fn from(value: UserBreakKind) -> Self {
match value {
UserBreakKind::Exit => RuntimeCosts::Exit,
UserBreakKind::Leave => RuntimeCosts::Leave,
UserBreakKind::Wait => RuntimeCosts::Wait,
UserBreakKind::WaitFor => RuntimeCosts::WaitFor,
UserBreakKind::WaitUpTo => RuntimeCosts::WaitUpTo,
_ => RuntimeCosts::Null,
}
}
}
34 changes: 29 additions & 5 deletions gcore/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@ pub fn reply_deposit(message_id: MessageId, amount: u64) -> Result<()> {
/// }
/// ```
pub fn exit(inheritor_id: ActorId) -> ! {
unsafe { gsys::gr_exit(inheritor_id.as_ptr()) }
let mut data = [0u8; 8];
let ptr = (inheritor_id.as_ptr() as u32).to_le_bytes();
data[2] = ptr[0];
data[3] = ptr[1];
data[4] = ptr[2];
data[5] = ptr[3];
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}

/// Reserve the `amount` of gas for further usage.
Expand Down Expand Up @@ -282,7 +288,9 @@ pub fn gas_available() -> u64 {
/// }
/// ```
pub fn leave() -> ! {
unsafe { gsys::gr_leave() }
let mut data = [0u8; 8];
data[0] = 1;
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}

/// Get the total available value amount.
Expand Down Expand Up @@ -332,7 +340,9 @@ pub fn value_available() -> u128 {
/// }
/// ```
pub fn wait() -> ! {
unsafe { gsys::gr_wait() }
let mut data = [0u8; 8];
data[0] = 2;
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}

/// Same as [`wait`], but delays handling for a specific number of blocks.
Expand All @@ -341,13 +351,27 @@ pub fn wait() -> ! {
///
/// Panics if it is impossible to pay the given `duration`.
pub fn wait_for(duration: u32) -> ! {
unsafe { gsys::gr_wait_for(duration) }
let mut data = [0u8; 8];
data[0] = 3;
let raw_duration = duration.to_le_bytes();
data[2] = raw_duration[0];
data[3] = raw_duration[1];
data[4] = raw_duration[2];
data[5] = raw_duration[3];
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}

/// Same as [`wait`], but delays handling for the maximum number of blocks that
/// can be paid for and doesn't exceed the given `duration`.
pub fn wait_up_to(duration: u32) -> ! {
unsafe { gsys::gr_wait_up_to(duration) }
let mut data = [0u8; 8];
data[0] = 4;
let raw_duration = duration.to_le_bytes();
data[2] = raw_duration[0];
data[3] = raw_duration[1];
data[4] = raw_duration[2];
data[5] = raw_duration[3];
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}

/// Resume previously paused message handling.
Expand Down
16 changes: 14 additions & 2 deletions gcore/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,17 @@ pub mod ext {
/// }
/// ```
pub fn panic(data: &str) -> ! {
unsafe { gsys::gr_panic(data.as_ptr(), data.len() as u32) }
let mut data = [0u8; 8];
data[0] = 5;
let ptr = (data.as_ptr() as u32).to_le_bytes();
data[2] = ptr[0];
data[3] = ptr[1];
data[4] = ptr[2];
data[5] = ptr[3];
let len = (data.len() as u16).to_le_bytes();
data[6] = len[0];
data[7] = len[1];
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}

/// Out of memory panic
Expand Down Expand Up @@ -90,6 +100,8 @@ pub mod ext {
/// }
/// ```
pub fn oom_panic() -> ! {
unsafe { gsys::gr_oom_panic() }
let mut data = [0u8; 8];
data[0] = 6;
unsafe { gsys::gr_user_break(u64::from_le_bytes(data)) }
}
}
10 changes: 2 additions & 8 deletions pallets/gear/src/benchmarking/tests/syscalls_integrity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,9 @@ where
SyscallName::BlockTimestamp => check_gr_block_timestamp::<T>(),
SyscallName::GasAvailable => check_gr_gas_available::<T>(),
SyscallName::ValueAvailable => check_gr_value_available::<T>(),
SyscallName::Exit
| SyscallName::Leave
| SyscallName::Wait
| SyscallName::WaitFor
| SyscallName::WaitUpTo
SyscallName::UserBreak
| SyscallName::Wake
| SyscallName::Debug
| SyscallName::Panic
| SyscallName::OomPanic => {/* tests here aren't required, read module docs for more info */},
| SyscallName::Debug => {/* tests here aren't required, read module docs for more info */},
SyscallName::Alloc
| SyscallName::Free
| SyscallName::FreeRange => check_mem::<T>(),
Expand Down
9 changes: 5 additions & 4 deletions utils/wasm-instrument/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ impl SyscallName {
Ptr::Hash(HashType::SubjectId).into(),
Ptr::MutBlockNumberWithHash(HashType::SubjectId).into(),
]),
Self::UserBreak => SyscallSignature::gr_infallible([ValueType::I64.into()]),
Self::UserBreak => SyscallSignature::gr_infallible([Data]),
Self::SystemBreak => unimplemented!("Unsupported syscall signature for system_break"),
}
}
Expand Down Expand Up @@ -564,7 +564,7 @@ impl TryFrom<u8> for UserBreakKind {
4 => Ok(UserBreakKind::WaitUpTo),
5 => Ok(UserBreakKind::Panic),
6 => Ok(UserBreakKind::OomPanic),
_ => Err(())
_ => Err(()),
}
}
}
Expand All @@ -578,7 +578,7 @@ impl From<UserBreakKind> for u8 {
UserBreakKind::WaitFor => 3,
UserBreakKind::WaitUpTo => 4,
UserBreakKind::Panic => 5,
UserBreakKind::OomPanic => 6
UserBreakKind::OomPanic => 6,
}
}
}
Expand Down Expand Up @@ -606,6 +606,7 @@ pub enum RegularParamType {
Free, // i32 page number to free
FreeUpperBound, // i32 free upper bound for use with free_range
Version, // i32 version number of exec settings
Data, // i64 data for user_break
}

/// Hash type.
Expand All @@ -629,7 +630,7 @@ impl From<ParamType> for ValueType {
ParamType::Regular(regular_ptr) => match regular_ptr {
Length | Pointer(_) | Offset | DurationBlockNumber | DelayBlockNumber | Handler
| Alloc | Free | FreeUpperBound | Version => ValueType::I32,
Gas => ValueType::I64,
Gas | Data => ValueType::I64,
},
ParamType::Error(_) => ValueType::I32,
}
Expand Down

0 comments on commit 6649ec2

Please sign in to comment.