带你读《GO语言公链开发实战》之一:公链设计架构

简介: 本书的目标是引导读者全面了解区块链技术实现原理,笔者也一直坚信,了解某一系统最直接的方式就是研读它的源码,所以本书并不是只介绍区块链技术,而是深入分析其背后的实现原理。通过阅读本书,读者可以全面地了解一条公链的技术实现。本书基于比原链的源代码进行分析,比原链是一个开源的有智能合约功能的公共区块链平台,是国内优秀的公链,目前比原链的代码量不多,而且源码结构清晰,特别适合初学者学习。

区块链技术丛书
点击查看第二章
点击查看第三章
GO语言公链开发实战

image.png

郑东旭 杨明珠 潘盈瑜 翟萌 编著

第1章

公链设计架构

1.1 概述

区块链技术起源于2008年中本聪的论文《比特币:一种点对点电子现金系统》,区块链诞生自中本聪的比特币。
区块链是一个分布式账本,一种通过去中心化、去信任的方式集体维护一个可靠数据库分布式账本是一种在网络成员之间共享、复制和同步的数据库,记录网络参与者之间的交易,比如资产或数据的交换。
区块链分类如下。

  • 公链:无官方组织及管理机构,无中心服务器。参与的节点按照系统规则自由地接入网络,节点间基于共识机制开展工作。
  • 私链:建立在某个企业内部,系统运作规则根据企业要求进行设定,读写权限仅限于少数节点,但仍保留着区块链的真实性和部分去中心化特性。
  • 联盟链:若干个机构联合发起,介于公链和私链之间,兼容部分去中心化的特性。

本书基于国内优秀项目比原链(Bytom),为读者展开公链技术的完整实现。如果说比特币代表区块链1.0时代,以太坊拥有图灵完备性代表的是区块链2.0时代的话,比原链则基于UTXO模型支持了更丰富的功能(图灵完备的智能合约、多资产管理、Tensority新型的PoW共识算法等),其代表的是区块链2.5时代。比原链是一个开源项目,整个项目基于GO语言开发,代码托管于GitHub上(https://github.com/Bytom/bytom )。
本书基于比原链的1.0.5版本源码进行分析。读者不用纠结本书为何不使用比特币或以太坊作为示例,所谓“有道无术,术尚可求也,有术无道,止于术”,作者认为大部分区块链技术实现都是相似的。目前主要在共识算法(PoW、PoS)和模型(UTXO或Account模型)方面有所不同。比原链作为国内优秀的公链,代码量并不多,而且清晰的源码结构使得程序员和链圈爱好者的学习成本也不高。我们从中可以学到很多东西,如GO语言程序设计及应用、公链设计架构、公链运行原理等。
本章主要内容包括:

  • 比原链的总体架构。
  • 比原链架构内部各模块功能。
  • 比原链编译部署及应用。

1.2 公链总体架构

比原链(Bytom Blockchain或者Bytom)是一个开源的有智能合约功能的公共区块链平台。比原链公链设计架构如图1-1所示。

1.3 比原链各模块功能

我们将从图1-1所示的比原链总架构图中抽离出各个模块,逐一分析及阐述。

1.3.1 用户交互层

比原链的用户交互层如图1-2所示。
1. bytomcli客户端
bytomcli是用户与bytomd进程在命令行下建立通信的RPC客户端。在已经部署比原链的机器上,用户能够使用bytomcli可执行文件发起对比原链的多个管理请求。
bytomcli发送相应的请求,请求由bytomd进程接收并处理。bytomcli的一次完整生命周期结束。
2. bytom-dashboard
bytom-dashboard与bytomcli功能类似,都是发送请求与bytomd进程建立通信。用户可通过Web页面与bytomd进程进行更为友好的交互通信。
在已经部署比原链机器上,会默认开启bytom-dashboard功能,无须再手动部署bytom-dashboard。实际上通过传入的参数用户可以决定是否开启或关闭bytom-dashboard功能。如传入--web.closed,则可以关闭该功能。项目源码地址:https://github.com/Bytom/bytom-dashboard

image.png

image.png

1.3.2 接口层

比原链接口层架构如图1-3所示。

image.png

API Server是比原链中非常重要的一个功能,在比原链的架构中专门服务于bytomcli和dashboard,它的功能是接收、处理并响应与用户和矿池相关的请求。默认启动9888端口。API Server的总之主要功能如下:

  • 接收并处理用户或矿池发送的请求。
  • 管理交易,包括打包、签名、提交等接口操作。
  • 管理本地钱包接口。
  • 管理本地P2P节点信息接口。
  • 管理本地矿工挖矿操作接口等。

API Server服务过程中,在监听地址listener上接收bytomcli或bytom-dashboard的请求访问,对每一个请求,API Server均会创建一个新的goroutine来处理请求。首先,API Server读取请求内容,解析请求;其次,匹配相应的路由项;再次,调用路由项的Handler回调函数来处理;最后,Handler处理完请求之后给bytomcli响应该请求。

1.3.3 内核层

1. 区块和交易管理
内核层包括区块和交易管理、智能合约、虚拟机。
比原链内核层架构如图1-4所示。
内核层是比原链中最重要的功能,代码量大约占总量的54%。
区块链的基本结构是一个链表。链表由一个个区块串联组成。一个区块链中包含成千上万个区块,而一个区块内又包含一个或多个交易。在比原链内核层有一个重要的功能是对区块和交易进行管理。

image.png

当网络中的某个节点接收到一个新的有效区块时,节点会验证新区块。当新的区块并未在现有的主链中找到它的父区块,这个新区块会进入孤块管理中等待父区块。如果从现有的主链中找到了父区块,则将其加入到主链。
当网络中的某个节点接收到一笔交易时,节点会验证交易的合法性。验证成功后,该笔交易放入交易池等待矿工打包。一笔交易从发送到完成的整个生命周期需要经过如下过程:
1)A通过钱包向B发出一笔交易,交易金额为100比原币(BTM)。
2)该笔交易被广播到P2P网络中。
3)矿工收到交易信息,验证交易合法性。
4)打包交易,将多个交易组成一个新区块。
5)新区块加入到一个已经存在的区块链中。
6)交易完成,成为区块链的一部分。
2. 智能合约
从传统意义上来说,合约就是现实生活中的合同。区块链中的智能合约是一种旨在以数字化的方式让验证合约谈判或履行合约规则更加便捷的计算机协议。智能合约本质上是一段运行在虚拟机上的“程序代码”,可以在没有第三方信任机构的情况下执行可信交易。
智能合约具有两个特性:可追踪性和不可逆转性。
智能合约是比原链中最核心、也是最重要的部分。在后面章节中,我们会详细介绍智能合约模型(主流模型:UTXO模型、账户模型)、运行原理,以及BVM虚拟机工作机制。我们还将深入代码,了解区块链上智能合约如何在没有第三方信任机构的情况下进行可信交易。
3. 虚拟机
比原链虚拟机(Bytom Virtual Machine,BVM)是建立在区块链上的代码运行环境,其主要作用是处理比原链系统内的智能合约。BVM是比原链中非常重要的部分,在智能合约存储、执行和验证过程中担当着重要角色。
BVM用Equity语言来编写智能合约。比原链是一个点对点的网络,每一个节点都运行着BVM,并执行相同的指令。BVM是在沙盒中运行,和区块链主链完全分开。

