零知識證明可以在不洩露具體資訊的情況下向其他人證明自己掌握該資訊,這聽起來非常适合去中心化應用。在這個教程中,我們将利用zksnark來實作一個具體的NodeJS零知識證明應用:漁船無需透露自己的具體位置,就可以向監管機構證明自己處于劃定的合法捕撈區内 —— 我們的主要武器是snarkjs和circom。

用自己熟悉的語言學習以太坊DApp開發: Java | Php Python .Net / C# Golang Node.JS Flutter / Dart
1、需求分析
設計零知識證明應用方案的第一步是要将具體的問題轉換為一個電路。我們要證明漁船處于合法捕撈區内,這個問題中存在以下變量:
- 合法捕撈區的範圍,可以用該區域的經度/次元的最大值和最小值來表示漁船的位置,用漁船的經度和次元來表示
容易得到如下的輸入輸出映射:
+--------------+
漁船經度/次元 ->| |
| |
捕撈區經度最大/最小值 ->| 電路 |-> 在/不在合法捕撈區
| |
捕撈區緯度最大/最小值 ->| |
+--------------+
2、circom電路實作
據此,我們可以得到如下的circom電路定義:
其中:
- latitudeRange:電路輸入,表示合法捕撈區域的緯度的最小值和最大值,數組
- longitudeRange:電路輸入,表示合法捕撈區域的經度的最小值和最大值,數組
- fishingLocation:電路輸入,表示漁船的經度和次元,數組
- out:電路輸出,1表示漁船在合法捕撈區,0表示漁船不在合法捕撈區
由于我們要隐藏漁船的具體位置,是以在上面的circom電路中,你可以看到fishingLocation被定義為private。
3、circom電路編譯
如果還沒有安裝circom的話,使用如下指令全局安裝circom:
npm install -g circom
注意:推薦使用node 12,因為内置了原生的大數計算,效率提升10倍!
使用如下指令編譯電路檔案InRange.circom,輸出結果命名為InRange.json:
circom InRange.circom -o InRange.json
4、zksnark的可信設定
在使用zksnark之前,需要一個可信設定,而且該可信設定依賴于具體的電路,例如我們編譯得到的InRange.json。
使用snarkjs來建立這個可信設定,同樣,如果需要安裝的話,使用如下指令:
npm install -g snarkjs
現在我們利用漁業監控電路進行可信設定:
snarkjs setup -c InRange.json
上面的指令将會在目前目錄建立兩個檔案:proving_key.json和verification_key.json。其中proving_key.json用于證明你的輸入是有效的(滿足電路限制),而verification_key.json用來驗證别人提供的證據。
5、計算ziksarnk電路信号的見證(witness)
在我們建立提供給其他人的證據之前,需要先計算出電路中所有信号(包括輸入信号和中間信号)
的見證。為此我們需要建立一個輸入檔案input.json,其中包含所有輸入(公開輸入和私有輸入)的值,然後利用這個輸入檔案計算得到見證檔案witness.json,這兩個檔案都不會公開。
下面是我們的漁業監控電路的輸入檔案示例:
{
"latitudeRange": [ 20, 21],
"longitudeRange": [ 176, 190],
"fishingLocation": [ 20, 180]
}
使用sparkjs來計算得出見證檔案witness.json:
snarkjs calculatewitness -c InRange.json
6、建立zksnark證據
有了witness.json,我們就可以建立提供給其他人的證據了:
snarkjs proof
上面的指令将在目前目錄生成proof.json和公開檔案public.json,publc.json實際上就是witness.json檔案内容的一個子集,其中僅包含電路中可公開信号的值。
現在目錄裡的檔案如下圖所示:
7、校驗zksnark證據
現在你(漁船船長)可以把verification_key.json、proof.json和public.json提供給監管機構了,監管方使用如下指令即可驗證你的船的确在合法捕撈區内,但卻不知道你的具體位置:
snarkjs verify
GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD!
原文連結:
零知識證明實戰漁業監 — 彙智網