基于共识算法和区块链模拟实现超级账本

这篇具有很好参考价值的文章主要介绍了基于共识算法和区块链模拟实现超级账本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于共识算法和区块链模拟实现超级账本

实验语言:GO

实验环境:GoLand 2022.1 ; go 1.13.4.widows-amd64.msi ;curl-7.83.1

实验中使用的开源包:

http://github.com/davecgh/go-spew/spew;http://github.com/gorilla/mux;http://github.com/joho/godotenv;

实验中使用的工具包:

"crypto/sha256"“encoding/hex”“encoding/json”“fmt”“io”“log”“net/http”“os”“strconv”“strings”“sync”"time”

实验中的网络端口:http://localhost:8080

目录

实验简述

1.基于pow算法挖矿并实现区块链的基本功能

2.基于LevleDB实现数据的KV存储

实验背景

P2P

对等网络,即对等计算机网络,是一种在对等者之间分配任务和工作负载的分布式应用架构,网络的参与者共享他们所拥有的一部分硬件资源(处理能力、存储能力、网络连接能力、打印机等),这些共享资源通过网络提供服务和内容,能被其它对等节点直接访问而无需经过中间实体。在此网络中的参与者既是资源、服务和内容的提供者,又是资源、服务和内容的获取者。

比特币

与大多数货币不同,比特币不依靠特定货币机构发行,它依据特定算法,通过大量的计算产生,比特币经济使用整个P2P网络中众多节点构成的分布式数据库来确认并记录所有的交易行为,并使用密码学的设计来确保货币流通各个环节的安全性。P2P的去中心化特性与算法本身可以确保无法通过大量制造比特币来人为操控币值。基于密码学的设计可以使比特币只能被真实的拥有者转移或支付。

区块链

区块链,就是一个又一个区块组成的链条。每一个区块中保存了一定的信息,它们按照各自产生的时间顺序连接成链条。这个链条被保存在所有的服务器中,只要整个系统中有一台服务器可以工作,整条区块链就是安全的。这些服务器在区块链系统中被称为节点,它们为整个区块链系统提供存储空间和算力支持。如果要修改区块链中的信息,必须征得半数以上节点的同意并修改所有节点中的信息,而这些节点通常掌握在不同的主体手中。

实验第一部分-基于pow算法挖矿并实现区块链的基本功能

实验原理

区块有两种,一个是普通区块,一个就是创世区块。创世区块就是一项区块链项目中的第一个区块。

实验内容

配置环境

声明变量

//区块结构体
type Block struct 
{
   PreHash   string
   Hashcode  string
   TimeStamp string
   Diff      int
   Value     string
   Index     int
   Nonce     int
}

//区块链链表
type lian_my struct {
   NextNode *lian_my
   Data     *BLOCK.Block
}

这一步用于根据比特币定义我们的哈希值以及新的链表

方法

通过自带的数据包生成每一个区块的哈希值
func GenerationHashValue(block Block) string {
   var hashdata = strconv.Itoa(block.Index) + strconv.Itoa(block.Nonce) + strconv.Itoa(block.Diff) + block.TimeStamp
   var hashmy = sha256.New()
   hashmy.Write([]byte(hashdata))
   hashed := hashmy.Sum(nil)
   return hex.EncodeToString(hashed)
}

生成之后的区块
func GenerateNextBlock(data string, oldBlock Block) Block {
   var newBlock Block
   newBlock.TimeStamp = time.Now().String()
   newBlock.Diff = 3
   newBlock.Index = oldBlock.Nonce + 1
   newBlock.Value = data
   newBlock.PreHash = oldBlock.Hashcode
   newBlock.Nonce = 0
   newBlock.Hashcode = pow(newBlock.Diff, &newBlock)
   return newBlock
}
初始区块声明
func GenerateFirstBlock(data string) Block {
   var chuangshi Block
   chuangshi.PreHash = "0"
   chuangshi.TimeStamp = time.Now().String()
   chuangshi.Diff = 3
   chuangshi.Value = data
   chuangshi.Index = 1
   chuangshi.Nonce = 0
   chuangshi.Hashcode = GenerationHashValue(chuangshi)
   return chuangshi
}
pow算法
//pow工作量证明
func pow(diff int, block *Block) string {
   for {
      hashmy := GenerationHashValue(*block)
      if strings.HasPrefix(hashmy, strings.Repeat("0", diff)) {
         return hashmy
         fmt.Println("挖到了一个区块")
      } else {
         block.Nonce++
      }
   }
}