1.3.4 钱包层

比原链钱包层架构如图1-5所示。

image.png

钱包可以类比于我们日常生活中的保险箱,我们关心保险箱的开门方式(密钥)和其中保存的财产(UTXO)。比原链钱包层主要负责保存密钥、管理地址、维护UTXO信息,并处理交易的生成、签名,对外提供钱包、交易相关的接口。
比原链的交易发送分为三步:
1)Build:根据交易的输入和输出,构造交易数据。
2)Sign:使用私钥对每个交易输入进行签名。
3)Submit:将交易提交到网络进行广播,等待打包。

1.3.5 共识层

比原链共识层架构如图1-6所示。

image.png

共识层用于实现全网数据的一致性,区块链是去中心化账本,需要全网对账本达成共识。共识层通过验证区块和交易,保证新的区块在所有节点上以相同的方式产生。简单说,共识机制就是通过某种方式竞争“记账权”,得到记账权的节点可以将自己生成的区块追加到现有区块链的尾部,其他节点可以根据相同的规则,验证并接受这些区块,丢弃那些无法通过验证的区块。
常见的共识机制有工作量证明(Proof-of-Work,PoW)、股权证明(Proof-of-Stake,PoS)等。
PoW共识机制利用复杂的数学难题作为共识机制,目前一般使用“hash函数的计算结果小于特定的值”。由于hash函数的特性,不可能通过函数值来反向计算自变量,所以必须用枚举的方式进行计算,直到找出符合要求的hash值。这一过程需要进行大量运算。PoW的复杂性保证了任何人都需要付出大量的运算来产生新的块,如果要篡改已有的区块,则需要付出的算力比网络上其他节点的总和都大。PoW优缺点对比如表1-1所示。

