use super::*;
mod native {
extern "C" {
pub fn eth2_loadPreStateRoot(offset: *const u32);
pub fn eth2_blockDataSize() -> u32;
pub fn eth2_blockDataCopy(outputOfset: *const u32, offset: u32, length: u32);
pub fn eth2_savePostStateRoot(offset: *const u32);
pub fn eth2_pushNewDeposit(offset: *const u32, length: u32);
}
}
pub fn load_pre_state_root() -> Bytes32 {
let mut ret = Bytes32::default();
unsafe { native::eth2_loadPreStateRoot(ret.bytes.as_mut_ptr() as *const u32) }
ret
}
pub fn block_data_size() -> usize {
unsafe { native::eth2_blockDataSize() as usize }
}
pub fn unsafe_block_data_copy(from: usize, length: usize, ret: &mut [u8]) {
unsafe {
native::eth2_blockDataCopy(ret.as_mut_ptr() as *const u32, from as u32, length as u32);
}
}
#[cfg(feature = "std")]
pub fn acquire_block_data() -> Vec<u8> {
let length = block_data_size();
let mut ret: Vec<u8> = unsafe_alloc_buffer(length);
unsafe_block_data_copy(0, length, &mut ret);
ret
}
pub fn block_data_copy(from: usize, length: usize, ret: &mut [u8]) -> Result<(), Error> {
let size = block_data_size();
if (size < from) || ((size - from) < length) || (ret.len() < length) {
Err(Error::OutOfBoundsCopy)
} else {
unsafe_block_data_copy(from, length, ret);
Ok(())
}
}
pub fn push_new_deposit(deposit: &[u8]) {
unsafe { native::eth2_pushNewDeposit(deposit.as_ptr() as *const u32, deposit.len() as u32) }
}
pub fn save_post_state_root(state: &Bytes32) {
unsafe { native::eth2_savePostStateRoot(state.bytes.as_ptr() as *const u32) }
}
#[macro_export]
macro_rules! eth2_shard_script {
($process_block:ident) => {
#[cfg(target_arch = "wasm32")]
#[no_mangle]
pub extern "C" fn main() {
let pre_state_root = eth2::load_pre_state_root();
let block_data = eth2::acquire_block_data();
let (post_state_root, deposits) = $process_block(&pre_state_root, &block_data);
eth2::push_new_deposit(&deposits);
eth2::save_post_state_root(&post_state_root)
}
};
}