日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

区块链技术实现只需180行go代码!

發布時間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 区块链技术实现只需180行go代码! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

區塊鏈技術實現只需180行go代碼!

通過本文,你將可以使用Go創建自己的區塊鏈、理解哈希函數是如何保持區塊鏈的完整性、掌握如何創造并添加新的塊、實現多個節點通過競爭生成塊、通過瀏覽器來查看整個鏈、了解所有其他關于區塊鏈的基礎知識。

如果你希望馬上開始學習以太坊DApp開發,可以訪問匯智網提供的出色的在線互動教程:

  • 以太坊DApp實戰開發入門
  • 去中心化電商DApp實戰開發

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

開發環境

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

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

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

~$ go get github.com/gorilla/mux
  • 1

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

~$ go get github.com/joho/godotenv
  • 1

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

ADDR=8080
  • 1

接下來,我們創建一個?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" )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

數據模型

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

type Block struct {Index intTimestamp stringBPM intHash stringPrevHash string }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • Index 是這個塊在整個鏈中的位置
  • Timestamp 顯而易見就是塊生成時的時間戳
  • Hash 是這個塊通過 SHA256 算法生成的散列值
  • PrevHash 代表前一個塊的 SHA256 散列值
  • BPM 每分鐘心跳數,也就是心率

接著,我們再定義一個結構表示整個鏈,最簡單的表示形式就是一個 Block 的 slice:

var Blockchain []Block
  • 1

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

散列和生成新塊

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

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

我們接著寫一個函數,用來計算給定的數據的 SHA256 散列值:

func calculateHash(block Block) string {record := string(block.Index) + block.Timestamp + string(block.BPM) + block.PrevHashh := sha256.New()h.Write([]byte(record))hashed := h.Sum(nil)return hex.EncodeToString(hashed) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

func generateBlock(oldBlock Block, BPM int) (Block, error) {var newBlock Blockt := time.Now()newBlock.Index = oldBlock.Index + 1newBlock.Timestamp = t.String()newBlock.BPM = BPMnewBlock.PrevHash = oldBlock.HashnewBlock.Hash = calculateHash(newBlock)return newBlock, nil }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

其中,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 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

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

func replaceChain(newBlocks []Block) {if len(newBlocks) > len(Blockchain) {Blockchain = newBlocks} }
  • 1
  • 2
  • 3
  • 4
  • 5

到這一步,我們基本就把所有重要的函數完成了。接下來,我們需要一個方便直觀的方式來查看我們的鏈,包括數據及狀態。通過瀏覽器查看 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 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

其中的端口號是通過前面提到的 .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 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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)) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

type Message struct {BPM int }
  • 1
  • 2
  • 3

再看看 handler 的實現:

func handleWriteBlock(w http.ResponseWriter, r *http.Request) {var m Messagedecoder := 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)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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

{"BPM":75}
  • 1

還記得前面我們寫的 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) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

快要大功告成了。

接下來,我們把這些關于區塊鏈的函數,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()) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

哦耶!完成了

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

讓我們來啟動它:

~$ go run main.go
  • 1

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

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

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

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

總結

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

目前這個實現中不包括任何 P2P 網絡的內容,我們會在下一篇文章中補充這部分內容,當然,我們鼓勵你在這個基礎上自己實踐一遍!

原文:180行go代碼讓你徹底理解區塊鏈是什么

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的区块链技术实现只需180行go代码!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 人妻少妇精品视频一区二区三区 | 国产成人在线视频观看 | 欧美成年人视频在线观看 | 97青青草 | 成人动漫在线观看免费 | wwww欧美 | 给我看高清的视频在线观看 | 成人免费aaa| 91九色蝌蚪91por成人 | 久久网免费视频 | 免费高清毛片 | 黄色在线免费 | av在线天堂 | av大片在线 | 亚洲AV无码乱码国产精品色欲 | 日本黄色片视频 | 熟女少妇一区二区三区 | 欧美一区亚洲 | 亚洲乱码一区二区 | 97视频成人 | 99精品视频免费看 | 夜夜嗨老熟女av一区二区三区 | 四虎色| 天堂av片| 国产成年人网站 | 欧美在线综合 | 国产午夜精品久久久久久久 | 久久涩 | 最近最新最好看的2019 | 中文字幕不卡在线播放 | 国产精品久久久久9999爆乳 | 国产内射老熟女aaaa∵ | 天天射影院 | 欧美影音 | 亚洲精品电影网 | 毛毛毛片 | 国产成人精品在线视频 | 性感美女在线 | 毛片一区 | 欧美日韩欧美日韩在线观看视频 | 在线成人影视 | 国产精品无码一区二区三区三 | 久久久久无码国产精品一区李宗瑞 | 日本欧美在线视频 | 91精品国产一区二区在线观看 | www黄色网 | 亚洲黄页网站 | www久久久久久久 | 亚洲国产精品成人av | 超碰福利在线 | 免费国产羞羞网站视频 | 美女网站在线 | 国产精品欧美一区喷水 | 国产精品jizz在线观看软件 | 精品一区二区三区无码视频 | 久操精品| 美女福利视频一区 | 日本免费黄网站 | 亚洲区综合 | 国产农村妇女毛片精品久久 | 国产激情网址 | 最新国产一区 | 日本美女久久 | 男人操女人逼逼视频 | av不卡在线看 | a在线观看免费 | 韩国伦理片在线观看 | 超碰8| 亚洲一区二区三区四区在线观看 | 亚洲欧美日韩综合在线 | 91欧美一区| 91色视频在线| 成人黄色片免费 | 日本美女动态图 | 老司机深夜福利在线观看 | 清草视频 | 99久久精品免费看国产交换 | 在线播放你懂的 | 揄拍自拍| www.日韩在线 | 欧美日本一区二区三区 | 69精品在线观看 | 中文字幕网址在线 | 无码精品一区二区三区AV | 秋霞国产午夜精品免费视频 | 日韩黄色影视 | 久久久久99精品成人片我成大片 | 国产日韩精品视频 | 97超碰网 | 东京热无码av一区二区 | 国产视频欧美 | 男女啪啪无遮挡 | 久久久久久国产精品 | 欧美日韩中文国产一区发布 | 日韩久久高清 | 亚洲无码一区二区三区 | av网站在线播放 | 香港a毛片| 国产免费视频一区二区三区 |