零知识证明系列之三——入门zkSNARK
前文回顧
回顧一下一套完善的零知識證明體系需要以下的條件:
(1)完備性(Completeness)如果證明方和驗證方都是誠實的,并遵循證明過程的每一步,進行正確的計算,那么這個證明一定是成功的,驗證方一定能夠接受證明方。
(2)合理性(Soundness) 沒有人能夠假冒證明方,使這個證明成功。
(3)零知識性(Zero-knowledge)證明過程執行完之后,驗證方只獲得了“證明方擁有這個知識”這條信息,而沒有獲得關于這個知識本身的任何一點信息。
接下來就是我們的重頭戲zksanrk了。
預備知識
P vs NP
克雷數學研究所官網找到了關于 P和NP問題的簡單說明。
簡單地翻譯過來就是:
假設你正在為400名大學生組織住宿,但是空間有限只有100名學生能留在宿舍里。更復雜的是還給了你一份不相容學生的名單,并要求在你的最終選擇中不要出現這份名單中的任何一對。
這是計算機科學家稱之為NP問題的一個例子,因為很容易檢查一個同事提出的一百個學生的給定選擇是否令人滿意,然而從頭開始找到這100個人的任務似乎太難了以至于完全不切實際。
事實上從400名申請者中選擇100名學生的方法總數比已知宇宙中的原子數量還要多!這類問題可以被快速檢查,但是通過程序來解決的話則會花費時間太長以至不可接受,比如300年或者更多。
斯蒂芬·庫克和列昂尼德·萊文在1971年獨立地提出了P(即容易找到)和NP(即容易檢查)問題。
P 問題(easy to find)
all problems solvable, deterministically, in polynomial time
多項式時間內可解決的問題(當然在多項式時間是可驗證的)
NP 問題(easy to check)
non-deterministic Polynomial time
非確定性多項式時間可解決的問題
大家一定都對算法時間復雜度的大O表示法不陌生吧,簡單的來說,時間復雜度并不是表示一個程序解決問題需要花多少時間,而是當問題規模擴大后,程序需要的時間長度增長得有多快。
例如上圖所示,增長速度最快的左邊兩條線是非多項式級的,剩余的是多項式級別的。當我們在解決一個問題時,我們選擇的算法通常都需要是多項式級的復雜度,非多項式級的復雜度需要的時間太多,往往會超時,除非是數據規模非常小。
自然地,人們會想到一個問題:會不會所有的問題都可以找到復雜度為多項式級的算法呢?答案是否定的。有的問題甚至找不到正確的算法程序,例如大名鼎鼎的停機問題(The Halting Porblem,可以自行了解下)。
那么P問題與NP問題的關系呢?很顯然,所有的P類問題都是NP問題,多項式內被求解的問題一定在多項式時間內被驗證。那么所有NP類問題都是P類問題嘛,是否有P=NP這個問題已經困擾了科學家多年時間,不過大部分人還是認為兩者不等。雖然無法被證明,但是正是NPC問題的存在,使人們相信P≠NP。NPC問題可以理解為NP問題中最“難”的那一類問題。一個問題A可以約化為問題B,通俗地說就是問題B比問題A難,解決了B就能解決A。舉個簡單的例子,比如你有了二元一次方程的通解,那你一定能得到解決一元一次方程的通解,因為一元一次方程是二元一次方程二次系數為零的特殊情況。所以說,一個問題約化成另一個問題,所對應的時間復雜度相等或者增加了。
通過不斷的約化,能夠找到復雜度更高,但應用范圍更廣的算法來代替復雜度雖低,但只能用于很小一類問題的算法。神奇的事情來了!所有NP問題都可以約化為NPC問題,即如果NPC中任何一個問題能夠在多項式時間內找到最優解,則NP中的每個問題都能在多項式時間內找到最優解,即P=NP。遺憾的是,至今為止,對于NPC問題,目前沒有多項式的有效算法,只能用指數級甚至階乘級復雜度的算法。
QAP和NP
理解了P問題,NP問題以及NPC問題以后,大家回想一下之前所說的數獨游戲,本質上是一個NP問題,我們找不到一個多項式時間的算法可以算出數獨,但是給我數獨的解我立刻就可以判斷這個數獨的解對不對。同樣的,schnorr協議中的離散對數難題也是一個NP問題,給任意一個有限域上的整數 r,生成元G,我們就可以在循環群中找到一個對應的點 rG,但是反過來給你rG和G讓去找到r是一件很困難的事情,即相對應的,你很難找到schnorr協議里的私鑰,但是能很輕松去驗證如果有這個私鑰到底是不是正確的。
所以來說,需要證明的問題,肯定是NP問題,如果是P問題,不存在問題解的”尋找“,也就不存在證明。zkSNARK問題處理的都是NP問題。
那么問題又來了,我們有如此繁多的NP問題以及最難的NPC問題,我們如何構造一個通用的協議呢?
答案就是我們把任何NP或者NPC問題轉化為QAP的形式,而QAP satisfy problem(二次算數程序可滿足性問題)是一個NPC問題。簡單解釋QAP滿足性問題即,給一系列的多項式以及一個目標多項式,是否能根據這一系列的多項式,求得它們的一個線性組合,剛好可以整除多項式。即如下描述:
-
給定一系列多項式,目標
-
求一個線性組合,使得?,可記為
這個問題如果給出了一個解,那么驗證很簡單,直接除t(x)即可驗證是否滿足,但是想求解就很難。
zkSNARK的思路就是,將原問題的解轉化為一個QAP可滿足性問題的解,然后公開QAP問題,這樣的話擁有解的人用證明公開自己擁有一個解,其他人可以簡單驗證證明是否成立。
構建R1CS
“V神Vitalik Buterin,以太坊的創始人,是區塊鏈界真正的KOL,是和中本聰同樣偉大的存在,在他的博客里描述了如何一步一步構建QAP,接下來加上一些自己粗略的見解,帶大家了解整個過程的全貌。
首先,我們要把整個驗證過程用代碼的形式寫出來。比如說在數獨游戲中,不允許泄露的信息(即我們自己的答案)稱為私有輸入(secret input,有時也稱witness),而已經填好的數字我們叫公有輸入(public input)。我們不妨設私有輸入為,
共有輸入為,我們接下來要做的就是用代碼把約束寫出來,也就是每一行每一列和每一個9宮格都是1-9。當然這個例子需要大量的約束條件和代碼,我們不妨拿v神博客上簡單一些的例子來進行說明。
問題從V神的例子開始,對于方程?,顯然其解是3,我們(證明者)要向別人(驗證者)證明我們知道這個方程的解但是不能向對方透露這個解的知識。
首先,先把方程干的事情通過計算機代碼寫出來,就像下面這樣:
def qeval(x):
y = x**3
return x + y + 5
然后,我們把代碼拍平:
拍平后的代碼一次只能做下面的一種事情,x=y(x可以是數字或變量)。x=y op z(其中op可以是+,-,*,/等運算)
sym_1?=?x?*?x
y?=?sym_1?*?x
sym_2?=?y?+?x
~out?=?sym_2?+?5
在上面的過程中,我們引入了一些中間變量,但是整體跟我們的代碼是等價的。
接下來,我們需要把拍平的代碼寫成一個叫作R1CS(rank-1 constraint system)的東西。
R1CS 是一個由三向量組(a,b,c)組成的序列,R1CS 有個解向量s,s必須滿足運算s·a*s·b-s·c=0
表示向量的點積,向量的長度是系統里變量的個數,就像下面這樣:
在本例中其解向量的結構即為?
接著我們可以根據程序的第一個等式構造出:
a?=?[0,?1,?0,?0,?0,?0]
b?=?[0,?1,?0,?0,?0,?0]
c?=?[0,?0,?0,?1,?0,?0]
這實際上就是對程序第一行等式的另一種描述方式。
接下來是第二個等式:
a?=?[0,?0,?0,?1,?0,?0]
b?=?[0,?1,?0,?0,?0,?0]
c?=?[0,?0,?0,?0,?1,?0]
第三個等式:
a?=?[0,?1,?0,?0,?1,?0]
b?=?[1,?0,?0,?0,?0,?0]
c?=?[0,?0,?0,?0,?0,?1]
第四個等式:
a?=?[5,?0,?0,?0,?0,?1]
b?=?[1,?0,?0,?0,?0,?0]
c?=?[0,?0,?1,?0,?0,?0]
于是我們就得到了包含四個約束的R1CS,本質上就是對私密輸入,也就是我們的解向量??進行了約束。
把向量合在一起,我們就得到了完整的R1CS系統:
A
[0,?1,?0,?0,?0,?0]
[0,?0,?0,?1,?0,?0]
[0,?1,?0,?0,?1,?0]
[5,?0,?0,?0,?0,?1]
B
[0,?1,?0,?0,?0,?0]
[0,?1,?0,?0,?0,?0]
[1,?0,?0,?0,?0,?0]
[1,?0,?0,?0,?0,?0]
C
[0,?0,?0,?1,?0,?0]
[0,?0,?0,?0,?1,?0]
[0,?0,?0,?0,?0,?1]
[0,?0,?1,?0,?0,?0]
從R1CS到QAP
我們可以看到矩陣A,B,C,是一個4乘6的矩陣,我們把矩陣A的第一列拿出來用來構建多項式
選取4個點:
(1,0),(2,0),(3,0),(4,5)
然后求過這4個點的多項式,其中矩陣的值用來當成縱坐標,橫坐標我們用1,2,3,4來賦值。
可以得到多項式是?
構造多項式的過程可以使用拉格朗日插值法,或者FFT(快速傅里葉變換),總而言之,我們有四個點,于是可以得到含有四個系數的三次多項式。
然后我們如法炮制,可以得到剩下的多項式
A?polynomials
[-5.0,?9.166,?-5.0,?0.833]
[8.0,?-11.333,?5.0,?-0.666]
[0.0,?0.0,?0.0,?0.0]
[-6.0,?9.5,?-4.0,?0.5]
[4.0,?-7.0,?3.5,?-0.5]
[-1.0,?1.833,?-1.0,?0.166]
B?polynomials
[3.0,?-5.166,?2.5,?-0.333]
[-2.0,?5.166,?-2.5,?0.333]
[0.0,?0.0,?0.0,?0.0]
[0.0,?0.0,?0.0,?0.0]
[0.0,?0.0,?0.0,?0.0]
[0.0,?0.0,?0.0,?0.0]
C?polynomials
[0.0,?0.0,?0.0,?0.0]
[0.0,?0.0,?0.0,?0.0]
[-1.0,?1.833,?-1.0,?0.166]
[4.0,?-4.333,?1.5,?-0.166]
[-6.0,?9.5,?-4.0,?0.5]
[4.0,?-7.0,?3.5,?-0.5]
這時候神奇的事情發生了!我們把得到的18個多項式按照下圖的方式去排列,把代入多項式得到的值就是我們R1CS矩陣的第一列,得到的值就R1CS矩陣的第二列,得到的值就R1CS矩陣的第三列,根據R1CS的形式
,我們得到這一系列多項式的線性組合在的時候值為0,根據初中學的因式定理,也就是說這一系列多項式的線性組合可以提出因子,同理我們可以提出因子。
所以我們檢驗四個約束的方式變成檢驗在
是否成立,也就是檢驗這個線性組合的多項式有沒有因子。
所以我們意識到了我們通過多項式方式所做的操作本質是和R1CS在做同樣的事情,這二者是等價的。
這時候我們再看QAP滿足問題的描述,是不是發現不知不覺中我們已經把問題轉化完畢了,問題的描述如下:
-
給定一系列多項式,目標
-
求一個線性組合,使得?,可記為
其中,對應的就是我們解向量??的每一個值,也就是我們的私密輸入,對應的是
對應的是我們的,這個問題如果給出了一個解,也就是說我們知道了解向量??,
也只有正確的解向量??,才能使以它為系數的線性組合的多項式整除目標多項式。
至此為止,我們已經完成了構建QAP的全過程。
結? 語
這篇文章我們簡單闡述了計算復雜度中的P問題,NP問題以及NPC問題與QAP的關系,以及我們如何把一個復雜的問題轉換到zkSNARK能解決的形式QAP上,我們如何在這個基礎上繼續構造協議呢?我們后面繼續探討。
文章部分內容參考:
https://vitalik.ca/general/2016/12/10/qap.html
https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/
RECOMMEND
推薦閱讀
零知識證明系列之二——Schnorr協議
零知識證明系列之一——初探零知識證
Tips
更多長安鏈開源項目QA,可登錄開源社區、技術文檔庫查看。
下載源碼
https://git.chainmaker.org.cn/chainmaker/chainmaker-go
查閱文檔
https://docs.chainmaker.org.cn/
長安鏈ChainMaker案例征集
http://www.wenjuan.com/s/UZBZJvhFGte/
“長安鏈ChainMaker”是國內首個自主可控區塊鏈軟硬件技術體系,由微芯研究院聯合頭部企業和高校共同研發,具有全自主、高性能、強隱私、廣協作的突出特點。長安鏈面向大規模節點組網、高交易處理性能、強數據安全隱私等下一代區塊鏈技術需求,融合區塊鏈專用加速芯片硬件和可裝配底層軟件平臺,為構建高性能、高可信、高安全的數字基礎設施提供新的解決方案,為長安鏈生態聯盟提供強有力的區塊鏈技術支撐。取名“長安鏈”,喻意“長治久安、再創輝煌、鏈接世界“
總結
以上是生活随笔為你收集整理的零知识证明系列之三——入门zkSNARK的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt利用openGL绘制三棱锥
- 下一篇: (ssl1960)2009年东莞市信息学