一、定义创世块并打印

区块链是由一个个的区块所组成。我们把第一个区块称之为“创世块”。创世块与其他普通区块不一样的是,创世块没有前置哈希。下面我们定义一个结构体保存创世块的信息。

(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)
	}
}