1. 程式人生 > >區塊鏈技術基礎原理與演算法(比特幣為例,主要是比特幣的原理),密碼學原理

區塊鏈技術基礎原理與演算法(比特幣為例,主要是比特幣的原理),密碼學原理

密碼學原理

對稱加密演算法

原理

對稱加密:使用同一金鑰進行加密和解密

傳統密碼加密,私鑰演算法加密,加密速度快,密文是緊湊的安全的

加密過程

A同學生成明文->通過私鑰和加密演算法->生成密文->將密文通過網路傳輸到目的地B同學->通過同一私鑰以及解密演算法->解密為明文

對稱加密演算法的缺點:

兩個人有一對金鑰,那麼3個人就需要3個金鑰,兩兩之間都需要一個金鑰,人越多金鑰越多,並且為了安全起見,金鑰用過一次就會丟棄更換金鑰,就出現了一系列問題:金鑰分發、金鑰儲存和管理、缺乏對數字簽名/不可否認的支援

 

常用對稱演算法:

DES :

l des是一種塊或分組加密演算法,20世紀70年代IBM公司發明,1976年11月納為美國國家標準

l DES金鑰是固定的56bit,不夠安全

l DES以塊模式對64bit的塊進行操作,解釋如下:

假如有一段1G的明文資料需要加密,加密演算法首先將這段明文資料按照64bit一段一段分開,然後加密64bit的明文塊。(如果加密的資料長度不是64位的倍數,可以按照某種具體的規則來填充位。)

64bit明文->初始置換IP->在金鑰控制下16輪迭代->交換左右32bit->初始逆向置換IP->輸出64bit密文

DES有兩種方式ECB和CBC

ECB方式:

就是將資料按照8個位元組一段進行DES加密或解密得到一段段的8個位元組的密文或者明文,最後一段不足8個位元組,按照需求補足8個位元組(一般補0或者F)進行計算(平行計算),之後按照順序將計算所得的資料連在一起即可,各段資料之間互不影響。這樣一來相同的明文和金鑰得到的是相同的密文,經過大量的統計分析和嘗試攻擊,密文很有可能被破解,比如中文出現最多的字“的”,可能很快就能到這個明文對應的密文。

CBC方式:

  1. 首先將資料按照8個位元組一組進行分組得到D1D2…Dn(若資料不是8的整數倍,用指定的補位資料補位)
  2. 第一組資料D1與初始化向量IV異或後的結果進行DES加密得到第一組密文C1(初始化向量IV為全零)
  3. 第二組資料D2與第一組的加密結果C1異或以後的結果進行DES加密,得到第二組密文C2
  4. 之後的資料以此類推,得到Cn
  5. 按順序連為C1C2C3…Cn即為加密結果。

簡單講就是首先將明文分組與前一個密文分組進行異或運算,然後再進行加密,上面提到的初始化向量IV,是因為當加密第一個明文分組時,不存在前一個密文分組,因此需要準備一個長度為一個分組的位元序列來代替前一個密文分組,通常縮寫為IV。這樣的方式就保證了明文和密文並不是一一對應關係,即同一組明文不一定為同一組密文。安全性提高了很多。

雖然des演算法是安全的,但是56bit的金鑰長度太短,容易被暴力破解,不夠安全,所以需要經常修改金鑰,防止暴力破解,另外交換金鑰的方式或者說通道,必須是安全的,防止金鑰洩露。

3DES

3des演算法金鑰長度達到了168位,並且做了3遍des加密(嚴格意義上說是兩遍),所以暴力破解可能性很低,達到了更高程度的安全。但是會變慢增加延時,不適用與語音視訊的加解密。

AES

l 因為des演算法不夠安全了,所以出現了AES,AES適合於高速網路,適合在硬體上實現

l 金鑰長度可以為128bit,192bit,或者256bit(還能以32bit的倍數擴充套件)。

l 軟硬體執行效率較高,AES可用於無線/語言視訊加密

 

RC系列

包括RC2、RC4、RC5,其中最常用的是RC4

RC4是基於流模式加密演算法,面向bit操作,應用範圍很廣,比如https、WEP、WPA。

WPA2用的AES演算法。

輕量級加密演算法,執行速度快,對加密硬體要求低,以後可能會用到物聯網的一些硬體裝置上。

IDEA

類似於DES,IDEA演算法也是一種資料塊加密演算法,它設計了一系列加密輪次,每輪加密都使用從完整的加密金鑰中生成的一個子金鑰。與DES的不同處在於,它採用軟體實現和採用硬體實現同樣快速。速度都比des快。

Blowfish

Blowfish是一個對稱加密塊演算法,由Bruce Schneider於1993年設計,現已應用在多種加密產品。Blowfish能保證很好的加密速度,並且目前為止沒有發現有效地破解方法。

易於軟體快速實現,所需儲存空間不到5KB,適用於金鑰不經常改變的加密,比如監測水質的裝置,可能放到水中三五年不便,就可以用Blowfish。

國密演算法

SM1、SM2演算法,都是對稱演算法,但是不能出口,一般用到國家政務、警務通等領域

非對稱加密演算法

兩支對應金鑰,稱為公鑰和私鑰,一般是公鑰加密私鑰解密。

簽名一般是私鑰簽名,公鑰驗籤。

加解密過程

同學A產生明文->使用同學B的公鑰加密成密文->通過網路傳輸到同學B->通過同學B的私鑰解密->同學B得到明文

同學B的私鑰始終儲存在B的本地,且公鑰不能推匯出私鑰,所以即使密文被截獲,也是很難被解密的,安全的。

非對稱加密演算法的特點

加密速度非常慢,密文非緊湊的,

公鑰和私鑰不相同,通過私鑰可以推匯出公鑰但是不能通過公鑰推匯出私鑰。

三種用途:

加密解密

數字簽名:保證資訊的不可否認性

金鑰交換:雙方協商會話金鑰

常用演算法:

RSA演算法:支援上面所說的三種用途

DH演算法:只支援金鑰交換

