Utilice golang para construir una cadena de bloques basada en el modelo UTXO desde cero (1. Implemente la cadena de bloques más simple)

La forma de comprender verdaderamente los principios subyacentes de la cadena de bloques es escribir una capa subyacente. La dificultad de desarrollo de la cadena de bloques del modelo UTXO es relativamente simple. Una vez completado el desarrollo, pruebe el modelo basado en cuentas.
No escribiré sobre qué es blockchain, modelo UTXO y modelo de cuenta, etc. Hay mucha información en Internet, por lo que puedes aprender los conceptos básicos de blockchain antes de escribir.

Entorno de desarrollo: goland+go1.20
dirección github de este proyecto: dirección espejo de lighteningchain : lighteningchain(1)

crear proyecto

Utilice goland para crear un proyecto, asígnele el nombre lighteningchain e go mod init lighteningchaininicialice el proyecto coninserte la descripción de la imagen aquí

estructura de bloque

Cada bloque debe contener información de encabezado para describir el bloque de manera resumida y luego almacenar datos importantes que se guardarán en el área de almacenamiento de datos (cuerpo) del bloque. Primero defina la estructura del bloque y blockchain la estructura
de

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

type BlockChain struct {
    
    
	Blocks []*Block
}

Calcular el hash

Con la estructura, el cálculo hash del bloque también es fundamental.

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
}

La variable de información es la cadena de bytes después de concatenar los distintos atributos del bloque. bytes.Join puede conectar varias cadenas de bytes, el segundo parámetro es el delimitador al conectar las cadenas de bytes, si se establece en []byte{}, estará vacío.

Crea bloques y blockchains

Bien, la preparación de la cadena de bloques está completa y el siguiente paso es crear bloques y conectarlos.
Primero defina la función de creación de bloques.

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

Pero cada bloque debe estar vinculado al hash del bloque anterior, entonces, ¿qué pasa con el primer bloque? Aquí es donde se necesita el bloque génesis.

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

Agrega el bloque creado a la blockchain

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

Ahora que toda la cadena de bloques está construida, ejecútela y probémosla. Por cierto, no olvides inicializar.

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

La función principal escribe y ejecuta la cadena de bloques de prueba.

A continuación, podemos ejecutar la cadena de bloques. Escribimos algunas instancias, las agregamos y las generamos para ver:

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

Haga clic en Ejecutar, el resultado es el siguiente:

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

¡todo es normal!

Resumir

Este capítulo construye la cadena de bloques más simple, principalmente para profundizar la comprensión del bloque y la estructura de datos de la cadena de bloques. Se puede ver que este proyecto actualmente no se ajusta a la idea de alta cohesión y bajo acoplamiento, por lo que el próximo capítulo optimizará esto e introducirá el mecanismo de consenso POW (Prueba de trabajo).

Referencias

Tutorial de Go Blockchain, parte 1: Hola, Blockchain

Supongo que te gusta

Origin blog.csdn.net/qq_44232564/article/details/129260568
Recomendado
Clasificación