从零到一用go语言造一个小型区块链(一)

这篇具有很好参考价值的文章主要介绍了从零到一用go语言造一个小型区块链(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

学了两个月左右的区块链理论知识,学来学去总是不深入,总是觉得迷迷糊糊,于是我打算自己造一个小型私有的区块链。当然这一个项目我也是有借鉴前人视频的,因为项目这个东西其实单靠一个人的力量根本搞不动的,只好借鉴前人的视频来深化自己的基础内容,同时也增加自己的项目经验。

环境

编程语言:go语言
测试环境以及运行环境:windows11

理论知识

golang 区块链项目,golang,区块链,开发语言
区块链:存数据的块+hash指针链。
hash:哈希,类似于一个数学函数f(x),其输出空间f(x)为2^256次方,而输入空间x是无限的。所以有一定几率会有hash碰撞。
hash碰撞:就是两个不同的输入,却有两个相同的输出。但是专家说这个几率比bigbang还小,专家把它称为collision resistance。此外专家还提出了其余两个hash的性质:hiding , puzzle friendly。
collision resistance:耐撞,就是hash可以尽量避免碰撞的意思。
hiding:单向的,不可逆转的,即知道x可以推f(x),但是知道f(x)不可以推x。
puzzle friendly:谜一般的存在,就是这玩意很难快速通过x找出f(x),只能一个个不同的x尝试,所以这也成为了pow!
pow:proof of work,工作量证明,说白了:你家电脑开着挖矿计算f(x),电表转了多少w(或者 尝试x的次数),这就是你的工作量证明。进而v神提出了某太坊(也是区块链),想要改变某特币中pow为pos。
pos:proof of state,权益证明,说白了:有钱就有权!
UTXO:未花费的交易输出,就是一个数据结构存放了未花费的交易,这样就不用从当前区块往前查找自己获得的比特币以及自己花费的比特币来计算自己余额。
golang 区块链项目,golang,区块链,开发语言
全节点:保存区块链一切的信息
轻节点:只保留与自身相关的交易信息,等到需要验证的时候,去全节点进行验证交易信息是否伪造篡改。
交易信息:transaction,它是矿工将区块链上相关的转账交易等进行打包,生成merkle tree,然后通过merkle tree获得根值的hash值。
merkle tree:默克尔树,哈希树,叶节点链接交易信息,并且逐层取hash,直到获得根hash,将其存储block header(区块头),如下图所示。
golang 区块链项目,golang,区块链,开发语言
挖矿:用电获得算力,用算力计算hash值,查看hash是否小于区块链系统指定的target区间。这个hash值是block header中的信息进行concat(链接)的字节,然后将这些字节进行计算获得hash(当然nonce是可变的,所以可以使得每次输出的hash不同,从而找到符合的hash值)

初步实现pow的框架

初步实现:能算hash,让其达到target区间内的hash。

1.实现单个的block(区块)

package block

import (
	"bytes"
	"crypto/sha256"
	"strconv"
	"time"
)

type Block struct {
	//区块 包含 高度 prevhash thishash merkleTree(交易数据) timestamp nonce
	Height        int64
	PrevBlockHash []byte
	Data          []byte
	thisBlockHash []byte
	Timestamp     int64
	Nonce         int64
}

// 创建新的区块
func CreateBlock(data string, height int64, prevBlockHash []byte) *Block {
	block := new(Block)
	block.Height = height
	block.Data = []byte(data)
	block.Timestamp = time.Now().Unix()
	block.PrevBlockHash = prevBlockHash
	block.thisBlockHash = nil
	block.Nonce = 0
	//pow:proof of work,工作量的证明,返回hash和nonce
	pow := NewProofOfWork(block)
	//开始挖矿
	hash, nonce := pow.Start()
	//更新两者
	block.thisBlockHash = hash[:]
	block.Nonce = nonce
	return block
}

// 形成hash值
func (block *Block) SetHash() {
	//高度字节化
	height := Int64ToByte(block.Height)
	//timeStamp := Int64ToByte(block.Timestamp)
	//时间戳字节化
	timeString := strconv.FormatInt(block.Timestamp, 2)
	timeStamp := []byte(timeString)
	//拼接所有属性
	blockBytes := bytes.Join([][]byte{height, block.PrevBlockHash, block.Data, timeStamp, block.thisBlockHash}, []byte{})
	//形成hash
	hash := sha256.Sum256(blockBytes)
	//类型转换
	block.thisBlockHash = hash[:]
}

// 生成创世块
func CreateGenesisBlock(data string) *Block {
	genesisBlock := new(Block)
	//创世区块的长度为1,无前hash指针
	genesisBlock.PrevBlockHash = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	genesisBlock.Data = []byte(data)
	genesisBlock.Height = 1
	genesisBlock.Timestamp = time.Now().Unix()
	genesisBlock.SetHash()
	return genesisBlock
}

2.实现一整条blockchain(区块链)

package block

type BlockChain struct {
	//存储区块
	Blocks []*Block
}

// 创建带有创世区块的区块链
func CreateBCWithGB() *BlockChain {
	genesisBlock := CreateGenesisBlock("创世区块")
	return &BlockChain{[]*Block{genesisBlock}}
}

// 往区块链添加新的区块
func (bc *BlockChain) AppendBlock(data string, height int64, preHash []byte) {
	newBC := CreateBlock(data, height, preHash)
	bc.Blocks = append(bc.Blocks, newBC)
	//newBC := block.CreateBlock(data, int64(len(bc.Blocks)), bc.Blocks[len(bc.Blocks)-1].thisBlockHash)

}

3.实现proof of work(工作量证明)

package block

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"math/big"
)

