go-ethereum源码剖析:区块存储
来源:互联网 发布:2016淘宝严打刷单 编辑:程序博客网 时间:2024/05/18 06:23
区块和交易等数据最终都是存储在leveldb数据库中的,本文介绍区块和交易在leveldb中的存储格式。在core/database_util.go中封装了所有与区块存储和读取相关的代码,通过这些代码可以弄清楚区块、交易等数据结构在数据库中是如何存储的。
区块存储
leveldb是一个key-value数据库,所有数据都是以键-值对的形式存储。key一般与hash相关,value一般是要存储的数据结构的RLP编码。区块存储时将区块头和区块体分开存储。
区块头的存储格式为:
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函数用于从数据库中读取区块。
- go-ethereum源码剖析:区块存储
- go-ethereum源码剖析:交易
- 【区块链】go ethereum 安装与使用
- 以太坊go-ethereum项目源码本地环境搭建
- 区块链开发(一)搭建基于以太坊go-ethereum的私有链环境
- 区块链学习笔记(一)Ethereum-Go开发环境搭建
- 区块链开发(一)搭建基于以太坊go-ethereum的私有链环境
- 区块链零基础开发----1.搭建基于以太坊go-ethereum的私有链环境
- 区块链开发(一)搭建基于以太坊go-ethereum的私有链环境
- 区块链开发(十四)以太坊go-ethereum客户端查询交易列表探讨
- 【以太坊】Ethereum Popular Client: go-ethereum
- Ethereum钱包区块同步问题
- go-ethereum 部署私有链
- 基于Ubuntu系统搭建以太坊go-ethereum源码的开发环境
- Ethereum数据存储分析
- 在CENTOS7上玩转Ethereum区块链(2):Ethereum搭建篇
- 区块链 以太坊 ethereum 实践
- 区块链(一)--Bitcoin、Ethereum、Hyperledger
- IntelliJ IDEA 注册码 (秘钥)
- 安装 anaconda 时遇到的坑
- Get and Set Attribute Values with Properties
- AndroidStudio修改内存大小
- [leetcode]57. Insert Interval(Java)
- go-ethereum源码剖析:区块存储
- 几句哲理几句诗
- 报错的解决方法
- plsql连接远程Oracle数据库
- Android 仿「微信」自定义数字键盘
- Spring Boot + Mybatis + 二级缓存实例(Ehcache,Redis)
- pid_t的类型定义,一层一层剥洋葱
- android测量模式MeasureSpec的理解
- 关于使用position:relative居中的问题