//utils.go
package main
import (
"bytes"
"encoding/binary"
"log"
)
func IntToHex(num int64)[]byte{
buff:=new(bytes.Buffer) //开辟内存,存储字节集
err:=binary.Write(buff,binary.BigEndian,num)//num转化字节集写入,大端存储
if err!=nil{
log.Panic(err)
}
return buff.Bytes() //返回字节集合
}
//block.go
package main
import (
"time"
)
//定义区块
type Block struct{
Timestamp int64 //时间线,1970年1月1日00.00.00
Data []byte //交易数据
PrevBlockHash []byte //上一块数据的哈希
Hash []byte //当前块数据的哈希
Nonce int //工作量证明
}
/*//设定结构体对象哈希
func (block *Block)SetHash(){
//处理当前的时间,转化为10进制的字符串,再转化为字节集合
timestamp:=[]byte(strconv.FormatInt(block.Timestamp,10))
//叠加要哈希的数据
headers:=bytes.Join([][]byte{block.PrevBlockHash,block.Data,timestamp},[]byte{})
//计算出哈希地址
hash:=sha256.Sum256(headers)
block.Hash=hash[:]//设置哈希
}*/
//创建一个区块
func NewBlock(data string, prevBlockHash []byte) *Block{
//block是一个指针,取得一个对象初始化之后的地址
block:=&Block{time.Now().Unix(),[]byte(data),prevBlockHash,[]byte{},0}//time.Now().Unix()的单位为秒
pow:=NewProofOfWork(block)//挖矿附加这个区块
nonce,hash:=pow.Run()//开始挖矿
block.Hash=hash[:]
block.Nonce=nonce
//block.SetHash()//设置当前哈希
return block
}
//创建创世区块,
func NewGenesisBlock() *Block{
return NewBlock("hello, welcome to my second BlockChain",[]byte{})
}
//blockchain.go
package main
type BlockChain struct{
blocks []*Block //一个数组,每个元素都是指针,存储block区块的地址
}
//增加一个区块
func (blocks *BlockChain)AddBlock(data string ){
prevBlock:=blocks.blocks[len(blocks.blocks)-1] //取出最后一个区块
newBlock:=NewBlock(data,prevBlock.Hash) //创建一个区块
blocks.blocks=append(blocks.blocks,newBlock) //区块链插入新的区块
}
//创建一个区块链
func NewBlockchain ()*BlockChain{
return &BlockChain{[]*Block{NewGenesisBlock()}}
}
//proofofwork.go
package main
import (
"bytes"
"crypto/sha256"
"fmt"
"math"
"math/big"
)
var(
maxNonce=math.MaxInt64 //最大的64位整数
)
const targetBits=24//对比的位数
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(int64(targetBits)),//位数十六进制
IntToHex(int64(nonce)),//保存工作量的nonce
},[]byte{},
)
return data
}
//挖矿执行
func (pow * ProofOfWork) Run()(int,[]byte){
var hashInt big.Int
var hash [32]byte
nonce:=0
fmt.Printf("当前挖矿计算的区块数据%s",pow.block.Data)
for nonce
//test_pow.go
package main
import (
"crypto/sha256"
"fmt"
"strconv"
"time"
)
func mainx(){
flag:=0
start:=time.Now() //当前时间
for i:=0;i<10000000000;i++{ //循环挖矿
data:=sha256.Sum256([]byte(strconv.Itoa(i))) //计算哈希
fmt.Printf("%10d,%x\n",i,data)
fmt.Printf("%s\n",string(data[len(data)-2:]))
if string(data[len(data)-2:])=="00"{ //位数的哈希匹配
usedtime:=time.Since(start)
fmt.Printf("挖矿成功,用时%d ms\n",usedtime)
flag=1
break
}
}
if flag==0{
println("挖矿失败")
}
}
//main.go
package main
import (
"fmt"
"strconv"
)
func main(){
fmt.Println("hello game start")
bc:=NewBlockchain() //创建区块链
bc.AddBlock("小明1 pay 小红 10")
bc.AddBlock("小明2 pay 小红 20")
bc.AddBlock("小明3 pay 小红 30")
for _,block:=range bc.blocks{
fmt.Printf("上一块哈希%x\n",block.PrevBlockHash)
fmt.Printf("数据: %s\n",block.Data)
fmt.Printf("当前哈希%x\n",block.Hash)
pow:=NewProofOfWork(block)//校验工作量
fmt.Printf("pow %s\n",strconv.FormatBool(pow.Validate()))
fmt.Println()
}
}