30分鐘入門比特幣與區塊鏈

  常見的比特幣與區塊鏈入門文章大約分爲兩類,一類是面向非開發人員的科普讀物;另一類是面向開發人員的技術指南。前者易流於淺表,讓讀者接觸了一堆名詞和概念,卻無法對比特幣與區塊鏈有個直觀的認識;而後者又往往直接進入細節,使開發人員一葉障目不能從全局瞭解技術概貌。本文嘗試將這兩類文章合二爲一,同時避免上述兩種缺陷。文章前部分適合想了解比特幣和區塊鏈的非開發人員,整篇文章適合想轉入比特幣與區塊鏈相關開發的技術人員。

一. 比特幣是什麼

  瞭解一個陌生事物最快的方法,莫過於和一個熟知的事物進行對比,找出差異,研究差異。以轉賬支付爲例,來說明傳統貨幣轉賬和比特幣轉賬時分別發生了什麼。這裏說的傳統貨幣特指由各個國家發行的法定貨幣,如美元,人民幣等,也包括這些貨幣在銀行系統中的虛擬形式,如人們在銀行的存款。以下統稱法幣。
  下表爲張三分別用法幣和比特幣向李四轉賬的步驟:

步驟 法幣 比特幣 備註
1 張三和李四分別在銀行開戶,設置對應的密碼。 張三和李四各自安裝一個稱爲錢包的軟件,並用該軟件產生賬戶及相應賬戶的密碼。 錢包軟件產生的賬戶和密碼使用前一般不會讓任何第三方機構知曉,只存在於用戶自己的手機或優盤上。
2 張三要保證自己銀行賬戶裏有足夠的錢來轉給李四,如果不夠先要往銀行存入一筆。 張三要保證自己比特幣賬戶裏的錢足夠轉賬,如果不夠則通過比特幣交易平臺購買比特幣,將比特幣存入錢包軟件產生的賬戶裏,本質上是將銀行裏的法幣兌換成比特幣。 比特幣交易平臺將比特幣劃入張三賬戶的過程,和我們這裏討論的將張三的比特幣劃入李四賬號的過程類似。另外還可以通過挖礦的方式獲得比特幣,這對普通用戶不易實現,該內容我們稍後再討論。
3 張三通過輸入密碼的形式授權銀行將自己賬戶的一筆錢轉入李四的賬戶。 張三使用自己錢包軟件裏對應賬戶的密碼授權並轉賬到李四的收款賬戶,並通知區塊鏈網絡。 稍後介紹區塊鏈,現在只需知道區塊鏈能記錄授權的比特幣交易就行了。
4 銀行記下張三的操作,從張三的賬戶扣除一筆錢,並在李四的賬戶增加同樣數目的一筆錢。 區塊鏈網絡記錄下張三的轉賬記錄。 在第三步中,比特幣授權和轉賬的動作同時發生,因此這一步只需要記錄轉賬。區塊鏈網絡和銀行完成相同的功能:記賬。
5 銀行通知張三和李四轉賬成功。 張三和李四均可通過查詢區塊鏈網絡確認轉賬成功。 區塊鏈網絡和銀行完成相同功能:確認交易

  由上表可知,從用戶角度看比特幣和法幣一樣完成轉賬交易的功能,甚至連步驟都很相似,但每一步又都有差異。
  步驟1:雖然都要有賬戶和密碼,法幣賬戶是在銀行設置,銀行會保存用戶的賬戶和密碼數據;而比特幣的賬戶和密碼,在使用之前除了用戶自己沒有任何第三方機構知曉。
  步驟2:給銀行賬戶充值必須通過銀行系統,如果開戶銀行的系統出了故障(如果光纖被施工隊挖斷),故障期間張三是無法充值的;而給比特幣充值時,如果某家交易平臺故障,張三可以隨便換其它充值平臺,因爲比特錢包產生的賬戶所有交易平臺都認可。
  步驟3:法幣的密碼驗證授權,必須要經過銀行這樣的中心繫統;而比特幣的密碼驗證授權不依賴於任何中心繫統,它只依賴於密碼學提供的算法。和步驟2中一樣,比特幣不會受特定系統的波動而影響密碼驗證。
  步驟4和步驟5:法幣記賬和交易確認需要銀行的介入;而比特幣則藉助於區塊鏈網絡,後文我們將講到區塊鏈是由許多公司或個人共同在維護,即使某些公司或個人的設備出了故障,也不會影響整個區塊鏈網絡的運轉。
  除了以上,法幣和比特幣的發行方式也不同:法幣一般是由國家發行,並以法律形式保證其流通使用;而比特幣的發行方式是:挖礦,理論上所有人都可以參與挖礦來獲得比特幣。這和地球上的另一種貨幣黃金很相似。黃金在地球上是稀有的而且也是有限的,比特幣也是有限的,而且開採量也是逐年減少直到約一百年後開採完。注意挖礦這詞其實只是一個比喻,挖礦和區塊鏈的運作緊密相關,我們在下節討論。
  總結:法幣交易的每一步都需要一箇中心機構來保證,要麼是國家,要麼是國家認可的銀行;而比特幣幾乎不需要任何中心化的機構和設備就可以完成所有交易。另外在區塊鏈中保存的交易數據只是匿名的賬戶數據(沒有張三和李四的任何信息,只是一個很長的數字串),通常也認爲它是匿名的。一句話總結:比特幣是一種去中心化的匿名數字加密貨幣,它使用區塊鏈來進行交易記賬。
  前文爲了方便理解,省去了許多細節,爲了在實際接觸比特幣時不造成困惑,筆者認爲有幾點有必要說明一下.
  比特幣錢包軟件產生的賬戶,在比特幣術語裏通常叫地址(Bitcoin address),一個比特幣錢包可以產生很多個地址,這些地址用來接受別人的轉賬,這和電子郵地址有點相似,不同的是一個地址只用來接收一次轉賬。一個地址對應一個密碼,比特幣術語裏叫密鑰(private key),用戶對地址裏資金的使用權完全由密鑰來保障,因此安全地保存密鑰至關重要,一旦丟了,不存在重置密碼的說法。
  實際中,不少公司發行的錢包程序往往要用戶註冊,以便將用戶錢包軟件裏的賬戶密鑰數據加密存儲在公司服務器,用戶只要記得在該公司的賬戶密碼,即使弄丟了錢包程序裏的數據,還是可以通過存儲在該公司的備份找回,但這並非比特幣本身的內容。這相當於用戶自己有些金條(比特幣),在某個公司開了個保險櫃存放這些金條,但把這些金條放在家裏的保險櫃(加密的優盤)也是一樣的。將金條放在一家公司,意味着你對這家公司的實力非常有信心,它不會被盜賊攻 擊,也不會監守自盜。

