您好,登錄后才能下訂單哦!
目錄:
一.初始化區塊鏈
1.代碼結構
2. 定義區塊結構與方法
3. 定義區塊鏈結構與方法
4. 幫助庫代碼
5. 測試生成區塊與初始化區塊鏈
6. 測試代碼
二. POW挖礦實現
1.代碼結構
2. 定義pow算法實現
3. 修改區塊的生成方式(從自定義到挖礦)
4. 測試代碼,測試挖礦
5.驗證區塊有效性
一.初始化區塊鏈
1. 代碼結構
Block.go :定義區塊結構與方法
BlockChain.go :定義區塊鏈結構與方法
help.go :將常用代碼塊進行封裝,形成幫助庫
main.go:測試代碼
2.定義區塊結構與方法
package BLC import ( "time" "strconv" "bytes" "crypto/sha256" ) //定義區塊 type Block struct { //1.區塊高度,也就是區塊的編號,第幾個區塊 Height int64 //2.上一個區塊的Hash值 PreBlockHash []byte //3.交易數據(最終都屬于transaction 事務) Data []byte //4.創建時間的時間戳 TimeStamp int64 //5.當前區塊的Hash值 Hash []byte //6.Nonce 隨機數,用于驗證工作量證明 Nonce int64 } //定義區塊生成Hash的方法 func (block *Block) SetHash() { //1.將Height 轉換為字節數組 []byte heightBytes := IntToHex(block.Height) //2.將TimeStamp 轉換為字節數組 []byte //2.1 將Int64的TimeStamp 轉換成二進制 timeString := strconv.FormatInt(block.TimeStamp, 2) //2.2 將二進制字符串轉成字節數組 timeBytes := []byte(timeString) //3.拼接所有屬性,形成一個二維的byte數組 blockBytes := bytes.Join([][]byte{heightBytes, block.PreBlockHash, block.Data, timeBytes, block.Hash}, []byte{}) //4.生成Hash hash := sha256.Sum256(blockBytes) block.Hash = hash[:] } //1. 創建新的區塊 func NewBlock(data string, height int64, PreBlockHash []byte) *Block { //創建區塊 block := &Block{ height, PreBlockHash, []byte(data), time.Now().Unix(), nil, 0, } //設置Hash block.SetHash() return block } //2.生成創世區塊 func CreateGenesisBlock(data string) *Block { return NewBlock(data, 1, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) }
3.定義區塊鏈與方法
package BLC type BlockChain struct { Blocks []*Block //存儲有序的區塊 } func (blc *BlockChain)AddBlockChain(data string,height int64,preHash []byte){ //創建新區塊 newBlock := NewBlock(data,height,preHash) //往鏈中添加區塊 blc.Blocks=append(blc.Blocks,newBlock) } //1.創建帶有創世區塊的區塊鏈 func CreateBlockChainWithGenesisBlock() *BlockChain { //創建創世區塊 genesisBlock := CreateGenesisBlock("Genesis Data..") //返回區塊鏈對象 return &BlockChain{[]*Block{genesisBlock}} }
4.幫助代碼庫
package BLC import ( "bytes" "encoding/binary" "log" ) //將int64轉換為字節數組 func IntToHex(num int64) []byte { buff := new(bytes.Buffer) err := binary.Write(buff, binary.BigEndian, num) if err != nil { log.Panic(err) } return buff.Bytes() }
5.測試代碼
package main import ( "publicChain/BLC" "fmt" ) func main() { //創建創世區塊 blockChain := BLC.CreateBlockChainWithGenesisBlock() //創建新的區塊 blockChain.AddBlockChain("Send $100 to Bruce", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) blockChain.AddBlockChain("Send $200 to Apple", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) blockChain.AddBlockChain("Send $300 to Alice", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) blockChain.AddBlockChain("Send $400 to Bob", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) fmt.Printf("創建的區塊鏈為:\t%v\n", blockChain) fmt.Printf("區塊鏈存儲的區塊為:\t%v\n", blockChain.Blocks) fmt.Printf("第二個區塊的數據信息(交易信息)為:\t%v\n", string(blockChain.Blocks[1].Data)) }
結果顯示
二. POW挖礦實現
1.代碼結構
多出的ProofOfWork.go用于實現挖礦
2. 定義pow算法實現
ProofOfWork.go
package BLC import ( "math/big" "bytes" "crypto/sha256" "fmt" "time" ) type ProofOfWork struct { Block *Block //當前要驗證的區塊 target *big.Int //大數存儲,區塊難度 } //數據拼接,返回字節數組 func (pow *ProofOfWork) prePareData(nonce int) []byte { data := bytes.Join( [][]byte{ pow.Block.PreBlockHash, pow.Block.Data, IntToHex(pow.Block.TimeStamp), IntToHex(int64(targetBit)), IntToHex(int64(nonce)), IntToHex(int64(pow.Block.Height)), }, []byte{}, ) return data } //256位Hash里面至少要有16個零0000 0000 0000 0000 const targetBit = 16 func (proofOfWork *ProofOfWork) Run(num int64) ([]byte, int64) { //3.判斷Hash的有效性,如果滿足條件循環體 nonce := 0 var hashInt big.Int //存儲新生成的hash值 var hash [32]byte for { //1. 將Block的屬性拼接成字節數組 databytes := proofOfWork.prePareData(nonce) //2.生成Hash hash = sha256.Sum256(databytes) fmt.Printf("挖礦中..%x\n", hash) //3. 將hash存儲至hashInt hashInt.SetBytes(hash[:]) //4.判斷hashInt是否小于Block里面的target // Cmp compares x and y and returns: // // -1 if x < y // 0 if x == y // +1 if x > y //需要hashInt(y)小于設置的target(x) if proofOfWork.target.Cmp(&hashInt) == 1 { //fmt.Println("挖礦成功", hashInt) fmt.Printf("第%d個區塊,挖礦成功:%x\n",num,hash) fmt.Println(time.Now()) time.Sleep(time.Second * 2) break } nonce ++ } return hash[:], int64(nonce) } //創建新的工作量證明對象 func NewProofOfWork(block *Block) *ProofOfWork { /*1.創建初始值為1的target 0000 0001 8 - 2 */ target := big.NewInt(1) //2.左移256-targetBit target = target.Lsh(target, 256-targetBit) return &ProofOfWork{block, target} }
3. 修改區塊的生成方式(從自定義到挖礦)
Block.go
package BLC import ( "time" ) //定義區塊 type Block struct { //1.區塊高度,也就是區塊的編號,第幾個區塊 Height int64 //2.上一個區塊的Hash值 PreBlockHash []byte //3.交易數據(最終都屬于transaction 事務) Data []byte //4.創建時間的時間戳 TimeStamp int64 //5.當前區塊的Hash值 Hash []byte //6.Nonce 隨機數,用于驗證工作量證明 Nonce int64 } //1. 創建新的區塊 func NewBlock(data string, height int64, PreBlockHash []byte) *Block { //創建區塊 block := &Block{ height, PreBlockHash, []byte(data), time.Now().Unix(), nil, 0, } //調用工作量證明的方法,并且返回有效的Hash和Nonce值 //創建pow對象 pow := NewProofOfWork(block) //挖礦驗證 hash, nonce := pow.Run(height) block.Hash = hash[:] block.Nonce = nonce return block } //2.生成創世區塊 func CreateGenesisBlock(data string) *Block { return NewBlock(data, 1, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) }
4. 測試代碼,測試挖礦
main.go
package main import ( "publicChain/part2-工作量證明/BLC" "fmt" ) func main() { fmt.Println("開始挖礦") //創建創世區塊 blockChain := BLC.CreateBlockChainWithGenesisBlock() //創建新的區塊 blockChain.AddBlockChain("Send $100 to Bruce", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) blockChain.AddBlockChain("Send $200 to Apple", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) blockChain.AddBlockChain("Send $300 to Alice", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) blockChain.AddBlockChain("Send $400 to Bob", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) fmt.Printf("創建的區塊鏈為:\t%v\n", blockChain) fmt.Printf("區塊鏈存儲的區塊為:\t%v\n", blockChain.Blocks) fmt.Printf("第二個區塊的數據信息(交易信息)為:\t%v\n", string(blockChain.Blocks[1].Data)) fmt.Printf("第二個區塊的隨機數為:\t%v\n", blockChain.Blocks[1].Nonce) }
測試結果
共計對五個區塊進行挖礦,結果如上
5.驗證區塊有效性
ProofOfWork.go
//判斷挖礦得到的區塊是否有效 func (proofOfWork *ProofOfWork) IsValid() bool { //1.proofOfWork.Block.Hash //2.proofOfWork.Target var hashInt big.Int hashInt.SetBytes(proofOfWork.Block.Hash) if proofOfWork.target.Cmp(&hashInt) == 1 { return true } return false }
測試代碼:
main.go
//通過POW挖出新的區塊block block := BLC.NewBlock("Send $500 to Tom", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) //手動將該區塊添加至區塊鏈中 blockChain.Blocks = append(blockChain.Blocks, block) //創建一個工作量證明對象 proofOfWork := BLC.NewProofOfWork(block) //判斷該區塊是否合法有效 fmt.Println(proofOfWork.IsValid())
測試結果:
第六個區塊是我們新創建的區塊,返回值為true,驗證有效
參考資料:
區塊鏈共識算法-POW: https://www.jianshu.com/p/b23cbafbbad2
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。