Огляд NeuroWASM
NeuroWASM — середовище виконання контрактів NeuroChain: WebAssembly, який виконує інтерпретатор wasmi, з обліком у fuel і host-функціями, що імпортуються з модуля env. Його семантика слідує CosmWasm і NEAR, плюс нативні функції AI host.
Він не сумісний на рівні бінарників з wasmd чи nearcore — ті самі ідеї, інший інтерфейс.
Модель виконання
- Синхронні виклики. Контракт, що викликає інший, виконує його до кінця, перш ніж продовжити (як в EVM).
- Один журнал на транзакцію. Усі записи сховища, зміни балансів і перекази всього дерева викликів фіксуються разом — або, якщо щось перервалося, жоден з них.
- Читання власних записів. Вкладений виклик бачить незафіксовані записи того, хто викликає.
- Ліміт глибини — 8 вкладених викликів (
MAX_CALL_DEPTH). - Детермінованість. Кожен валідатор виконує той самий байткод на тому самому стані й отримує той самий результат; немає годинника, випадковості чи доступу до мережі.
Заплановано пізніше: асинхронні підповідомлення з точкою входу reply, потім обіцянки в стилі NEAR і пакети IBC v2.
Host-функції
Усі імпорти — з env. Вказівники й довжини — зміщення i32 в експортовану контрактом memory.
| Область | Працює | Заплановано |
|---|---|---|
| Пам'ять | allocate, deallocate, abort | — |
| Сховище | get_storage, set_storage | remove_storage, storage_has, storage_usage |
| Контекст | get_caller, get_block_height, get_balance, get_stake, get_stake_at | get_self_addr, get_signer, get_block_time, get_shard_id, get_attached_deposit, gas_remaining |
| Банк і події | transfer, emit_event, set_return | log |
| Міжконтрактні виклики | call_contract | call_contract_with_value |
| Криптографія | — | sha3_256, verify_mldsa65, addr_validate |
| AI host | — | Читання моделей, сертифікатів, Sentinel, списку довіри й абстракції акаунтів |
Точки входу, які експортує контракт, описано в Експортах контракту; ліміти й ціни fuel — у Газ і ліміти.
Мінімальний контракт
Лічильник на no_std Rust. Він читає виклик, зберігає число в сховищі й повертає його.
#![no_std]
#[link(wasm_import_module = "env")]
extern "C" {
fn get_storage(key_ptr: i32, key_len: i32, val_ptr: i32, val_max: i32) -> i32;
fn set_storage(key_ptr: i32, key_len: i32, val_ptr: i32, val_len: i32);
fn set_return(ptr: i32, len: i32);
}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { core::arch::wasm32::unreachable() }
const KEY: &[u8] = b"count";
fn read_count() -> u64 {
let mut buf = [0u8; 20];
let n = unsafe { get_storage(KEY.as_ptr() as i32, KEY.len() as i32, buf.as_mut_ptr() as i32, 20) };
if n <= 0 { return 0; }
core::str::from_utf8(&buf[..n as usize]).ok().and_then(|s| s.parse().ok()).unwrap_or(0)
}
#[no_mangle]
pub extern "C" fn call(input_ptr: i32, input_len: i32) {
let input = unsafe { core::slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
let mut n = read_count();
if input.windows(11).any(|w| w == b"\"increment\"") {
n += 1;
let mut out = [0u8; 20];
let s = fmt_u64(n, &mut out);
unsafe { set_storage(KEY.as_ptr() as i32, KEY.len() as i32, s.as_ptr() as i32, s.len() as i32) };
}
let mut out = [0u8; 20];
let s = fmt_u64(n, &mut out);
unsafe { set_return(s.as_ptr() as i32, s.len() as i32) };
}
fn fmt_u64(mut v: u64, buf: &mut [u8; 20]) -> &[u8] {
let mut i = 20;
loop { i -= 1; buf[i] = b'0' + (v % 10) as u8; v /= 10; if v == 0 { break; } }
&buf[i..]
}Викличте його з {"function":"increment"}, щоб додати одиницю, або з будь-чим іншим, щоб прочитати. Збирайте й розгортайте, як описано в Розгортанні контрактів. Токен NRC-20 у neurochain/contracts/nrc20 — повний, більший приклад.
Проєктний документ цього інтерфейсу — docs/neuro-wasm-spec.md у репозиторії.