BCOS源码学习(一)基础概念

本文主要介绍了BCOS区块链的基础概念,包括哈希、RLP编码、账户、MPT(默克尔-帕特里夏树)以及JSON。哈希在BCOS中起到全局唯一标识的作用;RLP编码是一种可逆的字节数组编码方式;账户分为外部账户和合约账户,由Account类表示;MPT是BCOS中存储数据的关键,结合了默克尔树和紧凑前缀树的优点;JSON则作为一种数据交换格式在BCOS中使用。

本篇主要是扫盲,解决一些基础概念问题,对以太坊或者BCOS有了解的可以直接略过,BCOS是在以太坊的基础上修改而来。

一:哈希

哈希是BCOS中最重要的概念,通过给定的哈希算法h=h(x)可以将一个得到一个哈希值h,该输入是不可逆的,哈希在数学上是唯一的,因此它可以作为某个对象的全局唯一标识符,因此如果我们将一个哈希值和它对应的对象以[k,v]的形式保存在键值对中,可以很方便的索引到所需要的对象;哈希的另外一个特点是不可逆的,即不能通过h反推出它的对象x的值。
在BCOS中,哈希函数的实现在\libdevcore\SHA3.cpp中,我们不关心它的具体实现,它计算哈希的函数就是简单的sha3(),返回一个h256类型的值。
需要关注的是和哈希有关的几个数据类型,即以h开头的如h2048,、h1024等等,这是BCOS里专门为哈希散列值准备的容器,在\libdevcore\FixedHash中实现,FixedHash类重载了相应的操作符,我们可以像使用内置类型一样使用h+数字的这类型的结构;这些结构的意义也很容易了解,如h64就是指64位的哈希散列值,这里的数字代表二进制数目,而不是字节数,这点要注意;该类还提供了哈希类型(h+数字)的vector容器和set容器。
在之后我们会经常遇到Address这个数据类型,它代表BCOS当中的地址,只要时刻记得它就是一个h160就可以了。

二:RLP编码

RLP也是BCOS中极为基础和重要的机制,其定义可以参见以太坊的RLP
这种编码格式可以将任意嵌套的字节数组变成一个无嵌套的字节数组bytes,它可以线性的表示任意数据,另外该编码方式是可逆的。需要指出BCOS中,大多数情况下,数据都是编码成RLP之后才进行保存或者哈希的。
这里需要注意一个数据类型byte,在libdevcore\common.h中定义,它是一个uint8_t就是一个字节,该文件还定义了bytes,它实际上是一个vector<byte>。跑一下题,这个文件中还定义了许多名字,其中最为重要的是u+数字的类型如u128、u64等,这里的数字表示的也是位而不是字节,u代表的是无符号,以后我们会经常遇到这个类型。还有一个重要的数据类型vector_ref,定义在\libdevcore\vector_ref中,该类可以当成一个vector来用。
回到RLP,RLP的实现在\libdevcore\RLP,里面比较重要的俩个类是RLP类和RLPStream类,RLP类用来读取RLP格式的字节数组,RLPStream则提供了重要的函数append,该函数可以将给定的数据追加到字节流,该函数的重载版本几乎覆盖可能涉及的需要写入流中的数据类型,也就是说这俩个类,一个负责生产RLP字节流,一个负责读RLP字节格式;RLP类为自己提供了一个迭代器,我们可以像使用容器一样使用RLP。
RLP既然是双向的,那么RLP数据也一定可以还原成原始数据;该类重载了相应的操作符,最重要的是提供了允许数据的转换的方式,如explicit operator std::string() const { return toString(); },就允许将RLP格式的数据转换成字符串。图中所示的bytesConstRef实际上就是一个vector_ref<byte const>
其实我们可以不必关注其实现细节,直接把它当做内置类型使用就可以了。

这里写图片描述

三:账户

BCOS中账户是极为关键的概念,账户分为俩类:一类是外部账户,外部账户代表着外部代理人的,如节点,机构等;一类是合约账户,合约账户就是指合约。实际上这俩类账户对于BCOS来说是讲的是一个东西,它们指的都是Account类,该类在\libethereum\Account中实现。可以将账户理解成一个状态的集合。
账户主要包含几个重要的成员:

    u256 m_nonce;//随机数
    u256 m_balance = 0;//余额
    bytes m_codeCache;//合约代码的缓存
    h256 m_storageRoot = EmptyTrie; //存储
    std::unordered_map<u256, u256> m_storageOverlay;
    h256 m_codeHash = EmptySHA3;//合约代码的哈希值

其中由于BCOS抛弃了代币的概念,所以余额的这个字段在这里无用;随机数是对账户状态的一个计数器,保证每一笔交易只能被处理一次,如果账户是一个外部账户,那么随机数代表的就是此账户地址发送的交易的序号,如果是一个合约账户,该数字代表的就是创建合约的序号;合约代码缓存是指如果该账户是合约账户则合约的代码就保存在这里,存储那一部分中m_storageRoot而是一个MPT树的树根,m_storageOverlay键值对才是真正保存账户状态的地方,需要注意的是,树根将被保存在一个状态数据库中,如果我们想要找到这个账户的状态,需要从状态数据库中读取树根,顺着MPT树来找。
在这里需要解释的多一点,当我们通过状态树,找到了某个账户的m_storageRoot。并不意味着我们就找到了该账户保存的数据了,m_storageRoot本身就是一颗树,想要都该账户里保存的数据,还要通过m_storageRoot这颗树再去寻找,至于状态树,那是下一章的内容了~

