1. 程式人生 > >比特幣協議工作原理

比特幣協議工作原理

比特幣

現在,讓我們離開Infocoin,轉向的真正的比特幣協議。比特幣和我們剛才一步步建立起來的Infocoin沒有多大的差別,除了一個明顯的改變。

要使用比特幣,首先你得在電腦裡安裝一個錢包。為了讓你更好的理解,下圖是一個叫做Multibit的錢包的截圖。你可以在左上角看到比特幣的餘額——0.06555555 個比特幣,按截圖的當時的交易價格來算將近70美元。截圖右邊顯示了兩個最近的交易,他們是存入這0.06555555個比特幣。

假設你是一個商家,你已經準備好了一個線上商店,你決定允許客戶用比特幣支付。你需要做的是,用你的錢包程式新生成一個比特幣地址。它會自動生成一對公鑰和私鑰,然後hash你的公鑰來形成你的比特幣地址。

然後你將你的比特幣地址發給要付給你錢的人。你可以用郵箱,或者直接放到你的網頁上。這是安全的,因為你的地址只不過是hash了的公鑰,你可以放心的公佈給任何人(沒人能通過它來得到你的私鑰)。 我會在後面解釋為什麼比特幣地址用的是公鑰的hash值而不是公鑰本身。

現在那個準備付錢的人需要建立一個新的交易。讓我們看一個真實的轉入0.319個比特幣的交易資料。下面這個就將近是原始資料了,這裡有三個地方的改變:1)資料沒有連續化;2)加了行編號,為了更好理解;3)省略了hash資料的一長串數字,只保留了前6位。

1.  {"hash":"7c4025...",
2.  "ver":1,
3.  "vin_sz":1,
4.  "vout_sz":1,
5.  "lock_time":0,
6.  "size":224,
7.  "in":[
8.    {"prev_out":
9.      {"hash":"2007ae...",
10.      "n":0},
11.    "scriptSig":"304502... 042b2d..."}],
12. "out":[
13.   {"value":"0.31900000",
14.    "scriptPubKey":"OP_DUP OP_HASH160 a7db6f OP_EQUALVERIFY OP_CHECKSIG"}]}

讓我們一行一行解釋。

第1行,交易hash值(16進位制),他是用來代表這個交易的唯一標記。

第2行,告訴我們這個交易用的是第一版本的比特幣協議。

第3、4行,告訴我們這個交易有一個輸入和一個輸出。(一個交易可以有多個輸入和多個輸出)

第5行,是一個鎖定時間(lock_time),可以用它來控制這個交易什麼時候完成。現在大多數的比特幣交易鎖定時間都是0,也就是馬上完成交易。

第6行,告訴我們這個交易的大小有多少個位元組(bytes),注意,這個不是交易的錢。

第7到11行,這一段定義了這個交易的輸入部分,確切的說,8到10行告訴我們要轉走錢的這個輸入值的錢是從上一個交易輸出值裡得來的。那個2007ae…就是上一個交易的16進位制的hash值,用來指向上一個交易。n=0說的是它是上一個交易裡面的第一個輸出,我們過一會兒會看到多個輸入和輸出是什麼樣子,所以現在先不用擔心。11行是那個傳送錢的人的數字簽名:304502… 空格之後是他的公鑰:04b2d… 同樣這兩個都是16進位制

這裡輸入部分值得注意的是,它並沒有說前一個交易中的比特幣,有多少會轉給後一個。實際上,在前一個交易裡面n=0的輸出內所有的比特幣都被轉移了。比如說,如果前一個交易裡的第一個輸出(n=0)裡面有2個比特幣,那麼這兩個比特幣在新的這個交易中都會被花掉。這看起來很不方便,就好像用20美元的現金去買一個麵包一樣。解決辦法是提供一個找零錢的機制,這一點可以通過多個輸入和輸出的方式解決,下一部分就會講到。

第12到14行,這段定義了交易的輸出。具體說,13行告訴我們輸出的錢的數量,這裡是0.319個比特幣。14行比較複雜,值得注意的是字串a7db6f…是收取比特幣的地址。這一行其實是一段比特幣的指令碼語言,在這裡不細講指令碼語言的細節。你只需要知道a7db6f…是收取的地址就行了。

