使用golang从零开始搭建基于UTXO模型的区块链(一、实现最简易的区块链)

真正理解区块链底层原理的方法就是写一个底层,UTXO模型区块链的开发难度还是比较简单的,等开发完后再去尝试一下基于account模型的。
什么是区块链以及UTXO模型和account模型等问题我就不在这里写了,网上的资料有很多,跟着写之前可以先去了解一下区块链的基础知识。

开发环境:goland+go1.20
该项目github地址:lighteningchain
mirror地址:lighteningchain(1)

创建项目

使用goland创建项目,取名为lighteningchain,并使用go mod init lighteningchain初始化项目在这里插入图片描述

区块结构

每个区块应该包含头部(head)信息用于总结性的描述这个区块,然后在区块的数据存放区(body)中存放要保存的重要数据
首先定义区块结构体和区块链的结构体

type Block struct {
    
    
	Timestamp int64
	Hash      []byte //区块hash值就是其ID
	PrevHash  []byte
	Data      []byte
}

type BlockChain struct {
    
    
	Blocks []*Block
}

计算哈希

有了结构体后,区块的哈希计算也是必不可少的

func (b *Block) SetHash() {
    
    
	information := bytes.Join([][]byte{
    
    Int64ToByte(b.Timestamp), b.PrevHash, b.Data}, []byte{
    
    })
	hash := sha256.Sum256(information) //软件包sha256 实现 FIPS 180-4 中定义的 SHA224 和 SHA256 哈希算法。
	b.Hash = hash[:]
}

func Int64ToByte(num int64) []byte {
    
    
	var buf = make([]byte, 8)
	binary.BigEndian.PutUint64(buf, uint64(num))
	return buf
}

information变量是将区块的各项属性串联之后的字节串。bytes.Join可以将多个字节串连接,第二个参数是将字节串连接时的分隔符,这里设置为[]byte{}即为空。

创建区块和区块链

好了,区块链的准备工作完成,下面就要开始创建区块并将它们连在一起。
首先定义区块创建函数

func CreateBlock(prevhash []byte, data []byte) *Block {
    
    
	block := Block{
    
    time.Now().Unix(), []byte{
    
    }, prevhash, data}
	block.SetHash() //所有数据添加好后再计算hash
	return &block
}

可是每个区块都要链接上一个区块的hash,那第一个区块怎么办?这时就需要创世区块。

func GenesisBlock() *Block {
    
    
	genesisWords := "HelloWorld!"
	return CreateBlock([]byte{
    
    }, []byte(genesisWords))
}

把创建好的区块添加到区块链上

func (bc *BlockChain) AddBlock(data string) {
    
    
	newBlock := CreateBlock(bc.Blocks[len(bc.Blocks)-1].Hash, []byte(data))
	bc.Blocks = append(bc.Blocks, newBlock)
}

这下整个区块链就搭建好了,下面我们运行试试。对了,不要忘记初始化。

func CreateBlockChain() *BlockChain {
    
    
	myBlockchain := BlockChain{
    
    }
	myBlockchain.Blocks = append(myBlockchain.Blocks, GenesisBlock())
	return &myBlockchain
}

main函数编写运行测试区块链

接下来我们就可以运行区块链了,我们自己编写几个实例加进去然后输出看看:

func main() {
    
    
	blockchain := CreateBlockChain()
	time.Sleep(time.Second)
	blockchain.AddBlock("This is first Block after Genesis")
	time.Sleep(time.Second)
	blockchain.AddBlock("This is second!")
	time.Sleep(time.Second)
	blockchain.AddBlock("Awesome!")
	time.Sleep(time.Second)

	for num, block := range blockchain.Blocks {
    
    
		fmt.Printf("number:%d Timestamp: %d\n", num, block.Timestamp)
		fmt.Printf("number:%d hash: %x\n", num, block.Hash)
		fmt.Printf("number:%d Previous hash: %x\n", num, block.PrevHash)
		fmt.Printf("number:%d data: %s\n", num, block.Data)
	}
}

点击运行,输出如下:

number:0 Timestamp: 1677568251
number:0 hash: 5af650b22cc85f225c2c42850714be9466408025dfec7191436d7efa7a716433
number:0 Previous hash: 
number:0 data: HelloWorld!
number:1 Timestamp: 1677568252
number:1 hash: 3b2eafc41f8c0bd319fd2e7fd44ff2d15215ab931e6a599dc83b60f055653cb8
number:1 Previous hash: 5af650b22cc85f225c2c42850714be9466408025dfec7191436d7efa7a716433
number:1 data: This is first Block after Genesis
number:2 Timestamp: 1677568253
number:2 hash: 1be2cf3334f59a54a33e9c28957ecb836f17d731f6731bc7540066f99c2338c7
number:2 Previous hash: 3b2eafc41f8c0bd319fd2e7fd44ff2d15215ab931e6a599dc83b60f055653cb8
number:2 data: This is second!
number:3 Timestamp: 1677568254
number:3 hash: 460d954e05c98774b58426372f61997bed92ce7b4e2effb749b7bc2f0c19bdf3
number:3 Previous hash: 1be2cf3334f59a54a33e9c28957ecb836f17d731f6731bc7540066f99c2338c7
number:3 data: Awesome!

Process finished with the exit code 0

一切正常!

总结

本章搭建了一个最简易的区块链,主要是加深对于区块和区块链数据结构的认识。可以看出来,此项目目前并不符合高内聚低耦合思想,因此下一章将对此进行优化,并引入POW(工作量证明)共识机制。

参考资料

Go Blockchain Tutorial Part 1: Hello, Blockchain

猜你喜欢

转载自blog.csdn.net/qq_44232564/article/details/129260568