亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

Go語言開發區塊鏈只需180行代碼(推薦)

2020-04-01 18:57:24
字體:
來源:轉載
供稿:網友

區塊鏈開發用什么語言?通過本文你將使用Go語言開發自己的區塊鏈(或者說用go語言搭建區塊鏈)、理解哈希函數是如何保持區塊鏈的完整性、掌握如何用Go語言編程創造并添加新的塊、實現多個節點通過競爭生成塊、通過瀏覽器來查看整個鏈、了解所有其他關于區塊鏈的基礎知識。

但是,文章中將不會涉及工作量證明算法(PoW)以及權益證明算法(PoS)這類的共識算法,同時為了讓你更清楚得查看區塊鏈以及塊的添加,我們將網絡交互的過程簡化了,關于 P2P 網絡比如“全網廣播”這個過程等內容將在后續文章中補上。

開發環境

我們假設你已經具備一點 Go 語言的開發經驗。在安裝和配置 Go 開發環境后之后,我們還要獲取以下一些依賴:

~$ go get github.com/davecgh/go-spew/spew

spew可以幫助我們在終端中中直接查看 struct 和 slice 這兩種數據結構。

~$ go get github.com/gorilla/mux

Gorilla 的 mux 包非常流行, 我們用它來寫 web handler。

~$ go get github.com/joho/godotenv

godotenv可以幫助我們讀取項目根目錄中的.env 配置文件,這樣就不用將 http端口之類的配置硬編碼進代碼中了。比如像這樣:

ADDR=8080

接下來,我們創建一個 main.go 文件。之后的大部分工作都圍繞這個文件,開始寫代碼吧!

導入依賴包

我們將所有的依賴包以聲明的方式導入進去:

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

數據模型

接著我們來定義一個結構體,它代表組成區塊鏈的每一個塊的數據模型:

type Block struct { Index  int Timestamp string BPM  int Hash  string PrevHash string}

Index 是這個塊在整個鏈中的位置
Timestamp 顯而易見就是塊生成時的時間戳
Hash 是這個塊通過 SHA256 算法生成的散列值
PrevHash 代表前一個塊的 SHA256 散列值
BPM 每分鐘心跳數,也就是心率
接著,我們再定義一個結構表示整個鏈,最簡單的表示形式就是一個 Block 的 slice:

var Blockchain []Block

我們使用散列算法(SHA256)來確定和維護鏈中塊和塊正確的順序,確保每一個塊的 PrevHash 值等于前一個塊中的 Hash 值,這樣就以正確的塊順序構建出鏈:

go語言,開發,區塊鏈

散列和生成新塊

我們為什么需要散列?主要是兩個原因:

  • 在節省空間的前提下去唯一標識數據。散列是用整個塊的數據計算得出,在我們的例子中,將整個塊的數據通過 SHA256 計算成一個定長不可偽造的字符串。
  • 維持鏈的完整性。通過存儲前一個塊的散列值,我們就能夠確保每個塊在鏈中的正確順序。任何對數據的篡改都將改變散列值,同時也就破壞了鏈。以我們從事的醫療健康領域為例,比如有一個惡意的第三方為了調整“人壽險”的價格,而修改了一個或若干個塊中的代表不健康的 BPM 值,那么整個鏈都變得不可信了。

我們接著寫一個函數,用來計算給定的數據的 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)}

這個 calculateHash 函數接受一個塊,通過塊中的 Index,Timestamp,BPM,以及 PrevHash 值來計算出 SHA256 散列值。接下來我們就能編寫一個生成塊的函數:

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}

其中,Index 是從給定的前一塊的 Index 遞增得出,時間戳是直接通過 time.Now() 函數來獲得的,Hash 值通過前面的 calculateHash 函數計算得出,PrevHash 則是給定的前一個塊的 Hash 值。

校驗塊

搞定了塊的生成,接下來我們需要有函數幫我們判斷一個塊是否有被篡改。檢查 Index 來看這個塊是否正確得遞增,檢查 PrevHash 與前一個塊的 Hash 是否一致,再來通過 calculateHash 檢查當前塊的 Hash 值是否正確。通過這幾步我們就能寫出一個校驗函數:

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}

除了校驗塊以外,我們還會遇到一個問題:兩個節點都生成塊并添加到各自的鏈上,那我們應該以誰為準?這里的細節我們留到下一篇文章,這里先讓我們記住一個原則:始終選擇最長的鏈:

go語言,開發,區塊鏈

通常來說,更長的鏈表示它的數據(狀態)是更新的,所以我們需要一個函數能幫我們將本地的過期的鏈切換成最新的鏈:

func replaceChain(newBlocks []Block) { if len(newBlocks) > len(Blockchain) {  Blockchain = newBlocks }}

