区块链V2版本实现之二

部分代码(proofofwork.go文件中Run函数实现):

 1 //这是pow的运算函数,为了获取挖矿的随机数,同时返回区块的哈希值
 2 func (pow *ProofOfWork) Run() ([]byte, uint64) {
 3    //1. 获取block数据
 4    //2. 拼接nonce
 5    //3. sha256
 6    //4. 与难度值比较
 7      //a. 哈希值大于难度值,nonce++
 8      //b. 哈希值小于难度值,挖矿成功,退出
 9 
10    var nonce uint64
11 
12    //block := pow.block
13 
14    var hash [32]byte
15 
16    for ; ; {
17 
18       fmt.Printf("%x\r", hash)
19 
20       //data := block + nonce
21       hash = sha256.Sum256(pow.prepareData(nonce))
22 
23       //将hash(数组类型)转成big.int, 然后与pow.target进行比较, 需要引入局部变量
24       var bigIntTmp big.Int
25       bigIntTmp.SetBytes(hash[:])
26 
27       //   -1 if x <  y
28       //    0 if x == y
29       //   +1 if x >  y
30       //
31       //func (x *Int) Cmp(y *Int) (r int) {
32       //   x              y
33       if bigIntTmp.Cmp(pow.target) == -1 {
34          //此时x < y , 挖矿成功!
35          fmt.Printf("挖矿成功!nonce: %d, 哈希值为: %x\n", nonce, hash)
36          break
37       } else {
38          nonce ++
39       }
40    }
41 
42    return hash[:], nonce
43 }
44 
45 //拼接block和nonce
46 func (pow *ProofOfWork) prepareData(nonce uint64) []byte {
47    block := pow.block
48 
49    tmp := [][]byte{
50       uintToByte(block.Version),
51       block.PrevBlockHash,
52       block.MerKleRoot,
53       uintToByte(block.TimeStamp),
54       uintToByte(block.Difficulity),
55       block.Data,
56       uintToByte(nonce),
57    }
58 
59    data := bytes.Join(tmp, []byte{})
60    return data
61 }

部分代码(使用pow更新block.go文件):

 1 ackage main
 2 
 3 import (
 4    "time"
 5 )
 6 
 7 //定义区块结构
 8 type Block struct {
 9    //区块版本号
10    Version uint64
11    //前区块哈希
12    PrevBlockHash [] byte
13    //先填写为空,后续v4的时候使用
14    MerKleRoot [] byte
15    //从1970.1.1至今的秒数
16    TimeStamp uint64
17    //挖矿难度值,v2时使用
18    Difficulity uint64
19    //随机数,挖矿找的就是这个随机数
20    Nonce uint64
21    //数据,目前使用字节流,v4开始使用交易代替
22    Data [] byte
23    //当前区块哈希,区块中本来不存在,为了方便所以添加进来
24    Hash [] byte
25 }
26 
27 const genesisInfo = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
28 
29 //创建区块,对Block的每一个字段填充数据
30 func NewBlock(data string, prevBlockHash []byte) *Block{
31    block := Block{
32       Version:00,
33 
34       PrevBlockHash: prevBlockHash,
35 
36       MerKleRoot:[]byte{},
37 
38       TimeStamp:uint64(time.Now().Unix()),
39       //随便写,v2再调整
40       Difficulity:10,
41       //随便写,v2再调整
42       Nonce:10,
43 
44       Data:          []byte(data),
45 
46       Hash:          []byte{}, //先填充为空
47    }
48 
49    ////V1之二版本添加实现hash输出
50    //block.SetHash()
51 
52    //V2版本的工作量证明
53    pow := NewProofOfWork(&block)
54    hash,nonce := pow.Run()
55 
56    block.Hash = hash
57    block.Nonce = nonce
58 
59    return &block
60 }
61 
62 //v2版本的工作量证明已经实现过了
63 ////为了生成区块哈希,实现一个简单的函数,来计算哈希值,没有随机值,没有难度值
64 //func (block *Block) SetHash() {
65 // //var data []byte
66 // ////类型是byte,而数据结构是uint64,所以构建一个工具类,将uint64转换为byte
67 // //data = append(data, uintToByte(block.Version)...)
68 // //data = append(data, block.PrevBlockHash...)
69 // //data = append(data, block.MerKleRoot...)
70 // //data = append(data, uintToByte(block.TimeStamp)...)
71 // //data = append(data, uintToByte(block.Difficulity)...)
72 // //data = append(data, uintToByte(block.Nonce)...)
73 // //data = append(data, block.Data...)
74 //
75 // //使用Join函数将二维数据便捷的转换为一维数据
76 // tmp := [][]byte{
77 //    uintToByte(block.Version),
78 //    block.PrevBlockHash,
79 //    block.MerKleRoot,
80 //    uintToByte(block.TimeStamp),
81 //    uintToByte(block.Difficulity),
82 //    uintToByte(block.Nonce),
83 //    block.Data,
84 // }
85 //
86 // data := bytes.Join(tmp,[]byte{})
87 //
88 // hash /* [32]byte */:= sha256.Sum256(data)
89 // block.Hash = hash[:]
90 //}

显示效果:

 

posted @ 2020-12-02 22:31  北漂的尘埃  阅读(127)  评论(0编辑  收藏  举报