函数传入指针,这个相当于是在不断的挖矿,for是一个死循环,用block的信息生成一个哈希值,判断这一次的哈希值是否前面的0满足diff,这里可以直接使用hasprefix()函数来进行判断,相当的方便。

区块链记录
//创建头节点,保存创世区块
func CreaterHeader(data *BLOCK.Block) *lian_my {
   headerNode := new(lian_my)
   headerNode.NextNode = nil
   headerNode.Data = data
   return headerNode
}

//添加下一个结点
func Addnode(data *BLOCK.Block, node *lian_my) *lian_my {
   var newNode *lian_my = new(lian_my)
   newNode.NextNode = nil
   newNode.Data = data
   node.NextNode = newNode
   return newNode
}

//展示当前所有节点
func ShowNodes(node *lian_my) {
   n := node
   for {
      if n.NextNode == nil {
         fmt.Println(n.Data)
         break
      } else {
         fmt.Println(n.Data)
         n = n.NextNode
      }
   }
}

调用方法运行结果

初始化第一个区块
进行挖矿

对区块链共识仿真

广播基本的区块链

实验 第二部分-模拟实现基于LevelDB的KV存储

实验原理

leveldb是谷歌两位工程师使用C++实现的k-v存储系统,我们这里希望使用go进行复现, 属于按照key和value存储,用户也是可以重写排序函数,包含了最基本的数据操作接口,put,get,delay.同时多次操作可以认为是一次原子操作,可以用于支持事务。

实验代码里的方法及对象

结构体初始化
DB结构体
type DB struct {
   path string
   data map[string][]byte
}

这里path(字符串类型)用于存储连接的地址,data(byte类型)用于存储kv的键值

迭代器接口和结构体
type Iterator interface {
   Next() bool
   Key() []byte
   Value() []byte
}
type myIterator struct {
   data   []Pair
   index  int
   length int
}

​ NEXT判断是否下一个有值, key和value用于遍历键值

键值的结构体
type Pair struct {
   Key   []byte
   Value []byte
}
初始化结构体
func NewDefaultIterator(data map[string][]byte) *myIterator {
   my := new(myIterator)
   my.index = -1
   my.length = len(data)
   for k, v := range data {
      p := Pair{[]byte(k),
         v,
      }
      my.data = append(self.data, p)
   }
   return my
}

初始化迭代器的默认值并进行遍历

迭代器基本功能的实现
func (self *myIterator) Next() bool {
   if self.index < self.length-1 {
      self.index++
      return true
   }
   return false
}

func (self *myIterator) Key() []byte {
   if self.index == -1 || self.index >= self.length {
      panic(fmt.Errorf("INDEXOUTOFBOUNDERROR"))
   }
   return self.data[self.index].Key
}

func (self *myIterator) Value() []byte {
   if self.index >= self.length {
      panic(fmt.Errorf("INDEXOUTOFBOUNDERROR"))
   }
   return self.data[self.index].Value
}

实现下一个是否存在,以及返回value 和key

模拟功能实现

模拟连接
func New(path string) (*DB, error) {
   my := DB{
      path: path,
      data: make(map[string][]byte),
   }
   return &my, nil
}
模拟put,get
func (my *DB) Put(key []byte, value []byte) error {
   my.data[string(key)] = value
   return nil
}


func (my *DB) Get(key []byte) ([]byte, error) {
   if v, ok := my.data[string(key)]; ok {
      return v, nil//如果有则说明可以直接使用
   } else {//如果返回为空,则说明没有
      return nil, 
      fmt.Errorf("Not Found")
   }
}
模拟 Del
func (self *DB) Del(key [](byte)) error {
   if _, ok := self.data[string(key)]; ok {
      delete(self.data, string(key))
      return nil
   } else {
      return fmt.Errorf("not Found")
   }
}

