Multi-VM Runtime
The Tenzro Virtual Machine provides a unified execution runtime supporting three distinct virtual machines: Ethereum Virtual Machine (EVM), Solana Virtual Machine (SVM), and Canton DAML. This multi-VM architecture enables cross-ecosystem smart contract deployment, transaction execution, and state management within a single blockchain infrastructure.
Architecture Overview
The multi-VM runtime is built around the MultiVmRuntime orchestrator, which routes transactions to the appropriate executor based on VM type. Each virtual machine maintains its own execution context, gas accounting model, and state management while sharing a unified storage backend through RocksDB.
┌─────────────────────────────────────────┐
│ MultiVmRuntime │
│ Transaction Router & Orchestrator │
└───────────┬─────────────────────────────┘
│
┌───────┼────────┐
│ │ │
┌───▼───┐ ┌─▼──┐ ┌──▼───┐
│ EVM │ │SVM │ │ DAML │
│Executor│ │Exec│ │Exec │
└───┬───┘ └─┬──┘ └──┬───┘
│ │ │
└───────┼───────┘
│
┌───────▼──────┐
│ State Adapter │
│ (RocksDB) │
└───────────────┘
VM Type Routing
Transactions include a vm_type field that determines which executor processes the transaction. The runtime performs zero-copy routing to minimize overhead during execution dispatch.
use tenzro_vm::{MultiVmRuntime, VmType};
use tenzro_types::{Transaction, Address};
// Initialize multi-VM runtime
let runtime = MultiVmRuntime::new(storage.clone());
// Execute EVM transaction
let evm_tx = Transaction {
vm_type: VmType::Evm,
from: sender_address,
to: Some(contract_address),
data: hex::decode("0xa9059cbb...")?,
gas_limit: 100_000,
gas_price: 20_000_000_000, // 20 Gwei
..Default::default()
};
let result = runtime.execute_transaction(&evm_tx).await?;
// Execute SVM transaction
let svm_tx = Transaction {
vm_type: VmType::Svm,
data: borsh::to_vec(&svm_instruction)?,
gas_limit: 200_000, // Compute units
..Default::default()
};
let result = runtime.execute_transaction(&svm_tx).await?;
// Execute DAML transaction
let daml_tx = Transaction {
vm_type: VmType::Daml,
data: serde_json::to_vec(&daml_command)?,
gas_limit: 50_000,
..Default::default()
};
let result = runtime.execute_transaction(&daml_tx).await?;
Block-STM Parallel Execution
Tenzro implements Block-STM (Software Transactional Memory) for optimistic parallel transaction execution. Transactions are executed speculatively across multiple threads with automatic conflict detection and reexecution when conflicts occur.
MVCC Multi-Version Data
The Block-STM engine maintains multi-version concurrency control (MVCC) to track read and write dependencies between transactions. Each transaction operates on a versioned snapshot of state, allowing concurrent execution without blocking.
use tenzro_vm::block_stm::{BlockStmExecutor, BlockStmConfig};
let config = BlockStmConfig {
num_threads: 8,
max_reexecutions: 16,
conflict_threshold: 0.5, // 50% conflict rate triggers sequential fallback
enable_metrics: true,
};
let executor = BlockStmExecutor::new(config, storage.clone());
// Execute block of transactions in parallel
let transactions = vec![tx1, tx2, tx3, tx4, tx5];
let results = executor.execute_block(transactions).await?;
// Access execution metrics
let stats = executor.stats();
println!("Parallel executions: {}", stats.parallel_executions);
println!("Sequential executions: {}", stats.sequential_executions);
println!("Total reexecutions: {}", stats.total_reexecutions);
println!("Conflict rate: {:.2}%", stats.conflict_rate() * 100.0);
Conflict Detection
When a transaction reads state that was written by a lower-indexed transaction that has not yet committed, a conflict is detected. The dependent transaction is automatically reexecuted after its dependencies commit.
Automatic Sequential Fallback: If the conflict rate exceeds 50% after multiple reexecution rounds, the executor automatically falls back to sequential execution for the remainder of the block to avoid excessive overhead.
EIP-1559 Fee Market
Tenzro implements EIP-1559 dynamic fee market mechanics with base fee adjustment, fee burning, and priority fees. The base fee adjusts by ±12.5% per block based on gas usage relative to the 15M gas target.
Base Fee Calculation
use tenzro_vm::fee_market::FeeMarket;
let mut fee_market = FeeMarket::new();
// Current block used 20M gas (above 15M target)
let parent_gas_used = 20_000_000;
let parent_gas_limit = 30_000_000;
let parent_base_fee = 1_000_000_000; // 1 Gwei
let new_base_fee = fee_market.calculate_next_base_fee(
parent_base_fee,
parent_gas_used,
parent_gas_limit,
);
println!("New base fee: {} wei", new_base_fee); // 1.125 Gwei (12.5% increase)
// Fee burning
let base_fee_burned = fee_market.calculate_base_fee_burn(
parent_gas_used,
new_base_fee,
);
println!("TNZO burned: {}", base_fee_burned);
Priority Fee Suggestions
The fee market provides priority fee suggestions based on transaction urgency levels: instant, fast, normal, and economy. Priority fees are paid directly to validators as incentive for inclusion.
use tenzro_vm::fee_market::TransactionUrgency;
// Get priority fee suggestions
let instant_priority = fee_market.suggest_priority_fee(TransactionUrgency::Instant);
let fast_priority = fee_market.suggest_priority_fee(TransactionUrgency::Fast);
let normal_priority = fee_market.suggest_priority_fee(TransactionUrgency::Normal);
let economy_priority = fee_market.suggest_priority_fee(TransactionUrgency::Economy);
println!("Instant (next block): {} Gwei", instant_priority / 1_000_000_000);
println!("Fast (1-2 blocks): {} Gwei", fast_priority / 1_000_000_000);
println!("Normal (3-5 blocks): {} Gwei", normal_priority / 1_000_000_000);
println!("Economy (5+ blocks): {} Gwei", economy_priority / 1_000_000_000);
// Total fee calculation
let max_fee_per_gas = fee_market.current_base_fee() + fast_priority;
let effective_gas_price = std::cmp::min(
max_fee_per_gas,
fee_market.current_base_fee() + max_priority_fee_per_gas,
);
ERC-4337 Account Abstraction
Tenzro supports ERC-4337 account abstraction natively, enabling smart contract wallets, gas sponsorship via paymasters, and custom validation logic. User operations are validated and executed through the EntryPoint contract.
EntryPoint Contract
The EntryPoint contract coordinates user operation validation, execution, and gas payment. It manages nonce validation, signature verification delegation, and paymaster integration.
use tenzro_vm::account_abstraction::{EntryPoint, UserOperation};
let entry_point = EntryPoint::new(entry_point_address);
// Create user operation
let user_op = UserOperation {
sender: smart_account_address,
nonce: 0,
init_code: vec![], // Empty if account exists
call_data: encode_function_call("transfer", &[recipient, amount])?,
call_gas_limit: 100_000,
verification_gas_limit: 50_000,
pre_verification_gas: 21_000,
max_fee_per_gas: 20_000_000_000,
max_priority_fee_per_gas: 2_000_000_000,
paymaster_and_data: vec![], // Empty if user pays
signature: vec![], // Account-specific signature
};
// Validate user operation
let validation_result = entry_point.validate_user_op(&user_op, state)?;
if validation_result.is_valid {
// Execute user operation
let result = entry_point.handle_user_op(user_op, state).await?;
println!("User operation executed: {:?}", result);
}
Smart Account Modules
Smart accounts support pluggable modules for social recovery, session keys, spending limits, and batch transactions. Modules extend account functionality without modifying core validation logic.
use tenzro_vm::account_abstraction::{SmartAccount, AccountModule};
use tenzro_vm::account_abstraction::modules::{
SocialRecoveryModule, SessionKeyModule, SpendingLimitModule
};
// Create smart account with modules
let mut account = SmartAccount::new(owner_address);
// Add social recovery (2-of-3 guardians)
let recovery = SocialRecoveryModule {
threshold: 2,
guardians: vec![guardian1, guardian2, guardian3],
};
account.add_module(AccountModule::SocialRecovery(recovery));
// Add session key for limited operations
let session_key = SessionKeyModule {
public_key: session_pk,
allowed_operations: vec!["transfer", "approve"],
valid_until: timestamp + 86400, // 24 hours
call_gas_limit: 100_000,
};
account.add_module(AccountModule::SessionKey(session_key));
// Add spending limit
let spending_limit = SpendingLimitModule {
daily_limit: parse_ether("100")?, // 100 TNZO/day
reset_timestamp: next_midnight,
spent_today: 0,
};
account.add_module(AccountModule::SpendingLimit(spending_limit));
// Validate operation against all modules
let is_valid = account.validate_operation(&user_op)?;
Paymaster Gas Sponsorship
Paymasters enable third-party gas sponsorship, allowing applications to subsidize transaction fees for users. Paymasters validate operations and commit to paying gas costs before execution.
use tenzro_vm::account_abstraction::{Paymaster, PaymasterValidationResult};
let paymaster = Paymaster::new(paymaster_address);
// Paymaster validates user operation
let context = paymaster.validate_user_op(&user_op, state)?;
match context {
PaymasterValidationResult::Valid { context_data, valid_until } => {
// Paymaster agrees to sponsor
println!("Gas sponsored until: {}", valid_until);
// Execute operation
let result = entry_point.handle_user_op(user_op, state).await?;
// Paymaster is charged for gas
paymaster.post_operation(result.gas_used, context_data, state)?;
}
PaymasterValidationResult::Invalid(reason) => {
println!("Paymaster rejected: {}", reason);
}
}
Precompile Registry
Tenzro extends the EVM with custom precompiled contracts for TEE attestation, ZK proof verification, model inference, and settlement operations. Precompiles are callable at reserved addresses starting from 0x0000...0100.
| Address | Precompile | Gas Cost |
|---|
0x0100 | TEE Attestation Verify | 50,000 |
0x0101 | ZK Proof Verify | 100,000 |
0x0102 | Model Inference Request | 200,000 |
0x0103 | Settlement Execute | 75,000 |
Gas Oracle
The gas oracle provides real-time gas price estimation and transaction cost calculation. It tracks historical base fees and priority fees to provide accurate predictions for different confirmation speeds.
use tenzro_vm::gas_oracle::GasOracle;
let oracle = GasOracle::new();
// Estimate gas for transaction
let estimated_gas = oracle.estimate_gas(&transaction)?;
println!("Estimated gas: {}", estimated_gas);
// Get current gas prices
let prices = oracle.gas_prices();
println!("Base fee: {} Gwei", prices.base_fee / 1_000_000_000);
println!("Slow priority: {} Gwei", prices.slow_priority / 1_000_000_000);
println!("Normal priority: {} Gwei", prices.normal_priority / 1_000_000_000);
println!("Fast priority: {} Gwei", prices.fast_priority / 1_000_000_000);
// Calculate total transaction cost
let total_cost = oracle.estimate_transaction_cost(
&transaction,
TransactionUrgency::Fast,
)?;
println!("Total cost: {} TNZO", format_ether(total_cost));
State Adapter
The state adapter provides a unified interface for all VMs to interact with persistent storage. It tracks dirty state changes during transaction execution and commits them atomically upon successful completion.
Production Note: The current state adapter maintains changes in memory only. The commit() method clears dirty flags but does not persist to RocksDB.
Gas Constants
| Constant | Value | Description |
|---|
| MAX_GAS_LIMIT | 30,000,000 | Maximum gas per transaction |
| DEFAULT_GAS_LIMIT | 10,000,000 | Default gas if not specified |
| MIN_GAS_PRICE | 1 Gwei | Minimum gas price accepted |
| TARGET_GAS_USED | 15,000,000 | EIP-1559 target per block |
| MIN_BASE_FEE | 0.1 Gwei | Minimum base fee floor |
| MAX_BASE_FEE | 1000 Gwei | Maximum base fee ceiling |
| MAX_CALL_DEPTH | 1,024 | Maximum call stack depth |
| MAX_CONTRACT_SIZE | 24,576 bytes | Maximum contract bytecode size |
| BLOCK_STM_MAX_REEXEC | 16 | Max reexecution attempts |
| CONFLICT_THRESHOLD | 50% | Sequential fallback trigger |
| AA_MAX_BUNDLE_SIZE | 100 | Max user ops per bundle |
Configuration
use tenzro_vm::{VmConfig, EvmConfig, SvmConfig, DamlConfig};
// Configure multi-VM runtime
let config = VmConfig {
default_gas_limit: 10_000_000,
max_gas_limit: 30_000_000,
default_chain_id: 1337,
evm_config: Some(EvmConfig {
evm_version: revm::EvmVersion::London,
enable_precompiles: true,
max_code_size: 24576,
}),
svm_config: Some(SvmConfig {
compute_budget: 1_400_000,
enable_syscalls: true,
max_account_data_size: 10_485_760, // 10 MB
}),
daml_config: Some(DamlConfig {
canton_endpoint: "http://localhost:5011".to_string(),
max_command_size: 1_048_576, // 1 MB
timeout_seconds: 30,
}),
};
let runtime = MultiVmRuntime::with_config(config, storage)?;
Production Readiness
Production-Ready Components:
- EVM executor with full revm integration
- SVM executor with solana_rbpf BPF execution
- DAML executor with real Canton gRPC client
- Block-STM parallel execution with MVCC
- EIP-1559 fee market with base fee adjustment
- ERC-4337 account abstraction (EntryPoint, modules, paymasters)
- Gas metering with overflow checks
Outstanding Issues:
- State adapter does not persist to storage
- Most EVM precompiles return empty results
- Tenzro-specific precompiles are stubs
- No transaction signature verification
- No gas refunds for SSTORE clearing
- No nonce validation or replay protection