1. 程式人生 > >區塊鏈系列教程之:比特幣的錢包與交易

區塊鏈系列教程之:比特幣的錢包與交易

[toc] # 簡介 錢包在比特幣中是做什麼的呢?比特幣的交易又有什麼特點呢?怎麼才能偽造比特幣的交易呢?今天和大家一起學習一下比特幣中的錢包和交易。 # 比特幣密碼學的基礎 之前我們提到過比特幣使用的並不是什麼新技術,只是對於老的技術比如:P2P網路,分散式系統,密碼學,共識演算法的重新而又巧妙的應用。 在錢包和交易生成驗證的過程中,都需要使用到密碼學的計算。這裡我們先介紹一下比特幣中會使用到的幾種密碼學技術。 更多精彩內容且看: * [區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新](http://www.flydean.com/blockchain/) * [Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新](http://www.flydean.com/learn-spring-boot/) * [Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新](http://www.flydean.com/spring5/) * [java程式設計師從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程](http://www.flydean.com/java-roadmap-2020/) ## 單向雜湊函式(hash演算法) 在介紹單向雜湊函式之前,我們先了解一下什麼情況下需要使用到單向雜湊函式。 如果你需要從國外的網站上下載一個軟體,但是因為種種原因,國外的網路太慢了,下載幾個G的資料幾乎是不可能的。剛好國內有映象網站,可以從國內下載資料。但是如何保證國內的映象不是被篡改過後的呢?這個時候就需要單向雜湊函數了。一般來說網站會提供MD5或者SHA的值作為驗證值。 單向雜湊函式有一個輸入和輸出。輸入稱為訊息,輸出稱為雜湊值。 雜湊值的長度跟訊息的長度無關,不論多少大小的長度的訊息,都會計算出固定長度的雜湊值。 hash演算法有下面幾個特點: 1. 能夠根據任意長度的訊息計算出固定長度的雜湊值。 2. 計算速度要快。 3. 訊息不同,雜湊值也不同。 這就意味著,如果僅僅是一點點的變動都會引起整個雜湊值的巨大變化。 因為雜湊值的大小是固定的,所以有可能會出現不同的訊息產生相同雜湊值的情況。這種情況叫做碰撞。 難以發現碰撞的性質被稱為抗碰撞性。當給定某條訊息的雜湊值時,必須保證很難找到和該訊息具有相同雜湊值的另一條訊息。 4. 單向雜湊函式必須具有單向性。所謂單向性是指無法通過雜湊值來反推出訊息的性質。 比特幣使用的雜湊演算法是SHA256,他是安全雜湊演算法SHA(Secure Hash Algorithm)系列演算法的一種(另外還有SHA-1、SHA-224、SHA-384 和 SHA-512 等變體),SHA是美國國家安全域性 (NSA) 設計,美國國家標準與技術研究院(NIST) 釋出的,主要適用於數字簽名標準(DigitalSignature Standard DSS)裡面定義的數字簽名演算法(Digital Signature Algorithm DSA)。 RIPEMD(RACE Integrity Primitives Evaluation Message Digest,RACE原始完整性校驗訊息摘要),是Hans Dobbertin等3人在md4,md5的基礎上,於1996年提出來的。 ## 非對稱加密演算法 非對稱加密演算法也叫公鑰密碼演算法,通過生成的公私鑰來對明文密文進行加密解密。 非對稱加密演算法需要兩個金鑰:公開金鑰(publickey)和私有金鑰(privatekey)。公開金鑰與私有金鑰是一對,如果用公開金鑰對資料進行加密,只有用對應的私有金鑰才能解密;如果用私有金鑰對資料進行加密,那麼只有用對應的公開金鑰才能解密。因為加密和解密使用的是兩個不同的金鑰,所以這種演算法叫作非對稱加密演算法。 ![](https://img-blog.csdnimg.cn/20200331134503633.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_0,text_aHR0cDovL3d3dy5mbHlkZWFuLmNvbQ==,size_35,color_8F8F8F,t_70) ## 擴充套件閱讀:同態加密 同態加密是一種加密形式,它允許人們對密文進行特定的代數運算得到仍然是加密的結果,將其解密所得到的結果與對明文進行同樣的運算結果一樣。換言之,這項技術令人們可以在加密的資料中進行諸如檢索、比較等操作,得出正確的結果,而在整個處理過程中無需對資料進行解密。其意義在於,真正從根本上解決將資料及其操作委託給第三方時的保密問題,例如對於各種雲端計算的應用。 # 金鑰,地址和錢包 比特幣的所有權是通過數字金鑰、比特幣地址和數字簽名來確立的。數字金鑰實際上並不是儲存在網路中,而是由使用者生成並存儲在一個檔案或簡單的資料庫 中,稱為錢包。儲存在使用者錢包中的數字金鑰完全獨立於比特幣協議,可由使用者的錢包軟體生成並管理,而無需區塊鏈或網路連線。金鑰實現了比特幣的許多有趣特性,包括去中心化信任和控制、所有權認證和基於密碼學證明的安全模型。 比特幣錢包只包含私鑰而不是比特幣。每一個使用者有一個包含多個私鑰的錢包。錢包中包含成對的私鑰和公鑰。使用者用這些私鑰來簽名交易,從而證明它們擁有交易的輸出(也就是其中的比特幣)。比特幣是以交易輸出的形式來儲存在區塊鏈中(通常記為vout或txout)。 如果錢包只包含私鑰,那麼錢包地址是什麼呢?錢包地址是從公鑰的hash值的出來的,如下圖所示: ![](https://img-blog.csdnimg.cn/20200608220335798.png) 1. 首先使用隨機數發生器生成一個『私鑰』。一般來說這是一個256bits的數,擁有了這串數字就可以對相應『錢包地址』中的比特幣進行操作,所以必須被安全地儲存起來。 2. 『私鑰』經過SECP256K1演算法處理生成了『公鑰』。SECP256K1是一種橢圓曲線演算法,通過一個已知『私鑰』時可以算得『公鑰』,而『公鑰』已知時卻無法反向計算出『私鑰』。這是保障比特幣安全的演算法基礎。 3. 同SHA256一樣,RIPEMD160也是一種Hash演算法,由『公鑰』可以計算得到『公鑰雜湊』,而反過來是行不通的。 4. 將一個位元組的地址版本號連線到『公鑰雜湊』頭部(對於比特幣網路的pubkey地址,這一位元組為“0”),然後對其進行兩次SHA256運算,將結果的前4位元組作為『公鑰雜湊』的校驗值,連線在其尾部。 5. 將上一步結果使用BASE58進行編碼(比特幣定製版本),就得到了『錢包地址』。 比如,1A1zP1eP5QGefi2DMPTfTL5TTmv7DivfNa。 所以私鑰,公鑰和錢包地址的關係如下圖所示: ![](https://img-blog.csdnimg.cn/20200608220530700.png) 大家看到錢包地址1A1zP1eP5QGefi2DMPTfTL5TTmv7DivfNa有什麼想法呢? 肯定有人在想,這麼一大長串字母和數字實在是太不好記憶了。能不能生產一個比較好記的錢包地址呢? 比如MyNameIsHanMeiMei....這樣開頭的地址呢? 當然可以,這叫做靚號地址,只不過需要大量的算力才行。 # 比特幣中的交易 簡單來說,交易就是告知全網:比特幣的持有者已授權把比特幣轉帳給其他人。而新持有者能夠再次授權,轉移給該比特幣所有權鏈中的其他人。 > 注意, 在比特幣的世界裡既沒有賬戶,也沒有餘額,只有分散到區塊鏈裡的UTXO(Unspent Transaction Outputs)。 怎麼理解這個UTXO呢?沒有賬戶也沒有餘額,那麼錢包裡面的金額是怎麼計算出來的呢? 別急,讓我們一一道來。 話說,在比特幣中,比特幣錢包間的轉賬是通過交易(Transaction)實現的。 ![](https://img-blog.csdnimg.cn/20200608225429272.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_0,text_aHR0cDovL3d3dy5mbHlkZWFuLmNvbQ==,size_35,color_8F8F8F,t_70) 我們看一個標準的交易流程。 那麼問題來了,世界上第一個比特幣是哪裡來的呢? 答,是挖礦來的。好了,我們的001交易表示的就是一個挖礦的過程,在這個交易中,輸入就是挖礦,輸出編號1,BTC數目是50,目的地址是A,表示這50個BTC給A了。 接下來,A想發25個BTC給B,怎麼構造這個交易呢? 同樣的,我們需要一個輸入,這個輸入就是001交易的1號輸出,我們用001.1來表示。輸出分為兩個,第一個輸出編號1,表示要付25個BTC給B。第二個輸出編號2,表示剩下的BTC要還給A。 大家可能會問了,輸入是50BTC,兩個輸出加起來才45個BTC,好像還少了5個BTC?沒錯,這個5個BTC就是給礦工的挖礦所得。 接下來,A又繼續轉賬給C,同樣的道理,把一個一個的交易連線起來。 從上面的例子我們可以看到,實際上錢是存在一個一個的交易記錄裡面的,那些未被花費的輸出,就叫做UTXO(Unspent Transaction Outputs)。 那麼怎麼保證轉賬給B的錢,不會被其他的人消費呢?這就涉及到交易的加密過程了。 我們以單個輸入和輸出為例來詳細瞭解一下交易的構成: ![](https://img-blog.csdnimg.cn/20200608231017101.png) 上圖中,交易的輸入就是txid,也就是之前生成的還有未花費暑輸出的交易ID。output index就是交易的輸出id。 一個非常重要的ScriptSig是輸入交易的驗證,表明這個使用者擁有這個賬戶的轉賬許可權。 輸出是一個指令碼,只有滿足指令碼執行條件的人才能花費這個output。這也就是ScriptSig需要驗證的指令碼。 我們看下指令碼是怎麼做認證的吧。 比特幣的標準輸出形式有兩種。Pay To Public Key Hash (P2PKH) 和 Pay To Script Hash (P2SH)。兩者的區別在於,一個是輸出到public key的hash,一個是輸出到任意的一個指令碼輸出hash。 為了保證輸出只能由特定的人來花費,一般的情況下是直接輸出到對方的public key hash。由於只有對方擁有的私鑰能夠生成這個public key hash,也就是說只有對方才能夠對這個輸出進行驗證。 但每次都需要知道對方的public key hash還是比較麻煩的,更簡單的做法就是,傳送者直接輸出到一個特定的hash值就行了,只要對方能夠生成這個hash就可以。 下面的例子是一個P2PKH的指令碼形式。 ![](https://img-blog.csdnimg.cn/20200608231552560.png) P2PKH的輸出是一個指令碼,裡面一個重要的值就是PK hash。 怎麼驗證呢? 驗證方提供兩個值,一個是sig,一個是PubKey。因為比特幣的虛擬機器是棧結構的,我們先把這兩個值入棧。 然後呼叫OP_DUP對最上層的PubKey進行拷貝,然後呼叫OP_HASH160演算法來計算Pk Hash,然後將傳送方儲存的Pk Hash入棧。接下來呼叫OP_EQUALVERIFY對兩個PK Hash進行對比。 如果對比成功,最後一步就是驗證Sig和PubKey是否匹配。 如果都成功,說明接收方的確是這個PK Hash的擁有者。那麼對方就可以盡情使用了。 # 擴充套件閱讀:圖靈非完備性 和馮·諾伊曼同為現代計算機奠基人的阿蘭·圖靈(AlanTurin)在1950年提出了判定計算機能否像人那般實際“思考”的標準,也就是著名的“圖靈檢驗”。 他設想一臺超級計算機和一個人躲藏在幕後回答提問者的問題,而提問者則試圖分辨哪個是人哪個是計算機。 圖靈爭辯說,假如計算機偽裝得如此巧妙,以致沒有人可以在實際上把它和一個真人分辨開來的話,那麼我們就可以聲稱,這臺計算機和人一樣具備了思考能力,或者說,意識(他的原詞是“智慧”)。 在可計算性理論裡,如果一系列操作資料的規則(如指令集、程式語言、細胞自動機)按照一定的順序可以計算出結果,被稱為圖靈完備(turing complete)。 比特幣指令碼語言不是圖靈完備的,具有一定的侷限性,它沒有迴圈語句和複雜的條件控制語句。 # 總結 本文介紹了比特幣的錢包和交易的概念,希望大家能夠喜歡。 > 本文作者:flydean程式那些事 > > 本文連結:[http://www.flydean.com/bitcoin-transactions/](http://www.flydean.com/bitcoin-transactions/) > > 本文來源:flydean的部落格 > > 歡迎關注我的公眾號:程式那些事,更多精彩等著您!