go-ethereum源碼剖析:區Block Storage

來源:互聯網
上載者:User

區塊和交易等資料最終都是儲存在leveldb資料庫中的,本文介紹區塊和交易在leveldb中的儲存格式。在core/database_util.go中封裝了所有與區Block Storage和讀取相關的代碼,通過這些代碼可以弄清楚區塊、交易等資料結構在資料庫中是如何儲存的。

區Block Storage

leveldb是一個key-value資料庫,所有資料都是以鍵-值對的形式儲存。key一般與hash相關,value一般是要儲存的資料結構的RLP編碼。區Block Storage時將區塊頭和區塊體分開儲存。

區塊頭的儲存格式為:

headerPrefix + num (uint64 big endian) + hash -> rlpEncode(header)

其中key由區塊號(uint64大端格式)、區塊hash、以及一個首碼構成,value是區塊頭的RLP編碼。

區塊體的儲存格式為:

bodyPrefix + num (uint64 big endian) + hash -> rlpEncode(block body)

其中key由區塊號(uint64大端格式)、區塊hash、以及一個首碼構成,value是區塊體的RLP編碼。

key中的首碼可以用來區分資料的類型,在core/database_util.go中定義了各種首碼:

headerPrefix        = []byte("h")   // headerPrefix + num (uint64 big endian) + hash -> headertdSuffix            = []byte("t")   // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> tdnumSuffix           = []byte("n")   // headerPrefix + num (uint64 big endian) + numSuffix -> hashblockHashPrefix     = []byte("H")   // blockHashPrefix + hash -> num (uint64 big endian)bodyPrefix          = []byte("b")   // bodyPrefix + num (uint64 big endian) + hash -> block body

其中headerPrefix定義了區塊頭的首碼為h,bodyPrefix定義了區塊體的首碼為b。

下面是儲存區塊頭的函數:

// WriteHeader serializes a block header into the database.func WriteHeader(db ethdb.Database, header *types.Header) error {    data, err := rlp.EncodeToBytes(header)    if err != nil {        return err    }    hash := header.Hash().Bytes()    num := header.Number.Uint64()    encNum := encodeBlockNumber(num)    key := append(blockHashPrefix, hash...)    if err := db.Put(key, encNum); err != nil {        glog.Fatalf("failed to store hash to number mapping into database: %v", err)    }    key = append(append(headerPrefix, encNum...), hash...)    if err := db.Put(key, data); err != nil {        glog.Fatalf("failed to store header into database: %v", err)    }    glog.V(logger.Debug).Infof("stored header #%v [%x…]", header.Number, hash[:4])    return nil}

它是先對區塊頭進行RLP編碼,encodeBlockNumber將區塊號轉換成大端格式,然後組裝key。這裡先向資料庫中儲存一條 區塊hash->區塊號 的映射,最後將區塊頭的RLP編碼寫到資料庫中。

下面是儲存區塊體的函數:

// WriteBody serializes the body of a block into the database.func WriteBody(db ethdb.Database, hash common.Hash, number uint64, body *types.Body) error {    data, err := rlp.EncodeToBytes(body)    if err != nil {        return err    }    return WriteBodyRLP(db, hash, number, data)}// WriteBodyRLP writes a serialized body of a block into the database.func WriteBodyRLP(db ethdb.Database, hash common.Hash, number uint64, rlp rlp.RawValue) error {    key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)    if err := db.Put(key, rlp); err != nil {        glog.Fatalf("failed to store block body into database: %v", err)    }    glog.V(logger.Debug).Infof("stored block body [%x…]", hash.Bytes()[:4])    return nil}

WriteBody先對區塊體進行RLP編碼,然後調用WriteBodyRLP將區塊體的RLP編碼寫到資料庫中。WriteBodyRLP根據上面的規則群組裝key,然後向資料庫中寫入一條記錄。

還有一個WriteBlock函數分別調用WriteBody和WriteHeader將區塊寫到資料庫中。此外還有GetHeader GetBody GetBlock函數用於從資料庫中讀取區塊。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.