四:MPT

MPT(Merkle-PatriciaTrie)贯穿了整个BCOS。BCOS中的MPT树,我更愿意将其理解为一种[k,v]的实现方法,我们知道在BCOS中大多数的数据都是以键值对的方式存储的,比如说我们想要找到一个账户,那么我们需要知道该账户的地址,这就是键,与其对应的账户内容,就是值。在有很多个地址的情况下,怎么快速找到我们要的那个地址,进而得到它对应的值,最笨的方法是挨个遍历。BCOS采用的方法是用MPT,它既是默克尔树也是紧凑前缀树,在\libdevcore\Triexxx中实现了这个结构,当我们在介绍BCOS具体的区块数据组织形式时可能会与它打交道,这里先不管。
先来说什么是前缀树,如图:
这里写图片描述
这就是前缀树,每个节点所携带的数据由该节点的位置来体现,子节点共享父节点的前缀,在图中键标注在节点中,值标注在节点下,在计算机中以键值对的方式保存,如[ab,I]就表示键为ab而值为I,图中的要保存的数据是I am Tire !。
紧凑前缀树是对前缀树的改进,如果一个节点有唯一的子节点,那么就与父节点合并,上图基于紧凑前缀树的表示如图:
这里写图片描述
默克尔树,又被称为哈希树,它的特点是树中保存的键值对的键是数据块的哈希值,其中叶子节点直接对应要保存的数据块的哈希值,而非叶子节点则保存的是其子节点的串联字符串的哈希值,I am Tire !用默克尔树的表示如下图:

### 如何交叉编译 BCOS 源码 BCOS个由中国自主研发的联盟链框架,支持图灵完备的智能合约[^2]。交叉编译是指在个平台上生成可以在另个平台上运行的代码的过程。对于 BCOS 的交叉编译,通常涉及以下几个方面:目标平台架构、依赖库的交叉编译以及构建工具链的配置。 以下是个典型的交叉编译流程,适用于大多数基于 Linux 的目标平台: #### 1. 环境准备 确保主机系统已经安装了必要的交叉编译工具链和依赖项。例如,如果目标平台是 ARM 架构,可以使用 `arm-linux-gnueabi` 或 `aarch64-linux-gnu` 工具链。 ```bash sudo apt-get update sudo apt-get install -y build-essential cmake git ``` 下载并配置交叉编译工具链。例如,可以从 Linaro 官方网站获取最新的 ARM 工具链,并将其路径添加到环境变量中: ```bash export PATH=/path/to/toolchain/bin:$PATH ``` #### 2. 获取 BCOS 源码 从官方仓库克隆 BCOS 源码: ```bash git clone https://github.com/FISCO-BCOS/FISCO-BCOS.git cd FISCO-BCOS git checkout tags/v3.x.x # 替换为具体版本号 ``` #### 3. 配置 CMake 工具链文件 创建个工具链文件(如 `toolchain.cmake`),用于指定交叉编译器和目标平台: ```cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) # 设置交叉编译器 set(CMAKE_C_COMPILER /path/to/toolchain/bin/arm-linux-gnueabihf-gcc) set(CMAKE_CXX_COMPILER /path/to/toolchain/bin/arm-linux-gnueabihf-g++) # 设置目标平台的 sysroot set(CMAKE_FIND_ROOT_PATH /path/to/toolchain/sysroot) # 调整查找规则 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) ``` #### 4. 构建 BCOS 使用 CMake 和工具链文件进行交叉编译: ```bash mkdir build && cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake make -j$(nproc) ``` 这将生成适合目标平台的可执行文件。 #### 5. 处理依赖项 BCOS 可能依赖于些第三方库(如 OpenSSL、Boost 等)。这些库也需要进行交叉编译,并确保其路径被正确包含在 CMake 配置中。 例如,交叉编译 OpenSSL: ```bash ./config --prefix=/path/to/output --openssldir=/path/to/ssl shared no-asm --cross-compile-prefix=arm-linux-gnueabihf- make -j$(nproc) make install ``` 然后,在 CMake 配置中指定这些库的路径: ```cmake set(OPENSSL_ROOT_DIR /path/to/output) find_package(OpenSSL REQUIRED) ``` #### 6. 测试生成的二进制文件 将生成的二进制文件复制到目标设备上,并验证其是否能够正常运行。 --- ### 注意事项 - 确保交叉编译工具链与目标平台匹配,否则可能导致二进制文件无法运行。 - 如果 BCOS 使用了特定的加密算法或共识协议,可能需要额外的依赖项或补丁[^1]。 - 在某些情况下,可能需要修改源码以适应目标平台的特性。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值