From 67eb3bf67bfbd1bb218faada7fd31a894736aaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 18 Nov 2019 21:05:37 +0100 Subject: [PATCH] `sr-io` remove unused files --- primitives/sr-io/with_std.rs | 553 -------------- primitives/sr-io/without_std.rs | 1241 ------------------------------- 2 files changed, 1794 deletions(-) delete mode 100644 primitives/sr-io/with_std.rs delete mode 100644 primitives/sr-io/without_std.rs diff --git a/primitives/sr-io/with_std.rs b/primitives/sr-io/with_std.rs deleted file mode 100644 index 7e0504c37aafc..0000000000000 --- a/primitives/sr-io/with_std.rs +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use primitives::{ - blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair, H256, - traits::KeystoreExt, storage::ChildStorageKey, hexdisplay::HexDisplay, Hasher, - offchain::{self, OffchainExt}, -}; -// Switch to this after PoC-3 -// pub use primitives::BlakeHasher; -pub use substrate_state_machine::{BasicExternalities, TestExternalities}; - -use trie::{TrieConfiguration, trie_types::Layout}; - -use std::{collections::HashMap, convert::TryFrom}; - -use externalities::{with_externalities, set_and_run_with_externalities, ExternalitiesExt}; - -/// Additional bounds for `Hasher` trait for with_std. -pub trait HasherBounds {} -impl HasherBounds for T {} - -/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage -/// key or panics otherwise. -/// -/// Panicking here is aligned with what the `without_std` environment would do -/// in the case of an invalid child storage key. -fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { - match ChildStorageKey::from_slice(storage_key) { - Some(storage_key) => storage_key, - None => panic!("child storage key is invalid"), - } -} - -impl StorageApi for () { - fn storage(key: &[u8]) -> Option> { - with_externalities(|ext| ext.storage(key).map(|s| s.to_vec())) - .expect("storage cannot be called outside of an Externalities-provided environment.") - } - - fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - with_externalities(|ext| ext.storage(key).map(|value| { - let data = &value[value_offset.min(value.len())..]; - let written = std::cmp::min(data.len(), value_out.len()); - value_out[..written].copy_from_slice(&data[..written]); - value.len() - })).expect("read_storage cannot be called outside of an Externalities-provided environment.") - } - - fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.child_storage(storage_key, key).map(|s| s.to_vec()) - }) - .expect("storage cannot be called outside of an Externalities-provided environment.") - } - - fn set_storage(key: &[u8], value: &[u8]) { - with_externalities(|ext| - ext.set_storage(key.to_vec(), value.to_vec()) - ); - } - - fn read_child_storage( - storage_key: &[u8], - key: &[u8], - value_out: &mut [u8], - value_offset: usize, - ) -> Option { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.child_storage(storage_key, key) - .map(|value| { - let data = &value[value_offset.min(value.len())..]; - let written = std::cmp::min(data.len(), value_out.len()); - value_out[..written].copy_from_slice(&data[..written]); - value.len() - }) - }) - .expect("read_child_storage cannot be called outside of an Externalities-provided environment.") - } - - fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.set_child_storage(storage_key, key.to_vec(), value.to_vec()) - }); - } - - fn clear_storage(key: &[u8]) { - with_externalities(|ext| - ext.clear_storage(key) - ); - } - - fn clear_child_storage(storage_key: &[u8], key: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.clear_child_storage(storage_key, key) - }); - } - - fn kill_child_storage(storage_key: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.kill_child_storage(storage_key) - }); - } - - fn exists_storage(key: &[u8]) -> bool { - with_externalities(|ext| - ext.exists_storage(key) - ).unwrap_or(false) - } - - fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.exists_child_storage(storage_key, key) - }).unwrap_or(false) - } - - fn clear_prefix(prefix: &[u8]) { - with_externalities(|ext| ext.clear_prefix(prefix)); - } - - fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.clear_child_prefix(storage_key, prefix) - }); - } - - fn storage_root() -> [u8; 32] { - with_externalities(|ext| - ext.storage_root() - ).unwrap_or(H256::zero()).into() - } - - fn child_storage_root(storage_key: &[u8]) -> Vec { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.child_storage_root(storage_key) - }).expect("child_storage_root cannot be called outside of an Externalities-provided environment.") - } - - fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]> { - with_externalities(|ext| - ext.storage_changes_root(parent_hash.into()).map(|h| h.map(|h| h.into())) - ).unwrap_or(Ok(None)).expect("Invalid parent hash passed to storage_changes_root") - } - - fn blake2_256_trie_root(input: Vec<(Vec, Vec)>) -> H256 { - Layout::::trie_root(input) - } - - fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { - Layout::::ordered_trie_root(input) - } -} - -impl OtherApi for () { - fn chain_id() -> u64 { - with_externalities(|ext| - ext.chain_id() - ).unwrap_or(0) - } - - fn print_num(val: u64) { - log::debug!(target: "runtime", "{}", val); - } - - fn print_utf8(utf8: &[u8]) { - if let Ok(data) = std::str::from_utf8(utf8) { - log::debug!(target: "runtime", "{}", data) - } - } - - fn print_hex(data: &[u8]) { - log::debug!(target: "runtime", "{}", HexDisplay::from(&data)); - } - - fn log( - level: LogLevel, - target: &[u8], - message: &[u8], - ) { - let target = std::str::from_utf8(target).unwrap_or("invalid utf8"); - let msg = std::str::from_utf8(message).unwrap_or("invalid utf8"); - - log::log!( - target: target, - log::Level::from(level), - "{}", - msg, - ) - } -} - -impl CryptoApi for () { - fn ed25519_public_keys(id: KeyTypeId) -> Vec { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .ed25519_public_keys(id) - }).expect("`ed25519_public_keys` cannot be called outside of an Externalities-provided environment.") - } - - fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .write() - .ed25519_generate_new(id, seed) - .expect("`ed25519_generate` failed") - }).expect("`ed25519_generate` cannot be called outside of an Externalities-provided environment.") - } - - fn ed25519_sign( - id: KeyTypeId, - pubkey: &ed25519::Public, - msg: &[u8], - ) -> Option { - let pub_key = ed25519::Public::try_from(pubkey.as_ref()).ok()?; - - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .ed25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg)) - }).expect("`ed25519_sign` cannot be called outside of an Externalities-provided environment.") - } - - fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool { - ed25519::Pair::verify(sig, msg, pubkey) - } - - fn sr25519_public_keys(id: KeyTypeId) -> Vec { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .sr25519_public_keys(id) - }).expect("`sr25519_public_keys` cannot be called outside of an Externalities-provided environment.") - } - - fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .write() - .sr25519_generate_new(id, seed) - .expect("`sr25519_generate` failed") - }).expect("`sr25519_generate` cannot be called outside of an Externalities-provided environment.") - } - - fn sr25519_sign( - id: KeyTypeId, - pubkey: &sr25519::Public, - msg: &[u8], - ) -> Option { - let pub_key = sr25519::Public::try_from(pubkey.as_ref()).ok()?; - - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .sr25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg)) - }).expect("`sr25519_sign` cannot be called outside of an Externalities-provided environment.") - } - - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { - sr25519::Pair::verify(sig, msg, pubkey) - } - - fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> { - let rs = secp256k1::Signature::parse_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; - let mut res = [0u8; 64]; - res.copy_from_slice(&pubkey.serialize()[1..65]); - Ok(res) - } - - fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError> { - let rs = secp256k1::Signature::parse_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; - Ok(pubkey.serialize_compressed()) - } -} - -impl HashingApi for () { - fn keccak_256(data: &[u8]) -> [u8; 32] { - tiny_keccak::keccak256(data) - } - - fn blake2_128(data: &[u8]) -> [u8; 16] { - blake2_128(data) - } - - fn blake2_256(data: &[u8]) -> [u8; 32] { - blake2_256(data) - } - - fn twox_256(data: &[u8]) -> [u8; 32] { - twox_256(data) - } - - fn twox_128(data: &[u8]) -> [u8; 16] { - twox_128(data) - } - - fn twox_64(data: &[u8]) -> [u8; 8] { - twox_64(data) - } -} - -fn with_offchain(f: impl FnOnce(&mut dyn offchain::Externalities) -> R, msg: &'static str) -> R { - with_externalities(|ext| ext - .extension::() - .map(|ext| f(&mut **ext)) - .expect(msg) - ).expect("offchain-worker functions cannot be called outside of an Externalities-provided environment.") -} - -impl OffchainApi for () { - fn is_validator() -> bool { - with_offchain(|ext| { - ext.is_validator() - }, "is_validator can be called only in the offchain worker context") - } - - fn submit_transaction(data: Vec) -> Result<(), ()> { - with_offchain(|ext| { - ext.submit_transaction(data) - }, "submit_transaction can be called only in the offchain worker context") - } - - fn network_state() -> Result { - with_offchain(|ext| { - ext.network_state() - }, "network_state can be called only in the offchain worker context") - } - - fn timestamp() -> offchain::Timestamp { - with_offchain(|ext| { - ext.timestamp() - }, "timestamp can be called only in the offchain worker context") - } - - fn sleep_until(deadline: offchain::Timestamp) { - with_offchain(|ext| { - ext.sleep_until(deadline) - }, "sleep_until can be called only in the offchain worker context") - } - - fn random_seed() -> [u8; 32] { - with_offchain(|ext| { - ext.random_seed() - }, "random_seed can be called only in the offchain worker context") - } - - fn local_storage_set(kind: offchain::StorageKind, key: &[u8], value: &[u8]) { - with_offchain(|ext| { - ext.local_storage_set(kind, key, value) - }, "local_storage_set can be called only in the offchain worker context") - } - - fn local_storage_compare_and_set( - kind: offchain::StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - with_offchain(|ext| { - ext.local_storage_compare_and_set(kind, key, old_value, new_value) - }, "local_storage_compare_and_set can be called only in the offchain worker context") - } - - fn local_storage_get(kind: offchain::StorageKind, key: &[u8]) -> Option> { - with_offchain(|ext| { - ext.local_storage_get(kind, key) - }, "local_storage_get can be called only in the offchain worker context") - } - - fn http_request_start( - method: &str, - uri: &str, - meta: &[u8], - ) -> Result { - with_offchain(|ext| { - ext.http_request_start(method, uri, meta) - }, "http_request_start can be called only in the offchain worker context") - } - - fn http_request_add_header( - request_id: offchain::HttpRequestId, - name: &str, - value: &str, - ) -> Result<(), ()> { - with_offchain(|ext| { - ext.http_request_add_header(request_id, name, value) - }, "http_request_add_header can be called only in the offchain worker context") - } - - fn http_request_write_body( - request_id: offchain::HttpRequestId, - chunk: &[u8], - deadline: Option, - ) -> Result<(), offchain::HttpError> { - with_offchain(|ext| { - ext.http_request_write_body(request_id, chunk, deadline) - }, "http_request_write_body can be called only in the offchain worker context") - } - - fn http_response_wait( - ids: &[offchain::HttpRequestId], - deadline: Option, - ) -> Vec { - with_offchain(|ext| { - ext.http_response_wait(ids, deadline) - }, "http_response_wait can be called only in the offchain worker context") - } - - fn http_response_headers( - request_id: offchain::HttpRequestId, - ) -> Vec<(Vec, Vec)> { - with_offchain(|ext| { - ext.http_response_headers(request_id) - }, "http_response_headers can be called only in the offchain worker context") - } - - fn http_response_read_body( - request_id: offchain::HttpRequestId, - buffer: &mut [u8], - deadline: Option, - ) -> Result { - with_offchain(|ext| { - ext.http_response_read_body(request_id, buffer, deadline) - }, "http_response_read_body can be called only in the offchain worker context") - } -} - -impl Api for () {} - -/// A set of key value pairs for storage. -pub type StorageOverlay = HashMap, Vec>; - -/// A set of key value pairs for children storage; -pub type ChildrenStorageOverlay = HashMap, StorageOverlay>; - -/// Execute the given closure with global functions available whose functionality routes into -/// externalities that draw from and populate `storage` and `children_storage`. -/// Forwards the value that the closure returns. -pub fn with_storage R>( - storage: &mut (StorageOverlay, ChildrenStorageOverlay), - f: F -) -> R { - let mut alt_storage = Default::default(); - rstd::mem::swap(&mut alt_storage, storage); - - let mut ext = BasicExternalities::new(alt_storage.0, alt_storage.1); - let r = set_and_run_with_externalities(&mut ext, f); - - *storage = ext.into_storages(); - - r -} - -#[cfg(test)] -mod std_tests { - use super::*; - use primitives::map; - - #[test] - fn storage_works() { - let mut t = BasicExternalities::default(); - assert!(set_and_run_with_externalities(&mut t, || { - assert_eq!(storage(b"hello"), None); - set_storage(b"hello", b"world"); - assert_eq!(storage(b"hello"), Some(b"world".to_vec())); - assert_eq!(storage(b"foo"), None); - set_storage(b"foo", &[1, 2, 3][..]); - true - })); - - t = BasicExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()], map![]); - - assert!(!set_and_run_with_externalities(&mut t, || { - assert_eq!(storage(b"hello"), None); - assert_eq!(storage(b"foo"), Some(b"bar".to_vec())); - false - })); - } - - #[test] - fn read_storage_works() { - let mut t = BasicExternalities::new(map![ - b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec() - ], map![]); - - set_and_run_with_externalities(&mut t, || { - let mut v = [0u8; 4]; - assert!(read_storage(b":test", &mut v[..], 0).unwrap() >= 4); - assert_eq!(v, [11u8, 0, 0, 0]); - let mut w = [0u8; 11]; - assert!(read_storage(b":test", &mut w[..], 4).unwrap() >= 11); - assert_eq!(&w, b"Hello world"); - }); - } - - #[test] - fn clear_prefix_works() { - let mut t = BasicExternalities::new(map![ - b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), - b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), - b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), - b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() - ], map![]); - - set_and_run_with_externalities(&mut t, || { - clear_prefix(b":abc"); - - assert!(storage(b":a").is_some()); - assert!(storage(b":abdd").is_some()); - assert!(storage(b":abcd").is_none()); - assert!(storage(b":abc").is_none()); - }); - } -} diff --git a/primitives/sr-io/without_std.rs b/primitives/sr-io/without_std.rs deleted file mode 100644 index c3f7d62031b93..0000000000000 --- a/primitives/sr-io/without_std.rs +++ /dev/null @@ -1,1241 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#[doc(hidden)] -pub use rstd; -pub use rstd::{mem, slice}; - -use core::{intrinsics, panic::PanicInfo}; -use rstd::{vec::Vec, cell::Cell, convert::TryInto}; -use primitives::offchain; -use codec::Decode; - -#[cfg(not(feature = "no_panic_handler"))] -#[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { - unsafe { - let message = rstd::alloc::format!("{}", info); - extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32); - intrinsics::abort() - } -} - -#[cfg(not(feature = "no_oom"))] -#[alloc_error_handler] -pub extern fn oom(_: core::alloc::Layout) -> ! { - static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; - - unsafe { - extern_functions_host_impl::ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); - intrinsics::abort(); - } -} - -/// External (Host) APIs -pub mod ext { - use super::*; - - /// The state of an exchangeable function. - #[derive(Clone, Copy)] - enum ExchangeableFunctionState { - /// Original function is present - Original, - /// The function has been replaced. - Replaced, - } - - /// A function which implementation can be exchanged. - /// - /// Internally this works by swapping function pointers. - pub struct ExchangeableFunction(Cell<(T, ExchangeableFunctionState)>); - - impl ExchangeableFunction { - /// Create a new instance of `ExchangeableFunction`. - pub const fn new(impl_: T) -> Self { - Self(Cell::new((impl_, ExchangeableFunctionState::Original))) - } - } - - impl ExchangeableFunction { - /// 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 { - 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 Sync for ExchangeableFunction {} - - /// Restores a function implementation on drop. - /// - /// Stores a static reference to the function object and the original implementation. - pub struct RestoreImplementation(&'static ExchangeableFunction, Option); - - impl Drop for RestoreImplementation { - 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 $ret )?> = - ExchangeableFunction::new(extern_functions_host_impl::$name); - )* - - /// The exchangeable extern functions host implementations. - pub(crate) 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_functions! { - /// Host functions for printing, useful for debugging. - fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32); - /// Print data as hex. - fn ext_print_hex(data: *const u8, len: u32); - /// Print a number - fn ext_print_num(value: u64); - /// Print a log line if logging for given level and target is enabled. - fn ext_log( - level: u32, - target_data: *const u8, - target_len: u32, - message_data: *const u8, - message_len: u32, - ); - - /// Set value for key in storage. - fn ext_set_storage(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); - /// 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; - /// Remove storage entries which key starts with given prefix. - fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32); - /// Remove child storage entries which key starts with given prefix. - fn ext_clear_child_prefix( - storage_key_data: *const u8, - storage_key_len: u32, - prefix_data: *const u8, - prefix_len: u32, - ); - /// 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; - /// 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; - /// Gets the trie root of the storage. - fn ext_storage_root(result: *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, - 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; - - /// Calculate a blake2_256 merkle trie root. - fn ext_blake2_256_enumerated_trie_root( - values_data: *const u8, - lens_data: *const u32, - lens_len: u32, - result: *mut u8 - ); - /// BLAKE2_128 hash - fn ext_blake2_128(data: *const u8, len: u32, out: *mut u8); - /// BLAKE2_256 hash - fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); - /// XX64 hash - fn ext_twox_64(data: *const u8, len: u32, out: *mut u8); - /// XX128 hash - fn ext_twox_128(data: *const u8, len: u32, out: *mut u8); - /// XX256 hash - fn ext_twox_256(data: *const u8, len: u32, out: *mut u8); - /// Keccak256 hash - fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); - - /// Returns all `ed25519` public keys for the given key type from the keystore. - fn ext_ed25519_public_keys(id: *const u8, result_len: *mut u32) -> *mut u8; - - /// Note: `ext_ed25519_verify` returns `0` if the signature is correct, nonzero otherwise. - fn ext_ed25519_verify( - msg_data: *const u8, - msg_len: u32, - sig_data: *const u8, - pubkey_data: *const u8, - ) -> u32; - - /// Generate an `ed25519` key pair for the given key type id and store the public key - /// in `out`. - fn ext_ed25519_generate(id: *const u8, seed: *const u8, seed_len: u32, out: *mut u8); - - /// Sign the given `msg` with the `ed25519` key pair that corresponds to then given key - /// type id and public key. The raw signature is stored in `out`. - /// - /// # Returns - /// - /// - `0` on success - /// - nonezero if something failed, e.g. retrieving of the key. - fn ext_ed25519_sign( - id: *const u8, - pubkey: *const u8, - msg: *const u8, - msg_len: u32, - out: *mut u8, - ) -> u32; - - /// Returns all `sr25519` public keys for the given key type from the keystore. - fn ext_sr25519_public_keys(id: *const u8, result_len: *mut u32) -> *mut u8; - - /// Note: `ext_sr25519_verify` returns 0 if the signature is correct, nonzero otherwise. - fn ext_sr25519_verify( - msg_data: *const u8, - msg_len: u32, - sig_data: *const u8, - pubkey_data: *const u8, - ) -> u32; - - /// Generate an `sr25519` key pair for the given key type id and store the public - /// key in `out`. - fn ext_sr25519_generate(id: *const u8, seed: *const u8, seed_len: u32, out: *mut u8); - - /// Sign the given `msg` with the `sr25519` key pair that corresponds to then given key - /// type id and public key. The raw signature is stored in `out`. - /// - /// # Returns - /// - /// - `0` on success - /// - nonezero if something failed, e.g. retrieving of the key. - fn ext_sr25519_sign( - id: *const u8, - pubkey: *const u8, - msg: *const u8, - msg_len: u32, - out: *mut u8, - ) -> u32; - - /// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise. - /// - /// pubkey_data must point to 64 bytes. - fn ext_secp256k1_ecdsa_recover( - msg_data: *const u8, - sig_data: *const u8, - pubkey_data: *mut u8, - ) -> u32; - - /// Note: ext_secp256k1_ecdsa_recover_compressed returns 0 if the signature is correct, nonzero otherwise. - /// - /// pubkey_data must point to 33 bytes. - fn ext_secp256k1_ecdsa_recover_compressed( - msg_data: *const u8, - sig_data: *const u8, - pubkey_data: *mut u8, - ) -> u32; - - //================================ - // Offchain-worker Context - //================================ - - /// Returns if the local node is a potential validator. - /// - /// - `1` == `true` - /// - `0` == `false` - fn ext_is_validator() -> u32; - - /// Submit transaction. - /// - /// # Returns - /// - /// - 0 if it was successfuly added to the pool - /// - nonzero otherwise. - fn ext_submit_transaction(data: *const u8, len: u32) -> u32; - - /// Returns information about the local node's network state. - /// - /// # Returns - /// - /// The encoded `Result`. - /// `written_out` contains the length of the message. - /// - /// The ownership of the returned buffer is transferred to the runtime - /// code and the runtime is responsible for freeing it. This is always - /// a properly allocated pointer (which cannot be NULL), hence the - /// runtime code can always rely on it. - fn ext_network_state(written_out: *mut u32) -> *mut u8; - - /// Returns current UNIX timestamp (milliseconds) - fn ext_timestamp() -> u64; - - /// Pause execution until given timestamp (milliseconds; `deadline`) is reached. - /// - /// The deadline is obtained by querying the current timestamp via `ext_timestamp` - /// and then adding some time to it. - fn ext_sleep_until(deadline: u64); - - /// Generate a random seed - /// - /// `data` has to be a pointer to a slice of 32 bytes. - fn ext_random_seed(data: *mut u8); - - /// Write a value to local storage. - fn ext_local_storage_set(kind: u32, key: *const u8, key_len: u32, value: *const u8, value_len: u32); - - /// Write a value to local storage in atomic fashion. - /// - /// # Returns - /// - `0` in case the value has been set - /// - `1` if the `old_value` didn't match - fn ext_local_storage_compare_and_set( - kind: u32, - key: *const u8, - key_len: u32, - old_value: *const u8, - old_value_len: u32, - new_value: *const u8, - new_value_len: u32, - ) -> u32; - - /// Read a value from local storage. - /// - /// - /// # Returns - /// - /// - 0 if the value has not been found, the `value_len` is set to `u32::max_value`. - /// - Otherwise, pointer to the value in memory. `value_len` contains the length of the value. - fn ext_local_storage_get(kind: u32, key: *const u8, key_len: u32, value_len: *mut u32) -> *mut u8; - - /// Initiates a http request. - /// - /// `meta` is parity-scale-codec encoded additional parameters to the request (like redirection policy, - /// timeouts, certificates policy, etc). The format is not yet specified and the field is currently - /// only reserved for future use. - /// - /// # Returns - /// - /// `RequestId(u16)` of initiated request, any value beyond `u16::max_value` - /// signifies an error. - fn ext_http_request_start( - method: *const u8, - method_len: u32, - url: *const u8, - url_len: u32, - meta: *const u8, - meta_len: u32, - ) -> u32; - - /// Add a header to the request. - /// - /// # Returns - /// - /// - `0` if successful (and the request id exists) - /// - nonzero otherwise - fn ext_http_request_add_header( - request_id: u32, - name: *const u8, - name_len: u32, - value: *const u8, - value_len: u32, - ) -> u32; - - /// Write a chunk of request body. - /// - /// Writing an empty chunks finalises the request. - /// Passing `0` as deadline blocks forever. - /// - /// # Returns - /// - /// - `0` if successful, - /// - nonzero otherwise (see HttpError for the codes) - fn ext_http_request_write_body( - request_id: u32, - chunk: *const u8, - chunk_len: u32, - deadline: u64, - ) -> u32; - - /// Block and wait for the responses for given requests. - /// - /// Note that if deadline is 0 the method will block indefinitely, - /// otherwise unready responses will produce `DeadlineReached` status. - /// (see #primitives::offchain::HttpRequestStatus) - /// - /// Make sure that `statuses` have the same length as ids. - fn ext_http_response_wait( - ids: *const u32, - ids_len: u32, - statuses: *mut u32, - deadline: u64, - ); - - /// Read all response headers. - /// - /// Note the headers are only available before response body is fully consumed. - /// - /// # Returns - /// - /// - A pointer to parity-scale-codec encoded vector of pairs `(HeaderKey, HeaderValue)`. - /// - In case invalid `id` is passed it returns a pointer to parity-encoded empty vector. - fn ext_http_response_headers( - id: u32, - written_out: *mut u32, - ) -> *mut u8; - - /// Read a chunk of body response to given buffer. - /// - /// Passing `0` as deadline blocks forever. - /// - /// # Returns - /// - /// The number of bytes written if successful, - /// - if it's `0` it means response has been fully consumed, - /// - if it's greater than `u32::max_value() - 255` it means reading body failed. - /// - /// In case of failure, the error code should be mapped to `HttpError` - /// in a following manner: - /// - `u32::max_value()` HttpError code 1 (DeadlineReached) - /// - `u32::max_value() - 1` HttpError code 2 (IoError) - /// The rest is reserved for potential future errors. - fn ext_http_response_read_body( - id: u32, - buffer: *mut u8, - buffer_len: u32, - deadline: u64, - ) -> u32; - } -} - -pub use self::ext::*; - -impl StorageApi for () { - fn storage(key: &[u8]) -> Option> { - let mut length: u32 = 0; - unsafe { - let ptr = ext_get_allocated_storage.get()(key.as_ptr(), key.len() as u32, &mut length); - from_raw_parts(ptr, length) - } - } - - fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { - let mut length: u32 = 0; - unsafe { - 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 - ); - from_raw_parts(ptr, length) - } - } - - fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - unsafe { - 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), - } - } - } - - fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - unsafe { - 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, - value_offset as u32 - ) { - none if none == u32::max_value() => None, - length => Some(length as usize), - } - } - } - - fn set_storage(key: &[u8], value: &[u8]) { - unsafe { - ext_set_storage.get()( - key.as_ptr(), key.len() as u32, - value.as_ptr(), value.len() as u32 - ); - } - } - - fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { - unsafe { - ext_set_child_storage.get()( - storage_key.as_ptr(), storage_key.len() as u32, - key.as_ptr(), key.len() as u32, - value.as_ptr(), value.len() as u32 - ); - } - } - - fn clear_storage(key: &[u8]) { - unsafe { - ext_clear_storage.get()( - key.as_ptr(), key.len() as u32 - ); - } - } - - fn clear_child_storage(storage_key: &[u8], key: &[u8]) { - unsafe { - ext_clear_child_storage.get()( - storage_key.as_ptr(), storage_key.len() as u32, - key.as_ptr(), key.len() as u32 - ); - } - } - - fn exists_storage(key: &[u8]) -> bool { - unsafe { - ext_exists_storage.get()( - key.as_ptr(), key.len() as u32 - ) != 0 - } - } - - fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { - unsafe { - ext_exists_child_storage.get()( - storage_key.as_ptr(), storage_key.len() as u32, - key.as_ptr(), key.len() as u32 - ) != 0 - } - } - - fn clear_prefix(prefix: &[u8]) { - unsafe { - ext_clear_prefix.get()( - prefix.as_ptr(), - prefix.len() as u32 - ); - } - } - - fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]) { - unsafe { - ext_clear_child_prefix.get()( - storage_key.as_ptr(), storage_key.len() as u32, - prefix.as_ptr(), prefix.len() as u32 - ); - } - } - - fn kill_child_storage(storage_key: &[u8]) { - unsafe { - ext_kill_child_storage.get()( - storage_key.as_ptr(), - storage_key.len() as u32 - ); - } - } - - fn storage_root() -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_storage_root.get()(result.as_mut_ptr()); - } - result - } - - fn child_storage_root(storage_key: &[u8]) -> Vec { - let mut length: u32 = 0; - unsafe { - let ptr = ext_child_storage_root.get()( - storage_key.as_ptr(), - storage_key.len() as u32, - &mut length - ); - from_raw_parts(ptr, length).expect("ext_child_storage_root never returns u32::max_value; qed") - } - } - - fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]> { - let mut result: [u8; 32] = Default::default(); - let is_set = unsafe { - ext_storage_changes_root.get()(parent_hash.as_ptr(), parent_hash.len() as u32, result.as_mut_ptr()) - }; - - if is_set != 0 { - Some(result) - } else { - None - } - } - - - fn blake2_256_trie_root(_input: Vec<(Vec, Vec)>) -> H256 { - unimplemented!() - } - - fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { - let mut values = Vec::with_capacity(input.len()); - let mut lengths = Vec::with_capacity(input.len()); - for v in input { - values.extend_from_slice(&v); - lengths.push((v.len() as u32).to_le()); - } - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_blake2_256_enumerated_trie_root.get()( - values.as_ptr(), - lengths.as_ptr(), - lengths.len() as u32, - result.as_mut_ptr(), - ); - } - result.into() - } -} - -impl OtherApi for () { - fn chain_id() -> u64 { - unsafe { - ext_chain_id.get()() - } - } - - fn print_num(val: u64) { - unsafe { - ext_print_num.get()(val); - } - } - - fn print_utf8(utf8: &[u8]) { - unsafe { - ext_print_utf8.get()(utf8.as_ptr(), utf8.len() as u32); - } - } - - fn print_hex(data: &[u8]) { - unsafe { - ext_print_hex.get()(data.as_ptr(), data.len() as u32); - } - } - - fn log( - level: LogLevel, - target: &[u8], - message: &[u8] - ) { - unsafe { - ext_log.get()( - level as u32, - target.as_ptr(), - target.len() as u32, - message.as_ptr(), - message.len() as u32, - ) - } - } -} - -impl HashingApi for () { - fn keccak_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_keccak_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn blake2_128(data: &[u8]) -> [u8; 16] { - let mut result: [u8; 16] = Default::default(); - unsafe { - ext_blake2_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn blake2_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_blake2_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn twox_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_twox_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn twox_128(data: &[u8]) -> [u8; 16] { - let mut result: [u8; 16] = Default::default(); - unsafe { - ext_twox_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn twox_64(data: &[u8]) -> [u8; 8] { - let mut result: [u8; 8] = Default::default(); - unsafe { - ext_twox_64.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } -} - -impl CryptoApi for () { - fn ed25519_public_keys(id: KeyTypeId) -> Vec { - let mut res_len = 0u32; - unsafe { - let res_ptr = ext_ed25519_public_keys.get()(id.0.as_ptr(), &mut res_len); - Vec::decode(&mut rstd::slice::from_raw_parts(res_ptr, res_len as usize)).unwrap_or_default() - } - } - - fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public { - let mut res = [0u8; 32]; - let seed = seed.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]); - unsafe { - ext_ed25519_generate.get()(id.0.as_ptr(), seed.as_ptr(), seed.len() as u32, res.as_mut_ptr()) - }; - ed25519::Public(res) - } - - fn ed25519_sign( - id: KeyTypeId, - pubkey: &ed25519::Public, - msg: &[u8], - ) -> Option { - let mut res = [0u8; 64]; - let success = unsafe { - ext_ed25519_sign.get()( - id.0.as_ptr(), - pubkey.0.as_ptr(), - msg.as_ptr(), - msg.len() as u32, - res.as_mut_ptr(), - ) == 0 - }; - - if success { - Some(ed25519::Signature(res)) - } else { - None - } - } - - fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool { - unsafe { - ext_ed25519_verify.get()( - msg.as_ptr(), - msg.len() as u32, - sig.0.as_ptr(), - pubkey.0.as_ptr(), - ) == 0 - } - } - - fn sr25519_public_keys(id: KeyTypeId) -> Vec { - let mut res_len = 0u32; - unsafe { - let res_ptr = ext_sr25519_public_keys.get()(id.0.as_ptr(), &mut res_len); - Vec::decode(&mut rstd::slice::from_raw_parts(res_ptr, res_len as usize)).unwrap_or_default() - } - } - - fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public { - let mut res = [0u8;32]; - let seed = seed.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]); - unsafe { - ext_sr25519_generate.get()(id.0.as_ptr(), seed.as_ptr(), seed.len() as u32, res.as_mut_ptr()) - }; - sr25519::Public(res) - } - - fn sr25519_sign( - id: KeyTypeId, - pubkey: &sr25519::Public, - msg: &[u8], - ) -> Option { - let mut res = [0u8; 64]; - let success = unsafe { - ext_sr25519_sign.get()( - id.0.as_ptr(), - pubkey.0.as_ptr(), - msg.as_ptr(), - msg.len() as u32, - res.as_mut_ptr(), - ) == 0 - }; - - if success { - Some(sr25519::Signature(res)) - } else { - None - } - } - - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { - unsafe { - ext_sr25519_verify.get()( - msg.as_ptr(), - msg.len() as u32, - sig.0.as_ptr(), - pubkey.0.as_ptr(), - ) == 0 - } - } - - 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.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) - } { - 0 => Ok(pubkey), - 1 => Err(EcdsaVerifyError::BadRS), - 2 => Err(EcdsaVerifyError::BadV), - 3 => Err(EcdsaVerifyError::BadSignature), - _ => unreachable!("`ext_secp256k1_ecdsa_recover` only returns 0, 1, 2 or 3; qed"), - } - } - - fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError> { - let mut pubkey = [0u8; 33]; - match unsafe { - ext_secp256k1_ecdsa_recover_compressed.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) - } { - 0 => Ok(pubkey), - 1 => Err(EcdsaVerifyError::BadRS), - 2 => Err(EcdsaVerifyError::BadV), - 3 => Err(EcdsaVerifyError::BadSignature), - _ => unreachable!("`ext_secp256k1_ecdsa_recover_compressed` only returns 0, 1, 2 or 3; qed"), - } - } -} - -impl OffchainApi for () { - fn is_validator() -> bool { - unsafe { ext_is_validator.get()() == 1 } - } - - fn submit_transaction(data: Vec) -> Result<(), ()> { - let ret = unsafe { - ext_submit_transaction.get()(data.as_ptr(), data.len() as u32) - }; - - if ret == 0 { - Ok(()) - } else { - Err(()) - } - } - - fn network_state() -> Result { - let mut len = 0_u32; - let raw_result = unsafe { - let ptr = ext_network_state.get()(&mut len); - - from_raw_parts(ptr, len) - }; - - match raw_result { - Some(raw_result) => codec::Decode::decode(&mut &*raw_result).unwrap_or(Err(())), - None => Err(()) - } - } - - fn timestamp() -> offchain::Timestamp { - offchain::Timestamp::from_unix_millis(unsafe { - ext_timestamp.get()() - }) - } - - fn sleep_until(deadline: offchain::Timestamp) { - unsafe { - ext_sleep_until.get()(deadline.unix_millis()) - } - } - - fn random_seed() -> [u8; 32] { - let mut result = [0_u8; 32]; - unsafe { - ext_random_seed.get()(result.as_mut_ptr()) - } - result - } - - fn local_storage_set(kind: offchain::StorageKind, key: &[u8], value: &[u8]) { - unsafe { - ext_local_storage_set.get()( - kind.into(), - key.as_ptr(), - key.len() as u32, - value.as_ptr(), - value.len() as u32, - ) - } - } - - fn local_storage_compare_and_set( - kind: offchain::StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - let (ptr, len) = match old_value { - Some(old_value) => ( - old_value.as_ptr(), - old_value.len() as u32, - ), - None => (0 as *const u8, u32::max_value()), - }; - - unsafe { - ext_local_storage_compare_and_set.get()( - kind.into(), - key.as_ptr(), - key.len() as u32, - ptr, - len, - new_value.as_ptr(), - new_value.len() as u32, - ) == 0 - } - } - - fn local_storage_get(kind: offchain::StorageKind, key: &[u8]) -> Option> { - let mut len = 0u32; - unsafe { - let ptr = ext_local_storage_get.get()( - kind.into(), - key.as_ptr(), - key.len() as u32, - &mut len, - ); - - from_raw_parts(ptr, len) - } - } - - fn http_request_start(method: &str, url: &str, meta: &[u8]) -> Result { - let method = method.as_bytes(); - let url = url.as_bytes(); - - let result = unsafe { - ext_http_request_start.get()( - method.as_ptr(), - method.len() as u32, - url.as_ptr(), - url.len() as u32, - meta.as_ptr(), - meta.len() as u32, - ) - }; - - if result > u16::max_value() as u32 { - Err(()) - } else { - Ok(offchain::HttpRequestId(result as u16)) - } - } - - fn http_request_add_header(request_id: offchain::HttpRequestId, name: &str, value: &str) -> Result<(), ()> { - let name = name.as_bytes(); - let value = value.as_bytes(); - - let result = unsafe { - ext_http_request_add_header.get()( - request_id.into(), - name.as_ptr(), - name.len() as u32, - value.as_ptr(), - value.len() as u32, - ) - }; - - if result == 0 { - Ok(()) - } else { - Err(()) - } - } - - fn http_request_write_body( - request_id: offchain::HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), offchain::HttpError> { - let res = unsafe { - ext_http_request_write_body.get()( - request_id.into(), - chunk.as_ptr(), - chunk.len() as u32, - deadline.map_or(0, |x| x.unix_millis()), - ) - }; - - if res == 0 { - Ok(()) - } else { - Err(res.try_into().unwrap_or(offchain::HttpError::IoError)) - } - } - - fn http_response_wait( - ids: &[offchain::HttpRequestId], - deadline: Option - ) -> Vec { - let ids = ids.iter().map(|x| x.0 as u32).collect::>(); - let mut statuses = Vec::new(); - statuses.resize(ids.len(), 0u32); - - unsafe { - ext_http_response_wait.get()( - ids.as_ptr(), - ids.len() as u32, - statuses.as_mut_ptr(), - deadline.map_or(0, |x| x.unix_millis()), - ) - } - - statuses - .into_iter() - .map(|status| status.try_into().unwrap_or(offchain::HttpRequestStatus::Invalid)) - .collect() - } - - fn http_response_headers( - request_id: offchain::HttpRequestId, - ) -> Vec<(Vec, Vec)> { - let mut len = 0u32; - let raw_result = unsafe { - let ptr = ext_http_response_headers.get()( - request_id.into(), - &mut len, - ); - - from_raw_parts(ptr, len).expect("ext_http_response_headers never return u32::max_value; qed") - }; - - codec::Decode::decode(&mut &*raw_result).unwrap_or_default() - } - - fn http_response_read_body( - request_id: offchain::HttpRequestId, - buffer: &mut [u8], - deadline: Option, - ) -> Result { - let res = unsafe { - ext_http_response_read_body.get()( - request_id.into(), - buffer.as_mut_ptr(), - buffer.len() as u32, - deadline.map_or(0, |x| x.unix_millis()), - ) - }; - - if res >= u32::max_value() - 255 { - let code = (u32::max_value() - res) + 1; - code.try_into().map_err(|_| offchain::HttpError::IoError) - } else { - Ok(res as usize) - } - } -} - -unsafe fn from_raw_parts(ptr: *mut u8, len: u32) -> Option> { - if len == u32::max_value() { - None - } else { - // Invariants required by Vec::from_raw_parts are not formally fulfilled. - // We don't allocate via String/Vec, but use a custom allocator instead. - // See #300 for more details. - Some(>::from_raw_parts(ptr, len as usize, len as usize)) - } -} - -impl Api for () {}