現在,你可以看到比特幣是如何解決我們之前提到的“序列號從哪裡來”的問題了。第一,比特幣並不是分開的一個個單獨的“幣”,而是一長串存在於blockchain裡的交易。通過儲存一個交易賬本來實現比特幣是一個很聰明的想法。第二,通過這種方式,我們不需要一箇中央機構來發布序列號。序列號可以通過hash交易本身來得到。

我們可以一直順著交易鏈一直往回看。最終到頭的時候,有兩種可能,第一,你可能會走到第一個比特幣交易,這個交易存在一個block裡,我們把這個block叫做“Genesis block (初始區塊)”。這是一個特殊的交易,它沒有輸入,只有50個比特幣的輸出。換句話說,它是最最早的比特幣供應。Genesis block被比特幣客戶端區別對待,這裡不去細講。

第二個順著交易鏈一直往回看得到的結果可能是你到達了一個被稱作“coinbase”的交易。除了Genesis block之外,每個block裡都開始於一個特殊的coinbase交易。這個交易是用來獎賞驗證這個block裡交易的挖礦者的。它用了和上述類似的資料形式,具體也不細講了,對coinbase交易感興趣的話可以看這裡

上面的描述不是很清楚的是,在11行裡面被數字簽名的東西到底是什麼。最顯然的是辦法是讓支付者把整個交易進行數字簽名。現在來說它不是這樣做的,一些交易被忽略了。這使得交易的一部有了可塑性,也就是說,它們可以在以後進行修改。然而,這個可塑的內容裡並不包括交易的數量,付款人和收款人。可塑性的問題在比特幣社群內有很多討論,有人希望去取消它,這裡不細談。

有多個輸入和輸出的交易

上一段裡面我們講了一個只有單個輸入和單個輸出的交易資料。實際上,大多比特幣交易都是有多個輸入或者多個輸出的。我們先看看這個交易的原始資料

1. {"hash":"993830...",
2. "ver":1,
3. "vin_sz":3,
4.  "vout_sz":2,
5.  "lock_time":0,
6.  "size":552,
7.  "in":[
8.    {"prev_out":{
9.      "hash":"3beabc...",
10.        "n":0},
11.     "scriptSig":"304402... 04c7d2..."},
12.    {"prev_out":{
13.        "hash":"fdae9b...",
14.        "n":0},
15.      "scriptSig":"304502... 026e15..."},
16.    {"prev_out":{
17.        "hash":"20c86b...",
18.        "n":1},
19.      "scriptSig":"304402... 038a52..."}],
20.  "out":[
21.    {"value":"0.01068000",
22.      "scriptPubKey":"OP_DUP OP_HASH160 e8c306... OP_EQUALVERIFY OP_CHECKSIG"},
23.    {"value":"4.00000000",
24.      "scriptPubKey":"OP_DUP OP_HASH160 d644e3... OP_EQUALVERIFY OP_CHECKSIG"}]}

像之前一樣,我們一行行解釋,大部分和剛才的是一樣的。

第1行,交易的hash值,用來作為這個交易的唯一標記。

第2行,比特幣協議的版本,第一版。

第3、4行,是說這個交易裡有3個輸入,2個輸出。

第5行,鎖定時間(和之前的一樣)。

第6行,交易的位元組大小。

第7到19行,定義了所有的輸入,每一個都對應這前一個交易的輸出。第一個輸入是8到11行。其內容形式和之前的一樣。 第二個輸入是12到15行,第三個是16到19行。

第20到24行,定義了所有的輸出,第一個輸出是21和22行,和之前一樣,21行說的是裡面有0.01068個比特幣。22行是一段比特幣的指令碼語言。字串e8c30622…是收款人的地址。 第二個輸出是23和24行,格式同上。

看起來有些奇怪的是,雖然每個輸出都有記錄著比特幣的數量,但是輸入卻沒有。當然每個輸入有多少比特幣可以從它的上一個交易中得到。在一個普通的比特幣交易中,所有的輸入價值之和要大於多有的輸出(除了剛才說的Genesis block和coinbase交易之外),如果輸入之和大於輸出,那麼多餘的比特幣就會作為交易費提供給這個交易所在的block的挖礦者。

