Skip to content

Commit

Permalink
feat: 增加工作量证明#1
Browse files Browse the repository at this point in the history
  • Loading branch information
pibigstar committed Oct 4, 2018
1 parent 4e50a6d commit 9e7cf5c
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.idea/workspace.xml
119 changes: 77 additions & 42 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/coin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ func main() {
fmt.Printf("Hash:%x\n", block.Hash)
fmt.Printf("Data:%s\n", block.Data)
fmt.Printf("PrevHash:%x\n", block.PrevBlockHash)

// 验证
pow := core.NewProofOfWork(block)
fmt.Println("POW:", pow.Validate())

fmt.Printf("\n\n")
}

}
8 changes: 6 additions & 2 deletions src/core/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ type Block struct {
Hash []byte // Hash值
PrevBlockHash []byte // 上一个区块的Hash值
Timestamp int64 // 时间戳
Nonce int // 工作量证明
}

// 生成一个新的区块
func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{[]byte(data), []byte{}, prevBlockHash, time.Now().Unix()}
block.SetHash()
block := &Block{[]byte(data), []byte{}, prevBlockHash, time.Now().Unix(),0}
pow := NewProofOfWork(block)
nonce, hash := pow.Run()
block.Hash = hash[:]
block.Nonce = nonce
return block
}

Expand Down
67 changes: 67 additions & 0 deletions src/core/proofofwork.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package core

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

var (
maxNonce = math.MaxInt64
)
// 困难度,数越大越困难
const targetBits = 8

type ProofOfWork struct {
block *Block
target *big.Int
}
// 创建一个新的工作量证明
func NewProofOfWork(block *Block) *ProofOfWork {
target := big.NewInt(1)
// 左移
target.Lsh(target, uint(256-targetBits))
pow := &ProofOfWork{block, 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(targetBits),
IntToHex(int64(nonce)),
}, []byte{})
return data
}
// 挖矿
func (pow *ProofOfWork) Run() (int, []byte) {
var hashInt big.Int
var hash [32]byte
nonce := 0
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++
}
}
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[:])
isValidate := hashInt.Cmp(pow.target) == -1
return isValidate
}
16 changes: 16 additions & 0 deletions src/core/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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("failed Int to hex:",err)
}
return buff.Bytes()
}

0 comments on commit 9e7cf5c

Please sign in to comment.