【区块链】Go 实现简单区块链

本文主要利用 Go 语言对区块链模型进行了简单的实现,通过 GoLand 创建链式结构和一个简单的 http server,对外暴露读写接口,运行 rpc 并以地址访问形式向区块链发送数据和读取数据。

简单区块链的实现大致步骤分为:

(1)创建 Block
(2)创建 Blockchain
(3)创建 Http server

在实现之前,首先通过 GoLand 创建 blockchainDemo 项目,并建立对应的 Block.goBlockchain.go 以及 Server.go 文件,具体的目录如下。

一、创建 Block

  • 创建 Block 文件
  • 创建 Block 结构体与相关函数
package core  import (  "crypto/sha256"  "encoding/hex"   "time")  type Block struct {  Index         int64  // 区块编号  Timestamp     int64  // 区块时间戳  PrevBlochHash string // 上一个区块哈希值  Hash          string // 当前区块哈希值  Data string // 区块数据  
}  // calculateHash 计算哈希值  
func calculateHash(b Block) string {  blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlochHash + b.Data  hashInBytes := sha256.Sum256([]byte(blockData))  return hex.EncodeToString(hashInBytes[:])  
}  // GenerateNewBlock 创建新区块  
func GenerateNewBlock(preBlock Block, data string) Block {  newBlock := Block{}  newBlock.Index = preBlock.Index + 1  newBlock.PrevBlochHash = preBlock.Hash  newBlock.Timestamp = time.Now().Unix()  newBlock.Data = data  newBlock.Hash = calculateHash(newBlock)  return newBlock  
}  // GenerateGenesisBlock 创建世纪区块  
func GenerateGenesisBlock() Block {  preBlock := Block{}  preBlock.Index = -1  preBlock.Hash = ""  return GenerateNewBlock(preBlock, "Genesis Block")  
}

这里需要注意的是,在创建世纪区块时,考虑到对 GenerateNewBlock 函数的复用,因此,创建了一个 preBlock 来辅助世纪块的创建,实际区块链上世纪块前面不存在其他区块,且世纪块以 0 作为索引。

二、创建 Blockchain

  • 创建 Blockchain 文件
  • 创建 Blockchain 结构体及相关方法
package core  import (  "fmt"  "log")  type Blockchain struct {  Blocks []*Block  
}  // CreateBlockchain 创建区块链  
func CreateBlockchain() *Blockchain {  genesisBlock := GenerateGenesisBlock()  blockchain := Blockchain{}  blockchain.AppendBlock(&genesisBlock)  return &blockchain  
}  // SendData 向区块链添加数据  
func (bc *Blockchain) SendData(data string) {  preBlock := bc.Blocks[len(bc.Blocks)-1]  newBlock := GenerateNewBlock(*preBlock, data)  bc.AppendBlock(&newBlock)  
}  // AppendBlock 向区块链添加新区块  
func (bc *Blockchain) AppendBlock(newBlock *Block) {  if len(bc.Blocks) == 0 {  bc.Blocks = append(bc.Blocks, newBlock)  return  }  if isValid(*newBlock, *bc.Blocks[len(bc.Blocks)-1]) {  bc.Blocks = append(bc.Blocks, newBlock)  } else {  log.Fatal("invalid block")  }  }  // 判断新添加的区块是否合法  
func isValid(newBlock Block, oldBlock Block) bool {  if newBlock.Index-1 != oldBlock.Index {  return false  }  if newBlock.PrevBlochHash != oldBlock.Hash {  return false  }  if calculateHash(newBlock) != newBlock.Hash {  return false  }  return true  
}  // Print 对区块链上的区块内容进行打印  
func (bc *Blockchain) Print() {  for _, block := range bc.Blocks {  fmt.Printf("Index: %d\n", block.Index)  fmt.Printf("Prev.Hash: %s\n", block.PrevBlochHash)  fmt.Printf("Curr.Hash: %s\n", block.Hash)  fmt.Printf("Data: %s\n", block.Data)  fmt.Printf("Timestamp: %d\n", block.Timestamp)  }  
}

三、创建 Http server

  • 创建 http server
  • 提供 API 访问接口