DSA演算法:只支援數字簽名

 

DH演算法

解決對稱加密演算法中金鑰分發的問題:前面提到對稱演算法中金鑰交換的過程必須用安全通道交換,但是很難能做到真正的安全通道,DH演算法就可以解決這個問題。

演算法過程:

第一步:同學A和同學B兩個人各自生成自己的DH公私鑰,私鑰自己儲存,公鑰傳送給對方。

第二步:同學A用同學B的公鑰和自己的私鑰通過DH演算法生成一個key,同學B同理生成一個key,最終AB同學生成的key應該是一樣的,這樣就實現了金鑰的交換。

這樣即使公鑰在傳輸過程中被截獲了,但是並不能從截獲到的公鑰推匯出key。

RSA演算法

金鑰長度在512-4096bit之間

RSA比用軟體實現的DES慢100倍

RSA比用硬體實現的DES慢1000倍

RSA的主要功能:加密、數字簽名和金鑰交換

其他公鑰演算法

Elgamal:DH的一種變形

橢圓曲線加密演算法(ECC):原理是給定橢圓曲線上兩個點A和B,如A=kB,要找到整數k非常困難,比特幣底層就是用的這種演算法。ECC金鑰更小,與1024位的RSA金鑰具有同樣安全的ECC金鑰只有160位

數字簽名

RSA可以提供數字簽名功能,提供認證和抗抵賴。

私鑰加密的過程:

同學A生成明文->通過傳送方的私鑰加密成密文->通過網路傳給B->B拿到密文用A同學的公鑰解密->得到明文

通過這個過程,B可以用A的公鑰解密開密文,就表示這段密文就是A傳送的,A就不能抵賴了。

數字簽名過程:

  1. 傳送方A生成明文
  2. 用接收方B的公鑰加密這段明文,生成密文。同時對明文資訊進行雜湊計算,得到摘要,將摘要用傳送方A的私鑰進行簽名,得到簽名值。
  3. 通過網路將密文和簽名值傳送給接收方B
  4. B收到密文和簽名後,首先將密文用自己的私鑰解密,得到明文。然後對明文進行雜湊,得到一個雜湊值,也就是上面說的摘要
  5. 接下來,B繼續對A發來的簽名,用傳送方的公鑰進行解密,得到一個摘要
  6. 最後接收方B將兩個摘要進行對比,如果一樣,就說明訊息是A發的並且中途沒有被篡改。

上面這段可以理解數字簽名的過程,但是真實使用過程中,並不會使用公鑰加密,一般對明文加密用的還是對稱演算法,可以保證速度,後面會講到,如何將對稱和非對稱演算法結合使用。

hash演算法:無論多長的明文資料,經過hash後,得到的都是一段定長的128或者256位元組資料,同一段明文對應同一個hash值,並且演算法不可逆,即不能通過摘要值逆算出明文,所以這裡既能保證速度,又可以保證安全。

數字證書與CA

首先,從上面那些加密過程中提出一個問題:傳送方A將明文加密的時候,如果判斷使用的加密公鑰就是接收方B的,而不是其他什麼人的呢?

這裡就引出了CA機構。

CA機構:頒發數字證書的機構,作為電子商務交易中受信任的第三方,承擔公鑰體系中公鑰的合法性檢驗的責任。CA中心(GlobalSign)為每個使用公開金鑰的使用者發放一個數字證書,數字證書的作用是證明證書中列出的使用者合法擁有證書中列出的公開金鑰。

也就是說,CA機構給了使用者B一個數字證書,數字證書中包含使用者B的資訊、公鑰以及認證有效期等,類似網路上的身份證。

雜湊與HMAC

雜湊Hash(雜湊函式)

將一段任意長的資料,經過計算,得到一段定長資料。

hash演算法有幾個特點:

l 不可逆:幾乎無法從得到的hash結果值,推匯出原文

l 無碰撞:兩段不一樣的原文,幾乎不可能得到一個同樣的hash值。

l 雪崩效應:原文有輕微的變化,得到的hash值會產生巨大變化

使用場景:

l 釋出檔案的完整性(比如下載一個炒股軟體,該軟體會給你一個MD值,下載成功後的MD5值和軟體告訴你的一樣,說明下載過程沒有問題)

l 伺服器中儲存使用者密碼

l 數字簽名

hash演算法有很多,常用的有MD5,SHA256

使用者密碼的儲存:

使用者名稱

密碼

test

123456

明文儲存的情況下:

 

 

雜湊儲存:

使用者名稱

密碼

test

e10adc3949ba59abbe56e057f20f883e

 

 

 

 

鹽+雜湊:

使用者名稱

密碼

test

2020-2-2 12:12:00

74acf6b6ef47772151b4b4666bde6c8c

 

密碼用明文儲存,如果你的資料庫被攻擊,那麼密碼直接就被盜走了,但是將密碼雜湊過後再儲存,即使密碼被盜走了也不會有問題了。那麼為什麼又會有第三種儲存方式?

這裡首先有一個概念叫彩虹表攻擊,彩虹表是一個預先準備好的表,表的內容就是一些有限字元組成的固定長度的純文字密碼對應的hash值,類似下面這樣的表,表的內容能達到100G以上,這樣就可以逆向的通過密碼的hash找到密碼的原文了。

密碼

密碼經過MD5演算法hash後

123456

e10adc3949ba59abbe56e057f20f883e

432432

d9aeba5e7bcdacec33d2504cfcbfc33b

 

 

 

 

為了防止彩虹表攻擊,就對hash的明文稍微改了一下,將密碼和鹽一起hash加密,鹽可以是一個時間,也可以是別的什麼值,

HMAC

HMAC是一種基於Hash函式和金鑰進行訊息認證的方法

具體說就是增加一個key做hash:HMAC=Hash(檔案+key)

這個key是雙方預先都知道的。

HMAC:可以做源認證以及完整性校驗,具體如下