image.png

PoS是另一种共识机制,这种方式要求节点将一部分加密货币锁定,并根据数量和锁定的时长等因素来分配记账权。PoS一般不需要大量计算,所以比PoW更加迅速和高效。PoS优缺点对比如表1-2所示。

image.png

目前还有少量加密数字货币采用其他共识机制,但PoW和PoS是共识机制的主流。由于比原链的特性,结合比原链崇尚“计算即权力”(一种已确定的利益分配的方式。只要计算力高或拥有更多的算力,那就拥有了某些控制权)的主张,需要在多节点上达成较强的共识,对全局一致性、去中心化要求较高,需要在一定程度上牺牲效率,所以比原链选择了PoW作为公链的共识机制。

1.3.6 数据存储层

比原链数据存储层架构如图1-7所示。

image.png

比原链在数据存储层上存储所有链上地址、资产交易等信息。数据存储层分为两部分;第一部分为缓存,大部分查询首先从缓存中进行,以减少对磁盘的IO压力;第二部分为持久化存储,当缓存中查询不到数据时,转而从持久化存储中读取,并添加一份到缓存中。
比原链默认使用LevelDB数据库作为持久化存储。LevelDB是Google开发的非常高效的链值数据库。LevelDB是单进程服务,不能同时有多个进程对一个数据库进行读写,同一时间只能有一个进程或一个进程以多并发的方式进行读写。
默认情况下,数据存储在--home参数下的data目录。以Darwin(即MacOS)平台为例,默认数据存储在$HOME/Library/Bytom/data。
数据库包括:

  • accesstoken.db:存储token信息(钱包访问控制权限)。
  • core.db:存储核心数据库。存储主链相关数据,包括块信息、交易信息、资产信息等。
  • discover.db:存储分布式网络中端到端的节点信息。
  • trusthistory.db:存储分布式网络中端到端的恶意节点信息。
  • txfeeds.db:存储目前比原链代码版本未使用该功能,暂不介绍。
  • wallet.db:存储本地钱包数据库。存储用户、资产、交易、UTXO等信息。

1.3.7 P2P分布式网络

比原链分布式网络层的架构如图1-8所示。

image.png

比原链作为一个去中心化的分布式系统,其底层个体间的通信机制对整个系统的稳定运行十分重要。个体间的数据同步、状态更新都依赖于整个网络中每个个体之间的通信机制。比原链的网络通信基于P2P通信协议,又根据自身业务的特殊性做了特别的设计。比原链的P2P分布式网络,主要分为四大部分:节点发现、区块同步、交易同步和快速广播。
1. 节点发现
P2P节点发现主要解决新加入网络的节点如何连接到区块链网络中。新加入的节点能够快速地被网络中其他的节点感知;同时节点自己也能够获得其他节点的信息,与其通信交换数据。比原链中的节点发现使用的是Kademlia算法实现的节点发现机制。Kademlia算法实现是一个结构化的P2P覆盖网络,每个节点都有一个全网唯一的标识,称为Node ID。Node ID被分散地存储在各个节点上。Kademlia将发现的节点存储到k桶(k-bucket)中,每个节点只连接距离自己最近的n个节点。以此形成的网络拓扑结构如下图1-9所示。

image.png

2. 区块同步
区块链是一种去中心化的分布式记账系统,全节点需要保存完整的区块信息。当一个节点加入到网络之后,需要做的第一件事情就是同步区块,构建完整的区块链。新加入的节点需要与网络中其他节点同步,从高度为1的区块开始到当前全网的最高高度,这样才能构建成一条完整的区块链。
节点启用快速功能时,同步节点每次最多能够同步1~128个区块(当前高度到下一个checkpoint高度的区块)信息。除了快速同步算法之外,还有普通同步算法。节点主要使用普通同步算法同步网络中较新的区块信息。普通同步算法主要为了保证节点中的区块信息不落后,能够及时同步新挖掘的区块。
普通同步和快速同步的区别是快速同步使用get-headers批量获取区块,使用checkpoint的验证来避免PoW工作量验证,从而能极大提高速度;普通同步一次只能获取一个区块。
快速同步和普通同步可以解决不同场景的需求。快速同步使节点能够快速地重建区块链信息,快速地加入到网络中,这是通过新块广播实现的。在不满足快速同步条件时,则用普通同步,每次同步时请求一个区块。
3. 交易同步
比原链网络为了保证交易的安全,每一笔交易达成后,节点需要将交易信息同步到网络中其他的节点,这个过程称作交易同步。交易同步验证的目的是保证安全性,当交易同步到网络中的其他的节点时,节点会验证交易是否合法,只有当交易合法,节点才会将交易写入自己的交易池中。另一方面,同步交易可以将交易同步到更多的节点,交易可以更快地被打包到区块中。
4. 快速广播
为了保证交易信息能够及时被确认和提交到主链上,比原链提供了快速广播。对于接收到的新区块和新交易信息,网络中的节点会快速广播到当前节点已知的其他节点。

