首页 联络聊天正文

没用200行编码写的区块链技术源码

webmaster5u 联络聊天 2020-08-09 17:56:56 55 5 | 来源:ZOL软件下载 区块

下列文章内容来自飞雪绝情 ,创作者飞雪绝情


github上有一个Repo,是一个应用Go语言(golang),不上200行编码写的区块链技术源码,精确的说是174行。著作人起了个姓名是 Code your own blockchain in less than 200 lines of Go! 并且创作者也因此写了一篇文章。https://medium.com/@mycoralhealth/code-your-own-blockchain-in-less-than-200-lines-of-go-e296286bcffc


本文是一个大约的构思和编码的完成,自然也有许多编码的逻辑性沒有涉及到,因此 我也对于这不上200行的编码开展一个剖析,包括原文章内容里沒有牵涉到的知识要点,对Go语言,区块链技术都是有一个更加深入的了解。


全部的源码都在这儿:https://github.com/nosequeldeebee/blockchain-tutorial/blob/master/main.go


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

在源码的开始,是创作者引进的一些包,有规范的,也是有第三方的。像sha256,hex这种规范包是以便sha-256编号用的,别的也有起动http服务项目,复印系统日志的log,高并发操纵的sync,时间格式的time。


第三方包有三个,在其中2个我还详解过,坚信大伙儿不容易生疏。


go-spew是一个自变量建筑结构的调节神器,能够 复印出自变量建筑结构相匹配的数据信息和构造,调节十分便捷


gorilla/mux是一个web路由器服务项目,能够 非常简单的帮大家搭建web服务。


但是现阶段用gin的比较多,也强烈推荐应用gin https://github.com/gin-gonic/gin。


godotenv是一个载入配备文章内容的库,能够 使我们载入.env文件格式的环境变量,例如从环境变量里载入IP、PORT等。但是现阶段环境变量還是强烈推荐YAML和TOML,相匹配的第三方库是:


gopkg.in/yaml.v21https://github.com/BurntSushi/toml


即然要写一个区块链技术,那麼毫无疑问的有一个区块链的实体线,大家根据golang的struct来完成。


// Block represents each 'item' in the blockchaintype Block struct {    Index     int    Timestamp string    BPM       int    Hash      string    PrevHash  string}

Block里包括几个字段:


  1. Index 便是Block的顺序索引

  2. Timestamp是转化成Block的时间格式

  3. BPM,创作者说意味着心跳,每分钟心跳数

  4. Hash是根据sha256转化成的散列值,对全部Block数据信息的Hash

  5. PrevHash 上一个Block的Hash,那样区块链才可以连在一起组成区块链技术

拥有区块链Block了,那麼区块链技术就十分找邦企了。


// Blockchain is a series of validated Blocksvar Blockchain []Block

便是那么简易,一个Block数字能量数组便是一个区块链技术。区块链技术的组成关键所在Hash和PrevHash,根据她们一个个串连起來,便是一串Block,也就是区块链技术。由于彼此之间根据Hash和PrevHash开展关系,因此 全部链难以被伪造,链越长被伪造的成本费越大,由于要把全部链所有改正才可以进行伪造的目地,那样的话,别的连接点认证此次伪造肯定是不可以根据的。


即然关键环节取决于Hash,因此 我们要先算出去一个Block的数据信息的Hash,也就是对Block里的字段名开展Hash,测算出一个唯一的Hash值。


// SHA256 hasingfunc calculateHash(block Block) string {    record := strconv.Itoa(block.Index)   block.Timestamp   strconv.Itoa(block.BPM)   block.PrevHash&nb sp;   h := sha256.New()    h.Write([]byte(record))    hashed := h.Sum(nil)    return hex.EncodeToString(hashed)}

sha256是golang内嵌的sha256的散列标准库,能够 使我们非常容易的转化成相匹配数据信息的散列值。从源码看,是把Block的全部字段名开展字符串拼接,随后根据sha256开展散列,散列的数据信息再根据hex.EncodeToString变换为16进制的字符串数组,那样就获得了大家普遍的sha256散列值,相近那样的字符串数组8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc7c92。