同學A 發起認證->到PPPOE服務端->服務端查到有儲存同學A的使用者名稱和密碼,返回隨機數x->同學A用自己的密碼和隨機數x做hash,將hash值發回給伺服器->伺服器同樣做hash,之後比對驗證。

為什麼要返回一個隨機數x,用隨機數x和密碼一起做雜湊,還是和上面說的一樣,防止彩虹表攻擊。

對稱加密和非對稱加密結合使用

l 在對稱演算法中有些問題,比如如何將同學A的金鑰傳遞給同學B,不能做數字簽名等

l 非對稱演算法中也有問題,比如加密速度慢,密文非緊湊。

因為這些優缺點,我們應該想到,如何將優點結合起來使用呢?可以這樣:

使用對稱加密演算法,對大檔案進行加密,使用非對稱加密演算法對對稱演算法使用的金鑰進行加密。

流程:

1、同學A 對明文進行雜湊,形成摘要->利用傳送方A的私鑰,對摘要進行簽名,得到傳送方簽名值

2、將明文+ 簽名+傳送方A的公鑰或者數字證書打包起來,使用一個隨機對稱金鑰,對其加密(這裡使用的就是對稱加密演算法),得到密文

3、用接收方B的公鑰對第二步中的隨機對稱金鑰加密,得到金鑰密文,將上一步的密文和本步驟的金鑰密文打包,形成數字信封,傳送給接收方B

4、B得到了兩個密文,一個是金鑰密文,一個是第2步驟的密文。使用接收方B的私鑰對金鑰密文進行解密,得到金鑰。

5、使用解開的金鑰對第2步驟的密文進行解密。解密得到了3個東西:一個明文,一個傳送方A的簽名,一個傳送方A的公鑰或者數字證書。

6、對上一步驟得到的明文進行hash計算,得到摘要。用傳送方A的公鑰對傳送方A的簽名進行解密,得到密文中的摘要,將兩個摘要進行比對。結果一樣就說明確實是傳送方A發的。

比特幣

區塊鏈層次與架構

 

層次

主要用到的技術

應用層

 

合約層

 

激勵層

 

共識層

通過各種共識演算法,達到共識。常用的:

PoW(工作量證明)Pos(權益證明)DPOS(股份授權證明)

網路層

P2P技術

資料層

密碼學技術(公鑰密碼學)

下三層 資料層、網路層、共識層是區塊鏈的核心,上三層就是應用層。

 

比特幣和區塊鏈的關係

區塊鏈是一種技術的集合/思想(去中心化),比特幣是基於區塊鏈的一種應用(移動網際網路與微信的關係)

比如網際網路,最早就是誕生了web等應用,後面又出現qq,微信,淘寶等,從只能傳輸文字,到傳輸語音,位置等。區塊鏈也是一樣,目前區塊鏈交易資訊是比特幣,但是也可以封裝其他的內容,將來會有各種應用,目前最牛的只有比特幣,其次以太坊。

 

中心化:

目前我們做交易,所有人的所有的交易都需要通過銀行,比如轉賬,消費等;央行可以無窮無盡印鈔票,導致通貨膨脹;銀行可以隨意凍結/沒收你的資產。所以銀行就是一箇中心化產物。去中心化就是交易過程脫離銀行,完全個人對個人。

比特幣就是一個完全脫離銀行,只依靠網際網路執行的貨幣系統,即使政府執法部門,也無法查封或沒收比特幣。比特幣在人類歷史上第一次用技術手段保證了私有財產神聖不可侵犯。

 

比特幣的共識機制:

POW工作量證明:簡單講就是誰幹的活多誰說了算

演算法:

非對稱密碼學

 

 

比特幣的特性:

硬通貨:跨境交易(包括暗網的一些黃賭毒交易,以及正常的跨境支付匯款等)

易攜帶:只需要一個私鑰

隱祕性:只暴露錢包地址;非法用途

無貨幣超發:貨幣緊縮(只有固定數量的比特幣,不會超發)

 

P2P網路

 

 

 

 

深入理解區塊鏈結構

區塊鏈分為區塊和鏈兩部分

區塊裡面包括一筆一筆的交易,然後將一個一個區塊連結起來,形成鏈式結構。

比特幣的區塊裡面封裝的是交易資訊,比如轉賬金額,收款人等;區塊鏈還可以封裝各種資訊,如證件、私人記錄、實物資產、留存證明等。封裝交易資訊形成了比特幣應用,封裝其他的資訊就可以形成其他應用。

比特幣結構:

 

 

 

 

 

每個區塊包含一個區塊頭部和N個交易。

區塊頭部包含:上面那個圖中的版本號,父區塊雜湊,Merkle樹根,時間戳,難度值,Nonce

 

版本號:比特幣的版本

父區塊雜湊:區塊0的雜湊值

Merkle樹根:區塊鏈非常重要的資料結構,也是一個雜湊

難度值:確保區塊鏈不會被很快挖出來,目前是約10分鐘出來一個區塊

時間戳:什麼時間生成的區塊

Nonce:隨機數,挖礦就是找到隨機數的過程

上面都是簡單說明一下,後面有重點講解,

 

比特幣常用術語

去中心化的賬本管理方式

 

 

 

 

每個人都有一個自己的賬本,當李四跟張三轉賬,比如100元,首先形成一個交易資訊,然後將這個交易資訊記錄到每個人的賬本上,所有人的賬本自始至終是一致的。這個賬本取代了銀行記賬的方式。

挖礦

比特幣礦工通過解決具有一定工作量的工作量證明機制問題,來管理比特幣網路—確認交易並且防止雙重支付。挖礦的過程就是在全網中和其他節點競爭記賬的過程,為什麼要競爭記賬呢?比如上面那張圖,轉賬完畢,每個人都要記賬,那麼第一個記賬的人就可以得到一些比特幣,所以第一個記賬的人就等於挖到了礦。

