go语言模拟区块链step1

go语言模拟区块链

实现思路

1.定义区块结构

​ 第一阶段: 先实现基础字段:前区块哈希,哈希,数据

​ 第二阶段: 补充字段:Version,时间戳,难度值等

2.创建一个区块(提供一个方法)

3.定义区块链结构

4.提供一个创建区块链的方法

5.提供一个向区块链中添加区块的方法

6.打印区块链

定义区块,创建区块
type Block struct {
	// 前区块哈希
	PrevHash []byte
	// 哈希, 为了方便,我们将当前区块的哈希放入Block中
	Hash []byte
	//数据
	Data []byte
}

//创建一个区块(提供一个方法)
//输入:数据,前区块的哈希值
//输出:区块
func NewBlock(data string, prevHash []byte) *Block {
	b := Block{
		PrevHash: prevHash,
		Hash:     nil,
		Data:     []byte(data),
	}

	//计算哈希值
	//TODO
	return &b
}
定义区块链,并创建
//定义区块链结构(使用数组模拟区块链)
type BlockChain struct {
	Blocks []*Block //区块链
}

//创世语
const genesisInfo = "The first block"

//提供一个创建区块链的方法
func NewBlockChain() *BlockChain {
	//创建BlockChain,同时添加一个创世块
	genesisBlock := NewBlock(genesisInfo, nil)

	bc := BlockChain{
		Blocks: []*Block{genesisBlock},
	}

	return &bc
}
main
func main() {
	bc := NewBlockChain()
	//变量区块数据

	for i, block := range bc.Blocks {
		fmt.Printf("当前区块高度: %d\n", i)
		fmt.Printf("PrevHash : %x\n", block.PrevHash)
		fmt.Printf("Hash : %x\n", block.Hash)
		fmt.Printf("Data : %s\n", string(block.Data))
	}
}
实现setHash
//提供计算区块哈希值的方法
func (b *Block) setHash() {
	//比特币哈希算法:sha256
	// data 是block各个字段拼成的字节流

	// Join(a []string, sep string) string
	//拼接三个切片,使用bytes.Join,接收一个二维的切片,使用一维切片拼接
	// Join(s [][]byte, sep []byte) []byte

	tmp := [][]byte{
		b.PrevHash,
		b.Hash,
		b.Data,
	}
	//使用join方法,将二维切片转为1维切片
	data := bytes.Join(tmp, []byte{})

	hash := sha256.Sum256(data)
	b.Hash = hash[:]
}

注意这里没有使用append,而是用的bytes.Join()

NewBlock中加入计算哈希值得方法

func NewBlock(data string, prevHash []byte) *Block {
	...
	//计算哈希值
	b.setHash()
	return &b
}
实现AddBlock方法
//提供一个向区块链中添加区块的方法
//参数:数据,不需要提供前区块的哈希值,因为bc可以通过自己的下标拿到
func (bc *BlockChain) AddBlock(data string) {
	//通过下标,得到最后一个区块
	lastBlock := bc.Blocks[len(bc.Blocks)-1]

	//最后一个区块哈希值是新区块的前哈希
	prevHash := lastBlock.Hash

	//创建block
	newBlcok := NewBlock(data, prevHash)

	//添加bc中
	bc.Blocks = append(bc.Blocks, newBlcok)
}

main

func main() {
	bc := NewBlockChain()
	//变量区块数据
    bc.AddBlock("今天是6月27日")
    bc.AddBlock("今天是6月28日")
	for i, block := range bc.Blocks {
		fmt.Printf("当前区块高度: %d\n", i)
		fmt.Printf("PrevHash : %x\n", block.PrevHash)
		fmt.Printf("Hash : %x\n", block.Hash)
		fmt.Printf("Data : %s\n", string(block.Data))
	}
}
补充Block字段
type Block struct {
	//版本号
	Version uint64

	// 前区块哈希
	PrevHash []byte

	//交易的根哈希值
	MerkleRoot []byte

	//时间戳
	TimeStamp uint64

	//难度值, 系统提供一个数据,用于计算出一个哈希值
	Bits uint64

	//随机数,挖矿要求的数值
	Nonce uint64

	// 哈希, 为了方便,我们将当前区块的哈希放入Block中
	Hash []byte

	//数据
	Data []byte
}
对应的修改NewBlock函数
func NewBlock(data string, prevHash []byte) *Block {
	b := Block{
		Version:    0,
		PrevHash:   prevHash,
		MerkleRoot: nil, //随意写的
		TimeStamp:  uint64(time.Now().Unix()),
		Bits:  0, //随意写的
		Nonce: 0, //随意写的
		Hash:  nil,
		Data:  []byte(data),
	}

	//计算哈希值
	b.setHash()

	return &b
}
对应修改setHash方法

这时需要创建一个函数工具,用来将uint64转为[]byte

func uintToByte(num uint64) []byte {
	var buffer bytes.Buffer
	//使用二进制编码
	// Write(w io.Writer, order ByteOrder, data interface{}) error
	err := binary.Write(&buffer, binary.LittleEndian, &num)
	if err != nil {
		fmt.Println("binary.Write err :", err)
		return nil
	}

	return buffer.Bytes()
}
func (b *Block) setHash() {
	tmp := [][]byte{
		uintToByte(b.Version), //将uint64转换为[]byte
		b.PrevHash,
		b.MerkleRoot,
		uintToByte(b.TimeStamp),
		uintToByte(b.Bits),
		uintToByte(b.Nonce),
		b.Hash,
		b.Data,
	}
	//使用join方法,将二维切片转为1维切片
	data := bytes.Join(tmp, []byte{})

	hash := sha256.Sum256(data)
	b.Hash = hash[:]
}
修改main函数
func main() {
	bc := NewBlockChain()
	//变量区块数据
	time.Sleep(1 * time.Second)

	bc.AddBlock("26号btc暴涨20%")
	time.Sleep(1 * time.Second)

	bc.AddBlock("27号btc暴涨10%")
	time.Sleep(1 * time.Second)

	for i, block := range bc.Blocks {
		fmt.Printf("\n+++++++++ 当前区块高度: %d ++++++++++\n", i)
		fmt.Printf("Version : %d\n", block.Version)
		fmt.Printf("PrevHash : %x\n", block.PrevHash)
		fmt.Printf("MerkleRoot : %x\n", block.MerkleRoot)
		fmt.Printf("TimeStamp : %d\n", block.TimeStamp)
		fmt.Printf("Bits : %d\n", block.Bits)
		fmt.Printf("Nonce : %d\n", block.Nonce)
		fmt.Printf("Hash : %x\n", block.Hash)
		fmt.Printf("Data : %s\n", block.Data)
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值