1.4 编译部署及应用

比原链的安装方式有多种。本书从源码分析的角度带领读者了解架构,所以使用源码编译的方式来介绍安装过程。
1. 源码编译部署
1)下载源码:
$ git clone https://github.com/Bytom/bytom.git $GOPATH/src/github.com/bytom
2)切换至1.0.5版本:
$ cd $GOPATH/src/github.com/bytom
$ git fetch origin v1.0.5
$ git checkout v1.0.5
3)编译源码:
$ make bytomd
$ make bytomcli
4)初始化:
$ cd ./cmd/bytomd
$ ./bytomd init --chain_id mainnet
目前比原链支持三种网络,使用chain_id进行区分,如下所示:

  • mainnet:主网。
  • testnet:也称wisdom,测试网。
  • solonet:单机模式。

5)启动bytomd进程:
$ ./bytomd node

$ ps -ef|grep bytomd
501 52318 449 0 2:00PM ttys000 0:00.85 ./bytomd node

$ ./bytomcli net-info
{
"current_block": 36714,
"highest_block": 36714,
"listening": true,
"mining": false,
"network_id": "wisdom",
"peer_count": 10,
"syncing": false,
"version": "1.0.5+2bc2396a"
}
当我们执行ps -ef命令看到bytomd进程时,说明进程已经处于运行状态。使用bytomcli获取节点状态信息,可以看到我们已经成功地运行了bytomd进程。
bytomd进程第一次启动后,默认不会开启挖矿功能。此时会从P2P网络种子节点中获取与之相邻的peer节点,建立握手连接并同步区块。我们将在第10章深入分析P2P网络底层工作原理。
2. 源码目录结构
比原链的源码目录如下所示:
$ tree -L 1
.
├── accesstoken Token管理
├── account 账户管理
├── api API Server接口管理
├── asset 资产管理
├── blockchain 交易打包、签名、查询等
├── cmd main入口文件
├── common 公共库
├── config 节点配置文件
├── consensus 共识相关模块
├── crypto 加密库
├── dashboard dashboard页面管理
├── database 数据库管理
├── docs 文档
├── encoding 协议相关的编解码库
├── env 环境变量管理
├── equity 智能合约语言编译器
├── errors 错误及异常管理
├── math 数学计算相关库
├── metrics metrics指标库,用于采集API Server请求相关指标
├── mining 挖矿模块
├── net API Server使用的HTTP基础库
├── netsync 网络同步管理
├── node 当前节点管理模块,环境初始化等
├── p2p 分布式网络管理模块
├── protocol 核心数据结构,包含块、交易、bvm虚拟机等
├── test 单元测试
├── testutil 单元测试工具包
├── util 工具包
├── vendor 第三方库
├── version 版本
└── wallet 钱包管理
3.开启挖矿模式
开启挖矿模式的命令如下:
$ ./bytomcli set-mining true
在默认情况下比原链的挖矿模式是关闭状态。开启挖矿模式有两种方式,第一种方式,使用bytomcli命令行交互,将mining参数设置为true,此时bytomcli会通过RPC协议与bytomd进程交互并启用挖矿模式。关闭挖矿模式则指定set-mining参数为false。第二种方式,使用dashboard页面启用挖矿参数,在这里请读者自行学习dashboard。
4.其他语言SDK简介
比原链技术社区提供了不同语言的SDK,如下所示:
PHP SDK:https://github.com/lxlxw/bytom-php-sdk
Java SDK:https://github.com/chainworld/java-bytom
Java SDK:https://github.com/successli/Bytom-Java-SDK
Python SDK:https://github.com/Bytom-Community/python-bytom
Node SDK:https://github.com/Bytom/node-sdk

1.5 本章小结

本章对比原链的总体架构分层进行了分析,通过比原链的总架构图可以看出一条完整公链的技术架构。然后通过安装部署,介绍了比原链的基础知识。
通过对公链架构的学习,可以从顶层宏观角度对公链设计、功能与价值等诸多方面进行全面了解。

