Розробка кастомної віртуальної машини блокчейну

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка кастомної віртуальної машини блокчейну
Складний
від 2 тижнів до 3 місяців
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1309
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1222
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    922
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1151
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    614
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    887

Розробка кастомної віртуальної машини блокчейну

EVM — це не єдина можлива архітектура. Вона була спроектована у 2014 році для конкретних компромісів того часу: 256-бітна стекова машина з дорогим storage, без паралелізму, з синхронним виконанням. За десять років з'явилися задачи, для яких EVM — субоптимальний вибір: ігрові рушії з тисячами станів, ZK-friendly обчислення, спеціалізовані фінансові примітиви. Кастомна VM — це не переизобретення колеса, а інженерне рішення для конкретного performance/expressivity вимірювання.

Зачем створювати VM з нуля

Перед тим як проектувати кастомну VM, потрібно чесно відповісти: не розв'язується ви задача через існуючі варіанти?

Коли існуючого достатньо:

  • EVM + Solidity + Foundry закривають 95% DeFi задач
  • Solana SBF (sBPF) — високопродуктивний DeFi, gaming
  • CosmWasm — кастомна L1 з Cosmos SDK без написання VM
  • Move (Aptos/Sui) — resource-oriented programming для asset safety

Коли потрібна кастомна VM:

  • ZK-proof generation: існуючі VM (EVM, WASM) не оптимізовані під арифметику кінцевих полів. ZK-friendly VM будується навколо Plonky2, Halo2 або STARK-сумісних операцій.
  • Domain-specific language потрібен на рівні виконання: наприклад, chess engine VM, де кожен opcode — операція з шахматною позицією, а state transitions верифікуються on-chain.
  • Паралельне виконання: EVM послідовний. Solana Sealevel виконує транзакції паралельно, знаючи заранее які account'ы вони затрагують. Аналогічна архітектура для EVM-несумісної L1.
  • Minified execution environment: бортові системи, IoT — мінімальний bytecode інтерпретатор для вбудовуваних пристроїв з верифікацією on-chain.

Архітектурні рішення при проектуванні VM

Тип VM: стекова vs реєстрова

Stack-based VM (EVM, WASM, JVM): операнди беруться зі стека, результат кладеться на стек. Простіший компілятор, компактний bytecode, але складна оптимізація — немає явних реєстрів.

Register-based VM (Lua VM, Dalvik, SBF): операнди — іменовані реєстри. Швидше при інтерпретації (менше push/pop операцій), простіша JIT-компіляція, bytecode трохи об'ємніше.

Для блокчейну зазвичай вибирають стекову VM: вона простіша формально верифікувати (важливо для аудиту), bytecode компактніше (менше calldata), і більшість компіляторів для неї добре вивчені.

Arithmetic: 256-bit vs field arithmetic

EVM використовує 256-bit integers — зручно для Ethereum адрес та хешів, але розточильно для ZK-proof систем. ZK-friendly VM будується навколо arithmetic у prime field F_p, де p — prime modulus конкретної proof system:

  • Plonky2: F_{2^64 - 2^32 + 1} (Goldilocks field)
  • Groth16 / Plonk на BN254: p ≈ 2^254
  • STARKs: F_{2^{64}-2^{32}+1} або F_{2^{31}-1}

Операції в цих полях нативно дешевше для proof generation. Якщо кінцева ціль — верифікувати виконання VM через ZK proof, arithmetic field повинен совпадати з proof system.

Instruction Set Architecture (ISA)

Проектуючи ISA, потрібно мінімізувати кількість opcodes, зберігаючи Turing-completeness. Мінімальний жизнеспособний набір:

Arithmetic:   ADD, SUB, MUL, DIV, MOD
Bitwise:      AND, OR, XOR, NOT, SHL, SHR
Comparison:   EQ, LT, GT
Memory:       LOAD, STORE (або PUSH/POP для stack-based)
Control flow: JUMP, JUMPI, HALT
Stack ops:    PUSH_N, POP, DUP, SWAP
Crypto:       HASH (keccak256 або poseidon для ZK)

Спеціалізовані opcodes для domain: наприклад, для фінансової VM — MULPERCENT (множення з процентами без overflow), SQRT (для AMM формул). Кожен новий opcode — додаткова складність у реалізації інтерпретатора, JIT-компілятора та формальної верифікації.

Реалізація інтерпретатора

Dispatch loop

Основа будь-якої VM — dispatch loop. Три підходи за продуктивністю:

Switch-case (найпростіший):

loop {
    let opcode = bytecode[pc];
    pc += 1;
    match opcode {
        0x01 => { // ADD
            let a = stack.pop()?;
            let b = stack.pop()?;
            stack.push(a.wrapping_add(b));
        }
        0x60 => { // PUSH1
            let val = bytecode[pc];
            pc += 1;
            stack.push(val as u64);
        }
        0x00 => break, // HALT
        _ => return Err(InvalidOpcode(opcode)),
    }
}