package main  import (  "blockchainDemo/core"  "encoding/json"   "io"   "net/http")  var blockchain *core.Blockchain  func run() {  http.HandleFunc("/blockchain/get", blockchainGetHandler)  http.HandleFunc("/blockchain/write", blockchainWriteHandler)  http.ListenAndServe("localhost:8888", nil)  
}  // 读接口  
func blockchainGetHandler(w http.ResponseWriter, r *http.Request) {  bytes, err := json.Marshal(blockchain)  if err != nil {  http.Error(w, err.Error(), http.StatusInternalServerError)  return  }  io.WriteString(w, string(bytes))  
}  // 写接口  
func blockchainWriteHandler(w http.ResponseWriter, r *http.Request) {  blockData := r.URL.Query().Get("data")  blockchain.SendData(blockData)  blockchainGetHandler(w, r)  
}  func main() {  blockchain = core.CreateBlockchain()  run()  
}

四、模型测试

在 GoLand 上运行 http server,从代码中可知监听端口为 8888,因此,读写操作对应的地址是:

  • http://localhost:8888/blockchain/get
  • http://localhost:8888/blockchain/write?data=Send 1 BTC to Me

参数 data 的内容可自定义

// 网页显示效果
{"Blocks":[{"Index":0,"Timestamp":1674227301,"PrevBlochHash":"","Hash":"90d7d6d9adc8a6dd4eca1e30d8c1a8556a8e3e508da81f30a9e520c2ee7124b0","Data":"Genesis Block"},{"Index":1,"Timestamp":1674227338,"PrevBlochHash":"90d7d6d9adc8a6dd4eca1e30d8c1a8556a8e3e508da81f30a9e520c2ee7124b0","Hash":"1a7c54ce0eaba45d5591640925405d90e74d9da5fa919b4e6eefa2447b2a4fb0","Data":"Send 1 BTC to Me"}]
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/31320.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS逆向系列之猿人学爬虫第14题-备而后动-勿使有变

文章目录 题目地址参数分析参考jspython 调用往期逆向文章推荐题目地址 https://match.yuanrenxue.cn/match/14题目难度标的是困难,主要难在js混淆部分。 参数分析 初始抓包有无限debugger反调试,可以直接hook 函数构造器过掉无限debugger Function.prototype.__construc…

Mirror网络库 | 说明

此篇为上文,下篇:Mirror网络库 | 实战 一、介绍 基于UNET,从2014年经过9年实战测试;服务器和客户端是一个项目;使用NetworkBehaviour而不是MonoBehaviour,还有NetworkServer和NetworkClient;Mi…

pdf怎么压缩到1m?这样做压缩率高!

PDF是目前使用率比较高的一种文档格式,因为它具有很高的安全性,还易于传输等,但有时候当文件体积过大时,会给我们带来不便,这时候简单的解决方法就是将其压缩变小。 想要将PDF文件压缩到1M,也要根据具体的情…

ASP.NET Core中间件记录管道图和内置中间件

管道记录 下图显示了 ASP.NET Core MVC 和 Razor Pages 应用程序的完整请求处理管道 中间件组件在文件中添加的顺序Program.cs定义了请求时调用中间件组件的顺序以及响应的相反顺序。该顺序对于安全性、性能和功能至关重要。 内置中间件记录 内置中间件原文翻译MiddlewareDe…

微服务 云原生:基于 Gogs + Drone 实现 CI/CD 自动化

一般构建部署 以一个简单的前后端项目来说,分别编写前后端的 Dockerfile 文件并构建镜像,然后编写 docker-compose.yml 构建部署,启动运行。每次代码变更后都需重新手动打包、构建、推送。 一个简单的例子: 前端: 项…

【力扣每日一题】2023.8.7 反转字符串

目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们一个字符数组形式的字符串,让我们直接原地修改反转字符串,不必返回。 给出的条件是使用O(1)的额外空间…

python爬虫相关

目录 初识爬虫 爬虫分类 网络爬虫原理 爬虫基本工作流程 搜索引擎获取新网站的url robots.txt HTHP协议 Resquests模块 前言: 安装 普通请求 会话请求 response的常用方法 简单案例 aiohttp模块 使用前安装模块 具体案例 数据解析 re解析 bs4…

AutoDL服务器的镜像版本太高,配置python3.7 tensorflow1.15版本的框架的步骤

1.选择一个实例,进入后端界面 2. 更新bashrc中的环境变量 conda init bash && source /root/.bashrc查看虚拟环境 conda info --envs可以看到此时有一个base的虚拟环境 但是它的python版本为3.8.10,无法安装tensorflow1.15,所以我们要创建一个…

Ctfshow web入门 SSTI 模板注入篇 web361-web372 详细题解 全

CTFshow SSTI web361 笔记分享 一、代码块 变量块 {{}} 用于将表达式打印到模板输出 注释块 {##} 注释 控制块 {%%} 可以声明变量,也可以执行语句 {% for i in .__class__.__mro__[1].__subclasses__() %}{% if i.__name___wrap_close %}{% print i.__init__.…

Nacos服务治理—负载均衡

引入负载均衡 在消费方引入负载均衡机制&#xff0c;同时简化获取服务提供者信息的流程 Spring Cloud引入组件LoadBalance实现负载均衡 添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web<…

js 正则表达式

js 正则表达式 http://tool.oschina.net/regex https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions 11 22 333

学习pytorch 3 tensorboard的使用

tensorboard的使用 1. 安装2. add_scalar 查看函数图形3. 查看结果4. add_image() 查看训练步骤中间结果的图片 1. 安装 pytorch conda环境 pip install tensorboard pip install opencv-python2. add_scalar 查看函数图形 常用来查看 train val loss等函数图形 from torch…

解决:Unexpected ‘debugger‘ statement.eslint(no-debugger) (即:页面中的 debugger 标红)的问题

1、问题描述&#xff1a; 其一、报错为&#xff1a; Unexpected debugger statement.eslint(no-debugger) 中文为&#xff1a; 意外的“调试器”语句.eslint&#xff08;无调试器&#xff09; 其二、问题描述为&#xff1a; 在正常的 vue 项目中使用 debugger 的调试过程…

Python-OpenCV中的图像处理-图像平滑

Python-OpenCV中的图像处理-图像平滑 图像平滑平均滤波高斯模糊中值模糊双边滤波 图像平滑 使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分&#xff08;比如&#xff1a;噪音&#xff0c;边界&#xff09;。所以边界也会被模糊…

K8s实战入门(三)

文章目录 3. 实战入门3.1 Namespace3.1.1 测试两个不同的名称空间之间的 Pod 是否连通性 3.2 Pod3.3 Label3.4 Deployment3.5 Service 3. 实战入门 本章节将介绍如何在kubernetes集群中部署一个nginx服务&#xff0c;并且能够对其进行访问。 3.1 Namespace Namespace是kuber…

ROS入门-第 1 章 ROS概述与环境搭建

目录 第 1 章 ROS概述与环境搭建 1.1 ROS简介 1.1.1 ROS概念 1.1.2 ROS设计目标 1.1.3 ROS发展历程 1.3 ROS快速体验 1.3.1 HelloWorld实现简介 1.3.2 HelloWorld&#xff08;C版&#xff09; 步骤 1&#xff1a;创建工作空间 步骤 2&#xff1a;创建发布者节点 步骤…

缓存平均的两种算法

引言 线边库存物料的合理性问题是物流仿真中研究的重要问题之一,如果线边库存量过多,则会对生产现场的布局产生负面影响,增加成本,降低效益。 写在前面 仿真分析后对线边Buffer的使用情况进行合理的评估就是一个非常重要的事情。比较关心的参数包括:缓存位最大值…

Hugging Face 的文本生成和大语言模型的开源生态

[更新于 2023 年 7 月 23 日: 添加 Llama 2。] 文本生成和对话技术已经出现多年了。早期的挑战在于通过设置参数和分辨偏差&#xff0c;同时控制好文本忠实性和多样性。更忠实的输出一般更缺少创造性&#xff0c;并且和原始训练数据更加接近&#xff0c;也更不像人话。最近的研…

16通道AD采集FMC子卡推荐哪些?

FMC149是一款16通道65MHz采样率14位直流耦合AD采集FMC子卡&#xff0c;符合VITA57.1规范&#xff0c;可以作为一个理想的IO模块耦合至FPGA前端&#xff0c;16通道AD通过FMC连接器&#xff08;HPC&#xff09;连接至FPGA从而大大降低了系统信号延迟。 该板卡支持板上可编程采样…

计算机视觉的应用9-视觉领域中的61个经典数据集【大集合】的应用与实战

大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用9-视觉领域中的61个经典数据集【大集合】的应用与实战,我们都知道计算机视觉是一门研究如何使计算机能够理解和解释数字图像或视频的技术和方法。在计算机视觉领域中,数据集是非常重要的资源,它们可以用于训练和评估…