二. 區塊鏈是什麼

  上文步驟三中我們說過,比特幣的使用授權不用經過像銀行這樣的中心繫統,它是用戶自己通過密碼算法來授權的。那爲什麼兩個用戶不直接交易,像金條一樣從自己荷包裏掏出來給對方就行了?爲什麼每次交易要像通知銀行一樣通知區塊鏈網絡?儘管比特幣在很多方面和天然貨幣黃金很相似,但卻有一個很大的不同:黃金沒法複製;而比特幣只是存在於優盤或電腦手機的數據,可以無限複製。這意味着張三把一份金條給李四後,他無法再把同樣的金條給別人;而張三把一份比特幣給李四後,他還可以再複製一份給其他人。怎麼解決這個問題呢?這就要用到區塊鏈了。
  簡單的說區塊鏈就是一個很多人或團體共同維護,所有人都可以訪問的賬本,賬本用來記錄每一次的比特幣轉賬,所有的用戶可以通過查詢賬本來了解自己錢包裏的餘額以及比特幣交易是否成功完成。
圖一區塊鏈
  如上圖所示,區塊鏈賬本分爲一個個區塊,每個區塊存儲了很多交易記錄,這些區塊按生成時間先後通過一定的方式連接起來,形成了一個鏈結構,這就是區塊鏈名字的來歷。圖中黃 色部分是上文例子在區塊鏈中形成的記錄。
  再來看區塊鏈怎麼解決上面的多重支付問題。收款方通過查詢區塊鏈是否有對應的轉賬記錄來檢查轉款是否到賬(對李四而言就是檢查是否有b到c的轉賬記錄);區塊鏈在記錄一筆轉賬交易前會先查詢同樣的一筆錢是否已經在區塊鏈記錄中轉給其它賬戶(張三的b賬戶是否已經轉出過錢),如果已經轉過,則認定當前轉賬非法而拒絕記錄該轉賬,這樣收款方就不能在區塊鏈賬本中找到對應的轉賬。
  在傳統的銀行交易系統中同樣存在類似賬本的設施,區塊鏈有什麼特別之處呢?在於我們上文所說的多人或團體共同維護,即去中心化。共同維護,意味着都可以往區塊鏈賬本中記賬,這帶來新的問題:怎麼保證每個記賬人都會誠實的記賬?比如怎麼防止張三給李四轉賬後,自己作爲記賬人,修改賬本把同樣的錢轉給自己?這要提到比特幣的另一個機制,就是通常所說的挖礦。
  假設每一個參與記賬(挖礦)的人都是唯利是圖,怎麼賺錢怎麼做(不考慮任何道德的約束),區塊鏈營造出了一個算法系統,讓每一個參與記賬的人都寧願通過誠實的記賬來獲取報酬。舉個栗子,有兩份工作:一份是搶銀行要花兩天時間,一份是挖金礦只花一天時間,挖金礦能獲得的報酬等於或大於搶銀行,理智的人都會選擇後者。區塊鏈的算法讓每個記賬的人都要花費一定的代價才能記賬,同時給記賬人獎勵。這裏的代價是計算時間,獎勵包括兩部分:一是從每筆交易抽取的佣金,二是由系統新產生的比特幣獎勵。第二項獎勵就是比特幣把記賬稱爲挖礦的原因了。
  區塊鏈記賬以區塊爲單位,把最新的交易記錄寫入一個區塊。記賬人擁有的計算設備,如礦機(專門用於挖礦的計算機)每次創建一個區塊記賬前都要先完成一道很難的迷題,誰先完成謎題誰就獲得記賬的權利和獲得報酬,大家也就以他生成的區塊,作爲最新的交易記錄追加到之前的賬本,當然新區塊要滿足一些基本規則,比如不和之前的賬本衝突,沒有記錄授權不正確的交易(這是靠前文說所的用戶地址和私鑰授來保證的)。
  這是什麼樣的一道謎題呢?有個很形象的比喻:擲骰子,誰先擲出滿足條件的骰子組合誰就獲勝。以兩顆骰子爲例,要扔出兩顆骰子之和不大於6的概率是41.6%,很容易,平均擲二到三次就有一次滿足。增加點難度,要求三顆骰子之和不大於4,那麼概率就只有1.8%,就是說平均擲50次以上骰子纔能有一次機會滿足條件,要花點時間來擲骰子了。但考慮到是很多計算機在擲骰子,速度很快,一般的礦機能輕易的一秒鐘擲上百億次,我們繼續通過增加骰子數和降低骰子數之和來增加難度,一直增加到全世界所有參加擲骰子的計算機一起玩,也才平均每十分鐘擲出一個滿足要求的組合。這大約會是怎樣的一種組合呢:一億個骰子擲出的總和不超過一億零幾十,想想擲一億顆骰子,幾乎每一顆都是1的概率。
  每個礦機都爭先記賬,誰先算出來謎題,誰就獲得記賬權和獲得報酬,即使某個礦機要做假賬,它也必須如此。同時由於區塊的鏈結構保證如果誰想要修改其中一個區塊的交易記錄,它必須重新創建這個區塊以及這個區塊以後所有已經創建的區塊,而每創建一個區塊都要花費大量時間去解決謎題。上文提到的比特幣加密授權機制能保證用戶最多能修改從自己賬戶轉出的交易記錄,爲了一筆交易的錢,他需要自己僞造多個區塊,由於之前已經存在正確的區塊,僞造區塊很有可能不被承認,從而損失挖礦收入。即使存在着某些願意做損人不利己買賣的記賬人能憑藉自身先進的計算設備比較快速的產生區塊來修改賬本,它也無法和整個區塊鏈網絡對抗,因爲正確的區塊鏈在不斷增長,而區塊鏈網絡總是以最長的區塊鏈爲正確的賬本。只要有51%的記賬人(假設每個記賬人有同樣的計算設備)覺得挖礦比搶銀行靠譜,區塊鏈網絡就能正常運作下去。以張三給李四轉賬以後,試圖修改賬本把錢又轉給自己爲例:
