go语言编写小型的区块链示例_go区块链链代码实例库-程序员宅基地

技术标签: 区块链  

本文介绍了:
如何创建自己的区块链
理解hash函数是如何保证区块链的完整性的
如何创建并添加新的块
多个节点如何竞争生成块
关于区块链的基本知识

但是,对于比如工作量证明算法(PoW)以及权益证明算法(PoS)这类的共识算法文章中将不会涉及。同时为了让你更清楚得查看区块链以及块的添加,我们将网络交互的过程简化了。

package main

import (
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "github.com/davecgh/go-spew/spew"
    "github.com/gorilla/mux"
    "github.com/joho/godotenv"
    "io"
    "log"
    "net/http"
    "os"
    "time"
)

//区块链块的结构体
type Block struct {
    //Index 是这个块在整个链中的位置
    Index int
    //Timestamp 块生成时的时间戳
    Timestamp string
    //每分钟心跳数,也就是心率
    BPM int
    //通过 SHA256 算法生成的散列值
    Hash string
    //代表前一个块的 SHA256 散列值
    PrevHash string
}

//表示整个链
var Blockchain []Block

//计算数据的sha256散列值
func calculateHash(block Block) string {
    record := string(block.Index) + block.Timestamp + string(block.BPM) + block.PrevHash
    h := sha256.New()
    h.Write([]byte(record))
    hashed := h.Sum(nil)
    return hex.EncodeToString(hashed)
}

//生成块
func generateBlock(oldBlock Block, BPM int) (Block, error) {
    var newBlock Block

    t := time.Now()
    newBlock.Index = oldBlock.Index + 1
    newBlock.Timestamp = t.String()
    newBlock.BPM = BPM
    newBlock.PrevHash = oldBlock.Hash
    newBlock.Hash = calculateHash(newBlock)

    return newBlock, nil
}

//校验块
func isBlockValid(newBlock, oldBlock Block) bool {
    if oldBlock.Index+1 != newBlock.Index {
        return false
    }

    if oldBlock.Hash != newBlock.PrevHash {
        return false
    }

    if calculateHash(newBlock) != newBlock.Hash {
        return false
    }
    return true
}

//将过期的链更新为最新的链
func replaceChain(newBlocks []Block) {
    if len(newBlocks) > len(Blockchain) {
        Blockchain = newBlocks
    }
}

//初始化web服务
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("/", handleGetBlockchain).Methods("GET")
    muxRouter.HandleFunc("/", handleWriteBlock).Methods("POST")
    return muxRouter
}

//get请求的handler
func handleGetBlockchain(w http.ResponseWriter, r *http.Request) {
    bytes, err := json.MarshalIndent(Blockchain, "", " ")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    io.WriteString(w, string(bytes))
}

//post请求的payload
type Message struct {
    BPM int
}

//post请求的handler
func handleWriteBlock(w http.ResponseWriter, r *http.Request) {
    var m Message

    decoder := json.NewDecoder(r.Body)
    if err := decoder.Decode(&m); err != nil {
        respondWidthJSON(w, r, http.StatusBadRequest, r.Body)
        return
    }
    defer r.Body.Close()

    newBlock, err := generateBlock(Blockchain[len(Blockchain)-1], m.BPM)
    if err != nil {
        respondWidthJSON(w, r, http.StatusCreated, newBlock)
    }

    //spew.Dump(isBlockValid(newBlock, Blockchain[len(Blockchain)-1]))
    //respondWidthJSON(w, r, http.StatusCreated, isBlockValid(newBlock, Blockchain[len(Blockchain)-1]))


    if isBlockValid(newBlock, Blockchain[len(Blockchain)-1]) {
        newBlockchain := append(Blockchain, newBlock)
        replaceChain(newBlockchain)
        spew.Dump(Blockchain)
    }

    respondWidthJSON(w, r, http.StatusCreated, newBlock)
}

//返回客户端响应
func respondWidthJSON(w http.ResponseWriter, r *http.Request, code int, payload interface{}) {
    response, err := json.MarshalIndent(payload, "", "  ")
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        w.Write([]byte("HTTP 500: Internal Server Error"))
    }
    w.WriteHeader(code)
    w.Write(response)
}

