# 什麼是VM?以及SolanaVM、EthereumVM、WASM(WebAssembly)、PVM等的差異 先介紹VM,再說明為何需要VM,VM的五大核心組成,這四個東西在這五大組成上有何差異造成他們的優缺點。 ## 一、VM(Virtual Machine) > [] **1.1** VM 像一個「沙盒」,**是一種安全機制,提供一個隔離的執行環境,用於測試不受信任的程式碼或進行實驗,而不會影響主機系統**。 這種隔離環境通常會限制程式對系統資源的訪問,例如檔案、網路和記憶體。  在區塊鏈世界中,VM 是一種**模擬電腦運算邏輯的軟體**,它不需要靠實體電腦就能執行程式碼,是**智能合約的運作引擎,**負責「理解、模擬、執行」你寫的合約。讓開發者寫好的程式碼可以安全、獨立地在區塊鏈上執行。 - 理解:讀懂你寫的程式邏輯(例如:轉帳給誰、怎麼判斷條件) - 模擬:模擬記憶體、運算、帳戶資料變化等過程 - 執行:按照規則一步步執行結果,保證公平性與安全性 - 隔離:不會影響其他區塊或真實電腦,不會出錯就炸掉全鏈 ### 1.2 🍎用 Apple 筆電裝 Parallels 跑 Windows 的比喻來說明 VM: 你有一台 Mac 筆電,預設不能跑 Windows 軟體。你只好裝一個叫 Parallels 的軟體,它會模擬出一個「虛擬 Windows 環境」,讓你可以在 Mac 上執行原本只能跑在 Windows 的程式。 區塊鏈就像一個作業系統,它自己不直接跑你的程式(合約),但它提供一個「模擬空間」來跑這些東西。那個模擬空間,就是 VM。 ## 二、 VM提供類似防火牆的預防性保護 ### 2.1 為什麼區塊鏈上不能直接執行程式,而需要 VM? 區塊鏈上的程式(也就是智能合約)要具備這些特性: 1. **所有節點都要跑出一模一樣的結果** 2. **不能有人用奇怪的寫法跑贏別人** 3. **不能跑太久耗盡資源** 4. **要能確保安全、不影響主系統** 這些特性,如果讓你「自由寫程式」就太危險了。 ### 2.2 如果沒有 VM 的限制與控制,任何人都可以寫出惡意合約😈: 1. **資源掠奪型合約** 故意寫成每次執行都消耗大量運算資源(Gas),讓別人區塊塞車、自己通暢 → 你佔滿鏈上資源、別人的轉帳卡死、鏈整體變慢甚至癱瘓 真實事件:Spamming / Gas War 攻擊;以太坊 NFT Mint 戰爭(如 Otherside 土地發售, 2022) 2. **偽裝轉帳程式** 把 UI 做得跟普通轉帳合約一樣,但其實偷偷把錢轉到你帳戶 → 使用者誤觸、財產被轉走,無法追回(因為區塊鏈不可逆) 真實事件:Approval 欺騙攻擊;Fake USDT Approve Scam(持續存在) 3. **無限迴圈陷阱** 在合約中寫死一段 while(true){} 無限執行的邏輯 → 礦工/節點處理這筆交易時卡住,浪費資源、整體效率下降 真實事件:DoS via Gas 燒盡;King of the Ether Throne(2016) 4. **時間炸彈或條件惡意觸發** 看似正常的合約,但一旦某條件成立就發動惡意操作(例如竊走所有 token) → 藏在 NFT 或 Defi 裡的漏洞造成重大損失 真實事件:Reentrancy 攻擊(重入漏洞);The DAO Hack(2016)損失約 6000 萬美元 VM 像是一道「防火牆」,防止你的程式碼直接操控主系統。 它透過以下方式**限制每個合約的權限與資源**: | 安全設計 | 用意 | | --- | --- | | **Gas 機制** | 每行運算都要花費資源,防止無限迴圈與濫用 | | **記憶體限制** | 不讓你佔據整個鏈上的記憶體 | | **沙盒模型** | 合約不能存取主機資料或鏈下世界的敏感內容 | | **指令集限制** | VM 只允許特定操作,不能呼叫未授權功能 | | **交易模擬驗證** | 節點會先模擬跑一次,確保結果可預期才會上鏈 | 所以我們需要一個受控的「執行環境」:所有人寫的程式,都必須先進到這個 VM 裡面,才能在區塊鏈上執行。而這個盒子裡的規則、語言、速度、安全性,就是各種 VM 的差異之處。 ## 三、VM 是由哪些核心組件構成的?SolanaVM、EVM、WASM、PVM在這些核心組件上的差異 既然VM是用來模擬電腦、執行區塊鏈上的智能合約,那麼它必然也需要具備像電腦一樣的「內部結構」,才能處理計算、儲存資料、回傳結果。我們可以把一個 VM 拆解為幾個核心模組,每一個都負責一個關鍵功能,而這些模組的設計方式,就是不同區塊鏈平台的 VM 差異所在。 以下是虛擬機的五大核心組成:**指令集(Instruction Set)、執行引擎(Execution Engine)、記憶體模型(Memory Model)、語言前端(Language Frontend / Compiler)、系統介面(System Interface / ABI)。**這些模組的技術選擇、組合方式不同,才會形成 EVM、WASM VM、Solana VM、PVM 等不同 VM 的優缺點與發展方向。 **3.1. 指令集(Instruction Set)** 這是 VM 的「語言字典」,**定義了VM可以理解和執行的所有動作**。 當你寫了一段智能合約,虛擬機不會直接看得懂你寫的高階語言(像 Solidity 或 Rust),它需要有一套自己的「基本動作字典」,也就是所謂的**指令集(Instruction Set)**。 指令集可以想像成是一種簡化版的語言,每一個指令就代表一個明確的動作。當你的程式被編譯之後,它就會變成一長串這種低階指令,交由虛擬機逐條執行。 指令集愈簡單、愈有限,執行過程愈可控、安全;但愈複雜、愈強大,就愈能表現高效能與靈活性。 **3.1.1 Ethereum 的虛擬機(EVM)**,它使用的指令叫做 *opcode*,像是 `ADD` 表示加法、`MUL` 表示乘法、`SSTORE` 表示把資料寫入區塊鏈上可永久保存的儲存區。這些指令設計得很簡單、單一,原因是要讓每個節點都能很確定地執行出一模一樣的結果,確保整個系統的一致性與安全性。 **3.1.2** **WebAssembly(簡稱 WASM)**是一種設計更現代的指令集,它原本是給瀏覽器用來執行高效能應用的。WASM 的指令比較接近現實中 CPU 使用的機器語言(RISC-like),例如 `i32.add` 就是把兩個 32 位元的整數相加,`local.get` 是從函式內的區域變數中讀取值,`call_indirect` 則是一種間接呼叫函式的方法,類似在程式中使用函數指標。這種設計雖然比 EVM 複雜,但能提供更強大的彈性與效能,讓不同語言都能編譯成共用的格式。 **3.1.3** **Solana** 採用的指令集則是基於一種叫做 **BPF(Berkeley Packet Filter)**的架構。這原本是 Linux 系統用來過濾網路包裹的機制,Solana 將它改造成高效能、低延遲的智能合約執行架構。Solana 的合約通常是用 Rust 或 C 語言撰寫,再編譯成 BPF bytecode,也就是一種針對 VM 優化過的機器碼格式。bytecode = 程式被編譯過後的一種「中間格式」,不是給人看的,而是給「VM」直接讀來執行的。BPF 指令比較貼近系統底層,能直接操控記憶體、資源與系統呼叫,這也是 Solana 在效能上大幅超越其他鏈的原因之一。 - **BPF(Berkeley Packet Filter)** Solana 的虛擬機採用的是一種叫做 **BPF(Berkeley Packet Filter)** 的技術架構,它原本是作業系統裡用來「過濾網路包裹(Packet)」的工具。所謂「Packet」,你可以把它想成網路世界的郵件小包裹。每個包裹裡裝著一點資料、以及標明「寄件人是誰、要寄去哪裡、排第幾順序」等等。電腦收到這些包裹之後,要判斷:「這是我想收的嗎?還是垃圾?還是攻擊?」。為了讓電腦能快速做出這個判斷,Linux 系統發明了 BPF。它是一種超迷你、超快速的虛擬機,可以用來執行一些小小的程式來分析每一個包裹內容,再決定「收」還是「丟」。 Solana 發現這套架構可以拿來區塊鏈應用。因為 BPF 原本就是為了「快速處理大量資料」「不能亂碰主系統」「要先通過安全檢查」這些目的設計的,而這些恰好也正是區塊鏈執行智能合約最需要的條件。所以他們就把 BPF 拿來改造成自己的虛擬機系統。 開發者在 Solana 上寫智能合約時,通常會用 Rust 或 C 語言來寫,然後編譯成 **BPF bytecode**。這個 bytecode 不是給人看的,而是給虛擬機看的「機器格式的指令」。這些指令是針對虛擬機設計、優化過的,能被快速、安全地執行,它是一種「對虛擬機優化過的機器碼格式」。 BPF 指令比較貼近系統底層,能直接操控記憶體、資源與系統呼叫。它在執行前都要先通過一個「驗證器」(verifier)的檢查,它會靜態分析整段程式碼,確保你不會無限迴圈、不會亂存記憶體、不會做越權的事,只有檢查通過的程式才會允許執行。因此,雖然它可以用來操控「合約所擁有的資源」,但一切都在規則之內。這也正是 Solana 能達到超高效能的原因之一:它用一個原本設計給系統底層的快速安全模組,來跑區塊鏈上的智能合約,又同時保有安全性。這與 Ethereum 那種「慢但穩」的 EVM 設計完全不同。 **3.1.4 Jam Protocol 設計的 PVM(Parallel Virtual Machine)**,它目前雖還在開發階段,但指令集預期會圍繞著「物件導向 (object-based)」來設計。未來每一個鏈上的資料物件不只是被動存資料,而是能像小型程式一樣主動運作,這需要一套完全不同於傳統「帳戶式 VM」的指令集邏輯。Jam 想做的,是讓區塊鏈變成一個**活的分散式物件系統**,不再只是被動存資料與執行交易,而是讓每個資料「自己會運作」,實現真正的自動化 Web3 世界。 - **帳戶式(account-based)VM**:鏈上有很多「帳戶(account)」,有些是人(EOA: externally owned account),有些是合約(contract account)。每個帳戶可以存資料、接收資產、發交易。資料儲存在帳戶之中,只有當你「發送一筆交易」時,才會觸發某個帳戶中的程式碼被執行。也就是說,這是**事件驅動的**。帳戶本身是不會主動動起來的,它只是被動地等待某人來喚醒它。 - 例如,你部署了一個 NFT 合約,它就安靜地躺在鏈上。只有當有人對它發出「mint」或「transfer」的交易時,它才會被喚醒,跑一下「有人要鑄幣」或「有人要轉移」的流程。平常,它就是一段冷冰冰的程式碼,加上一點靜態資料。 - 這個模式設計簡單、安全,也很好驗證,但缺點是每件事都必須「人為主動發指令」才能動,整個鏈的互動節奏是斷裂的、單向的、無法靈活聯動的。資料本身只能等你來查它、用它。這就是 Ethereum VM、Solana VM 的基本模式。 - **物件導向(object-based) VM** :在物件導向虛擬機中,區塊鏈不再是一堆被動帳戶的集合,而是一個由「活的物件」構成的生態系。每一個物件不只是存資料的容器,它還內建了自己的行為邏輯,能夠主動回應事件、與其他物件互動,甚至自行決定下一步要做什麼。 - 這些物件有點像程式設計語言中的「類別(class)」或「實例(instance)」:它們有自己的狀態、自己的方法,也可能繼承其他物件的能力,或與其他物件組成模組。 - 舉例來說,當有人發起一個投票,這不是單純寫入某個合約帳戶而已,而是整個 DAO 投票物件被激活,它可能會通知所有成員物件,請他們主動表態;而一個 NFT 物件可能會設定條件:「只有在週年紀念日當天,才可以轉移」,而不是等人來查詢這個條件再決定要不要轉。在這個模型中,每個物件就是一個有自身邏輯的小單位。 - 它們能夠被喚醒,也能主動喚醒彼此。鏈上狀態就像是一個即時互動的物件網路,而不是一堆等待查詢的靜態資料。這種設計更接近現實世界與 Web2 應用的邏輯:資料不再只是記錄,而是具有邏輯與行為的主體。這讓去中心化應用更自動化,也更容易組合出複雜的互動模式。 **3.2. 執行引擎(Execution Engine)** VM本身就像是一台模擬電腦,但裡面真正「把每一條指令跑起來」的部分,就是所謂的**執行引擎(Execution Engine)**。你可以把它想成是整台虛擬機的大腦或處理器,它負責讀取你寫好的程式碼,然後一行行地照順序執行出你想要的邏輯結果。 打個比方,前面介紹過的「指令集」就像是一本指令說明書,列出 VM 能理解的動作(例如:加法、儲存、跳轉、呼叫其他程式)。但這本說明書自己不會動,要有人去照著這本說明書「一步步地做事」,這個「做事的人」就是執行引擎。執行引擎的架構會直接影響到鏈上交易速度、吞吐量、能否支援並行計算。 當你寫好一段 Solidity 或 Rust 程式碼,編譯器會先把它轉成 bytecode,交給 VM 執行。 VM 的執行引擎會: 1. 逐行讀取這些 bytecode 2. 根據指令內容,執行對應動作(例如:把變數加總,存進記憶體) 3. 控制流程分支(像 if/else、迴圈等) 4. 執行完畢後,回傳執行結果或變更鏈上狀態 每一行都要執行、不能跳步,也不能隨便改行為,因為區塊鏈最重要的是**每一個節點執行結果都必須完全一樣**。 **3.2.1 EVM 使用一種叫做 直譯器(interpreter) 的執行方式** 意思是**它每次執行一條指令時,都是「即時解讀」那條指令,然後馬上執行。**你可以把它想成:一本英文小說,你不會整本翻譯完才開始唸,而是看到一句,就翻譯一句、唸一句。這樣做的好處是安全、結果容易追蹤;缺點是效率低,每次都要重複解釋,速度會慢。 **3.2.2 WASM:支援 即時編譯(JIT: Just-In-Time compilation)的「提前優化」模式** WASM VM 的執行引擎更靈活,它可以支援**即時編譯**,意思是它可以在程式第一次執行時,把整段 bytecode「翻成原生機器碼」,下次執行時就不用再解釋一次,直接跑。比喻:一本小說先整本翻好,之後閱讀起來超順。這讓 WASM 在一些應用上比 EVM 快得多,尤其適合複雜邏輯與長期執行的合約。 **3.2.3 Solana 的執行引擎是一個高度優化的 BPF 執行架構** 它的最大特點是:**能同時跑很多個合約邏輯,只要它們不搶同一份帳戶資料**。它不是一個人在唸書,而是一群人分頭唸不同的章節。如果你有十筆交易,而它們剛好不互相干擾,Solana 就能一次處理完全部,速度大幅提升。這種模式稱為「**可並行執行引擎(parallel execution engine)**」,這是傳統 EVM 完全做不到的事。 **3.2.4 Jam 的 PVM:每個物件都有自己的「小引擎」** Jam Protocol 所設計的 PVM 還在發展中,但它的目標更激進:未來每一個物件(例如:NFT、token、DAO 成員)都可以擁有自己的執行邏輯,彼此獨立卻又可以互動。這種設計需要一種全新的執行引擎邏輯,支援**高度模組化、即時喚醒、跨物件互動**,是目前最接近「自動化分散運算系統」的虛擬機設計之一。 PVM 的執行引擎採用非同步、事件驅動的模型。當某個物件透過系統介面送出訊息後,這個訊息不會馬上觸發對方物件的執行,而是會被送入**排程佇列(queue)**,由執行引擎依照交易順序與DAG 進行處理。 你可以想像:EVM 就像函數一層套一層執行(A 呼叫 B,B 呼叫 C);PVM 則像是每個物件接到訊息後自己決定什麼時候回應,有點像 email 而不是電話。 這樣的架構有幾個效果: - 不會出現同步呼叫鏈,減少「重入攻擊」風險 - PVM 不允許 A 物件直接呼叫 B 的方法,而是**只能發送訊息給 B**,B 會**稍後才處理這個訊息**。這表示:A 執行中時,B 不會「立刻」被叫來執行,沒有「call → call → call」的鏈狀呼叫路徑。而傳統 VM(像 EVM)裡的重入攻擊,是因為合約 A 呼叫合約 B,而 B 又在執行中立刻 call 回 A,導致 A 的邏輯還沒完成就又被打斷再進一次。 - 每個物件可以獨立失敗、不影響他人(錯誤隔離) - 每個物件的執行單元都是獨立的,而且是由執行引擎「一個個處理訊息」。如果 A 執行了訊息處理失敗(邏輯錯誤、資源不夠等),系統可以只回報 A 的錯誤,不影響正在排隊的 B、C。不像 EVM,如果你一個交易裡 call 了三個合約,只要其中一個錯,**整個交易會 rollback(全部退回)**。但在 PVM 裡,錯的是誰就讓誰失敗,**錯誤是區域性的,不是全局性的**。這種錯誤隔離設計,在複雜應用中非常重要,尤其是多人、多元合約組合的時候。 - 實現並行處理(平行 VM 執行) - 因為訊息互動是非同步的,**物件之間沒有直接依賴與共享狀態**,系統就可以把彼此無關的物件分配到不同的 GPU 核心同時執行。所以執行引擎只要根據「這些訊息彼此無衝突」,就可以放心丟給多個執行緒去平行處理,這正是 Jam 目標的 **大規模可擴展性與低延遲併發能力** 的核心。 **3.3 記憶體模型(Memory Model)** 在VM裡,當我們執行一段智能合約時,會需要「暫時存一些資料」,比如中間變數、使用者輸入、計算結果,甚至某些資料要保存到下一次使用。VM 需要自己的「虛擬記憶體」來儲存變數、暫存運算結果或資料狀態。那這些資料要存在哪裡?怎麼存?怎麼取出來?這就要靠虛擬機的「記憶體模型」來決定。記憶體模型的選擇會影響 VM 的靈活性、速度與合約設計方式,也決定是否能實現並行執行。 **3.3.1 Ethereum EVM:三層記憶體模型** - **暫存記憶體(memory):**執行時才會用,用完就會消失;類似你做數學運算時用的草稿紙。 - 每次交易期間開放的一塊空白記憶體,線性排列(byte-addressable) - 可以動態擴展、存放資料、參數、暫存結果等 - 合約執行完後會被清除 - **堆疊(stack):**最快但容量最小,只能存少量資料;像你手上的便利貼,一次只能紀錄兩三個項目。 - **最多只能放 1024 個元素** - 每一條指令都從這裡「取數字 → 運算 → 再放回來」 - 例如:`ADD` 會從堆疊頂端取兩個值,加總後再放回堆疊 - 沒有變數名稱,全部靠堆疊順序定位 - **儲存區(storage):**寫進去的資料會永久保留在鏈上;像保險櫃或帳本,改動都會被記錄、付費。 - 永久存在於區塊鏈上,只能用 `SLOAD` 與 `SSTORE` 操作 - 每筆修改都會耗費高額 Gas - 常用來記帳戶狀態、token 數量、mapping、結構資料等 整體運作範例: 1. 函數接收到參數(從 calldata) 2. 用指令把參數推到 stack 3. 從 stack 取值運算 → 暫存到 memory 4. 最後結果寫入 storage,或打包返回 EVM 採用的是「堆疊導向模型」(stack-based VM),搭配動態記憶體與鏈上 storage,形成三層分工明確的資料空間設計。這種設計非常簡潔、容易驗證,但也很受限:你無法像普通電腦一樣隨便從某個記憶體位址抓資料,也不支援複雜資料結構。儲存資料到區塊鏈(storage)會非常貴,因為區塊鏈要永久記住這些改動、也要讓全世界的節點都同步。這就是為什麼 EVM 記憶體模型偏保守、安全、但效率沒那麼高。 **3.3.2 WASM:線性記憶體,接近真實電腦** WASM 採用的是「線性記憶體模型」,就像一個超長的陣列(array),你可以把資料放在記憶體的第 0 位、第 100 位……你自己控制。 這種模型比堆疊更靈活,可以直接操作記憶體位置、儲存複雜資料(結構體、陣列、字串)、支援更多編譯器優化與高階語言功能。 也因為它更接近現代電腦的記憶體操作方式,所以更容易寫出效能高的合約,尤其是用 Rust、C++ 開發時。但它也相對危險:你有機會「亂存記憶體」,像是越界寫入或寫錯地方。所以通常要搭配額外的 sandbox 或其他型別檢查機制來保護安全。 **3.3.3 Solana:帳戶即記憶體,資料存取高度顯性化** Solana 的設計很特別,它不是給你一塊整體的記憶體空間,而是每個「帳戶(account)」本身就是一個資料儲存區。也就是說,你在 Solana 寫一個合約時,要明確地「指定」你會使用哪幾個帳戶,這些帳戶會提供你可以讀寫的資料區塊。沒有明確列出來的帳戶,是不能動的。 這個設計有兩個好處:所有記憶體讀寫都可以預先驗證,增加安全性。不同交易只要不動到同一個帳戶,就可以**同時處理** , 增加並行效能。 這就是 Solana 為什麼可以超高速處理大量交易,記憶體模型設計功不可沒。 **3.3.4 Jam 的 PVM:每個物件自帶記憶體空間** Jam Protocol 的 PVM 採用的是物件導向架構,記憶體不再是某一段統一的空間,而是每個 object(物件)自己就有一塊「屬於它的記憶體區」。 也就是說:一個 NFT 是一個 object,它有自己的資料與狀態記憶體;一個 DAO 提案也是 object,它可以更新自己的投票狀態,不用依賴其他帳戶;這些物件之間可以溝通,也可以隔離,不會互相踩資料。 這種模型讓每一筆資料都能「自己保存自己的邏輯與狀態」,就像你每個資料夾都有自己的筆記本,不用去爭搶共用空間,也更容易做到模組化與自動互動。 **3.4 語言前端(Language Frontend / Compiler)** 當你寫一段智能合約,像是 `if 有人轉帳過來就發 token`,你用的程式語言可能是 Solidity、Rust 或 C。但VM其實不懂這些語言,它只能看懂一種非常低階的「機器指令碼」,也就是前面提過的 **bytecode**。**語言前端**就是負責把你寫的程式「翻譯」成VM能理解的格式,確保能被正確地執行。 你可以把它想像成虛擬機的「口譯員」或「翻譯工具」: - 開發者寫的是人類工程師能懂的語言(高階程式語言) - VM 只能聽得懂一套機器語言(低階 bytecode) - 中間需要一個翻譯者:這就是語言前端,也就是所謂的 **compiler(編譯器)** **3.4.1 Ethereum(EVM)** Ethereum 的主力語言是 **Solidity**,是一種專門為區塊鏈寫智能合約設計的語言。它有專屬的編譯器,叫做 `solc`(Solidity compiler)。 當你寫好一段 Solidity 程式碼,`solc` 會:把它編譯成 EVM 可以執行的 bytecode,順便產生 ABI(Application Binary Interface),定義合約可以怎麼被外部呼叫。這個流程已經非常成熟,是目前整個區塊鏈最主流的開發路線。 **3.4.2 WASM 型 VM(如 Polkadot、CosmWasm)** WASM 沒有固定語言,而是支援「多種語言」透過共通工具編譯成 WebAssembly。 最常見的是用 **Rust**,因為它安全、穩定、效能高,社群工具也最成熟。開發者會用 `cargo`(Rust 套件工具)與 `wasm-pack` 等工具,把 Rust 程式編譯成 `.wasm` 檔案,供鏈上 VM 執行。 這樣做的好處是:可以用「真實世界正在用的程式語言」開發區塊鏈程式,不需要重新學一套「區塊鏈專用語言」。但也有壞處:每個平台的環境與 interface 不太一樣,需要學習成本,並且Debug 工具、生態資源沒 EVM 那麼完整。 **3.4.3 Solana** Solana 主要支援 **Rust** 和 **C**,開發流程很接近 WASM,但它編譯出來的不是 WebAssembly,而是 **BPF bytecode**(前面講過的快速低階指令碼格式)。 Solana 提供了自己的 SDK(開發工具包)與建構環境,開發者一樣用 Rust 寫程式,編譯之後就能部署在 Solana VM 上執行。 這個開發流程比較工程化、偏向系統層,適合有經驗的開發者,初學者會覺得難度比較高。 **3.4.4 Jam PVM** **Jam Protocol 尚未公布具體語言與 compiler**,但他們的理念是讓鏈上的物件具備「狀態 + 行為」的能力,所以未來的開發語言很可能也會偏向物件導向結構,可能像是:支援類別、繼承、封裝;每個物件可以定義自己的方法與事件反應;編譯成某種與 PVM 對應的 bytecode 格式。 Jam 強調模組化與自動互動,因此它的語言前端可能不是「寫一份大合約」,而是「建立許多小物件,彼此關聯、分工執行」。 目前這一層屬於技術願景,但可以預期會是未來區塊鏈開發的新模型。 **compiler** 會直接影響:你能不能用熟悉的語言開發區塊鏈程式?你的合約邏輯能不能有效表達?開發過程中是否好除錯、模擬、測試?生態系是否容易吸引新開發者加入? 它決定了這個區塊鏈「是不是寫程式的人願意用」。這就是為什麼 EVM 發展得這麼快,因為 Solidity + Remix + Hardhat + MetaMask + ethers.js… 整個開發工具鏈已經非常成熟。而 WASM 與 Solana 雖然技術潛力大,但語言前端與生態工具還沒那麼完整,學習曲線也比較陡峭。 **3.5. 系統介面(System Interface)** **系統介面讓虛擬機執行的程式能真正作用在區塊鏈上,是合約與區塊鏈之間溝通的橋樑。**當你寫智能合約時,合約裡的程式只是邏輯指令,它無法直接與區塊鏈互動。像是「把 token 傳給某人」這種操作,其實不能單靠程式本身完成,必須透過一套介面去連接區塊鏈系統,查帳戶、寫資料、發送交易,這套介面就叫**系統介面(System Interface)**。 智能合約不能直接知道區塊高度(block height)、帳戶餘額,也不能主動傳送資產。它必須「**請求**」區塊鏈系統幫它執行,這就像應用程式想查時間、開網頁,也都要透過作業系統提供的 API。 **3.5.1 Ethereum(EVM)** Ethereum 使用明確定義的 **ABI 標準**,加上 RPC 系統,支援: - 合約之間的互相呼叫(內部呼叫) - 合約與外部用戶端的互動(如使用者在 DApp 點按鈕 → 呼叫合約) - 事件(Event)記錄:合約執行結果可以 emit 一個事件,供外部程式監聽 EVM 的 ABI 是整個 Web3 工具鏈的基礎(像 ethers.js、web3.js、MetaMask 全部靠它),這些應用層的工具**會根據 ABI 所描述的函數與參數格式**,自動幫你把要執行的操作編碼成 EVM 可以解讀的資料格式。 - ABI ABI,全名是 **Application Binary Interface**,**智能合約的「操作手冊」**。是合約提供給外部世界的說明書,它定義了你合約裡有哪些函數可以被呼叫、每個函數的名稱、參數類型、輸出格式等等。 當使用者或 DApp 想跟你的合約互動(例如呼叫 `transfer()`),會先查 ABI,然後根據它來把資料編碼成 EVM 看得懂的格式,再發送給鏈上執行。 🔹 ABI 是由開發者寫合約時自定義的,編譯器會自動產生它。 舉個例子:假設你寫了一個 Solidity 合約,裡面有一個函數 `mint(address to, uint amount)` 當有人要執行這個函數時,他的交易會附上一段**編碼後的資料**,告訴 VM:我要呼叫 `mint` 這個函數、目標地址是誰、要發多少 token,而 VM 就會根據 ABI 去解譯這段資料,正確執行對應的邏輯。 - RPC RPC,全名是 **Remote Procedure Call(遠端程序呼叫)**,意思是「你在本地發出一個指令,讓遠端機器去幫你做事,然後回傳結果」。 在區塊鏈裡,RPC 是讓你的電腦(例如你的 DApp 前端)與節點(例如 Infura、Alchemy、自己的 full node)溝通的方式。 它的用途包括: - 發送交易到區塊鏈(例如 `eth_sendTransaction`) - 查詢帳戶餘額(例如 `eth_getBalance`) - 讀取區塊高度(例如 `eth_blockNumber`) - 呼叫合約(例如 `eth_call`) 當你在 DApp 上按下「轉帳」按鈕時,實際上是: 1. 用 ABI 把函數編碼成 bytecode 2. 用 RPC 把這段資料傳給節點 3. 節點交給 EVM 執行,然後把結果透過 RPC 回傳給你 **3.5.2 WASM(如 Polkadot、CosmWasm)** WASM 合約通常沒有固定 ABI 標準,而是透過 runtime (執行時期)提供的一組 **host functions**(主機函數)來與鏈互動。這些 host function 是被固定註冊進 VM 裡的,也就是說 VM 在執行時已經內建了能呼叫這些功能的機制。 - host functions 讓合約「向系統」請求做事。 host function 是虛擬機(VM)在執行合約時,提供給合約使用的一組「**內建 API 工具**」。 智能合約本質上只是邏輯程式碼,它不能直接存取區塊鏈的資料或資源(像 token、storage、狀態等),否則會很危險。host function 的設計就是為了「**控制權限**」,確保合約只能透過這些官方提供的函數來間接與鏈互動。只會在「 runtime(執行階段)」存在,是合約與區塊鏈系統互通的關鍵橋樑。 以 WASM 智能合約(如 CosmWasm、Polkadot)為例,合約內會呼叫類似下面的函數: ```rust env::get_balance() // 取得帳戶餘額 env::write_state(key, value) // 寫入 storage env::send(receiver, amount) // 傳送 token 給某人 ``` 這些函數**不是開發者自己寫的**,而是 **VM 內建註冊好、執行時才會注入的功能**,所以叫做「主機函數」(host = 由主機提供,非自己擁有)。 **3.5.3 Solana** Solana 採用一種非常嚴格的「Account-based Model (帳戶模型)」,它的系統介面設計強調: - 所有交易中用到的帳戶、資料欄位,**必須事先列明** - 合約執行時,**只能使用這些帳戶的記憶體** - 所有操作都透過 `syscalls`(系統呼叫)完成,像是: - `sol_log()`:記錄日誌 - `sol_transfer()`:轉帳 - `sol_invoke()`:呼叫另一個合約 這種設計的好處是安全、可預測,也方便 VM 做「並行處理」,但也讓開發門檻比較高。 - Syscall(System Call) Syscall 是「低階系統呼叫機制」,原本在作業系統中是應用程式向核心請求權限操作(如記憶體、檔案系統等)的方式。它的設計目的: 為了安全,應用程式不能直接操作系統底層資源,只能透過一套「請求清單」間接拜託系統幫忙做。 在區塊鏈 VM 裡,**智能合約其實就像應用程式**,它不能自己亂動鏈上的資料或資產。 所以 VM 也提供一套 **syscall 表(系統呼叫表)**,當合約執行時: - 它會呼叫某個編號(例如 `0x05` 表示「讀 storage」) - 傳入一堆記憶體參數 - VM 看到這個代號 → 查表 → 呼叫系統功能 → 把結果丟回合約 例如在 **Solana BPF VM** ```c sol_log("Hello world"); ``` 這行其實會被轉譯成一個 **syscall 呼叫**,例如: ``` call syscall_id=0x01 ; 呼叫系統註冊好的 log 函數 ``` 其他像: - `0x07`: 檢查簽章 - `0x09`: 傳送 lamports(Solana 的 token) - `0x0B`: 讀 account 資料 這些都是合約自己不能直接處理的,必須拜託 VM 系統幫忙完成。 **Syscall**只有一個編號與記憶體位址參數,更貼近底層、效能高。VM 看懂代號,幫你處理,但你自己看不出來它是幹嘛的,所以開發者需要查表或工具支援。很多效能導向鏈(如 Solana)會選擇 syscall 模式,以獲得更小體積、更快執行、更可控的行為。 **3.5.4 Jam 的 PVM** Jam 設計的 PVM 不再使用傳統「帳戶 → 系統 API」的模式,而是建立一個由**物件組成的互動生態系**。 在 PVM 中,每個物件的行為邏輯是獨立的,它們之間**不能直接呼叫彼此的方法**(不像 EVM 可用 `call`,或 WASM 可跨模組呼叫),所有跨物件的操作**都必須透過「訊息」的形式送出**。 這些訊息會透過系統介面提供的 **host function / 系統呼叫(syscall)** 寫入交易上下文中,例如: - `send_message(object_id, payload)` - `emit_event(event_data)` - `request_spawn(object_type, init_state)` 這種限制式互動的做法,本質上是一種「封裝」與「控制」:它讓物件只能透過官方定義的接口來互動,不能任意存取別人的狀態或邏輯,大幅提升安全性與可控性。 ABI、Host Function、Syscall三者比較: | | ABI | Host Function | Syscall | | --- | --- | --- | --- | | 定義 | 外部呼叫合約的格式說明 | VM 給合約用的功能介面 | 合約對系統功能的底層請求方式 | | 提供者 | 合約開發者(透過編譯器) | 區塊鏈 VM | 區塊鏈 VM/runtime 系統 | | 呼叫者 | DApp、使用者、前端 | 合約本身 | 合約本身 | | 時間點 | 部署前就定義好 | runtime 掛載 | runtime 解析代號 | | 資料格式 | JSON / 二進位對照表 | 函數接口 / 模組 API | 整數編號+記憶體參數 | | 易懂性 | 高(有函數名) | 中(有語意) | 低(需查表對應) | | 常見在哪裡 | Ethereum、WASM 合約 | WASM VM(如 CosmWasm) | Solana BPF、Move VM(底層處理) | ## **四、總結整理:安全沙盒(Sandbox / Resource Control)機制** VM 最重要的功能之一就是限制合約的行為,避免程式碼越界操作主機資源或破壞鏈的穩定性。 因為區塊鏈上的智能合約是**開放給全世界任何人部署與執行的**,這就有風險(詳細如前所述)。 沙箱不是額外的東西,而是前五項「整合起來」打造出的限制機制,用來保護整個區塊鏈的安全。 4.1 **防止越權存取記憶體(防止 buffer overflow、竄改他人資料)** - **EVM**:採堆疊導向,限制所有操作只能在自身 stack 和 memory 中進行 - **WASM**:每個合約有獨立線性記憶體空間,無法越界存取 - **BPF(Solana)**:只能存取被授權的帳戶記憶體區塊,其他區域完全封鎖 - **PVM(Jam)**:預期以物件為單位,各物件狀態獨立,不得互相寫入除非明確授權 **4.2 限制與系統互動的權限與方式(不能直接操控主機資源)** - **EVM**:透過 ABI 與系統互動,需經由特定方法(如 `call`, `delegatecall`)且消耗 gas - **WASM**:只能使用 runtime 提供的 host functions,例如 `env::send()` - **BPF**:只能呼叫白名單內的 syscall,如 `sol_transfer()`,其餘動作皆不允許 - **PVM**:物件發送訊息也需經過調度機制,由 runtime 控制是否放行 **4.3 防止未授權操作帳戶、資產或狀態(帳戶隔離)** - **EVM**:僅能寫入自身儲存空間,或呼叫明確合約地址的函數 - **WASM**:無法自行探索鏈上資料,需透過 host function 查詢特定帳戶 - **BPF**:執行前即指定可操作帳戶,其他帳戶一律拒絕互動 - **PVM**:每個 object 僅能操作自身狀態,需發送訊息才能觸及他人(封裝邏輯) 4.4 **禁止執行非預期或危險指令(防止任意跳轉、任意呼叫)** - **EVM**:opcode 限制明確,如無法任意 call 未知位址 - **WASM**:每個指令皆經過驗證,不可越界、不可隨意 call_indirect - **BPF**:Verifier 靜態檢查是否存在未對齊記憶體、非法跳轉、無效暫存器 - **PVM**:未來設計中,將以「訊息機制(Message-only Interaction)」避免物件任意執行他人邏輯 4.5 **合約執行環境之間互相隔離(不能共用狀態或記憶體)** - **EVM**:每個合約儲存空間獨立,需透過 `delegatecall` 才能共享邏輯 - **WASM**:記憶體空間完全分離,沒有任何共享段落 - **BPF**:執行時帳戶必須明確列出,其他合約無法隨便介入 - **PVM**:物件各自為單元,除非透過明確訊息機制,不得直接互調 快速總覽表 | 名稱 | 全名 | 用途/定位 | 特點/差異點 | | --- | --- | --- | --- | | **SolanaVM** | Solana Virtual Machine | Solana 鏈上原生執行環境 | 相容 Rust/C 開發,執行速度極快,低延遲、可高度並行 | | **EthereumVM (EVM)** | Ethereum Virtual Machine | Ethereum(與其兼容鏈)的虛擬機器 | 智能合約用 Solidity 編寫、Gas 機制、廣泛兼容性 | | **WASM** | WebAssembly | 可跨平台運行的通用虛擬指令集 | 可用多種語言編寫(如 Rust/C++),原為瀏覽器設計,現被用於鏈上(如 Polkadot) | | **PVM** | Parallel Virtual Machine | Jam 區塊鏈未來導入的虛擬機設計 | 高並行、多執行緒環境,支援 object-based 模型 |