搭建你的迷你区块链(设计篇 )
# 探长三生的区块链探险日记 🕵️♂️🔗
Ahoy, 区块链探险家们!🏴☠️ 我是探长三生,带着一颗对未知的好奇心,我将带领大家一起探索区块链的神秘世界!
# 🚀 程序员的超能力
程序员的天赋技能就是通过代码实践自己的想法,完成一个作品会有相当的成就感。
今天,我们要一起踏上实践之旅。我将以 C++14 的代码为例,和你分享设计并实现一个迷你区块链的例子。
# 🎯 目标和范围
首先我们要知道达成的目标,根据目标划定工作范围。
考虑到我们无法搭建一个类似比特币的庞大 P2P 网络,也没有太多精力实现一个真正意义上的完整功能的全节点钱包,而且完整的全节点过于复杂,会让学习者迷失在细节中。
所以我们的目标是:构建一个包含仅有基础功能的全节点客户端,它可能没有太炫酷的 UI 页面,也没有复杂的命令,它们可以提供下面的功能。
注意:由于我的时间有限,代码不能全部实现,主要是讲解设计和实现思路。后续我会逐渐完善代码,你也可以一起参与。
# 🛠 技术选型
我们在深入区块链技术专题中说到过,区块链的四个核心技术概念:P2P 网络、账户模型与存储、共识、加密模块。
# P2P 网络模块
- 考虑方便实现和测试,可选的方案有轻量级消息队列和 WebSocket。
- 考虑到集成的便利性,我们首选 WebSocket,因为至少需要一个 HTTP JSON-RPC Server,我们可以复用 Server 中的 Websocket 服务。
# 数据交换格式
- 我们考虑采用易读通用的 JSON 格式,而不是像比特币一样的数据序列化格式。
- 后期更改可以考虑升级到 Protobuf,后者优势主要体现在性能上。而在我们的例子中,性能永远不是首先考虑的,更多是它的易读和易调试性。
# 账户加密部分
- 由于 ECDSA 非对称加密模块过于复杂,我们选用 OpenSSL 库中的 RSA 算法作为加密模块。
- 交易模型上,我们考虑使用 UTXO 模型,因为状态模型需要维护状态,可能会带来额外的代码复杂度。
# 数据库存储
- 这个模块需要考虑到易用性和易读性,我们选用 SQLite 3 作为持久化存储。
# 共识算法
- 我们选用 PoW 作为共识算法,这是考虑到 PoW 实现起来十分简单,而且交易和区块的哈希计算会涉及 SHA-256,使用 PoW 算法我们就可以复用 SHA-256 的代码,使用 SHA-256 算法作为挖矿算法会降低我们的工作量。
# 📝 详细功能
有了技术选型之后,我们再对目标功能点进行细分拆解。
- P2P 网络:节点发现、节点维护、持久化保存、区块同步。
- 公私钥对:命令行,创建公私钥对并生成地址,提供私钥存储,公私钥验证。
- 交易查询:命令行,JSON 格式的交易查询返回,输入是某个地址。
- 余额查询:命令行,JSON 格式的余额查询返回,输入是某个地址。
- 挖矿:命令行、JSON 格式挖矿信息返回,输入是某个地址。
- 区块共识:编织区块链的算法,包含创世区块以及调整全网挖矿难度。
- 交易共识:验证单个交易的算法,包含签名验证和 UTXO 验证。
- 区块持久化存储:分叉与合并时的一致性,并为查询提供接口。
- 提供格式化输出交易的功能,这里的格式化主要指 JSON 格式。
通过详细的功能拆分我们可以发现,功能点多达三十余个,如何设计实现这三十多个功能点是我们接下来首先要解决的问题。问题是这三十多个功能点不是孤立的,而是有相互联系的,我们先从顶层开始设计。
# 🏗️ 架构设计
# Tinychain
- tinychain
- blockchain
- consensus
- database
- network
- http-server
- node
我们以 node
为最顶层,那么 node
会包含其他五个模块,node
启动就会把其他 5 个服务启动。
# cli-tinychain
- cli-tinychain
- JSON
- http-client
命令行就简单多了,我们把命令行的执行和计算全部都扔到 tinychian
当中,命令行只用一个 http-client
用 JSON 把 API 包起来即可。
# 📦 基础组件
- 基础组件
- log
- JSON-paser
- sha256
- key-pair
# 📜 区块数据结构设计
有了大致的顶层设计已经分类好,那么接下来我们考虑为每个模块填充一些数据结构。一个区块链最重要的是区块,所以我们从区块开始。
# 🧱 区块头的设计
参考比特币的设计,区块头包含了前向区块哈希、默克尔根哈希、时间戳、难度目标、Nonce 值和版本号。下面是一个可能的结构示例:
{
"target_bits": "45754******1240",
"hash": "239169e8**************9e3b1bc5cd697d96954d25acacd92df",
"merkle_tree_hash": "3d228afc58*****************790ea0b7635e5b4d44ab4f",
"nonce": "385**********0177480",
"height": 1234567,
"previous_block_hash": "4d2544e044bfd2f34***************5c7f3ff654",
"time_stamp": 1528070857,
"transaction_count": 1,
"version": 1
}
2
3
4
5
6
7
8
9
10
11
- target_bits: 当前区块的目标值;
- hash: 这个区块的哈希;
- merkle_tree_hash: 这个区块当中交易列表的默克尔根;
- nonce: 随机数;
- height: 当前区块的高度;
- previous_block_hash: 指向前向区块哈希;
- time_stamp: 生产这个区块时的时间戳;
- transaction_count: 这个区块当中包含的交易数量;
- version: 区块的版本号。
# 🛠️ 开发环境搭建
由于选取了 C++ 作为实现方式,搭建工程的过程会比较复杂一点。我们用的是 Ubuntu 16.04 开发环境,默认的 gcc 编译器是 gcc-5.4,是支持 C++14 标准的。代码也是全平台可移植的,如果你使用 Mac,也可以尝试搭建。
# 🧪 测试环境搭建
我们知道区块链是一个分布式网络环境,在开始之前,我们需要构造一个简单且容易测试的分布式网络环境。
# 🎉 总结
今天我大致介绍了实践一个迷你区块链的思路,我们先划定了实践的范围,接着考虑了技术选型,然后细化了详细功能,考虑了一个区块链需要的数据结构,最后考虑了开发环境和测试环境的搭建。
🤔 今天的问题是,你觉得搭建一个迷你区块链最难的部分是哪一部分呢?