百度百科:礦工們在挖礦過程中會得到兩種型別的獎勵:建立新區塊的新幣獎勵,以及區塊中所含交易的交易費。為了得到這些獎勵,礦工們爭相完成一種基於加密雜湊演算法的數學難題,也就是利用比特幣挖礦機進行雜湊演算法的計算,這需要強大的計算能力,計算過程多少,計算結果好壞作為礦工的計算工作量的證明,被稱為“工作量證明”。該演算法的競爭機制以及獲勝者有權在區塊鏈上進行交易記錄的機制,這二者保障了比特幣的安全

除了上面說的獎勵,還會獲得相應權利和義務:記賬的權利(把交易記錄到賬本)和廣播義務(將區塊全網廣播)

創世區塊

Block #0  2009.01.03誕生

區塊高度:

就是從#0、#1、 #2一直加,增加的區塊數

區塊深度

比如產生一個交易,開始一段時間深度為0,交易可以更改/撤銷(退換貨),隔一段時間,深度或逐漸加深,深度大於6的時候,交易就達到了非常安全的程度,不可再更改/撤銷.

深度是以產生交易的區塊為起點,比如在第10個區塊產生了這筆交易,那麼第10個區塊就是深度1,第11個區塊產生出來後就是深度2,第12個區塊就是深度3,以此類催,達到深度6,也就是創建出來第16個區塊後,交易就不可更改了。

交易確認

當一項交易被區塊鏈收錄後,就是交易確認

在此區款連之後每產生一個區塊,此項交易的確認數相應加1

比特幣錢包對交易確認數有相應設定(快速2次確認,非常安全6次確認收到錢)

 

 

UTXO 未花費的交易輸出

我們都知道比特幣是虛擬的,本質上就是一串程式碼。而記錄比特幣交易的賬戶模型,就是UTXO。比特幣系統中沒有比特幣,只有UTXO,即系統中沒有儲存誰有幾個比特幣,而是記錄的一筆一筆的交易,比如A給B轉了100元,那麼區塊中就多出兩筆交易,一筆是A減少100元,一筆是B增加100元。每一筆交易後的輸出就是一個UTXO。

 

舉個例子,假如我們現在錢包裡有100塊錢,你要花5塊錢,然後找零95塊。當你拿出來100塊大洋花出去的時候,這100塊就已經不能再算作UTXO,只有找零得到的95塊,才會算作UTXO。

 

每筆交易都有若干交易輸入,也就是資金來源,也都有若干筆交易輸出,也就是資金去向。一般來說,每一筆交易都要花費(spend)一筆輸入,產生一筆輸出,而其所產生的輸出,就是“未花費過的交易輸出”,也就是 UTXO。當之前的 UTXO 出現在後續交易的輸入時,就表示這個 UTXO 已經花費掉了,不再是 UTXO 了。

 

比特幣存在比特幣錢包中,比特幣錢包中的比特幣是怎麼來的呢?是將一筆一筆的交易數加起來,比如A同學先增加了200,又減少了100,又增加了300,那麼他的比特幣數量就是200-100+300=400

 

比特幣系統中沒有賬戶這個概念,也沒有賬戶餘額的概念,只有UTXO(被公鑰鎖定),沒有登入概念,只要自己有私鑰就可以使用這個比特幣。

 

轉賬將消耗掉你自己的UTXO,同時生成新的UTXO,用接收UTXO方的公鑰進行鎖定。

 

另外還要提一下,UTXO與傳統的賬戶系統有什麼區別。假如有兩個人,一個是小明,一個是小美。小明要給小美轉100塊錢。那麼傳統的賬戶模型是這樣的:先判斷小明賬戶裡是否有100塊的餘額,然後在小明的賬戶裡減少100塊,在小美賬戶裡增加100塊。

 

但UTXO的機制是這樣的:小明的賬戶裡有200塊錢,他要想給小美轉賬,必須將200塊錢全部消耗掉。所以他不僅要給小美轉100塊,還要給自己賬戶轉100塊。這樣一個好處就是,如果從第一個區塊開始逐步計算所有比特幣地址中的餘額,就可以計算出不同時間的各個比特幣賬戶的餘額了

 

比特幣交易鎖定與解鎖全過程

交易的輸出(UTXO),包含兩個東西:

l 鎖定的比特幣數量

l 鎖定指令碼(用接受者公鑰的雜湊)

只要接收者才能有權利花費這筆比特幣,所以用接收者的公鑰進行鎖定,但是為了更安全,比特幣是用的公鑰的雜湊值加密的這筆比特幣。

 

交易的輸入(UTXO+解鎖指令碼)

l 解鎖指令碼(簽名和傳送者公鑰)

 

比特幣鎖定/解鎖指令碼工作過程

 

 

 

 

 

B打算向C轉10個比特幣,怎麼判斷B有權利花掉這10個比特幣?

第一步,判斷鎖定指令碼:B會提供一個B私鑰簽名和一個B公鑰,系統將B公鑰進行hash,和鎖定指令碼那種的B公鑰雜湊如果相同,就證明B提供的確實是B的公鑰。

第二步,用B的公鑰解B的私鑰簽名,如果能解開,就證明確實是B的私鑰做的簽名,B確實有私鑰。

再舉一個例子,下面這個例子,假設交易手續費為0:

1、使用者A挖礦獲得了12.5BTC

這裡的12.5btc UTXO用曠工A的公鑰雜湊進行鎖定(加密)

注意:剛挖到的比特幣要100個區塊確認後才能花。

2、第一個交易:A向B和C各轉5 BTC

B多了5 BTC的TUXO,用B的公鑰雜湊進行鎖定

C多了5 BTC的UTXO,用C的公鑰雜湊進行鎖定

A去掉原來有的12.5的UTXO,換成2.5的UTXO,用A的公鑰雜湊進行鎖定

3、第二個交易:B向C轉2個BTC

B去掉原來的5 BTC的UYXO,改成3BTC的UTXO,仍然用B的公鑰雜湊進行加密鎖定

C多一個2 BTC的UTXO

4、第四個交易 :C向B轉6 BTC