KB存储测试

迭代器测试
测试方法:
import (
   "fmt"
   "testing"
)

//迭代器测试
func TestNewDefaultIterator(t *testing.T) {
   data := make(map[string][]byte)
   data["K1"] = []byte("V1")
   data["K2"] = []byte("V2")
   data["K3"] = []byte("V3")
   data["K4"] = []byte("V4")
   my := NewDefaultIterator(data)
   if my.length != 3 {
      t.Fatal()
   }
   for iter.Next() {
      fmt.Printf("%s : %s\n", my.Key(), string(my.Value()))
   }
}

测试结果

DB测试
测试方法
func Test_leveldb(t *testing.T) {
   db, err := New("")
   check(err)
   err = db.Put([]byte("k1"), []byte("v1"))
   check(err)
   err = db.Put([]byte("k4"), []byte("v4"))
   check(err)
   err = db.Put([]byte("k2"), []byte("v2"))
   check(err)
   err = db.Put([]byte("k1"), []byte("v1"))
   check(err)
   err = db.Put([]byte("k8"), []byte("v8"))
   check(err)
   v, err := db.Get([]byte("k8"))
   fmt.Printf("%s\n\n", v)

   if !bytes.Equal(v, []byte("v8")) {
      t.Fatal()
   }
   v, err = db.Get([]byte("k1"))
   if !bytes.Equal(v, []byte("v1")) {
      t.Fatal()
   }
   //err = db.Del([]byte("k1"))
   //check(err)
   iter := db.Iterator()
   for iter.Next() {
      fmt.Printf("%s - %s \n", string(iter.Key()), string(iter.Value()))
   }
}

func check(err error) {
   if err != nil {
      panic(err)
   }
}
测试结果
PUT和GET测试
DEL测试
GET不存在元素时测试

实验第3部分-局域网广播和有效区块链

实验内容

1.可以在网络端POST指令访问,添加新的比特币交易区块。

2.可以在网络端GET指令访问,查看所有已经添加的交易信息。

实验原理

1.实验中使用的开源包:

http://github.com/davecgh/go-spew/spew;

http://github.com/gorilla/mux;

http://github.com/joho/godotenv;

开源包功能:编写web程序的软件包,在控制台格式化输出结果,配置编写.env文件

实验方法

声明区块,区块链等基本(和前两部分一样)

注:基本代码和前两部分相同,但在下面处存在区别

var Blockchain []Block
var mutex = &sync.Mutex{}

上锁,并且有数组进行存储,同时在有效判别函数中,会抓取所有节点,寻找最长的链,来进行写入。但是在本次试验中因为我在本地并没有其他人的加入,所以我就用简单的python语言大概简述。

def resolve(self) ->bool:
  fujin=self.nodes
  new_chain = None
 	max_length = len(self.chain)
for node in fujin:
   get new_length
    if new_legth>max_length.  and ishashvaild(self)
    	max_length=length
      new_chain=chain
if new_chain:
    self.chain = new_chain
    return true
return false
互联网区块链方法
HTTP启动
//http启动
func run() error {
   mux := makeMuxRouter()
   httpAddr := os.Getenv("ADDR")
   log.Println("listening on", os.Getenv("ADDR"))
   s := &http.Server{
      Addr:           ":" + httpAddr,
      Handler:        mux,
      ReadTimeout:    10 * time.Second,
      WriteTimeout:   10 * time.Second,
      MaxHeaderBytes: 1 << 20,
   }
   if err := s.ListenAndServe(); err != nil {
      return err
   }
   return nil
}
对区块链数据的操作的初始化
func makeMuxRouter() http.Handler {
   muxRouter := mux.NewRouter()
   muxRouter.HandleFunc("/", handgetblockhain).Methods("GET")
   muxRouter.HandleFunc("/", handerwriteblock).Methods("POST")
   return muxRouter
}
查看互联网请求中的内容
func handgetblockhain(w http.ResponseWriter, r *http.Request) {
   bytes, err := json.MarshalIndent(Blockchain, "", "\t")
   if err != nil {
      http.Error(w, err.Error(), http.StatusInternalServerError)
      return
   }
   io.WriteString(w, string(bytes))
}
验证当前区块是否加入
func isblockivaild(newBlock, oldblock Block) bool {
   if oldblock.Index+1 != newBlock.Index {
      return false
   }
   if oldblock.HashCode != newBlock.PreHash {
      return false
   }
   if calculationHash(newBlock) != newBlock.HashCode {
      return false
   }
   return true
}

