2017年12月8日 星期五

比特幣交易所100%準備金驗證方案

比特幣交易所100%準備金驗證方案

摘要
就發展趨勢而言,交易所和提供錢包服務的網站如果僅僅持有客戶比特幣數量的一小部分,將遭到質疑,難以取得客戶信任;那麼對於客戶來說,能夠對提供服務的網站實際擁有比特幣數量進行驗證,將變得非常重要。使用基於Merkle Tree的技術,理論上可以在不必洩露過多客戶資訊的情況下,十分直接明瞭地實現這個目的。儘管存在一些現實的注意事項和需要顧及的限制條件,我們所描述的這個系統依賴于客戶有多麼的耐心和細緻。這個特點的存在並不影響這套系統的使用。
建議:任何時候都不要把您的幣置於協力廠商控制之下。
大綱
恕我將這些都羅列在下面
·  
·   簡單扁平化的帳戶列表
·   利用Merkle樹方法驗證資產負債表
o    特性(程式)
o    細節
o    一般關注點和容易出錯之處
o    落實
·   資產證明
·   一個能夠提供審計的交易所或錢包網站調查表
u
據我瞭解,這類似於博彩網站正在將盡可能地將公平賭博作為一個運營標準。如果這個能夠成為客戶拒絕沒有該種服務交易所的標準,難道不是件好事嗎?考慮一下吧,如果你向你的交易所詢問是否提供此類服務,你的交易所將怎麼有臉向你保證說他們備有規定數量的小部分保證金?
執行任何保護措施的副作用是客戶們在某種程度上有了更大的安全保證:交易所偶爾地核對一下帳目。如果帳號被一些節點或者帳戶執行BUG所擺脫,那樣做將是重要的。例如當某一未知方故意提交巨大數量的交易變異版本時,委託用戶端會發生BUG
本頁是一份還在進行中的工作,文檔來來去去,相互矛盾的一份份聲明,直到一切都確定下來。在這裡,“交易所”這個詞包括任何代你持幣的機構,例如線上錢包、博彩網站、協力廠商交易網站以及可能的其他類型。而“邪惡交易所這個詞指那些儲備了比規定的數量更少的準備金的交易機構。

u 簡單扁平化的帳戶列表
如果一個交易所的用戶被告知並接受了隱私條款,如果這種溝通是充分的,那麼客戶的數量和他們的帳戶餘額資訊既不涉及商業敏感資訊也不會成為安全風險,交易所可以為每個帳戶的餘額出一份扁平化的列表。
最大程度保護隱私而不使操作複雜化,交易所可以為每個帳戶(在下面對Merkle的說明中解釋對“登錄”和“臨時字串”的幾點考慮)列出帳戶餘額,HASH(登錄.臨時字串)
就下面的Merkle描述而言,被標記的清單應該在這樣一種情況下被發表:即在使用者能夠確認,針對同一條資訊他們自己全部核查了他們的帳戶,即使交易所是失律的。