Block的散列值被大家推算出来了,Block的Hash和PrevHash这两个字段名拿下了,那麼大家如今就可以转化成一个区块链了,由于别的几个字段全是能够 自动生成的。


// create a new block using previous block's hashfunc generateBlock(oldBlock Block, BPM int) Block {    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}

由于区块链技术是次序相接的,因此 我们在转化成一个新的区块链的情况下,务必了解上一个区块链,也就是源码里的oldBlock。此外一个主要参数BPM便是大家必须在区块链里储存的数据信息了,这儿创作者演试的事例是心跳,我们可以换为别的业务流程中要想的数据信息。


Index是上一个区块链的Index 1,维持次序;Timestamp根据time.Now()能够 获得;Hash根据calculateHash方式推算出来。那样大家就转化成了一个新的区块链。


在这儿创作者并沒有应用POW(劳动量证实)这类优化算法来转化成区块链,只是沒有一切标准的,这儿主要是以便仿真模拟区块链的转化成,演试便捷。


区块链能够 转化成了,可是转化成的区块链是不是可靠,大家还得对他开展校检,不可以随意转化成一个区块链。在BTC(BitCoin)中校检非常复杂,这儿创作者选用了简易仿真模拟的方法。


// make sure block is valid by checking index, and comparing the hash of the previous blockfunc 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}

简易的比照Index,Hash是不是恰当的,而且再次测算了一遍Hash,避免被伪造。


来到这儿,关于区块链的编码早已所有完成了,剩余的便是把区块链技术的转化成、查询等包裝成一个Web服务,能够 根据API、电脑浏览器浏览查询。由于创作者这儿沒有完成P2P网络,因此 选用的是WEB服务项目的方法。


// create handlersfunc makeMuxRouter() http.Handler {    muxRouter := mux.NewRouter()    muxRouter.HandleFunc("/", handleGetBlockchain).Methods("GET")    muxRouter.HandleFunc("/", handleWriteBlock).Methods("POST")    return muxRouter}

根据mux界定了2个Handler,URL全是/,可是相匹配的Method是不一样的。


GET方式根据handleGetBlockchain涵数完成,用以获得区块链技术的信息内容。


func handleGetBlockchain(w http.ResponseWriter, r *http.Request) {    bytes, err := json.MarshalIndent(Blockchain, "", "  ")   &n bsp;if err != nil {        http.Error(w, err.Error(), http.StatusInternalServerError)        return    }    io.WriteString(w, string(bytes))}

Blockchain是一个[]Block,handleGetBlockchain涵数的功效是把Blockchain恢复出厂设置为JSON字符串数组,随后显示信息出去。io.WriteString是一个非常好用的涵数,能够 往Writer里载入字符串数组。大量参照 Go语言实战演练手记(十九)| Go Writer 和 Reader


'POST'方式根据handleWriteBlock涵数完成,用以仿真模拟区块链的转化成。


