---
title: "如何使用零知識證明在以太坊上構建隱私應用程式"
description: "一種可重複使用的模式為以太坊上的匿名投票、混幣器、空投和會員系統提供動力。了解承諾-作廢者-證明循環，以及零知識工具如何讓現今的開發變得切實可行。"
author: "菲利普·克勞斯"
team: "EF Builder Growth"
tags:
  - "零知識證明"
  - "隱私"
published: 2026-05-12
image: /images/developers/blog/latest-post-header-2.png
breadcrumb: "以太坊上的隱私應用程式"
lang: zh-tw
---

以太坊在設計上是極度公開的。任何擁有區塊鏈瀏覽器的人都可以看到每個地址、餘額、交易、合約呼叫和事件。當你需要可驗證性時，這種透明度非常有用。但當用戶需要投票、申領、提款或證明會員身分，而不希望將每個操作都連結回同一個錢包時，這就會成為一個問題。

匿名會員制是一種可重複使用的模式，為以太坊上一大類隱私應用程式提供動力。人們首先註冊，然後在不透露自己是哪位成員的情況下，證明他們屬於該群體。零知識證明是註冊錢包和操作錢包之間的橋樑，而這座橋樑不會透露是誰跨越了它。

周邊的產品會改變，但隱私骨架保持不變。

## 透過匿名投票解釋該模式 {#the-pattern-explained-through-anonymous-voting}

該模式包含三個部分。一個承諾會註冊每位成員。一棵默克爾樹將這些承諾變成一個群體。一個證明和一個作廢者（nullifier）讓一位成員可以操作一次，而不會透露是哪位成員進行了操作。

### 第一步：註冊 {#step-one-registering}

每位投票者在鏈下建立兩個私密值：秘密（secret）和作廢者（nullifier）。投票者將這些值雜湊成一個公開的承諾，然後在鏈上註冊該承諾。

承諾是公開的註冊紀錄。秘密和作廢者是投票者稍後需要的私密票據（note）。如果遺失了票據，投票者就無法證明會員身分。如果洩漏了票據，其他人可能就可以代替該用戶投票。

因為承諾是一個雜湊，觀察者無法還原其中的私密值。承諾表示「有人註冊了」，但不會透露稍後誰將使用該註冊。

### 第二步：建立群體 {#step-two-building-the-crowd}

隨著越來越多投票者註冊，應用程式會將他們的承諾收集到一棵默克爾樹中。默克爾樹將一長串的值壓縮成單一雜湊，稱為根（root）。只要更改列表中的任何值，雜湊就會改變，因此根可以作為整個集合防篡改的摘要。

這棵樹就是你的匿名集。如果樹中有十個用戶，觀察者可以將後續的操作縮小到這十個人之一。如果樹中有一萬個用戶，就很難將操作連結到單一個人。一個匿名集很小的隱私應用程式通常不太具有隱私性，即使密碼學是正確的。

### 第三步：匿名操作 {#step-three-acting-anonymously}

當投票開始時，投票者不應該使用註冊承諾的同一個錢包進行投票。從註冊錢包投票會將投票直接連結回註冊者，從而破壞隱私保護工作。相反地，投票者會建立一個零知識證明。該陳述被編碼為一個電路，表示：「我知道能產生已註冊承諾的私密值，並且我正在揭露這次投票正確的作廢者雜湊。」

該證明能說服驗證者合約該陳述為真。它不會透露秘密、作廢者，或使用了哪個承諾。

作廢者是用來防止重複投票的機制。在提交證明的同時，投票者會發布一個作廢者雜湊。投票合約在接受投票後會儲存該雜湊。如果同一個私密票據再次用於同一次投票，它會產生相同的作廢者雜湊，合約就會拒絕第二次投票。結合證明，這使得合約只知道某個已註冊的投票者操作了一次，而不知道是哪一位。

## 可重複使用的閘門 {#the-reusable-gate}

同樣的證明與作廢者組合不僅適用於投票。撇開投票的情境，你得到的是一個用於智能合約函式的隱私閘門。

在函式執行之前，合約會檢查默克爾根、驗證證明、確認作廢者雜湊未被使用過，並將公開輸入綁定到正確的應用程式、鏈、投票、申領或提款。如果這些檢查通過，它會將作廢者標記為已使用，並執行函式的其餘部分。

將這個閘門放在投票之前，你就得到了匿名投票。將它放在空投申領之前，你就得到了匿名申領。將它放在提款函式之前，你就得到了混幣器風格提款流程的核心。相同的承諾樹、相同的作廢者概念、相同的證明模式。改變的只有函式主體和周邊的應用程式邏輯。

