mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 07:41:08 +00:00
fully refactor runtime-std to use conditional compilation
This commit is contained in:
@@ -1,6 +1,21 @@
|
||||
[package]
|
||||
name = "runtime-std"
|
||||
name = "polkadot-runtime-std"
|
||||
version = "0.1.0"
|
||||
authors = ["Robert Habermeier <rphmeier@gmail.com>"]
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.2"
|
||||
|
||||
[dependencies]
|
||||
pwasm-alloc = { path = "../wasm-runtime/pwasm-alloc", version = "0.1" }
|
||||
pwasm-libc = { path = "../wasm-runtime/pwasm-libc", version = "0.1" }
|
||||
environmental = { path = "../environmental", version = "0.1", optional = true }
|
||||
polkadot-state-machine = { path = "../state-machine", version = "0.1", optional = true }
|
||||
polkadot-primitives = { path = "../primitives", version = "0.1", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["environmental", "polkadot-state-machine", "polkadot-primitives"]
|
||||
nightly = []
|
||||
strict = []
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
//! Set a nightly feature
|
||||
|
||||
extern crate rustc_version;
|
||||
use rustc_version::{version, version_meta, Channel};
|
||||
|
||||
fn main() {
|
||||
// Assert we haven't travelled back in time
|
||||
assert!(version().unwrap().major >= 1);
|
||||
|
||||
// Set cfg flags depending on release channel
|
||||
if let Channel::Nightly = version_meta().unwrap().channel {
|
||||
println!("cargo:rustc-cfg=feature=\"nightly\"");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,39 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(lang_items))]
|
||||
#![cfg_attr(not(feature = "std"), feature(core_intrinsics))]
|
||||
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
||||
|
||||
#![cfg_attr(feature = "std", doc = "Polkadot runtime standard library as compiled when linked with Rust's standard library.")]
|
||||
#![cfg_attr(not(feature = "std"), doc = "Polkadot's runtime standard library as compiled without Rust's standard library.")]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
include!("../with_std.rs");
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
include!("../without_std.rs");
|
||||
|
||||
|
||||
|
||||
/// Prelude of common useful imports.
|
||||
///
|
||||
/// This should include only things which are in the normal std prelude.
|
||||
pub mod prelude {
|
||||
pub use ::vec::Vec;
|
||||
pub use ::boxed::Box;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#[macro_use]
|
||||
extern crate environmental;
|
||||
|
||||
extern crate polkadot_state_machine;
|
||||
extern crate polkadot_primitives as primitives;
|
||||
|
||||
use std::fmt;
|
||||
use primitives::ed25519;
|
||||
|
||||
pub use std::vec;
|
||||
pub use std::rc;
|
||||
pub use std::cell;
|
||||
pub use std::boxed;
|
||||
pub use std::slice;
|
||||
pub use std::mem;
|
||||
|
||||
pub use polkadot_state_machine::{Externalities, ExternalitiesError};
|
||||
use primitives::hexdisplay::HexDisplay;
|
||||
|
||||
// TODO: use the real error, not NoError.
|
||||
|
||||
#[derive(Debug)]
|
||||
/// As it says - an empty type we use for errors.
|
||||
pub struct NoError;
|
||||
impl fmt::Display for NoError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") }
|
||||
}
|
||||
|
||||
environmental!(ext : trait Externalities);
|
||||
|
||||
/// Get `key` from storage and return a `Vec`, empty if there's a problem.
|
||||
pub fn storage(key: &[u8]) -> Vec<u8> {
|
||||
ext::with(|ext| ext.storage(key).ok().map(|s| s.to_vec()))
|
||||
.expect("read_storage cannot be called outside of an Externalities-provided environment.")
|
||||
.unwrap_or_else(Vec::new)
|
||||
}
|
||||
|
||||
/// Get `key` from storage, placing the value into `value_out` (as much as possible) and return
|
||||
/// the number of bytes that the key in storage was.
|
||||
pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize {
|
||||
ext::with(|ext| {
|
||||
if let Ok(value) = ext.storage(key) {
|
||||
let value = &value[value_offset..];
|
||||
let written = ::std::cmp::min(value.len(), value_out.len());
|
||||
value_out[0..written].copy_from_slice(&value[0..written]);
|
||||
value.len()
|
||||
} else {
|
||||
// no-entry is treated as an empty vector of bytes.
|
||||
// TODO: consider allowing empty-vector to exist separately to no-entry (i.e. return
|
||||
// Option<usize>)
|
||||
0
|
||||
}
|
||||
}).expect("read_storage cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
/// Set the storage to some particular key.
|
||||
pub fn set_storage(key: &[u8], value: &[u8]) {
|
||||
ext::with(|ext|
|
||||
ext.set_storage(key.to_vec(), value.to_vec())
|
||||
);
|
||||
}
|
||||
|
||||
/// The current relay chain identifier.
|
||||
pub fn chain_id() -> u64 {
|
||||
ext::with(|ext|
|
||||
ext.chain_id()
|
||||
).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Conduct a Keccak-256 hash of the given data.
|
||||
pub use primitives::{blake2_256, twox_128, twox_256};
|
||||
|
||||
/// Verify a ed25519 signature.
|
||||
pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool {
|
||||
ed25519::verify(&sig[..], msg, &pubkey[..])
|
||||
}
|
||||
|
||||
/// Execute the given closure with global function available whose functionality routes into the
|
||||
/// externalities `ext`. Forwards the value that the closure returns.
|
||||
pub fn with_externalities<R, F: FnOnce() -> R>(ext: &mut Externalities, f: F) -> R {
|
||||
ext::using(ext, f)
|
||||
}
|
||||
|
||||
/// Trait for things which can be printed.
|
||||
pub trait Printable {
|
||||
fn print(self);
|
||||
}
|
||||
|
||||
impl<'a> Printable for &'a [u8] {
|
||||
fn print(self) {
|
||||
println!("Runtime: {}", HexDisplay::from(&self));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Printable for &'a str {
|
||||
fn print(self) {
|
||||
println!("Runtime: {}", self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for u64 {
|
||||
fn print(self) {
|
||||
println!("Runtime: {}", self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Print a printable value.
|
||||
pub fn print<T: Printable + Sized>(value: T) {
|
||||
value.print();
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_stubs {
|
||||
($( $name:ident ),*) => {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct TestExternalities {
|
||||
storage: HashMap<Vec<u8>, Vec<u8>>,
|
||||
}
|
||||
impl Externalities for TestExternalities {
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> {
|
||||
Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice))
|
||||
}
|
||||
|
||||
fn set_storage(&mut self, key: Vec<u8>, value: Vec<u8>) {
|
||||
self.storage.insert(key, value);
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> u64 { 42 }
|
||||
}
|
||||
|
||||
macro_rules! map {
|
||||
($( $name:expr => $value:expr ),*) => (
|
||||
vec![ $( ( $name, $value ) ),* ].into_iter().collect()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_works() {
|
||||
let mut t = TestExternalities { storage: map![], };
|
||||
assert!(with_externalities(&mut t, || {
|
||||
assert_eq!(storage(b"hello"), b"".to_vec());
|
||||
set_storage(b"hello", b"world");
|
||||
assert_eq!(storage(b"hello"), b"world".to_vec());
|
||||
assert_eq!(storage(b"foo"), b"".to_vec());
|
||||
set_storage(b"foo", &[1, 2, 3][..]);
|
||||
true
|
||||
}));
|
||||
|
||||
t.storage = map![b"foo".to_vec() => b"bar".to_vec()];
|
||||
|
||||
assert!(!with_externalities(&mut t, || {
|
||||
assert_eq!(storage(b"hello"), b"".to_vec());
|
||||
assert_eq!(storage(b"foo"), b"bar".to_vec());
|
||||
false
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_storage_works() {
|
||||
let mut t = TestExternalities { storage: map![
|
||||
b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
|
||||
], };
|
||||
|
||||
with_externalities(&mut t, || {
|
||||
let mut v = [0u8; 4];
|
||||
assert!(read_storage(b":test", &mut v[..], 0) >= 4);
|
||||
assert_eq!(v, [11u8, 0, 0, 0]);
|
||||
let mut w = [0u8; 11];
|
||||
assert!(read_storage(b":test", &mut w[..], 4) >= 11);
|
||||
assert_eq!(&w, b"Hello world");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate pwasm_libc;
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate pwasm_alloc;
|
||||
|
||||
pub use alloc::vec;
|
||||
pub use alloc::boxed;
|
||||
pub use alloc::rc;
|
||||
pub use core::mem;
|
||||
pub use core::slice;
|
||||
pub use core::cell;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
#[no_mangle]
|
||||
pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) {
|
||||
unsafe {
|
||||
ext_print_utf8(_file.as_ptr() as *const u8, _file.len() as u32);
|
||||
ext_print_num(_line as u64);
|
||||
ext_print_num(_col as u64);
|
||||
::core::intrinsics::abort()
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32);
|
||||
fn ext_print_hex(data: *const u8, len: u32);
|
||||
fn ext_print_num(value: u64);
|
||||
fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32);
|
||||
fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8;
|
||||
fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32;
|
||||
fn ext_chain_id() -> u64;
|
||||
fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8);
|
||||
fn ext_twox_128(data: *const u8, len: u32, out: *mut u8);
|
||||
fn ext_twox_256(data: *const u8, len: u32, out: *mut u8);
|
||||
fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32;
|
||||
}
|
||||
|
||||
/// Get `key` from storage and return a `Vec`, empty if there's a problem.
|
||||
pub fn storage(key: &[u8]) -> Vec<u8> {
|
||||
let mut length: u32 = 0;
|
||||
unsafe {
|
||||
let ptr = ext_get_allocated_storage(key.as_ptr(), key.len() as u32, &mut length);
|
||||
Vec::from_raw_parts(ptr, length as usize, length as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the storage to some particular key.
|
||||
pub fn set_storage(key: &[u8], value: &[u8]) {
|
||||
unsafe {
|
||||
ext_set_storage(
|
||||
key.as_ptr(), key.len() as u32,
|
||||
value.as_ptr(), value.len() as u32
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get `key` from storage, placing the value into `value_out` (as much as possible) and return
|
||||
/// the number of bytes that the key in storage was.
|
||||
pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize {
|
||||
unsafe {
|
||||
ext_get_storage_into(key.as_ptr(), key.len() as u32, value_out.as_mut_ptr(), value_out.len() as u32, value_offset as u32) as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// The current relay chain identifier.
|
||||
pub fn chain_id() -> u64 {
|
||||
unsafe {
|
||||
ext_chain_id()
|
||||
}
|
||||
}
|
||||
|
||||
/// Conduct a 256-bit Blake2 hash.
|
||||
pub fn blake2_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
// guaranteed to write into result.
|
||||
unsafe {
|
||||
ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Conduct four XX hashes to give a 256-bit result.
|
||||
pub fn twox_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
// guaranteed to write into result.
|
||||
unsafe {
|
||||
ext_twox_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Conduct two XX hashes to give a 128-bit result.
|
||||
pub fn twox_128(data: &[u8]) -> [u8; 16] {
|
||||
let mut result: [u8; 16] = Default::default();
|
||||
// guaranteed to write into result.
|
||||
unsafe {
|
||||
ext_twox_128(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Verify a ed25519 signature.
|
||||
pub fn ed25519_verify(sig: &[u8], msg: &[u8], pubkey: &[u8]) -> bool {
|
||||
sig.len() == 64 && pubkey.len() == 32 && unsafe {
|
||||
ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ptr())
|
||||
} == 0
|
||||
}
|
||||
|
||||
/// Trait for things which can be printed.
|
||||
pub trait Printable {
|
||||
fn print(self);
|
||||
}
|
||||
|
||||
impl<'a> Printable for &'a [u8] {
|
||||
fn print(self) {
|
||||
unsafe {
|
||||
ext_print_hex(self.as_ptr(), self.len() as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Printable for &'a str {
|
||||
fn print(self) {
|
||||
unsafe {
|
||||
ext_print_utf8(self.as_ptr() as *const u8, self.len() as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for u64 {
|
||||
fn print(self) {
|
||||
unsafe { ext_print_num(self); }
|
||||
}
|
||||
}
|
||||
|
||||
/// Print a printable value.
|
||||
pub fn print<T: Printable + Sized>(value: T) {
|
||||
value.print();
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_stubs {
|
||||
( $( $name:ident ),* ) => {
|
||||
pub mod _internal {
|
||||
$(
|
||||
#[no_mangle]
|
||||
pub fn $name(input_data: *mut u8, input_len: usize) -> u64 {
|
||||
let input = if input_len == 0 {
|
||||
&[0u8; 0]
|
||||
} else {
|
||||
unsafe {
|
||||
$crate::slice::from_raw_parts(input_data, input_len)
|
||||
}
|
||||
};
|
||||
|
||||
let output = super::$name(input);
|
||||
output.as_ptr() as u64 + ((output.len() as u64) << 32)
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user