圖二僞造區塊鏈
  圖中CDE這幾個區塊是很多個記賬人共同算出來的,而C’D’只能靠張三一家計算,他的計算速度幾乎不可能趕上整個網絡的區塊生成速度,而且他生成的區塊會因爲得不到整個網絡的承認不能產生任何收益。實際中李四確認轉賬並不是在區塊C產生後立即確認,還會等到C,D,E等後面五個區塊形成後才確認(交易數額越大,往往等的區塊越多),這會進一步增加張三僞造區塊的難度。

三. 涉及的數據算法

  我們進一步深入,前文至少留下了這三個問題:
  1.用戶的交易授權是怎麼進行的,爲什麼不需要一箇中心機構來進行密碼驗證?
  2.爲什麼修改一個區塊,必須修改這個區塊後面所有的區塊,怎麼做到的?
  3.擲骰子這個謎題究竟是怎麼實現的?
  在解決這些問題前,我們先回顧一些基本算法。比特幣/區塊鏈涉及的算法,主要有兩類:1.哈希算法 2.非對稱加密。對這兩類算法不太瞭解的讀者,可以閱讀筆者之前的文章《構成信息安全技術體系的三類基本算法》。這裏我們簡要列出:
哈希或數據摘要:

byte[] hash(byte[] data);//爲了和比特幣開發文檔保持一致用hash代替digest.

