Zcash算是區塊鏈目前發展中隱私性做的最徹底的系統
本篇文章會先講解Zcash的交易結構,驗證交易是否合法的抽象觀念,盡量解釋怎麼產生一個private transaction,以及礦工驗證private transaction的一些原理。
因為Zcash本身是來自bitcoin專案,故相關內容可能會隱含到UTXO相關知識
交易結構與地址種類
上圖是一個Zcash交易在網路中的抽象概念圖,其中,Shielded address
表示的是這種地址是具有隱私性的,通常以字母z
開頭,或稱z-addrs
,一個交易的送方可以是z-addr同時收方也是一個z-addr,而其他的交易資訊,如送的ZEC數量與收的ZEC數量同時都可以遮蔽保有隱私性,而證明某個地址的確保有某個utxo的所有權並可交易,則需要透過密碼學的zero-knowledge proof
的方式產生一個證明,並且此種零知識證明具有non-interactive的性質,亦即任意public verifier皆可自行驗證某個prover有權花費某個utxo
這件事的真偽,我們將在後面的篇章詳談細節。
同樣的,Zcash中也可以傳送一般訊息透明的交易,其中資訊公開的地址常為t
開頭,稱t-addrs
或Transparent addresses
,而這些透明的地址在產生交易時,需要與Transparent Value Pool(TVP)
互動,並且產生公開的交易資料。
交易手續費將永遠是公開的,故一個Zcash transaction本身可以包含隱私的地址、公開的地址、隱私的ZEC數量、公開的ZEC數量、公開的手續費等資料。
我們可以在blockchain explorer看到這樣的例子
在其他UTXO架構的區塊鏈,因為一個交易的送方和收方地址都是公開的,故常常找零地址會為了要做混淆保持匿名性,所以每一個交易會產生一個新的找零地址,但在Zcash中,因為z-addrs本身就是保有隱私性的地址,故重複使用這些地址當作找零地址並不會有任何弱點問題。
交易隱私性的種類
由上一個章節可以知道地址分成公開的t-addrs和隱私的z-addrs,排列組合即可造就幾種不同隱私等級的交易:
- Public
- Shielding
- Deshielding
- Private
Public
此種交易的交易收送方和金額都是公開的,與bitcoin相同,可以說是沒有任何隱私性,只有區塊鏈自有的匿名性
Shielding
若由公開地址將完整將金額送給另一個隱私地址,則這樣的交易其實就算收方地址和收取的金額是具有隱私性的,但因為送方的資料是公開的,故其實已經泄露的交易金額的資訊,所以這種交易只有斷開未來相關交易地址的linkability (連結性)
,但若收方地址有多個隱私地址,則可能是送方自己的隱私找零地址,故依然無法猜測真的收方到底收到了多少錢,只有一個可猜測的金額範圍。
如此例
Deshielding
將會公開原本的隱私金額資料,但由於交易送方是z-addr,因此也無法透過UTXO的特性往貨幣的上游追蹤。
Private
什麼都看不到,跟國防布一樣
Private交易
Private交易的資料庫觀念
每一個未花掉的UTXOs可以想成是一個擁有者的public key和BTC數量的note
,為了簡單說明概念,假設每個note表示1BTC,並且每一個note都有個隨機的序列號r
,則一個未花費的UTXO資料庫可以表示為:
Note1 = (PK1, r1) | Note2 = (PK2, r2) | Note3 = (𝖯𝖪3, r3) |
---|
則要做到隱私的第一步則是,完整節點不直接儲存這些note資料而是儲存note的密文或hash value。
H1 = HASH(Note1) | H2 = HASH(Note2) | H3 = HASH(Note3) |
---|
要做到隱私的第二步是這個資料庫會保存這些hash,即使某個UTXO已經被花掉了,那麼,現在這個資料庫就不是只記錄尚未花掉的UTXO了,而是所有產生的UTXO都要保留,那麼要如何分辨哪些已經花掉,哪些沒花掉呢?這時候就會用到nullifier set
,記錄哪些note的序列號的r之hash value,表示某個note已經被使用掉了,舉例,當note2被使用掉之後,現在note資料庫應該如下表:
HASHED NOTES | NULLIFIER SET |
---|---|
H1 = HASH(Note1) | nf1 = HASH(r2) |
H2 = HASH(Note2) | |
H3 = HASH(Note3) |
產生一個Private交易
假設Alice擁有note1,想要交易給Bob,Bob的公鑰是PK4,在先不解釋太多密碼學的前提下,先假設Alice和Bob之間有個私有通道可以直接溝通,則一個交易會如下步驟執行:
- Alice隨機挑選一個
r4
,並定義新的Note4=(PK4, r4)
- Alice透過私有通道傳送Note4給Bob
- Alice傳送Note1的nullifier,
nf2=HASH(r1)
給所有完整節點 - Alice傳送Note4的hash value,
H4=HASH(Note4)
給所有完整節點
當每個完整節點接收到nf2
和H4
,會檢查nf2
是不是在nullifier set中,若不存在,則將nf2
加到nullifier set中,並將H4
加到hashed notes中,故經過Alice和Bob此次交易後,note資料庫如下表:
HASHED NOTES | NULLIFIER SET |
---|---|
H1 = HASH(Note1) | nf1 = HASH(r2) |
H2 = HASH(Note2) | nf2 = HASH(𝗋1) |
H3 = HASH(Note3) | |
H4 = HASH(Note4) |
But!完整節點檢查了note1之前有沒有被花掉,但我們並沒有檢查它是不是屬於Alice的,甚至,我們根本沒檢查它是不是一個合法的note,如何檢查它是不是一個合法的note,只要完整節點將note1做hash並與hashed notes列表比較,是不是存在此hash value即可,但這會要求Alice廣播note1給所有完整節點,這就違反了我們想達到的隱私。
是時候讓Zero-Knowledge proofs來拯救了!
Zero-Knowledge proofs
經過上述的情境,我們可以知道,條件是要在不洩漏note1詳細資料等隱私的情況下,提出一個proof string,稱π
,給所有完整節點,並單靠這個π
就能說服所有的public verifier,任何能廣播π
的人,他的確知道PK1(公鑰)
, SK1(私鑰)
和r1(note1對應的序列號)
,且能夠使得:
Note1=(PK1, r1)
之hash value,存在hashed notes中SK1
是對應PK1
的私鑰(任何能證明自己有私鑰的人,就證明了有Note1的所有權)r1
的hash value是nf2
(由此可知,nf2
是Note1的nullifier,並且nf2
尚未在nullifier set中,所以Note1還沒被花掉)
這個零知識證明π
還有個最重要的特性,保證不會洩漏任何關於PK1
, SK1
和r1
的資訊。
以上是Zcash在private transaction上非常簡化的說明,為的是先建立讀者對零知識證明的需求從何而來的導讀,中間有很多事情在實際上更為嚴謹,如:
- hashed notes實際上並不是一個list,而是以Merkle tree的形式組織的,為的是更有效的建立Zero-Knowledge proofs,
π
,更進一步,我們還要儲存note對應的computationally hiding
和binding commitment
,而不是只儲存note對應的hash - nullifier需要被定義的更複雜,為了保障接收方與送方的隱私
- 此處並沒有提到如何消除Alice和Bob之間建立隱私通道的需求
我們將在後續介紹整個zkSNARKs
時,一一解答。