5.4 账本数据
賬本數(shù)據(jù)(Ledger)是以二進制文件的形式存儲的,每個賬本數(shù)據(jù)存儲在不同的目錄下。后面的內(nèi)容都是在已經(jīng)區(qū)分了賬本的情況下再對數(shù)據(jù)進行查詢的。基于文件系統(tǒng)的區(qū)塊存儲實現(xiàn)了如下功能接口。
1)賬本存儲管理。
·提交區(qū)塊到賬本(AddBlock)
·獲取區(qū)塊鏈信息(GetBlockchainInfo)
·獲取區(qū)塊數(shù)據(jù)(RetrieveBlocks)
·關(guān)閉區(qū)塊存儲(Shutdown)
2)索引管理:跟蹤區(qū)塊和交易保存在哪個文件。
·根據(jù)哈希值獲取區(qū)塊(RetrieveBlockByHash)
·根據(jù)區(qū)塊編號獲取區(qū)塊(RetrieveBlockByNumber)
·根據(jù)交易編號獲取交易(RetrieveTxByID)
·根據(jù)區(qū)塊編號和交易編號獲取交易(RetrieveTxByBlockNumTranNum)
·根據(jù)交易編號獲取區(qū)塊(RetrieveBlockByTxID)
·根據(jù)交易編號獲取交易驗證碼(RetrieveTxValidationCodeByTxID)
賬本數(shù)據(jù)的所有操作都是通過區(qū)塊文件管理器(blockfileMgr)實現(xiàn)的,定義如下:
type blockfileMgr struct {
? ?rootDir ? ? ? ? ? string ? ? ? ? ? ? ? ? ? ? // 區(qū)塊鏈中區(qū)塊存儲的根目錄
? ?conf ? ? ? ? ? ? ?*Conf ? ? ? ? ? ? ? ? ? ? ?// 配置信息
? ?db ? ? ? ? ? ? ? ?*leveldbhelper.DBHandle ? ?// 數(shù)據(jù)庫指針
? ?index ? ? ? ? ? ? index ? ? ? ? ? ? ? ? ? ? ?// 區(qū)塊索引接口
? ?cpInfo ? ? ? ? ? ?*checkpointInfo ? ? ? ? ? ?// 區(qū)塊檢查點信息
? ?cpInfoCond ? ? ? ?*sync.Cond ? ? ? ? ? ? ? ? // 條件變量
? ?currentFileWriter *blockfileWriter ? ? ? ? ? // 當(dāng)前寫入?yún)^(qū)塊文件的指針
? ?bcInfo ? ? ? ? ? ?atomic.Value ? ? ? ? ? ? ? // 區(qū)塊鏈信息
}
區(qū)塊文件管理器實現(xiàn)的功能分為幾類。
1)賬本數(shù)據(jù)存儲管理。
·確定文件存儲在哪個目錄;
·確定區(qū)塊存儲在哪個文件。
2)檢查點管理:跟蹤最新持久化存儲的文件。
3)索引管理:跟蹤區(qū)塊和交易保存在哪個文件。
5.4.1 賬本數(shù)據(jù)存儲
區(qū)塊文件管理器創(chuàng)建的文件名以"blockfile_"為前綴,6位數(shù)字為后綴,后綴必須是從小到大連續(xù)的數(shù)字, 中間不能有缺失,比如blockfile_000000、blockfile_000001、blockfile_000002等。默認(rèn)的區(qū)塊文件大小上 限為64MB(目前這個大小在代碼中是固定的,以后可能會動態(tài)調(diào)整)。一個賬本能保存的最大數(shù)據(jù)量大概有61TB,這應(yīng)該能滿足目前絕大多數(shù)的應(yīng)用了。
區(qū)塊文件管理器維護一個當(dāng)前寫入?yún)^(qū)塊文件的指針currentFileWriter,寫入?yún)^(qū)塊文件的數(shù)據(jù)包括兩個 部分,一個是區(qū)塊大小,另一個是區(qū)塊數(shù)據(jù)。寫入?yún)^(qū)塊文件中的區(qū)塊大小和區(qū)塊數(shù)據(jù)都是經(jīng)過序列化處理的,序列化過程見技術(shù)實現(xiàn)部分。如果寫入?yún)^(qū)塊大小和序列 化后,當(dāng)前區(qū)塊文件的大小超過設(shè)定值,則會寫入到下一個區(qū)塊文件中。創(chuàng)建一個新的區(qū)塊檢查點信息(見區(qū)塊索引部分),保存到數(shù)據(jù)庫中。
若寫入?yún)^(qū)塊文件和保存區(qū)塊檢查點信息的過程出現(xiàn)任何異常,就會根據(jù)區(qū)塊檢查點記錄的最新區(qū)塊文件偏移 latestFileChunksize(見區(qū)塊索引部分),恢復(fù)區(qū)塊文件到寫入前的狀態(tài)。多個區(qū)塊數(shù)據(jù)保存到區(qū)塊文件后,區(qū)塊文件形成了一個非結(jié)構(gòu)化的 二進制文件,它需要在區(qū)塊文件外記錄索引信息,才能快速地定位到區(qū)塊。保存區(qū)塊數(shù)據(jù)后會建立這個區(qū)塊的索引,并保存到數(shù)據(jù)庫中,詳細(xì)的構(gòu)建區(qū)塊索引過程在 后面的章節(jié)會有介紹。
最后是更新區(qū)塊鏈文件管理器維護的區(qū)塊檢查點信息和區(qū)塊鏈信息。
5.4.2 賬本數(shù)據(jù)讀取
區(qū)塊文件流(blockfileStream)和區(qū)塊流(blockStream)是以數(shù)據(jù)流的方式從區(qū)塊文件系 統(tǒng)中讀取區(qū)塊的,區(qū)塊文件流是從單個文件中讀取的,區(qū)塊流可以跨不同的文件,實際的文件讀取通過區(qū)塊文件流來實現(xiàn)。區(qū)塊流維護了當(dāng)前的區(qū)塊文件流指針,還 有當(dāng)前區(qū)塊文件的編號等,詳細(xì)的定義如下:
type blockStream struct {
? ?rootDir ? ? ? ? ? string ? ? ? ? ? ?// 區(qū)塊鏈中區(qū)塊存儲的根目錄
? ?currentFileNum ? ?int ? ? ? ? ? ? ? // 當(dāng)前讀取文件區(qū)塊的編號
? ?endFileNum ? ? ? ?int ? ? ? ? ? ? ? // 結(jié)束讀取文件區(qū)塊的編號
? ?currentFileStream *blockfileStream ?// 當(dāng)前區(qū)塊文件流指針
}
可以有多個區(qū)塊流同時讀取區(qū)塊文件以獲取區(qū)塊數(shù)據(jù),讀取從區(qū)塊文件currentFileNum的某個偏移開始, 到區(qū)塊文件endFileNum(包含整個區(qū)塊文件)之間的所有區(qū)塊。結(jié)束讀取文件區(qū)塊的endFileNum可以設(shè)置為小于0的數(shù)值,這表示讀取后續(xù)所 有的區(qū)塊文件,直到賬本數(shù)據(jù)目錄下某個區(qū)塊文件不存在為止。
跟區(qū)塊文件存儲過程類似,讀取區(qū)塊數(shù)據(jù)需要先讀取區(qū)塊數(shù)據(jù)的大小,再讀取區(qū)塊數(shù)據(jù)本身。區(qū)塊數(shù)據(jù)的大小是可變長的 64位數(shù)字,最大長度為8個字節(jié)。由于可變長數(shù)字序列化后最后一個字節(jié)的最高位是0,所以能從字節(jié)流中區(qū)分出區(qū)塊數(shù)據(jù)大小和區(qū)塊數(shù)據(jù)本身。詳細(xì)的編碼規(guī)則 見序列化部分。
區(qū)塊迭代器(blocksItr)基于區(qū)塊流,實現(xiàn)了獲取區(qū)塊數(shù)據(jù)(RetrieveBlocks)的接口。增加的一個業(yè)務(wù)邏輯是如果需要獲取的區(qū)塊編號還未生成,迭代器會一直等待,直到獲取到指定區(qū)塊或者關(guān)閉迭代器。
5.4.3 交易模擬執(zhí)行
鏈碼是可以并行執(zhí)行的,執(zhí)行的過程并不影響當(dāng)前的狀態(tài)數(shù)據(jù)庫。實現(xiàn)的方法是在最新賬本上生成一個賬本數(shù)據(jù)的模擬 器,模擬執(zhí)行過程生成的數(shù)據(jù)會寫入模擬器的writeMap中,讀取的數(shù)據(jù)寫入到readMap中,最后再根據(jù)writeMap和readMap生成 TxRwSet結(jié)果。每次鏈碼執(zhí)行的時候都會生成一個新的模擬器,所以多個鏈碼并行執(zhí)行并不會相互影響,模擬執(zhí)行的結(jié)果也不會直接影響當(dāng)前的狀態(tài)數(shù)據(jù)庫, 生成的TxRwSet在提交交易的時候,只有驗證通過以后才會記錄到賬本中。
來源:我是碼農(nóng),轉(zhuǎn)載請保留出處和鏈接!
本文鏈接:http://www.54manong.com/?id=1067
'); (window.slotbydup = window.slotbydup || []).push({ id: "u3646208", container: s }); })(); '); (window.slotbydup = window.slotbydup || []).push({ id: "u3646147", container: s }); })();總結(jié)
- 上一篇: HTML5带音乐手机摇一摇抽奖代码
- 下一篇: 论文助手网站