來源:一個故事告訴你比特幣運行機制html
週末花時間看了一些比特幣原理相關的資料,雖然不敢說把每一個細節都徹底搞懂了,不過總體思路和關鍵部分的主要原理仍是比較明白。寫一篇文章分享給你們。這篇文章的定位會比較科普,儘可能用類比的方法將比特幣的基本原理講出來。這篇文章不會涉及算法和協議中比較細節的部分,打算後面會再寫一篇程序員視角下的比特幣原理,那裏會從技術人員的視角對比特幣系統中較爲關鍵的數據結構、算法和協議進行一些講解。程序員
在這篇文章中我會給出一個虛擬的村莊叫「比特村」,整個文章會以講故事的方式,逐步告訴你們比特幣提出的動機、解決了什麼問題以及一些關鍵組件的目標和設計方案。算法
咱們先從比特幣產生的動機開始。數據結構
話說在這個世界上,有一個叫比特村的小村莊,村莊共有幾百戶人家。這個村莊幾乎與世隔絕,過着自給自足的生活。因爲沒有大規模貿易,比特村村民一直過着以物易物的生活,也就是說村民之間並無使用統一的貨幣,互相間的貿易基本上就是老張家拿一袋麪粉換老李家一隻羊,王大嫂拿一筐野果換劉大嬸兩尺布。村民們一直就這麼純樸的生活着。分佈式
終於有一天,村民以爲一直這樣以物易物實在太不方便了,因而村子全員開會,討論如何解決這個問題。有人提議,以便於分割且稀有的東西,例如黃金,做爲通常等價物,把其它物品和黃金的對應關係編成一張表格,例如一克黃金對應一隻羊,一克黃金對應一袋麪粉等等,此時老張不再用扛着一袋麪粉氣喘吁吁的去老李家換羊了,他只要從家裏摸出一克金子,就能夠去老李家牽回一隻羊,而老李拿着這一克黃金能夠從任何願意出讓麪粉的人那裏換回一袋麪粉,固然也能夠換取任何和一克黃金等值的物品。函數
此時比特村進入了實物貨幣時代。工具
好景不長,過了一段時間,實物貨幣的弊端也出現了。由於比特村附近金礦並很少,開採和冶煉金子太費時費力了。而隨着使用,金子老是不斷會由於磨損、丟失或有人故意囤積而發生損耗。全村人又一次坐在了一塊兒,開始商討對策。此時有人說,其實你們也沒必要必定要真的用黃金啊,隨便找張紙,寫上「一克黃金」,只要全村人都認同這張紙就等於一克黃金,問題不就解決了。其餘人紛紛表示認同,但同時也有了新的問題:真實的黃金是須要開採和冶煉的,金礦有限,開採和冶煉也須要成本,因此沒有人能夠短時間憑空製造大量的黃金,可寫字就不一樣了,只要我紙夠筆夠,隨便像寫多少寫多少,那這就變成拼誰家裏紙多了,搞很差到時一萬張紙才能換一隻羊(實際上這就發生了經濟學上的通貨膨脹)。字體
你們一想也是啊。不過此時又有人提出瞭解決方案:這個紙不是誰寫都有效,咱們只認村裏德高望重的老村長寫得,你們都認識老村長的字。老村長寫一些紙,同時按照各家黃金存量發給你們等量的紙,例如老張家有二百克黃金,老村長就發給老張二百張寫着「一克黃金」的紙,同時將老張家的黃金拿走做爲抵押。就這樣,老村長將村裏全部黃金收歸到本身的家裏,並按各家上交的黃金數量發給等值的寫有字的紙。此時村民就能夠拿着這些紙當黃金進行貿易了,並且你們都認得老村長的字,其餘人僞造不出來。另外,若是誰的紙磨損太嚴重,也可拿到老村長那裏兌換新的等值的紙,另外老村長承諾任何人若是想要換成真黃金,只要拿紙回來,老村長就會把等值的黃金還給那人。由於老村長寫得紙的黃金量和真實放在家裏的黃金量是同樣的,因此只要嚴格按照銷燬多少紙新寫多少紙的原則,每一張有效的紙總能換回相應的真黃金。編碼
此時,比特村進入了符號貨幣(紙幣)時代。而老村長就承擔了政府和銀行的角色。加密
又過了幾年,老村長因爲天天都要覈對大量的舊紙幣,寫新的紙幣,還要把各類帳目仔細作好記錄。一來二去,老村長操勞過分不幸駕鶴西去了。
比特村再次召開全體大會,討論應該怎麼辦。此時老村長的兒子二狗子挺身而出接過了父親的筆,承擔起貨幣發行的責任。這個年輕的村長二狗子很聰明,他作了幾天,發現好像也不用真的寫那麼多紙。徹底能夠這樣:村民把紙幣都交上來,銷燬,可是二狗子會記錄下每戶上交的紙幣數量。之後若是要進行付錢,例如老張要拿一克金子向老李換一隻羊,就一塊兒給二狗子打個電話,說明要將老張名下的一克金子劃歸老李名下,二狗子拿出帳本,看看老張名下是否有一克金子,若是有就在老張的名下減掉一克,在老李的名下加上一克,這樣就完成了支付,此時老李在電話中聽到二狗子確認轉帳完成,就能夠放心讓老張把羊牽走了。
此時比特村進入了中央系統虛擬貨幣時代。每一個村民都不須要用實物支付,支付過程變成了二狗子那邊維護的帳本上數字的變動。
這新上任的二狗子是聰明,不過這人有時候是聰明反被聰明誤。有一天二狗子盯着這帳本,心想這全村各戶誰有多少錢就是我說的算,那我豈不是……。因而他頭腦一熱,私自從老張賬下劃了十克金子到本身名下。
本覺得完美無缺,但沒想到老張也有記帳的習慣,有一天他正要付錢卻被二狗子告知帳戶沒錢了。老張覈對了一下本身的帳本,明明還有十克啊,因而拿着帳本去找二狗子理論,這一覈對發現了那筆未經老張贊成的轉帳。
東窗事發!比特村炸開鍋了。二狗子被彈劾是不可避免了,不過經過這件事,你們發現了帳本集中在一我的手裏的弊端:
正當人們不知所措時,村裏一個叫中本聰的宅男科學家走上了臺,告訴你們他已經設計了一套不依賴任何中央處理人的叫比特幣的虛擬貨幣系統,能夠解決上述問題。而後他緩緩講述了本身的方案。
下面咱們就來看看中本聰同窗是如何設計這套系統的。
中本聰首先說明,要對現有帳簿進行以下改造:
此言一出,下面馬上炸鍋了。第一條還無所謂,可是第二條簡直沒法接受,由於帳簿但是記錄了全部村民的交易,這樣你們的隱私不全暴露了嗎。
中本聰卻是鎮定自若,拿出了一對奇怪的東西。
中本聰說,你們不要慌。在他的這套機制下,任何人都不使用真實身份交易,而是使用一個惟一的代號交易。
他展現了手裏神奇的東西,說這兩件東西分別叫保密印章和印章掃描器。後面他會給村裏每一戶發一個保密印章和一個印章掃描器。二者的做用以下:
有了這兩個神奇的東西,你們就能夠在不暴露真實身份的狀況下進行交易了,而印章隱含的那一串字符就是這戶人家的代號。具體如何巧妙利用保密印章和印章掃描器進行交易,會在下文詳述。
下一步,中本聰面向全村招募虛擬礦工,招募要求以下:
很快,大約有五分之一的村民加入比特幣礦工組織,共分紅了7個組。
下面,中本聰宣佈,先根據二狗子手裏的帳簿,把抵押的全部黃金按帳簿記錄的餘額退還給每位村民,而後完全銷燬這本帳簿。
而後,中本聰拿出一本新帳簿,在帳簿的第一頁上記錄了一些交易記錄,特別的是,這些記錄的付款人一欄全都是「系統」,而收款人分別是每一個印章對應的隱含字符,表明初始時刻,系統爲每一戶默認分配了必定數量比特幣,可是數量很是少,都只有幾枚,甚至有些不幸的村戶沒有得到比特幣。
接着中本聰說,因爲目前市面上比特幣很是少,你們能夠先回到用黃金作貨幣的時代,因爲我不是村長,我也沒有權利強迫你們必定要認可比特幣,你們能夠自行決定要不要接受比特幣。不過隨着比特幣的流動和礦工的活動,比特幣會慢慢多起來。
作了這麼多鋪墊,終於說到重點了,下面說一下在這樣一個體系下如何完成支付。以老張付給老李10個比特幣爲例。
爲了支付10個比特幣,老張首先要詢問老李的標識字符串,例如是「ABCDEFG」,同時老張也有一個標識字符串例如是「HIJKLMN」,而後老張寫一張單子,內容爲「HILKLMN支付10比特幣給ABCDEFG」,而後用本身的保密印章改一個章,將這張單子交給老李。另外爲了便於追溯這筆錢的來源,還要在單子裏註明這筆錢的來源記在哪一頁,例如這個單子裏,老張的10比特幣來自創建帳簿時系統的贈送,記錄在帳簿第一頁。
老李拿到這個單子後,須要確認這個單子確實是來自「HIJKLMN」這我的(也就是老張)簽署的,這個並不困難。由於單子上必須有保密章,老李拿出印章掃描器,掃一下章,若是液晶屏顯示出的字符和付款人字符是一致的(這裏是「HIJKLMN」),就能夠確認單子確實是付款人簽署的。這是由於根據保密印章的機制,沒有其餘人能夠僞造印章,任何一我的只要掃描一下印章,均可以確認單子的付款人和蓋章人是否一致。
這個系統到目前仍是頗有問題。經過保密印章,收款人雖然能夠確認付款人確實簽署了這份單子,可是沒法自行確認付款人是否有足夠的餘額支付。以前的中央虛擬貨幣系統中,二狗子負責檢查付款人的餘額,並通知收款人交易是否有效,如今把二狗子開了,誰來負責記帳和確認每筆交易的有效性呢?
以前說過,中本聰設計的這個系統是分佈式貨幣系統,不依賴任何中央人物,因此不會有一個或少數幾我的負責這件事,最終承擔這份工做的是以前所提到的礦工組織。老張、老李和全村其餘任何使用比特幣進行交易的村民都依賴礦工組織的工做才能完成交易。
礦工的工做是整個系統的核心,也是最複雜性最高的地方。下面逐步介紹礦工的工做內容和目的。
俗話說,工欲善其事,必先利其器。比特幣礦工雖然不用鐵撅、鐵杴和探照燈等工具,不過也要有一些必備的東西。
初始帳簿。每一個組首先本身複製一份初始帳簿,初始帳簿只有一頁,記錄了系統的第一次贈送
空帳簿紙。每一個小組有若干帳簿紙,每一頁紙上僅有帳簿結構,沒有填內容,具體內容的書寫規則後面講述。下面是一張空帳簿紙的樣子,各個字段的意義後面會說到
編碼生成器(哈希函數)。中本聰又向礦工組織的每一個組分發了若干編碼生成器,這個東西很神奇,將一頁帳簿填好內容的帳簿紙放入這個機器,機器會在帳簿紙的「本帳單編號」一欄自動打印一串由「0」和「1」組成的編號,共256個。最神奇的是,編號生成器有以下功能:
有了上面的工具,礦工組織就能夠開工了!
中本聰規定,每筆交易的發起人,不但要將交易單給到收款人,還要同時複製若干份如出一轍的交易單投遞到每一個礦工小組的收件箱裏。
礦工小組的人按期到本身的收件箱裏把收集到的交易單一併取出來。
此時小組的人拿出一張空的帳簿紙,把這些交易填寫到「交易清單」一欄,同時找到當前帳簿最後一頁,將最後一頁的編號抄寫到「上一張帳單編號一欄」。 注意還有個「幸運數字」,能夠隨便填上一個數字,如12345。而後,將這樣帳簿紙放入編號生成器,打印好編號,一張帳簿就算完成了。
若是你覺得礦工的工做就這麼簡單,那就大錯特錯了,中本聰有個變態的規定:只有編號的前10個數均爲0,這頁帳簿紙纔算有效。
根據以前對編號生成器的描述,要修改編號,只能修改帳簿紙的內容,而「交易清單」和「上一張帳簿紙編號」是不能隨便改的,那麼只能改幸運數字了。因而爲了生成有效的帳簿紙,小組裏的礦工就不斷抄寫帳簿紙,但每張紙的幸運數字都不一樣,而後不斷的重複將紙放入編碼器,若是生成的編號不符合規定,這張紙就算廢了,重複這個過程直到生成一串有效的編號。
咱們知道,若是編號的每個數字都是隨機的,那麼平均寫1000多張幸運數字不一樣的紙才能得到一個有效的編號。
這就奇怪了,這些礦工爲何要拼命幹這看似無心義的事情呢?還記得以前說過礦工有報酬吧,這就是礦工的動力了。中本聰規定:每一張帳簿紙的交易清單第一條交易爲「系統給這個小組支付50個比特幣」。也就是說,若是你生成了一張有意義的帳簿紙,而且被全部挖礦小組接受了,那麼就意味着這條交易也被接受了,你的挖礦小組得到了50個比特幣。
這就是礦工被叫作礦工的緣由,也是爲何以前說隨着交易和礦工的活動,比特幣的數量會不斷增多。例以下面是一個挖礦過程,這個小組的公共比特幣賬號爲「UVWXYZ」。
在幸運數字嘗試到「533」時,系統生成了一頁有效帳簿。
當某挖礦小組幸運的生成了一張有意義的帳簿,爲了獲得獎勵,必須馬上請其它小組確認本身的工做。前面說過,當前村裏有7個挖礦組,因此這個小組必須將有效帳簿紙謄抄6份馬不停蹄送到其餘6個小組請求確認。
中本聰規定,當某個小組接到其餘小組送來的帳簿紙時,必須當即停下手裏的挖礦工做進行帳簿確認。
須要確認的信息有三個:
首先看第一個,這個確認比較簡單。只要將送來的帳簿紙放入編碼生成器進行驗證,若是驗證經過,則編號有效。
第二部分須要將帳簿頁上的「上一頁帳簿紙編號」和這個小組目前保存的有效帳簿最後一頁編號比對,若是相同則確認,若是不一樣,須要順着已有帳簿向前比對,直到找到這個編號的頁。若是沒有找到指定的「上一頁帳簿紙編號」對應的頁,這個小組會將此頁丟掉。不予確認。
注意,由上面的機制能夠保證,若是各個小組手裏的帳簿紙是相同的,那麼他們都能按一樣的順序裝訂成相同的帳簿。由於後面一張紙的編號老是依賴前面的紙的編號,編碼生成器的機制保證了全部合法帳簿紙的相對前後順序在每一個小組那裏都是相同的(可能會有分支,但不會出現環,後面細講)。
最後是如何確認交易清單有效,其實也就是要確認當前每筆交易的付款人有足夠的餘額支付這筆錢。因爲交易信息裏包含這筆錢是如何來的,還包含了記錄來源交易的帳單編號。例如,HIJKLMN要給ABCDEFG10個比特幣,並註明了這10個比特幣來自以前OPQRST支付給HIJKLMN的一筆交易,確認時首先要確認以前這筆交易是否存在,同時還要檢查HIJKLMN在這以前沒有將這10個比特幣支付給別人。這一切確認後,這筆交易有效性就被確認了。
其中第一筆是系統獎勵給生成這頁帳簿的小組的50個,這筆交易你們都默認認可,後面的只要按照上述方法追溯,就能夠確認HIJKLMN是否當前真有10個比特幣支付給ABCDEFG。
若是完成了全部了上述驗證並所有經過,這個小組就承認了上述帳簿紙有效,而後將這張帳簿紙併入小組的主帳簿,捨棄目前正在進行的工做,後面的挖礦工做會基於這本更新後的主帳本進行。
對於挖礦小組來講,當帳簿紙送出去後,若是後面有收到其餘小組送來的帳簿紙,其「上一頁帳簿紙編號」爲本身以前送出去的帳簿紙,那麼就表示他們的工做成功被其餘小組承認了,由於已經有小組基於他們的帳簿紙繼續工做了。此時,能夠粗略的說能夠認爲已經獲得了50個比特幣。
另外,任何一個小組當新生成有效帳簿紙或確認了別的小組的帳簿紙時,就將最新被這個小組認可的交易寫到公告牌上,那麼收款人只要發現相關交易被各個小組承認了,基本就能夠認爲這筆錢已經到了本身的帳上,後面他就能夠在付款時將錢的來源指向這筆交易了。
以上就是整個比特幣的支付體系。下面咱們來分析一下,這個體系爲何能夠工做下去,以及這個體系可能面臨的風險。
雖然上面闡述了比特幣的基本運做規則,可是村民們仍是有很多疑問。因此中本聰同窗專門開了個答疑會,解答常見問題。下面總結一下村民最集中關心的問題。
注意在上面的運行機制中,各個挖礦小組是並行工做的,所以徹底可能出現這樣的狀況:某小組收到兩份不同的帳簿頁,它們都基於當前這個小組的主帳簿的最後一頁,而且內容也都徹底合法,怎麼辦?
關於這個問題,中本聰同窗說,小組不該該以線性方式組織帳簿,而應該以樹狀組織帳簿,任什麼時候刻,都以當前最長分支做爲主帳簿,可是保留其它分支。舉個例子,某小組同時收到A、B兩份帳簿頁,經覈算都是合法的,此時小組應該將兩頁以分叉的形式組織起來,以下圖所示:
黑色表示當前帳簿主幹。此時,能夠隨便選擇一個頁做爲當前主分支,例如選擇A:
此時若是有一個新的帳簿頁是基於A的,那麼這個主幹就延續下去:
若是這個主幹一直這麼延續下去,表示你們基本都以A爲主幹,B就會被遺忘。可是也有可能突然B變成更長了:
那麼咱們就須要將B分支做爲當前主幹,基於這個分支進行後續工做。
從局部來看,雖然在某一時刻各個小組的帳簿主幹可能存在不一致,但大方向是一致的,那些偶爾因爲不一樣步產生的小分支,會很快被淹沒在歷史中。
關於這個問題,中本聰同窗說,只要挖礦組織中大多數人是誠實的,這個系統就可靠,具體分幾個方面給予答覆。
首先,基於保密印章機制,沒有人能僞造他人身份進行付款,由於編碼生成器在打印編碼時會覈對全部交易單的保密印章,印章和付款人不一致會拒絕打印。
並且誠實的礦工也不會認可不合法的交易(如某筆交易付款方餘額不夠)。
因此只有一種可能的攻擊行爲,即在收款人確認收款後,從另外一條分支上創建另外的交易單,取消以前的付款,而將同一筆錢再次付款給另外一我的(即所謂的double-spending問題)。下面一樣用一個例子說明這個問題。
先假設有一個攻擊者擁有10個比特幣,他準備將這筆錢同時支付給兩名受害者A和B,並都獲得認可。
第一步,攻擊者準備從受害者A手裏買10比特幣的黃金,他簽署交易單給受害者A,轉10個比特幣給受害者A。
第二步,這筆交易在最新的帳簿頁中被確認,並被各個挖礦小組公告出來。受害人A看到公告,確認比特幣到帳,給了攻擊者10個比特幣等值的黃金。
第三步,攻擊者找到帳簿,從包含剛纔交易的帳簿頁的前一頁作出一個分支,生成更多的帳單頁,超過剛纔的分支。因爲此時剛纔攻擊者製造的分支變成了主幹分支,而包含受害者A獲得錢的分支變成了旁支,所以挖礦組織再也不認可剛纔的轉帳,受害者A獲得的10比特幣被取消了。
第四步,攻擊者能夠再次簽署交易單,將同一筆錢支付給受害者B。受害者B確認錢到帳後,支付給攻擊者等值黃金。
至此,攻擊者將10個比特幣花了兩次,從兩名受害者那裏各購得等值黃金。攻擊者還能夠如法炮製,取消與受害者B的轉帳,將同一筆錢再支付給其餘人……
關於這種攻擊,中本聰給出的解決方案是,建議收款人不要在公告掛出時當即確認交易完成,而是應該再看一段時間,等待各個挖礦小組再掛出6張確認帳簿,而且以前的帳簿沒有被取消,才確認錢已到帳。
中本聰解釋道,以前設定變態的編號規則,正是爲了防護這一點。根據前面所述,生成有效帳簿頁不是那麼簡單的,要花費大量的人力反覆試不一樣的幸運數字,並且過程徹底是碰運氣。若是某帳簿頁包含你收到錢的確認,而且在後面又延續了6個,那麼攻擊者想要在落後6頁的狀況下從另外一個分支趕超當前主分支是很是困難的,除非攻擊者擁有很是多的人力,超過其餘全部誠實礦工的人力之和。
並且,若是攻擊者有如此多人力,與其花這麼大力氣搞這種攻擊,還不如作良民挖礦來的收益大。這就從動機上杜絕了攻擊的造成。
中本聰說,這一點我也想到了。前面忘了說了,我給礦工組織的操做細則手冊會說明,剛開始咱們協議每生成一頁帳簿,獎勵小組50個比特幣,後面,每當帳簿增長21,000頁,獎勵就減半,例如當達到210,000頁後,每生成一頁帳簿獎勵25個比特幣,420,000頁後,每生成一頁獎勵12.5個,依次類推,等帳簿達到6,930,000頁後,新生成帳簿頁就沒有獎勵了。此時比特幣全量約爲21,000,000個,這就是比特幣的總量,因此不會無限增長下去。
到時,礦工的收益會由挖礦所得變爲收取手續費。例如,你在轉帳時能夠指定其中1%做爲手續費支付給生成帳簿頁的小組,各個小組會挑選手續費高的交易單優先確認。
不會。中本聰解釋,雖然能夠任意加入和退出礦工組織,致使礦工人數變化,每一個礦工也會拿到一個編碼生成器,不過我已經在編碼生成器中加入了調控機制,當前工做的編碼生成器越多,每一個機器的效率就越低,保證新帳簿頁生成速率不變。
確實是這樣的。例如你要和某人交易,必然要要到他的代號才能填寫交易單。由於收款人一欄要填入那人的代號。不過中本聰說能夠提供無限制的保密印章,建議每一次交易用不一樣的保密印章,這樣查帳簿就追查不到同一我的的全部帳目了。
答疑完畢。