C轉給B之前有一個5BTC,一個2BTC,要給B 6BTC,就會將原來的5和2BTC的UTXO全部刪掉,換成1BTC的UTXO用C的公鑰雜湊加密和6BTC

以及給B的6BTC的UTXO用B的公鑰雜湊加密

 

經過上面一些交易,最後剩下的UTXO,就只有步驟2中A的2.5BTC,步驟3中B的3BTC和步驟4中B的6BTC以及C的1BTC。此時比特幣的總和依然是最開始曠工A挖礦挖出來的12.5。

交易的傳播與驗證

交易

交易包含兩部分:輸入n和輸出m。n>=0,m>0

輸入:要被花費的UTXO+解鎖指令碼(私鑰簽名+公鑰)

輸出:一個或多個UTXO(幣值+鎖定指令碼(公鑰的雜湊))

n>=0怎麼理解呢?第一筆交易,例如上面那個例子中的曠工A,挖礦得到獎勵,是沒有輸入的,只有輸出,此時就是n=0的情況。其他的交易都是n>0的情況,你要花錢首先得有錢。所以除了第一筆那樣的交易,其他的交易都包含兩部分,輸入和輸出。

m>0:輸出就是你買東西或者轉賬等,給人家錢,不可能給0

 

交易傳播與驗證過程:

  • 錢包軟體生成交易,並向鄰居節點傳播
  • 節點對收到的交易進行驗證,並丟棄不合法交易
  • 交易的size要小於區塊size的上限
  • 交易輸入的UTXO是存在的(向全節點的UTXO資料庫檢索)
  • 交易輸入的UTXO沒有被其他交易引用,防止雙花
  • 輸入的總金額>=輸出總金額
  • 驗證解鎖指令碼
  • 將合法的交易加入本地Transaction資料庫中,併發送給臨近節點。

區塊的生成與連線

 

曠工在挖礦前要元件區塊

1、將coinbase交易打包進區塊(每個區塊的第一筆交易都是這個,曠工挖礦挖來的12.5BTC)

2、將交易池中高優先順序的交易打包進區塊

優先順序:交易額度*UTXO深度/交易size(類比銀行)

交易size:防止粉塵攻擊(類似銀行的存款期限,存起來不經常動,size就小)

UTXO深度:防止頻繁轉賬攻擊(很久沒有轉賬的深度更大,轉賬越頻繁的深度越小)

建立區塊頭部

 

 

 

 

區塊鏈:

區塊0--區塊1--區塊2--區塊3.。。。

 

區塊1的父區塊雜湊是區塊0的區塊雜湊

區塊2的父區塊雜湊是區塊2的區塊雜湊

。。。

這樣一來只要中間有一個交易資訊改變,會導致他後面的所有區塊都要變。

算出隨機數Nonce,意味著挖礦成功,之後將計算出來的隨機數nonce填入區塊頭部,向鄰近節點傳播(接力賽)

區塊0儲存的資訊:

當時正是英國財政大臣第二次出手疏解銀行危機之時,表示對中心化銀行和政府的不滿。

相鄰節點收到新區塊後,立即做如下檢查:

驗證POW的nonce值是否符合難度值

檢查時間戳是否小於當前時間2小時

檢查Merkle樹根是否正確

檢查區塊size要小於區塊size上限

第一筆交易必須是coinbase交易

驗證每個交易

比特幣程式碼網站:http://btc.yt/lxr/satoshi/ident?_i=CheckBlock

 

二叉樹與Merkle樹

樹:由多個節點組成的一種資料結構,每個節點儲存資料,節點包括:根節點、父節點、子節點、兄弟節點

特殊樹:二叉樹(方便查詢)

比如有資料:12、5、2、18、19、15、17、16、9

如下圖,第一個數12,放到頂端;5小於12,放到左邊,2小於12,到左邊,小於5,放到5的左邊,18大於12,放右邊,19大於12,大於18,放18右邊。。。

 

 

 

 

Merkle樹作用

防止資料篡改(節點儲存Hash值)

快速驗證某個交易是否存在

從葉子節點構造樹

 

Merkle樹儲存的是交易資訊的雜湊,比如現在有三筆交易資訊:a、b、c,將這三筆交易做雜湊得到Ha、Hb、Hc,就會如圖中所示,將Ha和Hb再次雜湊,生成Hab,因為沒有Hd,所以將Hc和Hc做雜湊,生成Hcc,然後再將Hab和Hcc雜湊,生成根節點。

如何防止資料篡改的?任何一個交易的改變,交易的雜湊就會改變,那麼上層所有的雜湊都會變,比如Ha改變了,那麼Hab也會改變,root也會變。所以只要根節點雜湊值沒變,和頭部的Merkle樹根一致,那麼就可以保證交易都沒有被篡改。

 

 

 

 

 

 

怎麼驗證區塊是否在交易裡面?

比如a那筆交易是張三給李四轉錢的交易,如何驗證這筆交易在這個區塊裡,就用a這筆交易的雜湊Ha跟他兄弟節點Hb做雜湊,得到Hab,再用Hab和他兄弟節點Hcc做雜湊,得到根節點,判斷根節點和頭部的Merkle樹根一致,就說明這個交易在這個區塊中。

root就是頭部的Merkle樹根,Merkle樹根是負責一個區塊內部的所有交易的hash,父區塊雜湊是區塊和區塊之間的hash。父區塊雜湊是防止整個區塊被篡改。

比特幣存在的問題

 

比特幣網路擁堵

跟P2P沒有關係,跟底層區塊鏈有關係,因為區塊每10分鐘生成一個導致的。每10分鐘就會有一個新的區塊被“挖掘”出來,每個區塊裡包含著從上一個區塊產生到目前這段時間內發生的所有交易,這些交易被依次新增到區塊鏈中。由於每次礦工在打包新區塊時,最多也就能打包幾千條交易資訊。所以以前交易量沒那麼多時,一般等到下一個區塊打包完,就能到賬了,也就是10分鐘左右就到賬了;但是一旦交易量上去了,那麼對不起,這次甚至下次打包新區塊時,估計都不能打包上這筆新交易了。因為前面還有好多交易都在排著隊等著被打包被驗證呢!

