之前的博文已经实现了区块连的基本的工作原理,但在比特币系统中有一个很重要的概念:工作量证明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