常見的比特幣與區塊鏈入門文章大約分爲兩類,一類是面向非開發人員的科普讀物;另外一類是面向開發人員的技術指南。前者易流於淺表,讓讀者接觸了一堆名詞和概念,卻沒法對比特幣與區塊鏈有個直觀的認識;然後者又每每直接進入細節,使開發人員一葉障目不能從全局瞭解技術概貌。本文嘗試將這兩類文章合二爲一,同時避免上述兩種缺陷。文章前部分適合想了解比特幣和區塊鏈的非開發人員,整篇文章適合想轉入比特幣與區塊鏈相關開發的技術人員。算法
瞭解一個陌生事物最快的方法,莫過於和一個熟知的事物進行對比,找出差別,研究差別。以轉帳支付爲例,來講明傳統貨幣轉帳和比特幣轉帳時分別發生了什麼。這裏說的傳統貨幣特指由各個國家發行的法訂貨幣,如美圓,人民幣等,也包括這些貨幣在銀行系統中的虛擬形式,如人們在銀行的存款。如下統稱法幣。
下表爲張三分別用法幣和比特幣向李四轉帳的步驟:segmentfault
步驟 | 法幣 | 比特幣 | 備註 |
---|---|---|---|
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次數。spa
熟悉哈希計算的讀者應該能猜到區塊之間是經過一個個哈希值鏈接起來的,以下圖:
咱們將在下文討論難度值和隨機值。由圖可見,區塊A的任何修改,均會致使其區塊頭的變化,從而致使區塊B的區塊頭中哈希值的變化,這種變化會一直傳導到A以後的全部區塊。須要指出交易記錄的哈希值是一個稱爲「Merkle tree」的根節點,交易記錄發生任何變更都會致使「Merkle tree」根節點的變化,詳情可參閱相關文檔。
擲骰子在區塊鏈中的術語叫工做量證實(Proof Of Work,縮寫POW),證實礦工生成區塊平均花費了規定的時間。擲骰子的過程,其實就是不停嘗試找到一隨機值,使得這個隨機值和區塊頭其它信息合在一塊兒後計算出來的哈希值小於指定的難度值(這裏難度值越小,難度越大)。
難度值是一個隨着區塊鏈網絡總的計算能力動態調整的值。每產生2016個新的區塊進行一次統計,若是平均每一個區塊產生的時間少於10分鐘,難度就會增長一點(難度值減少);反之則減少難度(難度值增大)。
做爲一篇入門級文章,本文忽略了許多非核心的技術環節,以求在最短的時間內讓讀者對比特幣的技術架構有個初步瞭解。有進一步學習需求的讀者能夠訪問比特幣官網bitcoin.org中的開發指南和參考文檔。