為什麼一個區塊最多隻能打包幾千條資訊?

現在一個區塊的大小差不多是1MB,也就是1000KB,可以把一個區塊比做一個書包的大小。一筆交易差不多是250B,也就是0.25KB,可以把一筆交易比做一根鉛筆的大小。現在要往1000KB的書包裡放0.25KB的鉛筆,能放多少根筆?不難算出,是4000根:

即,一個區塊,最多也就包含差不多4000筆交易。

交易費用昂貴

交易費用給的高,會被優先處理,因為網路擁堵,速度慢,交易費用也會更高

 

以太坊的出現,也會成為比特幣發展的阻礙

因為有上面的這些問題,所以目前正在考慮比特幣擴容

比特幣擴容

有人會問:書包太小了,換個大書包吧!

也有人會說:交易能不能壓縮一下啊,鉛筆再小一點!

沒錯,這些都是解決目前交易擁堵的方式。即:

1.擴大區塊的大小,從1MB提升到2MB甚至4MB甚至更大。

2.交易壓縮,將沒用的資訊去掉,節約每筆交易的空間,好讓區塊裡能存放更多的交易。

 

對於第一個解決方案,擴大區塊大小,從幾年前起,比特幣社群、礦場、比特幣主要核心開發人員之間就開始討論了。吳忌寒等曠工團隊主張擴容,但核心開發人員反對將區塊擴容。

 

對於第二個解決方案,人們確實找到了可以壓縮交易的方法,壓縮的方式有兩種:

 

1)儲存一半的公鑰。

 

這是因為私鑰在生成公鑰時,採用的是橢圓曲線加密法,最開始人們都沒當回事,後來受交易擁堵的影響,有人關注到,因為是橢圓演算法的,所以是對稱的,所以只需要儲存一半的公鑰,就能表達出之前的意思,這樣既沒有什麼影響,又能節省空間,讓一個區塊包含更多的交易,何樂而不為?於是大家就開始接受壓縮公鑰的方式了。

 

2)隔離見證,即將一筆交易的交易部分和簽名部分拆開。

 

開發者們發現,一筆0.25KB的交易記錄中,實際交易資訊佔了一小部分,還有一部分叫做簽名信息,這簽名信息佔了一大部分,於是開發者們把簽名信息從交易記錄中剝離出去,單獨開發了一塊空間儲存簽名信息。於是之前一個區塊裡包含了眾多交易的交易資訊和簽名信息,現在一個區塊裡只需要包含這些交易記錄的交易資訊就好了,簽名信息在另一個附屬的塊中捆綁在區塊上,一併發給其他礦工。這樣的話,也能節省出來一部分空間。

 

針對隔離見證,曠工和核心開發團隊們有過兩次共識,第一次共識,是2016年2月在香港的會議,稱為香港共識:Core團隊的代表同意在實施隔離見證後,區塊大小擴容到2M。(前提是95%以上的算力曠工支援)

第二次共識,2017年5月的紐約會議,稱為紐約共識:全網80%算力的礦主達成Segwit(隔離見證)2x擴容,意思是隻要80%以上的礦主同意擴容,就將區塊大小擴容到2M。

BIP:意思是比特幣改進建議,針對擴容就搞瞭如下幾個BIP:

BIP141(95%支援就實施)+BIP 91(80%支援即可)+BIP102(升級到2M)

這裡就看出去中心化的一點缺點:沒有中心,沒有權威,大家都可以說話,意見統一起來就很困難,就比如這次擴容,搞了三個BIP,來回開會,才有一點結論出來。

 

Core團隊反對擴容區塊的原因:

  • 不願意輕易更改系統,比如銀行仍使用COBOK語言編寫的系統
  • 防止個人不能執行全節點,因為每個區塊太大了,總體容易激增(違背去中心化)
  • 增加到2M沒太大作用,主推 閃電網路/側鏈 解決交易擁堵

 

閃電網路/側鏈 :閃電網路的主要思路十分簡單 -- 將大量交易放到比特幣區塊鏈之外進行。核心的概念主要有兩個:RSMC(Recoverable Sequence Maturity Contract)和 HTLC(Hashed Timelock Contract)。前者解決了鏈下交易的確認問題,後者解決了支付通道的問題。

簡單說一些交易沒必要上主網路,在鏈下解決就足夠了。中心化和去中心化結合。

 

曠工反對的原因

 

  • 閃電網路將會導致交易中心化,違背比特幣點對點交易的初衷
  • 閃電網路屬於BlockStream公司,大多數Core團隊成員是BlockStream僱員。
  • 如果將來絕大部分交易都在閃電網路/側鏈,曠工會損失交易費
  • Core壟斷了海外論壇,利用社群影響力封殺反對core的開發者和社群成員

 

BCC分叉

因為上面的一些原因,就有人搞出來比特幣的分叉,目前主要有BU團隊,BitcoinABC團隊。

BU團隊:

比特幣無限大小:放開區塊大小限制,一次能處理足夠的資料,提升網效率

BU方案曾經獲得全網40%算力支援

程式碼BUG太多,未能獲得社群廣泛支援

 

BitcoinABC團隊,團隊成員還是來自BU團隊:

基於BU程式碼,打造了BCC,2017.08.01執行硬分叉(ViaBTC推動)

BCC沒有Segwit,區塊容量8M

BCC官網:https://www.bitcoincash.org

 

比特幣分叉

針對擴容有兩種解決方案:軟分叉(修輔路、側鏈),硬分叉(重新修條更寬的路)

軟分叉:

是在原來基礎上進行優化,將區塊提高到2M,8M,16M,以SegWit閃電網路未主流解決方案。鏈上的一部分升級到軟分叉後,即使有些沒有升級的,可以互相相容,最終還是在一條鏈上。

硬分叉:

