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 () {}