fvm-std 1.0.0

tool for user to write contract which will be run in hyperchain with rust
Documentation
use crate::prelude::*;
use crate::types::LogLevel;

pub(crate) mod env {
    extern "C" {
        pub(crate) fn fvm_storage_read(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32,
                                       val: *mut u8, vlen: u32, offset: u32) -> u32;
        pub(crate) fn fvm_call_contract(addr: *const u8, input_ptr: *const u8, input_len: u32) -> u32;
        pub(crate) fn fvm_cns_call_contract(cns: *const u8, cns_len: u32, input_ptr: *const u8, input_len: u32) -> u32;
        pub(crate) fn fvm_storage_write(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32, val: *const u8, vlen: u32);
        pub(crate) fn fvm_storage_delete(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32);
        pub(crate) fn fvm_block_height() -> u64;
        pub(crate) fn fvm_input_length() -> u32;
        pub(crate) fn fvm_block_time() -> u64;
        pub(crate) fn fvm_fetch_input(dst: *mut u8);
        pub(crate) fn fvm_tx_hash(tx_hash: *const u8);
        pub(crate) fn fvm_self_address(dest: *mut u8);
        pub(crate) fn fvm_caller_address(dest: *mut u8);
        pub(crate) fn fvm_origin_address(dest: *mut u8);
        pub(crate) fn fvm_return(ptr: *const u8, len: u32);
        pub(crate) fn fvm_revert(ptr: *const u8, len: u32) -> !;
        pub(crate) fn fvm_log(ptr: *const u8, len: u32);
        pub(crate) fn fvm_debug(class_prt: *const u8, class_len: u32, ptr: *const u8, len: u32, level: u32);
        pub(crate) fn fvm_call_return(dst: *mut u8);
        pub(crate) fn fvm_sha256(data_ptr: *const u8, len: u32, val: *mut u8);
        pub(crate) fn fvm_add_list_key(list_name_ptr: *const u8, list_name_len: u32, index: u32) -> i64;
        pub(crate) fn fvm_get_list_key(list_name_ptr: *const u8, list_name_len: u32, index: u32) -> i64;
        pub(crate) fn fvm_remove_list_key(list_name_ptr: *const u8, list_name_len: u32, index: u32) -> i64;
        pub(crate) fn fvm_write_list_keys(old_list_name_ptr: *const u8, old_list_name_len: u32, new_list_name_ptr: *const u8, new_list_name_len: u32, size: u32);
    }
}

pub(crate) fn call_contract(addr: &Address, input: &[u8]) -> Vec<u8> {
    let addr: &[u8] = addr.as_ref();
    let size =
        unsafe { env::fvm_call_contract(addr.as_ptr(), input.as_ptr(), input.len() as u32) };
    let mut output = vec![0u8; size as usize];
    if size != 0 {
        let value = &mut output[..];
        unsafe {
            env::fvm_call_return(value.as_mut_ptr());
        }
    }

    output
}

pub(crate) fn cns_call_contract(cns: &[u8], input: &[u8]) -> Vec<u8> {
    let size =
        unsafe { env::fvm_cns_call_contract(cns.as_ptr(), cns.len() as u32, input.as_ptr(), input.len() as u32) };
    let mut output = vec![0u8; size as usize];
    if size != 0 {
        let value = &mut output[..];
        unsafe {
            env::fvm_call_return(value.as_mut_ptr());
        }
    }

    output
}


pub(crate) fn storage_write(key: &[u8], prefix: &[u8], val: &[u8]) {
    unsafe {
        env::fvm_storage_write(key.as_ptr(), key.len() as u32,
                               prefix.as_ptr(), prefix.len() as u32,
                               val.as_ptr(), val.len() as u32);
    }
}

pub(crate) fn storage_read(key: &[u8], prefix: &[u8]) -> Option<Vec<u8>> {
    const INITIAL: usize = 32;
    let mut val = vec![0; INITIAL];
    let size = unsafe {
        env::fvm_storage_read(
            key.as_ptr(), key.len() as u32,
            prefix.as_ptr(), prefix.len() as u32,
            val.as_mut_ptr(),
            val.len() as u32,
            0,
        )
    };

    // no value find for key
    if size == 0 {
        return None;
    }
    let size = size as usize;
    val.resize(size, 0);
    if size > INITIAL {
        let value = &mut val[INITIAL..];
        debug_assert!(value.len() == size - INITIAL);
        unsafe {
            env::fvm_storage_read(
                key.as_ptr(), key.len() as u32,
                prefix.as_ptr(), prefix.len() as u32,
                value.as_mut_ptr(),
                value.len() as u32,
                INITIAL as u32,
            )
        };
    }

    Some(val)
}