func handleWriteBlock(w http.ResponseWriter, r *http.Request) {    w.Header().Set("Content-Type", "application/json")    //应用了一个Mesage建筑结构,更便捷的储存BPM    var msg Message    //接受恳求的数据信息,相近{"BPM":60}那样的文件格式    decoder := json.NewDecoder(r.Body)    if err := decoder.Decode(&msg); err != nil {        respondWithJSON(w, r, http.StatusBadRequest, r.Body)        return    }    defer r.Body.Close()    //操纵高并发,转化成区块链技术,而且校检    mutex.Lock()    prevBlock := Blockchain[len(Blockchain)-1]    newBlock := generateBlock(prevBlock, msg.BPM)    //校检区块链技术    if isBlockValid(newBlock, prevBlock) {        Blockchain = append(Blockchain, newBlock)        spew.Dump(Blockchain)    }    mutex.Unlock()    //回到新的区块链信息内容    respondWithJSON(w, r, http.StatusCreated, newBlock)}

之上编码我开展了注解,有利于了解。主要是根据POST推送一个{"BPM":60}文件格式的BODY来加上区块链,假如文件格式恰当,那麼就转化成区块链开展校检,达标了就添加到区块链里;假如文件格式不对,那麼回到错误报告。


用以操纵高并发的锁能够 参照Go语言实战演练手记(十七)| Go 读写锁


这一方式里有一个Message建筑结构,主要是以便有利于实际操作便捷。


// Message takes incoming JSON payload for writing heart ratetype Message struct {    BPM int}

回到的JSON信息内容,也被提取变成一个涵数respondWithJSON,有利于公共。


func respondWithJSON(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"))        return    }    w.WriteHeader(code)    w.Write(response)}

好啦,快完成了,之上Web的Handler早已好啦,如今我们要起动大家的Web服务了。


// web serverfunc run() error {    mux := makeMuxRouter()    //从环境变量里载入监视的端口号    httpPort := os.Getenv("PORT")    log.P rintln("HTTP Server Listening on port :", httpPort)    s := &http.Server{        Addr:           ":"   httpPort,        Handler:        mux,        ReadTimeout:    10 * time.Second,        WriteTimeout:   10 * time.Second,        MaxHeaderBytes: 1 << 20,    }    if err := s.ListenAndServe(); err != nil {        return err    }    return nil}

和原生态的http.Server基础一样,应当比较好了解。mux实际上也是一个Handler,这就是全部Handler解决链。如今大家就差一个main主函数来起动大家全部程序流程了。


//操纵高并发的锁var mutex = &sync.Mutex{}func main() {    //载入env环境变量    err := godotenv.Load()    if err != nil {        log.Fatal(err)    }    //打开一个goroutine转化成一个创世区块链    go func() {        t := time.Now()        genesisBlock := Block{}        genesisBlock = Block{0, t.String(), 0, calculateHash(genesisBlock), ""}        spew.Dump(genesisBlock)        mutex.Lock()        Blockchain = append(Blockchain, genesisBlock)        mutex.Unlock()    }()    log.Fatal(run())}

全部main涵数并不太繁杂,关键便是载入env环境变量,打开一个go协程转化成一个创世区块链而且加上到区块链技术的第一个部位,随后便是根据run涵数起动Web服务。


一个区块链技术都是有一个创世区块链,也就是第一个区块链。拥有第一个区块链大家才可以加上第二个,第三个,第N个区块链。创世区块链由于是第一个区块链,因此 它是沒有PrevHash的。


总算能够 运作了,假定大家设定的PORT是8080,如今大家根据go run main.go起动这一简单的区块链技术程序流程,就可以见到控制面板輸出的创世区块链信息内容。随后大家根据打开浏览器http://localhost:8080还可以见到这一区块链技术的信息内容,里边只有一个创世区块链。


假如我们要增加一个区块链,根据curl或是postman,向http://localhost:8080 推送body文件格式为{"BPM":60}的POST的信息内容就可以。随后在根据电脑浏览器浏览http://localhost:8080查询区块链技术信息内容,认证是不是早已加上取得成功。


到这儿,全部源码的剖析早已完后,大家看下这一简单的区块链技术牵涉到是多少专业知识:


  1. sha256散列

  2. 字节数到16进制变换

  3. 高并发同步锁

  4. Web服务

  5. 环境变量

  6. 后向式链表

  7. 建筑结构

  8. JSON

  9. ……

这些,上边的许多专业知识,我已经在文章内容中解读或是根据之前些的文章内容表明,大伙儿能够 看一下,详尽掌握。




下载地址:
http://www.webmaster5u.com/down/99811445.zip
解压密码:9981144599811445
版权声明

旭日站长免费提供编程教程,网页特效,手机教程,游戏攻略和IT资讯等内容,打造内容丰富的站长学习!

本文链接:http://www.webmaster5u.com/jtdh/551.html

评论

精彩评论