区块链是由一个个的区块所组成。我们把第一个区块称之为“创世块”。创世块与其他普通区块不一样的是,创世块没有前置哈希。下面我们定义一个结构体保存创世块的信息。
(1)定义区块结构体
// 定义区块
type Block struct {
PrevHash []byte // 上一个区块哈希
Hash []byte // 当前区块哈希
Data []byte // 区块数据
}
(2)提供创建方法
// 创建方法
// 参数一:区块数据
// 参数二:前置区块的哈希
func NewBlock(data []byte, prevHash []byte) *Block {
block := Block{
PrevHash: prevHash,
Data: []byte(data),
}
block.SetHash()
return &block
}
(3)生成哈希
// 设置区块哈希
func (block *Block) SetHash() {
tmp := [][]byte{
block.PrevHash,
block.Data,
}
blockInfo := bytes.Join(tmp, []byte{})
// 2.使用sha256加密
hash := sha256.Sum256(blockInfo)
block.Hash = hash[:]
}
(4)打印区块
const genesisInfo = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
func main() {
block := NewBlock([]byte(genesisInfo), []byte{0x0000000000000000})
fmt.Printf("PreHash : %x\n", block.PrevHash)
fmt.Printf("Hash : %x\n", block.Hash)
fmt.Printf("Data : %s\n", block.Data)
}
二、引入区块链结构
(1)引入区块链结构
type BlockChain struct {
Blocks []*Block // 保存所有区块
}
(2)提供创建方法
const genesisInfo = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
// 创建方法
func NewBlockChain() *BlockChain {
// 创建创世块
genericBlock := NewBlock([]byte(genesisInfo), []byte{})
// 创建BlockChain
bc := BlockChain{[]*Block{genericBlock}}
return &bc
}
(3)改写main方法
func main() {
bc := NewBlockChain()
for i, block := range bc.Blocks {
fmt.Println("======== block height : ", i, "=======")
fmt.Printf("PreHash : %x\n", block.PrevHash)
fmt.Printf("Hash : %x\n", block.Hash)
fmt.Printf("Data : %s\n", block.Data)
}
}
(4)实现AddBlock方法
// 添加区块
func (bc *BlockChain) AddBlock(data string) {
// 获取最后区块
lastBlock := bc.Blocks[len(bc.Blocks)-1]
// 创建一个新区块
block := NewBlock([]byte(data), lastBlock.Hash)
// 添加新区块
bc.Blocks = append(bc.Blocks, block)
}
(5)改写main方法
func main() {
bc := NewBlockChain()
bc.AddBlock("1111")
bc.AddBlock("2222")
for i, block := range bc.Blocks {
fmt.Println("======== block height : ", i, "=======")
fmt.Printf("PreHash : %x\n", block.PrevHash)
fmt.Printf("Hash : %x\n", block.Hash)
fmt.Printf("Data : %s\n", block.Data)
}
}
三、补充Block字段
(1)补充Block字段
// 定义区块
type Block struct {
// 版本号
Version uint64
// 前区块哈希值
PrevHash []byte
// 梅克尔根
MerKleRoot []byte
// 时间戳
TimeStamp uint64
// 难度值
Difficulty uint64
//随机数
Nonce uint64
// 当前区块哈希值
Hash []byte
// 区块数据
Data []byte
}
(2)改写NewBlock方法
// 创建方法
func NewBlock(data []byte, prevHash []byte) *Block {
block := Block{
Version: 00,
PrevHash: prevHash,
MerKleRoot: []byte{},
TimeStamp: uint64(time.Now().Unix()),
Difficulty: 1,
Nonce: 1,
Data: []byte(data)}
//提供一个设置哈希的方法
block.SetHash()
return &block
}
(3)重写SetHash方法
// 设置区块哈希
func (block *Block) SetHash() {
tmp := [][]byte{
block.PrevHash,
block.Data,
block.MerKleRoot,
uint64ToByte(block.Version),
uint64ToByte(block.TimeStamp),
uint64ToByte(block.Difficulty),
uint64ToByte(block.Nonce),
}
blockInfo := bytes.Join(tmp, []byte{})
// 2.使用sha256加密
hash := sha256.Sum256(blockInfo)
block.Hash = hash[:]
}
(4)提供uint64ToByte方法
// 把uint64转换成字节数组
func uint64ToByte(num uint64) []byte {
var buffer bytes.Buffer
err := binary.Write(&buffer, binary.BigEndian, num)
if err != nil {
log.Panic(err)
}
return buffer.Bytes()
}
(5)改写main方法
func main() {
bc := NewBlockChain()
bc.AddBlock("1111")
bc.AddBlock("2222")
for i, block := range bc.Blocks {
fmt.Println("======== block height : ", i, "=======")
fmt.Printf("Version : %d\n", block.Version)
fmt.Printf("PreHash : %x\n", block.PrevHash)
fmt.Printf("MerKleRoot : %x\n", block.MerKleRoot)
fmt.Printf("TimeStamp : %d\n", block.TimeStamp)
fmt.Printf("Difficulty : %d\n", block.Difficulty)
fmt.Printf("Nonce : %d\n", block.Nonce)
fmt.Printf("Hash : %x\n", block.Hash)
fmt.Printf("Data : %s\n", block.Data)
}
}