用 Go 構建一個區塊鏈 ---- Part 1: 基本原型__區塊鏈

來源:互聯網
上載者:User

翻譯的系列文章我已經放到了 GitHub 上:blockchain-tutorial,後續如有更新都會在 GitHub 上,可能就不在這裡同步了。如果想直接運行代碼,也可以 clone GitHub 上的教程倉庫,進入 src 目錄執行 make 即可。 引言

區塊鏈是 21 世紀最具革命性的技術之一,它仍然處於不斷成長的階段,而且還有很多潛力尚未顯現出來。 本質上,區塊鏈只是一個分散式資料庫而已。 不過,使它獨一無二的是,區塊鏈是一個公開的資料庫,而不是一個私人資料庫,也就是說,每個使用它的人都有一個完整或部分的副本。 只有經過其他資料庫管理員的同意,才能向資料庫中添加新的記錄。 此外,也正是由於區塊鏈,才使得加密貨幣和智能合約成為現實。

在本系列文章中,我們將實現一個簡化版的區塊鏈,基於它來構建簡化版的加密貨幣。 區塊

讓我們從 “區塊鏈” 中的 “區塊” 談起。在區塊鏈中,儲存有效資訊的是區塊。比如,比特幣區Block Storage的有效資訊,就是比特幣交易,交易資訊也是所有加密貨幣的本質。除此以外,區塊還包含了一些技術資訊,比如版本,目前時間戳和前一個區塊的雜湊。

在本文中,我們並不會實現一個像比特幣技術規範所描述的區塊鏈,而是實現一個簡化版的區塊鏈,它僅包含了一些關鍵資訊。看起來就像是這樣:

type Block struct {    Timestamp     int64    Data          []byte    PrevBlockHash []byte    Hash          []byte}                      1            2            3            4            5            6          
Timestamp 是目前時間戳,也就是區塊建立的時間。 Data 是區Block Storage的實際有效資訊。 PrevBlockHash 儲存的是前一個塊的雜湊。 Hash 是當前塊的雜湊。

在比特幣技術規範中,Timestamp, PrevBlockHash, Hash 是區塊頭(block header),區塊頭是一個單獨的資料結構。而交易,也就是這裡的 Data, 是另一個單獨的資料結構。為了簡便起見,我把這兩個混合在了一起。

那麼,我們要如何計算雜湊呢。如何計算雜湊,是區塊鏈一個非常重要的部分。正是由於這個特性,才使得區塊鏈是安全的。計算一個雜湊,是在計算上非常困難的一個操作。即使在高速電腦上,也要花費不少時間 (這就是為什麼人們會購買 GPU 來挖比特幣) 。這是一個有意為之的架構設計,它故意使得加入新的區塊十分困難,因此可以保證區塊一旦被加入以後,就很難再進行修改。在本系列未來幾篇文章中,我們將會討論和實現這個機制。

目前,我們僅取了 Block 結構的一些欄位(Timestamp, Data 和 PrevBlockHash),並將它們相互串連起來,然後在串連後的結果上計算一個 SHA-256 的雜湊. 讓我們在 SetHash 方法中完成這個任務:

func (b *Block) SetHash() {    timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))    headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})    hash := sha256.Sum256(headers)    b.Hash = hash[:]}                      1            2            3            4            5            6            7          

接下來,按照 Golang 的慣例,我們會實現一個用於簡化建立一個區塊的函數:

func NewBlock(data string, prevBlockHash []byte) *Block {    block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}    block.SetHash()    return block}                      1            2            3            4            5          

這就是區塊部分的全部內容了。 區塊鏈

下面讓我們來實現一個區塊鏈。本質上,區塊鏈僅僅是一個有著特定結構的資料庫,是一個有序,後向串連的列表。這也就是說,區塊按照插入的順序進行儲存,每個塊都被串連到前一個塊。這樣的結構,能夠讓我們快速地擷取鏈上的最新塊,並且高效地通過雜湊來檢索一個塊。

在 Golang 中,可以通過一個 array 和 map 來實現這個結構:array 儲存有序的雜湊(Golang 中 array 是有序的),map 儲存 hask -> block 對(Golang 中, map 是無序的)。 但是在基本的原型階段,我們只用到了 array,因為現在還不需要通過雜湊來擷取塊。

type Blockchain struct {    blocks []*Block}                      1            2            3          

這就是我們的第一個區塊鏈。我從來沒有想過它會是這麼容易。

現在,讓我們能夠給它添加一個塊:

func (bc *Blockchain) AddBlock(data string) {    prevBlock := bc.blocks[len(bc.blocks)-1]    newBlock := NewBlock(data, prevBlock.Hash)    bc.blocks = append(bc.blocks, newBlock)}                      1            2            3            4            5          

完成。不過,真的就這樣了嗎。

為了加入一個新的塊,我們必須要有一個已有的塊,但是,現在我們的鏈是空的,一個塊都沒有。所以,在任何一個區塊鏈中,都必須至少有一個塊。這樣的塊,也就是鏈中的第一個塊,通常叫做創世塊(genesis block). 讓我們實現一個方法來建立一個創世塊:

func NewGenesisBlock() *Block {    return NewBlock("Genesis Block", []byte{})}                      1            2            3          

現在,我們可以實現一個函數來建立有創世塊的區塊鏈:

func NewBlockchain() *Blockchain {    return &Blockchain{[]*Block{NewGenesisBlock()}}}                      1            2            3          

來檢查一個我們的區塊鏈是否如期工作:

func main() {    bc := NewBlockchain()    bc.AddBlock("Send 1 BTC to Ivan")    bc.AddBlock("Send 2 more BTC to Ivan")    for _, block := range bc.blocks {        fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)        fmt.Printf("Data: %s\n", block.Data)        fmt.Printf("Hash: %x\n", block.Hash)        fmt.Println()    }}                      1            2            3            4            5            6            7            8            9            10            11            12            13          

輸出:

Prev. hash:Data: Genesis BlockHash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168Prev. hash: aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168Data: Send 1 BTC to IvanHash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1Prev. hash: d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1Data: Send 2 more BTC to IvanHash: 561237522bb7fcfbccbc6fe0e98bbbde7427ffe01c6fb223f7562288ca2295d1                      1            2            3            4            5            6            7            8            9            10            11          

總結

我們建立了一個非常簡單的區塊鏈原型:它僅僅是一個數組構成的一系列區塊,每個塊都與前一個塊相關聯。真實的區塊鏈要比這複雜得多。在我們的區塊鏈中,加入新的塊非常簡單,而且很快,但是在真實的區塊鏈中,加入新的塊需要很多工作:你必須要經過十分繁重的計算(這個機制叫做工作量證明),來獲得添加一個新塊的權力。並且,區塊鏈是一個沒有單一決策者的分散式資料庫。因此,一個新的塊必須要被網路的其他參與者確認和同意(這個機制叫做共識(consensus))。還有一點,我們的區塊鏈還沒有任何的交易。

在接下來的文章的我們將會一一覆蓋這些特性。

本文涉及的原始碼:part_1

區塊雜湊演算法:https://en.bitcoin.it/wiki/Block_hashing_algorithm

原文:

Building Blockchain in Go. Part 1: Basic Prototype

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.