多個輸入和輸出的作用是找零。假設我想要給你0.15個比特幣。我可以花掉我之前收到的0.2個比特幣。當然,我不想給你全部0.2個,所以解決辦法就是,我給你發0.15個比特幣,然後再給我自己的另外一個比特幣地址發0.05個比特幣。這樣,那0.05就是給我的找零。這個概念和你在現實商店裡的找零不太一樣,這個更像是你給你自己付錢。但是大致意思是一樣的。

結語

比特幣背後的基本概念就算是描述完了。當然,我也忽略了許多細節——這畢竟不是一個正式的說明書。但是我想描述的是通常使用的比特幣背後的概念。

雖然比特幣後面的規則是簡單和容易理解的,這並不意味著這些規則將產生的所有可能結果也容易理解。對於比特幣可以說的還有很多,我會在以後的文章中闡述一些。但是現在,我姑且做一些零碎的總結。

比特幣有多麼匿名?許多人說比特幣可以匿名使用。這個說法形成於類似Silk Road之類的黑市。然而這個說法是虛構的。Blockchain是公開的,也就意味著任何人都可以看所有的比特幣交易。雖然比特幣地址並沒有直接和真實世界裡人物的身份相對應,但電腦科學家們已經做了很多工作去解密“匿名”的社交網路。Blockchain是他們一個極好的目標。在不遠的將來,如果大多數比特幣使用者身份還都不能相對有信心的識別出來,那我感到會非常驚奇。這個識別不一定會完全確認,但是足夠提供有著很大可能性的目標。此外,身份將會是可追溯的,這意味著那些2011年在Silk Road上賣毒品的人,仍然可以在2020年在blockchain上找到。這些反匿名技術對電腦科學家來說是眾所周知的,甚至可以說包括NSA(美國國家安全域性)也知道。如果說NSA或者其他機構已經反匿名了很多使用者的話,我並不會覺得奇怪。比特幣被吹捧成匿名的這個說法是有點滑稽的。它不是匿名的,相反,比特幣可能是迄今為止世界上最為公開和透明的金融工具。

你能通過比特幣發財嗎?也許吧,Tim O’Reilly 曾經說過 “錢就像是汽車裡面的油——你需要注意,否則就會困在路邊上——但是生活不是圍繞著加油站轉圈!” 大多數對比特幣的興趣似乎來自於那些人生目標僅僅是找到一個大的加油站的人。我必須承認,這個讓人困惑。我相信更有趣的、更享受的是把比特幣或者其他數碼貨幣看做一個塑造新的人類合作行為的工具。那是理性上的迷人,提供了巨大的創新的可能,它是有社會價值的,同樣也可能會賺到一些錢。但是如果賺錢是你的主要目的,那我相信有其他更容易成功的辦法。

我所忽略的細節:雖然這篇文章描述了比特幣背後的主要概念,但有很多細節我並沒有提到。其中之一是協議裡面的很棒的節省空間的技巧,基於一個叫做Merkle tree的資料結構。這是細節,但它是一個極其精彩的細節,如果你喜歡資料結構的話,很值得去看看。你可以通過比特幣白皮書瞭解大概情況。第二,我幾乎沒有提到比特幣網路——其中一些問題比如,這個網路如何處理拒絕了的伺服器攻擊,節點是如何加入和離開網路的,等等。這是個很有意思的話題,但同時也是包含很多細節的話題,所以我在這裡忽略了。你可以通過上面的一些連結來閱讀更多與之相關的東西。

比特幣指令碼:在這篇文章裡,我解釋了比特幣作為一個線上的電子貨幣。但是這只是更大更有趣的故事之中的一小部分。正如我們所見,每個比特幣交易裡都有一段比特幣指令碼語言。這個指令碼在這篇文章裡被簡化成了類似於這樣的話 “我Alice要給Bob 10個比特幣”。 但是這個指令碼語言可以同時被用來表述更復雜的交易。換句話說,比特幣是一個可程式設計的貨幣。在以後的文章裡,我會解釋這個腳本系統和如何將比特幣指令碼作為一個平臺來支援各種各樣的令人驚歎的金融產品。

如果覺得有幫助,建議你Tip給這篇文章的原作者Michael Nielsen, 他的地址是17ukkKt1bNLAqdJ1QQv8v9Askr6vy3MzTZ , 你也可以follow他的Twitter 。 或者關注他的將要出版的關於neural networks and deep learning新書的第一章