非對稱加密:

class KeyPair  //密鑰對
{
    byte [] privateKey  //私鑰
    byte [] publicKey;  //公鑰
};
KeyPair generateKeyPair();//用於產生一個密鑰對
byte[] asyEncrypt(byte[] plainData,byte[] publicKey);   //用私鑰對數據加密
byte[] asyDecrypt(byte[] cipherData,byte[] privateKey); //用公鑰對私鑰加密的數據解密

四.交易授權

  首先比特幣錢包軟件爲用戶生成收款地址和祕鑰,這是通過調用generateKeyPair()來產生的,收款地址address=hash(KeyPair.publicKey),加一次hash的目的是爲了收款時不暴露用戶的publicKey,減少從publicKey推導privateKey的可能性,雖然目前還沒有通過publicKey推導出privateKey的案例。和收款地址對應的祕鑰就是KeyPair.privateKey,因爲比特幣採用的keyPair可以從privateKey推導出publicKey,所以錢包裏保存的數據就只是privateKey。以張三轉賬給李四的這個交易爲例,在區塊鏈裏產生的交易數據簡化後如下圖所示:
交易授權

  如圖中所示每次交易的授權是通過簽名來進行的,每個交易的輸入信息來源於之前交易的輸出(除了固定放在區塊鏈第一個位置的礦工收入獎勵,作爲一個特殊的交易,本文不討論)。圖中的簽名部分數據本身包含了一個publicKey,這實際上是構成了一個證書,見《構成信息安全技術體系的三類基本算法》數字證書一節。如張三獲得李四的收款地址後,就可以通過錢包軟件授權轉賬,即生成簽名,如下圖:
簽名

  生成簽名後,錢包軟件就將本次交易的輸入,輸出和簽名打包廣播到區塊鏈網絡中。區塊鏈網絡的礦工節點就開始驗證這個交易是否合法,驗證過程如下圖:
驗籤

  由此可見比特幣使用了傳統的數字簽名手段來完成了交易的授權。實際中比特幣的簽名和驗簽過程,是使用其定義的一個腳本來完成的。使用腳本可以做到更多的控制和更復雜的授權,如多方授權的合約交易。另外爲了個更強的安全性,許多地方求哈希時,做了多遍哈希,本文爲了簡便忽略了hash次數。

五.區塊鏈的鏈

  熟悉哈希計算的讀者應該能猜到區塊之間是通過一個個哈希值連接起來的,如下圖:
圖片描述

  我們將在下文討論難度值和隨機值。由圖可見,區塊A的任何修改,均會導致其區塊頭的變化,從而導致區塊B的區塊頭中哈希值的變化,這種變化會一直傳導到A之後的所有區塊。需要指出交易記錄的哈希值是一個稱爲“Merkle tree”的根節點,交易記錄發生任何變動都會導致“Merkle tree”根節點的變化,詳情可參閱相關文檔。

六.擲骰子

  擲骰子在區塊鏈中的術語叫工作量證明(Proof Of Work,縮寫POW),證明礦工生成區塊平均花費了規定的時間。擲骰子的過程,其實就是不停嘗試找到一隨機值,使得這個隨機值和區塊頭其它信息合在一起後計算出來的哈希值小於指定的難度值(這裏難度值越小,難度越大)。

圖片描述
  難度值是一個隨着區塊鏈網絡總的計算能力動態調整的值。每產生2016個新的區塊進行一次統計,如果平均每個區塊產生的時間少於10分鐘,難度就會增加一點(難度值減小);反之則減小難度(難度值增大)。

七.更多

  作爲一篇入門級文章,本文忽略了許多非核心的技術環節,以求在最短的時間內讓讀者對比特幣的技術架構有個初步瞭解。有進一步學習需求的讀者可以訪問比特幣官網bitcoin.org中的開發指南和參考文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章