package main
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"log"
"time"
)
//创建一个区块
type Block struct {
//1 版本号
Version uint64
//2 区块前哈希
PrevHash []byte
//3 梅克尔根(这是一个哈希值 v4版本介绍)
MerkleRoot []byte
//4 时间戳
TimeStamp uint64
//5 难度值(调整比特币挖矿的难度值)
Difficulty uint64
//6 随机数 这就是挖矿所寻找的数
Nonce uint64
//7 区块当前哈希
Hash []byte //当前区块哈希,正常比特币区块当中木有当前区块哈希 我们是为了方便作了简化
//8 区块当前数据
Data []byte
}
//1 补充区块代码
//2 更新计算哈希函数
//3 优化代码
//实现一个辅助函数 功能是将uint64转[]byte
func Uint64ToByte(num uint64) []byte {
//TODO
var buffer bytes.Buffer
err:= binary.Write(&buffer,binary.BigEndian,num)
if err!=nil{
log.Panic(err)
}
return buffer.Bytes()
}
//创建区块
func NewBlock(data string,prevBlockHash []byte) *Block {
block:=Block{
Version: 00,
PrevHash: prevBlockHash,
MerkleRoot: []byte{},
TimeStamp: uint64(time.Now().Unix()),
Difficulty: 0,
Nonce: 0,
Hash: []byte{},
Data: []byte(data),
}
block.SetHash()
return &block
}
//当前区块哈希数据的拼接 (只有创建的区块才能调用)
func (block *Block) SetHash() {
var blockByteInfo []byte //存储拼接好的数据 最后作为sha256函数的参数
blockByteInfo=append(blockByteInfo,block.PrevHash...)
blockByteInfo=append(blockByteInfo,block.Data...)
blockByteInfo=append(blockByteInfo,block.MerkleRoot...)
blockByteInfo=append(blockByteInfo,Uint64ToByte(block.Version)...)
blockByteInfo=append(blockByteInfo,Uint64ToByte(block.TimeStamp)...)
blockByteInfo=append(blockByteInfo,Uint64ToByte(block.Difficulty)...)
blockByteInfo=append(blockByteInfo,Uint64ToByte(block.Nonce)...)
hash:=sha256.Sum256(blockByteInfo)
block.Hash=hash[:]
}
//构造区块链 结构体
type BlockChain struct {
blocks []*Block
}
//创建区块链
func NewBlockChain() *BlockChain {
genesisBlock:=genesisBlock()
return &BlockChain{
blocks: []*Block{genesisBlock},
}
}
//创建一个创世区块链
func genesisBlock() *Block {
return NewBlock("我是创世区块链",[]byte{})
}
//5添加区块
func (bc *BlockChain) AddBlock(data string) {
//最后一块哈希
lastHash:= bc.blocks[len(bc.blocks)-1]
block:= NewBlock(data,lastHash.Hash)
bc.blocks=append(bc.blocks,block)
}
//6. 重构代码
func main() {
bc:= NewBlockChain()
bc.AddBlock("班长转账给你50枚比特币")
bc.AddBlock("副班长转账给你50枚比特币")
for i,v:= range bc.blocks{
fmt.Printf("当前区块的高度是: %x\n",i)
fmt.Printf("区块的前哈希是: %x\n",v.PrevHash)
fmt.Printf("区块的当前哈希是:%x\n",v.Hash)
fmt.Printf("区块的当前数据是:%s\n",v.Data)
}
//block:= NewBlock("创世区块",[]byte{})
//fmt.Printf("区块的前哈希是: %x\n",block.PrevHash)
//fmt.Printf("区块的当前哈希是:%x\n",block.Hash)
//fmt.Printf("区块的当前数据是:%s\n",block.Data)
}