目錄:
創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括保康網(wǎng)站建設(shè)、??稻W(wǎng)站制作、??稻W(wǎng)頁制作以及??稻W(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,保康網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到保康省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
一.初始化區(qū)塊鏈
1.代碼結(jié)構(gòu)
2. 定義區(qū)塊結(jié)構(gòu)與方法
3. 定義區(qū)塊鏈結(jié)構(gòu)與方法
4. 幫助庫代碼
5. 測試生成區(qū)塊與初始化區(qū)塊鏈
6. 測試代碼
二. POW挖礦實(shí)現(xiàn)
1.代碼結(jié)構(gòu)
2. 定義pow算法實(shí)現(xiàn)
3. 修改區(qū)塊的生成方式(從自定義到挖礦)
4. 測試代碼,測試挖礦
5.驗(yàn)證區(qū)塊有效性
一.初始化區(qū)塊鏈
1. 代碼結(jié)構(gòu)
Block.go :定義區(qū)塊結(jié)構(gòu)與方法
BlockChain.go :定義區(qū)塊鏈結(jié)構(gòu)與方法
help.go :將常用代碼塊進(jìn)行封裝,形成幫助庫
main.go:測試代碼
2.定義區(qū)塊結(jié)構(gòu)與方法
package BLC import ( "time" "strconv" "bytes" "crypto/sha256" ) //定義區(qū)塊 type Block struct { //1.區(qū)塊高度,也就是區(qū)塊的編號,第幾個區(qū)塊 Height int64 //2.上一個區(qū)塊的Hash值 PreBlockHash []byte //3.交易數(shù)據(jù)(最終都屬于transaction 事務(wù)) Data []byte //4.創(chuàng)建時間的時間戳 TimeStamp int64 //5.當(dāng)前區(qū)塊的Hash值 Hash []byte //6.Nonce 隨機(jī)數(shù),用于驗(yàn)證工作量證明 Nonce int64 } //定義區(qū)塊生成Hash的方法 func (block *Block) SetHash() { //1.將Height 轉(zhuǎn)換為字節(jié)數(shù)組 []byte heightBytes := IntToHex(block.Height) //2.將TimeStamp 轉(zhuǎn)換為字節(jié)數(shù)組 []byte //2.1 將Int64的TimeStamp 轉(zhuǎn)換成二進(jìn)制 timeString := strconv.FormatInt(block.TimeStamp, 2) //2.2 將二進(jìn)制字符串轉(zhuǎn)成字節(jié)數(shù)組 timeBytes := []byte(timeString) //3.拼接所有屬性,形成一個二維的byte數(shù)組 blockBytes := bytes.Join([][]byte{heightBytes, block.PreBlockHash, block.Data, timeBytes, block.Hash}, []byte{}) //4.生成Hash hash := sha256.Sum256(blockBytes) block.Hash = hash[:] } //1. 創(chuàng)建新的區(qū)塊 func NewBlock(data string, height int64, PreBlockHash []byte) *Block { //創(chuàng)建區(qū)塊 block := &Block{ height, PreBlockHash, []byte(data), time.Now().Unix(), nil, 0, } //設(shè)置Hash block.SetHash() return block } //2.生成創(chuàng)世區(qū)塊 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.定義區(qū)塊鏈與方法
package BLC type BlockChain struct { Blocks []*Block //存儲有序的區(qū)塊 } func (blc *BlockChain)AddBlockChain(data string,height int64,preHash []byte){ //創(chuàng)建新區(qū)塊 newBlock := NewBlock(data,height,preHash) //往鏈中添加區(qū)塊 blc.Blocks=append(blc.Blocks,newBlock) } //1.創(chuàng)建帶有創(chuàng)世區(qū)塊的區(qū)塊鏈 func CreateBlockChainWithGenesisBlock() *BlockChain { //創(chuàng)建創(chuàng)世區(qū)塊 genesisBlock := CreateGenesisBlock("Genesis Data..") //返回區(qū)塊鏈對象 return &BlockChain{[]*Block{genesisBlock}} }
4.幫助代碼庫
package BLC import ( "bytes" "encoding/binary" "log" ) //將int64轉(zhuǎn)換為字節(jié)數(shù)組 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() { //創(chuàng)建創(chuàng)世區(qū)塊 blockChain := BLC.CreateBlockChainWithGenesisBlock() //創(chuàng)建新的區(qū)塊 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("創(chuàng)建的區(qū)塊鏈為:\t%v\n", blockChain) fmt.Printf("區(qū)塊鏈存儲的區(qū)塊為:\t%v\n", blockChain.Blocks) fmt.Printf("第二個區(qū)塊的數(shù)據(jù)信息(交易信息)為:\t%v\n", string(blockChain.Blocks[1].Data)) }
結(jié)果顯示
二. POW挖礦實(shí)現(xiàn)
1.代碼結(jié)構(gòu)
多出的ProofOfWork.go用于實(shí)現(xiàn)挖礦
2. 定義pow算法實(shí)現(xiàn)
ProofOfWork.go
package BLC import ( "math/big" "bytes" "crypto/sha256" "fmt" "time" ) type ProofOfWork struct { Block *Block //當(dāng)前要驗(yàn)證的區(qū)塊 target *big.Int //大數(shù)存儲,區(qū)塊難度 } //數(shù)據(jù)拼接,返回字節(jié)數(shù)組 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的有效性,如果滿足條件循環(huán)體 nonce := 0 var hashInt big.Int //存儲新生成的hash值 var hash [32]byte for { //1. 將Block的屬性拼接成字節(jié)數(shù)組 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)小于設(shè)置的target(x) if proofOfWork.target.Cmp(&hashInt) == 1 { //fmt.Println("挖礦成功", hashInt) fmt.Printf("第%d個區(qū)塊,挖礦成功:%x\n",num,hash) fmt.Println(time.Now()) time.Sleep(time.Second * 2) break } nonce ++ } return hash[:], int64(nonce) } //創(chuàng)建新的工作量證明對象 func NewProofOfWork(block *Block) *ProofOfWork { /*1.創(chuàng)建初始值為1的target 0000 0001 8 - 2 */ target := big.NewInt(1) //2.左移256-targetBit target = target.Lsh(target, 256-targetBit) return &ProofOfWork{block, target} }
3. 修改區(qū)塊的生成方式(從自定義到挖礦)
Block.go
package BLC import ( "time" ) //定義區(qū)塊 type Block struct { //1.區(qū)塊高度,也就是區(qū)塊的編號,第幾個區(qū)塊 Height int64 //2.上一個區(qū)塊的Hash值 PreBlockHash []byte //3.交易數(shù)據(jù)(最終都屬于transaction 事務(wù)) Data []byte //4.創(chuàng)建時間的時間戳 TimeStamp int64 //5.當(dāng)前區(qū)塊的Hash值 Hash []byte //6.Nonce 隨機(jī)數(shù),用于驗(yàn)證工作量證明 Nonce int64 } //1. 創(chuàng)建新的區(qū)塊 func NewBlock(data string, height int64, PreBlockHash []byte) *Block { //創(chuàng)建區(qū)塊 block := &Block{ height, PreBlockHash, []byte(data), time.Now().Unix(), nil, 0, } //調(diào)用工作量證明的方法,并且返回有效的Hash和Nonce值 //創(chuàng)建pow對象 pow := NewProofOfWork(block) //挖礦驗(yàn)證 hash, nonce := pow.Run(height) block.Hash = hash[:] block.Nonce = nonce return block } //2.生成創(chuàng)世區(qū)塊 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("開始挖礦") //創(chuàng)建創(chuàng)世區(qū)塊 blockChain := BLC.CreateBlockChainWithGenesisBlock() //創(chuàng)建新的區(qū)塊 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("創(chuàng)建的區(qū)塊鏈為:\t%v\n", blockChain) fmt.Printf("區(qū)塊鏈存儲的區(qū)塊為:\t%v\n", blockChain.Blocks) fmt.Printf("第二個區(qū)塊的數(shù)據(jù)信息(交易信息)為:\t%v\n", string(blockChain.Blocks[1].Data)) fmt.Printf("第二個區(qū)塊的隨機(jī)數(shù)為:\t%v\n", blockChain.Blocks[1].Nonce) }
測試結(jié)果
共計(jì)對五個區(qū)塊進(jìn)行挖礦,結(jié)果如上
5.驗(yàn)證區(qū)塊有效性
ProofOfWork.go
//判斷挖礦得到的區(qū)塊是否有效 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挖出新的區(qū)塊block block := BLC.NewBlock("Send $500 to Tom", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) //手動將該區(qū)塊添加至區(qū)塊鏈中 blockChain.Blocks = append(blockChain.Blocks, block) //創(chuàng)建一個工作量證明對象 proofOfWork := BLC.NewProofOfWork(block) //判斷該區(qū)塊是否合法有效 fmt.Println(proofOfWork.IsValid())
測試結(jié)果:
第六個區(qū)塊是我們新創(chuàng)建的區(qū)塊,返回值為true,驗(yàn)證有效
參考資料:
區(qū)塊鏈共識算法-POW: https://www.jianshu.com/p/b23cbafbbad2