​ 论证是否是旧的区块+1,以及哈希值是否对应

POST,挖到一个区块后进行广播

//声明一个post类型的数据类型
type Message struct {
   BPM int
}

func handerwriteblock(writer http.ResponseWriter, request *http.Request) {
   writer.Header().Set("Content-Type", "application/json")
   var message Message
   decoder := json.NewDecoder(request.Body)
   if err := decoder.Decode(&message); err != nil {
      respondWithJson(writer, request, http.StatusNotFound, request.Body)
      return
   }
   defer request.Body.Close()

   //生成区块
   mutex.Lock()
   newblock := generateBlock(Blockchain[len(Blockchain)-1], message.BPM)
   mutex.Unlock()

   //判断是否合法
   if isblockivaild(newblock, Blockchain[len(Blockchain)-1]) {
      Blockchain = append(Blockchain, newblock)
      spew.Dump(Blockchain)
   }
   respondWithJson(writer, request, http.StatusCreated, newblock)
}

     func respondWithJson(writer http.ResponseWriter, request *http.Request, code int, inter interface{}) {
   writer.Header().Set("Content-Type", "application/json")
   //格式化输出JSON
   response, err := json.MarshalIndent(inter, "", "\t")
   if err != nil {
      writer.WriteHeader(http.StatusInternalServerError)
      writer.Write([]byte("HTTP 500:Serve Error"))
      return
   }
   writer.WriteHeader(code)
   writer.Write(response)
}

实验结果

测试主方法
func main() {
   err := godotenv.Load()
   if err != nil {
      log.Fatal(err)
   }
   go func() {
      genesisblock := Block{}
      genesisblock = Block{
         0, time.Now().String(), 0, calculationHash(genesisblock),
         "", differculty, 0}
      mutex.Lock()
      Blockchain = append(Blockchain, genesisblock)
      mutex.Unlock()
      spew.Dump(genesisblock)
   }()
   log.Fatal(run())
}
.env配置文件
ADDR= 8080
Curl测试命令事例
curl -H "Content-Type: application/json" -X POST -d"{\"BPM\":10}"“http://localhost:8080”

curl http://localhost:8080
实验结果

发送指令

播在局域网中

发送被希望记录的交易信息

挖到矿后将其加入了区块链

代码扩展部分

我个人是还想使用bee-go metaMast做一个使用区块链交易界面的,但是还是因为个人的问题,代码在golang的前端部分已经完善,但在remix智能公约部分陷进去,出不来了。所以我简要的附上几张图,工程文件里的view会附上我的html css文件。


首页

查询

智能合约

beego

实验心得

在长达两个月的时间,我从GO语言的小白到可以逐步完善自己的想法,从只知道区块链可以炒股到逐渐对其中的原理有了更深的理解,尤其是在广播时候的代码,因为比特币公开的源代码是用c++编写的,所以用go浮现的时候就有了颇多困难。尤其是开发智能合约到最后还要学Solidity语言。

因为之前一直都在TI杯比赛中接触代码,但是比赛中大多数都是基于嵌入式环境的硬件系统,无论是ARDUINO,STM32还是ESP82266的开发虽然在调试上但是其中的编程语言都是基于C的,GO和css则完全是面向对象的,尤其是Golang的go get,每次下载一个包都是困难重重,无法cloning竟然还和内网有关。

但是面向对象的有趣在于可以大大减少程序员的调试难度,思路也更有逻辑性。暑假里 我一定要彻底完成我自己的以太坊彩票站。