到這一步,我們基本就把所有重要的函數完成了。接下來,我們需要一個方便直觀的方式來查看我們的鏈,包括數據及狀態。通過瀏覽器查看 web 頁面可能是最合適的方式!

Web 服務

我猜你一定對傳統的 web 服務及開發非常熟悉,所以這部分你肯定一看就會。

借助 Gorilla/mux 包,我們先寫一個函數來初始化我們的 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}

其中的端口號是通過前面提到的 .env 來獲得,再添加一些基本的配置參數,這個 web 服務就已經可以 listen and serve 了!

接下來我們再來定義不同 endpoint 以及對應的 handler。例如,對“/”的 GET 請求我們可以查看整個鏈,“/”的 POST 請求可以創建塊。

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))}

為了簡化,我們直接以 JSON 格式返回整個鏈,你可以在瀏覽器中訪問 localhost:8080 或者 127.0.0.1:8080 來查看(這里的8080就是你在 .env 中定義的端口號 ADDR)。

POST 請求的 handler 稍微有些復雜,我們先來定義一下 POST 請求的 payload:

type Message struct { BPM int}

再看看 handler 的實現:

func handleWriteBlock(w http.ResponseWriter, r *http.Request) { 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() newBlock, err := generateBlock(Blockchain[len(Blockchain)-1], m.BPM) if err != nil {  respondWithJSON(w, r, http.StatusInternalServerError, m)  return } if isBlockValid(newBlock, Blockchain[len(Blockchain)-1]) {  newBlockchain := append(Blockchain, newBlock)  replaceChain(newBlockchain)  spew.Dump(Blockchain) } respondWithJSON(w, r, http.StatusCreated, newBlock)}

我們的 POST 請求體中可以使用上面定義的 payload,比如:

{"BPM":75}

還記得前面我們寫的 generateBlock 這個函數嗎?它接受一個“前一個塊”參數,和一個 BPM 值。POST handler 接受請求后就能獲得請求體中的 BPM 值,接著借助生成塊的函數以及校驗塊的函數就能生成一個新的塊了!

除此之外,你也可以:

使用spew.Dump 這個函數可以以非常美觀和方便閱讀的方式將 struct、slice 等數據打印在控制臺里,方便我們調試。
測試 POST 請求時,可以使用 POSTMAN 這個 chrome 插件,相比 curl它更直觀和方便。
POST 請求處理完之后,無論創建塊成功與否,我們需要返回客戶端一個響應:

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 服務的函數“組裝”起來:

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())}

這里的 genesisBlock (創世塊)是 main 函數中最重要的部分,通過它來初始化區塊鏈,畢竟第一個塊的 PrevHash 是空的。

哦耶!完成了

可以從這里獲得完整的代碼:Github repo

讓我們來啟動它:

~$ go run main.go

在終端中,我們可以看到 web 服務器啟動的日志信息,并且打印出了創世塊的信息:

go語言,開發,區塊鏈

接著我們打開瀏覽器,訪問 localhost:8080 這個地址,我們可以看到頁面中展示了當前整個區塊鏈的信息(當然,目前只有一個創世塊):

go語言,開發,區塊鏈

接著,我們再通過 POSTMAN 來發送一些 POST 請求:

go語言,開發,區塊鏈

刷新剛才的頁面,現在的鏈中多了一些塊,正是我們剛才生成的,同時你們可以看到,塊的順序和散列值都正確。

go語言,開發,區塊鏈

總結

剛剛我們完成了一個自己的區塊鏈,雖然很簡單(陋),但它具備塊生成、散列計算、塊校驗等基本能力。接下來你就可以繼續深入的學習區塊鏈的其他重要知識,比如工作量證明、權益證明這樣的共識算法,或者是智能合約、Dapp、側鏈等等。

