use wasmer::{imports, Function, ImportObject, Store};
use super::MethodCallError;
pub trait ContractBinaryInterface<T>
where
T: wasmer::WasmerEnv + 'static,
{
fn set(
env: &T,
key_ptr: u32,
key_len: u32,
value_ptr: u32,
value_len: u32,
) -> Result<(), FuncError>;
fn get(env: &T, key_ptr: u32, key_len: u32, value_ptr_ptr: u32) -> Result<i64, FuncError>;
fn get_network_storage(
env: &T,
key_ptr: u32,
key_len: u32,
value_ptr_ptr: u32,
) -> Result<i64, FuncError>;
fn balance(env: &T) -> Result<u64, FuncError>;
fn block_height(env: &T) -> Result<u64, FuncError>;
fn block_timestamp(env: &T) -> Result<u32, FuncError>;
fn prev_block_hash(env: &T, hash_ptr_ptr: u32) -> Result<(), FuncError>;
fn calling_account(env: &T, address_ptr_ptr: u32) -> Result<(), FuncError>;
fn current_account(env: &T, address_ptr_ptr: u32) -> Result<(), FuncError>;
fn method(env: &T, method_ptr_ptr: u32) -> Result<u32, FuncError>;
fn arguments(env: &T, arguments_ptr_ptr: u32) -> Result<u32, FuncError>;
fn amount(env: &T) -> Result<u64, FuncError>;
fn is_internal_call(env: &T) -> Result<i32, FuncError>;
fn transaction_hash(env: &T, hash_ptr_ptr: u32) -> Result<(), FuncError>;
fn call(
env: &T,
call_input_ptr: u32,
call_input_len: u32,
rval_ptr_ptr: u32,
) -> Result<u32, FuncError>;
fn return_value(env: &T, value_ptr: u32, value_len: u32) -> Result<(), FuncError>;
fn transfer(env: &T, transfer_input_ptr: u32) -> Result<(), FuncError>;
fn defer_create_deposit(
env: &T,
create_deposit_input_ptr: u32,
create_deposit_input_len: u32,
) -> Result<(), FuncError>;
fn defer_set_deposit_settings(
env: &T,
set_deposit_settings_input_ptr: u32,
set_deposit_settings_input_len: u32,
) -> Result<(), FuncError>;
fn defer_topup_deposit(
env: &T,
top_up_deposit_input_ptr: u32,
top_up_deposit_input_len: u32,
) -> Result<(), FuncError>;
fn defer_withdraw_deposit(
env: &T,
withdraw_deposit_input_ptr: u32,
withdraw_deposit_input_len: u32,
) -> Result<(), FuncError>;
fn defer_stake_deposit(
env: &T,
stake_deposit_input_ptr: u32,
stake_deposit_input_len: u32,
) -> Result<(), FuncError>;
fn defer_unstake_deposit(
env: &T,
unstake_deposit_input_ptr: u32,
unstake_deposit_input_len: u32,
) -> Result<(), FuncError>;
fn log(env: &T, log_ptr: u32, log_len: u32) -> Result<(), FuncError>;
fn sha256(env: &T, msg_ptr: u32, msg_len: u32, digest_ptr_ptr: u32) -> Result<(), FuncError>;
fn keccak256(env: &T, msg_ptr: u32, msg_len: u32, digest_ptr_ptr: u32)
-> Result<(), FuncError>;
fn ripemd(env: &T, msg_ptr: u32, msg_len: u32, digest_ptr_ptr: u32) -> Result<(), FuncError>;
fn verify_ed25519_signature(
env: &T,
msg_ptr: u32,
msg_len: u32,
signature_ptr: u32,
address_ptr: u32,
) -> Result<i32, FuncError>;
}
pub(crate) fn create_importable<'a, T, K>(store: &'a Store, env: &T) -> Importable<'a>
where
T: wasmer::WasmerEnv + 'static,
K: ContractBinaryInterface<T> + 'static,
{
Importable(
imports! {
"env" => {
"set" => Function::new_native_with_env(store, env.clone(), K::set),
"get" => Function::new_native_with_env(store, env.clone(), K::get),
"get_network_storage" => Function::new_native_with_env(store, env.clone(), K::get_network_storage),
"balance" => Function::new_native_with_env(store, env.clone(), K::balance),
"block_height" => Function::new_native_with_env(store, env.clone(), K::block_height),
"block_timestamp" => Function::new_native_with_env(store, env.clone(), K::block_timestamp),
"prev_block_hash" => Function::new_native_with_env(store, env.clone(), K::prev_block_hash),
"calling_account" => Function::new_native_with_env(store, env.clone(), K::calling_account),
"current_account" => Function::new_native_with_env(store, env.clone(), K::current_account),
"method" => Function::new_native_with_env(store, env.clone(), K::method),
"arguments" => Function::new_native_with_env(store, env.clone(), K::arguments),
"amount" => Function::new_native_with_env(store, env.clone(), K::amount),
"is_internal_call" => Function::new_native_with_env(store, env.clone(), K::is_internal_call),
"transaction_hash" => Function::new_native_with_env(store, env.clone(), K::transaction_hash),
"call" => Function::new_native_with_env(store, env.clone(), K::call),
"return_value" => Function::new_native_with_env(store, env.clone(), K::return_value),
"transfer" => Function::new_native_with_env(store, env.clone(), K::transfer),
"defer_create_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_create_deposit),
"defer_set_deposit_settings" => Function::new_native_with_env(store, env.clone(), K::defer_set_deposit_settings),
"defer_topup_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_topup_deposit),
"defer_withdraw_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_withdraw_deposit),
"defer_stake_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_stake_deposit),
"defer_unstake_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_unstake_deposit),
"_log" => Function::new_native_with_env(store, env.clone(), K::log),
"sha256" => Function::new_native_with_env(store, env.clone(), K::sha256),
"keccak256" => Function::new_native_with_env(store, env.clone(), K::keccak256),
"ripemd" => Function::new_native_with_env(store, env.clone(), K::ripemd),
"verify_ed25519_signature" => Function::new_native_with_env(store, env.clone(), K::verify_ed25519_signature),
}
},
store,
)
}
pub(crate) fn create_importable_view<'a, T, K>(store: &'a Store, env: &T) -> Importable<'a>
where
T: wasmer::WasmerEnv + 'static,
K: ContractBinaryInterface<T> + 'static,
{
Importable(
imports! {
"env" => {
"set" => Function::new_native(store, not_callable::set),
"get" => Function::new_native_with_env(store, env.clone(), K::get),
"get_network_storage" => Function::new_native_with_env(store, env.clone(), K::get_network_storage),
"balance" => Function::new_native_with_env(store, env.clone(), K::balance),
"block_height" => Function::new_native(store, not_callable::block_height),
"block_timestamp" => Function::new_native(store, not_callable::block_timestamp),
"prev_block_hash" => Function::new_native(store, not_callable::prev_block_hash),
"calling_account" => Function::new_native(store, not_callable::calling_account),
"current_account" => Function::new_native_with_env(store, env.clone(), K::current_account),
"method" => Function::new_native_with_env(store, env.clone(), K::method),
"arguments" => Function::new_native_with_env(store, env.clone(), K::arguments),
"amount" => Function::new_native(store, not_callable::amount),
"is_internal_call" => Function::new_native_with_env(store, env.clone(), K::is_internal_call),
"transaction_hash" => Function::new_native(store, not_callable::transaction_hash),
"call" => Function::new_native_with_env(store, env.clone(), K::call), "return_value" => Function::new_native_with_env(store, env.clone(), K::return_value),
"transfer" => Function::new_native(store, not_callable::transfer),
"defer_create_deposit" => Function::new_native(store, not_callable::defer_create_deposit),
"defer_set_deposit_settings" => Function::new_native(store, not_callable::defer_set_deposit_settings),
"defer_topup_deposit" => Function::new_native(store, not_callable::defer_topup_deposit),
"defer_withdraw_deposit" => Function::new_native(store, not_callable::defer_withdraw_deposit),
"defer_stake_deposit" => Function::new_native(store, not_callable::defer_stake_deposit),
"defer_unstake_deposit" => Function::new_native(store, not_callable::defer_unstake_deposit),
"_log" => Function::new_native_with_env(store, env.clone(), K::log),
"sha256" => Function::new_native_with_env(store, env.clone(), K::sha256),
"keccak256" => Function::new_native_with_env(store, env.clone(), K::keccak256),
"ripemd" => Function::new_native_with_env(store, env.clone(), K::ripemd),
"verify_ed25519_signature" => Function::new_native_with_env(store, env.clone(), K::verify_ed25519_signature),
}
},
store,
)
}
pub(crate) struct Importable<'a>(pub(crate) ImportObject, &'a Store);
pub(crate) mod blank {
use wasmer::{imports, Function, Store};
pub(crate) fn imports(store: &Store) -> wasmer::ImportObject {
imports! {
"env" => {
"set" => Function::new_native(store, set),
"get" => Function::new_native(store, get),
"get_network_storage" => Function::new_native(store, get_network_storage),
"balance" => Function::new_native(store, balance),
"block_height" => Function::new_native(store, block_height),
"block_timestamp" => Function::new_native(store, block_timestamp),
"prev_block_hash" => Function::new_native(store, prev_block_hash),
"calling_account" => Function::new_native(store, calling_account),
"current_account" => Function::new_native(store, current_account),
"method" => Function::new_native(store, method),
"arguments" => Function::new_native(store, arguments),
"amount" => Function::new_native(store, amount),
"is_internal_call" => Function::new_native(store, is_internal_call),
"transaction_hash" => Function::new_native(store, transaction_hash),
"call" => Function::new_native(store, call),
"return_value" => Function::new_native(store, return_value),
"transfer" => Function::new_native(store, transfer),
"defer_create_deposit" => Function::new_native(store, defer_create_deposit),
"defer_set_deposit_settings" => Function::new_native(store, defer_set_deposit_settings),
"defer_topup_deposit" => Function::new_native(store, defer_topup_deposit),
"defer_withdraw_deposit" => Function::new_native(store, defer_withdraw_deposit),
"defer_stake_deposit" => Function::new_native(store, defer_stake_deposit),
"defer_unstake_deposit" => Function::new_native(store, defer_unstake_deposit),
"_log" => Function::new_native(store, log),
"sha256" => Function::new_native(store, sha256),
"keccak256" => Function::new_native(store, keccak256),
"ripemd" => Function::new_native(store, ripemd),
"verify_ed25519_signature" => Function::new_native(store, verify_ed25519_signature),
}
}
}
pub(crate) fn set(_: u32, _: u32, _: u32, _: u32) {}
pub(crate) fn get(_: u32, _: u32, _: u32) -> i64 {
0
}
pub(crate) fn get_network_storage(_: u32, _: u32, _: u32) -> i64 {
0
}
pub(crate) fn balance() -> u64 {
0
}
pub(crate) fn block_height() -> u64 {
0
}
pub(crate) fn block_timestamp() -> u32 {
0
}
pub(crate) fn prev_block_hash(_: u32) {}
pub(crate) fn calling_account(_: u32) {}
pub(crate) fn current_account(_: u32) {}
pub(crate) fn method(_: u32) -> u32 {
0
}
pub(crate) fn arguments(_: u32) -> u32 {
0
}
pub(crate) fn amount() -> u64 {
0
}
pub(crate) fn is_internal_call() -> i32 {
0
}
pub(crate) fn transaction_hash(_: u32) {}
pub(crate) fn call(_: u32, _: u32, _: u32) -> u32 {
0
}
pub(crate) fn return_value(_: u32, _: u32) {}
pub(crate) fn transfer(_: u32) {}
pub(crate) fn defer_create_deposit(_: u32, _: u32) {}
pub(crate) fn defer_set_deposit_settings(_: u32, _: u32) {}
pub(crate) fn defer_topup_deposit(_: u32, _: u32) {}
pub(crate) fn defer_withdraw_deposit(_: u32, _: u32) {}
pub(crate) fn defer_stake_deposit(_: u32, _: u32) {}
pub(crate) fn defer_unstake_deposit(_: u32, _: u32) {}
pub(crate) fn log(_: u32, _: u32) {}
pub(crate) fn sha256(_: u32, _: u32, _: u32) {}
pub(crate) fn keccak256(_: u32, _: u32, _: u32) {}
pub(crate) fn ripemd(_: u32, _: u32, _: u32) {}
pub(crate) fn verify_ed25519_signature(_: u32, _: u32, _: u32, _: u32) -> i32 {
0
}
}
mod not_callable {
use super::FuncError;
pub(crate) fn set(_: u32, _: u32, _: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn block_height() -> Result<u64, FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn block_timestamp() -> Result<u32, FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn prev_block_hash(_: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn calling_account(_: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn amount() -> Result<u64, FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn transaction_hash(_: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn transfer(_: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn defer_create_deposit(_: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn defer_set_deposit_settings(_: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn defer_topup_deposit(_: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn defer_withdraw_deposit(_: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn defer_stake_deposit(_: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
pub(crate) fn defer_unstake_deposit(_: u32, _: u32) -> Result<(), FuncError> {
Err(FuncError::Internal)
}
}
#[derive(Debug, thiserror::Error)]
pub enum FuncError {
#[error("Internal")]
Internal,
#[error("Runtime")]
Runtime(anyhow::Error),
#[error("GasExhaustionError")]
GasExhaustionError,
#[error("Runtime")]
MethodCallError(MethodCallError),
#[error("ContractNotFound")]
ContractNotFound,
#[error("InsufficientBalance")]
InsufficientBalance,
}
impl From<wasmer::RuntimeError> for FuncError {
fn from(e: wasmer::RuntimeError) -> Self {
Self::Runtime(e.into())
}
}
impl From<anyhow::Error> for FuncError {
fn from(e: anyhow::Error) -> Self {
Self::Runtime(e)
}
}