區塊鏈(Bitcoin)簡介
前言
10月快結束了。這個月一直在除錯sawtooth,坑太多了,填都填不過來。準確說這大半年來都是在搞區塊鏈hyperledger sawtooth。最近我也會在部門做這方面的share,所以把這篇自己對區塊鏈的理解文章貼上來湊數了。 文章主要還是基於bitcoin來分析,最核心的材料是中本聰寫的<BitCoin: A Peer-to-Peer Electronic Cash System>。看過bitcoin,自己工作中用的是sawtooth,本質原理上區塊鏈都是一致的,核心區別是consensus演算法。 這篇文章是briefly的介紹。想說明白blockchain設計初衷,解釋blockchain最初想解決的痛點。希望可以區分虛擬的幣和區塊鏈之間的關係。
為什麼需要區塊鏈?
當前網際網路上的交易(購物/購票等消費)需要依賴可信的第三方支付機構(支付寶,Paypal等)。 這種支付模式在大多數情況下都挺好用的,但因為這種模式是基於信任第三方建立的,所以天生就有某些缺點。比如:
A. Non-reversible transactions.
Bitcoin強調要做到交易不可撤銷。我搜索了國外刷信用卡交易的一下rules。他們為了保護消費者,在刷信用卡交易過程中如果發生爭議,可以通過charge back來請求撤銷交易。且消費者請求charge back時可以繞過商家,直接找支付機構,提供相關理由和證據。支付機構仲裁後便會把錢直接退給消費者的。 在正常情況下,這種操作可以一定程度上保護消費者。但它很容易被人惡意利用,這對商戶來說就是潛在的交易風險。
B. Increases transaction costs.
增加交易成本。以支付寶為例,不論使用APP支付還是當面付,商戶都需要支付費率。這在無形中增加了交易成本。
C. Limiting the minimum transaction size.
限制交易最低金額。這個和支付費率有關,從前兩幅圖的支付費率看,目前支付寶並沒有限制交易最低金額,但它事實上有能力去做這個。先以銀行轉賬為例說明這個問題。比如銀行之間跨行轉賬會收取轉賬費,最低要求2塊/筆。如果你轉賬1塊,還得額外再支付2塊轉賬費。所以這直接限制了小額轉賬的發生。類似的,假如某個支付工具限制最低交易費率為0.1元/筆。那基本限制了0.1元以下商品的交易,會賣一件賠一件,甚至0.2或者0.5元的商品都會絕跡,因為這個交易費率就佔了50%或者20%。
D. Relay on financial institutions to provide stable service
依賴支付工具提供穩定的服務。正常情況下支付工具都能穩定工作,但有時候外界造成的破壞會很嚴重。比如下圖藍翔畢業生KO支付寶。而且這種模型造成的後果一般都比較嚴重,比如商戶直接不能進行交易,或者賬戶資訊不能同步。 為了解決傳統中心化支付系統的弊端,“中本聰”提出了一種peer-to-peer的電子支付系統,Bitcoin。
2. Peer-to-Peer支付系統(blockchain)的實現
雖然blockchain把中心化的支付模式變成了P2P的模式,但本質仍然是電子支付。一般電子支付過程中都需要解決以下問題:1.驗證 2.安全 3.歷史記錄。 Bitcoin的誕生,意味著在 p2p模式下找到了解決了上述問題的方法。
2.1 Transactions
Bitcoin使用數字簽名來解決信任問題。數字簽名使用public key很容易就能驗證transaction的真實性。具體過程如下: Owner transfers coin to next時會把前一次的交易以及next owner的public key進行hash算出摘要。然後current owner對這個摘要進行簽名,最後把這個簽名新增到transaction的末尾傳送給next owner。Next owner收到transaction便可以用前一個owner的public key來驗證本次交易的真實性。
2.2 Double-spending
數字貨幣(或電子支付)除了驗證真實性,還需要解決double-spending的問題。 因為數字貨幣(電子支付)傳輸內容是數字資訊,所以它更容易被複制或者偽造。傳統的中心化支付模式是因為所有交易都需要經過支付機構,所以支付機構有能力根據歷史交易等資訊來解決double-spending的問題。 但如果是P2P的支付系統,因為沒有中心化的支付機構,所以要解決double-spending的問題必須想辦法記錄下所有交易,並且需要讓大多數node使用同一套交易歷史記錄。 要達到這個目標,那所有交易都應該publicly announced,如果是合法的,那麼大多數node都會把這個block新增到chain中,讓所有node都擁有相同的交易資訊記錄,並且保證block的order也是一樣的。在這個系統中,block與block之間連成一條交易記錄的chain,並且這個chain會隨著交易不斷進行而增長,這就是blockchain。 PS: double-spending的問題和中心化或者去中心化的模式無關。它是由於數字資訊更容易產生或者被複制。比如群發的垃圾郵件,傳送給所有接收者的內容是一樣的,但接收者不一樣,這就是個典型的double-spending問題。Bitcoin解決double-spending就是參考了處理垃圾郵件的辦法。
2.3 How to keep order?(timestamp server)
Bitcoin使用Timestap來保證block的順序。Timestamp由timestamp server提供。 一個block包含一組交易資料,bitcoin會將這個block加上timestamp進行hash。 這使得block被破解的難度加大。因為要產生相同的雜湊,除了知道交易內容外,還需要保證時時間也一致。 一個合法的timestamp需要保證其值大於blockchain中,前11個block的timestamp裡的中位數,且小於network-adjust time + 2 hours。 所謂network-adjust time是,所有和你連線節點返回給你的UTC裡的中位數。節點之間建立連線時會獲取對方的UTC,本地會算出它和本地UTC之前的offset,並儲存。所以,最終本地可以算出所有連線節點裡的UTC中位數offset。這個中位數offset + local UTC就是network adjust time。不過這個offset不能超過70 min,也就是network adjust time的調整範圍不能超過70 min。 這裡取中位數而非平均值是為了避免極值帶來的影響。不過Bitcoin的timestamp依然算不上精準,精度只有1~2小時。
2.4 Who can add a block?(Proof-of-Work)
Timestamp也只是保證block能按照時間先後順序連結起來。還需要確定由哪個node(timestamp server)來新增這個block,否則所有node都同時新增block的blockchain會出問題。Node的選擇由PoW演算法來決定。 Bitcoin的PoW演算法參考了,https://en.wikipedia.org/wiki/Hashcash Hashcash的原理是:在郵件正文前加一個hashcash stamp的header。這個hashcash stamp需要滿足一定的規則,比如前20bit必須是0。傳送方為了能算出符合要求的stamp必須通過窮舉法來暴力破解。所以只要傳送方傳送的郵件header前由這個stamp,就意味著傳送方投入了CPU time去做這個事情,也就是stamp是Proof of Work。 因為垃圾郵件傳送者的商業模式是以極低的成本傳送一封郵件,只要增加每封垃圾郵件的傳送成本,傳送者就無利可圖了。 上圖就是Hashcash的header細節。Bits記錄header的hash值中前導0的個數,這個例子是20,表示hash值的前20 bit必須是0;Date記錄郵件傳送時間;Resource記錄接收者的郵箱;rand是隨機數;counter是每進行一次hash執行+1,直到找到合規的hash值。 對每個接受者來說,郵箱是唯一的。所以發給不同接收這的垃圾郵件都要重新計算這個hash值。並且header中還用日期來指明郵件的傳送時間。所以同樣的郵件在不同時間傳送給同一個接收者也需要重新計算hash值。這就提高了每封垃圾郵件的傳送成本。 在傳送郵件之前,傳送者先根據header內容計算出hash值。如果hash的前20 bit都是0,那麼這個hash值就是合規的(換句話說header的內容也是合規的)。如果不是,那麼counter +1之後繼續運算hash,如此往復直到找到合規的hash(header)。 如果bits是20,採用的是160bit的SHA1演算法,那麼total的hash值有2160個,符合要求的hash值由2140個。所以找到符合要求的hash的概率是1/220,大約計算一百萬次可以找到合規的hash和header。對現在的PC來說,一百萬次hash運算大約需要花費1秒鐘。普通使用者可以接受這個時間,但對於需要傳送大量垃圾郵件者來說,這個成本就提高了。 Bitcoin的PoW類似於Hashcash,但還是由區別。Hashcash中通過rnd和counter來猜hash值,Bitcoin中只用一個nonce。如果hash沒有猜中,nonce +1後進行下一輪hash運算。合規的hash值由網路中所有node共享的target來指定。這個target是一個前導為指定個數0的hash值中的最大值。比如要求前導兩個0,target就是0x00FFFFxxxx,要求前導6個0,target就是0x000000FFFFxxxx。由於硬體的發展等原因,整個網路的算力是動態調整的。所以Bitcoin為了控制網路中block的新增速度,需要動態調整target,也就是調整target前導0的個數。通過控制0的個數,hash計算難度就會成指數倍的變化。比如Bitcoin初始化時,要求前hash的前32bit為0。到了2017年8月,已經變成前72bit為0。 由於只有猜中了hash值後,nonce才不會變,否則nonce會一直累加,所以nonce也等於CPU的工作量證明。 並且這個nonce值會新增到block中。假如有惡意者想修改block中的內容,他必須重新計算這個hash值,而因為每個block都把之前的block hash include進來,所以想修改一個歷史block,除了重新計算這個block本身,還需要計算這個block之後的所有block的hash。
2.5 Network
Bitcoin的執行過程如下:
- 向網路中所有node廣播一個新的transactions。
- 每個node把收到的transactions打包到block中。
- 每個node進行PoW運算來找到合規的hash值。
- 找到hash值的node將block廣播到所有node。
- 接受到block的node開始驗證transaction的合法性。
- Node把這個block記到賬本中,然後基於這個block的hash計算下個hash值。
2.5.1 Chain split
Chain還需要解決分叉的問題。 所有node都把最長的chain作為是正確的chain,並把產生的block加到這條chain上。但有可能在同一時間點,兩個node都各自算出了一個block,然後它們被同時廣播到Bitcoin網路中。這樣一部分節點可能會收到這個block,另一部分會收到另外一個block。在這何種情況下,node就把先收到的block新增到chain上,並且也會暫時把另外一個block儲存起來。如果最後,基於另一個block的chain變得更長了,那麼node會切換到更長的那條chain上。
2.5.2 Transaction or block dropped
新的transaction也並不需要保證必須到達所有node。因為有可能在它到達其它node之前,它就已經被新增到block中了。同樣,Block也可以drop。如果一個node沒有收到一個block,那當它收到next block時很容易發現node缺少一個pre hash。此時,它會向網路請求這個丟失的block。
2.6 Incentive
為了鼓勵node以honest的方式執行,Bitcoin設定了獎勵規則。Block中的第一個transaction必須是 coinbase transaction或者叫generation transaction。它用來儲存新增block成功的獎勵,或者block中其他transaction支付的transaction fee,它由建立block的node自己建立。一個block可以包含一個或多個transactions,但第一個transaction必須是coinbase transaction。 Transaction中coin的流向如下圖所示。transaction的支出來源於之前transaction的收入,所以每個transaction的output作為下一筆transaction的input。 一個transaction中可以建立多個output給不同的地址。為了避免double-spending的問題,每個output只能做一次input。 如果input的小於output,這是一個無效的transaction。但是input可以大於output,多餘的作為transaction fee給新增block成功的那個node。上圖中的transaction fee就是10K。 Node從Coin base中獲取的coin有鎖定期,必須等到新增100 block之後才能使用。這樣做是為了解決blockchain fork問題。因為這個block在將來可能會因為分叉問題而被丟棄,如果block丟棄,coinbase的coin應當是無效的。
2.7 disk space
隨著Block的不斷新增,blockchain的size會不斷增長,Bitcoin通過merkle tree來減輕磁碟儲存空間的壓力。 交易以hash值的方式儲存在merkle tree中,Block Header中只存放一個root hash。刪減歷史交易資訊並不會改變root hash。如圖刪除了tx0~2的交易。默克爾樹的原理可以參考其他資料。
2.8 簡便驗證
根據默克爾樹的特性,Bitcoin可以實現簡便驗證(這是位元錢包的基礎)。一個節點可以刪除交易資訊,所以它沒有辦法自己做驗證,它做驗證需要連線到full node上(儲存歷史資訊)。具體不展開分析了。