func main() {
    err := godotenv.Load()
    if err != nil {
        log.Fatal(err)
    }

    //初始化区块链
    go func() {
        t := time.Now()
        genesisBlock := Block{0, t.String(), 0, "", ""}
        spew.Dump(genesisBlock)
        Blockchain = append(Blockchain, genesisBlock)
    }()
    log.Fatal(run())
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/b1303110335/article/details/79243510

智能推荐

大数据处理利器:Hadoop具有五大优势-程序员宅基地

文章浏览阅读773次。高可扩展性 Hadoop是一个高度可扩展的存储平台,因为他可以存储和分发横跨数百个并行操作的廉价的服务器数据集群。不同于传统的关系型数据库系统不能扩展到处理大量的数据,Hadoop是能给企业提供涉及成百上千TB的数据节点上运行的应用程序。 成本效益 Hadoop还为企业用户提供了极具成本..._hadoop的主要优势包括实时计算处理

ArcGIS修改矢量边界(土地利用图图斑)_arcgis pro 基于底图修改矢量边界-程序员宅基地

文章浏览阅读1.6w次,点赞7次,收藏53次。前言:本文就ArcGIS软件中的土地利用矢量图修改、更新方式进行介绍(其他矢量边界修改方式也可作为参考)。在处理土地利用图的过程中不免遇到矢量边界存在一些偏移,或者边界所围区域错分为一些类别。单块图斑还可以直接处理该图斑,但是进行按类融合后,对于局部的区域就较难编辑了(会影响到整个类的区域)。而土地利用矢量图又存在这拓扑(即这些图斑、或者融合后的地类是无缝隙、无重叠,这样才可以进行面积的计算、..._arcgis pro 基于底图修改矢量边界

谷歌Android 2.2支持Flash的十大后果(转)_手机版谷歌支持flash-程序员宅基地

文章浏览阅读387次。感谢瑞士留学的投递新闻来源:腾讯科技据国外媒体报道,由于Android 2.2操作系统的缘故,Adobe公司的Flash平台正在越来越多的Android手机上大行其道。对于那些批评苹果不在其iOS系统上支持Flash的人来说,Flash出现在Android 2.2是一件好事。Flash的支持者表示,Flash可以显著改善用户在智能手机上的浏览体验。 然而,并不是所有人都这么看。一些人认为,Flash只会带来安全漏洞,弊大于利。虽然这些人知道目前大部分的视频和游_手机版谷歌支持flash

简单几步,让微信小程序变身 H5 网页_小程序转换成网页 在线-程序员宅基地

文章浏览阅读4.9k次。云开发(Tencent Cloud Base,TCB)是腾讯云为移动开发者提供的一站式后端云服务,它帮助开发者统一构建和管理资源,免去了移动应用开发过程中繁琐的服务器搭建及运维、域名注册及备案、数据接口实现等繁琐流程,让开发者可以专注于业务逻辑的实现,而无需理解后端逻辑及服务器运维知识,开发门槛更低,效率更高。官方教程:https://tencentcloudbase.github.io/We..._小程序转换成网页 在线

TMainMenu 类 - 手动建立菜单 : 指定快捷键《转》-程序员宅基地

文章浏览阅读87次。菜单项通过 ShortCut 属性来设定快捷键, ShortCut 是 TShortcut 类型的; TShortcut 是一个子界: 0..65535ShortCut 的所有可选值请参加列表:http://www.cnblogs.com/LceMeaning/archive/2013/01/09/2853071.html================================..._tmenuitem.shortcut

slidebox使用教程 设定焦点数量-程序员宅基地

文章浏览阅读1.1k次。如下图所示的class="num" 下的a标签有几个就有几个焦点,对应下面的<li>标签的图片,js设定图片时间<div class="hot left" id="hot"> <div class="num"> <a class="curr"></a> <a></a> <a>&l..._slidebox使用教程

随便推点

2D图形_2d 图形gift-程序员宅基地

文章浏览阅读683次。package GUI;import java.awt.*;import javax.swing.*;import java.awt.geom.*; //提供用于在与二维几何形状相关的对象上定义和执行操作的 Java 2D 类。/** * * @author Zhu Zhengyan */public class DrawTest { public _2d 图形gift

【2017年蓝桥杯Java-B组省赛题解】_java计算a=1>2?3:4>5?6:7>8-程序员宅基地

文章浏览阅读1w次。2017Java-B组省赛一、购物单(计算器)二、纸牌三角形(模拟、数学思维去重)三、承压计算(杨辉三角、数学思维)四、魔方状态(做不来)五、六、程序填空题七、日期问题(非常细节的模拟、Calendar类)八、包子凑数(最大公约数)九、分巧克力(模拟、二分)※十、k倍区间(前缀和)一、购物单(计算器)标题: 购物单 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物。老板忙的时候经常让小明帮忙到商场代为购物。小明很厌烦,但又不好推辞。 这不,XX大促销又来了!老板夫人开出了长长的购物_java计算a=1>2?3:4>5?6:7>8

数据标准化之均值方差标准化(原理+Python代码)-程序员宅基地

文章浏览阅读1.2w次,点赞4次,收藏29次。一、原理介绍常用的数据标准化方法有最大最小归一化、均值方差标准化、小数定标法、定量特征二值化等。其中,均值方差标准化是一种将数据转化为标准正态分布的标准化方法。在回归模型中,服从正态分布的自变量和因变量往往对应着较好的回归预测效果。均值方差标准化的计算公式为: x′=x−μσ x'=\frac{x-\mu }{\sigma } x′=σx−μ​公式中,x表示单个数据的取值,μ\muμ表示对应列的均值,σ\sigmaσ表示对应列的方差二、代码实现#加载模块from sklearn.preproces_均值方差标准化

iOS-UIDatePicker以及UIPickerView--日期选择和地址选择实现(省市县三级联动)-程序员宅基地

文章浏览阅读381次。金陵子弟来相送,欲行不行各尽觞!<地幔岩>简单说几句:UIDatePicker:1: 直接继承 UIControl (那么就可以有 addTarget ........的方法使用 可以添加相应的触发事件)2: 可以用来选择作为时间选择器, 通过 datePickerMode 选择样式效果3: 使用比较多的属性可以点进去看下一般就是 date(当前..._ios picker view 滑动的时候日期

使用JAVA实现TCP数据转发-程序员宅基地

文章浏览阅读3.3k次。2019独角兽企业重金招聘Python工程师标准>>> ..._java实现tcp转发nt

轨迹分析—Matlab计算均方位移_matlab知道运动方程求位移-程序员宅基地

文章浏览阅读4k次,点赞2次,收藏13次。热力学性质的不均匀性导致的热力学过程叫做输运过程,相应的现象叫做输运现象。由于粒子数密度的不均匀性导致粒子的输运(扩散现象).由于粒子数密度的不均匀性导致粒子的输运(扩散现象).均方根位移是随时间测量的,以确定粒子是否仅由于扩散而扩散。均方根位移是随时间测量的,以确定粒子是否仅由于扩散而扩散。那么如何根据轨迹文件计算MSD呢?那么如何根据轨迹文件计算MSD呢?_matlab知道运动方程求位移

推荐文章

热门文章

相关标签