Zcash基本原理

Posted by Benjamin Lu on 2017-09-07

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-addrsTransparent addresses,而這些透明的地址在產生交易時,需要與Transparent Value Pool(TVP)互動,並且產生公開的交易資料。

交易手續費將永遠是公開的,故一個Zcash transaction本身可以包含隱私的地址、公開的地址、隱私的ZEC數量、公開的ZEC數量、公開的手續費等資料。

我們可以在blockchain explorer看到這樣的例子

在其他UTXO架構的區塊鏈,因為一個交易的送方和收方地址都是公開的,故常常找零地址會為了要做混淆保持匿名性,所以每一個交易會產生一個新的找零地址,但在Zcash中,因為z-addrs本身就是保有隱私性的地址,故重複使用這些地址當作找零地址並不會有任何弱點問題。

交易隱私性的種類

交易隱私性

由上一個章節可以知道地址分成公開的t-addrs和隱私的z-addrs,排列組合即可造就幾種不同隱私等級的交易:

  1. Public
  2. Shielding
  3. Deshielding
  4. 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之間有個私有通道可以直接溝通,則一個交易會如下步驟執行:

  1. Alice隨機挑選一個r4,並定義新的Note4=(PK4, r4)
  2. Alice透過私有通道傳送Note4給Bob
  3. Alice傳送Note1的nullifier,nf2=HASH(r1)給所有完整節點
  4. Alice傳送Note4的hash value,H4=HASH(Note4)給所有完整節點

當每個完整節點接收到nf2H4,會檢查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對應的序列號),且能夠使得:

  1. Note1=(PK1, r1)之hash value,存在hashed notes中
  2. SK1是對應PK1的私鑰(任何能證明自己有私鑰的人,就證明了有Note1的所有權)
  3. r1的hash value是nf2(由此可知,nf2是Note1的nullifier,並且nf2尚未在nullifier set中,所以Note1還沒被花掉)

這個零知識證明π還有個最重要的特性,保證不會洩漏任何關於PK1, SK1r1的資訊。

以上是Zcash在private transaction上非常簡化的說明,為的是先建立讀者對零知識證明的需求從何而來的導讀,中間有很多事情在實際上更為嚴謹,如:

  1. hashed notes實際上並不是一個list,而是以Merkle tree的形式組織的,為的是更有效的建立Zero-Knowledge proofs,π,更進一步,我們還要儲存note對應的computationally hidingbinding commitment,而不是只儲存note對應的hash
  2. nullifier需要被定義的更複雜,為了保障接收方與送方的隱私
  3. 此處並沒有提到如何消除Alice和Bob之間建立隱私通道的需求

我們將在後續介紹整個zkSNARKs時,一一解答。