mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 14:41:11 +00:00
20a3989785
* Implement Printable for tuples. * Add debugging function. * Add debug 1. * Implement for everything. * RuntimeDebug derive. * Introduce RuntimeDebug. * Add some dummy logging. * Replace RuntimeDebug with Debug. * Revert "Replace RuntimeDebug with Debug." This reverts commit bc47070a8cb30241b2b590b2fa29fd195088162f. * Working on Debug for all. * Fix bounds. * Add debug utils. * Implement runtime logging. * Add some docs and clean up. * Clean up derives. * Fix custom derive impl. * Bump runtime. * Fix long lines. * Fix doc test. * Use CARGO_CFG_STD. * Revert "Use CARGO_CFG_STD." This reverts commit ea429566de18ed0fa052571b359eb9826a64a9f4. * Use parse_macro_input * Update lockfile. * Apply review suggestions. * Remove stray re-export. * Add no-std impl. * Update lockfile.
393 lines
13 KiB
Rust
393 lines
13 KiB
Rust
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
//! 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<Vec<u8>>;
|
|
|
|
/// Get `key` from child storage and return a `Vec`, empty if there's a problem.
|
|
fn child_storage(storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>>;
|
|
|
|
/// 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<usize>;
|
|
|
|
/// 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<usize>;
|
|
|
|
/// 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<u8>;
|
|
|
|
/// "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<u8>, Vec<u8>)>) -> H256;
|
|
|
|
/// A trie root formed from the enumerated items.
|
|
fn blake2_256_ordered_trie_root(input: Vec<Vec<u8>>) -> 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<ed25519::Public>;
|
|
/// 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<ed25519::Signature>;
|
|
/// 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<sr25519::Public>;
|
|
/// 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<sr25519::Signature>;
|
|
/// 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<u8>) -> Result<(), ()>;
|
|
|
|
/// Returns information about the local node's network state.
|
|
fn network_state() -> Result<OpaqueNetworkState, ()>;
|
|
|
|
/// 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<Vec<u8>>;
|
|
|
|
/// 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<HttpRequestId, ()>;
|
|
|
|
/// 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<Timestamp>,
|
|
) -> 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<Timestamp>,
|
|
) -> Vec<HttpRequestStatus>;
|
|
|
|
/// 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<u8>, Vec<u8>)>;
|
|
|
|
/// 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<Timestamp>,
|
|
) -> Result<usize, HttpError>;
|
|
}
|
|
}
|
|
|
|
/// 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<primitives::Blake2Hasher, u64>;
|