pub(crate) fn storage_delete(key: &[u8], prefix: &[u8]) {
    unsafe {
        env::fvm_storage_delete(key.as_ptr(), key.len() as u32,
                                prefix.as_ptr(), prefix.len() as u32);
    }
}

pub(crate) fn block_time() -> u64 {
    unsafe { env::fvm_block_time() }
}

pub(crate) fn block_height() -> u64 {
    unsafe { env::fvm_block_height() }
}

pub(crate) fn self_address() -> Address {
    let mut addr: Address = Address::zero();
    unsafe {
        env::fvm_self_address(addr.as_mut().as_mut_ptr());
    }

    addr
}

pub(crate) fn caller_address() -> Address {
    let mut addr: Address = Address::zero();
    unsafe {
        env::fvm_caller_address(addr.as_mut().as_mut_ptr());
    }
    addr
}

pub(crate) fn origin_address() -> Address {
    let mut addr: Address = Address::zero();
    unsafe {
        env::fvm_origin_address(addr.as_mut().as_mut_ptr());
    }
    addr
}

pub(crate) fn tx_hash() -> H256 {
    let tx_hash = H256::zero();
    unsafe {
        env::fvm_tx_hash(tx_hash.as_ptr());
    }
    tx_hash
}

pub(crate) fn sha256(data: impl AsRef<[u8]>) -> H256 {
    let data = data.as_ref();
    let mut hash = H256::zero();
    unsafe {
        env::fvm_sha256(data.as_ptr(), data.len() as u32, hash.as_mut_ptr());
    }
    hash
}


pub(crate) fn input() -> Vec<u8> {
    let len = unsafe { env::fvm_input_length() };

    if len == 0 {
        Vec::new()
    } else {
        let mut data = vec![0; len as usize];
        unsafe {
            env::fvm_fetch_input(data.as_mut_ptr());
        }
        data
    }
}

pub(crate) fn ret(data: &[u8]) {
    unsafe {
        env::fvm_return(data.as_ptr(), data.len() as u32);
    }
}

pub(crate) fn event(data: &[u8]) {
    unsafe {
        env::fvm_log(data.as_ptr(), data.len() as u32);
    }
}

pub(crate) fn log(class_name: &[u8], data: &[u8], level: LogLevel) {
    let level_type: u32 = match level {
        LogLevel::CRITICAL => 0,
        LogLevel::ERROR => 1,
        LogLevel::WARNING => 2,
        LogLevel::NOTICE => 3,
        LogLevel::INFO => 4,
        LogLevel::DEBUG => 5,
    };
    unsafe {
        env::fvm_debug(class_name.as_ptr(), class_name.len() as u32, data.as_ptr(), data.len() as u32, level_type);
    }
}

pub(crate) fn revert(msg: &str) -> ! {
    unsafe {
        env::fvm_revert(msg.as_ptr(), msg.len() as u32);
    }
}

pub(crate) fn add_list_key(list_name: &[u8], index: u32) -> Option<i64> {
    let key =
        unsafe { env::fvm_add_list_key(list_name.as_ptr(), list_name.len() as u32, index) };
    if key < 0 {
        None
    } else {
        Some(key)
    }
}

pub(crate) fn get_list_key(list_name: &[u8], index: u32) -> Option<i64> {
    let key =
        unsafe { env::fvm_get_list_key(list_name.as_ptr(), list_name.len() as u32, index) };
    if key < 0 {
        None
    } else {
        Some(key)
    }
}

pub(crate) fn remove_list_key(list_name: &[u8], index: u32) -> Option<i64> {
    let key =
        unsafe { env::fvm_remove_list_key(list_name.as_ptr(), list_name.len() as u32, index) };
    if key < 0 {
        None
    } else {
        Some(key)
    }
}

pub(crate) fn write_list_keys_back(old_list_name: &[u8], list_name: &[u8], size: u32) {
    unsafe { env::fvm_write_list_keys(old_list_name.as_ptr(), old_list_name.len() as u32, list_name.as_ptr(), list_name.len() as u32, size) };
}