通過升級系統,改變程式碼,徹底解決擴容問題,以BU為主流解決方案。不能相容以前的方案。所以這個鏈會分成兩個鏈,BTC/BCH,ETC/ETH.

 

擴容是指硬分叉,隔離見證指的是軟分叉。

 

比特幣和以太坊都進行了硬分叉。BTC BCH    ETC ETH

萊特幣 利用隔離見證進行軟分叉

 

臨時分叉:

  • 僅發生在幾乎同時爆塊(同時找到滿足條件的隨機數)的情況,這種分叉是暫時的
  • 鏈分叉後,繼續挖礦,挖著挖著就會出現有一個鏈長一個鏈段的情況。根據共識機制,曠工最終會切換到最長鏈上繼續挖礦
  • 短鏈上的交易全部無效,爆塊曠工費(曠工費無效)
  • 短鏈上的曠工就重新到長鏈上繼續挖礦

 

比特幣的三個地址

私鑰地址

 

私鑰地址可以產生公鑰和比特幣地址

只需要儲存私鑰,就能夠花費對應地址上的比特幣

私鑰的本質是隨機數(比特幣私鑰256位)

私鑰總數是2256,資料量超過了宇宙中原子總數,很難遍歷所有私鑰。

比特幣私鑰是安全的,並不是說不可能出現重複的私鑰,而是說不可能通過遍歷的方式找到某一個特定的私鑰。

 

比特幣私鑰地址WIF(Wallet Import Format)

 

私鑰的格式:

私鑰字首80+私鑰本體+字尾(壓縮私鑰字尾是01,非壓縮私鑰無後綴)+校驗

壓縮私鑰 (76位十六進位制 2+64+2+8) <=>(52位Base58):

 

非壓縮私鑰 (74位十六進位制 2+64+8) <=>(51位Base58):

 

 

 

 

如何生成WIF私鑰:

第一步,隨機選取一個32位元組的數、大小介於1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之間,作為私鑰。

private_key= bytes.fromhex('0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D01')

  第二步,新增字首0x80

rk = b'\x80' + private_key

  第三步,取兩次雜湊的前4個位元組(8位十六進位制),作為校驗值新增在後面

checksum = hashlib.sha256(hashlib.sha256(rk).digest()).digest()[0:4]

rk = rk + checksum

最後用Base58表示法轉換一下

return base58.b58encode(rk)

如果運算正確,得出的私鑰值應該是:

 

KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617

 

第一步的64字元是標準格式私鑰256bit,64個字元。

WIF格式私鑰更短,是經過Base58編碼得到的,叫作壓縮格式私鑰,以K或L開頭,大小是52個字元。

未壓縮格式私鑰:5開頭,大小51個字元

 

生成自己私鑰的方法:

  • 通過某些私鑰生成網站,會存在安全性問題
  • 擲骰子,16面的扔64次
  • 用中文,英文,或漢語拼音的雜湊值
  • http://www.fileformat.info/tool/hash.htm

 

公鑰地址

 

是由私鑰,通過橢圓曲線加密演算法(ECC)生成,是一個65byte陣列

 

壓縮公鑰是02或03開頭66位(2+64):

 

非壓縮公鑰是04開頭130位十六進位制(2+64+64):

 

 

注意它們的第二行內容完全一樣

 

公鑰的生成:

 

 

 

 

錢包地址

錢包地址的生成過程:

 

 

 

 

1、3935a3e3751b68e04(自己隨機產生一個數)(或者是生成一個助記詞)

2、填充,得到256bit的私鑰(private_key):

000000000000000000000000000000000000000000000003935a3e3751b68e04

3、對私鑰進行橢圓曲線演算法加密(SECP256k1),得到64位元組的公鑰(public_key):

e8977d298d194929e92b1a87a37f232f8838aaa3e14746217c46def324d7577ca273075eb4edb98c18a6e27c4549aca44620aef4567bfb35d942e7ba0edce75f

4、新增0x04頭(以0x04開頭的公鑰標記這是沒有經過壓縮的公鑰),長度變為65位元組:

04e8977d298d194929e92b1a87a37f232f8838aaa3e14746217c46def324d7577ca273075eb4edb98c18a6e27c4549aca44620aef4567bfb35d942e7ba0edce75f

5、對步驟4的公鑰作sha256雜湊加密,得到如下摘要(長度為32位元組):

ac40cc78422db4050f1a99c2e539a68eca62b8c8c3496c330d588d2ed794e140

6、對步驟5的資料作ripemd160雜湊加密,得到公鑰hash(長度20位元組):

e2d12b1c117fe64cb868a81ee3a61c74b64c59ed

以下步驟展示公鑰hash生成錢包地址的過程:

7.1、假設 tem_hash = SHA256( SHA256(0x00+公鑰hash) ), 取tem_hash前4個位元組:f3891721

7.2、 checksum = f3891721

7.3、 0x00 + 公鑰hash + checksum:

        00c8db639c24f6dc026378225e40459ba8a9e54d1af3891721

7.4、將7.3中的位元組流進行base58的轉換,得到錢包地址:

       1MgJHdTuHkyZ6gzzMQGkZHd4CPn6joU5GL

注:錢包地址與公鑰hash從轉換來看,完全可以互逆,所以大部分情形下二者是等價的,只是表現形式不一樣而已。

輕錢包

 

輕錢包是比特幣的非全節點,儲存空間有限,只儲存區塊的頭部,空間只有80位元組,區塊本身大小:1M,8M

SPV簡單支付驗證(Simplified Payment Verification),這個概念出現其實很簡單,以比特幣為例子,目前節點如果儲存完整的區塊鏈資料那麼有幾百G,一般的個人終端上無法滿足這個量級的儲存空間,而且這個資料量還會一直增加,那麼針對個人的終端需要一種簡單的驗證模式,相應就出現了SPV,比如MultiBit這種輕量級錢包用的就是SPV模式。

輕錢包只儲存區塊頭部,不儲存區塊資訊,但是UTXO在區塊內,所以如果想要交易,必須向鄰近的全節點的區塊鏈傳送交易資訊。

 

