目录:

一.初始化区块链

1.代码结构

2. 定义区块结构与方法

3. 定义区块链结构与方法

4. 帮助库代码

5. 测试生成区块与初始化区块链

6. 测试代码

二. POW挖矿实现

1.代码结构

2. 定义pow算法实现

3. 修改区块的生成方式(从自定义到挖矿)

4. 测试代码,测试挖矿

5.验证区块有效性


一.初始化区块链

1. 代码结构


Block.go :定义区块结构与方法

BlockChain.go :定义区块链结构与方法

help.go :将常用代码块进行封装,形成帮助库

main.go:测试代码


2.定义区块结构与方法


packageBLCimport("time""strconv""bytes""crypto/sha256")//定义区块typeBlockstruct{//1.区块高度,也就是区块的编号,第几个区块Heightint64//2.上一个区块的Hash值PreBlockHash[]byte//3.交易数据(最终都属于transaction事务)Data[]byte//4.创建时间的时间戳TimeStampint64//5.当前区块的Hash值Hash[]byte//6.Nonce随机数,用于验证工作量证明Nonceint64}//定义区块生成Hash的方法func(block*Block)SetHash(){//1.将Height转换为字节数组[]byteheightBytes:=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.生成Hashhash:=sha256.Sum256(blockBytes)block.Hash=hash[:]}//1.创建新的区块funcNewBlock(datastring,heightint64,PreBlockHash[]byte)*Block{//创建区块block:=&Block{height,PreBlockHash,[]byte(data),time.Now().Unix(),nil,0,}//设置Hashblock.SetHash()returnblock}//2.生成创世区块funcCreateGenesisBlock(datastring)*Block{returnNewBlock(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.定义区块链与方法

packageBLCtypeBlockChainstruct{Blocks[]*Block//存储有序的区块}func(blc*BlockChain)AddBlockChain(datastring,heightint64,preHash[]byte){//创建新区块newBlock:=NewBlock(data,height,preHash)//往链中添加区块blc.Blocks=append(blc.Blocks,newBlock)}//1.创建带有创世区块的区块链funcCreateBlockChainWithGenesisBlock()*BlockChain{//创建创世区块genesisBlock:=CreateGenesisBlock("GenesisData..")//返回区块链对象return&BlockChain{[]*Block{genesisBlock}}}


4.帮助代码库

packageBLCimport("bytes""encoding/binary""log")//将int64转换为字节数组funcIntToHex(numint64)[]byte{buff:=new(bytes.Buffer)err:=binary.Write(buff,binary.BigEndian,num)iferr!=nil{log.Panic(err)}returnbuff.Bytes()}


5.测试代码

packagemainimport("publicChain/BLC""fmt")funcmain(){//创建创世区块blockChain:=BLC.CreateBlockChainWithGenesisBlock()//创建新的区块blockChain.AddBlockChain("Send$100toBruce",blockChain.Blocks[len(blockChain.Blocks)-1].Height+1,blockChain.Blocks[len(blockChain.Blocks)-1].Hash)blockChain.AddBlockChain("Send$200toApple",blockChain.Blocks[len(blockChain.Blocks)-1].Height+1,blockChain.Blocks[len(blockChain.Blocks)-1].Hash)blockChain.AddBlockChain("Send$300toAlice",blockChain.Blocks[len(blockChain.Blocks)-1].Height+1,blockChain.Blocks[len(blockChain.Blocks)-1].Hash)blockChain.AddBlockChain("Send$400toBob",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


packageBLCimport("math/big""bytes""crypto/sha256""fmt""time")typeProofOfWorkstruct{Block*Block//当前要验证的区块target*big.Int//大数存储,区块难度}//数据拼接,返回字节数组func(pow*ProofOfWork)prePareData(nonceint)[]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{},)returndata}//256位Hash里面至少要有16个零0000000000000000consttargetBit=16func(proofOfWork*ProofOfWork)Run(numint64)([]byte,int64){//3.判断Hash的有效性,如果满足条件循环体nonce:=0varhashIntbig.Int//存储新生成的hash值varhash[32]bytefor{//1.将Block的属性拼接成字节数组databytes:=proofOfWork.prePareData(nonce)//2.生成Hashhash=sha256.Sum256(databytes)fmt.Printf("挖矿中..%x\n",hash)//3.将hash存储至hashInthashInt.SetBytes(hash[:])//4.判断hashInt是否小于Block里面的target//Cmpcomparesxandyandreturns:////-1ifx<y//0ifx==y//+1ifx>y//需要hashInt(y)小于设置的target(x)ifproofOfWork.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++}returnhash[:],int64(nonce)}//创建新的工作量证明对象funcNewProofOfWork(block*Block)*ProofOfWork{/*1.创建初始值为1的target000000018-2*/target:=big.NewInt(1)//2.左移256-targetBittarget=target.Lsh(target,256-targetBit)return&ProofOfWork{block,target}}




3. 修改区块的生成方式(从自定义到挖矿)

Block.go

packageBLCimport("time")//定义区块typeBlockstruct{//1.区块高度,也就是区块的编号,第几个区块Heightint64//2.上一个区块的Hash值PreBlockHash[]byte//3.交易数据(最终都属于transaction事务)Data[]byte//4.创建时间的时间戳TimeStampint64//5.当前区块的Hash值Hash[]byte//6.Nonce随机数,用于验证工作量证明Nonceint64}//1.创建新的区块funcNewBlock(datastring,heightint64,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=noncereturnblock}//2.生成创世区块funcCreateGenesisBlock(datastring)*Block{returnNewBlock(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


packagemainimport("publicChain/part2-工作量证明/BLC""fmt")funcmain(){fmt.Println("开始挖矿")//创建创世区块blockChain:=BLC.CreateBlockChainWithGenesisBlock()//创建新的区块blockChain.AddBlockChain("Send$100toBruce",blockChain.Blocks[len(blockChain.Blocks)-1].Height+1,blockChain.Blocks[len(blockChain.Blocks)-1].Hash)blockChain.AddBlockChain("Send$200toApple",blockChain.Blocks[len(blockChain.Blocks)-1].Height+1,blockChain.Blocks[len(blockChain.Blocks)-1].Hash)blockChain.AddBlockChain("Send$300toAlice",blockChain.Blocks[len(blockChain.Blocks)-1].Height+1,blockChain.Blocks[len(blockChain.Blocks)-1].Hash)blockChain.AddBlockChain("Send$400toBob",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.TargetvarhashIntbig.InthashInt.SetBytes(proofOfWork.Block.Hash)ifproofOfWork.target.Cmp(&hashInt)==1{returntrue}returnfalse}

测试代码:

main.go

//通过POW挖出新的区块blockblock:=BLC.NewBlock("Send$500toTom",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