go语言实现简易比特币系统(一):区块及区块链

1. 区块

开始之前,先看一下区块的结构
在这里插入图片描述
上图为比特币第0个区块信息,通常情况下,区块结构分为区块头和区块体。分类之后的区块结构可以用下图表示

在这里插入图片描述下面开始实现区块及相应功能

定义区块结构

//定义简单区块结构
type Block struct {
    
    
	//版本
	Version uint64
	//前区块哈希
	PrevHash []byte
	//Merkel根
	MerkelRoot []byte
	//时间戳
	TimeStamp uint64
	//难度值
	Difficulty uint64
	//随机数
	Nonce uint64

	//当前区块哈希,正常情况下比特币区块中没有当前区块哈希,我们为了方便做了简化
	Hash []byte
	//数据
	Data []byte
}

创建区块函数

定义完区块后,就需要创建去创建区块了。

func NewBlock (data string, prevBlockHash []byte) *Block{
    
    
	block := Block{
    
    
		Version:    00, //这里的版本号随便为随便填写,以后会完善
		PrevHash:   prevBlockHash,
		MerkelRoot: []byte{
    
    }, //同上
		TimeStamp:  uint64(time.Now().Unix()),
		Difficulty: 0,  //同上
		Nonce:      0,  //同上
		Hash:       []byte{
    
    },
		Data:       []byte(data),
	}

	block.SetHash()

	return &block
}

创建生成当前区块哈希方法

func (block *Block) SetHash(){
    
    
	//拼装数据
	tmp := [][]byte{
    
    
		Uint64ToByte(block.Version),
		block.PrevHash,
		block.MerkelRoot,
		Uint64ToByte(block.TimeStamp),
		Uint64ToByte(block.Difficulty),
		Uint64ToByte(block.Nonce),
		block.Data,
	}
	blockInfo := bytes.Join(tmp, []byte{
    
    })

	//对数据进行sha256
	hash := sha256.Sum256(blockInfo)
	//设置当前区块的hash为新生成的hash
	block.Hash = hash[:]
}

创建Uint64ToByte函数, 把uint64转化为byte

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

2. 区块链

使用数组引入区块链

这里先简单的使用数组充当区块链,后续会使用bolt进行优化

type BlockChain struct {
    
    
	//定义一个区块类型的数组
	blocks []*Block
}

创建区块链

func NewBlockChain () *BlockChain{
    
    
	//定义创世块
	genesisBlock := GenesisBlock()

	//返回一个区块链
	return &BlockChain{
    
    blocks: []*Block{
    
    genesisBlock}}
}

创建创世块

func  GenesisBlock() *Block {
    
    
	return NewBlock("创世块!", []byte{
    
    })

}

创建添加区块的方法

func (bc *BlockChain) AddBlock (data string) {
    
    
	//获取前区块哈希
	lastBlock := bc.blocks[len(bc.blocks)-1]
	prevHash := lastBlock.Hash
	//创建新区块,并设置数据和前区块hash
	block := NewBlock(data, prevHash)
	//把新区块添加到区块链后面
	bc.blocks = append(bc.blocks, block)
}

测试

func main () {
    
    
	//获取区块链
	bc := NewBlockChain()
	//为区块链添加一个新的区块
	bc.AddBlock("第二个区块")
	for i, block := range bc.blocks{
    
    
		fmt.Printf("============当前区块高度%d==============\n", i)
		fmt.Printf("前区块哈希: %x\n", block.PrevHash)
		fmt.Printf("区块哈希: %x\n", block.Hash)
		fmt.Printf("区块数据: %s\n", block.Data)
	}

}

源码:https://gitee.com/xiaoshengdada/go_bitcoin.git
自此,一个简单的比特币架构设计完成,但是比特币系统的精髓远远不止这些。后面会继续完善这个系统。下一篇博客会加pow共识算法(挖矿功能)。
如果有问题可以来微信群交流,一起学习进步。
在这里插入图片描述最最后,推荐一位大佬的公众号:区块链技术栈,没错就是那位死磕以太坊源码作者的公众号。

猜你喜欢

转载自blog.csdn.net/qq_31639829/article/details/115287531