我們都知道我們看到的比特幣現(xiàn)金的余額其實(shí)都來(lái)自于UTXO,即未花費(fèi)的交易輸出。正是因?yàn)椴捎昧薝TXO才讓我們的交易全部都記錄在區(qū)塊鏈上,保證了去中心化。
基于此,一個(gè)名為T(mén)omas 的人提出了UTXO證明。他認(rèn)為使用UTXO證明可以允許完整節(jié)點(diǎn)的快速同步,因?yàn)橥暾?jié)點(diǎn)可以下載UTXO集而不是歷史區(qū)塊,而且不會(huì)降低安全性。昨天,他在社交平臺(tái)上Yours上發(fā)布文章表示在BCH測(cè)試網(wǎng)上出現(xiàn)第一個(gè)UTXO證明。以下是此文的譯文。
如果你仔細(xì)檢查了BCH測(cè)試網(wǎng)上的每一個(gè)區(qū)塊,你可能會(huì)注意到一個(gè)奇怪的現(xiàn)象。在區(qū)塊1237565中,coinbase的交易包含一個(gè)額外的輸出:
OP_RETURN [5554583011007bc4426b03824ccca5912bb147bd9f6847b670a08f24b79a4b5ed0b36393]
這個(gè)元數(shù)據(jù)就是UTXO證明,它目前正在比特幣現(xiàn)金網(wǎng)絡(luò)中被開(kāi)發(fā)。讓我們看看它是如何工作的。
快速同步節(jié)點(diǎn)
目前新的完整節(jié)點(diǎn)需要下載整個(gè)歷史區(qū)塊。這不僅會(huì)在初始設(shè)置中引起煩人的延遲,而且還會(huì)導(dǎo)致現(xiàn)有節(jié)點(diǎn)負(fù)擔(dān)過(guò)重,以至于需要花很大一部分帶寬來(lái)為這些舊的區(qū)塊服務(wù)。
為什么完整節(jié)點(diǎn)需要這些?他們并沒(méi)有實(shí)際驗(yàn)證這些區(qū)塊。大多數(shù)implementations都包含一個(gè)名為“assumevalid”的參數(shù),其中包含一個(gè)硬編碼的默認(rèn)值:
這并沒(méi)有像聽(tīng)起來(lái)那樣可信。當(dāng)你去驗(yàn)證這些區(qū)塊的時(shí)候,你將會(huì)根據(jù)軟件中寫(xiě)入的規(guī)則進(jìn)行驗(yàn)證。所有這些被聲明的硬編碼值都是假定有效的,因此這些區(qū)塊都將遵循同樣軟件中編程的規(guī)則。這只是一個(gè)“預(yù)編譯驗(yàn)證”,不會(huì)增加信任或降低安全性。
這些完整節(jié)點(diǎn)需要整個(gè)歷史區(qū)塊的唯一原因是啟動(dòng)他們的記賬本。因?yàn)闉榱蓑?yàn)證傳入的交易和區(qū)塊,他們必須知道哪些交易的輸出目前未用完。他們必須創(chuàng)建一個(gè)未使用的交易輸出集或UTXO集。生成此集合需要他們?yōu)g覽所有的區(qū)塊收集所有的輸出,并去掉輸入所消耗的輸出。
如果完整節(jié)點(diǎn)能夠下載UTXO集(?2GB)而不是整個(gè)歷史記錄(?140GB),這將是一個(gè)巨大的改進(jìn)。
UTXO證明:第一次嘗試
數(shù)據(jù)集的證明是為該數(shù)據(jù)集確定性計(jì)算的值。
一個(gè)很好的例子是如何將交易提交到區(qū)塊中。當(dāng)我們通俗地說(shuō)交易是在一個(gè)區(qū)塊中的時(shí)候,我們實(shí)際上是指交易提交給了的交易證明(“merkle root”)。這意味著只能使用該交易構(gòu)建證明。這允許節(jié)點(diǎn)下載交易并且和他們一起進(jìn)行驗(yàn)證并構(gòu)建證明,從而確定交易是否在區(qū)塊中。
我們可以對(duì)UTXO集做同樣的事情。如果我們?cè)趨^(qū)塊中的某處(在coinbase輸出中)創(chuàng)建整個(gè)UTXO證明,則新的完整節(jié)點(diǎn)可以下載UTXO集并根據(jù)此證明進(jìn)行驗(yàn)證。
構(gòu)建證明的一個(gè)簡(jiǎn)單方法是按某個(gè)鍵排列所UTXO,然后將它們整理在一起:
這種證明(24d0 …)將用于完整節(jié)點(diǎn)的同步。這個(gè)集合具有唯一確定性,所以新的完整節(jié)點(diǎn)可以下載UTXO集并根據(jù)此證明進(jìn)行驗(yàn)證。
但它有一個(gè)主要缺陷:節(jié)點(diǎn)將需要從整個(gè)UTXO集的每個(gè)區(qū)塊中完全重構(gòu)它。這可能會(huì)花費(fèi)很長(zhǎng)時(shí)間才能實(shí)現(xiàn)。
使其重復(fù)
我們需要構(gòu)建一個(gè)重復(fù)的證明:implementations應(yīng)該能夠從區(qū)塊的交易中更新證明,而不需要完全重構(gòu)它。
簡(jiǎn)單的改變就可以實(shí)現(xiàn)這個(gè)目的。我們要做的是分別對(duì)每個(gè)UTXO進(jìn)行哈希處理,將這些哈希值作為數(shù)字處理,然后簡(jiǎn)單地將它們加在一起:
新的同步節(jié)點(diǎn)就可以像以前一樣對(duì)其進(jìn)行驗(yàn)證,但相同的證明還可以在每個(gè)區(qū)塊中更新。implementations可以簡(jiǎn)單地減去花費(fèi)的輸出的散列,并添加新的輸出,并且結(jié)果證明與當(dāng)前集合構(gòu)造時(shí)相同。
新的同步節(jié)點(diǎn)就可以像以前一樣對(duì)其進(jìn)行驗(yàn)證,但相同的證明還可以在每個(gè)區(qū)塊中更新。implementations可以簡(jiǎn)單地減去花費(fèi)的輸出的散列,并添加新的輸出,并且結(jié)果證明與當(dāng)前集合構(gòu)造時(shí)相同。
然而,這也有一個(gè)缺陷:它不是獨(dú)一無(wú)二的。攻擊者可能構(gòu)造一個(gè)相同結(jié)構(gòu)的UTXO集從而導(dǎo)致相同的證明。雖然證明量太大而無(wú)法嘗試每種組合,但攻擊者可能會(huì)濫用這個(gè)事實(shí),即我們使用簡(jiǎn)單的加法應(yīng)用和巧妙的算法來(lái)輕松找到這樣的組合。
確保安全
幸運(yùn)的是,讓它迭代不需要我們使用加法。不過(guò)我們也可以使用像加法一樣的東西。只要我們有一個(gè)可交換的操作并且有一些方法可以將它反向應(yīng)用,它就可以工作。我們可以使用任何組,對(duì)于具有比加法更好的安全性的組來(lái)說(shuō),一個(gè)好的候選方法是secp256k1橢圓曲線及其組運(yùn)算。
我們可以將每個(gè)哈希值設(shè)定為x ,然后去找y ,使得y = x3 + 7 ,而不是簡(jiǎn)單將哈希值加在一起。(x,y)則是曲線上的一個(gè)點(diǎn),我們可以使用橢圓曲線組操作“⊕”組合這些點(diǎn)。(除了例外情況,A⊕B = C意味著找到C使得存在與A,B和C匹配的線性方程)。
這種結(jié)構(gòu)被稱(chēng)為橢圓曲線多重散列哈希(ECMH)。
這種方法需要注意的一點(diǎn)是:對(duì)于許多x 值,曲線方程是沒(méi)有結(jié)果的。大概只有一半能夠找到結(jié)果。
為了解決這個(gè)問(wèn)題,我們只需要在哈希中添加一個(gè)數(shù)字(一個(gè)“nonce”),然后再次哈希,只要算法失敗就增加數(shù)字:
現(xiàn)在我們有一個(gè)安全的證明,可以重復(fù)地更新每一個(gè)區(qū)塊,并且可以用于新的完整節(jié)點(diǎn)來(lái)檢查他們接收到的UTXO集合。這是證明,它可以在測(cè)試網(wǎng)絡(luò)的區(qū)塊中找到。
下一步的計(jì)劃
在進(jìn)行快速同步節(jié)點(diǎn)之前,還有一些工作要做。
主要是4個(gè)步驟:
1、維護(hù)并將一條信息性的UTXO證明列入到coinbase中。
2、實(shí)現(xiàn)utxo / getutxo P2P消息以允許傳輸U(kuò)TXO集。
3、將驗(yàn)證UTXO證明作為塊驗(yàn)證規(guī)則的一部分。
4、推出快速同步引導(dǎo)方法。
我們?cè)趨^(qū)塊1237565中看到的是對(duì)于步驟1的代碼的初始測(cè)試,其目前正在由各種implementations進(jìn)行審查和討論。
未來(lái)的版本
UTXO證明將對(duì)全節(jié)點(diǎn)初始同步提供方便。但是它并未啟用UTXO包含或排除證明。雖然我們可以根據(jù)證明驗(yàn)證整個(gè)集合,但無(wú)法以這種方式驗(yàn)證單個(gè)UTXO。
UTXO包含和排除證明可能會(huì)讓有些人感興趣,可以允許一種新型的錢(qián)包不依賴(lài)追蹤區(qū)塊來(lái)查找離線時(shí)的交易,而且可以同步當(dāng)前的余額。
未來(lái)版本可能會(huì)使這成為可能。例如,可以將UTXO集分為區(qū)域,其中每個(gè)區(qū)域維護(hù)其自己的ECMH,并且這些區(qū)域散列在樹(shù)形中。
第一個(gè)版本的證明主要集中在主要目標(biāo)上:使整個(gè)節(jié)點(diǎn)的初始同步速度非??欤p少向新節(jié)點(diǎn)提供舊塊的帶寬負(fù)擔(dān)。