科普一下比特幣的區塊鏈是什么,老手們可以直接跳過這一部分了。這里說的比特幣,是2017年8月以前的比特幣,后來分為了 有隔離見證的BTC 和沒有隔離見證的 BCH 兩條鏈。下面會有不少看起來很專業的東西,不過請放心,我不是專業的程序員,不會講太深的。稍微理解一點比特幣的架構和轉賬的方法,對理解隔離見證的騙局很有幫助。比特幣鏈條大概是長這個樣子:
我們可以看到幾個區塊(Block),可以看到每個區塊都有兩個部分:一部分是虛線畫出來的 Prev.block 指向上一個區塊,這部分我們叫它“區塊頭”,另外一部分是“區塊主體” Transaction,即這個區塊里交易的信息。由于每個區塊頭都指向上一個區塊的頭,所以這個系統我們叫他區塊鏈。再詳細點看這個區塊頭:
Prev-Hash 是上一個區塊的這4個信息合起來的Hash 結果,Timestamp 是目前的時間,有這兩個的限制,礦工至少要收到上一個區塊的區塊頭,才能開始挖下一個區塊。Tx_Root 是這個區塊的主體里所有交易的Merkle Root,如果有任何一個交易被改變,這個 Tx_Root 就會有變化。 如此,比特幣的區塊形成了一條不能被更改的鏈:加入這個 Block11里面的 Tx1被改變了,那他上面的 Hash1就會變,Tx_Root 也就變了,這樣 Block11的4個信息合起來的 Hash 結果會不一樣,就和 Block12的 Prev_Hash 斷開了,Block12就無效,以此類推。
支付腳本
區塊鏈里的交易,大概可以理解為是 “A 地址轉給 B 地址 xx 個幣”,“B 地址轉給 C 地址 xx 個幣”這樣的信息。如果 C地址收到了 xx 個幣,但沒有往外轉,那這就會在 UTXO 數據庫里記一條:“C 地址還有 xx 幣沒花掉”。假如 C 地址是普通的1打頭的比特幣地址,要花掉這筆錢,就需要用到一個腳本,這個腳本是“B 地址轉給 C 地址 xx 個幣”時規定的,定了這筆錢要怎么才能被C 地址花掉。一般這個腳本是這樣的兩部分
scriptPubKey部分: OP_DUP OP_HASH160 《pubKeyHash》 OP_EQUALVERIFY OP_CHECKSIG
scriptSig部分: 《sig》 《pubKey》
不會編程的朋友請不要害怕,不難看懂的。scriptPubKey部分有幾個“操作碼”,是 OP 打頭的,表示幾種操作。《pubKeyHash》就是比特幣地址的中間部分,不帶開頭的版本號1和末尾的幾位校驗碼,這部分是對公鑰進行 Hash 的結果。scriptSig部分要由想轉賬的這個人提供,公鑰《pubKey》,和用私鑰對這筆交易的簽名《sig》。由私鑰可以推導出公鑰,公鑰可以推導出比特幣的地址,這兩個步驟都不能反推(在當今科技下)。如果一個人可以展示私鑰對這筆交易的簽名,又可以提供這個地址的公鑰,那我們就相信這筆轉賬是他授權的,別人偽造不了。礦池收到了提供的交易,和交易的簽名,要怎么驗證呢?就是運行一遍上面的腳本,看看結果是不是“True”。如果結果是 True 那就算通過了。首先要把scriptSig里的東西“堆”起來,形成一個“堆棧”:
《pubKey》
《sig》
然后,就一個一個地執行scriptPubKey部分。先是一個 OP_DUP,這個是復制操作,這些操作都是對著堆棧的頂部操作。所以復制操作后堆棧變成了:
《pubKey》
《pubKey》
《sig》
然后是一個 OP_HASH160,是 Hash160算法的操作,把堆棧頂部的《pubKey》變成了《pubKey Hash1》:
《pubKeyHash1》
《pubKey》
《sig》
然后是《pubKeyHash》,把這個推進堆棧:
《pubKeyHash》
《pubKeyHash1》
《pubKey》
《sig》
然后是OP_EQUALVERIFY,是檢查是否相等的操作,對著堆棧頂部的兩個元素進行。如果提供的《pubKey》是沒錯的話,應該是一樣的,操作后堆棧變成了:
《pubKey》
《sig》
最后一個操作碼是OP_CHECKSIG,檢查這個簽名《sig》和公鑰《pubKey》是不是對的上,如果沒問題,堆棧就清空了。任何一步出問題都會造成腳本報錯,如果沒出錯,那腳本結果是 True,表示通過。
腳本能用的操作碼還有很多,可以進行 if,else,add,sub,drop,swap等等等等。比如,B 地址給 C 地址轉賬的時候,在剛才的腳本開頭,加上一個《expiry time》和一個操作碼 OP_CHECKLOCKTIMEVERIFY,就可以制造一筆凍結款,C 地址里的這筆錢要經過特定時間后才能花,在到期之前OP_CHECKLOCKTIMEVERIFY會讓腳本驗證失敗。
據“2009年就開始參與比特幣開發”的 Craig Wright 的說法,如果有足夠的操作碼,比特幣系統也是圖靈完備的,也可以運行ETH 那樣的智能合約。但是,許多操作碼在2013年被 Core 禁用了(因為 Core 開發者看不懂那些操作碼有什么用),對腳本的限制也更多。BCH 在2018年的開發路線圖里就包含了修復操作碼設計的部分。
如果,B 地址給 C 地址轉賬的時候,把腳本搞成這樣:
scriptPubKey部分: 留空
scriptSig部分: OP_TRUE
那這個腳本就是永遠都可以通過的,不需要提供任何信息。這筆錢誰來轉出,怎么轉出都是有效的,我們稱這錢現在是 anyone-can-spend。這筆錢等于就是給了礦池,因為礦池最終決定誰的交易可以被打包進塊。如果有人把自己的錢轉入這么一個 anyone-can-spend地址,礦池肯定會把這筆錢打給自己。
這個anyone-can-spend的腳本,就是隔離見證(Segwit)的基礎。用這個腳本,轉賬的時候就不用在區塊里提供簽名了,簽名被“隔離”到了區塊鏈以外,故名“隔離見證”。雖然簽名挪了地方,但是轉賬的話簽名還是要給的,不然豈不是亂轉賬了。其實,用戶該發送的信息沒有少,礦池要驗證的信息也沒有少,區別只是在區塊鏈里存的信息少了。由于區塊被設置了1MB 上限,并且已經堵滿了,如果交易在區塊里占的空間小一點,就能多擠幾個交易進這個1MB 塊。隔離見證技術被吹噓有1.7 x 的擴容效果,如果所有人的交易都用這種 anyone-can-spend的格式的話。現在問題來了,這樣把簽名信息挪出區塊鏈,有什么好處?為什么不直接把1MB 上限放寬到2MB 呢?
軟硬分叉之爭
如上的疑問,就是擴容軟硬分叉之爭。因為 Segwit 是一個所謂的軟分叉,而提高區塊大小會是一個硬分叉。在之前的文章里已經說過,其實這里面軟硬分叉之爭是個表象,本質上是路線之爭:普及后,比特幣是流通的幣,還是流通幣的結算層;是流通的幣更去中心,還是結算層更去中心。軟硬分叉其實都只是技術手段而已,真正最后的結果還是被人所控制的。
涉及到“共識層”的修改,就會形成“分叉”。共識的運行其實是兩個半層面,一層是在有算力的節點(礦池),第二層是沒有算力的全節點,還有簡單支付驗證的輕錢包 SPV 我們算半層。軟分叉的特點是“舊版軟件還能認新共識”。硬分叉是“舊版軟件不認可新版軟件”。我們用下面一張圖來看軟硬分叉的情況。
?
在 Block8區塊之后,系統從 V1軟分叉升級到 V2,這時:
算力層:
運行 V2的礦工(大多數算力)認為最長的有效鏈是上面的這一條。
運行 V1的礦工(少量未升級算力)也認為最長的有效鏈是上面的這一條,會放棄掉自己的 Block9(V1)形成孤塊,因為它不是最長了。而 V1礦工挖出的舊版本塊不會被 V2礦工承認,這樣,V1礦工不升級,就面臨著不被承認的境況,礦機白白浪費電。
全節點層:
運行 V1和V2的全節點(無算力)都認為最長的有效鏈是上面的這一條。V1節點因為沒有礦機而無經濟損失。
SPV 層:
運行V1和V2的 SPV錢包都認為最長的有效鏈是上面的這一條。
總結來看,軟分叉時,只要挖礦的節點需要升。如果不升級,會有經濟損失。
對比一下,系統從 V1硬分叉升級到 V2,這時:
算力層:
運行 V2的礦工(大多數算力)認為最長的有效鏈是上面的這一條。
運行 V1的礦工(少量未升級算力)認為最長的有效鏈是下面的這一條,上面一條雖然長但是無效。這樣,V1礦工不升級,就會和 V2形成兩條并行的鏈。
全節點層:
運行 V2的節點(無算力)認為最長的有效鏈是上面的這一條。
運行 V1的節點(無算力)認為最長的有效鏈是下面的這一條,上面一條雖然長但是無效。
SPV 層:
如果這個硬分叉是擴容1M到2M 的話,由于 SPV 錢包不檢查容量限制,所以不會因為容量而判某鏈無效。運行V1和V2的 SPV錢包都認為最長的有效鏈是上面的這一條。如果這個硬分叉修改了挖礦算法或者難度調節算法,那么 SPV 節點也會依新舊版本各自認各自的鏈。
總結來看,硬分叉時,不只要挖礦的節點需要升級,不挖礦的節點也要升級,SPV看情況, 可能可以不用升級。如果一部分算力不升級,會被拆成互相不能轉賬的兩種幣,像現在的 BTC 和 BCH 一樣。
這么看,軟分叉是不是比硬分叉來得安全呢?如果擔心有人因為不知道大家升級,或忘記及時升級的話,看起來軟分叉可以預防比特幣被莫名其妙分為兩個幣。但這種情況是不存在的好么?現在算力都在幾個礦池手里,只要提前幾個星期通知一下大家做好準備,完全不會出現“忘記升級”這種事。能出現“忘記升級”的只能是普通用戶,普通沒有算力的用戶,對系統的運行也沒有影響。BCH 上的 DAA 硬分叉(把難度調節算法更改為逐塊調整)已經非常好地展示了這樣的硬分叉,對普通用戶的使用并不構成障礙。我們平時使用其他軟件,也經常面臨著不升級一下登陸不進去這樣的情況,并不是什么要命的事情。Core 開發組一直在妖魔化硬分叉,表示硬分叉會造成比特幣分裂為兩種幣,影響市場穩定。其實有分歧造成的硬分叉攔不住(BCH 分離出來),沒分歧的硬分叉升級沒危險(BCH 難度算法調整),無視路線分歧硬說軟分叉安全是沒有理由的。
軟硬分叉之爭的結局:中間派的失敗
在大家對硬分叉的安全性有質疑的時候,中間派試圖用“合并分叉”這樣的手段來調解。大致手法就是先用大家都認可安全的軟分叉從 V1升級到 V1.5,然后在 V1.5里預埋硬分叉到 V2 的代碼。這樣,如果是有算力“忘記升級”,他的 V1會在升級到 V1.5的時候被孤立,但不會立刻形成2種幣。等到 V1.5到 V2進行硬分叉升級的時候,由于是預埋的代碼,自動運行的,不會“忘記”。沒有鄙視程序員的意思,這是一種典型的“程序員思維”。軟件是死的,人是活的。如果人要搞事情,用代碼是限制不住的。
中間派的最后運行的方案是 Segwit2x 方案,合并分叉 Segwit 和2M 這兩個升級,前一個是軟分叉,后一個是硬分叉。這個方案在紐約得到了超過83%的算力的支持,紐約會議之后,中國礦業又內部約定:大家都運行 Segwit2x 的軟件,這個軟件預埋了代碼,在 Segwit 激活后90天,自動激活2M 的升級。問題就來了,你如何知道別人運行的軟件和你是一樣的?除非是黑進礦池的服務器去,否則從外部完全不能判斷別人會不會在3個月后進行2M 分叉。雖然代碼是寫了,但別人可以運行別的版本的軟件,可以把那幾行刪掉,改掉,外人無從得知。反擴容派是傾向于要 Segwit而不要2M,中間派是為了要2M 愿意妥協 Segwit。當 Segwit 激活 以后,中間派沒法靠這2行代碼來逼反擴容派進行2M 升級,分裂成2種幣的結局依然是難免的。最后結果大家也看到了,中間派認慫取消掉了2M 硬分叉的計劃。
從2016以來,為了不讓比特幣分成兩種幣,大家花了那么多的時間在開會談判上,現在才明白過來:如果路線有分歧,沒有技術手段可以防止比特幣分成兩種幣,也沒有技術手段可以督促其他方面參與或不參與一個硬分叉。
隔離見證軟分叉(Segwit)的危險
前面我們提到,隔離見證是一個軟分叉,舊版依然可以兼容,在升級的時候可以預防“因為忘記升級而亂套”。這可以算一個非常模糊的優點,具體有沒有用是很值得懷疑的。相比之下,這軟分叉的缺點就要嚴重得多。還是畫個圖看一下:
從 Block7開始,系統加入了 Segwit 的功能。前面介紹腳本的段落里已經介紹過這種 anyone-can-spend 的地址,假如 Block7里一個 Segwit 交易,把幣發到了一個任何人都可以花的地址 C 里面,簽名放在了外面。假設 C 地址的擁有者,打算在 Block8把錢花出去,發送幣給地址 D,誠實的礦工會驗證C用戶的簽名,安全性基本和以前是一樣的。這里,讀者可以可以看到,“這筆錢是不是 C 的”這個問題,要靠 Block7下面掛著的那個小塊 sig來回答。如果僅看Block7的信息,得出的結論會是“這筆錢是無主的隨便撿”。
眾所周知這個 Segwit 功能是一個軟分叉,也就是說舊版軟件依然會承認 Segwit 版發出來的塊,不用升級。舊版的軟件根本就看不到 這個小塊 sig。舊版錢包軟件(全節點或 SPV 錢包)看到這筆錢就是無主的,任何人都可以花的。好在算力一層是必須全部升級的,舊版錢包軟件如果提出要轉走這筆錢會被所有算力拒絕,只能眼睜睜地看著錢在那里無主地放著。舊版錢包不能正確地獲得交易信息,僅僅是驗證機制被繞過了,無法發現交易模型已經改變了。前面我們介紹過,區塊鏈的一個特點就是,后一個區塊依賴前一個區塊的區塊頭里的信息,如果修改一筆交易,區塊頭會變化,會造成整個鏈條的失效。可是現在 Segwit 的“外掛見證塊”并不在這個鏈條里面,修改 sig 里面的內容是不會使鏈條失效的。如果我有算力,但不是 C 地址的擁有者,我無法提供地址 C 的簽名,但我把地址 C 的錢轉給自己,這個塊一定會被其他礦池拒絕掉,因為他們驗證了 sig 發現我并沒有資格動這筆錢。可是舊版錢包(全節點或 SPV 錢包),和新版的 SPV 錢包(不驗證和自己不相關的交易,只接收區塊頭),都不會發現,他們只會跟隨最長的塊,sig 的內容不影響有效與否。
因此,Segwit 帶來了一種新型的51%攻擊。這種攻擊我在之前的一篇回答里介紹過:
一般幣的51%攻擊:我在高度12345上發布一個交易,從 A 地址到 B 地址發送1000比特幣。同時我用自己的壓倒性的算力,重新挖出一條12344-12345-12346的鏈,不包含剛才的交易。這樣 B 一開始以為我付款了,后來我付款的那個塊被孤立了,最終成型的最長鏈里不包含我的支付。這也是為什么各大交易所都要求3個確認,6個確認,就是防止出現你發送幣給交易所的交易被孤立。一般認為6個確認后就幾乎不會出問題了。小額支付(幾萬美金以內)經常1確認甚至0確認(塊不滿的時候)也可以,因為對于小額交易你沒有經濟動力去攻擊。小額沒賺頭,大額肯定會要求多個塊的確認很難做到,也沒賺頭,并且攻擊窗口就是交易發布后的那一兩個小時,過去了就沒法攻擊了。所以至今比特幣沒有發生過真正意義上的 51%攻擊。
SW 幣的51%攻擊:Segwit交易帶來了“AnyOneCanSpend”地址,它實質上是一個空白的交易簽名。這種交易的簽名被挪移到了附加的見證塊里,因此這個技術叫做“隔離見證”。當然,雖然這個交易的簽名不在這里,礦池肯定還是會去附加的見證塊里找出來核對驗證。在大家都核對驗證的情況下,安全性和以前是一樣的。控制算力超過50%的礦霸礦池,可以直接放棄附加見證塊的核對,并把AnyOneCanSpend地址里的錢轉給自己,然后孤立那些去核對見證塊的礦池。由于 Segwit 是軟分叉升級,原來的那些沒有 Segwit 功能的 SPV 錢包和全節點錢包還是可以用的,這些錢包也沒有核對附加見證塊的能力,這時候這些錢包都會認為礦霸的鏈是合法的最長鏈。和一般幣的51%攻擊巨大的區別就是:一般幣的51%攻擊只能退回自己的一筆支付,而SW 幣的51%可以花掉別人賬上的錢,而且這錢的數字是從 SW 激活起慢慢積累變多的。SW 運行的越久,SW 交易運用的越多,這筆錢的數量也就越大,有動力攻擊的算力也就越容易找。參考資料:Risk of SegWit - Mining Cartels - nChain
軟分叉可以在不驚動普通用戶的情況下偷偷進行,上 Segwit 功能是軟分叉,關閉 Segwit 功能也是軟分叉,也可以偷偷地進行。一旦使用了 Segwit 功能,把幣放在了AnyOneCanSpend地址里,就只能信任51%的算力不會去進行關閉 Segwit 功能的軟分叉。如果不使用 Segwit 功能,把幣放在“經典”的1字頭地址里面,任何軟分叉都不能讓你失去這幣,除非有絕大部分算力針對你的存幣地址發動一個硬分叉,才能把這個地址里面的錢轉給別的地址。顯然這種硬分叉是無法成為主流的,估計中本聰也得不到這種待遇。放在1字頭地址里的幣就是你的幣,只有你可以轉走賣掉,別人都不行。放在 Segwit 地址里的幣,就要看礦業有沒有誠信了,如果超過51%的算力發動取消 Segwit 的軟分叉,剩下的49%里必須有算力主動發起硬分叉才能甩脫51%算力的最長鏈,保住你的幣。可是 目前 Segwit 鏈的座右銘就是“We don’t hard-fork”,是不是有點尷尬?
有人會說,51%算力發起關閉 Segwit 功能的軟分叉是不可能做到的事情。這點我同意,但是也許你不需要51%算力來做到這事。如果我是搗亂礦池,占5%算力,我挖出一個塊以后,簽名 部分拖延1分鐘再發出去,其他礦池敢不敢再這1分鐘里以我這個塊為基礎挖下一個塊?如果挖,一分鐘以后收到 簽名 的內容可能會發現這個塊里有非法的交易,這一分鐘就白挖了。如果不挖,一分鐘以后 簽名 內容是正常的,就浪費了一分鐘。我只要用5%的算力搗亂,每天出幾個塊,就足以逼很多礦池修改自己的軟件設定,在收到簽名前就開始挖礦。搗亂礦池可以把 簽名 漸漸拖更久,比如10分鐘后才發,很少的算力就可以把嚴格驗證 簽名搞成成本挺高的事情。不驗證簽名的礦工收益更高,這在 Segwit 以前的比特幣上是不可能發生的事情,如今可能了。如果有30%的算力不驗證附加的簽名塊,那我只要21%的算力就可以發動上述的 Segwit 獨有的51%攻擊了。
隔離見證軟分叉(Segwit)無法擴容
Core的開發者一直在宣傳,說 Segwit 可以帶來1.3x,后來又說1.7x,又四舍五入到2x 的擴容效果。從交易數來看,2017年8月中旬激活 Segwit 以來,每個塊的交易數勉強突破了之前的高點2250,連1.1x 的擴容效果也沒有。每個塊2000+筆的交易能力是不夠的,必須盡快改進,這一點上各派都沒有異議。Core 的開發者現在已經不提“ Segwit 有立竿見影的擴容效果”這話了,著重宣傳閃電網絡。“小額交易走閃電幾乎零手續費,大額結算上主鏈五十美金一筆”,這已經是 Core 支持者的信仰宣言。
第二層交易網絡
我們來簡單對比一下BCH 的“傳統”單層模型,和閃電網絡的第二層模型。
手續費方面:
以50美金一筆手續費的大額結算來計算(50美金就是今天的手續費水平),閃電網絡開閉通道各需要一次交易,就是100美金的成本(閃電節點的成本沒有計入)。如果平均每個通道結算時已經發生過1000筆交易,那每個交易的成本為10美分,勉強還屬于比較低的手續費水平。要什么樣的通道才能1000筆結算一次呢?以我的想象力,我只能想到這個是支付寶,銀行或者地下錢莊的模型,把我的幣充值鎖進去慢慢花。交易所等機構之間大概更有用一些,對于普通用戶其實是毫無作用。
按照每個塊開閉2000次閃電網絡通道(1M 的極限),每個通道1000筆交易來算,BCH 的模型里,1000000筆交易差不多也就是500MB 區塊。nChain 已經和 BitcoinUnlimited 聯合測試過1GB 區塊,并沒有很科幻。
安全方面:
Segwit 的安全性問題已經是一個很好的反例了。區塊鏈,或者說a chain of digital signatures,是中本聰的杰作,也是比特幣和支付寶,銀行,信用卡的根本區別。在比特幣,現在的 BCH 里,沒有私鑰誰也沒法挪動你的錢,你必須有私鑰才能把錢挪動到指定的地方。閃電網絡雖然已經宣稱進行過多輪測試,但“怎么保證通道內的交易公正不被修改”這個問題,依然沒有清楚的回答。如果有哪位朋友有好的資料能夠提供,不勝感激。從我目前的理解是,閃電通道內基本還是充值卡的模型,外加了通過多次交換簽名來讓雙方對余額有共識,但如果雙方有意或無意對余額有分歧,需要由 閃電節點來裁決。Segwit 的問題又出現了:有人可以在沒有你的數字簽名的情況下挪動你的錢。
安全方面,這一篇文章值得看看:https://news.bitcoin.com/lightning-network-centralization-leads-economic-censorship/
技術方面:
剛剛其實都是我瞎編的,目前閃電網絡完全沒有如此大流量的公開測試,考慮到閃電通道內多次反復交換簽名的設計,同等硬件瓶頸下閃電網絡的交易容量堪憂。
結語
我在敲這篇文章的時候,BTC 正在瘋漲,BCH 和其他所有幣都被“抽血”而下跌。同時,BTC 擁堵了17萬筆交易沒有確認,單筆手續費大約50美金。Steam 宣布放棄比特幣支付渠道,因為手續費太貴了沒法用了。Bitpay 宣布要投資支持比特幣以外的各種幣,也是因為手續費太高。
市場在短時間內是不理智的,這個混亂時間點上暴漲暴跌都不稀奇。如果說再過十年,市場上主流的是哪種幣?一個挪動困難,安全性堪憂的 BTC 真能保值十年嗎?如今 BTC 確實是有保值增值的功效,在過去幾年里任何一個時間點,甚至過去幾個月的任何一個時間點買入,到今天都是大賺。暴漲總是有頭的,如果BTC 不再暴漲,失去了支付渠道和商家支持的 BTC 就沒有上新聞的能力了,在投資者的圈子里,不再暴漲的BTC也失去了增值保值的能力。如今加密貨幣都是新事物,嚴格意義上來說BTC 也還沒有進入公眾視野,新聞里的 BTC 只有暴漲,沒有應用。這兩年新入場投資加密貨幣的,都很少有只買 BTC 的了,都是 ETH等幣搭配著投資,在幣圈 BTC 都不是那么大眾化,終究是會淡出公眾視野,變得越來越小眾的。十年后能成為主流的幣,一定是接下來幾年能第一個真正進入公共視野的幣,我猜這個幣是BCH。
評論
查看更多