輕錢包的SPV驗證

當SPV節點收到一個交易請求,其實節點是無法證實對端節點的可靠性的,那麼在一個交易發起過程中,一般會包括對端節點的支付UTXO、對端節點的簽名、交易金額、SPV節點的地址。SPV節點驗證通過支付驗證,檢查區塊頭資訊來確認發生這個交易的是否在區塊鏈中,並且在當前的區塊鏈系統中有多少區塊進行確認。這裡囉嗦下區塊頭,區塊頭中包括prev_block_hash和merkle_root_hash這兩個最為重要的驗證值。

1.SPV節點通過getheaders從相鄰的全資料節點獲得區塊頭資訊(這裡涉及一個問題,SPV對特定的幾個交易選擇讀取,無疑會透露錢包地址資訊)

2.計算當前交易的HASH值。

3.用計算後後的HASH值,去比對定位block head,確定是否存在目前的最長一條連結上。

4.從區塊中獲取構建merkle tree 所需的hash值,並計算merkle_root_hash

5.計算結果如果一致說明交易真實存在。

6.根據block header來確認有多少區塊確認交易。

什麼是挖礦/礦池

挖礦:

以拋硬幣為例:

正面朝上: 1

反面朝上: 0

立起來: X

 

誰丟擲如下組合,獎勵50比特幣:

11110000XX11110000XXXXXXX0101010101X01X1010X..

 

利用電腦CPU跑程式計算,一秒拋2次,專用GPU顯示卡,一秒拋200次

單位時間拋硬幣次數可以理解成算力,算力越大,拋中可能性越大。

 

挖礦就是尋找上面的組合的過程。

 

礦池

 

 

 

 

 

挖礦的本質:維護比特幣網路,大家得記賬,不能白記,得給獎勵,最初獎勵50個比特幣,每4年減半。

比特幣挖礦:消耗計算機+電力

黃金挖礦:消耗人力

 

挖礦底層機制

比特幣系統裡為什麼要設計挖礦?

  • 增加惡意行為的成本。比如黑客,想要挖礦,必須去購買很多大型裝置
  • 爭奪記賬權利,獲取獎勵(總共2100萬枚比特幣,都是靠挖礦來挖來的)

 

挖礦流程圖

 

 

 

 

挖礦難度調整

 

  • 每2016個區塊調整難度
  • 新目標值=當前目標值*(過去2016區塊用時分鐘/20160分鐘)
  • 目標值與難度值成反比(計算公式異常複雜)

 

 

區塊鏈共識演算法和激勵機制

什麼是區塊鏈共識機制?

區塊鏈具備:去中心化特性

沒有類似銀行的記賬機構,全網節點怎麼打成共識/一致?

  • POW:通過評估你的工作量來決定你獲得記賬權的概率,算力越大,記賬機率大 ---比特幣
  • POS:通過評估你持有代幣數量和時長,決定你記賬的機率 (幣天)---點點幣

不浪費電力 51%攻擊更難

  • POW+POS:用POW發行新幣,用POS維護區塊鏈網路安全
  • DPOS:選定“人大代表”記賬---EOS選21個根節點記賬,委託選出來的這21個代表去記賬,其他的人不能記。

 

比特幣共識機制 工作量證明POW

 

怎麼證明你英語好/網路牛人? CET6/CCIE證書

POW(Proof of Work)

  • 通過付出大量的工作代價來證明自己是非惡意節點
  • 計算出一個難題的隨機數答案(nonce),如同擲骰子
  • 獲取記賬權利
  • 打包交易並通知其他節點

 

POS(Proof of Stake) 股權證明機制

 

  • POS 根據你持有代幣的量和時間(幣天),給你發利息的一個制度
  • 比如你持有100個幣,總共持有了30天,那麼,此時你的幣天就為3000
  • 如果你發現了一個POS區塊,你的幣天就會被清空為0
  • 你每被清空365幣天,你將會從區塊中獲得0.05個幣的利息
  • 假定利息可理解為年利率5%,利息 = 3000 * 5% / 365 = 0.41個幣

 

問題:大股東控制,造成中心化。 人性: 有錢人犯罪率低

 

總結

  • POW通過挖礦獎勵,交易費激勵大家維護比特幣節點
  • POS則由大股東負責維護區塊鏈節點,產生利息
  • DPOS選舉“人大代表”記賬,維護區塊鏈

 

拜占庭將軍問題

拜占庭將軍問題(Byzantine failures),是由萊斯利·蘭伯特(Leslie Lamport)提出的點對點通訊中的基本問題。

 

拜占庭問題的最初描述是:n 個將軍被分隔在不同的地方,忠誠的將軍希望通過某種協議達成某個命令的一致(比如一起進攻或者一起後退)。但其中一些背叛的將軍會通過傳送錯誤的訊息阻撓忠誠的將軍達成命令上的一致。Lamport 證明了在將軍總數大於3m ,背叛者為m 或者更少時,忠誠的將軍可以達成命令上的一致。

 

背景:

  • 拜占庭帝國派出10支軍隊,去包圍一個強大的敵人
  • 至少6支軍隊同時進攻才能攻下,不然會失敗,損兵折將

 

難題:一些將軍可能是叛徒,會發布假的(相反的)進攻意向

目的:將軍需要找到一種共識機制,可以遠端協商,一起進攻/不進攻

 

解決方案PBFT ( Practical Byzantine Fault Tolerance ,實用拜占庭容錯演算法)

  • 每個節點向所有其他節點發送訊息
  • 每個節點根據收到的所有訊息來決定最終的策略
  • 缺點:每個節點向全網節點發送大量的訊息,因為這個缺點,所以不適合在比特幣世界裡用,容易造成網路堵塞。
  • 這個演算法有解前提:n>=3m+1(n為將軍總數,m為叛徒數量)

m<= ( n-1 )/3

 

 整理了一下前段時間學習的區塊鏈的視訊內容,老師講的挺好的,感覺確實理解了很多