首页 > 文章列表 > 使用go实现简易比特币区块链公链功能

使用go实现简易比特币区块链公链功能

golang
354 2022-12-17

使用go语言实现具备以下功能的简易区块链

  • 区块与区块链
  • 共识机制
  • 数据库
  • Cli命令行操作
  • 交易管理
  • 密码学
  • 数字签名
  • 交易缓存池
  • P2P网络管理

由于平时还要进行论文工作,项目不定时更新

2021.1.1实现了区块结构、区块链结构、工作量证明pow,剩下部分陆续更新

1.实现区块结构


package BLC



import (

	"bytes"

	"crypto/sha256"

	"time"

)



//实现一个最基本的区块结构

type Block struct {

	TimeStamp int64 //时间戳,区块产生的时间

	Heigth int64//区块高度(索引、号码)代表当前区块的高度

	PreBlockHash []byte//前一个区块(父区块)的哈希

	Hash []byte//当前区块的哈希

	Data []byte//交易数据

}

//创建一个新的区块

func NewBlock(height int64,preBlockHash []byte,Data []byte) *Block {

	var block Block

	block=Block{Heigth: height,PreBlockHash: preBlockHash,Data: Data,TimeStamp: time.Now().Unix()}

	block.SetHash()

	return &block

}

//计算区块哈希

func (b *Block)SetHash() { 

	//int64转换成字节数组

	//高度转换

	heightBytes:=IntToHex(b.Heigth)

	//时间转换

	timeStampBytes:=IntToHex(b.TimeStamp)

//拼接所有属性进行hash

	blockBytes:=bytes.Join([][]byte{heightBytes,timeStampBytes,b.PreBlockHash,b.Data},[]byte{})

	hash:=sha256.Sum256(blockBytes)

	b.Hash=hash[:]

}

2.实现区块链结构


package BLC



type BlockChain struct {

	Blocks []*Block //存储有序的区块

}

//初始化区块链

func CreateBlockChainWithGenesisBlock() *BlockChain {

	//添加创世区块

	genesisBlock:=CreateGenesisBlock("the init of blockchain")



	return &BlockChain{[]*Block{genesisBlock}}

}

//添加新的区块到区块链中

func (bc *BlockChain)AddBlock(height int64,data []byte,prevBlockHash []byte){

	newBlock := NewBlock(height,prevBlockHash,data)

	bc.Blocks=append(bc.Blocks,newBlock)

}

3.实现工作量证明


package BLC



import (

	"bytes"

	"crypto/sha256"

	"fmt"

	"math/big"

)



//目标难度值,生成的hash前 targetBit 位为0才满足条件

const targetBit =16

//工作量证明

type ProofOfWork struct {

	Block *Block //对指定的区块进行验证

	target *big.Int //大数据存储

}

//创建新的pow对象

func NewProofOfWork(block *Block) *ProofOfWork {

	target:=big.NewInt(1)

	target=target.Lsh(target,256-targetBit)

	return &ProofOfWork{block,target}

}

//开始工作量证明

func (proofOfWork *ProofOfWork)Run() ([]byte,int64) {

	//数据拼接

	var nonce=0 //碰撞次数

	var hash [32]byte //生成的hash

	var hashInt big.Int //存储转换后的hash

	for {

		dataBytes:=proofOfWork.prepareData(nonce)

		hash=sha256.Sum256(dataBytes)

		hashInt.SetBytes(hash[:])

		fmt.Printf("hash:\r%x",hash)

		//难度比较

		if proofOfWork.target.Cmp(&hashInt)==1{

			break

		}

		nonce++

	}

	fmt.Printf("碰撞次数:%d\n",nonce)

	return hash[:],int64(nonce)

}

//准备数据,将区块属性拼接起来,返回字节数组

func (pow *ProofOfWork)prepareData(nonce int) []byte {

	data:=bytes.Join([][]byte{

		pow.Block.PreBlockHash,

		pow.Block.Data,

		IntToHex(pow.Block.TimeStamp),

		IntToHex(pow.Block.Heigth),

		IntToHex(int64(nonce)),

		IntToHex(targetBit),

	},[]byte{})

	return data

}

4.当前运行结果