Go區(qū)塊鏈從0到1:區(qū)塊持久化乃秀、命令行交互

簡介:

到目前為止肛著,我們實(shí)現(xiàn)了一個(gè)簡單的區(qū)塊鏈基礎(chǔ)模型,建立了工作量證明的機(jī)制跺讯。本文將與大家一起實(shí)現(xiàn)區(qū)塊鏈的持久化存儲(chǔ)枢贿,以及實(shí)現(xiàn)一個(gè)簡單的命令行對(duì)區(qū)塊鏈進(jìn)行操作。我們先忽略區(qū)塊鏈“分布式”的特征刀脏,專注實(shí)現(xiàn)其數(shù)據(jù)庫的特征局荚。

數(shù)據(jù)庫:

目前為止,我們沒有數(shù)據(jù)庫愈污,我們將區(qū)塊鏈存在內(nèi)存中耀态。對(duì)于實(shí)現(xiàn)的區(qū)塊,我們再次使用暂雹,不能和別人分享該區(qū)塊首装,因此我們要實(shí)現(xiàn)區(qū)塊鏈的持久化。

比特幣白皮書中并沒有指定特定的數(shù)據(jù)庫類型杭跪,它取決于開發(fā)者的選擇仙逻,在實(shí)際使用中比特幣使用leveldb作為數(shù)據(jù)庫。大家來了解一種新的數(shù)據(jù)庫:

BoltDB:

1.簡單

2.使用go語言

3.不需要啟動(dòng)服務(wù)

4.滿足我們需要的數(shù)據(jù)結(jié)構(gòu)需求

From the BoltDB’s?README on Github:

Bolt is a pure Go key/value store inspired by Howard Chu’s LMDB project. The goal of the project is to provide a simple, fast, and reliable database for projects that don’t require a full database server such as Postgres or MySQL.

Since Bolt is meant to be used as such a low-level piece of functionality, simplicity is key. The API will be small and only focus on getting values and setting values. That’s it.

簡單的key/value涧尿,api專注于setting和getting系奉。

需要注意的是,boltDB存儲(chǔ)二進(jìn)制類型數(shù)據(jù)姑廉,因此為了存儲(chǔ)區(qū)塊缺亮,我們必須進(jìn)行序列化,我們使用golibarary中的encoding/gob作為序列化和反序列化函數(shù)庄蹋。

數(shù)據(jù)庫結(jié)構(gòu):

我們參考比特幣的存儲(chǔ)結(jié)構(gòu)(將區(qū)塊鏈數(shù)據(jù)分為兩個(gè)bucket):

1.blocks區(qū)塊存儲(chǔ)區(qū)塊鏈中區(qū)塊的元數(shù)據(jù)瞬内。

2.chainstate 存儲(chǔ)鏈的狀態(tài),存儲(chǔ)未話費(fèi)交易輸出和一些元數(shù)據(jù)限书。

在blocks區(qū)虫蝶,其key/value結(jié)構(gòu)如下:

1.'b' + 32位區(qū)塊哈希 作為區(qū)塊的索引

2.'f' + 4位文件句柄 -> 文件信息記錄

3.'l' -> 4位文件句柄??->上一個(gè)區(qū)塊的文件信息

4.'R' -> 1位布爾型: 是否在索引中

5.'F' + 1位標(biāo)記長度 + 標(biāo)記名 -> 1 byte boolean: various flags that can be on or off

6.'t' + 32位交易哈希 -> 交易記錄

在chainstate區(qū),其key/value結(jié)構(gòu)如下:

1.'c' + 32位交易哈希 -> 本次交易的未花費(fèi)交易輸出

2.'B' -> 32位交易哈希: 到目前為止未消費(fèi)交易的區(qū)塊哈希

由于倦西,我們本文并不實(shí)現(xiàn)交易能真,同時(shí)我們不分開文件存儲(chǔ),所以數(shù)據(jù)庫總的區(qū)塊結(jié)構(gòu)可以簡化為:

1.32位區(qū)塊哈希>區(qū)塊結(jié)構(gòu)(序列化的)

2.‘l’>上一個(gè)區(qū)塊的哈希

序列化:

由于boltDB只能存儲(chǔ)[]byte類型數(shù)據(jù),為了存儲(chǔ)區(qū)塊數(shù)據(jù)粉铐,我們需要實(shí)現(xiàn)序列化接口疼约。我們使用go libarary中提供的encoding/gob函數(shù)實(shí)現(xiàn)區(qū)塊的序列化。

另外我們需要一個(gè)函數(shù)蝙泼,將db中的block反序列化為Block結(jié)構(gòu)程剥,以再次讀取。

持久化:

從NewBlockChain函數(shù)開始汤踏,新建了一個(gè)BlockChain實(shí)例织鲸,并且將GeneiusBlock加入其中。

持久化步驟如下:

1.打開一個(gè)數(shù)據(jù)文件

2.檢查是否該文件是否有保存的區(qū)塊鏈信息

