//! WASM Virtual Machine for Synor smart contracts. //! //! Synor uses Rust-only smart contracts compiled to WebAssembly. This provides: //! - Memory safety and type safety //! - Predictable gas metering //! - Sandboxed execution //! - Rich standard library //! //! # Architecture //! //! ```text //! ┌─────────────────────────────────────────────────────────────────┐ //! │ SMART CONTRACT VM │ //! ├─────────────────────────────────────────────────────────────────┤ //! │ │ //! │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ //! │ │ WASM │ │ Host │ │ Contract │ │ //! │ │ Engine │ │ Functions │ │ Storage │ │ //! │ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │ //! │ │ │ │ │ //! │ └─────────────────┼──────────────────────┘ │ //! │ │ │ //! │ ┌──────▼───────┐ │ //! │ │ Execution │ │ //! │ │ Context │ │ //! │ └──────────────┘ │ //! │ │ //! └─────────────────────────────────────────────────────────────────┘ //! ``` //! //! # Contract Interface //! //! Contracts must export these functions: //! - `init(params: &[u8]) -> Result<(), Error>` - Initialize contract //! - `call(method: &str, params: &[u8]) -> Result, Error>` - Call method #![allow(dead_code)] pub mod compression; pub mod compute; pub mod context; pub mod engine; pub mod gas; pub mod gas_estimator; pub mod host; pub mod scheduler; pub mod speculation; pub mod storage; pub mod tiered; pub use context::{CallContext, ExecutionContext}; pub use engine::{ContractModule, VmEngine, VmInstance}; pub use gas::{Gas, GasConfig, GasMeter}; pub use gas_estimator::{costs, GasEstimate, GasEstimator}; pub use host::HostFunctions; pub use scheduler::{ AccessSet, ExecutionBatch, LockManager, ParallelExecutor, ParallelScheduler, ScheduledResult, ScheduledTransaction, SchedulerConfig, SchedulerStats, TransactionBuilder, }; pub use storage::{ContractStorage, MemoryStorage, StorageKey, StorageValue}; pub use tiered::{ CompilationTier, CompilerStatistics, TieredCompiler, TieredConfig, TieredModule, }; pub use compression::{ BytecodeCompressor, CompressedBytecode, CompressedContractStore, CompressionConfig, CompressionLevel, CompressionStats, DeltaPatch, }; pub use speculation::{ CachedState, ContractCache, GlobalCacheStats, HotStateCache, PendingExecution, SpeculativeConfig, SpeculativeContext, SpeculativeExecutor, SpeculativeResult, SpeculativeStats, StateSnapshot, StateVersion, }; use synor_types::{Address, Hash256}; /// Maximum contract code size (1 MB). pub const MAX_CONTRACT_SIZE: usize = 1024 * 1024; /// Maximum memory pages (64 KB each, max 16 MB). pub const MAX_MEMORY_PAGES: u32 = 256; /// Maximum call depth. pub const MAX_CALL_DEPTH: u32 = 64; /// Maximum execution time (milliseconds). pub const MAX_EXECUTION_TIME_MS: u64 = 30_000; /// Contract identifier. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct ContractId(pub Hash256); impl ContractId { /// Creates a new contract ID. pub fn new(hash: Hash256) -> Self { ContractId(hash) } /// Creates from bytes. pub fn from_bytes(bytes: [u8; 32]) -> Self { ContractId(Hash256::from_bytes(bytes)) } /// Returns as bytes. pub fn as_bytes(&self) -> &[u8; 32] { self.0.as_bytes() } } impl std::fmt::Display for ContractId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", hex::encode(&self.0.as_bytes()[..8])) } } /// Contract execution result. #[derive(Clone, Debug)] pub struct ExecutionResult { /// Return data. pub return_data: Vec, /// Gas used. pub gas_used: u64, /// Logs emitted. pub logs: Vec, /// Storage changes. pub storage_changes: Vec, /// Internal calls made. pub internal_calls: Vec, } impl ExecutionResult { /// Creates a successful empty result. pub fn success() -> Self { ExecutionResult { return_data: Vec::new(), gas_used: 0, logs: Vec::new(), storage_changes: Vec::new(), internal_calls: Vec::new(), } } /// Creates a result with return data. pub fn with_data(data: Vec) -> Self { ExecutionResult { return_data: data, gas_used: 0, logs: Vec::new(), storage_changes: Vec::new(), internal_calls: Vec::new(), } } } /// Log emitted by a contract. #[derive(Clone, Debug)] pub struct ContractLog { /// Contract that emitted the log. pub contract: ContractId, /// Log topics (indexed). pub topics: Vec, /// Log data. pub data: Vec, } /// Storage change made by a contract. #[derive(Clone, Debug)] pub struct StorageChange { /// Contract storage. pub contract: ContractId, /// Storage key. pub key: StorageKey, /// Old value (None if new). pub old_value: Option, /// New value (None if deleted). pub new_value: Option, } /// Internal contract call. #[derive(Clone, Debug)] pub struct InternalCall { /// Caller contract. pub from: ContractId, /// Callee contract. pub to: ContractId, /// Method called. pub method: String, /// Call value. pub value: u64, /// Gas limit. pub gas_limit: u64, /// Input data. pub input: Vec, /// Success status. pub success: bool, /// Return data. pub return_data: Vec, } /// Contract deployment parameters. #[derive(Clone, Debug)] pub struct DeployParams { /// Contract bytecode (WASM). pub code: Vec, /// Constructor arguments. pub args: Vec, /// Initial value to send. pub value: u64, /// Gas limit. pub gas_limit: u64, /// Deployer address. pub deployer: Address, /// Salt for CREATE2-style addresses. pub salt: Option, } /// Contract call parameters. #[derive(Clone, Debug)] pub struct CallParams { /// Target contract. pub contract: ContractId, /// Method to call. pub method: String, /// Call arguments. pub args: Vec, /// Value to send. pub value: u64, /// Gas limit. pub gas_limit: u64, /// Caller address. pub caller: Address, } /// VM errors. #[derive(Debug, Clone, thiserror::Error)] pub enum VmError { /// Contract not found. #[error("Contract not found: {0}")] ContractNotFound(ContractId), /// Invalid bytecode. #[error("Invalid bytecode: {0}")] InvalidBytecode(String), /// Bytecode too large. #[error("Bytecode too large: {size} > {max}")] BytecodeTooLarge { size: usize, max: usize }, /// Out of gas. #[error("Out of gas: used {used}, limit {limit}")] OutOfGas { used: u64, limit: u64 }, /// Execution error. #[error("Execution error: {0}")] ExecutionError(String), /// Memory access violation. #[error("Memory access violation: {0}")] MemoryViolation(String), /// Stack overflow. #[error("Stack overflow")] StackOverflow, /// Call depth exceeded. #[error("Call depth exceeded: {0} > {}", MAX_CALL_DEPTH)] CallDepthExceeded(u32), /// Execution timeout. #[error("Execution timeout")] Timeout, /// Invalid method. #[error("Invalid method: {0}")] InvalidMethod(String), /// Serialization error. #[error("Serialization error: {0}")] SerializationError(String), /// Storage error. #[error("Storage error: {0}")] StorageError(String), /// Host function error. #[error("Host function error: {0}")] HostError(String), /// Contract panicked. #[error("Contract panicked: {0}")] Panic(String), /// Reverted by contract. #[error("Reverted: {0}")] Revert(String), } #[cfg(test)] mod tests { use super::*; #[test] fn test_contract_id() { let hash = Hash256::from_bytes([0x42; 32]); let id = ContractId::new(hash); assert_eq!(id.as_bytes(), &[0x42; 32]); assert!(!id.to_string().is_empty()); } #[test] fn test_execution_result() { let result = ExecutionResult::success(); assert!(result.return_data.is_empty()); assert_eq!(result.gas_used, 0); let result = ExecutionResult::with_data(vec![1, 2, 3]); assert_eq!(result.return_data, vec![1, 2, 3]); } }