extern "C" {
/**
* @brief Set global verbosity level of the library
* @param verbosity_level New verbosity level (0 - never, 1 - error, 2 - warning, 3 - info, 4 - debug)
*/
pub fn emulator_set_verbosity_level(verbosity_level: u32) -> bool;
/**
* @brief Create TVM emulator
* @param code_boc Base64 encoded BoC serialized smart contract code cell
* @param data_boc Base64 encoded BoC serialized smart contract data cell
* @param vm_log_verbosity Verbosity level of VM log
* @return Pointer to TVM emulator object
*/
pub fn tvm_emulator_create(
code: *const std::os::raw::c_char,
data: *const std::os::raw::c_char,
vm_log_verbosity: u32,
) -> *mut ::std::os::raw::c_void;
/**
* @brief Set libraries for TVM emulator
* @param libs_boc Base64 encoded BoC serialized libraries dictionary (HashmapE 256 ^Cell).
* @return true in case of success, false in case of error
*/
pub fn tvm_emulator_set_libraries(
tvm_emulator: *mut std::os::raw::c_void,
libs_boc: *const std::os::raw::c_char,
) -> bool;
/**
* @brief Set c7 parameters
* @param tvm_emulator Pointer to TVM emulator
* @param address Adress of smart contract
* @param unixtime Unix timestamp
* @param balance Smart contract balance
* @param rand_seed_hex Random seed as hex string of length 64
* @param config Base64 encoded BoC serialized Config dictionary (Hashmap 32 ^Cell)
* @return true in case of success, false in case of error
*/
pub fn tvm_emulator_set_c7(
tvm_emulator: *mut std::os::raw::c_void,
address: *const std::os::raw::c_char,
unixtime: u32,
balance: u64,
rand_seed_hex: *const std::os::raw::c_char,
config: *const std::os::raw::c_char,
) -> bool;
/// Sets extra-currency balances on a TVM emulator.
///
/// `extra_currencies` uses the upstream `currency_id=balance` space-separated format.
///
/// # Safety
///
/// `tvm_emulator` must be a valid, live TVM emulator pointer and `extra_currencies` must point
/// to a valid, NUL-terminated C string for the duration of the call.
pub fn tvm_emulator_set_extra_currencies(
tvm_emulator: *mut std::os::raw::c_void,
extra_currencies: *const std::os::raw::c_char,
) -> bool;
/// Sets a previously created configuration object on a TVM emulator.
///
/// The configuration remains caller-owned and must outlive the emulator's use of it.
///
/// # Safety
///
/// `tvm_emulator` must be a valid, live TVM emulator pointer and `config` must be a valid,
/// live pointer returned by [`emulator_config_create`](crate::emulator_config_create).
pub fn tvm_emulator_set_config_object(
tvm_emulator: *mut std::os::raw::c_void,
config: *mut std::os::raw::c_void,
) -> bool;
/// Sets the previous-blocks tuple used as the thirteenth element of `c7`.
///
/// # Safety
///
/// `tvm_emulator` must be a valid, live TVM emulator pointer. If `info_boc` is non-null, it
/// must point to a valid, NUL-terminated C string for the duration of the call.
pub fn tvm_emulator_set_prev_blocks_info(
tvm_emulator: *mut std::os::raw::c_void,
info_boc: *const std::os::raw::c_char,
) -> bool;
/**
* @brief Set TVM gas limit
* @param tvm_emulator Pointer to TVM emulator
* @param gas_limit Gas limit
* @return true in case of success, false in case of error
*/
pub fn tvm_emulator_set_gas_limit(
tvm_emulator: *mut std::os::raw::c_void,
gas_limit: u64,
) -> bool;
/**
* @brief Enable or disable TVM debug primitives
* @param tvm_emulator Pointer to TVM emulator
* @param debug_enabled Whether debug primitives should be enabled or not
* @return true in case of success, false in case of error
*/
pub fn tvm_emulator_set_debug_enabled(
tvm_emulator: *mut std::os::raw::c_void,
debug_enabled: std::os::raw::c_int,
) -> bool;
/**
* @brief Run get method
* @param tvm_emulator Pointer to TVM emulator
* @param method_id Integer method id
* @param stack_boc Base64 encoded BoC serialized stack (VmStack)
* @return Json object with error:
* {
* "success": false,
* "error": "Error description"
* }
* Or success:
* {
* "success": true
* "vm_log": "...",
* "vm_exit_code": 0,
* "stack": "Base64 encoded BoC serialized stack (VmStack)",
* "missing_library": null,
* "gas_used": 1212
* }
*/
pub fn tvm_emulator_run_get_method(
tvm_emulator: *mut std::os::raw::c_void,
method_id: i32,
stack_boc: *const std::os::raw::c_char,
) -> *const std::os::raw::c_char;
/**
* @brief Run get method with raw params
* @param len Length of params
* @param params_boc serialized params
* @param gas_limit Gas limit
* @return buffer with result length and result
* result is serialized cell chat contains:
* result.code: i32
* result.gas_used: i64
* vm stack: ref
*/
pub fn tvm_emulator_emulate_run_method(
len: u32,
params_boc: *const std::os::raw::c_char,
gas_limit: i64,
) -> *const std::os::raw::c_char;
/// Runs the optimized get-method emulator and returns both the response and VM log.
///
/// The returned opaque result owns both of its string fields and must be released with
/// [`run_method_detailed_result_destroy`].
///
/// # Safety
///
/// `params_boc` must point to a readable buffer of at least `len` bytes. The returned pointer
/// must not be used after it is destroyed.
pub fn tvm_emulator_emulate_run_method_detailed(
len: u32,
params_boc: *const std::os::raw::c_char,
gas_limit: i64,
) -> *mut std::os::raw::c_void;
/// Destroys a detailed get-method result and its response and log fields.
///
/// # Safety
///
/// `detailed_result` must be a valid pointer returned by
/// [`tvm_emulator_emulate_run_method_detailed`] that has not already been destroyed.
pub fn run_method_detailed_result_destroy(detailed_result: *mut std::os::raw::c_void);
/**
* @brief Send external message
* @param tvm_emulator Pointer to TVM emulator
* @param message_body_boc Base64 encoded BoC serialized message body cell.
* @return Json object with error:
* {
* "success": false,
* "error": "Error description"
* }
* Or success:
* {
* "success": true,
* "new_code": "Base64 boc decoded new code cell",
* "new_data": "Base64 boc decoded new data cell",
* "accepted": true,
* "vm_exit_code": 0,
* "vm_log": "...",
* "missing_library": null,
* "gas_used": 1212,
* "actions": "Base64 boc decoded actions cell of type (OutList n)"
* }
*/
pub fn tvm_emulator_send_external_message(
tvm_emulator: *mut std::os::raw::c_void,
message_body_boc: *const std::os::raw::c_char,
) -> *const ::std::os::raw::c_char;
/**
* @brief Send internal message
* @param tvm_emulator Pointer to TVM emulator
* @param message_body_boc Base64 encoded BoC serialized message body cell.
* @param amount Amount of nanograms attached with internal message.
* @return Json object with error:
* {
* "success": false,
* "error": "Error description"
* }
* Or success:
* {
* "success": true,
* "new_code": "Base64 boc decoded new code cell",
* "new_data": "Base64 boc decoded new data cell",
* "accepted": true,
* "vm_exit_code": 0,
* "vm_log": "...",
* "missing_library": null,
* "gas_used": 1212,
* "actions": "Base64 boc decoded actions cell of type (OutList n)"
* }
*/
pub fn tvm_emulator_send_internal_message(
tvm_emulator: *mut std::os::raw::c_void,
message_body_boc: *const std::os::raw::c_char,
amount: u64,
) -> *const ::std::os::raw::c_char;
/**
* @brief Destroy TVM emulator object
* @param tvm_emulator Pointer to TVM emulator object
*/
pub fn tvm_emulator_destroy(tvm_emulator: *mut std::os::raw::c_void);
/// Destroys a string allocated by the emulator library.
///
/// Use this for strings returned by emulator functions unless their documentation specifies a
/// different owner. A null pointer is accepted.
///
/// # Safety
///
/// `string` must be null or a live pointer allocated and returned by the emulator library that
/// has not already been destroyed. It must not be used after this call.
pub fn string_destroy(string: *const std::os::raw::c_char);
/// Returns JSON containing the emulator library's commit hash and commit date.
///
/// The returned string must be released with [`string_destroy`].
///
/// # Safety
///
/// The returned pointer must be checked for null before dereferencing and must not be used after
/// it is passed to [`string_destroy`].
pub fn emulator_version() -> *const std::os::raw::c_char;
}
#[cfg(test)]
mod tests {
use super::*;
use std::error::Error;
use std::ffi::{CStr, CString};
unsafe fn take_emulator_string(
value: *const std::os::raw::c_char,
) -> Result<String, Box<dyn Error>> {
assert!(!value.is_null());
let value_owned = CStr::from_ptr(value).to_str()?.to_owned();
string_destroy(value);
Ok(value_owned)
}
#[test]
fn test_all_tvm_emulator_exports() -> Result<(), Box<dyn Error>> {
let code = "te6cckECCwEAAe0AART/APSkE/S88sgLAQIBYgIDAgLMBAUCA3pgCQoD79mRDjgEit8GhpgYC42Eit8H0gGADpj+mf9qJofQB9IGpqGEAKqThdRxgamqiq44L5cCSA/SB9AGoYEGhAMGuQ/QAYEogaKCF4BFAqkGQoAn0BLGeLZmZk9qpwQQg97svvKThdcYEakuAB8YEYAmACcYEvgsIH+XhAYHCACT38FCIBuCoQCaoKAeQoAn0BLGeLAOeLZmSRZGWAiXoAegBlgGSQfIA4OmRlgWUD5f/k6DvADGRlgqxniygCfQEJ5bWJZmZkuP2AQA/jYD+gD6QPgoVBIIcFQgE1QUA8hQBPoCWM8WAc8WzMkiyMsBEvQA9ADLAMn5AHB0yMsCygfL/8nQUAjHBfLgShKhA1AkyFAE+gJYzxbMzMntVAH6QDAg1wsBwwCOH4IQ1TJ223CAEMjLBVADzxYi+gISy2rLH8s/yYBC+wCRW+IAMDUVxwXy4En6QDBZyFAE+gJYzxbMzMntVAAuUUPHBfLgSdQwAchQBPoCWM8WzMzJ7VQAfa289qJofQB9IGpqGDYY/BQAuCoQCaoKAeQoAn0BLGeLAOeLZmSRZGWAiXoAegBlgGT8gDg6ZGWBZQPl/+ToQAAfrxb2omh9AH0gamoYP6qQQFEAfwk=\0";
let data = "te6cckECFAEAA3wAAlFwOPUE4QoACAG/b+7lv/B/MjjfQ11sWK3b4LOpS7Bc7BSmJBVmyz5hdQECAEoBaHR0cHM6Ly90YXJhbnRpbmkuZGV2L3N0b24vbW9vbi5qc29uART/APSkE/S88sgLAwIBYgQFAgLMBgcAG6D2BdqJofQB9IH0gahhAgHUCAkCAUgKCwC7CDHAJJfBOAB0NMDAXGwlRNfA/AL4PpA+kAx+gAxcdch+gAx+gAwAtMfghAPin6lUiC6lTE0WfAI4IIQF41FGVIgupYxREQD8AngNYIQWV8HvLqTWfAK4F8EhA/y8IAARPpEMHC68uFNgAgEgDA0CASASEwH1APTP/oA+kAh8AHtRND6APpA+kDUMFE2oVIqxwXy4sEowv/y4sJUNEJwVCATVBQDyFAE+gJYzxYBzxbMySLIywES9AD0AMsAySD5AHB0yMsCygfL/8nQBPpA9AQx+gB3gBjIywVQCM8WcPoCF8trE8yCEBeNRRnIyx8ZgDgP3O1E0PoA+kD6QNQwCNM/+gBRUaAF+kD6QFNbxwVUc21wVCATVBQDyFAE+gJYzxYBzxbMySLIywES9AD0AMsAyfkAcHTIywLKB8v/ydBQDccFHLHy4sMK+gBRqKGCCJiWgIIImJaAErYIoYIImJaAoBihJ+MPJdcLAcMAI4A8QEQCayz9QB/oCIs8WUAbPFiX6AlADzxbJUAXMI5FykXHiUAioE6CCCJiWgKoAggiYloCgoBS88uLFBMmAQPsAECPIUAT6AljPFgHPFszJ7VQAcFJ5oBihghBzYtCcyMsfUjDLP1j6AlAHzxZQB88WyXGAGMjLBSTPFlAG+gIVy2oUzMlx+wAQJBAjAA4QSRA4N18EAHbCALCOIYIQ1TJ223CAEMjLBVAIzxZQBPoCFstqEssfEss/yXL7AJM1bCHiA8hQBPoCWM8WAc8WzMntVADbO1E0PoA+kD6QNQwB9M/+gD6QDBRUaFSSccF8uLBJ8L/8uLCggiYloCqABagFrzy4sOCEHvdl97Iyx8Vyz9QA/oCIs8WAc8WyXGAGMjLBSTPFnD6AstqzMmAQPsAQBPIUAT6AljPFgHPFszJ7VSAAgyAINch7UTQ+gD6QPpA1DAE0x+CEBeNRRlSILqCEHvdl94TuhKx8uLF0z8x+gAwE6BQI8hQBPoCWM8WAc8WzMntVIH++ZZY=\0";
let code_slice = code.as_bytes();
let data_slice = data.as_bytes();
let code_packed = code_slice.as_ptr();
let data_packed = data_slice.as_ptr();
let empty_cell = CString::new("te6cckEBAQEAAgAAAEysuc0=")?;
let address = CString::new(format!("0:{}", "F".repeat(64)))?;
let rand_seed = CString::new("F".repeat(64))?;
let extra_currencies = CString::new("100=20000 200=1")?;
let invalid = CString::new("invalid")?;
unsafe {
assert!(emulator_set_verbosity_level(0));
let emulator =
tvm_emulator_create(code_packed as *const i8, data_packed as *const i8, 2);
assert!(!emulator.is_null());
assert!(tvm_emulator_set_libraries(emulator, empty_cell.as_ptr()));
assert!(tvm_emulator_set_c7(
emulator,
address.as_ptr(),
1_337,
1_000,
rand_seed.as_ptr(),
std::ptr::null(),
));
assert!(tvm_emulator_set_extra_currencies(
emulator,
extra_currencies.as_ptr(),
));
assert!(tvm_emulator_set_prev_blocks_info(
emulator,
std::ptr::null(),
));
assert!(tvm_emulator_set_gas_limit(emulator, 1_000_000));
assert!(tvm_emulator_set_debug_enabled(emulator, 1));
let result = take_emulator_string(tvm_emulator_run_get_method(
emulator,
11111123,
invalid.as_ptr(),
))?;
assert!(result.contains(r#""success":false"#));
let raw_result = tvm_emulator_emulate_run_method(
invalid.as_bytes().len() as u32,
invalid.as_ptr(),
1_000_000,
);
assert!(raw_result.is_null());
let detailed_result = tvm_emulator_emulate_run_method_detailed(
invalid.as_bytes().len() as u32,
invalid.as_ptr(),
1_000_000,
);
assert!(!detailed_result.is_null());
run_method_detailed_result_destroy(detailed_result);
let result = take_emulator_string(tvm_emulator_send_external_message(
emulator,
invalid.as_ptr(),
))?;
assert!(result.contains(r#""success":false"#));
let result = take_emulator_string(tvm_emulator_send_internal_message(
emulator,
invalid.as_ptr(),
1_000,
))?;
assert!(result.contains(r#""success":false"#));
tvm_emulator_destroy(emulator);
let version = take_emulator_string(emulator_version())?;
assert!(version.contains("emulatorLibCommitHash"));
assert!(version.contains("emulatorLibCommitDate"));
string_destroy(std::ptr::null());
}
Ok(())
}
}