|版權聲明:本文爲博主原創文章,未經博主允許不得轉載。博客地址:https://blog.csdn.net/sgsgy5
前言:閒暇時期,參考了一些資料,用go簡單的實現了比特幣中的一些相關功能,實現完全大概2000行代碼左右,現在剛利用閒暇時間寫了一點小功能,大概500多行代碼左右,只實現了基本的區塊鏈接,存儲是選擇了github上面的一個開源庫,bolt輕量級數據庫,還有很多需要迭代完善,這個月內打算完善好,可供參考
- 區塊的結構,和區塊鏈的結構定義,一些相關功能沒有加入,後期會加入,比如交易,UTXO等
- pow工作量證明,現在不夠完善,後期會完善
- 錢包結點的相關功能,後期會完善
- 加密的相關功能,後期會完善
type Block struct { //區塊的一個結構
Version uint64 //版本號
PrevBlockHash []byte //前區塊哈希值
MerkelRoot []byte //這是一個哈希值,後面完善
TimeStamp uint64 //時間戳,從1970.1.1到現在的秒數
Difficulty uint64 //通過這個數字,算出一個哈希值:0x00010000000xxx,暫時寫死難度,代碼裏面大概5個前導0以上本地普通電腦就跑不動了
Nonce uint64 // 這是我們要找的隨機數,挖礦就找證書
Hash []byte //當前區塊哈希值, 正常的區塊不存在,我們爲了方便放進來
Data []byte //數據本身,區塊體,先用字符串表示,v4版本的時候會引用真正的交易結構
}
//定義一個區塊鏈結構,使用bolt數據庫進行保存
type BlockChain struct { //存儲在數據庫中,會生成一個文件
//數據庫的句柄
Db *bolt.DB
//最後一個區塊的哈希值
lastHash []byte //在內存中的臨時值,只保存最後一個區塊哈希
}
const difficulty = 16 //難度值寫死暫時,後期完善
//1. 定義工作量證明, block, 難度值
type ProofOfWork struct {
//數據來源
block Block
//難度值
target *big.Int //一個能夠處理大數的內置的類型,有比較方法
}
上面是一些基本的結構, 這裏比較主要的就是工作量證明函數 我們來看一下實現方式
func (pow *ProofOfWork) Run() ([]byte, uint64) {
//1. 拿到區塊數據
//block := pow.block
//區塊的哈希值
var currentHash [32]byte
//挖礦的隨機值
var nonce uint64
for {
info := pow.prepareData(nonce)
//2. 對數據做哈希運算
currentHash = sha256.Sum256(info)
//3. 比較
//引用big.int,將獲取的[]byte類型的哈希值轉成big.int
var currentHashInt big.Int
currentHashInt.SetBytes(currentHash[:])
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
//func (x *Int) Cmp(y *Int) (r int) {
if currentHashInt.Cmp(pow.target) == -1 {
//a. 比目標小,成功,返回哈希和nonce
break
} else {
//b. 比目標大,繼續nonce++
nonce++
}
}
return currentHash[:], nonce
}
這裏的哈希運算就是,加上隨機數來運算哈希,一直找找到一個隨機數使得哈希符合難度值 比目標哈希是00001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,那麼就需要找比這個哈希小的哈希,就是前面一定要有5個0的哈希才符合要求,這樣打包區塊纔是有效的,
我們這裏就簡單實現了,後期迭代會加入UTXO,交易機制,還有錢包結點相關功能,歡迎提意見,