【跟着源码学】EOS智能合约之eosio.system - part1

本系列仍是着眼于了解EOS的设计理念,力求在繁杂的版本变动,以及各类区块链技术文章当中,根据源码整理出一个清晰简明的eos实现,而暂时不着眼研究C++工程开发的奇淫巧技,主要是由于还须要时(目)间(前)继(领)续(悟)修(不)炼(到)。git

正文

clipboard.png

代码连接github

这个multi_index是什么呢?

在eoslib目录下有multi_index.hpp,天然而然的来看看这里面有什么线索。数据库

这里,找到了以下解释:api

  • EOSIO Multi-Index API provides a C++ interface to the EOSIO database. It is patterned after Boost Multi Index Container.
  • EOSIO Multi-Index table requires exactly a uint64_t primary key. For the table to be able to retrieve the primary key,
  • the object stored inside the table is required to have a const member function called primary_key() that returns uint64_t.
  • EOSIO Multi-Index table also supports up to 16 secondary indices. The type of the secondary indices could be any of:
    • uint64_t
    • uint128_t
    • uint256_t
    • double
    • long double

原来multi_index是跟EOSIO数据库相关的API。相对应的,官方开发者文档有DB API的描述,简要解释一下使用场景:数据结构

好比开发一个游戏DApp,用户有本身的Action(很难翻译,能够理解为执行一个函数,好比randint(6),模拟了一次掷骰子,返回结果从1至6)操做, 该游戏智能合约要记录每位用户游戏Actions,本次合约执行完毕后数据不能丢失,就须要将数据存储到 EOS 数据库中。架构

Action在被称为Action执行上下文的环境中运做。以下图所示,dom

clipboard.png

Action上下文提供执行Action所需的几件事情。
其中一件事是Action的工做内存。这是Action执行的地方。在处理一个Action以前,EOSIO为该Action进行一次内存清理工做。在新Action的上下文中当另外一个Action执行时可能已经被设置的变量不可用。在Action中传递状态的惟一方法是将其持久存储并从EOSIO数据库中检索。ide

声明

看到这里,感受引入概念愈来愈多,暂时先搬运了一些现成资料(见参考),再后续学习中慢慢消化。函数

这里提到了eosio::multi_index table借鉴了Boost库中的multi_index容器(Boost库中的mult_index)。能够在概念上看做传统数据库中的表格,其中行是容器中的单个对象,列是容器中对象的成员属性,而且索引经过与一个键兼容的键提供对对象的快速查找 对象成员属性。工具

传统的数据库表容许索引成为表中某些列数的用户定义函数。eosio::multi_index一样容许索引是任何用户定义的函数。但其返回值仅限于受支持的一组受限密钥类型之一。

传统数据库表一般有一个惟一的主键,它容许明确标识表中的特定行,并为表中的行提供标准排序顺序。eosio::multi_index支持相似的语义,可是该对象的主键在eosio::multi_index容器必须是惟一的无符号64位整数。eosio::multi_index中的对象容器按主键索引按无符号64位整数主键的升序排序。

智能合约没法直接操做存储在硬盘中的数据表,而是须要使用multi_index做为中间工具(或者叫容器),每一个multi_index实例都与一个特定帐户的特定数据表进行交互(取决于实例化时的参数)。EOS智能合约与EOS数据库的数据交互以下图所示。

clipboard.png

每个multi_index都至关于传统数据库的一个数据表(table),但将传统数据库的行与列的形式改成了单纯的列。也就是说multi_index是一个线性排列的表,只有一列,每一行都只存储一个对象。可是通常来讲multi_index存储的对象都是结构体或者类,里面含有多个成员变量,因此multi_index存储数据的灵活性也是不亚于传统数据库的。

咱们使用官方的“汽车维修店”示例,咱们创建一个数据表,储存每一个汽车维修店客户的帐户名、保养时间、车辆里程。那么multi_index数据表储存的项目中,每一个都是以下的结构体:

struct service_rec {
    uint64_t        pkey;           // 主键
    account_name    customer;       // 车主用户名
    uint32_t        service_date;   // 维修保养时间
    uint32_t        odometer;       // 车辆里程
}

在传统数据库中,须要创建一个 4 列的数据表,用来储存每一个用户的这个 4 个数据,而multi_index的每一个数据表只有一列,只存储每一个用户的 service_rec 整个结构体便可。下图为multi_index数据结构。

clipboard.png

多索引迭代器(multi_index iterator),与仅提供键值(key-value)存储的其余区块链不一样,EOSIO Multi-Index表容许合约开发人员保存按照各类不一样键类型排序的对象集合,这些键类型能够从对象内的数据派生。这使得丰富的检索功能。最多能够定义16个二级索引,每一个索引都有本身的排序和检索表格内容的方式。

EOSIO多索引迭代器遵循C++迭代器通用的模式。全部迭代器都是双向常量,能够是const_iterator或const_reverse_iterator。迭代器能够取消引用以提供对多索引表中的对象的访问。

在 EOS 数据库中,能够将迭代器比喻为一个“电梯”,在整个数据表中上下穿梭。全部对数据的操做必须经过迭代器完成。典型的数据修改过程是这样的:首先使用迭代器的find()方法,在特定的索引中寻找须要的数据,好比在车主用户名索引中寻找某个用户。迭代器会移动到须要的数据对象上。而后就可使用迭代器的modify()方法修改当前迭代器对应的数据。下图为迭代器指向用户 Sue 的状况。

clipboard.png

参考

EOS多索引表
EOS 数据库与持久化 API —— 架构

相关文章
相关标签/搜索