美文网首页
Go区块链从0到1:区块持久化、命令行交互

Go区块链从0到1:区块持久化、命令行交互

作者: 弱碱强酸 | 来源:发表于2018-08-29 17:23 被阅读0次

    简介:

    到目前为止,我们实现了一个简单的区块链基础模型,建立了工作量证明的机制。本文将与大家一起实现区块链的持久化存储,以及实现一个简单的命令行对区块链进行操作。我们先忽略区块链“分布式”的特征,专注实现其数据库的特征。

    数据库:

    目前为止,我们没有数据库,我们将区块链存在内存中。对于实现的区块,我们再次使用,不能和别人分享该区块,因此我们要实现区块链的持久化。

    比特币白皮书中并没有指定特定的数据库类型,它取决于开发者的选择,在实际使用中比特币使用leveldb作为数据库。大家来了解一种新的数据库:

    BoltDB:

    1.简单

    2.使用go语言

    3.不需要启动服务

    4.满足我们需要的数据结构需求

    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存储二进制类型数据,因此为了存储区块,我们必须进行序列化,我们使用golibarary中的encoding/gob作为序列化和反序列化函数。

    数据库结构:

    我们参考比特币的存储结构(将区块链数据分为两个bucket):

    1.blocks区块存储区块链中区块的元数据。

    2.chainstate 存储链的状态,存储未话费交易输出和一些元数据。

    在blocks区,其key/value结构如下:

    1.'b' + 32位区块哈希 作为区块的索引

    2.'f' + 4位文件句柄 -> 文件信息记录

    3.'l' -> 4位文件句柄  ->上一个区块的文件信息

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

    5.'F' + 1位标记长度 + 标记名 -> 1 byte boolean: various flags that can be on or off

    6.'t' + 32位交易哈希 -> 交易记录

    在chainstate区,其key/value结构如下:

    1.'c' + 32位交易哈希 -> 本次交易的未花费交易输出

    2.'B' -> 32位交易哈希: 到目前为止未消费交易的区块哈希

    由于,我们本文并不实现交易,同时我们不分开文件存储,所以数据库总的区块结构可以简化为:

    1.32位区块哈希>区块结构(序列化的)

    2.‘l’>上一个区块的哈希

    序列化:

    由于boltDB只能存储[]byte类型数据,为了存储区块数据,我们需要实现序列化接口。我们使用go libarary中提供的encoding/gob函数实现区块的序列化。

    另外我们需要一个函数,将db中的block反序列化为Block结构,以再次读取。

    持久化:

    从NewBlockChain函数开始,新建了一个BlockChain实例,并且将GeneiusBlock加入其中。

    持久化步骤如下:

    1.打开一个数据文件

    2.检查是否该文件是否有保存的区块链信息

    3.如果存在区块链信息:新建一个区块链实例,设置该区块链tip指向db中存储的区块链的最后一个区块哈希

    4.如果不存在区块链:

            1.新建区块链实例

            2.存储在数据库中

            3.将创世区块的哈希作为最后一个区块哈希

            4.新建一个区块链实例,tip指向创世区块

    同时我们需要更新区块的结构如下:

    type BlockChainstruct {

            tip []byte

            db  *bolt.DB

    }

    接下来我们需要更新AddBlock方法:

    现在我们实现了添加新区块的功能,但是出现一个问题,我们无法获取已经保存的区块链的信息。因此,我们需要增加新的功能,从db中读取区块链信息。

    查看区块链:

    至此为止,所有的区块均存储在数据库中,我们可以重新打开区块链文件新增区块。但是我们缺少一个重要功能,一次浏览每个区块的内容。

    BoltDB提供api可以循环一个bucket中内容,但是其key是字节排序的,我们希望按区块添加的顺序依次打印区块信息。由于我们不希望一次将所有区块的信息加载入内存,因此需要实现一个迭代功能。

    CLI:

    目前,我们实现了NewBlockChain、AddBlock方法,现在就开始实现简单的命令行操作方法吧。

    1.blockchain_go AddBlock "A pays B two yuan"

    2.blockchain_go PrintChain

    所有的命令行操作方法,我们都由CLI struct实现。

    该结构的命令行由Run方法维护输入。

    其中,os.Args返回参数中,第一个参数返回为可执行命令文件路径:

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

    上述命令使用os.Args返回参数数组,os.Args[0]为C://goblock/main.exe,os.Args[1]为addblock,os.Args[2]为data,os.Args[3]为test。具体的使用可查看flag包用法,后文会介绍。

    到目前为止,我们实现了命令行向区块db中添加区块,以及查看区块信息的功能。

    相关文章

      网友评论

          本文标题:Go区块链从0到1:区块持久化、命令行交互

          本文链接:https://www.haomeiwen.com/subject/hnyfwftx.html