package main
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"fmt"
"log"
"strconv"
"time"
)
type Block struct {
Height int64
PrevBlockHash []byte
Data []byte
Timestamp int64
Hash []byte
}
func (block *Block) SetHash() {
// 1. Height []byte
heightBytes := IntToHex(block.Height)
fmt.Println("高度 => ", heightBytes)
// 2. 将时间戳转[]byte
// 2 ~ 36
// 1528097970
timeString := strconv.FormatInt(block.Timestamp, 2)
fmt.Println("时间转化二进制 => ", timeString)
timeBytes := []byte(timeString)
fmt.Println(timeBytes)
// 3. 拼接所有属性
blockBytes := bytes.Join([][]byte{heightBytes, block.PrevBlockHash, block.Data, timeBytes}, []byte{})
// 4. 生成Hash
hash := sha256.Sum256(blockBytes)
block.Hash = hash[:]
fmt.Println("生成hash完成 => ", block.Hash)
}
type BlockChain struct {
Blocks []*Block
}
//AddBlocktoChain 增加区块到链
func (blc *BlockChain) AddBlocktoChain(data string, height int64, prevHash []byte) {
block := NewBlock(data, height, prevHash)
blc.Blocks = append(blc.Blocks, block)
}
func main() {
blc := CreateBlockchainWithGenesisBlock()
blc.AddBlocktoChain("peter send bob 100$", blc.Blocks[len(blc.Blocks)-1].Height+1, blc.Blocks[len(blc.Blocks)-1].Hash)
blc.AddBlocktoChain("bob send alice 150$", blc.Blocks[len(blc.Blocks)-1].Height+1, blc.Blocks[len(blc.Blocks)-1].Hash)
blc.AddBlocktoChain("alice send bob 50$", blc.Blocks[len(blc.Blocks)-1].Height+1, blc.Blocks[len(blc.Blocks)-1].Hash)
fmt.Println("区块高度 =>", blc.Blocks[len(blc.Blocks)-1].Height)
}
//NewBlock 创建新块
//参数:数据、高度、上一个的HASH值
func NewBlock(data string, height int64, prevBlockHash []byte) *Block {
block := &Block{
height,
prevBlockHash,
[]byte(data),
time.Now().Unix(),
nil,
}
block.SetHash()
return block
}
//CreateGenesisBlock 创建创世区块
func CreateGenesisBlock(data string) *Block {
return NewBlock(data, 1, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
}
//CreateBlockchainWithGenesisBlock 创建带有创世区块的区块链头
func CreateBlockchainWithGenesisBlock() *BlockChain {
genesisBlock := CreateGenesisBlock("Genesis data(创世块)...")
fmt.Println("=> 创建genesis block...")
return &BlockChain{[]*Block{genesisBlock}}
}
//IntToHex 将int64转换为字节数组
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()
}