3.如果存在區(qū)塊鏈信息:新建一個(gè)區(qū)塊鏈實(shí)例溪胶,設(shè)置該區(qū)塊鏈tip指向db中存儲(chǔ)的區(qū)塊鏈的最后一個(gè)區(qū)塊哈希

4.如果不存在區(qū)塊鏈:

? ? ? ? 1.新建區(qū)塊鏈實(shí)例

? ? ? ? 2.存儲(chǔ)在數(shù)據(jù)庫中

? ? ? ? 3.將創(chuàng)世區(qū)塊的哈希作為最后一個(gè)區(qū)塊哈希

? ? ? ? 4.新建一個(gè)區(qū)塊鏈實(shí)例搂擦,tip指向創(chuàng)世區(qū)塊

同時(shí)我們需要更新區(qū)塊的結(jié)構(gòu)如下:

type BlockChainstruct {

????????tip []byte

? ? ? ? db? *bolt.DB

}

接下來我們需要更新AddBlock方法:

現(xiàn)在我們實(shí)現(xiàn)了添加新區(qū)塊的功能,但是出現(xiàn)一個(gè)問題哗脖,我們無法獲取已經(jīng)保存的區(qū)塊鏈的信息瀑踢。因此,我們需要增加新的功能才避,從db中讀取區(qū)塊鏈信息橱夭。

查看區(qū)塊鏈:

至此為止,所有的區(qū)塊均存儲(chǔ)在數(shù)據(jù)庫中工扎,我們可以重新打開區(qū)塊鏈文件新增區(qū)塊徘钥。但是我們?nèi)鄙僖粋€(gè)重要功能,一次瀏覽每個(gè)區(qū)塊的內(nèi)容肢娘。

BoltDB提供api可以循環(huán)一個(gè)bucket中內(nèi)容呈础,但是其key是字節(jié)排序的,我們希望按區(qū)塊添加的順序依次打印區(qū)塊信息橱健。由于我們不希望一次將所有區(qū)塊的信息加載入內(nèi)存而钞,因此需要實(shí)現(xiàn)一個(gè)迭代功能。

CLI:

目前拘荡,我們實(shí)現(xiàn)了NewBlockChain臼节、AddBlock方法,現(xiàn)在就開始實(shí)現(xiàn)簡單的命令行操作方法吧珊皿。

1.blockchain_go AddBlock "A pays B two yuan"

2.blockchain_go PrintChain

所有的命令行操作方法网缝,我們都由CLI struct實(shí)現(xiàn)。

該結(jié)構(gòu)的命令行由Run方法維護(hù)輸入蟋定。

其中粉臊,os.Args返回參數(shù)中,第一個(gè)參數(shù)返回為可執(zhí)行命令文件路徑:

例如: C://goblock/main.exe? addblock -data test

上述命令使用os.Args返回參數(shù)數(shù)組驶兜,os.Args[0]為C://goblock/main.exe扼仲,os.Args[1]為addblock远寸,os.Args[2]為data,os.Args[3]為test屠凶。具體的使用可查看flag包用法驰后,后文會(huì)介紹。

到目前為止矗愧,我們實(shí)現(xiàn)了命令行向區(qū)塊db中添加區(qū)塊灶芝,以及查看區(qū)塊信息的功能。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末唉韭,一起剝皮案震驚了整個(gè)濱河市监署,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纽哥,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栖秕,死亡現(xiàn)場離奇詭異春塌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)簇捍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門只壳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人暑塑,你說我怎么就攤上這事吼句。” “怎么了事格?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵惕艳,是天一觀的道長。 經(jīng)常有香客問我驹愚,道長远搪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任逢捺,我火速辦了婚禮谁鳍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘劫瞳。我一直安慰自己倘潜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布志于。 她就那樣靜靜地躺著涮因,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恨憎。 梳的紋絲不亂的頭發(fā)上蕊退,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天郊楣,我揣著相機(jī)與錄音,去河邊找鬼瓤荔。 笑死净蚤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的输硝。 我是一名探鬼主播今瀑,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼点把!你這毒婦竟也來了橘荠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤郎逃,失蹤者是張志新(化名)和其女友劉穎哥童,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體褒翰,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贮懈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了优训。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朵你。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖揣非,靈堂內(nèi)的尸體忽然破棺而出抡医,到底是詐尸還是另有隱情,我是刑警寧澤早敬,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布忌傻,位于F島的核電站,受9級(jí)特大地震影響搁嗓,放射性物質(zhì)發(fā)生泄漏芯勘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一腺逛、第九天 我趴在偏房一處隱蔽的房頂上張望荷愕。 院中可真熱鬧,春花似錦棍矛、人聲如沸安疗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荐类。三九已至,卻和暖如春茁帽,著一層夾襖步出監(jiān)牢的瞬間玉罐,已是汗流浹背屈嗤。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吊输,地道東北人饶号。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像季蚂,于是被迫代替她去往敵國和親茫船。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349