Computed goto / threaded dispatch (C/C++, GCC extension): замість switch кожен opcode handler закінчується jump до наступного handler'а напрямки. ~20-30% швидше switch у гарячому циклі.

JIT-компіляція: компіляція bytecode в native machine code перед виконанням. Cranelift (Rust, використовується в Wasmtime) або LLVM backend. Дає 5–10x прискорення для compute-intensive контрактів. Додає значну складність: потрібен JIT-компілятор, security sandbox для generated code.

Для блокчейн VM JIT використовується рідко — execution environment повинен бути детерменіванним та sandboxed. WebAssembly (Wasmtime/Wasmer) береб це готовим рішенням.

Memory model

EVM має три типи пам'яті: stack (1024 елементів), memory (лінійна, растет по запиту, оплачується), storage (persistent, дорого). Кастомна VM може спростити це до двох:

Execution memory — локальна память функції, не персистентна. Flat array з bounds checking:

struct Memory {
    data: Vec<u8>,
    gas_used: u64,
}
impl Memory {
    fn load(&mut self, offset: u32, size: u32) -> Result<&[u8]> {
        self.expand_to(offset + size)?;
        Ok(&self.data[offset as usize..(offset + size) as usize])
    }
    fn expand_to(&mut self, size: u32) -> Result<()> {
        if size as usize > self.data.len() {
            let gas = memory_expansion_cost(self.data.len(), size as usize);
            self.gas_used += gas;
            self.data.resize(size as usize, 0);
        }
        Ok(())
    }
}

State storage — persistent key-value. За блокчейном — зазвичай Merkle Patricia Trie (Ethereum) або Jellyfish Merkle Tree (Aptos/Diem) для state commitment. Реалізація поверх RocksDB або LevelDB.

Gas metering та determinism

Детерменізм — обов'язкова вимога для блокчейн VM. Одинаковий bytecode + state + input повинні давати одинаковий результат на будь-якому вузлі. Це значить:

  • Ніякого floating point arithmetic (IEEE 754 може давати різні результати)
  • Детерменіваний порядок обходу hash map (у Rust використовуйте BTreeMap, не HashMap)
  • Версіоновані opcodes: нові opcodes вводяться лише через hard fork
  • Bounds для всіх операцій: максимальний stack size, максимальна memory, максимальний gas

Gas metering — механізм запобігання DoS через нескінченні цикли. Кожен opcode має фіксовану gas стоимість. Перед виконанням перевіряємо та списуємо:

fn execute_opcode(&mut self, opcode: u8) -> Result<()> {
    let cost = GAS_TABLE[opcode as usize];
    self.gas_remaining = self.gas_remaining
        .checked_sub(cost)
        .ok_or(OutOfGas)?;
    // ... execute opcode
}

Gas table для кастомної VM проектується на основі benchmarking реальних opcode execution times. Дорогі операції (HASH, STORE) коштують пропорційно більше.

ZK-сумісна VM: специфіка

Якщо ціль — доводити виконання VM через ZK proof (zkEVM або кастомний zkVM), архітектура значно ускладнюється.

Execution trace: потрібно генерувати trace виконання програми — таблиця всіх state transitions для кожного кроку. Proof system верифікує, що trace коректен відносно ISA.

Step | PC | Opcode | Stack[0] | Stack[1] | Memory | ...
-----|-----|--------|----------|----------|--------|----
0    | 0   | PUSH 5 | —        | —        | []     | ...
1    | 2   | PUSH 3 | 5        | —        | []     | ...
2    | 4   | ADD    | 5        | 3        | []     | ...
3    | 5   | HALT   | 8        | —        | []     | ...

Constraint system: для кожного opcode пишуться поліноміальні constraints, які доводять коректність переходу. Наприклад, для ADD: stack_next[0] = stack[0] + stack[1]. Все це — algebraic circuit для proof system.

Reference проекти: RISC Zero (zkVM на RISC-V ISA), Valida (спеціально для ZK-proof friendly ISA), Polygon Miden (STARK-based zkVM). Вивчення їх открытых вихідних кодів — обов'язковий крок перед проектуванням власного zkVM.

Етапи розробки

Фаза Вміст Тривалість
ISA design Специфікація opcodes, gas table, memory model 2–4 тиж
Interpreter Базовий інтерпретатор, тести на коректність 4–6 тиж
Gas metering & limits Повна реалізація gas системи, DoS захист 2–3 тиж
State storage Merkle tree, persistence, state root 3–5 тиж
Compiler/toolchain Компілятор з high-level мови в bytecode 4–8 тиж
Integration Інтеграція у consensus layer блокчейну 3–6 тиж
ZK circuit (опціонально) Constraint system, proof generation 8–16 тиж
Formal verification Математична верифікація ключових властивостей 4–8 тиж

Розробка production-ready кастомної VM — це 12–24 місяці роботи для команди з 3–5 інженерів. Більшість проектів, які заявляють про "кастомну VM за квартал", реалізують тонку обгортку над WASM або EVM, а не підлинно кастомну архітектуру.