use crate::{
buffer::PayloadSlice,
env_vars::EnvVars,
ids::{ActorId, MessageId, ReservationId},
memory::Memory,
message::{DispatchKind, HandlePacket, InitPacket, MessageContext, ReplyPacket},
pages::WasmPage,
};
use alloc::{collections::BTreeSet, string::String};
use core::fmt::Display;
use gear_core_errors::{ReplyCode, SignalCode};
use gear_wasm_instrument::syscalls::SyscallName;
use parity_scale_codec::{Decode, Encode};
use scale_decode::DecodeAsType;
use scale_encode::EncodeAsType;
use scale_info::TypeInfo;
pub trait Externalities {
type UnrecoverableError;
type FallibleError;
type AllocError: Display;
fn alloc<Context>(
&mut self,
ctx: &mut Context,
mem: &mut impl Memory<Context>,
pages_num: u32,
) -> Result<WasmPage, Self::AllocError>;
fn free(&mut self, page: WasmPage) -> Result<(), Self::AllocError>;
fn free_range(&mut self, start: WasmPage, end: WasmPage) -> Result<(), Self::AllocError>;
fn env_vars(&self, version: u32) -> Result<EnvVars, Self::UnrecoverableError>;
fn block_height(&self) -> Result<u32, Self::UnrecoverableError>;
fn block_timestamp(&self) -> Result<u64, Self::UnrecoverableError>;
fn send_init(&mut self) -> Result<u32, Self::FallibleError>;
fn send_push(&mut self, handle: u32, buffer: &[u8]) -> Result<(), Self::FallibleError>;
fn send_commit(
&mut self,
handle: u32,
msg: HandlePacket,
delay: u32,
) -> Result<MessageId, Self::FallibleError>;
fn send(&mut self, msg: HandlePacket, delay: u32) -> Result<MessageId, Self::FallibleError> {
let handle = self.send_init()?;
self.send_commit(handle, msg, delay)
}
fn send_push_input(
&mut self,
handle: u32,
offset: u32,
len: u32,
) -> Result<(), Self::FallibleError>;
fn reservation_send_commit(
&mut self,
id: ReservationId,
handle: u32,
msg: HandlePacket,
delay: u32,
) -> Result<MessageId, Self::FallibleError>;
fn reservation_send(
&mut self,
id: ReservationId,
msg: HandlePacket,
delay: u32,
) -> Result<MessageId, Self::FallibleError> {
let handle = self.send_init()?;
self.reservation_send_commit(id, handle, msg, delay)
}
fn reply_push(&mut self, buffer: &[u8]) -> Result<(), Self::FallibleError>;
fn reply_commit(&mut self, msg: ReplyPacket) -> Result<MessageId, Self::FallibleError>;
fn reservation_reply_commit(
&mut self,
id: ReservationId,
msg: ReplyPacket,
) -> Result<MessageId, Self::FallibleError>;
fn reply(&mut self, msg: ReplyPacket) -> Result<MessageId, Self::FallibleError> {
self.reply_commit(msg)
}
fn reservation_reply(
&mut self,
id: ReservationId,
msg: ReplyPacket,
) -> Result<MessageId, Self::FallibleError> {
self.reservation_reply_commit(id, msg)
}
fn reply_to(&self) -> Result<MessageId, Self::FallibleError>;
fn signal_from(&self) -> Result<MessageId, Self::FallibleError>;
fn reply_push_input(&mut self, offset: u32, len: u32) -> Result<(), Self::FallibleError>;
fn source(&self) -> Result<ActorId, Self::UnrecoverableError>;
fn reply_code(&self) -> Result<ReplyCode, Self::FallibleError>;
fn signal_code(&self) -> Result<SignalCode, Self::FallibleError>;
fn message_id(&self) -> Result<MessageId, Self::UnrecoverableError>;
fn program_id(&self) -> Result<ActorId, Self::UnrecoverableError>;
fn debug(&self, data: &str) -> Result<(), Self::UnrecoverableError>;
fn payload_slice(&mut self, at: u32, len: u32) -> Result<PayloadSlice, Self::FallibleError>;
fn size(&self) -> Result<usize, Self::UnrecoverableError>;
fn random(&self) -> Result<(&[u8], u32), Self::UnrecoverableError>;
fn reserve_gas(
&mut self,
amount: u64,
duration: u32,
) -> Result<ReservationId, Self::FallibleError>;
fn unreserve_gas(&mut self, id: ReservationId) -> Result<u64, Self::FallibleError>;
fn system_reserve_gas(&mut self, amount: u64) -> Result<(), Self::FallibleError>;
fn gas_available(&self) -> Result<u64, Self::UnrecoverableError>;
fn value(&self) -> Result<u128, Self::UnrecoverableError>;
fn value_available(&self) -> Result<u128, Self::UnrecoverableError>;
fn wait(&mut self) -> Result<(), Self::UnrecoverableError>;
fn wait_for(&mut self, duration: u32) -> Result<(), Self::UnrecoverableError>;
fn wait_up_to(&mut self, duration: u32) -> Result<bool, Self::UnrecoverableError>;
fn wake(&mut self, waker_id: MessageId, delay: u32) -> Result<(), Self::FallibleError>;
fn create_program(
&mut self,
packet: InitPacket,
delay: u32,
) -> Result<(MessageId, ActorId), Self::FallibleError>;
fn reply_deposit(
&mut self,
message_id: MessageId,
amount: u64,
) -> Result<(), Self::FallibleError>;
fn forbidden_funcs(&self) -> &BTreeSet<SyscallName>;
fn msg_ctx(&self) -> &MessageContext;
}
#[derive(
Debug,
Encode,
EncodeAsType,
Decode,
DecodeAsType,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
TypeInfo,
)]
pub enum MessageWaitedType {
Wait,
WaitFor,
WaitUpTo,
WaitUpToFull,
}
pub trait WasmEntryPoint: Sized {
fn as_entry(&self) -> &str;
fn try_from_entry(entry: &str) -> Option<Self>;
fn try_into_kind(&self) -> Option<DispatchKind> {
<DispatchKind as WasmEntryPoint>::try_from_entry(self.as_entry())
}
}
impl WasmEntryPoint for String {
fn as_entry(&self) -> &str {
self
}
fn try_from_entry(entry: &str) -> Option<Self> {
Some(entry.into())
}
}
impl WasmEntryPoint for DispatchKind {
fn as_entry(&self) -> &str {
match self {
Self::Init => "init",
Self::Handle => "handle",
Self::Reply => "handle_reply",
Self::Signal => "handle_signal",
}
}
fn try_from_entry(entry: &str) -> Option<Self> {
let kind = match entry {
"init" => Self::Init,
"handle" => Self::Handle,
"handle_reply" => Self::Reply,
"handle_signal" => Self::Signal,
_ => return None,
};
Some(kind)
}
}