什么是工作量证明:
1、工作的结果作为数据加入区块链成为一个区块
2、完成这个工作的人会获得奖励(这也就是通过挖矿获得比特币)
3、整个“努力工作并进行证明”的机制,就叫工作量证明
为什么采用哈希算法:
1、不可逆:无法从一个哈希值恢复原始数据,哈希并不是加密
2、唯一性:对于特定的数据,只能有一个哈希值,并且这个哈希值是唯一的
3、防篡改:改变输入数据中的一个字节,导致输出一个完全不同的哈希
哈希算法特征:
1、正向快速:给定明文和hash算法,在有限时间和有限资源内能计算出hash值
2、逆向困难:给定hash值,在有限时间内很难逆推出明文
3、输入敏感:原始输入信息修改一点信息,产生的hash值会有很大的不同
4、冲突避免:很难找到两段内容不同的明文,使得他们的hash值一致(发生冲突)
main.go
package main
import (
"core"
"fmt"
"strconv"
)
func main() {
bc := core.NewBlockChain()
bc.AddBlock("Send 1 BC to Ivan")
bc.AddBlock("Send more BC to Ivan")
for _,block := range bc.Blocks {
fmt.Printf("Prev hash: %x\n", block.PrevBlockHash)
fmt.Printf("Data: %s\n", block.Data)
fmt.Printf("Hash: %x\n", block.Hash)
//创建工作量证明
pow := core.NewProofOfWork(block)
//验证工作量证明
fmt.Printf("Pow: %s\n", strconv.FormatBool(pow.Validate()))
fmt.Println()
}
}
block.go
package core
import (
"time"
"strconv"
"bytes"
"crypto/sha256"
)
//Block keeps block header
type Block struct {
Timestamp int64 //区块创建的时间
Data []byte //区块包含的数据
PrevBlockHash []byte //前一个区块的哈希值
Hash []byte //区块自身的哈希值,用于校验区块数据有效
Nonce int //记录工作量证明用到的数字
}
//NewBlock create and returns Block
func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{
Timestamp:time.Now().Unix(),
Data: []byte(data),
PrevBlockHash: prevBlockHash,
Hash: []byte{},
}
pow := NewProofOfWork(block) //新建工作量证明
nonce,hash := pow.Run() //执行工作量证明(挖矿)
block.Hash = hash
block.Nonce = nonce
return block
}
func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp},[]byte{})
hash := sha256.Sum256(headers)
b.Hash = hash[:]
}
//NewGenesisBlock create and returns genesis Block
func NewGenesisBlock() *Block {
return NewBlock("Genesis Block", []byte{})
}
proofofwork.go
package core
import (
"math"
"math/big"
"fmt"
"crypto/sha256"
"bytes"
)
var (
maxNonce = math.MaxInt64
)
const targetBits = 20
//ProofOfWork represents a proof-of-work
type ProofOfWork struct {
block *Block
target *big.Int
}
//NewProofOfWork builds and returns a ProofOfWork
func NewProofOfWork(b *Block) *ProofOfWork {
target := big.NewInt(1)
target.Lsh(target,uint(256-targetBits))
pow := &ProofOfWork{b, target}
return pow
}
func (pow *ProofOfWork) prepareData(nonce int) []byte {
data := bytes.Join(
[][]byte{
pow.block.PrevBlockHash,
pow.block.Data,
IntToHex(int64(pow.block.Timestamp)),
IntToHex(int64(nonce)),
},
[]byte{},
)
return data
}
func (pow *ProofOfWork) Run() (int, []byte) {
var hashInt big.Int
var hash [32]byte
nonce := 0
fmt.Printf("Mining the block containing \"%s\"\n", pow.block.Data)
for nonce < maxNonce {
data := pow.prepareData(nonce)
hash = sha256.Sum256(data)
fmt.Printf("\r%x", hash)
hashInt.SetBytes(hash[:])
if hashInt.Cmp(pow.target) == -1 {
break
}else{
nonce++
}
}
fmt.Print("\n\n")
return nonce,hash[:]
}
func (pow *ProofOfWork) Validate() bool {
var hashInt big.Int
data := pow.prepareData(pow.block.Nonce)
hash := sha256.Sum256(data)
hashInt.SetBytes(hash[:])
isValid := hashInt.Cmp(pow.target) == -1
return isValid
}
utils.go
package core
import (
"bytes"
"encoding/binary"
"log"
)
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()
}
打印结果:
Mining the block containing "Genesis Block"
00000965faabec60c056cc30d9e6e45a0db7cfa84cb5897d8d5bdaa96971bd5f
Mining the block containing "Send 1 BC to Ivan"
000006910ca6331d7c640787defe1189fb158bc3d624949bc61b68a3f0031efc
Mining the block containing "Send more BC to Ivan"
00000a9e4f7f891bf6dd7323a1a5b698d5ba88c9363c8f5c9676fd075d526796
Prev hash:
Data: Genesis Block
Hash: 00000965faabec60c056cc30d9e6e45a0db7cfa84cb5897d8d5bdaa96971bd5f
Pow: true
Prev hash: 00000965faabec60c056cc30d9e6e45a0db7cfa84cb5897d8d5bdaa96971bd5f
Data: Send 1 BC to Ivan
Hash: 000006910ca6331d7c640787defe1189fb158bc3d624949bc61b68a3f0031efc
Pow: true
Prev hash: 000006910ca6331d7c640787defe1189fb158bc3d624949bc61b68a3f0031efc
Data: Send more BC to Ivan
Hash: 00000a9e4f7f891bf6dd7323a1a5b698d5ba88c9363c8f5c9676fd075d526796
Pow: true
来源:https://www.cnblogs.com/coder-886/p/9777350.html