mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 02:21:03 +00:00
Prerequisites for validate_block in Cumulus (#1926)
* Adds benchmark for direct/indirect wasm function calls * Store the benchmark function pointer in a `Cell` * Add some documentation * Make function implementations exchangeable * Add parachain stub * Add macro for registering the `validate_block` function * Make all functions replace-able by unimplemented * Some more refactoring * Adds tests for executing empty parachain block * Work on a new test with empty witness data * Don't exchange `ext_print_*` stuff * Some cleanup and one more function for `validate_block` * More tests and more functions * Fixes after merging master * Use `parity-codec` `derive` feature * CHange implementation of `wasm-nice-panic-message` * Move `parachain` stuff to cumulus * Updated wasm files * Integrate feedback * Switch to `ExchangeableFunction` struct * More fixes * Switch to Cell and panic on multiple replaces * Increase `impl_version` * Fix shifting * Make the API more verbose of `ExchangeableFunction` * Increase `impl_version`
This commit is contained in:
@@ -20,19 +20,27 @@ pub use parity_codec as codec;
|
||||
pub use rstd;
|
||||
pub use rstd::{mem, slice};
|
||||
|
||||
use core::intrinsics;
|
||||
use rstd::vec::Vec;
|
||||
use core::{intrinsics, panic::PanicInfo};
|
||||
use rstd::{vec::Vec, cell::Cell};
|
||||
use hash_db::Hasher;
|
||||
use primitives::Blake2Hasher;
|
||||
|
||||
#[panic_handler]
|
||||
#[no_mangle]
|
||||
pub fn panic(info: &::core::panic::PanicInfo) -> ! {
|
||||
pub fn panic(info: &PanicInfo) -> ! {
|
||||
unsafe {
|
||||
if let Some(loc) = info.location() {
|
||||
ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32);
|
||||
ext_print_num(loc.line() as u64);
|
||||
ext_print_num(loc.column() as u64);
|
||||
#[cfg(feature = "wasm-nice-panic-message")]
|
||||
{
|
||||
let message = rstd::alloc::format!("{}", info);
|
||||
extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32);
|
||||
}
|
||||
#[cfg(not(feature = "wasm-nice-panic-message"))]
|
||||
{
|
||||
if let Some(loc) = info.location() {
|
||||
extern_functions_host_impl::ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32);
|
||||
extern_functions_host_impl::ext_print_num(loc.line() as u64);
|
||||
extern_functions_host_impl::ext_print_num(loc.column() as u64);
|
||||
}
|
||||
}
|
||||
intrinsics::abort()
|
||||
}
|
||||
@@ -43,41 +51,223 @@ pub extern fn oom(_: ::core::alloc::Layout) -> ! {
|
||||
static OOM_MSG: &str = "Runtime memory exhausted. Aborting";
|
||||
|
||||
unsafe {
|
||||
ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32);
|
||||
extern_functions_host_impl::ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of an exchangeable function.
|
||||
#[derive(Clone, Copy)]
|
||||
enum ExchangeableFunctionState {
|
||||
Original,
|
||||
Replaced,
|
||||
}
|
||||
|
||||
/// A function which implementation can be exchanged.
|
||||
///
|
||||
/// Internally this works by swapping function pointers.
|
||||
pub struct ExchangeableFunction<T>(Cell<(T, ExchangeableFunctionState)>);
|
||||
|
||||
impl<T> ExchangeableFunction<T> {
|
||||
/// Create a new instance of `ExchangeableFunction`.
|
||||
pub const fn new(impl_: T) -> Self {
|
||||
Self(Cell::new((impl_, ExchangeableFunctionState::Original)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> ExchangeableFunction<T> {
|
||||
/// Replace the implementation with `new_impl`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when trying to replace an already replaced implementation.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns the original implementation wrapped in [`RestoreImplementation`].
|
||||
pub fn replace_implementation(&'static self, new_impl: T) -> RestoreImplementation<T> {
|
||||
if let ExchangeableFunctionState::Replaced = self.0.get().1 {
|
||||
panic!("Trying to replace an already replaced implementation!")
|
||||
}
|
||||
|
||||
let old = self.0.replace((new_impl, ExchangeableFunctionState::Replaced));
|
||||
|
||||
RestoreImplementation(self, Some(old.0))
|
||||
}
|
||||
|
||||
/// Restore the original implementation.
|
||||
fn restore_orig_implementation(&self, orig: T) {
|
||||
self.0.set((orig, ExchangeableFunctionState::Original));
|
||||
}
|
||||
|
||||
/// Returns the internal function pointer.
|
||||
pub fn get(&self) -> T {
|
||||
self.0.get().0
|
||||
}
|
||||
}
|
||||
|
||||
// WASM does not support threads, so this is safe; qed.
|
||||
unsafe impl<T> Sync for ExchangeableFunction<T> {}
|
||||
|
||||
/// Restores a function implementation on drop.
|
||||
///
|
||||
/// Stores a static reference to the function object and the original implementation.
|
||||
pub struct RestoreImplementation<T: 'static + Copy>(&'static ExchangeableFunction<T>, Option<T>);
|
||||
|
||||
impl<T: Copy> Drop for RestoreImplementation<T> {
|
||||
fn drop(&mut self) {
|
||||
self.0.restore_orig_implementation(self.1.take().expect("Value is only taken on drop; qed"));
|
||||
}
|
||||
}
|
||||
|
||||
/// Declare extern functions
|
||||
macro_rules! extern_functions {
|
||||
(
|
||||
$(
|
||||
$( #[$attr:meta] )*
|
||||
fn $name:ident ( $( $arg:ident : $arg_ty:ty ),* ) $( -> $ret:ty )?;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$( #[$attr] )*
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static $name: ExchangeableFunction<unsafe fn ( $( $arg_ty ),* ) $( -> $ret )?> =
|
||||
ExchangeableFunction::new(extern_functions_host_impl::$name);
|
||||
)*
|
||||
|
||||
/// The exchangeable extern functions host implementations.
|
||||
mod extern_functions_host_impl {
|
||||
$(
|
||||
pub unsafe fn $name ( $( $arg : $arg_ty ),* ) $( -> $ret )? {
|
||||
implementation::$name ( $( $arg ),* )
|
||||
}
|
||||
)*
|
||||
|
||||
mod implementation {
|
||||
extern "C" {
|
||||
$(
|
||||
pub fn $name ( $( $arg : $arg_ty ),* ) $( -> $ret )?;
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Host functions, provided by the executor.
|
||||
/// A WebAssembly runtime module would "import" these to access the execution environment
|
||||
/// (most importantly, storage) or perform heavy hash calculations.
|
||||
/// See also "ext_" functions in sr-sandbox and sr-std
|
||||
extern "C" {
|
||||
/// Printing, useful for debugging
|
||||
extern_functions! {
|
||||
/// Host functions for printing, useful for debugging.
|
||||
fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32);
|
||||
fn ext_print_hex(data: *const u8, len: u32);
|
||||
fn ext_print_num(value: u64);
|
||||
|
||||
/// Host storage access and verification
|
||||
/// Set value for key in storage.
|
||||
fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32);
|
||||
fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32);
|
||||
/// Remove key and value from storage.
|
||||
fn ext_clear_storage(key_data: *const u8, key_len: u32);
|
||||
fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32);
|
||||
/// Checks if the given key exists in the storage.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `1` if the value exists.
|
||||
/// - `0` if the value does not exists.
|
||||
fn ext_exists_storage(key_data: *const u8, key_len: u32) -> u32;
|
||||
fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32;
|
||||
/// Remove storage entries which key starts with given prefix.
|
||||
fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32);
|
||||
fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32);
|
||||
/// Host-side result allocation
|
||||
/// Gets the value of the given key from storage.
|
||||
///
|
||||
/// The host allocates the memory for storing the value.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` if no value exists to the given key. `written_out` is set to `u32::max_value()`.
|
||||
///
|
||||
/// - Otherwise, pointer to the value in memory. `written_out` contains the length of the value.
|
||||
fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8;
|
||||
/// Host-side result allocation
|
||||
fn ext_get_allocated_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8;
|
||||
/// Gets the value of the given key from storage.
|
||||
///
|
||||
/// The value is written into `value` starting at `value_offset`.
|
||||
///
|
||||
/// If the value length is greater than `value_len - value_offset`, the value is written partially.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `u32::max_value()` if the value does not exists.
|
||||
///
|
||||
/// - Otherwise, the number of bytes written for value.
|
||||
fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32;
|
||||
fn ext_get_child_storage_into(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32;
|
||||
/// Gets the trie root of the storage.
|
||||
fn ext_storage_root(result: *mut u8);
|
||||
/// Host-side result allocation
|
||||
fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8;
|
||||
/// Get the change trie root of the current storage overlay at a block with given parent.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `1` if the change trie root was found.
|
||||
/// - `0` if the change trie root was not found.
|
||||
fn ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, parent_num: u64, result: *mut u8) -> u32;
|
||||
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_set_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32);
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_clear_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32);
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_exists_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32;
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_kill_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32);
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_get_allocated_storage`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_get_allocated_child_storage(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
written_out: *mut u32
|
||||
) -> *mut u8;
|
||||
/// A child storage function.
|
||||
///
|
||||
/// See [`ext_get_storage_into`] for details.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
fn ext_get_child_storage_into(
|
||||
storage_key_data: *const u8,
|
||||
storage_key_len: u32,
|
||||
key_data: *const u8,
|
||||
key_len: u32,
|
||||
value_data: *mut u8,
|
||||
value_len: u32,
|
||||
value_offset: u32
|
||||
) -> u32;
|
||||
/// Commits all changes and calculates the child-storage root.
|
||||
///
|
||||
/// A child storage is used e.g. by a contract.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - The pointer to the result vector and `written_out` contains its length.
|
||||
fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8;
|
||||
|
||||
/// The current relay chain identifier.
|
||||
fn ext_chain_id() -> u64;
|
||||
|
||||
@@ -107,7 +297,7 @@ impl ExternTrieCrypto for Blake2Hasher {
|
||||
let values = values.iter().fold(Vec::new(), |mut acc, sl| { acc.extend_from_slice(sl); acc });
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_blake2_256_enumerated_trie_root(
|
||||
ext_blake2_256_enumerated_trie_root.get()(
|
||||
values.as_ptr(),
|
||||
lengths.as_ptr(),
|
||||
lengths.len() as u32,
|
||||
@@ -122,7 +312,7 @@ impl ExternTrieCrypto for Blake2Hasher {
|
||||
pub fn storage(key: &[u8]) -> Option<Vec<u8>> {
|
||||
let mut length: u32 = 0;
|
||||
unsafe {
|
||||
let ptr = ext_get_allocated_storage(key.as_ptr(), key.len() as u32, &mut length);
|
||||
let ptr = ext_get_allocated_storage.get()(key.as_ptr(), key.len() as u32, &mut length);
|
||||
if length == u32::max_value() {
|
||||
None
|
||||
} else {
|
||||
@@ -138,7 +328,13 @@ pub fn storage(key: &[u8]) -> Option<Vec<u8>> {
|
||||
pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>> {
|
||||
let mut length: u32 = 0;
|
||||
unsafe {
|
||||
let ptr = ext_get_allocated_child_storage(storage_key.as_ptr(), storage_key.len() as u32, key.as_ptr(), key.len() as u32, &mut length);
|
||||
let ptr = ext_get_allocated_child_storage.get()(
|
||||
storage_key.as_ptr(),
|
||||
storage_key.len() as u32,
|
||||
key.as_ptr(),
|
||||
key.len() as u32,
|
||||
&mut length
|
||||
);
|
||||
if length == u32::max_value() {
|
||||
None
|
||||
} else {
|
||||
@@ -153,7 +349,7 @@ pub fn child_storage(storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>> {
|
||||
/// Set the storage of some particular key to Some value.
|
||||
pub fn set_storage(key: &[u8], value: &[u8]) {
|
||||
unsafe {
|
||||
ext_set_storage(
|
||||
ext_set_storage.get()(
|
||||
key.as_ptr(), key.len() as u32,
|
||||
value.as_ptr(), value.len() as u32
|
||||
);
|
||||
@@ -163,7 +359,7 @@ pub fn set_storage(key: &[u8], value: &[u8]) {
|
||||
/// Set the child storage of some particular key to Some value.
|
||||
pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) {
|
||||
unsafe {
|
||||
ext_set_child_storage(
|
||||
ext_set_child_storage.get()(
|
||||
storage_key.as_ptr(), key.len() as u32,
|
||||
key.as_ptr(), key.len() as u32,
|
||||
value.as_ptr(), value.len() as u32
|
||||
@@ -174,7 +370,7 @@ pub fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) {
|
||||
/// Clear the storage of some particular key.
|
||||
pub fn clear_storage(key: &[u8]) {
|
||||
unsafe {
|
||||
ext_clear_storage(
|
||||
ext_clear_storage.get()(
|
||||
key.as_ptr(), key.len() as u32
|
||||
);
|
||||
}
|
||||
@@ -183,7 +379,7 @@ pub fn clear_storage(key: &[u8]) {
|
||||
/// Clear the storage of some particular key.
|
||||
pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) {
|
||||
unsafe {
|
||||
ext_clear_child_storage(
|
||||
ext_clear_child_storage.get()(
|
||||
storage_key.as_ptr(), storage_key.len() as u32,
|
||||
key.as_ptr(), key.len() as u32
|
||||
);
|
||||
@@ -193,7 +389,7 @@ pub fn clear_child_storage(storage_key: &[u8], key: &[u8]) {
|
||||
/// Determine whether a particular key exists in storage.
|
||||
pub fn exists_storage(key: &[u8]) -> bool {
|
||||
unsafe {
|
||||
ext_exists_storage(
|
||||
ext_exists_storage.get()(
|
||||
key.as_ptr(), key.len() as u32
|
||||
) != 0
|
||||
}
|
||||
@@ -202,7 +398,7 @@ pub fn exists_storage(key: &[u8]) -> bool {
|
||||
/// Determine whether a particular key exists in storage.
|
||||
pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool {
|
||||
unsafe {
|
||||
ext_exists_child_storage(
|
||||
ext_exists_child_storage.get()(
|
||||
storage_key.as_ptr(), storage_key.len() as u32,
|
||||
key.as_ptr(), key.len() as u32
|
||||
) != 0
|
||||
@@ -212,7 +408,7 @@ pub fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool {
|
||||
/// Clear the storage entries key of which starts with the given prefix.
|
||||
pub fn clear_prefix(prefix: &[u8]) {
|
||||
unsafe {
|
||||
ext_clear_prefix(
|
||||
ext_clear_prefix.get()(
|
||||
prefix.as_ptr(),
|
||||
prefix.len() as u32
|
||||
);
|
||||
@@ -222,7 +418,7 @@ pub fn clear_prefix(prefix: &[u8]) {
|
||||
/// Clear an entire child storage.
|
||||
pub fn kill_child_storage(storage_key: &[u8]) {
|
||||
unsafe {
|
||||
ext_kill_child_storage(
|
||||
ext_kill_child_storage.get()(
|
||||
storage_key.as_ptr(),
|
||||
storage_key.len() as u32
|
||||
);
|
||||
@@ -233,10 +429,12 @@ pub fn kill_child_storage(storage_key: &[u8]) {
|
||||
/// the number of bytes that the key in storage was beyond the offset.
|
||||
pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option<usize> {
|
||||
unsafe {
|
||||
match ext_get_storage_into(
|
||||
key.as_ptr(), key.len() as u32,
|
||||
value_out.as_mut_ptr(), value_out.len() as u32,
|
||||
value_offset as u32
|
||||
match ext_get_storage_into.get()(
|
||||
key.as_ptr(),
|
||||
key.len() as u32,
|
||||
value_out.as_mut_ptr(),
|
||||
value_out.len() as u32,
|
||||
value_offset as u32,
|
||||
) {
|
||||
none if none == u32::max_value() => None,
|
||||
length => Some(length as usize),
|
||||
@@ -248,7 +446,7 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Op
|
||||
/// the number of bytes that the key in storage was beyond the offset.
|
||||
pub fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option<usize> {
|
||||
unsafe {
|
||||
match ext_get_child_storage_into(
|
||||
match ext_get_child_storage_into.get()(
|
||||
storage_key.as_ptr(), storage_key.len() as u32,
|
||||
key.as_ptr(), key.len() as u32,
|
||||
value_out.as_mut_ptr(), value_out.len() as u32,
|
||||
@@ -264,7 +462,7 @@ pub fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8],
|
||||
pub fn storage_root() -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_storage_root(result.as_mut_ptr());
|
||||
ext_storage_root.get()(result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -273,7 +471,7 @@ pub fn storage_root() -> [u8; 32] {
|
||||
pub fn child_storage_root(storage_key: &[u8]) -> Option<Vec<u8>> {
|
||||
let mut length: u32 = 0;
|
||||
unsafe {
|
||||
let ptr = ext_child_storage_root(storage_key.as_ptr(), storage_key.len() as u32, &mut length);
|
||||
let ptr = ext_child_storage_root.get()(storage_key.as_ptr(), storage_key.len() as u32, &mut length);
|
||||
if length == u32::max_value() {
|
||||
None
|
||||
} else {
|
||||
@@ -289,7 +487,7 @@ pub fn child_storage_root(storage_key: &[u8]) -> Option<Vec<u8>> {
|
||||
pub fn storage_changes_root(parent_hash: [u8; 32], parent_num: u64) -> Option<[u8; 32]> {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
let is_set = unsafe {
|
||||
ext_storage_changes_root(parent_hash.as_ptr(), parent_hash.len() as u32, parent_num, result.as_mut_ptr())
|
||||
ext_storage_changes_root.get()(parent_hash.as_ptr(), parent_hash.len() as u32, parent_num, result.as_mut_ptr())
|
||||
};
|
||||
|
||||
if is_set != 0 {
|
||||
@@ -326,7 +524,7 @@ pub fn ordered_trie_root<
|
||||
/// The current relay chain identifier.
|
||||
pub fn chain_id() -> u64 {
|
||||
unsafe {
|
||||
ext_chain_id()
|
||||
ext_chain_id.get()()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +532,7 @@ pub fn chain_id() -> u64 {
|
||||
pub fn blake2_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
ext_blake2_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -343,7 +541,7 @@ pub fn blake2_256(data: &[u8]) -> [u8; 32] {
|
||||
pub fn keccak_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_keccak_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
ext_keccak_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -352,7 +550,7 @@ pub fn keccak_256(data: &[u8]) -> [u8; 32] {
|
||||
pub fn twox_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_twox_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
ext_twox_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -361,7 +559,7 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] {
|
||||
pub fn twox_128(data: &[u8]) -> [u8; 16] {
|
||||
let mut result: [u8; 16] = Default::default();
|
||||
unsafe {
|
||||
ext_twox_128(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
ext_twox_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -369,14 +567,14 @@ pub fn twox_128(data: &[u8]) -> [u8; 16] {
|
||||
/// Verify a ed25519 signature.
|
||||
pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
unsafe {
|
||||
ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0
|
||||
ext_ed25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a sr25519 signature.
|
||||
pub fn sr25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
unsafe {
|
||||
ext_sr25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0
|
||||
ext_sr25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +584,7 @@ pub fn sr25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) ->
|
||||
pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> {
|
||||
let mut pubkey = [0u8; 64];
|
||||
match unsafe {
|
||||
ext_secp256k1_ecdsa_recover(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr())
|
||||
ext_secp256k1_ecdsa_recover.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr())
|
||||
} {
|
||||
0 => Ok(pubkey),
|
||||
1 => Err(EcdsaVerifyError::BadRS),
|
||||
@@ -404,7 +602,7 @@ pub trait Printable {
|
||||
impl<'a> Printable for &'a [u8] {
|
||||
fn print(self) {
|
||||
unsafe {
|
||||
ext_print_hex(self.as_ptr(), self.len() as u32);
|
||||
ext_print_hex.get()(self.as_ptr(), self.len() as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,14 +610,14 @@ impl<'a> Printable for &'a [u8] {
|
||||
impl<'a> Printable for &'a str {
|
||||
fn print(self) {
|
||||
unsafe {
|
||||
ext_print_utf8(self.as_ptr() as *const u8, self.len() as u32);
|
||||
ext_print_utf8.get()(self.as_ptr() as *const u8, self.len() as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for u64 {
|
||||
fn print(self) {
|
||||
unsafe { ext_print_num(self); }
|
||||
unsafe { ext_print_num.get()(self); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user