Use golang to build a blockchain based on the UTXO model from scratch (1. Implement the simplest blockchain)

The way to truly understand the underlying principles of the blockchain is to write an underlying layer. The development difficulty of the UTXO model blockchain is relatively simple. After the development is complete, try the account-based model.
I won’t write about what is blockchain, UTXO model and account model, etc. There are a lot of information on the Internet, so you can learn the basics of blockchain before writing.

Development environment: goland+go1.20
github address of this project: lighteningchain
mirror address: lighteningchain(1)

create project

Use goland to create a project, name it lighteningchain, and go mod init lighteningchaininitialize the project withinsert image description here

block structure

Each block should contain header information to describe the block summarily, and then store important data to be saved in the data storage area (body) of the block First define the block structure and
blockchain the structure of

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

type BlockChain struct {
    
    
	Blocks []*Block
}

Calculate the hash

With the structure, the hash calculation of the block is also essential

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
}

The information variable is the byte string after concatenating the various attributes of the block. bytes.Join can connect multiple byte strings, the second parameter is the delimiter when connecting the byte strings, if it is set to []byte{}, it will be empty.

Create blocks and blockchains

Ok, the preparation of the blockchain is complete, and the next step is to create blocks and connect them together.
First define the block creation function

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

But each block must be linked to the hash of the previous block, so what about the first block? This is where the genesis block is needed.

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

Add the created block to the blockchain

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

Now the entire blockchain is built, let’s run it and try it out. By the way, don't forget to initialize.

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

The main function writes and runs the test blockchain

Next, we can run the blockchain. We write a few instances and add them in and output them to see:

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

Click Run, the output is as follows:

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

everything is normal!

Summarize

This chapter builds the simplest blockchain, mainly to deepen the understanding of the block and blockchain data structure. It can be seen that this project does not currently conform to the idea of ​​high cohesion and low coupling, so the next chapter will optimize this and introduce a POW (Proof of Work) consensus mechanism.

References

Go Blockchain Tutorial Part 1: Hello, Blockchain

Guess you like

Origin blog.csdn.net/qq_44232564/article/details/129260568