// 代表该目标区域的hash中前16位为0
const targetZeroBits = 30

type ProofOfWork struct {
	block  *Block   //当前要验证的区块
	target *big.Int //挖矿难度(目标区域)
}

// 拼接数据,返回字节数组,以便形成hash
func (pow *ProofOfWork) prepData(nonce int64) []byte {
	data := bytes.Join(
		[][]byte{
			pow.block.PrevBlockHash,
			pow.block.Data,
			Int64ToByte(pow.block.Timestamp),
			Int64ToByte(int64(targetZeroBits)),
			Int64ToByte(int64(nonce)),
			Int64ToByte(int64(pow.block.Height))}, []byte{})
	return data
}

// 启动工作量证明(挖矿!)
func (pow *ProofOfWork) Start() ([]byte, int64) {
	//1.block属性拼接成字节数组
	//2.生成hash
	//3.判断hash有效性
	nonce := 0
	var hashInt big.Int //用于存储当前所生成的hash值
	var hash [32]byte
	for {
		prep := pow.prepData(int64(nonce))
		hash = sha256.Sum256(prep)
		fmt.Println(hash)
		hashInt.SetBytes(hash[:])
		fmt.Println(hash)
		if pow.target.Cmp(&hashInt) == 1 {
			break
		}
		nonce = nonce + 1
	}
	return hash[:], int64(nonce)
}

// 判断hash是否有效
func (pow *ProofOfWork) isValid() bool {
	var hashInt big.Int
	hashInt.SetBytes(pow.block.thisBlockHash)
	if pow.target.Cmp(&hashInt) == -1 {
		return false
	}
	return true
}

// 创建工作量证明的对象(矿工)
func NewProofOfWork(block *Block) *ProofOfWork {
	pow := new(ProofOfWork)
	//创建一个初始值为1的target
	target := big.NewInt(1)
	//左移256-targetZeroBits,这样就可以得到它的目标区域target
	target = target.Lsh(target, 256-targetZeroBits)
	pow.target = target
	pow.block = block
	return pow
}

大致的流程如下:
golang 区块链项目,golang,区块链,开发语言文章来源地址https://www.toymoban.com/news/detail-777602.html