也感谢沈老师和蔺老师在课堂上对于网络安全的讲解,让我认识到安全学科已经成为了新的行业热门,也了解到网络安全对于社会生产的重要性。

说明:

本实验中的代码均已开源在github;本说明文档首发于个人博客文章来源地址https://www.toymoban.com/news/detail-808998.html

到了这里,关于基于共识算法和区块链模拟实现超级账本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 超级账本与区块链应用场景

    去中心化应用的新需求 区块链技术在行业应用中的条件 行业应用的用户是有一定的范围的,一般限制在一个市场或某一个企业内部。这就要求应用具有 身份认证和许可授权 的功能。其次,企业往往需要数据在传输过程中不会被窃取。要求应用具有 保护交易信息传输 的设计

    2024年02月15日
    浏览(49)
  • 部署超级账本fabric区块可视化浏览器

    文件存放路径 在根目录中构建这样的目录结构 编写org1ProdNetworkConnection.json文件,注意自己的端口号和文件路径配置 编写 config.json 配置文件 编写 docker-compose-explorer.yaml 文件 启动 Hyperledger Explorer: 在 Hyperledger Explorer中启动 清理(不删除持久性数据): 彻底清理: 启动后访问

    2024年02月12日
    浏览(55)
  • 超级账本基金会执行董事Daniela Barbosa:开源区块链已成主流

    开源发展如今已是遍地开花,在区块链行业也起到了至关重要的作用。 2022 年 7 月 21 日,由中国开源软件推进联盟主办,赛迪传媒、《软件和集成电路》杂志社联合承办,CSDN 独家直播的“第十七届开源中国开源世界高峰论坛”上,基于开源的超级账本(区块链)基金会执行

    2024年01月17日
    浏览(39)
  • hyperledger fabric explorer 超级账本区块链浏览器搭建-docker的方式

    hyperledger fabric explorer 超级账本区块链浏览器搭建-使用docker的方式快速搭建一个超级账本区块链浏览器 区块链浏览器可以让用户更加直观地查看当前超级账本网络的情况,来观察整个区块链上的块数,节点数,通道,链码等; 官方推荐的搭建区块链浏览器有两种方法,一种是

    2023年04月08日
    浏览(40)
  • GO语言实现区块链POW共识算法- -区块定义与数据串行化

    持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情 区块链分布式系统,共识算法系统是它的灵魂,pow也就是工作量证明,证明你做过一定量的工作。(按劳分配,拼算力) 在我们实现pow之前,需要对区块链的基本架子先搭起来(相当

    2024年02月08日
    浏览(40)
  • Fabric 超级账本学习【5】Fabric2.4网络环境下——搭建Hyperledger Fabric区块链浏览器

    博主最近在搭建Hyperledger Fabric区块链浏览器过程中也学习了很多博主的搭建流程,踩了很多雷,踩了很多 坑,现将成功搭建好的Hyperledger Fabric区块链浏览器详细流程分享如下,帮助大家避雷闭坑 Hyperledger Explorer 是一个简单,强大,易于使用,维护良好的开源实用程序,可浏

    2023年04月23日
    浏览(51)
  • 竞赛python区块链实现 - proof of work工作量证明共识算法

    🔥 优质竞赛项目系列,今天要分享的是 python区块链实现 - proof of work工作量证明共识算法 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 学长以比特币的结构向大家详解区块链的组成部分 previous hash

    2024年02月05日
    浏览(52)
  • 【毕设教程】python区块链实现 - proof of work工作量证明共识算法

    Hi,大家好,这里是丹成学长,今天向同学们介绍如何构建一个区块链系统作为毕设,区块链的原理 🧿 选题指导, 项目分享: https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md 学长以比特币的结构向大家详解区块链的组成部分 previous hash(前

    2024年01月21日
    浏览(46)
  • 挑战杯 python区块链实现 - proof of work工作量证明共识算法

    🔥 优质竞赛项目系列,今天要分享的是 python区块链实现 - proof of work工作量证明共识算法 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 学长以比特币的结构向大家详解区块链的组成部分 previous hash

    2024年02月21日
    浏览(61)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包