相关文章
|
16小时前
|
存储 编译器 Go
Go语言学习12-数据的使用
【5月更文挑战第5天】本篇 Huazie 向大家介绍 Go 语言数据的使用,包含赋值语句、常量与变量、可比性与有序性
17 6
Go语言学习12-数据的使用
|
2天前
|
Java Go
一文带你速通go语言指针
Go语言指针入门指南:简述指针用于提升效率,通过地址操作变量。文章作者sharkChili是Java/CSDN专家,维护Java Guide项目。文中介绍指针声明、取值,展示如何通过指针修改变量值及在函数中的应用。通过实例解析如何使用指针优化函数,以实现对原变量的直接修改。作者还邀请读者加入交流群深入探讨,并鼓励关注其公众号“写代码的SharkChili”。
9 0
|
2天前
|
存储 缓存 Java
来聊聊go语言的hashMap
本文介绍了Go语言中的`map`与Java的不同设计思想。作者`sharkChili`是一名Java和Go开发者,同时也是CSDN博客专家及JavaGuide项目的维护者。文章探讨了Go语言`map`的数据结构,包括`count`、`buckets指针`和`bmap`,解释了键值对的存储方式,如何利用内存对齐优化空间使用,并展示了`map`的初始化、插入键值对以及查找数据的源码过程。此外,作者还分享了如何通过汇编查看`map`操作,并鼓励读者深入研究Go的哈希冲突解决和源码。最后,作者提供了一个交流群,供读者讨论相关话题。
9 0
|
3天前
|
Java Go
Go语言学习11-数据初始化
【5月更文挑战第3天】本篇带大家通过内建函数 new 和 make 了解Go语言的数据初始化过程
17 1
Go语言学习11-数据初始化
|
3天前
|
自然语言处理 安全 Java
速通Go语言编译过程
Go语言编译过程详解:从词法分析(生成token)到句法分析(构建语法树),再到语义分析(类型检查、推断、匹配及函数内联)、生成中间码(SSA)和汇编码。最后,通过链接生成可执行文件。作者sharkchili,CSDN Java博客专家,分享技术细节,邀请读者加入交流群。
21 2
|
3天前
|
Java Linux Go
一文带你速通Go语言基础语法
本文是关于Go语言的入门介绍,作者因其简洁高效的特性对Go语言情有独钟。文章首先概述了Go语言的优势,包括快速上手、并发编程简单、设计简洁且功能强大,以及丰富的标准库。接着,文章通过示例展示了如何编写和运行Go代码,包括声明包、导入包和输出语句。此外,还介绍了Go的语法基础,如变量类型(数字、字符串、布尔和复数)、变量赋值、类型转换和默认值。文章还涉及条件分支(if和switch)和循环结构(for)。最后,简要提到了Go函数的定义和多返回值特性,以及一些常见的Go命令。作者计划在后续文章中进一步探讨Go语言的其他方面。
10 0
|
4天前
|
JavaScript 前端开发 Go
Go语言的入门学习
【4月更文挑战第7天】Go语言,通常称为Golang,是由Google设计并开发的一种编程语言,它于2009年公开发布。Go的设计团队主要包括Robert Griesemer、Rob Pike和Ken Thompson,这三位都是计算机科学和软件工程领域的杰出人物。
12 1
|
5天前
|
Go
|
5天前
|
分布式计算 Java Go
Golang深入浅出之-Go语言中的分布式计算框架Apache Beam
【5月更文挑战第6天】Apache Beam是一个统一的编程模型,适用于批处理和流处理,主要支持Java和Python,但也提供实验性的Go SDK。Go SDK的基本概念包括`PTransform`、`PCollection`和`Pipeline`。在使用中,需注意类型转换、窗口和触发器配置、资源管理和错误处理。尽管Go SDK文档有限,生态系统尚不成熟,且性能可能不高,但它仍为分布式计算提供了可移植的解决方案。通过理解和掌握Beam模型,开发者能编写高效的数据处理程序。
134 1
|
5天前
|
算法 关系型数据库 MySQL
Go语言中的分布式ID生成器设计与实现
【5月更文挑战第6天】本文探讨了Go语言在分布式系统中生成全局唯一ID的策略,包括Twitter的Snowflake算法、UUID和MySQL自增ID。Snowflake算法通过时间戳、节点ID和序列号生成ID,Go实现中需处理时间回拨问题。UUID保证全局唯一,但长度较长。MySQL自增ID依赖数据库,可能造成性能瓶颈。选择策略时需考虑业务需求和并发、时间同步等挑战,以确保系统稳定可靠。
113 0