UTXO 代表 Unspent Transaction Output。
在比特币社群裡,Transaction 被簡稱為 TX,是以上面這個短語縮寫為 UTXO。一般會認為 UTXO 是比特币區塊鍊設計當中的一部分,但事實上 UTXO 和區塊鍊沒有必然的聯系,你可以完全照搬比特币區塊鍊,但不使用 UTXO。
HyperLedger 和Ethereum 一開始并沒有采用 UTXO,現在前者已經切換回 UTXO,後者打算增加這個選項。我覺得這也是中本聰的過人之處——後來者照着臨摹,中間想搞點小改進,結果做到後面,發現還是人家原版的水準高,紛紛又改回來…..
那麼到底什麼是 UTXO 呢?
前不久我聽“卓老闆談科技”裡“比特币”那一集,裡面講到比特币的付款過程,說他要給付給奶茶妹妹5個比特币,于是系統在他的賬戶裡減掉5,在奶茶妹妹的賬戶裡增加5,然後把這筆交易記入區塊鍊總賬,完成。雖然這個節目做得不錯,不過在這一點上卓老闆完全搞錯了,他描述的是基于賬戶的方案,而不是比特币實際采用的 UTXO 方案。
如果讓我們設計一個支付系統,一定會跟卓老闆想到一起去,給張三一個賬戶,裡面有餘額 100 元,李四有一個賬戶,裡面有餘額50元。當張三要付給李四20元時,做以下操作:
1. 檢查張三賬戶餘額是否充足,如果不足20元就終止交易,向張三報“餘額不足”
2. 在張三賬戶裡減去20元(假設零手續費)
3. 在李四賬戶裡增加20元
現在的銀行也好、信用卡也好、證券交易系統也好,網際網路第三方支付系統也好,其核心都是基于賬戶(account based)的設計,由關系資料庫支撐。
資料庫要確定兩點,第一是你要確定業務規則得到遵守,張三的餘額充足。第二是確定事務性,也就是原子性、一緻性、隔離性、持久性(ACID)。這些都是資料庫的常識性知識,這裡不贅述。這種基于賬戶的設計,簡單直覺,而且在 IT 系統設計裡用了幾十年,應該說沒有什麼問題。
但比特币沒有設計成基于賬戶的系統,而是發明了 UTXO 方案。
要了解UTXO,最簡單的辦法就是把一枚比特币從誕生到在商海中沉浮的經曆描述一下。我們假設一個這樣的場景:張三挖到12.5 枚比特币。過了幾天,他把其中 2.5 枚支付給李四。又過了幾天,他和李四各出資 2.5 比特币湊成 5 比特币付給王五。
如果是基于賬戶的設計,張、李、王三人在資料庫中各有一個賬戶,則他們三人的賬戶變化如下圖所示:
但在比特币中,這個過程是通過 UTXO 實作的,圖示如下:
比特币的區塊鍊賬本裡記錄的是一筆又一筆的交易。
每筆交易都有若幹交易輸入,也就是資金來源,也都有若幹筆交易輸出,也就是資金去向。一般來說,每一筆交易都要花費(spend)一筆輸入,産生一筆輸出,而其所産生的輸出,就是“未花費過的交易輸出”,也就是 UTXO。
比特币交易遵守幾個規則。
第一,除了 coinbase 交易之外,所有的資金來源都必須來自前面某一個或者幾個交易的 UTXO,就像接水管一樣,一個接一個,此出彼入,此入彼出,生生不息,錢就在交易之間流動起來了。
第二,任何一筆交易的交易輸入總量必須等于交易輸出總量,等式兩邊必須配平。
上圖第一個交易 #1001 号交易是 coinbase 交易。比特币是礦工挖出來的。當一個礦機費盡九牛二虎之力找到一個合格的區塊之後,它就獲得一個特權,能夠創造一個 coinbase 交易,在其中放入一筆新錢,并且在交易輸出的收款人位址一欄,堂堂正正的寫上自己的位址。在我寫文章的這一天(2016年8月9日),這筆比特币的數額規定為 12.5 枚,市價 48,576元人民币。這個 coinbase 交易随着張三挖出來的區塊被各個節點接受,經過六個确認以後永遠的烙印在曆史中。
過了幾天,張三打算付 2.5 個比特币給李四,張三就發起一#2001号交易,這個交易的資金來源項寫着“#1001(1)”,也就是 #1001 号交易——張三挖出礦的那個 coinbase 交易——的第一項 UTXO。然後在本交易的交易輸出 UTXO 項中,把2.5個比特币的收款人位址設為李四的位址。
請注意,這一筆交易必須将前面産生那一項 12.5 個比特币的輸出項全部消耗,而由于張三隻打算付給李四 2.5 個比特币,為了要消耗剩下的10比特币,他隻好把剩餘的那 10 個比特币支付給自己,這樣才能符合輸入與輸出配平的規則。
再過幾天,張三和李四打算AA制合起來給王五付 5 枚比特币。那麼張三或李四發起 #3001 号交易,在交易輸入部分,有兩個資金來源,分别是#2001(1) 和 #2001(2),代表第 #2001 号交易的第 (1) 和第 (2) 項 UTXO。然後在這個交易的輸出部分裡如法炮制,給王五5比特币,把張三剩下的 7.5 比特币發還給自己。以後王五若要再花他這5比特币,就必須在他的交易裡注明資金的來源是 #3001(1)。
是以,其實并沒有什麼比特币,隻有 UTXO。當我們說張三擁有 10 枚比特币的時候,我實際上是說,目前區塊鍊賬本中,有若幹筆交易的 UTXO 項收款人寫的是張三的位址,而這些 UTXO 項的數額總和是 10。因為在比特币系統裡,一個人可以擁有的位址資源,可謂取之不盡用之不竭。要知道自己的一大堆位址裡一共收了多少 UTXO,人是算不過來的,需要由比特币錢包代為跟蹤計算。
以上即為 UTXO 的一個簡要的介紹。
那麼UTXO高在哪裡?
比特币的很多技術點都不是中本聰的原創。比如基于“工作量證明(Proof-of-Work)”的共識達成機制是 Adam Back 在 Hashcash 裡提出來的,将全部交易計入一本總賬、并給交易打時間戳來防範雙花攻擊(double-spend attack)的思想是 Wei Dai 的 b-money 和 Nick Szabo 的 Bitgold提出來的,更不用說比特币網絡是零優化的大水漫灌式P2P網絡,僅就 P2P 技術而言,很多方面還趕不上2001年出現的 BitTorrent 。
但是有三個技術點絕對是中本聰原創,一個是區塊鍊的設計,一個是UTXO,一個是智能合約。而這三個設計是極為天才的,被斯坦福大學密碼學和計算機安全教授 Dan Boneh 評價為“extremely brilliant”,“必将激發無窮的創新”。
當然,但中本聰最了不起的地方并不是這三個單點創新,而是将所有這些技術點跟密碼學貨币自身特點相結合,設計了一套“懲惡揚善”的經濟激勵制度,将技術創新與制度設計糅合成一個嚴絲合縫的體系。
在這個體系裡,任何人都可以建立一個匿名節點,編寫破壞性的代碼,然後實施匿名攻擊,即便你攻擊得手、偷來大筆财富,也不會暴露身份,是以可以逍遙法外。
這個系統赤身裸體,開門揖盜,任由你攻擊破壞,甚至如果你成功的突破防線偷來一大筆财富,整個比特币體系不但不會懲罰你,還會堅定的保障你的贓款。然後懸賞100億美金,運作七年,至今為止,在主幹區塊鍊上,沒有發生一起成功的攻擊,一次都沒有。
中本聰把比特币設計得跟數學原理一樣漂亮,很多後來者連抄都抄不到這個水準。我想這就是為什麼加州大學洛杉矶分校的金融學教授 Bhagwan Chowdhry會提名中本聰為2016年度諾貝爾經濟學獎候選人。我相信中本聰在比特币裡的很多設計思想,以及整個比特币開發者社群所做的大量改進,不僅是區塊鍊的開山之作,而且也會成為IT系統設計的一個創新思想源泉。
UTXO 的設計就很值得玩味。在《什麼是UTXO》一文中對其設計方案進行了介紹。本文要讨論的是UTXO 的優點和不足。
中本聰為什麼要把比特币設計成這樣呢?考慮到他應該也不是從未來穿越回來的人物,以常理推論,他一開始應該也是從基于賬戶的系統出發來設計的,但他後來決定切換到UTXO方案,一定是遇到什麼問題。
很遺憾,比特币的源代碼裡找不到這些問題的答案。比特币的開發始于2007年5月,目前在Github 上最早的一版比特币源代碼是2009年9月16日中本聰 push 上去的 0.1.5 版,但其中 UTXO 的設計已經成型。
後來有人翻出自己的老郵件,找到了比特币2008年9月版的代碼。那份代碼是比特币區塊鍊上線之前幾個星期釋出的,應該非常接近比特币創世紀運作的那個版本。可如果你仔細去看的話,其中 UTXO 也已經定型。我們注定無法通過代碼考據來發現 UTXO 的設計脈絡了。
其他文獻材料呢?也不行。中本聰在發表比特币之前,主要是與一些密碼學專家郵件交流,這些郵件外界看不到。而他積極參加論壇讨論,主要發生在比特币已經發表以後。我找不到他在 UTXO 設計形成過程之中發表過任何相關的隻言片語。
既然這些辦法都不行,我們就隻好靠猜了。
我猜測,中本聰一開始設計比特币時,也采用了賬戶方案。但在2007年下半年或2008年上半年的某一個時刻,中本聰發現基于賬戶的方案有問題,于是創造了 UTXO 方案。
那麼基于賬戶的方案會遇到哪些問題呢?
如果采用基于賬戶的方案,可以肯定的是,你需要一個資料庫。這個資料庫能夠讓你很友善的查到張三、李四各自的賬戶餘額。
而 UTXO 方案當然也需要一個資料庫,這個資料庫記錄着目前系統裡每一筆“沒有花出去的交易輸出”,也是就比特币。當節點接收到一筆交易的時候,它需要去 UTXO 資料庫裡查,看看這筆交易所引用的 UTXO 是否存在,它的收款人(擁有者)是不是目前新交易的付款者。而交易結束之後,資料庫要做相應的更新。
首先要明确,無論是賬戶資料庫還是 UTXO 資料庫,必須是分散的,每結點一個克隆,一定不能是中心化的。如果比特币系統有一個中心資料庫,不管你有多少節點,每一筆交易都要跑去中心資料庫驗證一下、然後再執行“轉賬”的事務操作,那就完全談不上“去中心化”,比特币就毫無價值了,不如老老實實用支付寶。
既然都是每個節點克隆一個資料庫,根據交易過程同步修改,那麼一個賬戶資料庫跟一個 UTXO 資料庫,又有什麼分别呢?
進一步思考,我們會發現還是有很大分别。
首先,長期來看,賬戶資料庫會無限膨脹,而UTXO 資料庫體積會小很多。
要知道,比特币是個匿名體系,它的賬戶就是“位址”。每一個比特币使用者可以擁有幾乎無限多的位址,在比特币系統來看,它完全不知道兩個位址背後對應的是不是同一個人。
而且比特币鼓勵使用者開設大量位址,有些錢包軟體甚至每進行一次交易都新開一個賬戶,每收一次錢都開一堆賬戶來分散資金,以確定匿名性。這還不算,有很多使用者出于好奇,下載下傳一個比特币錢包,嘭嘭嘭申請它幾十個位址,然後冷冷的趴在那裡,永遠也不用。又或者有些位址用過以後,再也不用了,甚至幹脆被擁有者遺忘了。但所有這些有用的沒用的位址,咱們的賬戶資料庫都得不折不扣的記着。
時間越久了,賬戶資料庫裡“廢賬戶”所占的比例越大,體積無限膨脹,這個怎麼吃得消呢?要知道,比特币礦機每處理一筆交易,都需要查詢這個資料庫,當資料庫規模無限膨脹的時候,查詢速度也會放慢,耽誤比特币礦機的挖礦競争,這是無法接受的。
相比之下,UTXO裡面存放的都是“有用的”資料,也就是目前沒有被消費的比特币。礦工需要查詢和操作 UTXO 資料庫才能夠驗證交易,這個過程一定要快,越快越好,這樣在挖礦競賽中才能夠搶在别人前頭勝出。
多虧 UTXO方案,目前比特币運作了近八年,整個資料庫還不算太大,到2016年五月,壓縮體積約1.5GB,估計解壓後體積大約是8GB,能夠完整的放在記憶體裡。如果是賬戶資料庫,我估計記憶體早就放不下了。
其次,UTXO 資料庫允許并行事務操作。在賬戶資料庫中,張三要轉20元給李四,需要進行一個資料庫事務,在張三賬戶裡減20,在李四賬戶裡加20。如果與此同時,王五要轉30元給張三,那這個交易就得排隊,無法并行。
之是以這樣,歸根結底是因為這兩筆交易都需要跟“張三的賬戶餘額”這個共享狀态打交道。而在 UTXO 中,資料庫跟蹤的是比特币的所有權轉移,而不是賬戶的狀态。不管張三本人正在發生多少收支交易,這些收支交易都是發生在不同的比特币上的,更重要的是這些交易之間并不共享任何狀态,是以不會互相幹擾,所有這些交易可以并發執行。這帶來好處不光是快,更重要的是可擴充,可分布。
在很多大規模網際網路企業中,處理分布式事務是核心技術競争力之一,非得需要極強的精英技術團隊、大量長時間持之以恒的投入和維護改進,才能在這個領域站住腳。是不是可以基于 UTXO 發明一個技術體系,使得交易性事務處理也能充分分布?UTXO 是否具有更廣泛的适用領域?
比如,當你在天比特商城裡上花10比特币買一件衣服,而支比特寶不是在你的賬戶裡扣錢,而是在一個交易當中把衣服的所有權和10比特币的所有權對調,讓衣服的所有者從商家變成你,而讓比特币的所有者從你變成商家。
注意,這個過程不與同時進行的任何其他交易共享狀态,而且一個交易一個事務,事務完整性可以輕松確定。這樣一個交易過程,可以很容易地進行大規模分布。交易量大了,就加節點,交易量小了,就減節點。在這樣的體系結構下,我們完全不用為天比特商城和天比特寶一天完成多少百億的交易額而興奮激動、頂禮膜拜了,因為技術上這不再是什麼多了不起的事情了。當然,這隻是一個猜想。真的會是這樣麼?有沒有其他的坑?這是極其有吸引力的話題,值得未來不斷探讨。
當然,UTXO 也有一些缺點。
首先,UTXO 方案實作起來不是太容易,比較複雜。這也是為什麼 Ethereum 一開始沒有采用 UTXO 方案的原因。
其次,UTXO 資料庫現在膨脹得也很厲害。2015年五月,UTXO資料庫壓縮以後650MB,解壓後占記憶體裡 4GB。一年之後,壓縮體積1.3GB,解壓後占記憶體 8GB,這一年翻一個翻的速度,誰也受不了。比特币大牛 Galvin Andersen 做過一個估算,到2025年,要想把 UTXO 資料庫放進節點記憶體裡,光買記憶體就得花4,000美元。
UTXO 膨脹問題也使得人們對于比特币區塊擴容顧慮重重。如果比特币區塊從1MB擴容到 2MB,那麼UTXO會加速膨脹。
現在也有一些人提出了解決問題的建議,有的說通過激勵機制鼓勵節點進行 UTXO 合并,有的建議放松一些驗證要求,允許節點将 UTXO 放在磁盤上。Peter Todd 做了一個完整的建議,有興趣的人可以戳這裡(https://petertodd.org/2016/delayed-txo-commitments)。
我個人在翻故紙堆的過程當中,看到2010年一個叫 Red 的黑客跟中本聰的一段讨論。Red 建議資料庫裡不再存放目前UTXO集合,而隻是存放鑄币記錄:這幾枚比特币是什麼時間挖出來的、收款人是誰。然後,每當發生交易的時候,由錢包軟體負責将所開支的比特币從其被挖出的那個時刻開始一直到目前交易的全部換手記錄送出給節點,節點隻要驗證所有這些記錄環環相扣,數字簽名都對得上,就可以準許交易。
做一個比方,這個就好像買賣二手房。
政府那裡隻有這處房産的原始地契,而張三李四買賣雙方需要把原始地契和曆史上所有的轉手合同一張一張帶好,最後把自己這次買賣的合同拟好,來到辦事處。辦事員先從檔案庫裡調出該處房産的原始地契存檔,比對原始地契,證明此處房産确實從落成之日起,即為本區政府認可之合法物業,然後再一張一張核實換手合同,看轉手過程是否環環相扣,看簽名是否為真,直到最近一份合同,确認目前該物業确實為張三所有,然後核查最新的這份“張三将此處房産賣給李四”的合同,主要是查簽名,當然也要核對其他條件。核查通過後,就在上加蓋公章,認可交易。注意這份合同政府不必存檔,而應由李四帶回去妥善保管。下次當李四在要将房産賣給王五時,他需要帶着從原始地契直到“張三将此處房産賣給李四”的合同一起出示給政府辦事員,證明自己确實是目前房産的所有人。
這個方案的好處在于,原始鑄币記錄(相當于原始房契)數量是線性增長的,每個區塊隻産生一份這樣的記錄,是以相應的資料庫不會出現體積膨脹。而且等到比特币全部挖光之後,這個資料庫就停止增長了。
缺點呢,則是把複雜性完全嫁禍給了錢包軟體和節點驗證過程。每一筆交易,錢包都要向節點送出一個長長的、而且越來越長的比特币換手記錄。而節點也要從這些比特币的誕生時刻開始一筆一筆的核查,交易驗證的性能會大大下降。
正是因為這個原因,當時中本聰沒有接受這個方案。但是,這主要是因為貨币的流通速度太快。同樣這個方案在其他的應用場景下,或許是可行的。是以我在這裡詳細論述了一番。