Newer
Older
// Copyright (C) Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(unused_variables)]
use crate::{
host::{CallFlags, HostFn, HostFnImpl, Result, StorageFlags},
pack_hi_lo, ReturnFlags,
use pallet_revive_proc_macro::unstable_hostfn;
mod sys {
use crate::ReturnCode;
#[polkavm_derive::polkavm_define_abi]
mod abi {}
impl abi::FromHost for ReturnCode {
fn from_host((a0,): Self::Regs) -> Self {
}
}
#[polkavm_derive::polkavm_import(abi = self::abi)]
extern "C" {
pub fn set_storage(
flags: u32,
key_ptr: *const u8,
key_len: u32,
value_ptr: *const u8,
value_len: u32,
) -> ReturnCode;
pub fn clear_storage(flags: u32, key_ptr: *const u8, key_len: u32) -> ReturnCode;
pub fn get_storage(
flags: u32,
key_ptr: *const u8,
key_len: u32,
out_ptr: *mut u8,
out_len_ptr: *mut u32,
) -> ReturnCode;
pub fn contains_storage(flags: u32, key_ptr: *const u8, key_len: u32) -> ReturnCode;
pub fn take_storage(
flags: u32,
key_ptr: *const u8,
key_len: u32,
out_ptr: *mut u8,
out_len_ptr: *mut u32,
) -> ReturnCode;
pub fn call(
flags_and_callee: u64,
ref_time_limit: u64,
proof_size_limit: u64,
deposit_and_value: u64,
input_data: u64,
output_data: u64,
) -> ReturnCode;
pub fn delegate_call(
flags_and_callee: u64,
ref_time_limit: u64,
proof_size_limit: u64,
deposit_ptr: *const u8,
input_data: u64,
output_data: u64,
) -> ReturnCode;
pub fn instantiate(
ref_time_limit: u64,
proof_size_limit: u64,
deposit_and_value: u64,
input_data: u64,
output_data: u64,
address_and_salt: u64,
) -> ReturnCode;
pub fn terminate(beneficiary_ptr: *const u8);
pub fn call_data_copy(out_ptr: *mut u8, out_len: u32, offset: u32);
pub fn call_data_load(out_ptr: *mut u8, offset: u32);
pub fn seal_return(flags: u32, data_ptr: *const u8, data_len: u32);
pub fn caller(out_ptr: *mut u8);
pub fn origin(out_ptr: *mut u8);
pub fn is_contract(account_ptr: *const u8) -> ReturnCode;
pub fn to_account_id(address_ptr: *const u8, out_ptr: *mut u8);
pub fn code_hash(address_ptr: *const u8, out_ptr: *mut u8);
Cyrill Leutwiler
committed
pub fn code_size(address_ptr: *const u8) -> u64;
pub fn own_code_hash(out_ptr: *mut u8);
pub fn caller_is_origin() -> ReturnCode;
pub fn caller_is_root() -> ReturnCode;
pub fn address(out_ptr: *mut u8);
pub fn weight_to_fee(ref_time: u64, proof_size: u64, out_ptr: *mut u8);
pub fn weight_left(out_ptr: *mut u8, out_len_ptr: *mut u32);
pub fn ref_time_left() -> u64;
pub fn get_immutable_data(out_ptr: *mut u8, out_len_ptr: *mut u32);
pub fn set_immutable_data(ptr: *const u8, len: u32);
pub fn balance(out_ptr: *mut u8);
Cyrill Leutwiler
committed
pub fn balance_of(addr_ptr: *const u8, out_ptr: *mut u8);
pub fn chain_id(out_ptr: *mut u8);
pub fn value_transferred(out_ptr: *mut u8);
pub fn now(out_ptr: *mut u8);
pub fn gas_limit() -> u64;
pub fn minimum_balance(out_ptr: *mut u8);
pub fn deposit_event(
topics_ptr: *const [u8; 32],
num_topic: u32,
data_ptr: *const u8,
data_len: u32,
);
pub fn gas_price() -> u64;
pub fn base_fee(out_ptr: *mut u8);
Cyrill Leutwiler
committed
pub fn call_data_size() -> u64;
pub fn block_number(out_ptr: *mut u8);
pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8);
pub fn block_author(out_ptr: *mut u8);
pub fn hash_sha2_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
pub fn hash_keccak_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
pub fn hash_blake2_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
pub fn hash_blake2_128(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8);
pub fn call_chain_extension(
id: u32,
input_ptr: *const u8,
input_len: u32,
out_ptr: *mut u8,
out_len_ptr: *mut u32,
) -> ReturnCode;
pub fn call_runtime(call_ptr: *const u8, call_len: u32) -> ReturnCode;
pub fn sr25519_verify(
signature_ptr: *const u8,
pub_key_ptr: *const u8,
message_len: u32,
message_ptr: *const u8,
) -> ReturnCode;
pub fn set_code_hash(code_hash_ptr: *const u8);
pub fn ecdsa_to_eth_address(key_ptr: *const u8, out_ptr: *mut u8) -> ReturnCode;
pub fn instantiation_nonce() -> u64;
pub fn xcm_execute(msg_ptr: *const u8, msg_len: u32) -> ReturnCode;
pub fn xcm_send(
dest_ptr: *const u8,
msg_ptr: *const u8,
msg_len: u32,
out_ptr: *mut u8,
) -> ReturnCode;
pub fn new_query(
responder_ptr: *const u8,
responder_len: *const u8,
maybe_notify_ptr: *const u8,
maybe_notify_len: u32,
timeout_ptr: *const u8,
out_ptr: *mut u8,
) -> ReturnCode;
Cyrill Leutwiler
committed
pub fn return_data_size() -> u64;
pub fn return_data_copy(out_ptr: *mut u8, out_len_ptr: *mut u32, offset: u32);
}
}
#[inline(always)]
fn extract_from_slice(output: &mut &mut [u8], new_len: usize) {
debug_assert!(new_len <= output.len());
let tmp = core::mem::take(output);
*output = &mut tmp[..new_len];
}
#[inline(always)]
fn ptr_len_or_sentinel(data: &mut Option<&mut &mut [u8]>) -> (*mut u8, u32) {
match data {
Some(ref mut data) => (data.as_mut_ptr(), data.len() as _),
None => (crate::SENTINEL as _, 0),
}
}
#[inline(always)]
fn ptr_or_sentinel(data: &Option<&[u8; 32]>) -> *const u8 {
match data {
Some(ref data) => data.as_ptr(),
None => crate::SENTINEL as _,
}
}
impl HostFn for HostFnImpl {
fn instantiate(
ref_time_limit: u64,
proof_size_limit: u64,
deposit_limit: &[u8; 32],
mut address: Option<&mut [u8; 20]>,
mut output: Option<&mut &mut [u8]>,
salt: Option<&[u8; 32]>,
let address = match address {
Some(ref mut data) => data.as_mut_ptr(),
None => crate::SENTINEL as _,
};
let (output_ptr, mut output_len_ptr) = ptr_len_or_sentinel(&mut output);
let deposit_limit_ptr = deposit_limit.as_ptr();
let salt_ptr = ptr_or_sentinel(&salt);
let deposit_and_value = pack_hi_lo(deposit_limit_ptr as _, value.as_ptr() as _);
let address_and_salt = pack_hi_lo(address as _, salt_ptr as _);
let input_data = pack_hi_lo(input.len() as _, input.as_ptr() as _);
let output_data = pack_hi_lo(&mut output_len_ptr as *mut _ as _, output_ptr as _);
let ret_code = unsafe {
sys::instantiate(
ref_time_limit,
proof_size_limit,
deposit_and_value,
input_data,
output_data,
address_and_salt,
)
};
if let Some(ref mut output) = output {
extract_from_slice(output, output_len_ptr as usize);
}
ret_code.into()
}
fn call(
flags: CallFlags,
ref_time_limit: u64,
proof_size_limit: u64,
deposit_limit: &[u8; 32],
input: &[u8],
mut output: Option<&mut &mut [u8]>,
) -> Result {
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
let deposit_limit_ptr = deposit_limit.as_ptr();
let flags_and_callee = pack_hi_lo(flags.bits(), callee.as_ptr() as _);
let deposit_and_value = pack_hi_lo(deposit_limit_ptr as _, value.as_ptr() as _);
let input_data = pack_hi_lo(input.len() as _, input.as_ptr() as _);
let output_data = pack_hi_lo(&mut output_len as *mut _ as _, output_ptr as _);
let ret_code = unsafe {
sys::call(
flags_and_callee,
ref_time_limit,
proof_size_limit,
deposit_and_value,
input_data,
output_data,
)
};
if let Some(ref mut output) = output {
extract_from_slice(output, output_len as usize);
}
ret_code.into()
}
fn delegate_call(
flags: CallFlags,
address: &[u8; 20],
ref_time_limit: u64,
proof_size_limit: u64,
deposit_limit: &[u8; 32],
input: &[u8],
mut output: Option<&mut &mut [u8]>,
) -> Result {
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
let deposit_limit_ptr = deposit_limit.as_ptr();
let flags_and_callee = pack_hi_lo(flags.bits(), address.as_ptr() as u32);
let input_data = pack_hi_lo(input.len() as u32, input.as_ptr() as u32);
let output_data = pack_hi_lo(&mut output_len as *mut _ as u32, output_ptr as u32);
let ret_code = unsafe {
sys::delegate_call(
flags_and_callee,
ref_time_limit,
proof_size_limit,
deposit_limit_ptr as _,
input_data,
output_data,
)
};
if let Some(ref mut output) = output {
extract_from_slice(output, output_len as usize);
}
ret_code.into()
}
fn deposit_event(topics: &[[u8; 32]], data: &[u8]) {
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
unsafe {
sys::deposit_event(
topics.as_ptr(),
topics.len() as u32,
data.as_ptr(),
data.len() as u32,
)
}
}
fn set_storage(flags: StorageFlags, key: &[u8], encoded_value: &[u8]) -> Option<u32> {
let ret_code = unsafe {
sys::set_storage(
flags.bits(),
key.as_ptr(),
key.len() as u32,
encoded_value.as_ptr(),
encoded_value.len() as u32,
)
};
ret_code.into()
}
fn get_storage(flags: StorageFlags, key: &[u8], output: &mut &mut [u8]) -> Result {
let mut output_len = output.len() as u32;
let ret_code = {
unsafe {
sys::get_storage(
flags.bits(),
key.as_ptr(),
key.len() as u32,
output.as_mut_ptr(),
&mut output_len,
)
}
};
extract_from_slice(output, output_len as usize);
ret_code.into()
}
fn call_data_load(out_ptr: &mut [u8; 32], offset: u32) {
unsafe { sys::call_data_load(out_ptr.as_mut_ptr(), offset) };
fn gas_limit() -> u64 {
unsafe { sys::gas_limit() }
}
Cyrill Leutwiler
committed
fn call_data_size() -> u64 {
unsafe { sys::call_data_size() }
}
fn return_value(flags: ReturnFlags, return_value: &[u8]) -> ! {
unsafe { sys::seal_return(flags.bits(), return_value.as_ptr(), return_value.len() as u32) }
panic!("seal_return does not return");
}
fn gas_price() -> u64 {
unsafe { sys::gas_price() }
}
fn base_fee(output: &mut [u8; 32]) {
unsafe { sys::base_fee(output.as_mut_ptr()) }
}
fn balance(output: &mut [u8; 32]) {
unsafe { sys::balance(output.as_mut_ptr()) }
}
fn value_transferred(output: &mut [u8; 32]) {
unsafe { sys::value_transferred(output.as_mut_ptr()) }
}
fn now(output: &mut [u8; 32]) {
unsafe { sys::now(output.as_mut_ptr()) }
}
fn chain_id(output: &mut [u8; 32]) {
unsafe { sys::chain_id(output.as_mut_ptr()) }
fn address(output: &mut [u8; 20]) {
unsafe { sys::address(output.as_mut_ptr()) }
}
fn caller(output: &mut [u8; 20]) {
unsafe { sys::caller(output.as_mut_ptr()) }
}
fn origin(output: &mut [u8; 20]) {
unsafe { sys::origin(output.as_mut_ptr()) }
}
fn block_number(output: &mut [u8; 32]) {
unsafe { sys::block_number(output.as_mut_ptr()) }
fn block_author(output: &mut [u8; 20]) {
unsafe { sys::block_author(output.as_mut_ptr()) }
}
fn weight_to_fee(ref_time_limit: u64, proof_size_limit: u64, output: &mut [u8; 32]) {
unsafe { sys::weight_to_fee(ref_time_limit, proof_size_limit, output.as_mut_ptr()) };
}
fn hash_keccak_256(input: &[u8], output: &mut [u8; 32]) {
unsafe { sys::hash_keccak_256(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
}
fn get_immutable_data(output: &mut &mut [u8]) {
let mut output_len = output.len() as u32;
unsafe { sys::get_immutable_data(output.as_mut_ptr(), &mut output_len) };
extract_from_slice(output, output_len as usize);
}
fn set_immutable_data(data: &[u8]) {
unsafe { sys::set_immutable_data(data.as_ptr(), data.len() as u32) }
}
fn balance_of(address: &[u8; 20], output: &mut [u8; 32]) {
unsafe { sys::balance_of(address.as_ptr(), output.as_mut_ptr()) };
}
fn code_hash(address: &[u8; 20], output: &mut [u8; 32]) {
unsafe { sys::code_hash(address.as_ptr(), output.as_mut_ptr()) }
}
Cyrill Leutwiler
committed
fn code_size(address: &[u8; 20]) -> u64 {
unsafe { sys::code_size(address.as_ptr()) }
Cyrill Leutwiler
committed
fn return_data_size() -> u64 {
unsafe { sys::return_data_size() }
}
fn return_data_copy(output: &mut &mut [u8], offset: u32) {
let mut output_len = output.len() as u32;
{
unsafe { sys::return_data_copy(output.as_mut_ptr(), &mut output_len, offset) };
}
extract_from_slice(output, output_len as usize);
}
fn ref_time_left() -> u64 {
unsafe { sys::ref_time_left() }
}
#[unstable_hostfn]
fn to_account_id(address: &[u8; 20], output: &mut [u8]) {
unsafe { sys::to_account_id(address.as_ptr(), output.as_mut_ptr()) }
}
fn block_hash(block_number_ptr: &[u8; 32], output: &mut [u8; 32]) {
unsafe { sys::block_hash(block_number_ptr.as_ptr(), output.as_mut_ptr()) };
fn call_chain_extension(func_id: u32, input: &[u8], mut output: Option<&mut &mut [u8]>) -> u32 {
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
let ret_code = {
unsafe {
sys::call_chain_extension(
func_id,
input.as_ptr(),
input.len() as u32,
output_ptr,
&mut output_len,
)
}
};
if let Some(ref mut output) = output {
extract_from_slice(output, output_len as usize);
}
ret_code.into_u32()
}
fn call_data_copy(output: &mut [u8], offset: u32) {
let len = output.len() as u32;
unsafe { sys::call_data_copy(output.as_mut_ptr(), len, offset) };
}
fn call_runtime(call: &[u8]) -> Result {
let ret_code = unsafe { sys::call_runtime(call.as_ptr(), call.len() as u32) };
ret_code.into()
fn caller_is_origin() -> bool {
let ret_val = unsafe { sys::caller_is_origin() };
ret_val.into_bool()
fn caller_is_root() -> bool {
let ret_val = unsafe { sys::caller_is_root() };
ret_val.into_bool()
fn clear_storage(flags: StorageFlags, key: &[u8]) -> Option<u32> {
let ret_code = unsafe { sys::clear_storage(flags.bits(), key.as_ptr(), key.len() as u32) };
ret_code.into()
}
fn contains_storage(flags: StorageFlags, key: &[u8]) -> Option<u32> {
let ret_code =
unsafe { sys::contains_storage(flags.bits(), key.as_ptr(), key.len() as u32) };
ret_code.into()
fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result {
let ret_code = unsafe { sys::ecdsa_to_eth_address(pubkey.as_ptr(), output.as_mut_ptr()) };
ret_code.into()
}
#[unstable_hostfn]
fn hash_sha2_256(input: &[u8], output: &mut [u8; 32]) {
unsafe { sys::hash_sha2_256(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
}
#[unstable_hostfn]
fn hash_blake2_256(input: &[u8], output: &mut [u8; 32]) {
unsafe { sys::hash_blake2_256(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
}
#[unstable_hostfn]
fn hash_blake2_128(input: &[u8], output: &mut [u8; 16]) {
unsafe { sys::hash_blake2_128(input.as_ptr(), input.len() as u32, output.as_mut_ptr()) }
}
#[unstable_hostfn]
fn is_contract(address: &[u8; 20]) -> bool {
let ret_val = unsafe { sys::is_contract(address.as_ptr()) };
ret_val.into_bool()
}
#[unstable_hostfn]
fn minimum_balance(output: &mut [u8; 32]) {
unsafe { sys::minimum_balance(output.as_mut_ptr()) }
}
#[unstable_hostfn]
fn own_code_hash(output: &mut [u8; 32]) {
unsafe { sys::own_code_hash(output.as_mut_ptr()) }
fn set_code_hash(code_hash: &[u8; 32]) {
unsafe { sys::set_code_hash(code_hash.as_ptr()) }
fn sr25519_verify(signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> Result {
let ret_code = unsafe {
sys::sr25519_verify(
signature.as_ptr(),
pub_key.as_ptr(),
message.len() as u32,
message.as_ptr(),
)
};
ret_code.into()
fn take_storage(flags: StorageFlags, key: &[u8], output: &mut &mut [u8]) -> Result {
let mut output_len = output.len() as u32;
let ret_code = {
unsafe {
sys::take_storage(
flags.bits(),
key.as_ptr(),
key.len() as u32,
output.as_mut_ptr(),
&mut output_len,
)
}
};
extract_from_slice(output, output_len as usize);
ret_code.into()
fn terminate(beneficiary: &[u8; 20]) -> ! {
unsafe { sys::terminate(beneficiary.as_ptr()) }
panic!("terminate does not return");
fn weight_left(output: &mut &mut [u8]) {
let mut output_len = output.len() as u32;
unsafe { sys::weight_left(output.as_mut_ptr(), &mut output_len) }
extract_from_slice(output, output_len as usize)
}
fn xcm_execute(msg: &[u8]) -> Result {
let ret_code = unsafe { sys::xcm_execute(msg.as_ptr(), msg.len() as _) };
ret_code.into()
}
fn xcm_send(dest: &[u8], msg: &[u8], output: &mut [u8; 32]) -> Result {
let ret_code = unsafe {
sys::xcm_send(
dest.as_ptr(),
dest.len() as _,
msg.as_ptr(),
msg.len() as _,
output.as_mut_ptr(),
)
};
ret_code.into()
}
#[unstable_hostfn]
fn new_query(responder: &[u8], maybe_notify: &[u8], timeout: &[u8], output: &mut [u8; 32]) -> Result {
let ret_code = unsafe {
sys::new_query(
responder.as_ptr(),
responder.len() as _,
maybe_notify.as_ptr(),
maybe_notify.len() as _,
timeout.as_ptr(),
output.as_mut_ptr(),
)
};
ret_code.into()
}