📜 [專欄新文章] ZKP 與智能合約的開發入門
✍️ Johnson
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
這篇文章將以程式碼範例,說明 Zero Knowledge Proofs 與智能合約的結合,能夠為以太坊的生態系帶來什麼創新的應用。
本文為 Tornado Cash 研究系列的 Part 2,本系列以 tornado-core 為教材,學習開發 ZKP 的應用,另兩篇為:
Part 1:Merkle Tree in JavaScript
Part 3:Tornado Cash 實例解析
Special thanks to C.C. Liang for review and enlightenment.
近十年來最強大的密碼學科技可能就是零知識證明,或稱 zk-SNARKs (zero knowledge succinct arguments of knowledge)。
zk-SNARKs 可以將某個能得出特定結果 (output) 的計算過程 (computation),產出一個證明,而儘管計算過程可能非常耗時,這個證明卻可以快速的被驗證。
此外,零知識證明的額外特色是:你可以在不告訴對方輸入值 (input) 的情況下,證明你確實經過了某個計算過程並得到了結果。
上述來自 Vitalik’s An approximate introduction to how zk-SNARKs are possible 文章的首段,該文說是給具有 “medium level” 數學程度的人解釋 zk-SNARKs 的運作原理。(可惜我還是看不懂 QQ)
本文則是從零知識證明 (ZKP) 應用開發的角度,結合電路 (circuit) 與智能合約的程式碼來說明 ZKP 可以為既有的以太坊智能合約帶來什麼創新的突破。
基本上可以謹記兩點 ZKP 帶來的效果:
1. 擴容:鏈下計算的功能。
2. 隱私:隱藏秘密的功能。
WithoutZK.sol
首先,讓我們先來看一段沒有任何 ZKP 的智能合約:
這份合約的主軸在 process(),我們向它輸入一個秘密值 secret,經過一段計算過程後會與 answer 比對,如果驗證成功就會改寫變數 greeting 為 “answer to the ultimate question of life, the universe, and everything”。
Computation
而計算過程是一個簡單的函式:f(x) = x**2 + 6。
我們可以輕易推出秘密就是 42。
這個計算過程有很多可能的輸入值 (input) 與輸出值 (output):
f(2) = 10
f(3) = 15
f(4) = 22
…
但是能通過驗證的只有當輸出值和我們存放在合約的資料 answer 一樣時,才會驗證成功,並執行 process 的動作。
可以看到有一個 calculate 函式,說明這份合約在鏈上進行的計算,以及 process 需要輸入參數 _secret,而我們知道合約上所有交易都是公開的,所以這個 _secret 可以輕易在 etherscan 上被看到。
從這個簡單的合約中我們看到 ZKP 可以解決的兩個痛點:鏈下計算與隱藏秘密。
Circuits
接下來我們就改寫這份合約,加入 ZKP 的電路語言 circom,使用者就能用他的 secret 在鏈下進行計算後產生一個 proof,這 proof 就不會揭露有關 secret 的資訊,同時證明了當 secret 丟入 f(x) = x**2 + 6 的計算過程後會得出 1770 的結果 (output),把這個 proof 丟入 process 的參數中,經過 Verifier 的驗證即可執行 process 的內容。
有關電路 circuits 的環境配置,可以參考 ZKP Hello World,這裡我們就先跳過去,直接來看 circom 的程式碼:
template Square() { signal input in; signal output out; out <== in * in;}template Add() { signal input in; signal output out; out <== in + 6;}template Calculator() { signal private input secret; signal output out; component square = Square(); component add = Add(); square.in <== secret; add.in <== square.out; out <== add.out;}component main = Calculator();
這段就是 f(x) = x**2 + 6 在 circom 上的寫法,可能需要時間去感受一下。
ZK.sol
circom 寫好後,可以產生一個 Verifier.sol 的合約,這個合約會有一個函式 verifyProof,於是我們把上方的合約改寫成使用 ZKP 的樣子:
我們可以發現 ZK 合約少了 calculate 函式,顯然 f(x) = x**2 + 6 已經被我們寫到電路上了。
snarkjs
產生證明的程式碼以 javascript 寫成如下:
let { proof, publicSignals } = await groth16.fullProve(input, wasmPath, zkeyPath);
於是提交 proof 給合約,完成驗證,達到所謂鏈下計算的功能。
最後讓我們完整看一段 javascript 的單元測試,使用 snarkjs 來產生證明,對合約的 process 進行測試:
對合約來說, secret = 42 是完全不知情的,因此隱藏了秘密。
publicSignals
之前不太清楚 publicSignals 的用意,因此在這裡特別說明一下。
基本上在產生證明的同時,也會隨帶產生這個 circom 所有的 public 值,也就是 publicSignals,如下:
let { proof, publicSignals } = await groth16.fullProve(input, wasmPath, zkeyPath);
在我們的例子中 publicSignals 只有一個,就是 1770。
而 verifyProof 要輸入的參數除了 proof 之外,也要填入 public 值,簡單來說會是:
const isValid = verifyProof(proof, publicSignals);
問題來了,我們在設計應用邏輯時,當使用者要提交參數進行驗證的時候,publicSignals 會是由「使用者」填入嗎?或者是說,儘管是使用者填入,那它需不需要先經過檢查,才可以填入 verifyProof?
關鍵在於我們的合約上存有一筆資料:answer = 1770
回頭看合約上的 process 在進行 verifyProof 之前,必須要檢查 isAnswer(publicSignals[0]):
想想要是沒有檢查 isAnswer,這份合約會發生什麼事情?
我們的應用邏輯就會變得毫無意義,因為少了要驗證的答案,就只是完成計算 f(42) = 1770,那麼不論是 f(1) = 7 或 f(2) = 10,使用者都可以自己產生證明與結果,自己把 proof 和 publicSignals 填入 verifyProof 的參數中,都會通過驗證。
至此可以看出,ZKP 只有把「計算過程」抽離到鏈下的電路,計算後的結果仍需要與鏈上既有的資料進行比對與確認後,才能算是有效的應用 ZKP。
應用邏輯的開發
本文主要談到的是 zk-SNARKs 上層應用邏輯的開發,關於 ZKP 的底層邏輯如上述使用的 groth16 或其他如 plonk 是本文打算忽略掉的部分。
從上述的例子可以看到,即使我們努力用 circom 實作藏住 secret,但由於計算過程太過簡單,只有 f(x) = x**2+6,輕易就能從 answer 反推出我們的 secret 是 42,因此在應用邏輯的開發上,也必須注意 circom 的設計可能出了問題,導致私密訊息容易外洩,那儘管使用再強的 ZKP 底層邏輯,在應用邏輯上有漏洞,也沒辦法達到隱藏秘密的效果。
此外,在看 circom 的程式碼時,可以關注最後一個 template 的 private 與 public 值分別是什麼。以本文的 Calculator 為例,private 值有 secret,public 值有 out。
另外補充:
如果有個 signal input 但它不是 private input,就會被歸類為 public。
一個 circuit 至少會有一個 public,因為計算過程一定會有一個結果。
最後,在開發的過程中我會用 javascript 先實作計算過程,也可以順便產出 input.json,然後再用 circom 語言把計算過程實現,產生 proof 和 public 後,再去對照所有 public 值和 private 值,確認是不是符合電路計算後所要的結果,也就是比較 javascript 算出來的和 circom 算出來的一不一樣,如果不一樣就能確定程式碼是有 bug 的。
參考範例:https://github.com/chnejohnson/circom-playground
總結
本文的程式碼展現 ZKP 可以做到鏈下計算與隱藏秘密的功能,在真實專案中,可想而知電路的計算過程不會這麼單純。
會出現在真實專案中的計算像是 hash function,複雜一點會加入 Merkle Tree,或是電子簽章 EdDSA,於是就能產生更完整的應用如 Layer 2 擴容方案之一的 ZK Rollup,或是做到匿名交易的 Tornado Cash。
本文原始碼:https://github.com/chnejohnson/mini-zkp
下篇文章就來分享 Tornado Cash 是如何利用 ZKP 達成匿名交易的!
參考資料
概念介紹
Cryptography Playground
zk-SNARKs-Explainer
神奇的零知識證明!既能保守秘密,又讓別人信你!
認識零知識證明 — COSCUP 2019 | Youtube
應用零知識證明 — COSCUP 2020 | Youtube
ZK Rollup
動手實做零知識 — circom — Kimi
ZK-Rollup 开发经验分享 Part I — Fluidex
ZkRollup Tutorial
ZK Rollup & Optimistic Rollup — Kimi Wu | Medium
Circom
circom/TUTORIAL.md at master · iden3/circom · GitHub
ZKP Hello World
其他
深入瞭解 zk-SNARKs
瞭解神秘的 ZK-STARKs
zk-SNARKs和zk-STARKs解釋 | Binance Academy
[ZKP 讀書會] MACI
Semaphore
Zero-knowledge Virtual Machines, the Polaris License, and Vendor Lock-in | by Koh Wei Jie
Introduction & Evolution of ZK Ecosystem — YouTube
The Limitations of Privacy — Barry Whitehat — YouTube
Introduction to Zero Knowledge Proofs — Elena Nadolinski
ZKP 與智能合約的開發入門 was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
同時也有1部Youtube影片,追蹤數超過4萬的網紅史九87 SJ87,也在其Youtube影片中提到,📖 台大資訊工程學系 📖 教授教的東西根本用不到 📖 盤點「四大沒有用的必修課」 📖 這些必修課有什麼用? 📖 軟體工程師要學什麼 👨🏫 普通物理學 👨🏫 自動機與形式語言 👨🏫 計算機結構 👨🏫 數位電子與電路 📖 我要學硬體還是軟體! 📖 國立大學都逼你修用不到的物理學? 🙋🏽♂️...
「電路計算」的推薦目錄:
- 關於電路計算 在 Taipei Ethereum Meetup Facebook 的最佳解答
- 關於電路計算 在 Winnie老師的科學馬戲團 Facebook 的最佳貼文
- 關於電路計算 在 大詩人的寂寞投資筆記 Facebook 的最佳解答
- 關於電路計算 在 史九87 SJ87 Youtube 的最佳貼文
- 關於電路計算 在 串並聯電路---並聯電阻計算---老師講解11 - YouTube 的評價
- 關於電路計算 在 電路學【例題】串並聯電路基本練習(選修物理Ⅴ) - YouTube 的評價
- 關於電路計算 在 電路學【觀念】電阻的串聯公式及電壓分配(選修物理Ⅴ) 的評價
- 關於電路計算 在 深夜小學堂:今晚我想來個並聯電路的電流計算. 大家還記得 ... 的評價
電路計算 在 Winnie老師的科學馬戲團 Facebook 的最佳貼文
最近在教小學生電路學。用一些生活中的經驗,教他們電學、生活中的經驗,教他們電學、電壓、電流、電阻、靜電、斷路、短路、通路+簡單並聯+串聯電路計算。孩子們學習能力不輸我們國中生呀!!
拿了電光積木給他們玩,告訴他們要小心接,這積木都有線路,亂接可能造成短路,積木就會壞掉~~ 孩子們也都能理解,讓他們嘗試了很久!(我只有從旁協助,沒有直接告訴他們)
終於讓電燈亮囉~螺旋槳也飛起來囉~很棒吧!!
電路計算 在 大詩人的寂寞投資筆記 Facebook 的最佳解答
「世界上第一個發明可編程計算機的是德國工程師楚澤。楚澤發現很多運算道理都是一樣的,只是改改其中的數字,這種事情應該能讓機器完成。在此之前巴貝奇等人的計算機一次只能做一種運算,而楚澤則希望機器能夠按照流程完成一系列的運算。這件事自然就需要用程序控制。
楚澤發明的第一台計算機,即Z1,也是純機械的。它非常複雜,也非常大,因此需要用馬達驅動了。由於是純機械的,一秒鐘只能計算一次。也就是說,楚澤的計算機是利用更多的能量、更複雜的信息,完成更複雜的運算。
到目前為止,計算機雖然能完成越來越多的運算,但是消耗的能量也越來越高。打算盤進行一次計算可能只需要一粒芝麻的能量,擺弄帕斯卡和萊布尼茨的計算機就需要一顆綠豆的能量了,而巴貝奇的計算機需要一粒花生米的能量,楚澤的可能要一個橙子的能量。如果按照這個趨勢發展下去,人類是無法實現大量的數據計算的。
因此,楚澤在它第二個計算機中就使用了繼電器取代機械設備,這樣不僅消耗的能量低,而且速度快。為什麼繼電器的計算機比機械的快呢?因為機械運動有慣性,齒輪不可能正著轉完了馬上反著轉。繼電器雖然也有慣性,但是接觸和斷開的時間間隔可以非常短。如果我們把機械計算機看成是紐卡門蒸汽機,每次工作一下都要等氣缸冷卻,那麼繼電器的計算機就如同瓦特改進後的蒸汽機,不再需要冷卻這個過程,可以連續工作。
但是繼電器開關的頻率畢竟有限。如果能用電子設備取代繼電器,那麼計算的速度可以大幅度提升,這就是美國研制電子計算機的初衷。1946年,世界上第一台通用電子計算機埃尼亞克誕生了,它的速度在當時來講是飛快的,一秒鐘能進行5000次運算。
不過它的能耗也是巨大的,因為它裡面有近18000個電子管,每個電子管相當於一個小燈泡,它的耗電量大約是15萬瓦,當時它一啓動,周圍居民家的燈都會變暗。埃尼亞克消耗一度電大約能完成2.5萬次運算,我們記住這個數字,以便於後面和今天的計算機作比較。
第一台通用電子計算機埃尼亞克用到了圖靈在1936年提出的圖靈機的理論。所謂的圖靈機,是一種數學模型,它告訴人們,如何利用信息控制機械,實現計算。也就是說,計算的本質是一種機械運動,但它需要信息(指令)控制。計算機的這個本質直到今天都沒有改變。至於計算是如何通過機械運動實現的,這就涉及到香農的一項發明——開關電路了。今天所有的集成電路裡面其實都是各種各樣的開關電路。
自1946年以來,計算機70多年的發展,從本質上講就是提高能量利用率的過程。這70多年里有三個里程碑是你必須知道的。
第一個里程碑是晶體管的誕生,它將計算的能耗降低了兩個數量級。這是上個世紀50年代的事情。
第二個里程碑是集成電路的發明,它將計算的能耗又降低了大約兩個數量級。這是60年代初的事情。那時消耗一度電量可以完成1億次的運算了。
第三個里程碑則是1965年摩爾提出摩爾定律,即集成電路的性能每12個月翻一番,1975年摩爾對摩爾定律有所修正,認為1980年起集成電路的性能每兩年就會翻一番。
摩爾和他的同事諾伊斯當時預見到,將很多小集成電路芯片集成到一個大的芯片中,將是未來半導體行業發展的方向。而當時他們所在的仙童公司董事會卻意識不到這一點。於是二人離開了仙童創辦了英特爾公司。
在隨後的半個多世紀里,全世界半導體產業還真按照摩爾當年預見的速度在發展。從英特爾在1971年推出第一款處理器4004到2005年摩爾定律40週年之際,集成電路的性能還真提高了1000萬倍,完全符合摩爾定律的要求。
在2005年之後的十多年里,雖然集成電路的進步速度有所放緩,但是基本上還能做到每兩年翻一番,這樣累積下來又提高了百倍。這樣翻番進步疊加的結果是驚人的,以至於我們今天最差勁的智能手機,性能都比當年控制阿波羅登月的巨型計算機系統強很多。
如果我們用單位能耗提供的計算能力來衡量,這個進步也是相當快的。到2018年,世界上最快的橡樹嶺超級計算機一秒鐘最多能完成20億億次浮點運算,耗電2.7度,相當於一度電完成了7.5億億次的運算,比上世紀60年代最早的集成電路計算機進步了7億倍左右。
在經歷了50年的翻番進步後,基於半導體材料的集成電路裡面器件的集成度已經接近了物理的極限。因此有人認為摩爾定律不再適用了。但是,集成電路依然有發展的空間,那便是繼續提高單位能耗的計算能力,而不是一個芯片中絕對的計算能力。
如果我們以單位能耗的計算能力來衡量過去70多年計算機的進步,大約是每兩年半翻一番,比摩爾定律進步的速度略慢,這中間的差距是源於半導體芯片在變得複雜之後,大量的能量被用在發熱而非計算本身上面。實際上從十多年前開始,整個半導體產業的努力方向已經從單純提高性能,轉變為提高單位能耗性能了,並且在沿著這個方向取得了不小的進步。
那麼科學家和工程師們是怎麼做到這一點的呢?簡單地講就是用信息置換能量。我們不妨用兩個大家經常聽說的例子來說明。
第一個就是英偉達公司所謂的人工智能芯片。它其實是一種特殊的圖形處理器,並且對很多人工智能的應用作了專門的優化。相比英特爾的通用處理器,它單位能耗的計算能力能提高兩個數量級(百倍左右)。
那麼英偉達是怎麼做到的呢?它其實並沒有往處理器裡面塞更多的晶體管,而是根據人工智能計算的特點,將計算的精度從64位降低到8位,這樣就可以用同樣數量的晶體管搭建幾十倍的內核了,於是每一個內核的能耗就降低了。而這麼做的前提是,需要對人工智能算法的信息處理過程有深刻的瞭解。
第二個例子是Google的人工智能芯片TPU。Google自己講,它比英偉達的人工智能芯片單位能耗的計算能力又提高了兩個數量級(當然英偉達不承認)。Google是怎麼做到的呢?其實這種TPU只適合進行和深度學習有關的計算,不適合其他的信息處理,Google是將深度學習算法的特點設計到了處理器中。
從這兩個例子可以看出,如果我們在處理器中將信息處理的算法集成進去,就能大幅度提高單位能耗的計算能力,當然,這樣一來相應處理器的應用場景也就受到限制了。不過當某一類計算使用的人非常多了以後,這麼做還是值得的。
今天我們使用了能量和信息這兩根主線,將人類幾千年來,特別是最近幾十年來在計算機領域的成就,概括成了十來分鐘的內容。這樣你就能夠看清當今計算機領域的發展方向了,它一直沿著提高單位能耗的計算能力在進步,在過去,這體現為摩爾定律,今天,它更多地體現為利用信息置換能量。而計算的本質,就是在信息的控制下,利用能量實現運算。」
電路計算 在 史九87 SJ87 Youtube 的最佳貼文
📖 台大資訊工程學系
📖 教授教的東西根本用不到
📖 盤點「四大沒有用的必修課」
📖 這些必修課有什麼用?
📖 軟體工程師要學什麼
👨🏫 普通物理學
👨🏫 自動機與形式語言
👨🏫 計算機結構
👨🏫 數位電子與電路
📖 我要學硬體還是軟體!
📖 國立大學都逼你修用不到的物理學?
🙋🏽♂️ 我想長資識 🙋🏽♂️
👉追蹤我們👈
————————————————————————
史提 IG ► https://www.instagram.com/im10tea
9V IG ► https://www.instagram.com/im9vv
七桃八蕊 IG ► https://www.instagram.com/im87cat
史九87 FB ► https://www.facebook.com/shihjo87
商業合作請洽詢 ► shihjo87@gmail.com
————————————————————————
👉 Follow us 👈
————————————————————————
Steven IG ► https://www.instagram.com/im10tea
Jovy IG ► https://www.instagram.com/im9vv
Our cats: 7Tao 8Rei IG ► https://www.instagram.com/im87cat
SJ87 FB ► https://www.facebook.com/shihjo87
Biz contact ► shihjo87@gmail.com
————————————————————————

電路計算 在 電路學【例題】串並聯電路基本練習(選修物理Ⅴ) - YouTube 的推薦與評價

電路 學【例題】串並聯 電路 基本練習(選修物理Ⅴ). 吳旭明x蔡佳玲-物理學習網 ... 【模型加燈】02 電路 的基本知識和電阻值 計算 方法. Jade Hobby. ... <看更多>
電路計算 在 電路學【觀念】電阻的串聯公式及電壓分配(選修物理Ⅴ) 的推薦與評價

講義下載區https://sites.google.com/site/phyelearning/phy5/Current 這是由吳旭明老師及蔡佳玲老師所建立的免費數位學習內容更完整的課程結構請 ... ... <看更多>
電路計算 在 串並聯電路---並聯電阻計算---老師講解11 - YouTube 的推薦與評價
串並聯 電路 ---並聯電阻 計算 ---老師 ... ... <看更多>