feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// 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.
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// Flags used by a contract to customize exit behaviour.
|
||||
#[cfg_attr(feature = "scale", derive(codec::Encode, codec::Decode, scale_info::TypeInfo))]
|
||||
pub struct ReturnFlags: u32 {
|
||||
/// If this bit is set all changes made by the contract execution are rolled back.
|
||||
const REVERT = 0x0000_0001;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags used to change the behaviour of `seal_call` and `seal_delegate_call`.
|
||||
pub struct CallFlags: u32 {
|
||||
/// Forward the input of current function to the callee.
|
||||
///
|
||||
/// Supplied input pointers are ignored when set.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// A forwarding call will consume the current contracts input. Any attempt to
|
||||
/// access the input after this call returns will lead to [`Error::InputForwarded`].
|
||||
/// It does not matter if this is due to calling `seal_input` or trying another
|
||||
/// forwarding call. Consider using [`Self::CLONE_INPUT`] in order to preserve
|
||||
/// the input.
|
||||
const FORWARD_INPUT = 0b0000_0001;
|
||||
/// Identical to [`Self::FORWARD_INPUT`] but without consuming the input.
|
||||
///
|
||||
/// This adds some additional weight costs to the call.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This implies [`Self::FORWARD_INPUT`] and takes precedence when both are set.
|
||||
const CLONE_INPUT = 0b0000_0010;
|
||||
/// Do not return from the call but rather return the result of the callee to the
|
||||
/// callers caller.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This makes the current contract completely transparent to its caller by replacing
|
||||
/// this contracts potential output by the callee ones. Any code after `seal_call`
|
||||
/// can be safely considered unreachable.
|
||||
const TAIL_CALL = 0b0000_0100;
|
||||
/// Allow the callee to reenter into the current contract.
|
||||
///
|
||||
/// Without this flag any reentrancy into the current contract that originates from
|
||||
/// the callee (or any of its callees) is denied. This includes the first callee:
|
||||
/// You cannot call into yourself with this flag set.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// For `seal_delegate_call` should be always unset, otherwise
|
||||
/// [`Error::InvalidCallFlags`] is returned.
|
||||
const ALLOW_REENTRY = 0b0000_1000;
|
||||
/// Indicates that the callee is restricted from modifying the state during call execution,
|
||||
/// equivalent to Ethereum's STATICCALL.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// For `seal_delegate_call` should be always unset, otherwise
|
||||
/// [`Error::InvalidCallFlags`] is returned.
|
||||
const READ_ONLY = 0b0001_0000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,885 @@
|
||||
// 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.
|
||||
use crate::{CallFlags, Result, ReturnFlags};
|
||||
use paste::paste;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod wasm32;
|
||||
|
||||
macro_rules! hash_fn {
|
||||
( $name:ident, $bytes:literal ) => {
|
||||
paste! {
|
||||
#[doc = "Computes the " $name " " $bytes "-bit hash on the given input buffer."]
|
||||
#[doc = "\n# Notes\n"]
|
||||
#[doc = "- The `input` and `output` buffer may overlap."]
|
||||
#[doc = "- The output buffer is expected to hold at least " $bytes " bits."]
|
||||
#[doc = "- It is the callers responsibility to provide an output buffer that is large enough to hold the expected amount of bytes returned by the hash function."]
|
||||
#[doc = "\n# Parameters\n"]
|
||||
#[doc = "- `input`: The input data buffer."]
|
||||
#[doc = "- `output`: The output buffer to write the hash result to."]
|
||||
fn [<hash_ $name>](input: &[u8], output: &mut [u8; $bytes]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TODO remove cfg once used by all targets
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[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];
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[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),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[inline(always)]
|
||||
fn ptr_or_sentinel(data: &Option<&[u8]>) -> *const u8 {
|
||||
match data {
|
||||
Some(ref data) => data.as_ptr(),
|
||||
None => crate::SENTINEL as _,
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements [`HostFn`] for each supported target architecture.
|
||||
pub enum HostFnImpl {}
|
||||
|
||||
/// Defines all the host apis implemented by the wasm vm.
|
||||
pub trait HostFn: private::Sealed {
|
||||
/// Returns the number of times specified contract exists on the call stack. Delegated calls are
|
||||
/// not counted as separate calls.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `account`: The contract address. Should be decodable as an `T::AccountId`. Traps
|
||||
/// otherwise.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the number of times specified contract exists on the call stack.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn account_reentrance_count(account: &[u8]) -> u32;
|
||||
|
||||
/// Stores the address of the current contract into the supplied buffer.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the address.
|
||||
fn address(output: &mut &mut [u8]);
|
||||
|
||||
/// Lock a new delegate dependency to the contract.
|
||||
///
|
||||
/// Traps if the maximum number of delegate_dependencies is reached or if
|
||||
/// the delegate dependency already exists.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `code_hash`: The code hash of the dependency. Should be decodable as an `T::Hash`. Traps
|
||||
/// otherwise.
|
||||
fn lock_delegate_dependency(code_hash: &[u8]);
|
||||
|
||||
/// Stores the *free* balance of the current account into the supplied buffer.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the balance.
|
||||
fn balance(output: &mut &mut [u8]);
|
||||
|
||||
/// Stores the current block number of the current contract into the supplied buffer.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the block number.
|
||||
fn block_number(output: &mut &mut [u8]);
|
||||
|
||||
/// Make a call to another contract.
|
||||
///
|
||||
/// This is equivalent to calling the newer version of this function with
|
||||
/// `flags` set to [`CallFlags::ALLOW_REENTRY`]. See the newer version for documentation.
|
||||
#[deprecated(note = "Deprecated, use newer version instead")]
|
||||
fn call(
|
||||
callee: &[u8],
|
||||
gas: u64,
|
||||
value: &[u8],
|
||||
input_data: &[u8],
|
||||
output: Option<&mut &mut [u8]>,
|
||||
) -> Result;
|
||||
|
||||
/// Make a call to another contract.
|
||||
///
|
||||
/// Equivalent to the newer [`Self::call_v2`] version but works with
|
||||
/// *ref_time* Weight only
|
||||
#[deprecated(note = "Deprecated, use newer version instead")]
|
||||
fn call_v1(
|
||||
flags: CallFlags,
|
||||
callee: &[u8],
|
||||
gas: u64,
|
||||
value: &[u8],
|
||||
input_data: &[u8],
|
||||
output: Option<&mut &mut [u8]>,
|
||||
) -> Result;
|
||||
|
||||
/// Call (possibly transferring some amount of funds) into the specified account.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `flags`: See [`CallFlags`] for a documentation of the supported flags.
|
||||
/// - `callee`: The address of the callee. Should be decodable as an `T::AccountId`. Traps
|
||||
/// otherwise.
|
||||
/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
|
||||
/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
|
||||
/// - `deposit`: The storage deposit limit for instantiation. Should be decodable as a
|
||||
/// `Option<T::Balance>`. Traps otherwise. Passing `None` means setting no specific limit for
|
||||
/// the call, which implies storage usage up to the limit of the parent call.
|
||||
/// - `value`: The value to transfer into the contract. Should be decodable as a `T::Balance`.
|
||||
/// Traps otherwise.
|
||||
/// - `input`: The input data buffer used to call the contract.
|
||||
/// - `output`: A reference to the output data buffer to write the call output buffer. If `None`
|
||||
/// is provided then the output buffer is not copied.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error means that the call wasn't successful output buffer is returned unless
|
||||
/// stated otherwise.
|
||||
///
|
||||
/// - [CalleeReverted][`crate::ReturnErrorCode::CalleeReverted]: Output buffer is returned.
|
||||
/// - [CalleeTrapped][`crate::ReturnErrorCode::CalleeTrapped]
|
||||
/// - [TransferFailed][`crate::ReturnErrorCode::TransferFailed]
|
||||
/// - [NotCallable][`crate::ReturnErrorCode::NotCallable]
|
||||
fn call_v2(
|
||||
flags: CallFlags,
|
||||
callee: &[u8],
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
deposit: Option<&[u8]>,
|
||||
value: &[u8],
|
||||
input_data: &[u8],
|
||||
output: Option<&mut &mut [u8]>,
|
||||
) -> Result;
|
||||
|
||||
/// Call into the chain extension provided by the chain if any.
|
||||
///
|
||||
/// Handling of the input values is up to the specific chain extension and so is the
|
||||
/// return value. The extension can decide to use the inputs as primitive inputs or as
|
||||
/// in/out arguments by interpreting them as pointers. Any caller of this function
|
||||
/// must therefore coordinate with the chain that it targets.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If no chain extension exists the contract will trap with the `NoChainExtension`
|
||||
/// module error.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `func_id`: The function id of the chain extension.
|
||||
/// - `input`: The input data buffer.
|
||||
/// - `output`: A reference to the output data buffer to write the call output buffer. If `None`
|
||||
/// is provided then the output buffer is not copied.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// The chain extension returned value, if executed successfully.
|
||||
fn call_chain_extension(func_id: u32, input: &[u8], output: Option<&mut &mut [u8]>) -> u32;
|
||||
|
||||
/// Call some dispatchable of the runtime.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `call`: The call data.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns `Error::Success` when the dispatchable was successfully executed and
|
||||
/// returned `Ok`. When the dispatchable was executed but returned an error
|
||||
/// `Error::CallRuntimeFailed` is returned. The full error is not
|
||||
/// provided because it is not guaranteed to be stable.
|
||||
///
|
||||
/// # Comparison with `ChainExtension`
|
||||
///
|
||||
/// Just as a chain extension this API allows the runtime to extend the functionality
|
||||
/// of contracts. While making use of this function is generally easier it cannot be
|
||||
/// used in all cases. Consider writing a chain extension if you need to do perform
|
||||
/// one of the following tasks:
|
||||
///
|
||||
/// - Return data.
|
||||
/// - Provide functionality **exclusively** to contracts.
|
||||
/// - Provide custom weights.
|
||||
/// - Avoid the need to keep the `Call` data structure stable.
|
||||
fn call_runtime(call: &[u8]) -> Result;
|
||||
|
||||
/// Stores the address of the caller into the supplied buffer.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the
|
||||
/// extrinsic will be returned. Otherwise, if this call is initiated by another contract then
|
||||
/// the address of the contract will be returned.
|
||||
///
|
||||
/// If there is no address associated with the caller (e.g. because the caller is root) then
|
||||
/// it traps with `BadOrigin`.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the caller address.
|
||||
fn caller(output: &mut &mut [u8]);
|
||||
|
||||
/// Checks whether the caller of the current contract is the origin of the whole call stack.
|
||||
///
|
||||
/// Prefer this over [`is_contract()`][`Self::is_contract`] when checking whether your contract
|
||||
/// is being called by a contract or a plain account. The reason is that it performs better
|
||||
/// since it does not need to do any storage lookups.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// A return value of `true` indicates that this contract is being called by a plain account
|
||||
/// and `false` indicates that the caller is another contract.
|
||||
fn caller_is_origin() -> bool;
|
||||
|
||||
/// Checks whether the caller of the current contract is root.
|
||||
///
|
||||
/// Note that only the origin of the call stack can be root. Hence this function returning
|
||||
/// `true` implies that the contract is being called by the origin.
|
||||
///
|
||||
/// A return value of `true` indicates that this contract is being called by a root origin,
|
||||
/// and `false` indicates that the caller is a signed origin.
|
||||
fn caller_is_root() -> u32;
|
||||
|
||||
/// Clear the value at the given key in the contract storage.
|
||||
///
|
||||
/// Equivalent to the newer [`Self::clear_storage_v1`] version with
|
||||
/// the exception of the return type. Still a valid thing to call when not interested in the
|
||||
/// return value.
|
||||
fn clear_storage(key: &[u8]);
|
||||
|
||||
/// Clear the value at the given key in the contract storage.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `key`: The storage key.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the size of the pre-existing value at the specified key if any.
|
||||
fn clear_storage_v1(key: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Clear the value at the given key in the contract transient storage.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `key`: The storage key.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the size of the pre-existing value at the specified key if any.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn clear_transient_storage(key: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Retrieve the code hash for a specified contract address.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `account_id`: The address of the contract.Should be decodable as an `T::AccountId`. Traps
|
||||
/// otherwise.
|
||||
/// - `output`: A reference to the output data buffer to write the code hash.
|
||||
///
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [CodeNotFound][`crate::ReturnErrorCode::CodeNotFound]
|
||||
fn code_hash(account_id: &[u8], output: &mut [u8]) -> Result;
|
||||
|
||||
/// Checks whether there is a value stored under the given key.
|
||||
///
|
||||
/// This version is to be used with a fixed sized storage key. For runtimes supporting
|
||||
/// transparent hashing, please use the newer version of this function.
|
||||
fn contains_storage(key: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Checks whether there is a value stored under the given key.
|
||||
///
|
||||
/// The key length must not exceed the maximum defined by the contracts module parameter.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `key`: The storage key.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the size of the pre-existing value at the specified key if any.
|
||||
fn contains_storage_v1(key: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Checks whether there is a value stored under the given key in transient storage.
|
||||
///
|
||||
/// The key length must not exceed the maximum defined by the contracts module parameter.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `key`: The storage key.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the size of the pre-existing value at the specified key if any.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn contains_transient_storage(key: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Emit a custom debug message.
|
||||
///
|
||||
/// No newlines are added to the supplied message.
|
||||
/// Specifying invalid UTF-8 just drops the message with no trap.
|
||||
///
|
||||
/// This is a no-op if debug message recording is disabled which is always the case
|
||||
/// when the code is executing on-chain. The message is interpreted as UTF-8 and
|
||||
/// appended to the debug buffer which is then supplied to the calling RPC client.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Even though no action is taken when debug message recording is disabled there is still
|
||||
/// a non trivial overhead (and weight cost) associated with calling this function. Contract
|
||||
/// languages should remove calls to this function (either at runtime or compile time) when
|
||||
/// not being executed as an RPC. For example, they could allow users to disable logging
|
||||
/// through compile time flags (cargo features) for on-chain deployment. Additionally, the
|
||||
/// return value of this function can be cached in order to prevent further calls at runtime.
|
||||
fn debug_message(str: &[u8]) -> Result;
|
||||
|
||||
/// Execute code in the context (storage, caller, value) of the current contract.
|
||||
///
|
||||
/// Reentrancy protection is always disabled since the callee is allowed
|
||||
/// to modify the callers storage. This makes going through a reentrancy attack
|
||||
/// unnecessary for the callee when it wants to exploit the caller.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `flags`: See [`CallFlags`] for a documentation of the supported flags.
|
||||
/// - `code_hash`: The hash of the code to be executed.
|
||||
/// - `input`: The input data buffer used to call the contract.
|
||||
/// - `output`: A reference to the output data buffer to write the call output buffer. If `None`
|
||||
/// is provided then the output buffer is not copied.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error means that the call wasn't successful and no output buffer is returned unless
|
||||
/// stated otherwise.
|
||||
///
|
||||
/// - [CalleeReverted][`crate::ReturnErrorCode::CalleeReverted]: Output buffer is returned.
|
||||
/// - [CalleeTrapped][`crate::ReturnErrorCode::CalleeTrapped]
|
||||
/// - [CodeNotFound][`crate::ReturnErrorCode::CodeNotFound]
|
||||
fn delegate_call(
|
||||
flags: CallFlags,
|
||||
code_hash: &[u8],
|
||||
input_data: &[u8],
|
||||
output: Option<&mut &mut [u8]>,
|
||||
) -> Result;
|
||||
|
||||
/// Deposit a contract event with the data buffer and optional list of topics. There is a limit
|
||||
/// on the maximum number of topics specified by `event_topics`.
|
||||
///
|
||||
/// There should not be any duplicates in `topics`.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `topics`: The topics list encoded as `Vec<T::Hash>`. It can't contain duplicates.
|
||||
fn deposit_event(topics: &[u8], data: &[u8]);
|
||||
|
||||
/// Recovers the ECDSA public key from the given message hash and signature.
|
||||
///
|
||||
/// Writes the public key into the given output buffer.
|
||||
/// Assumes the secp256k1 curve.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `signature`: The signature bytes.
|
||||
/// - `message_hash`: The message hash bytes.
|
||||
/// - `output`: A reference to the output data buffer to write the public key.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [EcdsaRecoveryFailed][`crate::ReturnErrorCode::EcdsaRecoveryFailed]
|
||||
fn ecdsa_recover(
|
||||
signature: &[u8; 65],
|
||||
message_hash: &[u8; 32],
|
||||
output: &mut [u8; 33],
|
||||
) -> Result;
|
||||
|
||||
/// Calculates Ethereum address from the ECDSA compressed public key and stores
|
||||
/// it into the supplied buffer.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `pubkey`: The public key bytes.
|
||||
/// - `output`: A reference to the output data buffer to write the address.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [EcdsaRecoveryFailed][`crate::ReturnErrorCode::EcdsaRecoveryFailed]
|
||||
fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result;
|
||||
|
||||
/// Stores the weight left into the supplied buffer.
|
||||
///
|
||||
/// Equivalent to the newer [`Self::gas_left_v1`] version but
|
||||
/// works with *ref_time* Weight only.
|
||||
fn gas_left(out: &mut &mut [u8]);
|
||||
|
||||
/// Stores the amount of weight left into the supplied buffer.
|
||||
/// The data is encoded as Weight.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the weight left.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn gas_left_v1(output: &mut &mut [u8]);
|
||||
|
||||
/// Retrieve the value under the given key from storage.
|
||||
///
|
||||
/// This version is to be used with a fixed sized storage key. For runtimes supporting
|
||||
/// transparent hashing, please use the newer version of this function.
|
||||
fn get_storage(key: &[u8], output: &mut &mut [u8]) -> Result;
|
||||
|
||||
/// Retrieve the value under the given key from storage.
|
||||
///
|
||||
/// The key length must not exceed the maximum defined by the contracts module parameter.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `key`: The storage key.
|
||||
/// - `output`: A reference to the output data buffer to write the storage entry.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// [KeyNotFound][`crate::ReturnErrorCode::KeyNotFound]
|
||||
fn get_storage_v1(key: &[u8], output: &mut &mut [u8]) -> Result;
|
||||
|
||||
/// Retrieve the value under the given key from transient storage.
|
||||
///
|
||||
/// The key length must not exceed the maximum defined by the contracts module parameter.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `key`: The storage key.
|
||||
/// - `output`: A reference to the output data buffer to write the storage entry.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// [KeyNotFound][`crate::ReturnErrorCode::KeyNotFound]
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn get_transient_storage(key: &[u8], output: &mut &mut [u8]) -> Result;
|
||||
|
||||
hash_fn!(sha2_256, 32);
|
||||
hash_fn!(keccak_256, 32);
|
||||
hash_fn!(blake2_256, 32);
|
||||
hash_fn!(blake2_128, 16);
|
||||
|
||||
/// Stores the input passed by the caller into the supplied buffer.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This function traps if:
|
||||
/// - the input is larger than the available space.
|
||||
/// - the input was previously forwarded by a [`call()`][`Self::call()`].
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the input data.
|
||||
fn input(output: &mut &mut [u8]);
|
||||
|
||||
/// Instantiate a contract with the specified code hash.
|
||||
///
|
||||
/// Equivalent to the newer [`Self::instantiate_v2`] version but works
|
||||
/// with *ref_time* Weight only.
|
||||
#[deprecated(note = "Deprecated, use newer version instead")]
|
||||
fn instantiate_v1(
|
||||
code_hash: &[u8],
|
||||
gas: u64,
|
||||
value: &[u8],
|
||||
input: &[u8],
|
||||
address: Option<&mut &mut [u8]>,
|
||||
output: Option<&mut &mut [u8]>,
|
||||
salt: &[u8],
|
||||
) -> Result;
|
||||
|
||||
/// Instantiate a contract with the specified code hash.
|
||||
///
|
||||
/// This function creates an account and executes the constructor defined in the code specified
|
||||
/// by the code hash.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `code_hash`: The hash of the code to be instantiated.
|
||||
/// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution.
|
||||
/// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution.
|
||||
/// - `deposit`: The storage deposit limit for instantiation. Should be decodable as a
|
||||
/// `Option<T::Balance>`. Traps otherwise. Passing `None` means setting no specific limit for
|
||||
/// the call, which implies storage usage up to the limit of the parent call.
|
||||
/// - `value`: The value to transfer into the contract. Should be decodable as a `T::Balance`.
|
||||
/// Traps otherwise.
|
||||
/// - `input`: The input data buffer.
|
||||
/// - `address`: A reference to the address buffer to write the address of the contract. If
|
||||
/// `None` is provided then the output buffer is not copied.
|
||||
/// - `output`: A reference to the return value buffer to write the constructor output buffer.
|
||||
/// If `None` is provided then the output buffer is not copied.
|
||||
/// - `salt`: The salt bytes to use for this instantiation.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Please consult the [ReturnErrorCode][`crate::ReturnErrorCode`] enum declaration for more
|
||||
/// information on those errors. Here we only note things specific to this function.
|
||||
///
|
||||
/// An error means that the account wasn't created and no address or output buffer
|
||||
/// is returned unless stated otherwise.
|
||||
///
|
||||
/// - [CalleeReverted][`crate::ReturnErrorCode::CalleeReverted]: Output buffer is returned.
|
||||
/// - [CalleeTrapped][`crate::ReturnErrorCode::CalleeTrapped]
|
||||
/// - [TransferFailed][`crate::ReturnErrorCode::TransferFailed]
|
||||
/// - [CodeNotFound][`crate::ReturnErrorCode::CodeNotFound]
|
||||
fn instantiate_v2(
|
||||
code_hash: &[u8],
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
deposit: Option<&[u8]>,
|
||||
value: &[u8],
|
||||
input: &[u8],
|
||||
address: Option<&mut &mut [u8]>,
|
||||
output: Option<&mut &mut [u8]>,
|
||||
salt: &[u8],
|
||||
) -> Result;
|
||||
|
||||
/// Returns a nonce that is unique per contract instantiation.
|
||||
///
|
||||
/// The nonce is incremented for each successful contract instantiation. This is a
|
||||
/// sensible default salt for contract instantiations.
|
||||
fn instantiation_nonce() -> u64;
|
||||
|
||||
/// Checks whether a specified address belongs to a contract.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `account_id`: The address to check. Should be decodable as an `T::AccountId`. Traps
|
||||
/// otherwise.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns `true` if the address belongs to a contract.
|
||||
fn is_contract(account_id: &[u8]) -> bool;
|
||||
|
||||
/// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer.
|
||||
/// The data is encoded as `T::Balance`.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the minimum balance.
|
||||
fn minimum_balance(output: &mut &mut [u8]);
|
||||
|
||||
/// Retrieve the code hash of the currently executing contract.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the code hash.
|
||||
fn own_code_hash(output: &mut [u8]);
|
||||
|
||||
/// Load the latest block timestamp into the supplied buffer
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the timestamp.
|
||||
fn now(output: &mut &mut [u8]);
|
||||
|
||||
/// Returns the number of times the currently executing contract exists on the call stack in
|
||||
/// addition to the calling instance.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns `0` when there is no reentrancy.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn reentrance_count() -> u32;
|
||||
|
||||
/// Removes the delegate dependency from the contract.
|
||||
///
|
||||
/// Traps if the delegate dependency does not exist.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `code_hash`: The code hash of the dependency. Should be decodable as an `T::Hash`. Traps
|
||||
/// otherwise.
|
||||
fn unlock_delegate_dependency(code_hash: &[u8]);
|
||||
|
||||
/// Cease contract execution and save a data buffer as a result of the execution.
|
||||
///
|
||||
/// This function never returns as it stops execution of the caller.
|
||||
/// This is the only way to return a data buffer to the caller. Returning from
|
||||
/// execution without calling this function is equivalent to calling:
|
||||
/// ```nocompile
|
||||
/// return_value(ReturnFlags::empty(), &[])
|
||||
/// ```
|
||||
///
|
||||
/// Using an unnamed non empty `ReturnFlags` triggers a trap.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `flags`: Flag used to signal special return conditions to the supervisor. See
|
||||
/// [`ReturnFlags`] for a documentation of the supported flags.
|
||||
/// - `return_value`: The return value buffer.
|
||||
fn return_value(flags: ReturnFlags, return_value: &[u8]) -> !;
|
||||
|
||||
/// Replace the contract code at the specified address with new code.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// There are a couple of important considerations which must be taken into account when
|
||||
/// using this API:
|
||||
///
|
||||
/// 1. The storage at the code address will remain untouched. This means that contract
|
||||
/// developers must ensure that the storage layout of the new code is compatible with that of
|
||||
/// the old code.
|
||||
///
|
||||
/// 2. Contracts using this API can't be assumed as having deterministic addresses. Said another
|
||||
/// way, when using this API you lose the guarantee that an address always identifies a specific
|
||||
/// code hash.
|
||||
///
|
||||
/// 3. If a contract calls into itself after changing its code the new call would use
|
||||
/// the new code. However, if the original caller panics after returning from the sub call it
|
||||
/// would revert the changes made by [`set_code_hash()`][`Self::set_code_hash`] and the next
|
||||
/// caller would use the old code.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `code_hash`: The hash of the new code. Should be decodable as an `T::Hash`. Traps
|
||||
/// otherwise.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [CodeNotFound][`crate::ReturnErrorCode::CodeNotFound]
|
||||
fn set_code_hash(code_hash: &[u8]) -> Result;
|
||||
|
||||
/// Set the value at the given key in the contract storage.
|
||||
///
|
||||
/// Equivalent to [`Self::set_storage_v1`] version with the
|
||||
/// exception of the return type. Still a valid thing to call for fixed sized storage key, when
|
||||
/// not interested in the return value.
|
||||
fn set_storage(key: &[u8], value: &[u8]);
|
||||
|
||||
/// Set the value at the given key in the contract storage.
|
||||
///
|
||||
/// This version is to be used with a fixed sized storage key. For runtimes supporting
|
||||
/// transparent hashing, please use the newer version of this function.
|
||||
fn set_storage_v1(key: &[u8], value: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Set the value at the given key in the contract storage.
|
||||
///
|
||||
/// The key and value lengths must not exceed the maximums defined by the contracts module
|
||||
/// parameters.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `key`: The storage key.
|
||||
/// - `encoded_value`: The storage value.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the size of the pre-existing value at the specified key if any.
|
||||
fn set_storage_v2(key: &[u8], value: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Set the value at the given key in the contract transient storage.
|
||||
///
|
||||
/// The key and value lengths must not exceed the maximums defined by the contracts module
|
||||
/// parameters.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `key`: The storage key.
|
||||
/// - `encoded_value`: The storage value.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns the size of the pre-existing value at the specified key if any.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn set_transient_storage(key: &[u8], value: &[u8]) -> Option<u32>;
|
||||
|
||||
/// Verify a sr25519 signature
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `signature`: The signature bytes.
|
||||
/// - `message`: The message bytes.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [Sr25519VerifyFailed][`crate::ReturnErrorCode::Sr25519VerifyFailed]
|
||||
fn sr25519_verify(signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> Result;
|
||||
|
||||
/// Retrieve and remove the value under the given key from storage.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `key`: The storage key.
|
||||
/// - `output`: A reference to the output data buffer to write the storage entry.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// [KeyNotFound][`crate::ReturnErrorCode::KeyNotFound]
|
||||
fn take_storage(key: &[u8], output: &mut &mut [u8]) -> Result;
|
||||
|
||||
/// Retrieve and remove the value under the given key from transient storage.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `key`: The storage key.
|
||||
/// - `output`: A reference to the output data buffer to write the storage entry.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// [KeyNotFound][`crate::ReturnErrorCode::KeyNotFound]
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn take_transient_storage(key: &[u8], output: &mut &mut [u8]) -> Result;
|
||||
|
||||
/// Transfer some amount of funds into the specified account.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `account_id`: The address of the account to transfer funds to. Should be decodable as an
|
||||
/// `T::AccountId`. Traps otherwise.
|
||||
/// - `value`: The value to transfer. Should be decodable as a `T::Balance`. Traps otherwise.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [TransferFailed][`crate::ReturnErrorCode::TransferFailed]
|
||||
fn transfer(account_id: &[u8], value: &[u8]) -> Result;
|
||||
|
||||
/// Remove the calling account and transfer remaining balance.
|
||||
///
|
||||
/// This is equivalent to calling the newer version of this function
|
||||
#[deprecated(note = "Deprecated, use newer version instead")]
|
||||
fn terminate(beneficiary: &[u8]) -> !;
|
||||
|
||||
/// Remove the calling account and transfer remaining **free** balance.
|
||||
///
|
||||
/// This function never returns. Either the termination was successful and the
|
||||
/// execution of the destroyed contract is halted. Or it failed during the termination
|
||||
/// which is considered fatal and results in a trap + rollback.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `beneficiary`: The address of the beneficiary account, Should be decodable as an
|
||||
/// `T::AccountId`.
|
||||
///
|
||||
/// # Traps
|
||||
///
|
||||
/// - The contract is live i.e is already on the call stack.
|
||||
/// - Failed to send the balance to the beneficiary.
|
||||
/// - The deletion queue is full.
|
||||
fn terminate_v1(beneficiary: &[u8]) -> !;
|
||||
|
||||
/// Stores the value transferred along with this call/instantiate into the supplied buffer.
|
||||
/// The data is encoded as `T::Balance`.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `output`: A reference to the output data buffer to write the transferred value.
|
||||
fn value_transferred(output: &mut &mut [u8]);
|
||||
|
||||
/// Stores the price for the specified amount of gas into the supplied buffer.
|
||||
///
|
||||
/// Equivalent to the newer [`Self::weight_to_fee_v1`] version but
|
||||
/// works with *ref_time* Weight only. It is recommended to switch to the latest version, once
|
||||
/// it's stabilized.
|
||||
fn weight_to_fee(gas: u64, output: &mut &mut [u8]);
|
||||
|
||||
/// Stores the price for the specified amount of gas into the supplied buffer.
|
||||
/// The data is encoded as `T::Balance`.
|
||||
///
|
||||
/// If the available space in `output` is less than the size of the value a trap is triggered.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `ref_time_limit`: The *ref_time* Weight limit to query the price for.
|
||||
/// - `proof_size_limit`: The *proof_size* Weight limit to query the price for.
|
||||
/// - `output`: A reference to the output data buffer to write the price.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn weight_to_fee_v1(ref_time_limit: u64, proof_size_limit: u64, output: &mut &mut [u8]);
|
||||
|
||||
/// Execute an XCM program locally, using the contract's address as the origin.
|
||||
/// This is equivalent to dispatching `pezpallet_xcm::execute` through call_runtime, except that
|
||||
/// the function is called directly instead of being dispatched.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `msg`: The message, should be decodable as a [VersionedXcm](https://docs.pezkuwichain.io/sdk/master/pezstaging_xcm/enum.VersionedXcm.html),
|
||||
/// traps otherwise.
|
||||
/// - `output`: A reference to the output data buffer to write the [Outcome](https://docs.pezkuwichain.io/sdk/master/pezstaging_xcm/v3/enum.Outcome.html)
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns `Error::Success` when the XCM execution attempt is successful. When the XCM
|
||||
/// execution fails, `ReturnCode::XcmExecutionFailed` is returned
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn xcm_execute(msg: &[u8]) -> Result;
|
||||
|
||||
/// Send an XCM program from the contract to the specified destination.
|
||||
/// This is equivalent to dispatching `pezpallet_xcm::send` through `call_runtime`, except that
|
||||
/// the function is called directly instead of being dispatched.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `dest`: The XCM destination, should be decodable as [VersionedLocation](https://docs.pezkuwichain.io/sdk/master/pezstaging_xcm/enum.VersionedLocation.html),
|
||||
/// traps otherwise.
|
||||
/// - `msg`: The message, should be decodable as a [VersionedXcm](https://docs.pezkuwichain.io/sdk/master/pezstaging_xcm/enum.VersionedXcm.html),
|
||||
/// traps otherwise.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns `ReturnCode::Success` when the message was successfully sent. When the XCM
|
||||
/// execution fails, `ReturnErrorCode::XcmSendFailed` is returned.
|
||||
#[deprecated(
|
||||
note = "Unstable function. Behaviour can change without further notice. Use only for testing."
|
||||
)]
|
||||
fn xcm_send(dest: &[u8], msg: &[u8], output: &mut [u8; 32]) -> Result;
|
||||
}
|
||||
|
||||
mod private {
|
||||
pub trait Sealed {}
|
||||
impl Sealed for super::HostFnImpl {}
|
||||
}
|
||||
@@ -0,0 +1,915 @@
|
||||
// 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.
|
||||
use super::{
|
||||
extract_from_slice, ptr_len_or_sentinel, ptr_or_sentinel, CallFlags, HostFn, HostFnImpl, Result,
|
||||
};
|
||||
use crate::{ReturnCode, ReturnFlags};
|
||||
|
||||
mod sys {
|
||||
use super::ReturnCode;
|
||||
|
||||
#[link(wasm_import_module = "seal0")]
|
||||
extern "C" {
|
||||
pub fn account_reentrance_count(account_ptr: *const u8) -> u32;
|
||||
|
||||
pub fn lock_delegate_dependency(code_hash_ptr: *const u8);
|
||||
|
||||
pub fn address(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn balance(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn block_number(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn call(
|
||||
callee_ptr: *const u8,
|
||||
callee_len: u32,
|
||||
gas: u64,
|
||||
value_ptr: *const u8,
|
||||
value_len: u32,
|
||||
input_data_ptr: *const u8,
|
||||
input_data_len: u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn call_chain_extension(
|
||||
func_id: u32,
|
||||
input_ptr: *const u8,
|
||||
input_len: u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn call_runtime(call_ptr: *const u8, call_len: u32) -> ReturnCode;
|
||||
|
||||
pub fn caller(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn caller_is_origin() -> ReturnCode;
|
||||
|
||||
pub fn caller_is_root() -> ReturnCode;
|
||||
|
||||
pub fn clear_storage(key_ptr: *const u8);
|
||||
|
||||
pub fn clear_transient_storage(key_ptr: *const u8, key_len: u32) -> ReturnCode;
|
||||
|
||||
pub fn code_hash(
|
||||
account_id_ptr: *const u8,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn contains_storage(key_ptr: *const u8) -> ReturnCode;
|
||||
|
||||
pub fn contains_transient_storage(key_ptr: *const u8, key_len: u32) -> ReturnCode;
|
||||
|
||||
pub fn debug_message(str_ptr: *const u8, str_len: u32) -> ReturnCode;
|
||||
|
||||
pub fn delegate_call(
|
||||
flags: u32,
|
||||
code_hash_ptr: *const u8,
|
||||
input_data_ptr: *const u8,
|
||||
input_data_len: u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn deposit_event(
|
||||
topics_ptr: *const u8,
|
||||
topics_len: u32,
|
||||
data_ptr: *const u8,
|
||||
data_len: u32,
|
||||
);
|
||||
|
||||
pub fn ecdsa_recover(
|
||||
signature_ptr: *const u8,
|
||||
message_hash_ptr: *const u8,
|
||||
output_ptr: *mut u8,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn ecdsa_to_eth_address(public_key_ptr: *const u8, output_ptr: *mut u8) -> ReturnCode;
|
||||
|
||||
pub fn gas_left(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn get_storage(
|
||||
key_ptr: *const u8,
|
||||
out_ptr: *mut u8,
|
||||
out_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn get_transient_storage(
|
||||
key_ptr: *const u8,
|
||||
key_len: u32,
|
||||
out_ptr: *mut u8,
|
||||
out_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn hash_blake2_128(input_ptr: *const u8, input_len: u32, output_ptr: *mut u8);
|
||||
|
||||
pub fn hash_blake2_256(input_ptr: *const u8, input_len: u32, output_ptr: *mut u8);
|
||||
|
||||
pub fn hash_keccak_256(input_ptr: *const u8, input_len: u32, output_ptr: *mut u8);
|
||||
|
||||
pub fn hash_sha2_256(input_ptr: *const u8, input_len: u32, output_ptr: *mut u8);
|
||||
|
||||
pub fn input(buf_ptr: *mut u8, buf_len_ptr: *mut u32);
|
||||
|
||||
pub fn instantiation_nonce() -> u64;
|
||||
|
||||
pub fn is_contract(account_id_ptr: *const u8) -> ReturnCode;
|
||||
|
||||
pub fn minimum_balance(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn now(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn own_code_hash(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn reentrance_count() -> u32;
|
||||
|
||||
pub fn unlock_delegate_dependency(code_hash_ptr: *const u8);
|
||||
|
||||
pub fn seal_return(flags: u32, data_ptr: *const u8, data_len: u32) -> !;
|
||||
|
||||
pub fn set_code_hash(code_hash_ptr: *const u8) -> ReturnCode;
|
||||
|
||||
pub fn set_storage(key_ptr: *const u8, value_ptr: *const u8, value_len: u32);
|
||||
|
||||
pub fn set_transient_storage(
|
||||
key_ptr: *const u8,
|
||||
key_len: u32,
|
||||
value_ptr: *const u8,
|
||||
value_len: u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn sr25519_verify(
|
||||
signature_ptr: *const u8,
|
||||
public_key_ptr: *const u8,
|
||||
message_len: u32,
|
||||
message_ptr: *const u8,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn take_storage(
|
||||
key_ptr: *const u8,
|
||||
key_len: u32,
|
||||
out_ptr: *mut u8,
|
||||
out_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn take_transient_storage(
|
||||
key_ptr: *const u8,
|
||||
key_len: u32,
|
||||
out_ptr: *mut u8,
|
||||
out_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn terminate(beneficiary_ptr: *const u8) -> !;
|
||||
|
||||
pub fn transfer(
|
||||
account_id_ptr: *const u8,
|
||||
account_id_len: u32,
|
||||
transferred_value_ptr: *const u8,
|
||||
transferred_value_len: u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn value_transferred(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn weight_to_fee(gas: u64, output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
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,
|
||||
output_ptr: *mut u8,
|
||||
) -> ReturnCode;
|
||||
}
|
||||
|
||||
pub mod v1 {
|
||||
use crate::ReturnCode;
|
||||
|
||||
#[link(wasm_import_module = "seal1")]
|
||||
extern "C" {
|
||||
pub fn call(
|
||||
flags: u32,
|
||||
callee_ptr: *const u8,
|
||||
gas: u64,
|
||||
transferred_value_ptr: *const u8,
|
||||
input_data_ptr: *const u8,
|
||||
input_data_len: u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn clear_storage(key_ptr: *const u8, key_len: u32) -> ReturnCode;
|
||||
|
||||
pub fn contains_storage(key_ptr: *const u8, key_len: u32) -> ReturnCode;
|
||||
|
||||
pub fn gas_left(output_ptr: *mut u8, output_len_ptr: *mut u32);
|
||||
|
||||
pub fn get_storage(
|
||||
key_ptr: *const u8,
|
||||
key_len: u32,
|
||||
out_ptr: *mut u8,
|
||||
out_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn instantiate(
|
||||
code_hash_ptr: *const u8,
|
||||
gas: u64,
|
||||
value_ptr: *const u8,
|
||||
input_ptr: *const u8,
|
||||
input_len: u32,
|
||||
address_ptr: *mut u8,
|
||||
address_len_ptr: *mut u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
salt_ptr: *const u8,
|
||||
salt_len: u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn set_storage(
|
||||
key_ptr: *const u8,
|
||||
value_ptr: *const u8,
|
||||
value_len: u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn terminate(beneficiary_ptr: *const u8) -> !;
|
||||
|
||||
pub fn weight_to_fee(
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub mod v2 {
|
||||
use crate::ReturnCode;
|
||||
|
||||
#[link(wasm_import_module = "seal2")]
|
||||
extern "C" {
|
||||
pub fn call(
|
||||
flags: u32,
|
||||
callee_ptr: *const u8,
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
deposit_ptr: *const u8,
|
||||
transferred_value_ptr: *const u8,
|
||||
input_data_ptr: *const u8,
|
||||
input_data_len: u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn instantiate(
|
||||
code_hash_ptr: *const u8,
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
deposit_ptr: *const u8,
|
||||
value_ptr: *const u8,
|
||||
input_ptr: *const u8,
|
||||
input_len: u32,
|
||||
address_ptr: *mut u8,
|
||||
address_len_ptr: *mut u32,
|
||||
output_ptr: *mut u8,
|
||||
output_len_ptr: *mut u32,
|
||||
salt_ptr: *const u8,
|
||||
salt_len: u32,
|
||||
) -> ReturnCode;
|
||||
|
||||
pub fn set_storage(
|
||||
key_ptr: *const u8,
|
||||
key_len: u32,
|
||||
value_ptr: *const u8,
|
||||
value_len: u32,
|
||||
) -> ReturnCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A macro to implement all Host functions with a signature of `fn(&mut &mut [u8])`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```nocompile
|
||||
// impl_wrapper_for! {
|
||||
// () => [gas_left],
|
||||
// (v1) => [gas_left],
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Expands to:
|
||||
// ```nocompile
|
||||
// fn gas_left(output: &mut &mut [u8]) {
|
||||
// unsafe { sys::gas_left(...); }
|
||||
// }
|
||||
// fn gas_left_v1(output: &mut &mut [u8]) {
|
||||
// unsafe { sys::v1::gas_left(...); }
|
||||
// }
|
||||
// ```
|
||||
macro_rules! impl_wrapper_for {
|
||||
(@impl_fn $( $mod:ident )::*, $suffix_sep: literal, $suffix:tt, $name:ident) => {
|
||||
paste::paste! {
|
||||
fn [<$name $suffix_sep $suffix>](output: &mut &mut [u8]) {
|
||||
let mut output_len = output.len() as u32;
|
||||
unsafe {
|
||||
$( $mod )::*::$name(output.as_mut_ptr(), &mut output_len);
|
||||
}
|
||||
extract_from_slice(output, output_len as usize)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
() => {};
|
||||
|
||||
(($mod:ident) => [$( $name:ident),*], $($tail:tt)*) => {
|
||||
$(impl_wrapper_for!(@impl_fn sys::$mod, "_", $mod, $name);)*
|
||||
impl_wrapper_for!($($tail)*);
|
||||
};
|
||||
|
||||
(() => [$( $name:ident),*], $($tail:tt)*) => {
|
||||
$(impl_wrapper_for!(@impl_fn sys, "", "", $name);)*
|
||||
impl_wrapper_for!($($tail)*);
|
||||
};
|
||||
}
|
||||
|
||||
/// A macro to implement all the hash functions Apis.
|
||||
macro_rules! impl_hash_fn {
|
||||
( $name:ident, $bytes_result:literal ) => {
|
||||
paste::item! {
|
||||
fn [<hash_ $name>](input: &[u8], output: &mut [u8; $bytes_result]) {
|
||||
unsafe {
|
||||
sys::[<hash_ $name>](
|
||||
input.as_ptr(),
|
||||
input.len() as u32,
|
||||
output.as_mut_ptr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl HostFn for HostFnImpl {
|
||||
#[inline(always)]
|
||||
fn instantiate_v1(
|
||||
code_hash: &[u8],
|
||||
gas: u64,
|
||||
value: &[u8],
|
||||
input: &[u8],
|
||||
mut address: Option<&mut &mut [u8]>,
|
||||
mut output: Option<&mut &mut [u8]>,
|
||||
salt: &[u8],
|
||||
) -> Result {
|
||||
let (address_ptr, mut address_len) = ptr_len_or_sentinel(&mut address);
|
||||
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
|
||||
let ret_code = unsafe {
|
||||
sys::v1::instantiate(
|
||||
code_hash.as_ptr(),
|
||||
gas,
|
||||
value.as_ptr(),
|
||||
input.as_ptr(),
|
||||
input.len() as u32,
|
||||
address_ptr,
|
||||
&mut address_len,
|
||||
output_ptr,
|
||||
&mut output_len,
|
||||
salt.as_ptr(),
|
||||
salt.len() as u32,
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(ref mut address) = address {
|
||||
extract_from_slice(address, address_len as usize);
|
||||
}
|
||||
if let Some(ref mut output) = output {
|
||||
extract_from_slice(output, output_len as usize);
|
||||
}
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn instantiate_v2(
|
||||
code_hash: &[u8],
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
deposit: Option<&[u8]>,
|
||||
value: &[u8],
|
||||
input: &[u8],
|
||||
mut address: Option<&mut &mut [u8]>,
|
||||
mut output: Option<&mut &mut [u8]>,
|
||||
salt: &[u8],
|
||||
) -> Result {
|
||||
let (address_ptr, mut address_len) = ptr_len_or_sentinel(&mut address);
|
||||
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
|
||||
let deposit_ptr = ptr_or_sentinel(&deposit);
|
||||
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::v2::instantiate(
|
||||
code_hash.as_ptr(),
|
||||
ref_time_limit,
|
||||
proof_size_limit,
|
||||
deposit_ptr,
|
||||
value.as_ptr(),
|
||||
input.as_ptr(),
|
||||
input.len() as u32,
|
||||
address_ptr,
|
||||
&mut address_len,
|
||||
output_ptr,
|
||||
&mut output_len,
|
||||
salt.as_ptr(),
|
||||
salt.len() as u32,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(ref mut address) = address {
|
||||
extract_from_slice(address, address_len as usize);
|
||||
}
|
||||
|
||||
if let Some(ref mut output) = output {
|
||||
extract_from_slice(output, output_len as usize);
|
||||
}
|
||||
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn call(
|
||||
callee: &[u8],
|
||||
gas: u64,
|
||||
value: &[u8],
|
||||
input_data: &[u8],
|
||||
mut output: Option<&mut &mut [u8]>,
|
||||
) -> Result {
|
||||
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::call(
|
||||
callee.as_ptr(),
|
||||
callee.len() as u32,
|
||||
gas,
|
||||
value.as_ptr(),
|
||||
value.len() as u32,
|
||||
input_data.as_ptr(),
|
||||
input_data.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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn call_v1(
|
||||
flags: CallFlags,
|
||||
callee: &[u8],
|
||||
gas: u64,
|
||||
value: &[u8],
|
||||
input_data: &[u8],
|
||||
mut output: Option<&mut &mut [u8]>,
|
||||
) -> Result {
|
||||
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::v1::call(
|
||||
flags.bits(),
|
||||
callee.as_ptr(),
|
||||
gas,
|
||||
value.as_ptr(),
|
||||
input_data.as_ptr(),
|
||||
input_data.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()
|
||||
}
|
||||
|
||||
fn call_v2(
|
||||
flags: CallFlags,
|
||||
callee: &[u8],
|
||||
ref_time_limit: u64,
|
||||
proof_size_limit: u64,
|
||||
deposit: Option<&[u8]>,
|
||||
value: &[u8],
|
||||
input_data: &[u8],
|
||||
mut output: Option<&mut &mut [u8]>,
|
||||
) -> Result {
|
||||
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
|
||||
let deposit_ptr = ptr_or_sentinel(&deposit);
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::v2::call(
|
||||
flags.bits(),
|
||||
callee.as_ptr(),
|
||||
ref_time_limit,
|
||||
proof_size_limit,
|
||||
deposit_ptr,
|
||||
value.as_ptr(),
|
||||
input_data.as_ptr(),
|
||||
input_data.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()
|
||||
}
|
||||
|
||||
fn caller_is_root() -> u32 {
|
||||
unsafe { sys::caller_is_root() }.into_u32()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn delegate_call(
|
||||
flags: CallFlags,
|
||||
code_hash: &[u8],
|
||||
input: &[u8],
|
||||
mut output: Option<&mut &mut [u8]>,
|
||||
) -> Result {
|
||||
let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output);
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::delegate_call(
|
||||
flags.bits(),
|
||||
code_hash.as_ptr(),
|
||||
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()
|
||||
}
|
||||
|
||||
fn transfer(account_id: &[u8], value: &[u8]) -> Result {
|
||||
let ret_code = unsafe {
|
||||
sys::transfer(
|
||||
account_id.as_ptr(),
|
||||
account_id.len() as u32,
|
||||
value.as_ptr(),
|
||||
value.len() as u32,
|
||||
)
|
||||
};
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn deposit_event(topics: &[u8], data: &[u8]) {
|
||||
unsafe {
|
||||
sys::deposit_event(
|
||||
topics.as_ptr(),
|
||||
topics.len() as u32,
|
||||
data.as_ptr(),
|
||||
data.len() as u32,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_storage(key: &[u8], value: &[u8]) {
|
||||
unsafe { sys::set_storage(key.as_ptr(), value.as_ptr(), value.len() as u32) };
|
||||
}
|
||||
|
||||
fn set_storage_v1(key: &[u8], encoded_value: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe {
|
||||
sys::v1::set_storage(key.as_ptr(), encoded_value.as_ptr(), encoded_value.len() as u32)
|
||||
};
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn set_storage_v2(key: &[u8], encoded_value: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe {
|
||||
sys::v2::set_storage(
|
||||
key.as_ptr(),
|
||||
key.len() as u32,
|
||||
encoded_value.as_ptr(),
|
||||
encoded_value.len() as u32,
|
||||
)
|
||||
};
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn set_transient_storage(key: &[u8], encoded_value: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe {
|
||||
sys::set_transient_storage(
|
||||
key.as_ptr(),
|
||||
key.len() as u32,
|
||||
encoded_value.as_ptr(),
|
||||
encoded_value.len() as u32,
|
||||
)
|
||||
};
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn clear_storage(key: &[u8]) {
|
||||
unsafe { sys::clear_storage(key.as_ptr()) };
|
||||
}
|
||||
|
||||
fn clear_storage_v1(key: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe { sys::v1::clear_storage(key.as_ptr(), key.len() as u32) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn clear_transient_storage(key: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe { sys::clear_transient_storage(key.as_ptr(), key.len() as u32) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_storage(key: &[u8], output: &mut &mut [u8]) -> Result {
|
||||
let mut output_len = output.len() as u32;
|
||||
let ret_code =
|
||||
{ unsafe { sys::get_storage(key.as_ptr(), output.as_mut_ptr(), &mut output_len) } };
|
||||
extract_from_slice(output, output_len as usize);
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_storage_v1(key: &[u8], output: &mut &mut [u8]) -> Result {
|
||||
let mut output_len = output.len() as u32;
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::v1::get_storage(
|
||||
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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_transient_storage(key: &[u8], output: &mut &mut [u8]) -> Result {
|
||||
let mut output_len = output.len() as u32;
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::get_transient_storage(
|
||||
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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn take_storage(key: &[u8], output: &mut &mut [u8]) -> Result {
|
||||
let mut output_len = output.len() as u32;
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::take_storage(
|
||||
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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn take_transient_storage(key: &[u8], output: &mut &mut [u8]) -> Result {
|
||||
let mut output_len = output.len() as u32;
|
||||
let ret_code = {
|
||||
unsafe {
|
||||
sys::take_transient_storage(
|
||||
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 debug_message(str: &[u8]) -> Result {
|
||||
let ret_code = unsafe { sys::debug_message(str.as_ptr(), str.len() as u32) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn contains_storage(key: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe { sys::contains_storage(key.as_ptr()) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn contains_storage_v1(key: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe { sys::v1::contains_storage(key.as_ptr(), key.len() as u32) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn contains_transient_storage(key: &[u8]) -> Option<u32> {
|
||||
let ret_code = unsafe { sys::contains_transient_storage(key.as_ptr(), key.len() as u32) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
fn terminate(beneficiary: &[u8]) -> ! {
|
||||
unsafe { sys::terminate(beneficiary.as_ptr()) }
|
||||
}
|
||||
|
||||
fn terminate_v1(beneficiary: &[u8]) -> ! {
|
||||
unsafe { sys::v1::terminate(beneficiary.as_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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn input(output: &mut &mut [u8]) {
|
||||
let mut output_len = output.len() as u32;
|
||||
{
|
||||
unsafe { sys::input(output.as_mut_ptr(), &mut output_len) };
|
||||
}
|
||||
extract_from_slice(output, output_len as usize);
|
||||
}
|
||||
|
||||
fn return_value(flags: ReturnFlags, return_value: &[u8]) -> ! {
|
||||
unsafe { sys::seal_return(flags.bits(), return_value.as_ptr(), return_value.len() as u32) }
|
||||
}
|
||||
|
||||
fn call_runtime(call: &[u8]) -> Result {
|
||||
let ret_code = unsafe { sys::call_runtime(call.as_ptr(), call.len() as u32) };
|
||||
ret_code.into()
|
||||
}
|
||||
|
||||
impl_wrapper_for! {
|
||||
() => [caller, block_number, address, balance, gas_left, value_transferred, now, minimum_balance],
|
||||
(v1) => [gas_left],
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn weight_to_fee(gas: u64, output: &mut &mut [u8]) {
|
||||
let mut output_len = output.len() as u32;
|
||||
{
|
||||
unsafe { sys::weight_to_fee(gas, output.as_mut_ptr(), &mut output_len) };
|
||||
}
|
||||
extract_from_slice(output, output_len as usize);
|
||||
}
|
||||
|
||||
fn weight_to_fee_v1(ref_time_limit: u64, proof_size_limit: u64, output: &mut &mut [u8]) {
|
||||
let mut output_len = output.len() as u32;
|
||||
{
|
||||
unsafe {
|
||||
sys::v1::weight_to_fee(
|
||||
ref_time_limit,
|
||||
proof_size_limit,
|
||||
output.as_mut_ptr(),
|
||||
&mut output_len,
|
||||
)
|
||||
};
|
||||
}
|
||||
extract_from_slice(output, output_len as usize);
|
||||
}
|
||||
|
||||
impl_hash_fn!(sha2_256, 32);
|
||||
impl_hash_fn!(keccak_256, 32);
|
||||
impl_hash_fn!(blake2_256, 32);
|
||||
impl_hash_fn!(blake2_128, 16);
|
||||
|
||||
fn ecdsa_recover(
|
||||
signature: &[u8; 65],
|
||||
message_hash: &[u8; 32],
|
||||
output: &mut [u8; 33],
|
||||
) -> Result {
|
||||
let ret_code = unsafe {
|
||||
sys::ecdsa_recover(signature.as_ptr(), message_hash.as_ptr(), output.as_mut_ptr())
|
||||
};
|
||||
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()
|
||||
}
|
||||
|
||||
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 is_contract(account_id: &[u8]) -> bool {
|
||||
let ret_val = unsafe { sys::is_contract(account_id.as_ptr()) };
|
||||
ret_val.into_bool()
|
||||
}
|
||||
|
||||
fn caller_is_origin() -> bool {
|
||||
let ret_val = unsafe { sys::caller_is_origin() };
|
||||
ret_val.into_bool()
|
||||
}
|
||||
|
||||
fn set_code_hash(code_hash: &[u8]) -> Result {
|
||||
let ret_val = unsafe { sys::set_code_hash(code_hash.as_ptr()) };
|
||||
ret_val.into()
|
||||
}
|
||||
|
||||
fn code_hash(account_id: &[u8], output: &mut [u8]) -> Result {
|
||||
let mut output_len = output.len() as u32;
|
||||
let ret_val =
|
||||
unsafe { sys::code_hash(account_id.as_ptr(), output.as_mut_ptr(), &mut output_len) };
|
||||
ret_val.into()
|
||||
}
|
||||
|
||||
fn own_code_hash(output: &mut [u8]) {
|
||||
let mut output_len = output.len() as u32;
|
||||
unsafe { sys::own_code_hash(output.as_mut_ptr(), &mut output_len) }
|
||||
}
|
||||
|
||||
fn account_reentrance_count(account: &[u8]) -> u32 {
|
||||
unsafe { sys::account_reentrance_count(account.as_ptr()) }
|
||||
}
|
||||
|
||||
fn lock_delegate_dependency(code_hash: &[u8]) {
|
||||
unsafe { sys::lock_delegate_dependency(code_hash.as_ptr()) }
|
||||
}
|
||||
|
||||
fn unlock_delegate_dependency(code_hash: &[u8]) {
|
||||
unsafe { sys::unlock_delegate_dependency(code_hash.as_ptr()) }
|
||||
}
|
||||
|
||||
fn instantiation_nonce() -> u64 {
|
||||
unsafe { sys::instantiation_nonce() }
|
||||
}
|
||||
|
||||
fn reentrance_count() -> u32 {
|
||||
unsafe { sys::reentrance_count() }
|
||||
}
|
||||
|
||||
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(), msg.as_ptr(), msg.len() as _, output.as_mut_ptr())
|
||||
};
|
||||
ret_code.into()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// 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.
|
||||
|
||||
//! External C API to communicate with bizinikiwi contracts runtime module.
|
||||
//!
|
||||
//! Refer to bizinikiwi FRAME contract module for more documentation.
|
||||
|
||||
#![no_std]
|
||||
|
||||
mod flags;
|
||||
pub use flags::*;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod host;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use host::*;
|
||||
|
||||
macro_rules! define_error_codes {
|
||||
(
|
||||
$(
|
||||
$( #[$attr:meta] )*
|
||||
$name:ident = $discr:literal,
|
||||
)*
|
||||
) => {
|
||||
/// Every error that can be returned to a contract when it calls any of the host functions.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum ReturnErrorCode {
|
||||
/// API call successful.
|
||||
Success = 0,
|
||||
$(
|
||||
$( #[$attr] )*
|
||||
$name = $discr,
|
||||
)*
|
||||
/// Returns if an unknown error was received from the host module.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<ReturnCode> for Result {
|
||||
fn from(return_code: ReturnCode) -> Self {
|
||||
match return_code.0 {
|
||||
0 => Ok(()),
|
||||
$(
|
||||
$discr => Err(ReturnErrorCode::$name),
|
||||
)*
|
||||
_ => Err(ReturnErrorCode::Unknown),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl From<ReturnErrorCode> for u32 {
|
||||
fn from(code: ReturnErrorCode) -> u32 {
|
||||
code as u32
|
||||
}
|
||||
}
|
||||
|
||||
define_error_codes! {
|
||||
/// The called function trapped and has its state changes reverted.
|
||||
/// In this case no output buffer is returned.
|
||||
/// Can only be returned from `call` and `instantiate`.
|
||||
CalleeTrapped = 1,
|
||||
/// The called function ran to completion but decided to revert its state.
|
||||
/// An output buffer is returned when one was supplied.
|
||||
/// Can only be returned from `call` and `instantiate`.
|
||||
CalleeReverted = 2,
|
||||
/// The passed key does not exist in storage.
|
||||
KeyNotFound = 3,
|
||||
/// Deprecated and no longer returned: There is only the minimum balance.
|
||||
_BelowSubsistenceThreshold = 4,
|
||||
/// Transfer failed for other not further specified reason. Most probably
|
||||
/// reserved or locked balance of the sender that was preventing the transfer.
|
||||
TransferFailed = 5,
|
||||
/// Deprecated and no longer returned: Endowment is no longer required.
|
||||
_EndowmentTooLow = 6,
|
||||
/// No code could be found at the supplied code hash.
|
||||
CodeNotFound = 7,
|
||||
/// The account that was called is no contract.
|
||||
NotCallable = 8,
|
||||
/// The call to `debug_message` had no effect because debug message
|
||||
/// recording was disabled.
|
||||
LoggingDisabled = 9,
|
||||
/// The call dispatched by `call_runtime` was executed but returned an error.
|
||||
CallRuntimeFailed = 10,
|
||||
/// ECDSA public key recovery failed. Most probably wrong recovery id or signature.
|
||||
EcdsaRecoveryFailed = 11,
|
||||
/// sr25519 signature verification failed.
|
||||
Sr25519VerifyFailed = 12,
|
||||
/// The `xcm_execute` call failed.
|
||||
XcmExecutionFailed = 13,
|
||||
/// The `xcm_send` call failed.
|
||||
XcmSendFailed = 14,
|
||||
}
|
||||
|
||||
/// The raw return code returned by the host side.
|
||||
#[repr(transparent)]
|
||||
pub struct ReturnCode(u32);
|
||||
|
||||
/// Used as a sentinel value when reading and writing contract memory.
|
||||
///
|
||||
/// We use this value to signal `None` to a contract when only a primitive is
|
||||
/// allowed and we don't want to go through encoding a full Rust type.
|
||||
/// Using `u32::Max` is a safe sentinel because contracts are never
|
||||
/// allowed to use such a large amount of resources. So this value doesn't
|
||||
/// make sense for a memory location or length.
|
||||
const SENTINEL: u32 = u32::MAX;
|
||||
|
||||
impl From<ReturnCode> for Option<u32> {
|
||||
fn from(code: ReturnCode) -> Self {
|
||||
(code.0 < SENTINEL).then_some(code.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReturnCode {
|
||||
/// Returns the raw underlying `u32` representation.
|
||||
pub fn into_u32(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
/// Returns the underlying `u32` converted into `bool`.
|
||||
pub fn into_bool(self) -> bool {
|
||||
self.0.ne(&0)
|
||||
}
|
||||
}
|
||||
|
||||
type Result = core::result::Result<(), ReturnErrorCode>;
|
||||
Reference in New Issue
Block a user