Proof Of Work,简称POW,即对工作量的证明。
**挖矿(计算or工作)**的结果会作为数据加入区块链成为一个区块,完成这个**工作**的人也会获得奖励(即挖矿获得比特币)。
所以**挖矿**的过程是一种多劳多得的按劳分配模式,算力高,花费的时间多,获得的数字货币也就越多。
所以必须要证明矿工们为了得到答案确实进行了**计算**。
哈希算法
SHA256:一种将任意长度的消息压缩到某一固定长度的消息摘要的函数
①哈希算法不是加密算法,也就是没有密码,根据一个哈希值看不出或者说得不到原始数据,非常安全。
②一个唯一的原始数据,只能有唯一一个哈希,而且在已知原始数据和算法的前提下,可以较快计算出一个哈希值。
package main
import (
"../core"
"fmt"
"strconv"
)
func main()
{
bc :=core.NewBlockchain()
bc.AddBlock("Send 1 BTC to Ivan")
bc.AddBlock("Send 2 createblockchain -address hanshuhuan more BTC 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)
//新加:证明某个block的工作量
pow :=core.NewProofOfWork(block)
//新加:校验算法
fmt.Printf("PoW:%s\n",strconv.FormatBool(pow.Validate()))
fmt.Println()
}
}
package core
import (
"bytes"
"crypto/sha256"
"encoding/gob"
"log"
"time"
)
type Block struct
{
Timestamp int64
Transactions []*Transaction
PrevBlockHash []byte
Hash []byte
//新加
Nonce int
}
func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block
{
block := &Block
{
Timestamp: time.Now().Unix(),
Transactions: transactions,
PrevBlockHash: prevBlockHash,
Hash: []byte{},
//新加
Nonce: 0
}
//新加:创建一个工作量证明
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[:]
}
func NewGenesisBlock() *Block
{
return NewBlock( "Genesis Block",[]byte{})
}
package core;l
import (
"bytes"
"crypto/sha256"
"fmt"
"math"
"math/big"
)
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
{
//首先确定一个固定的整数1
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(pow.block.Timestamp),
IntToHex(int64(targetBits)),
//前面四项都是不可变的
IntToHex(int64(nonce)),
},
[]byte{},
)
return data
}
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()
}
func (pow *ProofOfWork) Run()(int,[]byte)
{
var hashInt big.Int
var hash [32]byte
nonce :=0
//开始计算
fmt.Printf("Mining the blockcontaining \"%s\"\n",pow.block.Data)
//一个一个对比
for nonce < maxNonce
{
//由四项不可变数据+一个可变数字nonce组成
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.Printf("\n\n")
return nonce,hash[:]
}
// Validate 校验算法
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
}
没有改动
package core
import
(
"bytes"
"encoding/binary"
"log"
)
// IntToHex Convert an int64 to a byte array
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()
}
通过一个“看似没有用的算法”,得到一个“看似没有用,但是又很麻烦的数”,因为这个计算的过程非常耗费时间(其实费电),所以这个工作量就有了价值。
首先得到这个结果的人把答案发布到网上,其他人都可以去证明(校验算法),都承认这个结果正确之后,那个首先拿到答案的人就有了比特币。
随着时间的推移,比特币全网算力不断增加,算法运行需要消耗的CPU越来越多,导致设备所需算力提高,比特币挖矿变得越发困难,所以比特币越来越难拿到,但是它本身数量有限,所以比特币越来越值钱。