mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-24 14:45:42 +00:00
Add native environment to make native source-code compatible with wasm.
Also tests.
This commit is contained in:
Generated
+6
@@ -170,6 +170,10 @@ dependencies = [
|
|||||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "environmental"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "error-chain"
|
name = "error-chain"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@@ -833,8 +837,10 @@ dependencies = [
|
|||||||
name = "runtime-support"
|
name = "runtime-support"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"environmental 0.1.0",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"polkadot-state-machine 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ members = [
|
|||||||
"candidate-agreement",
|
"candidate-agreement",
|
||||||
"client",
|
"client",
|
||||||
"collator",
|
"collator",
|
||||||
|
"environmental",
|
||||||
"executor",
|
"executor",
|
||||||
"primitives",
|
"primitives",
|
||||||
"rpc",
|
"rpc",
|
||||||
|
|||||||
@@ -27,20 +27,23 @@ pub fn using_environment<'a, T: 'a, S, F: FnOnce()>(
|
|||||||
global.with(|r| *r.borrow_mut() = 0 as *mut S);
|
global.with(|r| *r.borrow_mut() = 0 as *mut S);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_environment<'r, S, T: 'r, F: FnOnce(&'r mut T)>(
|
pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>(
|
||||||
global: &'static LocalKey<RefCell<*mut S>>,
|
global: &'static LocalKey<RefCell<*mut S>>,
|
||||||
mutator: F,
|
mutator: F,
|
||||||
) {
|
) -> Option<R> {
|
||||||
|
|
||||||
global.with(|r| {
|
global.with(|r| {
|
||||||
let br = r.borrow_mut();
|
let br = r.borrow_mut();
|
||||||
if *br != 0 as *mut S {
|
if *br != 0 as *mut S {
|
||||||
// safe because it's only non-zero when it in with_environment, which
|
// safe because it's only non-zero when it in with_environment, which
|
||||||
// is holding on to the underlying reference safely
|
// is holding on to the underlying reference safely
|
||||||
unsafe {
|
unsafe {
|
||||||
mutator(&mut *(*br as *mut S as *mut T));
|
Some(mutator(&mut *(*br as *mut S as *mut T)))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@@ -64,16 +67,18 @@ macro_rules! declare_generic_environment {
|
|||||||
$crate::using_environment(&GLOBAL, protected, f);
|
$crate::using_environment(&GLOBAL, protected, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with<F: for<'r, 't: 'r> FnOnce(&'r mut $t<'t>)>(f: F) {
|
pub fn with<R, F: for<'r, 't: 'r> FnOnce(&'r mut $t<'t>) -> R>(
|
||||||
|
f: F
|
||||||
|
) -> Option<R> {
|
||||||
let dummy = ();
|
let dummy = ();
|
||||||
with_closed(f, &dummy);
|
with_closed(f, &dummy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_closed<'d: 't, 't: 'r, 'r, F: FnOnce(&'r mut $t<'t>)>(
|
fn with_closed<'d: 't, 't: 'r, 'r, R, F: FnOnce(&'r mut $t<'t>) -> R>(
|
||||||
f: F,
|
f: F,
|
||||||
_dummy: &'d (),
|
_dummy: &'d (),
|
||||||
) {
|
) -> Option<R> {
|
||||||
$crate::with_environment(&GLOBAL, f);
|
$crate::with_environment(&GLOBAL, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,16 +96,18 @@ macro_rules! declare_simple_environment {
|
|||||||
$crate::using_environment(&GLOBAL, protected, f);
|
$crate::using_environment(&GLOBAL, protected, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with<F: for<'r> FnOnce(&'r mut $t)>(f: F) {
|
pub fn with<R, F: for<'r> FnOnce(&'r mut $t -> R)>(
|
||||||
|
f: F
|
||||||
|
) -> Option<R> {
|
||||||
let dummy = ();
|
let dummy = ();
|
||||||
with_closed(f, &dummy);
|
with_closed(f, &dummy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_closed<'d: 'r, 'r, F: FnOnce(&'r mut $t)>(
|
fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t -> R)>(
|
||||||
f: F,
|
f: F,
|
||||||
_dummy: &'d (),
|
_dummy: &'d (),
|
||||||
) {
|
) -> Option<R> {
|
||||||
$crate::with_environment(&GLOBAL, f);
|
$crate::with_environment(&GLOBAL, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,13 +119,13 @@ pub trait IntoUserDefinedElements {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_function_executor {
|
macro_rules! impl_function_executor {
|
||||||
( $objectname:ident : $structname:ty, $( $name:ident ( $( $names:ident : $params:ty ),* ) $( -> $returns:ty )* => $body:tt ),* => $($pre:tt)+ ) => (
|
( $objectname:ident : $structname:ty, $( $name:ident ( $( $names:ident : $params:ty ),* ) $( -> $returns:ty )* => $body:tt ),* => $($pre:tt)+ ) => (
|
||||||
impl $( $pre ) + $crate::wasm_utils::UserFunctionExecutor<$crate::wasm_utils::DummyUserError> for $structname {
|
impl $($pre)+ $crate::wasm_utils::UserFunctionExecutor<$crate::wasm_utils::DummyUserError> for $structname {
|
||||||
dispatch!($objectname, $( $name( $( $names : $params ),* ) $( -> $returns )* => $body ),*);
|
dispatch!($objectname, $( $name( $( $names : $params ),* ) $( -> $returns )* => $body ),*);
|
||||||
}
|
}
|
||||||
impl $( $pre ) + $structname {
|
impl $($pre)+ $structname {
|
||||||
signatures!($( $name( $( $params ),* ) $( -> $returns )* ),*);
|
signatures!($( $name( $( $params ),* ) $( -> $returns )* ),*);
|
||||||
}
|
}
|
||||||
impl $( $pre ) + $crate::wasm_utils::IntoUserDefinedElements for $structname {
|
impl $($pre)+ $crate::wasm_utils::IntoUserDefinedElements for $structname {
|
||||||
fn into_user_defined_elements(&mut self) -> UserDefinedElements<$crate::wasm_utils::DummyUserError> {
|
fn into_user_defined_elements(&mut self) -> UserDefinedElements<$crate::wasm_utils::DummyUserError> {
|
||||||
$crate::wasm_utils::UserDefinedElements {
|
$crate::wasm_utils::UserDefinedElements {
|
||||||
executor: Some(self),
|
executor: Some(self),
|
||||||
|
|||||||
@@ -9,3 +9,5 @@ strict = []
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "1.0.0"
|
lazy_static = "1.0.0"
|
||||||
parking_lot = "0.5"
|
parking_lot = "0.5"
|
||||||
|
polkadot-state-machine = { path = "../../state_machine" , version = "0.1" }
|
||||||
|
environmental = { path = "../../environmental", version = "0.1.0" }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate environmental;
|
||||||
extern crate parking_lot;
|
extern crate polkadot_state_machine;
|
||||||
|
|
||||||
pub use std::vec::Vec;
|
pub use std::vec::Vec;
|
||||||
pub use std::rc::Rc;
|
pub use std::rc::Rc;
|
||||||
@@ -8,38 +8,51 @@ pub use std::cell::RefCell;
|
|||||||
pub use std::boxed::Box;
|
pub use std::boxed::Box;
|
||||||
pub use std::mem::{size_of, transmute};
|
pub use std::mem::{size_of, transmute};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use polkadot_state_machine::Externalities;
|
||||||
use parking_lot::Mutex;
|
use std::fmt;
|
||||||
|
|
||||||
lazy_static! {
|
// TODO: use the real error, not NoError.
|
||||||
static ref HASHMAP: Mutex<HashMap<Vec<u8>, Vec<u8>>> = Mutex::new(HashMap::new());
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct NoError;
|
||||||
|
impl fmt::Display for NoError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ExternalitiesHolder<'a> {
|
||||||
|
ext: &'a mut Externalities<Error=NoError>,
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_generic_environment!(ext : ExternalitiesHolder);
|
||||||
|
|
||||||
pub fn storage(_key: &[u8]) -> Vec<u8> {
|
pub fn storage(_key: &[u8]) -> Vec<u8> {
|
||||||
HASHMAP.lock().get(_key).cloned().unwrap_or_else(Vec::new)
|
ext::with(|holder| holder.ext.storage(_key).ok().map(|s| s.to_vec()))
|
||||||
|
.unwrap_or(None)
|
||||||
|
.unwrap_or_else(|| vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn storage_into<T: Sized>(_key: &[u8]) -> Option<T> {
|
pub fn storage_into<T: Sized>(_key: &[u8]) -> Option<T> {
|
||||||
let size = size_of::<T>();
|
let size = size_of::<T>();
|
||||||
if let Some(value) = HASHMAP.lock().get(_key) {
|
|
||||||
if value.len() == size {
|
ext::with(|holder| {
|
||||||
unsafe {
|
if let Ok(value) = holder.ext.storage(_key) {
|
||||||
let mut result: T = std::mem::uninitialized();
|
if value.len() == size {
|
||||||
std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size)
|
unsafe {
|
||||||
.copy_from_slice(&value);
|
let mut result: T = std::mem::uninitialized();
|
||||||
return Some(result);
|
std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size)
|
||||||
|
.copy_from_slice(&value);
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
None
|
||||||
None
|
}).unwrap_or(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_storage(_key: &[u8], _value: &[u8]) {
|
pub fn set_storage(_key: &[u8], _value: &[u8]) {
|
||||||
HASHMAP.lock().insert(_key.to_vec(), _value.to_vec());
|
ext::with(|holder|
|
||||||
}
|
holder.ext.set_storage(_key.to_vec(), _value.to_vec())
|
||||||
|
);
|
||||||
pub fn init_storage(new: HashMap<Vec<u8>, Vec<u8>>) {
|
|
||||||
*HASHMAP.lock() = new;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@@ -50,6 +63,23 @@ macro_rules! impl_stubs {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct TestExternalities {
|
||||||
|
storage: HashMap<Vec<u8>, Vec<u8>>,
|
||||||
|
}
|
||||||
|
impl Externalities for TestExternalities {
|
||||||
|
type Error = NoError;
|
||||||
|
|
||||||
|
fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! map {
|
macro_rules! map {
|
||||||
($( $name:expr => $value:expr ),*) => (
|
($( $name:expr => $value:expr ),*) => (
|
||||||
@@ -59,15 +89,29 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn storage_works() {
|
fn storage_works() {
|
||||||
assert_eq!(storage(b"hello"), vec![]);
|
let mut t = TestExternalities { storage: map![], };
|
||||||
set_storage(b"hello", b"world");
|
|
||||||
assert_eq!(storage(b"hello"), b"world".to_vec());
|
{
|
||||||
assert_eq!(storage(b"foo"), vec![]);
|
let mut h = ExternalitiesHolder { ext: &mut t, };
|
||||||
set_storage(b"foo", &[1, 2, 3][..]);
|
ext::using(&mut h, || {
|
||||||
assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3]));
|
assert_eq!(storage(b"hello"), b"".to_vec());
|
||||||
assert_eq!(storage_into::<[u8; 3]>(b"hello"), None);
|
set_storage(b"hello", b"world");
|
||||||
init_storage(map![b"foo".to_vec() => b"bar".to_vec()]);
|
assert_eq!(storage(b"hello"), b"world".to_vec());
|
||||||
assert_eq!(storage(b"hello"), vec![]);
|
assert_eq!(storage(b"foo"), b"".to_vec());
|
||||||
assert_eq!(storage(b"foo"), b"bar".to_vec());
|
set_storage(b"foo", &[1, 2, 3][..]);
|
||||||
|
assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3]));
|
||||||
|
assert_eq!(storage_into::<[u8; 3]>(b"hello"), None);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
t.storage = map![b"foo".to_vec() => b"bar".to_vec()];
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut h = ExternalitiesHolder { ext: &mut t, };
|
||||||
|
ext::using(&mut h, || {
|
||||||
|
assert_eq!(storage(b"hello"), b"".to_vec());
|
||||||
|
assert_eq!(storage(b"foo"), b"bar".to_vec());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user