u 證明負債的Merkle方法
時間表
·   2013-03-01Greg Maxwell and Peter Todd討論問題和解決方案(從這裡開始“<@petertodd>好了,目標就是: 一個針對可審計的斷鏈交易的程式庫.”
·   2013-05-08:我瞭解到Greg Maxwell的想法並發表了文字稿
·   2013-05-18Peter Todd2013年比特幣大會的一個座談中描述了這個想法
·   2014-02mtgox公司停止提現,引發了對償付能力可證性的熱議。
所有的錯誤歸於我。

u Merkle樹方法的特性
目標:清楚地勾勒出Merkle方法能夠或者不能做什麼,使誤解最小化。
這個特點的存在並不影響這套系統的使用。
建議:任何時候都不要把您的幣置於協力廠商控制之下。
這個系統在以下情形下奏效:相當大比例的用戶會定期進行被平臺授權進行的核查。
這個系統不會為使用者與嚴重失律的交易所之間產生的爭議提供可證實的公開投訴。這個系統僅為你提供一個方法測試你對交易所償付能力和負責任程度(正如他們在公共宣傳中承諾的)的信任,如果數值上有差異,這個方法讓你有充分資訊來決定是否繼續使用該交易所的服務。
這個系統將使盜竊和騙局無處遁形,這個系統不能保護交易所免於失竊,也不會縱容一個邪惡的交易所擅自挪用客戶資金。
一個嚴重失律的交易所不會同時告訴你它曾保管你的貨幣但是卻從資產負債表上抹去了它們。反之,它會否認你曾經存入那些貨幣,並告訴你無所謂真假,因為沒有辦法證明。然而,如果一個嚴重失律的交易所告訴你他們曾經持有你100BTC,但是在資產負債表上,它們變成了50個,或者0個,或者乾脆假裝他們不認識你,你就可以根據這套系統,發起一個能夠被證實的投訴。

u Merkle 樹方法詳解
(參見 網路即時聊天記錄的 脫水精簡版 以及 完整詳解版,僅僅閱讀下面的描述也是非常有用的)
假設用戶使用他們的郵箱作為唯一ID(這樣ID出現衝突的情況非常少),那麼使用者資料表如下圖所示:
每個使用者再給多一個隨機臨時字串。(為了使示例儘量簡化,此處只用了一個很簡短的臨時字串,實際操作可用長字串)
E-mail
Balance
Nonce (hex)
3333
ab00
gavin@example.com
1
40ed
pieter@example.com
42
b569
nils@example.com
0
70d1
jeff@example.com
50
457a
wladimir@example.com
600
3fb3
2.718282
33ad
用戶的hash值(新建一個Nonce欄位)通過串聯表的各個欄位進行計算。為了使圖解更加明瞭,這裡我把所有輸入都字串化了,而且只取前四個字元作為結果,例如:
hexstr(
    firstfourbytes(
        sha256(
            concat( str(e-mail), str(balance), hexstr(nonce) )
        ) ))
所以,第一個用戶的hash值計算為:
hexstr( firstfourbytes( sha256( "satoshi@example.com3333ab00" ))) = e4fd9d12
(在真實的實現中,計算hash的函數,可能會輸入balance以及nonce的二進位值,而且還會在每個欄位中插入分割符來消除重複,以防止“邪惡的交易所”用同一個結點代表多個用戶。這裡我沒有用分割符,因為我不得不重新畫圖。)
E-mail
Balance
Nonce(hex)
Hash
3333
ab00
e4fd9d12
gavin@example.com
1
40ed
60248b27
pieter@example.com
42
b569
174c7c2d
nils@example.com
0
70d1
12aceafd
jeff@example.com
50
457a
e1bb96c1
wladimir@example.com
600
3fb3
a2cec836
greg@example.com
2.718282
33ad
ab50f328
接著帳號就被當作子葉結點插入到二叉樹裡面,而且被一些不完整的內部結點連接起來。樹可以用任意的形狀或者用戶所在的位置來構建,然而如果樹是平衡的那麼任意一個用戶都可以粗略地估算到總用戶數量。

更裡面一層的結點值通過外面一層的結點值計算而來。重申一次,為了簡單明瞭,我對各種計算用到的值進行了字串化/簡化/截取。最左邊的一對子結點可以像下面這樣計算:
parent.sum = left.sum + right.sum = 2.718282 + 1 = 3.718282
parent.hash = firstfourbytes( sha256( concat( str(parent.sum), hexstr(left.hash), hexstr(right.hash) )))
= firstfourbytes( sha256( "3.718282ab50f32860248b27" ))
= firstfourbytes( 4fdd5968686c6a8f68b10579fbeaefcbde45d4fe8b0023861e937fc95daaeb11 )
                = 4fdd5968
把所有結點連接起來後:

在這個微型的例子裡,路徑—>總帳 的公佈方法幾乎和直接公開使用者清單那樣,需要提供詳盡的資料,但是這種方法更加隱密、可以更加少地公佈商業資訊。這種路徑—>總帳 的方式需要公開資料量的增長速度也沒有直接公開用戶列表那麼快。如果Satoshi(餘額 3333)要驗證交易所的總帳,那麼交易所只需要抽取樹的下面部分內容即可:

實際上,交易所只需要給Satoshi提供他自己的隨機臨時值,以及那些標粗體的節點即可驗證總帳;其它節點的資料應該(而且也可以)在檢查時,通過用戶自己提供或者計算得來,這是非常緊湊簡潔的。我的Clojure實現以及OlivierJS實現在這裡:傳送門
為了保證邪惡的交易所不會用相同的一個節點來代表兩個餘額一樣的用戶(例如,給他們相同的 路徑—>總帳 ),每個子葉節點hash值的計算應該包含只屬於某個用戶的特定輸入值。這可能是使每個用戶差異最大化的最好選擇。如果使用的是用戶的ID,那麼交易所可能賦予多個用戶相同的ID值,這是不理想的。如果使用登陸名的話,邪惡的交易所可能會減少衝突。
為了保證每個用戶都不可以從他們自己的 路徑—>總帳 裡面推導出其它節點的資訊,每個子葉節點的hash值都應該包括一個臨時隨機值nonce作為輸入,這個隨機值只有交易所和某個用戶自己知道。否則,用戶可能會結合他猜測到的餘額以及他知道(或猜測到)的用戶唯一值,並把這兩個值聯合一起,進行資料跟蹤。提供了這個臨時隨機值已經足夠了,用戶的唯一輸入(指用來計算總帳的唯一值)可以公開。每次公佈資產負債報表時,每個使用者的隨機臨時值nonce都要重新生成一次。
如果hash值不改變的話,邪惡的交易所可能會玩類似“用戶配對”的小把戲,把兩個相鄰的子葉節點進行位置交換。每個子葉節點的hash值應當包括用戶的餘額,如上所述,或者內部節點的hash應當包括孩子結點的餘額(不是總餘額)。如果hash值的計算不受這個條件的約束,那麼邪惡的交易所會對兩個餘額相同的用戶匹配成相鄰的一組,並且給他們提供不同版本的樹,例如,假設:
·   左邊子葉的hash是: crc32( join("|", name, nonce ) )
·   裡面hash的輸入 是: crc32( join("|", str(left.sum + right.sum), hexstr(left.hash), hexstr(right.hash) ) )
·   總共只有兩個用戶:
o    用戶 tyler  nonce “turtle” ,餘額是100
o    用戶cameron  nonce“canary” 餘額是100
邪惡交易所給 tyler 的驗證樹:
·   : sum: 100; hash: crc32( join(“|”, str(100 + 0), “01C29E82”, “5A486B26” )) = crc32( “100|01C29E82|5A486B26” ) = F38E7221
o    (you): sum: 100; hash: crc32( “tyler|turtle” ) = 01C29E82
o    : sum: 0; hash: crc32( “cameron|canary” ) = 5A486B26
同時交易所給cameron這樣的驗證樹幹:
·   : sum: 100; hash: crc32( join(“|”, str(0 + 100), “01C29E82”, “5A486B26” )) = crc32( “100|01C29E82|5A486B26” ) = F38E7221
o    : sum: 0; hash: crc32( “tyler|turtle” ) = 01C29E82
o    (you): sum: 100; hash: crc32( “cameron|canary” ) = 5A486B26
兩個用戶都確定了他們在資產負債樹裡面的餘額(兩人總共有200),但是交易所只需要證明他的資產值是100就可以了。
每次交易所公佈資產負債hashroot樹時,用戶都想最做最詳盡地檢查(如檢查未公佈負債的機會)。同時,用戶希望交易所更加頻繁地進行披露,以使邪惡的交易所在兩次公佈資產負債的時間段內,挪用資產變得不實際。邪惡交易所會最小化所需要檢查的內容,而且僅僅公佈最近的一次hashroot。在實踐中,可能這些因素需要結合在一起,找到一個合適的公佈間隔,如一天、一周或者一個月。理論上講,一個負債的交易所應當簽署並發佈所有歷史公佈的hashroot,而且會郵件通知每個客戶他們自己的 路徑—>總帳,一個真正好的用戶收到郵件後也應該作相應地檢查,每次都不會遺漏交易所公佈的資料。
邪惡的交易所可能會提供一個唯一的,編織好的路徑—>總帳給每個使用者,唯一一個真實的節點就是用戶自己的子葉結點,而剩餘的整顆樹都未經證實。一個有責任的交易所會通過一個事前約定的途徑,公佈出hashroot,確保所有用戶看到的都是相同的視圖。一種交易所可能採取的方法是:每次在公佈時,發送一筆轉帳到某個位址上,這個地上是事先約定使用的,這一筆轉帳包含了OP_RETURNoutputoutput攜帶了已經簽名的hashroot。(這個output會被普遍地認為在浪費公共資源,但是這並不十分重要;而且還有其它的方法實現相同的結果。)
Greg Maxwell指出使用合適的技術,去實現“零洩露資訊作零知識證明”的協議是可能的,儘管本質上說實現起來會非常複雜。(如果你也在做同樣的事情,或許你應該聯繫Greg,因為他知道怎樣在零知識證明外保持ECDSA驗證)。
常見關注點及紕漏
目的:對最常見的難道交易所不能......”進行反駁以及提出並非顯而易見但會削弱它的實現細節。

現在:我看到最多的擔心就是交易所錯誤地將隱匿的帳戶餘額清零(而這些帳戶的所有者不會核查)以及提供負額的虛假帳戶以掩蓋事實;gmaxwellHN (123) Reddit的討論中提出了這個問題.

現有的代碼實現

Python
l  Nick/ OnTheMargin / ConceptPending / CryptX.io實現方案
JavaScript:
l Olivier Lalonde實現方案 (同時打包在npmjs.org ),置於一個更大的證明償付能力的框架 Olivier還提出了一個(未完成) 序列化格式 ,它將使出版商/檢查器之間的互通性變得更容易,並共用測試。
l ConceptPending實現方案現在還包括在JS用戶端驗證代碼(以及原始的Python)。
Clojure
l  我的方案 是接受accounts.json序列化格式的一部分,和目前僅實現的創造出完整的Merkle樹的功能。
C++:
l   Kraken實現方案
Ruby
l   Jan Han Xie開源引擎/交易所實現方案peat.io


證明資產的所有權

直截了當的做法就是對所有私密金鑰的所有權發表聲明。Olivier Lalonde寫了一個這樣的實行方案。大家會希望這份聲明包含著最新的資訊,以證明簽名是最近作出的及保證簽名不是在丟失私密金鑰的冷儲存期被提前生成;更理想的是能顯示出最後塊鏈高度和HASH值。用戶會去驗證那個簽名,以及驗證聲明中所說明的總債務可以由所有私密金鑰中可花出去的總幣值相等。
大多數交易熱錢包可能已經做著一些私密金鑰“消息簽名”的事了,所以不管怎樣都可以做得更加好一點:證明客戶提現時用的私密金鑰(所有私密金鑰的子集)和交易所進行“消息簽名”時用的私密金鑰是一樣的。
這可能造成一種“簽名即服務”的攻擊,如果一個邪惡的交易所付費給某個用戶,而這個用戶(比如說是文克萊沃斯兄弟)擁有大量的幣(數量達到了交易所聲明的那麼多),讓這個用戶來進行私密金鑰簽名。交易所並沒有擁有那些幣,或者只擁有其中的某一部分。
不管怎樣,仍然可能有很多看似很精美(或許不切實際的)協議可以直接地排它性地證明私密金鑰的所有權,也會有證明所有權後馬上把私密金鑰歸還給別人的情況出現。因為這並不可以說明交易所願意歸還那些幣,僅當如果它想歸還時候它才會歸還——當最近一次的證明結果取得成功後,永遠不可能防止交易所隱藏幣(比如以文克萊沃斯兄弟做交易為結局)。
最後,這裡有一個十分簡單的方法給交易所,讓交易所既可以也願意歸還所聲明的幣:一次性把幣歸還給用戶。如果不暫停交易所業務的話,這是做不到的。。但是仍然可以把所有幣一次性發送到提前準備好“1/2”的委託付款地址(應該是指多重簽名位址),交易所持有其中一個私密金鑰,客戶持有另一個私密金鑰。交易所需要等待交易達到一定的確認數量,如果此時用戶又把幣消費了出去,這就相當於另一種形式的提現;否則的話,這些幣最終會打到交易所的熱錢包。這可能會和某些交易所強加限制的每日提現數量的做法有衝突(這些做法可能是為了符合一些反洗錢條款),儘管如此,大筆的存入虛擬貨幣還是可以的。

誰在用這樣的準備金證明?

BitcoinityComboy鼓勵人們叫交易所提供這種證明。他們也提供用他的即時圖表進行免費推廣的獎金。(以取代現有的“這個地方正在等待一些重大交易”的推廣方式)。
Bifubao(幣付寶) :這個中國錢包網站(經典的共用錢包網站)的一個創始人在電子郵件中說,他們將在短期內使用Merkle樹的方法;可惜我不會說/閱讀中文,不能檢查他們的錢包,但他們有一些開源的代碼 來產生並檢查他們的樹。他們將用signmessage來證明資產,但只限于冷錢包(至少是個開始)。
Bitalo表示,他們的多重簽名就意味著你不需要這個證明了;我還沒有看過這個東西,但以多重簽名為基礎的錢包就意味著你擁有兩個金鑰,錢包網站擁有第三個,而所有的交易都需要三個金鑰中的兩個才能完成。最直接的實現方式就是讓你驗證他們是否真的保有你的資產。
BitBargain.co.uk  201435日起,BitBargain.co.uk提供了一個扁平化的列表匿名負債聲明,並用signmessage來證明相對應的熱/冷錢包中的資產控制 該聲明只有賣家知道——這裡最大的貨幣持有者—— 但買家可以詢問任何賣家以確認他們的餘額是否在負債列表中。BitBargain公開主動阻止用戶們不要把貨幣放在網站上,過後只收取買家(據說是非常少的)一筆保管費。
BitGo似乎在使用像Bitalo一樣的三選二系統。
BitPayjgarzik201434日說“作為一個支付系統而不是一個錢包,BitPay儘快地完成支付,力求零儲備。BitPay真的不希望長時間持有現金或者比特幣。對於美元 ,我們在24小時內完成支付,有時候更快。而對於比特幣也是一樣。我們最多持有資金幾個小時。
Bitstamp  2014-02-25 Bitstamp“他們正在執行季度的財務審計而且會在官方網站上公佈出來。” 20140306日,Bitstamp發了一個聲明說,三個月多以前(2013112223號),一個匿名的協力廠商公司給他們做過一次審計,沒有發現問題。但是既然他們沒有公佈這個協力廠商審計公司的名稱,用戶也不能決定他們是不是要相信這個審計者以及審計報告。如果FirestartrBitstamp的合夥人)的聲明是通過一個可證明的方式簽署,如果你有理由相信Firestartr,這或許有點價值;否則的話,這根本就不意味著什麼。
Bittylicious.co.uk 201434號說“暫時還沒有具體的方案,但是如果出現某種最好的方案,我們肯定會考慮的。”他們又補充到,虛擬貨幣僅以銷售者的名義保存在網站上,我們並不是一個一般意義上的錢包網站。
BitX:請從根本上相信我們:“我們樂意保證BITX完全妥善保管所有使用者的全部資產”好吧,焦急的GOX客戶曾被客服在224告訴說你們的幣是安全的18日,個別管理人員也這樣說過
Buttercoin: Benn Hoffman我們也想辦法制定出具體細節來保證我們持有的數量與客戶的儲幣(至少是提現)數量相等,而且必須在保證客戶隱私的前提下實現。同時指出對MERKLE方法的關注(“主要在於明白如何整合和有充足的時間去實現”)
Coinbase:決定開展現貨外部審計;我們不能忍受與mtgox發邀請給 Roger Ver(比特幣天使投資人)一樣的行為,我沒有理由不相信Andreas Antonopoulosblockchain首席安全官),但是我也沒有理由相信他。如果我是一名Coinbase的用戶或者計畫成為一名coinbase的用戶,這並不能讓我放心交易。
Coinfloor.co.uk自稱,”Coinfloor的系統在冷錢包內持有100%的資金,並且每筆提現會有3個工作人員經手進行多重認證。我們的規則將會防止任何惡意提現,避免客戶資金受到損失。同時也包括防止內外部盜竊以及對私匙的不當操作和強制多態。這裡似乎沒有告訴你什麼有用的東西(是100%準備金,還是僅持有小部分準備金?儘管使用了規則這個詞,我認為防止意味著“阻止”,而不是保證你可以免受損失。)以上他們所的並不意味著你可以驗證交易所的資產和負債,因此我認為這就相當於說請相信我們(正如GOX說過的那樣)。正是這樣的宣稱提前引爆了GOX的償付危機, 也許Coinfloor還會再來一次。
Coinkite宣稱可以某種程度上讓你驗證自己帳戶上的餘額;大概他們可以重複使用位址,然後每個用戶有一個位址,讓你可以按要求地標記資訊。我不是他們的用戶,也許不能進行有效的測試,也不能進行深入地瞭解,請自行閱讀他們的使用說明
Coinsetter表達了對Merkle方法的異議。它們說我們感覺這個方式是有局限性的。例如這套方法能夠辨識欺詐帳戶,但是它不能將帳戶餘額和實際的資產聯繫起來。他們從社區尋求解決和落實的辦法。起初我以為他們反對的理由是由於“可替代性,但是我確信我可能忽略了什麼。
CryptX.io has said it will launch with support for the Merkle approach and has provided an implementation in Python.
Cryptx.io說他們將著手支持MERKLE方法,並提供了使用Python語言的實現方案.
FYBSE:它的回應是令人失望的:”如果有任何疑問,請給我們郵件。請忽略這個所謂的承諾,正如上述對BITX說過的,焦急的GOX客戶曾收到客服在224日的答覆“幣是安全的”,18日,管理人員也這樣說過
Justcoin看起來是有興趣但是沒有表態
Just-Dicedooglus通過公佈所有帳號餘額列表,我已經證明了我們的償付能力。但是他們似乎對更好保護客戶隱私的MERKLE方法也有一定興趣。
Kraken:jesse回應他們不認為MERKLE方法的透明性比交易的隱私性更有價值,說他們更喜歡外部審計(我不能確定用什麼方法審計)。他還明確地說他們將嚴格隔離用戶資金。也就是說他們不混雜在一起。
peat.io  (測試中)2014318日落實MERKLE的債務保全。
Trustedcoin好像使用了三選二系統,與Bitalo/BitGo一樣。

要做的事情

·   關於隱藏負值餘額
o    延伸至何處將是個問題
o    傳送未經請求的證據的重要性
o    針對樹圖隨機化的准公平化證據的應對措施(我希望對於交易所隨機實施一個佈局而言,這是一個辦法,對於需要驗證的使用者而言,他們的節點被隨機分佈,進而交易所才會真正努力去錯誤地使潛在帳戶歸零,但是我還沒有得出結論)
·   在示例中使用CRC32(更容易閱讀,更清楚的一個科技專利)並且再次呈現圖表
·   複審更多的實現方案
·   包括來自於olalonde的長篇提案
·   複審更多的用途
·   更新測量
·   使no-balance-in-leaf-hash pairing圖表化
·   拓展分離器的需求
·   使olalonde的測試資料傻瓜化/能使用畫圖工具/根莖化




沒有留言:

張貼留言