Golang語言和區塊鏈理論學習完畢后,快速入門方法無疑是項目實戰。本文將參考https://jeiwan.cc/tags/blockchain/教程,學習如何基於Go語言構建區塊鏈。
1、引言
本文為原文第5部分學習筆記,該部分主要是實現blockchain的地址概念。一個比特幣地址的例子:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa。這是世界上首個比特幣地址,據說屬於比特幣發明人中本聰。比特幣地址是公開的,如果你想轉給某人一些BTC,那么就需要知道其地址。這些地址並不代表錢包,僅僅是具備可讀格式的公鑰。在比特幣世界中,你的ID是一個密鑰對(公/私鑰) ,該密鑰對需要保存在你的電腦或者其他你可以直接存取到它的設備。比特幣通過密碼學算法來創建密鑰對,從而保證在不能直接存取該密鑰情況下,沒人可以動你的錢。 本質上,比特幣錢包就是一個密鑰對。當你安裝錢包客戶端或者比特幣客戶端創建一個新地址時,一個密鑰對將會被創建。在比特幣世界,誰擁有密鑰,誰就可以掌控屬於該密鑰的錢。
2、Blockchain地址背景知識
在數學和密碼學中,數字簽名算法保證:
1. 當數據從發送者傳給接受者時,數據不會被篡改
2. 數據被某個發送者創建
3. 該發送者不能拒絕發送數據
通過簽名算法對數據進行處理后得到一個簽名,該簽名用於后續驗證數據使用。數字簽名使用私鑰簽名,公鑰驗證。
數據簽名需要以下信息:
1. 要簽名的數據
2. 私鑰
數據簽名過程生成一個簽名,簽名存儲於TXI中。為了校驗簽名,需要如下信息:
1. 已經被簽名的數據
2. 簽名信息
3. 公鑰
認證過程簡而言之就是:核查用私鑰加密數據后生成的簽名,是否可以用來生成公鑰。
讓我們回顧一個交易的整個聲明周期:
1. 伊始,僅僅有genesis block,該block包含一個coinbase交易。Coinbase交易不包含真是的TXI,因此不需要簽名。Coinbase交易中的TXO包含哈希后的公鑰(使用RIPEMD160(SHA256(PubKey)算法)。
2. 當有人消費時,新的交易被創建。該交易的TXI引用之前交易的TXO。每個TXI存儲一個未哈希的公鑰,和整個交易的簽名。
3. 比特幣中收到此交易的其他節點將進行驗證,將核查:TXI中公鑰的hash值是否和其引用的TXO的公鑰匹配(這保證發送者只能使用屬於其擁有的貨幣) ;簽名是否正確(這保證該交易是被一個真實的貨幣所有者創建的) 。
4. 當一個礦工准備好要挖一個新block時,該交易將放入到block中並開始挖礦。
5. 當挖到一個新block后,網絡中的其它節點會收到一個消息:該block被挖到了,同時將該block添加到blockchain中。
6. 在block被添加到blockchain之后,交易完成,其TXO可以被新的交易所引用了。
比特幣使用橢圓曲線算法生成私鑰。橢圓曲線是一個復雜的數學概念,在這不對其進行詳述(如果非常感興趣,可以參考this gentle introduction to elliptic curves,再次提醒:一大堆數學公式!) 我們所需要知道的就是這些曲線可以生成非常大的隨機數。比特幣所使用的曲線算法將從0到2256隨機選擇一個數(這意味着有大概1077個隨機數可供挑選,而宇宙可見范圍內存在大約1078到1082個原子) ,這使得同一私鑰被生成兩次的可能為0。
此外,比特幣使用ECDSA算法(Elliptic Curve Digital Signature Algorithm) 對交易進行簽名。比特幣使用Base58算法將公鑰編碼成可讀格式的字符串。該算法與著名的Base64算法類似,但為了避免利用相似性進行攻擊,Base58算法將一些字符移除了,因此沒有0(數值0) 、O(o的大寫形式) 、I(i的大寫形式) 、l(L的小寫形式) 。此外也沒有+和/。
比特幣地址由三部分組成:
Version Public key hash Checksum
00 62E907B15CBF27D5425399EBF6F0FB50EBB88F18 C29B7D93 3
3、EIPEMD160第三方擴展包安裝
按照教程實現代碼后,編譯運行提示如下錯誤信息:
D:\go\src\Blockchain5>Blockchain5 createwallet panic: crypto: requested hash function #9 is unavailable goroutine 1 [running]: crypto.Hash.New(0x9, 0x40, 0x40) C:/Go/src/crypto/crypto.go:89 +0x117 main.HashPubKey(0xc042096100, 0x40, 0x40, 0xc0420491c0, 0xc0420491e0, 0xc042049180) D:/go/src/Blockchain5/wallet.go:49 +0x91 main.Wallet.GetAddress(0x637da0, 0xc04204f540, 0xc0420491c0, 0xc0420491e0, 0xc042049180, 0xc042096100, 0x40, 0x40, 0x0, 0x0, ...) D:/go/src/Blockchain5/wallet.go:34 +0x61 main.(*Wallets).CreateWallet(0xc0420724e8, 0x6365e0, 0xc042066a80) D:/go/src/Blockchain5/wallets.go:31 +0x5f main.(*CLI).createWallet(0xc04206ff70) D:/go/src/Blockchain5/cli_createwallet.go:7 +0x3e main.(*CLI).Run(0xc04206ff70) D:/go/src/Blockchain5/cli.go:100 +0x5a8 main.main() D:/go/src/Blockchain5/main.go:5 +0x32
該信息提示加密算法ripemd160找不到,這說明標准包中不含該算法的實現,需要手動安裝擴展包。
瀏覽器輸入該安裝包路徑:“golang.org/x/crypto/ripemd160”,提示無法訪問,說明該網站在國內被禁了,需要先利用VPN等方式連接到外網,解決網絡問題。
到Go 語言包管理網站 輸入完整包名,如:“golang.org/x/crypto/ripemd160”
,回車或點擊【Go!】。如果包名輸入正確的話,下面會有提示下載過程,如果服務器上 `go get` 正確完成,下載地址列表會列出所有相關的包,點擊下載即可。
接下來,復制 golang.org.x.crypto.tar.gz
到 $GOPATH 目錄的 src 目錄下,解壓縮。接下來安裝這個包:
$ go install golang.org/x/crypto/ripemd160
安裝完成后,在wallet.go中 import “golang.org/x/crypto/ripemd160”
// HashPubKey hashes public key func HashPubKey(pubKey []byte) []byte { publicSHA256 := sha256.Sum256(pubKey) RIPEMD160Hasher := ripemd160.New() _, err := RIPEMD160Hasher.Write(publicSHA256[:]) if err != nil { log.Panic(err) } publicRIPEMD160 := RIPEMD160Hasher.Sum(nil) return publicRIPEMD160 }
重新編譯運行,即可,結果如下:
D:\go\src\Blockchain5>Blockchain5 createwallet Your new address: 12CNMc5CcitvdwUdy6gN4KUCUZLxNfu18x