以上所述是小編給大家介紹的Go語言開發區塊鏈只需180行代碼(推薦),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品影片在线观看| 在线观看久久av| 亚洲最新中文字幕| 欧美激情第99页| 日韩在线视频观看| 中文字幕欧美国内| 亚洲乱亚洲乱妇无码| www.久久草.com| 日韩中文字幕欧美| 欧美裸身视频免费观看| 黑人与娇小精品av专区| 欧美成人合集magnet| 成人在线小视频| 久久影院免费观看| 久久久噜噜噜久久| 亚洲精品国产精品久久清纯直播| 一区二区欧美久久| 国产亚洲欧洲在线| 国产视频福利一区| 久久国产精品电影| 欧美性色视频在线| 国产69精品久久久| 亚洲欧美国产视频| 久久国产精品免费视频| 国产精品亚洲欧美导航| 午夜精品久久17c| 18性欧美xxxⅹ性满足| 中文国产亚洲喷潮| 国产午夜精品一区二区三区| 国产在线精品播放| www.亚洲人.com| 欧美性一区二区三区| 欧美性猛交xxxx免费看久久久| 国产欧亚日韩视频| 国产午夜精品麻豆| 亚洲精品国产综合区久久久久久久| 久久久女女女女999久久| 国产精品ⅴa在线观看h| 亚洲美女www午夜| 精品久久久久人成| 欧美黑人极品猛少妇色xxxxx| 国产精品成人免费视频| 亚洲国产美女久久久久| 亚洲欧美一区二区激情| 性色av一区二区咪爱| 欧美日韩在线视频一区二区| 97人洗澡人人免费公开视频碰碰碰| 国产精品88a∨| 日韩中文字幕在线视频| 中文字幕亚洲精品| 国产精品一香蕉国产线看观看| 亚洲国产另类 国产精品国产免费| 欧美精品videosex极品1| 成人福利免费观看| 欧美日韩免费看| 欧美洲成人男女午夜视频| 亚洲天堂男人天堂女人天堂| 亚洲成人网在线| 久久久噜噜噜久久中文字免| 国产精品久久久亚洲| 国产欧美日韩中文字幕在线| 日韩精品在线观看一区二区| 亚洲va欧美va国产综合剧情| 欧美高清videos高潮hd| 国产欧美va欧美va香蕉在| 精品美女永久免费视频| 国产一区二区三区视频免费| 亚洲xxxx做受欧美| 亚洲欧美综合v| 国产亚洲成av人片在线观看桃| 国产精品久久久久7777婷婷| 国产精品久久视频| 亚洲香蕉在线观看| 国产精品丝袜视频| 91大神在线播放精品| 国产欧美一区二区三区在线看| 欧美电影在线观看网站| 欧美激情亚洲激情| 久久国产精品首页| 亚洲综合视频1区| 欧美日韩久久久久| 国产美女直播视频一区| 色噜噜久久综合伊人一本| 欧美肥老妇视频| 国产精品久久久久久亚洲影视| 国产精品第七十二页| 中文字幕欧美精品在线| 狠狠躁夜夜躁人人爽超碰91| 国产精品亚洲аv天堂网| 亚洲女同性videos| 久久久999国产| 久久久精品一区二区| 国产精品福利片| 亚洲激情在线观看视频免费| 中国china体内裑精亚洲片| 亚洲精品欧美一区二区三区| 日韩av男人的天堂| 欧美日韩一区二区三区在线免费观看| 2019中文字幕在线观看| 亚洲天堂精品在线| 亚洲成人激情小说| 91社区国产高清| 亚洲在线视频福利| 亚洲综合国产精品| 亚洲精品久久7777777| 国产色视频一区| 最近2019年好看中文字幕视频| 欧美性xxxx极品高清hd直播| 91精品在线观| 2019国产精品自在线拍国产不卡| 国产极品jizzhd欧美| 亚洲精品98久久久久久中文字幕| 欧美大荫蒂xxx| 亚洲高清免费观看高清完整版| 亚洲欧美成人一区二区在线电影| 欧美午夜精品久久久久久久| 亚洲男人天天操| 欧美高跟鞋交xxxxxhd| 亚洲一区二区三区香蕉| 98精品在线视频| 97视频网站入口| 欧美—级a级欧美特级ar全黄| 欧美在线影院在线视频| 亚洲第一黄色网| 最新中文字幕亚洲| 亚洲免费一在线| 久久免费少妇高潮久久精品99| 精品视频久久久久久| 国产有码一区二区| 亚洲激情视频在线| 久久久久久欧美| 成人免费观看a| 97视频在线观看免费| 日韩在线观看网址| 久久久久久九九九| 按摩亚洲人久久| 一本色道久久综合狠狠躁篇怎么玩| 久久视频这里只有精品| 国产精品扒开腿做爽爽爽男男| 国内精品久久久久久中文字幕| 色视频www在线播放国产成人| 日韩精品丝袜在线| 国产91ⅴ在线精品免费观看| 久久久av亚洲男天堂| 欧美日韩国产va另类| 久热精品视频在线免费观看| 91在线观看免费高清完整版在线观看| 国产精品一区二区在线| 欧美贵妇videos办公室| 亚洲精品欧美日韩专区| 91精品国产高清久久久久久91| 美女国内精品自产拍在线播放| 97人人模人人爽人人喊中文字| 欧美性视频网站| 一区二区av在线| 亚洲视频国产视频| 国产不卡在线观看| 国产香蕉精品视频一区二区三区| 久久视频在线看| 欧美日韩亚洲成人| 日韩欧美亚洲成人| 欧美极品欧美精品欧美视频| 国产精品久久久久不卡| 亚洲综合中文字幕68页|