博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【go共识算法】-POW
阅读量:6878 次
发布时间:2019-06-26

本文共 5394 字,大约阅读时间需要 17 分钟。

pow介绍

工作量证明(PoW,Proof of Work)。

通过计算一个数值(nonce ),使得拼揍上交易数据后内容的 Hash 值满足规定的上限。在节点成功找到满足的Hash值之后,会马上对全网进行广播打包区块,网络的节点收到广播打包区块,会立刻对其进行验证。

如果验证通过,则表明已经有节点成功解迷,自己就不再竞争当前区块打包,而是选择接受这个区块,记录到自己的账本中,然后进行下一个区块的竞争猜谜。 网络中只有最快解谜的区块,才会添加的账本中,其他的节点进行复制,这样就保证了整个账本的唯一性。

假如节点有任何的作弊行为,都会导致网络的节点验证不通过,直接丢弃其打包的区块,这个区块就无法记录到总账本中,作弊的节点耗费的成本就白费了,因此在巨大的挖矿成本下,也使得矿工自觉自愿的遵守比特币系统的共识协议,也就确保了整个系统的安全。

pow优缺点

  • 优点:完全去中心化,节点自由进出;
  • 缺点:目前bitcoin已经吸引全球大部分的算力,其它再用Pow共识机制的区块链应用很难获得相同的算力来保障自身的安全;挖矿造成大量的资源浪费;共识达成的周期较长,不适合商业应用

go实现pow共识算法

依赖软件

  • spew 在控制台中格式化输出相应的结果。
    $ go get github.com/davecgh/go-spew/spew
  • gorilla/mux 是编写web处理程序的流行软件包。
    $ go get github.com/gorilla/mux
  • godotenv 可以从我们项目的根目录的 .env 文件中读取数据。
    $ go get github.com/joho/godotenv

.env

ADDR=8080

main.go

package mainimport (        "crypto/sha256"        "encoding/hex"        "encoding/json"        "fmt"        "io"        "log"        "net/http"        "os"        "strconv"        "strings"        "sync"        "time"        "github.com/davecgh/go-spew/spew"        "github.com/gorilla/mux"        "github.com/joho/godotenv")const difficulty = 1type Block struct {        Index      int        Timestamp  string        BPM        int        Hash       string        PrevHash   string        Difficulty int        Nonce      string}var Blockchain []Blocktype Message struct {        BPM int}var mutex = &sync.Mutex{}func 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.Difficulty = difficulty    for i := 0; ; i++ {            hex := fmt.Sprintf("%x", i)            newBlock.Nonce = hex            if !isHashValid(calculateHash(newBlock), newBlock.Difficulty) {                    fmt.Println(calculateHash(newBlock), " do more work!")                    time.Sleep(time.Second)                    continue            } else {                    fmt.Println(calculateHash(newBlock), " work done!")                    newBlock.Hash = calculateHash(newBlock)                    break            }    }    return newBlock}func isHashValid(hash string, difficulty int) bool {    //复制 difficulty 个0,并返回新字符串,当 difficulty 为2 ,则 prefix 为 00    prefix := strings.Repeat("0", difficulty)    // HasPrefix判断字符串 hash 是否包含前缀 prefix    return strings.HasPrefix(hash, prefix)}func calculateHash(block Block) string {    record := strconv.Itoa(block.Index) + block.Timestamp + strconv.Itoa(block.BPM) + block.PrevHash + block.Nonce    h := sha256.New()    h.Write([]byte(record))    hashed := h.Sum(nil)    return hex.EncodeToString(hashed)}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 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}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))}func handleWriteBlock(w http.ResponseWriter, r *http.Request) {    w.Header().Set("Content-Type", "application/json")    var m Message    decoder := json.NewDecoder(r.Body)    if err := decoder.Decode(&m); err != nil {            respondWithJSON(w, r, http.StatusBadRequest, r.Body)            return    }       defer r.Body.Close()    //ensure atomicity when creating new block    mutex.Lock()    newBlock := generateBlock(Blockchain[len(Blockchain)-1], m.BPM)    mutex.Unlock()    if isBlockValid(newBlock, Blockchain[len(Blockchain)-1]) {            Blockchain = append(Blockchain, newBlock)            spew.Dump(Blockchain)    }       respondWithJSON(w, r, http.StatusCreated, newBlock)}func respondWithJSON(w http.ResponseWriter, r *http.Request, code int, payload interface{}) {    w.Header().Set("Content-Type", "application/json")    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)}func main() {    err := godotenv.Load()    if err != nil {            log.Fatal(err)    }       go func() {            t := time.Now()            genesisBlock := Block{}            genesisBlock = Block{0, t.String(), 0, calculateHash(genesisBlock), "", difficulty, ""}             spew.Dump(genesisBlock)            mutex.Lock()            Blockchain = append(Blockchain, genesisBlock)            mutex.Unlock()    }()     log.Fatal(run())}

转载地址:http://fcgfl.baihongyu.com/

你可能感兴趣的文章
CSS实现水平垂直居中的1010种方式(史上最全)
查看>>
BCH曼谷矿工会议的积极方面:社区彼此更加了解
查看>>
Android之观察者模式
查看>>
微信公众号支付开发全过程(Java 版)
查看>>
SwiftLint代码规范属性说明(二)
查看>>
本周半价(12.16-12.22)电子书
查看>>
是时候深入了解Linux的系统结构了
查看>>
4月第3周业务风控关注 | 文化部再次审查直播和游戏产品,已下架4939款直播应用...
查看>>
源码探探之startActivity(二)
查看>>
深入了解Flutter的isolate(1) ---- 事件循环(event loop)及代码运行顺序
查看>>
startService() 过程
查看>>
WebSocket 协议 1~4 节
查看>>
Android-WItemTouchHelperPlus几行代码搞定仿QQ侧滑
查看>>
Glide 知识梳理(5) 自定义GlideModule
查看>>
聊聊eureka的delta配置
查看>>
Masonry 源码解读(下)
查看>>
Swift如何给应用添加3D Touch菜单
查看>>
05_Node js 文件管理模块 fs
查看>>
关于python中可迭代对象和迭代器的一些理解
查看>>
界面无小事(五):自定义TextView
查看>>