[GO]使用go语言实现比特币的工作量证明

之前的博文已经实现了区块连的基本的工作原理,但在比特币系统中有一个很重要的概念:工作量证明POW,在比特币系统中它的作用就是在十分钟左右的时间内只有一个有能够记帐并得到奖励

在之前的博文中,区块的哈希值是我自己创建的,那么在这里需要将原区块函数更改为以下的样子

func NewBlock(data string, prevBlockHash []byte) *Block {
    //initial block data
    block := &Block{
        Version:1,
        PreBlockHash:prevBlockHash,
        //Hash:[]
        TimeStamp:time.Now().Unix(),
        TargetBits:targetBits,
        Nonce:0,
        MerkelRoot:[]byte{},
        Data:[]byte(data),
    }
    //block.SetHash() //get block hash
    pow := NewProofOfWork(block)
    nonce, hash := pow.Run()
    block.Nonce = nonce
    block.Hash = hash
    return block
}

新建一个工作证明proofofwork.go的文件

package main

import (
    "math/big"
    "bytes"
    "math"
    "crypto/sha256"
    "fmt"
)

const targetBits  = 24

type ProofOfWork struct {
    block     *Block
    targetBit *big.Int
}

func NewProofOfWork(block *Block) *ProofOfWork {
    var IntTarget = big.NewInt(1)
    IntTarget.Lsh(IntTarget, uint(256 - targetBits))
    return &ProofOfWork{block, IntTarget}
}

func (pow *ProofOfWork)PrepareRowData(nonce int64) []byte {
    block := pow.block
    tmp := [][]byte{
        IntToByte(block.Version),
        block.PreBlockHash,
        IntToByte(block.TimeStamp),
        block.MerkelRoot,
        IntToByte(nonce),
        IntToByte(targetBits),
        block.Data,
    }
    data := bytes.Join(tmp, []byte{})//join接收两个参数,第一个二维数组,第二个这里设置为空的连接符
    return data
}

func (pow *ProofOfWork)Run() (int64, []byte) {
    var nonce int64
    var hash [32]byte
    var HashInt big.Int
    fmt.Printf("Begin mining....")
    fmt.Printf("Target Hash : %x
", pow.targetBit.Bytes())
    for nonce < math.MaxInt64 {
        data := pow.PrepareRowData(nonce)
        hash = sha256.Sum256(data)
        HashInt.SetBytes(hash[:])
        if HashInt.Cmp(pow.targetBit) == -1 {
            fmt.Printf("found hash: %x
", hash)
            break
        } else {
            nonce++
        }
    }
    return nonce, hash[:]
}

func (pow *ProofOfWork)IsValid() bool  {
    data :=    pow.PrepareRowData(pow.block.Nonce)
    hash := sha256.Sum256(data)
    var IntHash big.Int
    IntHash.SetBytes(hash[:])
    return IntHash.Cmp(pow.targetBit) == -1
}

系统就会自动进行运算,go build *.go之后 ,执行结果为

baylor@baylor-virtual-machine:~/go/src/v2$ ./blockchain 
Begin mining....Target Hash : 010000000000000000000000000000000000000000000000000000000000
found hash: 0000009d511471179142f674a5efc491ce2e6c53aa941866037eaceb2864c364
Begin mining....Target Hash : 010000000000000000000000000000000000000000000000000000000000
found hash: 000000dc2edb49477aef1e99eb9dfd50c54ce5978a105071006a9ce0095de6fa
Begin mining....Target Hash : 010000000000000000000000000000000000000000000000000000000000
found hash: 000000c983192057f57ecfa3da5dab35701f67daa9a3556674e5d93bb75be142
============= block num :  0
Version 1
PreBlockHash: 
Hash: 0000009d511471179142f674a5efc491ce2e6c53aa941866037eaceb2864c364
TimeStamp: 5bc053cb
Nonce: 25d497c
MerkelRoot: 
Data: Gensis Block!
IsValid : true
============= block num :  1
Version 1
PreBlockHash: 0000009d511471179142f674a5efc491ce2e6c53aa941866037eaceb2864c364
Hash: 000000dc2edb49477aef1e99eb9dfd50c54ce5978a105071006a9ce0095de6fa
TimeStamp: 5bc053f2
Nonce: 19a5b8
MerkelRoot: 
Data: 班长转给老师一枚BTC
IsValid : true
============= block num :  2
Version 1
PreBlockHash: 000000dc2edb49477aef1e99eb9dfd50c54ce5978a105071006a9ce0095de6fa
Hash: 000000c983192057f57ecfa3da5dab35701f67daa9a3556674e5d93bb75be142
TimeStamp: 5bc053f4
Nonce: 943496
MerkelRoot: 
Data: 班长又转给老师一枚BTC
IsValid : true
原文地址:https://www.cnblogs.com/baylorqu/p/9778701.html