// 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 . //! This is part of the Substrate runtime. #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(lang_items))] #![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] #![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] use rstd::vec::Vec; use primitives::{ crypto::KeyTypeId, ed25519, sr25519, H256, offchain::{ Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, }, LogLevel, }; /// Error verifying ECDSA signature pub enum EcdsaVerifyError { /// Incorrect value of R or S BadRS, /// Incorrect value of V BadV, /// Invalid signature BadSignature, } /// Converts a public trait definition into a private trait and set of public functions /// that assume the trait is implemented for `()` for ease of calling. macro_rules! export_api { ( $( #[$trait_attr:meta] )* pub(crate) trait $trait_name:ident { $( $( #[$attr:meta] )* fn $name:ident ( $( $arg:ident : $arg_ty:ty ),* $(,)? ) $( -> $ret:ty )? $( where $( $w_name:path : $w_ty:path ),+ )?; )* } ) => { $( #[$trait_attr] )* pub(crate) trait $trait_name { $( $( #[$attr] )* fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )? $( where $( $w_name : $w_ty ),+ )?; )* } $( $( #[$attr] )* pub fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )? $( where $( $w_name : $w_ty ),+ )? { #[allow(deprecated)] <()>:: $name ( $( $arg ),* ) } )* } } export_api! { pub(crate) trait StorageApi { /// Get `key` from storage and return a `Vec`, empty if there's a problem. fn storage(key: &[u8]) -> Option>; /// Get `key` from child storage and return a `Vec`, empty if there's a problem. fn child_storage(storage_key: &[u8], key: &[u8]) -> Option>; /// Get `key` from storage, placing the value into `value_out` and return the number of /// bytes that the entry in storage has beyond the offset or `None` if the storage entry /// doesn't exist at all. /// If `value_out` length is smaller than the returned length, only `value_out` length bytes /// are copied into `value_out`. fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option; /// Get `key` from child storage, placing the value into `value_out` and return the number /// of bytes that the entry in storage has beyond the offset or `None` if the storage entry /// doesn't exist at all. /// If `value_out` length is smaller than the returned length, only `value_out` length bytes /// are copied into `value_out`. fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option; /// Set the storage of some particular key to Some value. fn set_storage(key: &[u8], value: &[u8]); /// Set the child storage of some particular key to Some value. fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]); /// Clear the storage of a key. fn clear_storage(key: &[u8]); /// Clear the storage of a key. fn clear_child_storage(storage_key: &[u8], key: &[u8]); /// Clear an entire child storage. fn kill_child_storage(storage_key: &[u8]); /// Check whether a given `key` exists in storage. fn exists_storage(key: &[u8]) -> bool; /// Check whether a given `key` exists in storage. fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool; /// Clear the storage entries with a key that starts with the given prefix. fn clear_prefix(prefix: &[u8]); /// Clear the child storage entries with a key that starts with the given prefix. fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]); /// "Commit" all existing operations and compute the resultant storage root. fn storage_root() -> [u8; 32]; /// "Commit" all existing operations and compute the resultant child storage root. fn child_storage_root(storage_key: &[u8]) -> Vec; /// "Commit" all existing operations and get the resultant storage change root. fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]>; /// A trie root formed from the iterated items. fn blake2_256_trie_root(input: Vec<(Vec, Vec)>) -> H256; /// A trie root formed from the enumerated items. fn blake2_256_ordered_trie_root(input: Vec>) -> H256; } } export_api! { pub(crate) trait OtherApi { /// The current relay chain identifier. fn chain_id() -> u64; /// Print a number. fn print_num(val: u64); /// Print any valid `utf8` buffer. fn print_utf8(utf8: &[u8]); /// Print any `u8` slice as hex. fn print_hex(data: &[u8]); /// Request to print a log message (stderr) on the host. /// /// Note that this will be only displayed if the host /// is enabed to display log messages with given /// level and target. /// /// Instead of using directly, prefer setting up `RuntimeLogger` /// and using `log` macros. fn log( level: LogLevel, target: &[u8], message: &[u8] ); } } export_api! { pub(crate) trait CryptoApi { /// Returns all ed25519 public keys for the given key id from the keystore. fn ed25519_public_keys(id: KeyTypeId) -> Vec; /// Generate an ed22519 key for the given key type and store it in the keystore. /// /// Returns the raw public key. fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public; /// Sign the given `msg` with the ed25519 key that corresponds to the given public key and /// key type in the keystore. /// /// Returns the raw signature. fn ed25519_sign( id: KeyTypeId, pubkey: &ed25519::Public, msg: &[u8], ) -> Option; /// Verify an ed25519 signature. /// /// Returns `true` when the verification in successful. fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool; /// Returns all sr25519 public keys for the given key id from the keystore. fn sr25519_public_keys(id: KeyTypeId) -> Vec; /// Generate an sr22519 key for the given key type and store it in the keystore. /// /// Returns the raw public key. fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public; /// Sign the given `msg` with the sr25519 key that corresponds to the given public key and /// key type in the keystore. /// /// Returns the raw signature. fn sr25519_sign( id: KeyTypeId, pubkey: &sr25519::Public, msg: &[u8], ) -> Option; /// Verify an sr25519 signature. /// /// Returns `true` when the verification in successful. fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool; /// Verify and recover a SECP256k1 ECDSA signature. /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. /// - returns `Err` if the signature is bad, otherwise the 64-byte pubkey (doesn't include the 0x04 prefix). fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError>; } } export_api! { pub(crate) trait HashingApi { /// Conduct a 256-bit Keccak hash. fn keccak_256(data: &[u8]) -> [u8; 32] ; /// Conduct a 128-bit Blake2 hash. fn blake2_128(data: &[u8]) -> [u8; 16]; /// Conduct a 256-bit Blake2 hash. fn blake2_256(data: &[u8]) -> [u8; 32]; /// Conduct four XX hashes to give a 256-bit result. fn twox_256(data: &[u8]) -> [u8; 32]; /// Conduct two XX hashes to give a 128-bit result. fn twox_128(data: &[u8]) -> [u8; 16]; /// Conduct two XX hashes to give a 64-bit result. fn twox_64(data: &[u8]) -> [u8; 8]; } } export_api! { pub(crate) trait OffchainApi { /// Returns if the local node is a potential validator. /// /// Even if this function returns `true`, it does not mean that any keys are configured /// and that the validator is registered in the chain. fn is_validator() -> bool; /// Submit transaction to the pool. /// /// The transaction will end up in the pool. fn submit_transaction(data: Vec) -> Result<(), ()>; /// Returns information about the local node's network state. fn network_state() -> Result; /// Returns current UNIX timestamp (in millis) fn timestamp() -> Timestamp; /// Pause the execution until `deadline` is reached. fn sleep_until(deadline: Timestamp); /// Returns a random seed. /// /// This is a trully random non deterministic seed generated by host environment. /// Obviously fine in the off-chain worker context. fn random_seed() -> [u8; 32]; /// Sets a value in the local storage. /// /// Note this storage is not part of the consensus, it's only accessible by /// offchain worker tasks running on the same machine. It IS persisted between runs. fn local_storage_set(kind: StorageKind, key: &[u8], value: &[u8]); /// Sets a value in the local storage if it matches current value. /// /// Since multiple offchain workers may be running concurrently, to prevent /// data races use CAS to coordinate between them. /// /// Returns `true` if the value has been set, `false` otherwise. /// /// Note this storage is not part of the consensus, it's only accessible by /// offchain worker tasks running on the same machine. It IS persisted between runs. fn local_storage_compare_and_set( kind: StorageKind, key: &[u8], old_value: Option<&[u8]>, new_value: &[u8], ) -> bool; /// Gets a value from the local storage. /// /// If the value does not exist in the storage `None` will be returned. /// Note this storage is not part of the consensus, it's only accessible by /// offchain worker tasks running on the same machine. It IS persisted between runs. fn local_storage_get(kind: StorageKind, key: &[u8]) -> Option>; /// Initiates a http request given HTTP verb and the URL. /// /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. /// Returns the id of newly started request. fn http_request_start( method: &str, uri: &str, meta: &[u8], ) -> Result; /// Append header to the request. fn http_request_add_header( request_id: HttpRequestId, name: &str, value: &str, ) -> Result<(), ()>; /// Write a chunk of request body. /// /// Writing an empty chunks finalises the request. /// Passing `None` as deadline blocks forever. /// /// Returns an error in case deadline is reached or the chunk couldn't be written. fn http_request_write_body( request_id: HttpRequestId, chunk: &[u8], deadline: Option, ) -> Result<(), HttpError>; /// Block and wait for the responses for given requests. /// /// Returns a vector of request statuses (the len is the same as ids). /// Note that if deadline is not provided the method will block indefinitely, /// otherwise unready responses will produce `DeadlineReached` status. /// /// Passing `None` as deadline blocks forever. fn http_response_wait( ids: &[HttpRequestId], deadline: Option, ) -> Vec; /// Read all response headers. /// /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. /// NOTE response headers have to be read before response body. fn http_response_headers(request_id: HttpRequestId) -> Vec<(Vec, Vec)>; /// Read a chunk of body response to given buffer. /// /// Returns the number of bytes written or an error in case a deadline /// is reached or server closed the connection. /// If `0` is returned it means that the response has been fully consumed /// and the `request_id` is now invalid. /// NOTE this implies that response headers must be read before draining the body. /// Passing `None` as a deadline blocks forever. fn http_response_read_body( request_id: HttpRequestId, buffer: &mut [u8], deadline: Option, ) -> Result; } } /// API trait that should cover all other APIs. /// /// Implement this to make sure you implement all APIs. trait Api: StorageApi + OtherApi + CryptoApi + HashingApi + OffchainApi {} mod imp { use super::*; #[cfg(feature = "std")] include!("../with_std.rs"); #[cfg(not(feature = "std"))] include!("../without_std.rs"); } #[cfg(feature = "std")] pub use self::imp::{StorageOverlay, ChildrenStorageOverlay, with_storage}; #[cfg(not(feature = "std"))] pub use self::imp::ext::*; /// Type alias for Externalities implementation used in tests. #[cfg(feature = "std")] pub type TestExternalities = self::imp::TestExternalities;