## 什麼在哪裡運行 {#what-runs-where}

私密工作通常在鏈下進行。用戶儲存票據，客戶端應用程式建立見證並運行證明者來產生證明。索引器會追蹤承諾和默克爾根。捆綁器會在鏈上傳播用戶操作（UserOperation），並由 ERC-4337 代付合約贊助燃料，因此一個全新的錢包不需要先從用戶已知的錢包獲取 ETH。

公開的強制執行發生在鏈上。驗證者合約會檢查證明。應用程式合約會檢查有效的根和未使用的作廢者、儲存作廢者雜湊，並執行公開操作。

敏感的使用者體驗（UX）在於票據的處理。請將秘密和作廢者視為金鑰。不要將它們放入分析、日誌、URL、錯誤報告或一般的伺服器端遙測中。一旦票據洩漏，無論證明有多強大，隱私都會蕩然無存。

## 工具已經跟上 {#the-tooling-caught-up}

你不需要手動編寫底層的密碼學程式碼。常見的做法是使用高階零知識語言編寫電路，產生一個 Solidity 驗證者，然後從應用程式合約中呼叫該驗證者。

適合的技術堆疊取決於工作需求。Circom 搭配 snarkjs 是應用程式級別電路行之有效的途徑。Noir 搭配 Barretenberg 是一條較新且對開發者友善的途徑。Halo2 和 gnark 是較低階的電路函式庫。像 RISC Zero 或 SP1 這樣的 zkVM 可以證明一般的程式，但證明的成本可能比小型的自訂電路更高。

對於匿名會員制，在編寫自己的電路之前，請先尋找現有的協定。Semaphore 將群組會員制和基於作廢者的防止重複使用機制打包成合約和 JavaScript 函式庫。對於私密投票和治理，MACI 是專門的途徑，因為它增加了防勾結的特性。成熟的協定通常比新的電路更安全。

## 僅有證明是不夠的 {#the-proof-is-not-enough}

如果錢包流程洩漏了關聯性，即使是完美的證明也會失效。從錢包 A 註冊，稍後又從錢包 A 進行操作，任何觀察者都能將這些交易連結起來。在操作前夕從錢包 A 轉帳給錢包 B，這筆資金交易也會造成同樣的問題。

這就是為什麼捆綁器和代付合約如此重要。操作錢包應該是全新的，而且它不應該需要從用戶試圖與該操作分開的錢包中接收 ETH。

同樣的問題也存在於鏈下。從同一個 IP 地址、RPC 供應商或工作階段提交註冊和操作交易，可能會削弱電路提供的隱私。前端可能會透過分析、本機儲存和支援日誌發生洩漏。零知識證明隱藏了證明內部的值，但它並不會隱藏交易周圍的所有事物。

公開輸入是隱私應用程式失敗的另一個地方。在電路中標記為公開、作為事件發出、包含在呼叫資料（calldata）中，或由合約儲存的任何內容都是可見的。審查公開輸入時，應像審查 Solidity 合約上的存取控制一樣仔細。

## 這對開發者帶來了什麼改變 {#what-this-changes-for-builders}

在以太坊上實現隱私是可行的。開發者可以將這些組件組合成真實的應用程式。這個技術堆疊包含：用於私密陳述的電路、用於檢查證明的驗證者、用於公開規則的應用程式合約、用於默克爾資料的索引器，以及用於無關聯提交和燃料贊助的捆綁器加代付合約。

困難的部分在於產品設計、金鑰管理、中繼資料衛生、稽核，以及擴大匿名集。只要其中任何一個環節出錯，證明所提供的隱私就會消失。

## 進一步閱讀 {#further-reading}

1. [零知識證明 (ethereum.org)](https://ethereum.org/zero-knowledge-proofs/)
2. [Semaphore 文件](https://docs.semaphore.pse.dev/)
3. [MACI 文件](https://maci.pse.dev/)
4. [Circom 文件](https://docs.circom.io/)
5. [Noir 文件](https://noir-lang.org/)
6. [Halo2 手冊](https://zcash.github.io/halo2/)
7. [gnark 文件](https://docs.gnark.consensys.io/)
8. [RISC Zero 文件](https://dev.risczero.com/api/)
9. [SP1 文件](https://docs.succinct.xyz/docs/sp1/introduction)
10. [EIP-4337：透過 EntryPoint 合約實現帳戶抽象化](https://eips.ethereum.org/EIPS/eip-4337)