use std::fmt;
use oasis_types::{Address, Balance};
pub trait Storage = serde::Serialize + serde::de::DeserializeOwned;
pub trait Service {
fn coalesce() -> Self;
fn sunder(c: Self);
}
pub trait Event {
fn emit(&self);
}
#[derive(Default, Copy, Clone, Debug)]
pub struct Context {
#[doc(hidden)]
pub sender: Option<Address>,
#[doc(hidden)]
pub value: Option<Balance>,
#[doc(hidden)]
pub gas: Option<u64>,
#[doc(hidden)]
pub call_type: CallType,
}
#[derive(Copy, Clone, Debug)]
pub enum CallType {
Default,
Delegated,
Constant,
}
impl Default for CallType {
fn default() -> Self {
CallType::Default
}
}
impl Context {
#[cfg(any(test, target_os = "wasi"))]
pub fn delegated() -> Self {
Self {
call_type: CallType::Delegated,
..Default::default()
}
}
pub fn with_gas(mut self, gas: u64) -> Self {
self.gas = Some(gas);
self
}
pub fn sender(&self) -> Address {
self.sender.unwrap_or_else(crate::backend::sender)
}
pub fn address(&self) -> Address {
crate::backend::address()
}
pub fn aad(&self) -> Vec<u8> {
crate::backend::aad()
}
pub fn value(&self) -> Balance {
self.value.unwrap_or_else(crate::backend::value)
}
}
impl Context {
#[cfg(any(test, not(target_os = "wasi")))]
pub fn with_sender(mut self, sender: Address) -> Self {
self.sender = Some(sender);
self
}
pub fn with_value<B: Into<Balance>>(mut self, value: B) -> Self {
self.value = Some(value.into());
self
}
}
#[derive(Clone, Serialize, Deserialize, failure::Fail)]
pub enum RpcError<E: Send + Sync + 'static> {
InvalidCallee,
InsufficientFunds,
InsufficientGas,
InvalidInput,
InvalidOutput(Vec<u8>),
Exec(E),
}
impl<E> From<crate::backend::Error> for RpcError<E>
where
E: serde::de::DeserializeOwned + Send + Sync,
{
fn from(err: crate::backend::Error) -> Self {
use crate::backend::Error as BackendError;
match err {
BackendError::Unknown => panic!("Unknown error occured."),
BackendError::InsufficientFunds => RpcError::InsufficientFunds,
BackendError::InvalidInput => RpcError::InvalidInput,
BackendError::InvalidCallee => RpcError::InvalidCallee,
BackendError::Execution { payload, .. } => {
match serde_cbor::from_slice::<E>(&payload) {
Ok(e) => RpcError::Exec(e),
Err(_) => RpcError::InvalidOutput(payload),
}
}
}
}
}
impl<E: Send + Sync> fmt::Debug for RpcError<E> {
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RpcError::InvalidCallee => write!(f, "invalid callee"),
RpcError::InsufficientFunds => write!(f, "caller has insufficient funds"),
RpcError::InsufficientGas => write!(f, "not enough gas to complete transaction"),
RpcError::InvalidInput => write!(f, "invalid input provided to RPC"),
RpcError::InvalidOutput(_) => write!(f, "invalid output returned by RPC"),
RpcError::Exec(_) => write!(f, "execution error"),
}
}
}
impl<E: Send + Sync> fmt::Display for RpcError<E> {
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl<E: Send + Sync + fmt::Debug> fmt::Debug for RpcError<E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RpcError::Exec(e) => write!(f, "execution error {:?}", e),
_ => fmt::Debug::fmt(self, f),
}
}
}
impl<E: Send + Sync + fmt::Display> fmt::Display for RpcError<E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RpcError::Exec(e) => write!(f, "execution error: {}", e),
_ => fmt::Display::fmt(self, f),
}
}
}