到了这里,关于从零到一用go语言造一个小型区块链(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用go语言撸一个简易版的区块链

    用go撸一个简易版的区块链 这个最初的版本时多年以前学习go的时候,自己撸的一个简易版本的区块链。不过麻雀虽小,五脏俱全。通过这个代码你了解区块链内部的大概运行机制时没有问题的。 比特币底层区块链的代码非常复杂,但是我们可以从中梳理几个核心的概念,然

    2024年01月16日
    浏览(41)
  • 从零实现一个数据库(DataBase) Go语言实现版 0.介绍

    英文源地址 我们为什么需要数据库?为什么不是直接把数据dump进文件中. 第一个话题就是持久化. 我们将讨论如果写入文件的过程中程序崩溃了, 或者电源断电了, 文件的状态会是什么样的呢? 文件是否只是丢失了最后一次写操作? 或者以写了一半的文件结束 或者是以更差的状态

    2024年02月06日
    浏览(39)
  • 开发一个Android应用:从零到一的实践指南

    在这篇博文中,我们将逐步探讨如何从头开始构建一个Android应用。我们将从最基本的环境搭建开始,然后深入讨论组件、布局和其他核心概念。在完成整个过程后,你将会掌握一个简单但完整的Android应用开发流程。让我们开始吧! 准备开发环境 创建项目 理解项目结构 设计

    2024年02月08日
    浏览(87)
  • go脚手架,可快速构建一个go小型项目

    1、项目技术使用 gin+sqlx+redis ,后续会引入需要的技术 2、项目目的 当我们有一个新的 idea 需要马上付出实践,用于构建小型项目,直接上手写接口即可,主要为了大学生可以快速完成作业,不需要搭建环境,本项目暂时完成不了复杂的业务哦~ 3、项目介绍 脚手架架构分为

    2024年02月09日
    浏览(61)
  • 【别再做XX外卖啦!和我从零到1编写Mini版Easy-ES】完成一个Mapper模型

    作者:沈自在 代码仓库:https://gitee.com/tian-haoran/mini-easy-es 本节教程分支:https://gitee.com/tian-haoran/mini-easy-es/tree/course_02_create_mapper/ ⚠️注意:本项目会持续更新,直到功能完善 1.1.1 什么是 FactoryBean接口? 很多同学都知道 BeanFactory 接口,这个是大名鼎鼎的Spring中的核心接口,

    2024年02月04日
    浏览(55)
  • 使用golang从零开始搭建基于UTXO模型的区块链(一、实现最简易的区块链)

    真正理解区块链底层原理的方法就是写一个底层,UTXO模型区块链的开发难度还是比较简单的,等开发完后再去尝试一下基于account模型的。 什么是区块链以及UTXO模型和account模型等问题我就不在这里写了,网上的资料有很多,跟着写之前可以先去了解一下区块链的基础知识。

    2024年02月10日
    浏览(51)
  • Golang:Go语言结构

    在我们开始学习 Go 编程语言的基础构建模块前,让我们先来了解 Go 语言最简单程序的结构。 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 表达式 注释 接下来让我们来看下简单的代码,该代码输出了\\\"Hello World!\\\": 让我们来看下以上程序的各个部分: 第一

    2024年02月10日
    浏览(59)
  • 学习如何在VS Code中创建一个Golang/Go项目,并运行一个简单的Golang程序

     学习如何在VS Code中创建一个Golang项目,并运行一个简单的Golang程序。 在VS Code 手动输入命令创建一个Golang项目 在VS Code 不输入命令创建一个Golang项目 1. 在VS Code 手动输入命令创建一个Golang项目 步骤1:在VS Code中创建一个新文件夹,用于存放Golang项目文件。 步骤2:打开VS

    2024年02月14日
    浏览(61)
  • 66.Go从零搭建一个orm框架【简版】

    代码地址:https://gitee.com/lymgoforIT/golang-trick/tree/master/39-go-orm 我们在使用各种语言去做需求的时候,不管是 Java , Golang 还是 C++ 等语言,应该都接触过使用 ORM 去链接数据库,这些 ORM 有些是项目组自己整合实现的,也有些是用的开源的组件。特别在 1 个全新的项目中,我们都

    2024年01月18日
    浏览(78)
  • 【GoLang】MAC安装Go语言环境

    小试牛刀 首先安装VScode软件 或者pycharm mac安装brew软件  brew install go 报了一个错误 不提供这个支持  重新brew install go 之后又重新brew reinstall go 使用go version 可以看到go 的版本 使用go env  可以看到go安装后的配置 配置一个环境变量 vim ~/.zshrc,  

    2024年02月15日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包