主页 > imtoken钱包ios下载 > EOS入门指南PART6——开发不忙,来看看智能合约数据是如何存储的

EOS入门指南PART6——开发不忙,来看看智能合约数据是如何存储的

imtoken钱包ios下载 2023-04-16 06:01:54

在上一章我们学习了在开发智能合约之前需要了解的必要概念:

如果智能合约开发是一个锁着门的图书馆,那么之前的学习就是关键。 现在我们终于可以用钥匙打开门,走进去一探究竟了。

概括

说到智能合约开发,大家首先想到的就是像solidity开发一样写代码,教语法。 EOS智能合约是用C++写的,基本语法可以买一本C++的书; 本文主要介绍EOS智能合约的数据存储,为大家扫清智能合约开发道路上的最后一道障碍。

什么是内存

我们在学习如何在主网创建账户的时候,接触到了RAM的概念。 我们不能像操作以太坊那样凭空生成一个地址作为自己的账户,而是需要先有一个账户,然后再创建一个账户。 涉及到RAM的一个关键知识点:创建账号需要消耗RAM。

那时候我们只是模模糊糊知道RAM大概就是内存的意思。

RAM 用于将数据存储在内存数据库中。 DApps 将使用它来存储状态信息,以便它们的应用程序可以快速使用这些信息。

RAM是EOS主网中的内存,用于存储用户在EOS中经常使用的数据(账户余额、合约状态等)。

BM对EOS的期望是成为区块链世界的【操作系统】,所以计算机的一些概念可以类比为EOS,计算机中的运行内存可以看作是EOS中的RAM; 和硬盘您可以对 EOS 区块链数据库进行基准测试。

因此,高访问的决策数据,如账户余额、智能合约的当前状态等,都会存储在RAM中,这部分数据会长期占用RAM; 而低访问的决策证据数据,如交易数据,将存储在EOS系统的硬盘中,即区块链中。 当存储账户状态的空间不足时,即内存不足时,无法进行转账或部署合约等相关操作。

什么是 EOS 数据库

以太坊账户存储了哪些数据_sitechainnews.com 以太坊挖矿数据_以太坊钱包如何设置子账户

我们之前介绍过transaction和action。 动作是智能合约执行的基本单元。 事务可以被认为是一个由一个或多个动作组成的原子操作。 动作在称为动作上下文的环境中执行。 动作上下文提供了执行动作所需的一些条件。 其中之一是动作的工作记忆,这是动作保存工作状态的地方。 在处理一个action之前,eosio会先为它清理内存,所以当一个变量在一个action中被赋值时,另一个action的context是无法获取到这个值的。 那么在动作之间传递状态的唯一方法就是将其持久化存储在 EOS 数据库中,如下所示:

EOS入门指南PART6——别忙着开发,先来看看智能合约数据是怎么存的

这个持久化存储就是存储数据的数据库。 EOS 允许智能合约定义自己的私有数据库表。 比如上图中Apply Context的内容是一次性的。 一旦一个动作被执行,该对象将被释放,只有存储在 EOSIO 数据库中的才会被保存。

什么是 multi_index

紧接着上面介绍的数据库,就是通过multi_index来访问和交互这张私有数据表。 EOS的multi_index类似于boost的multi_index,是一个多索引容器。 通过多级索引,智能合约具有类似于数据库模块的功能。

multi_index 是一个非常方便的容器,可以和数据库进行交互。

从字面上看,multi_index就是可以使用多个索引的数据表。

如下所示:

EOS入门指南PART6——别忙着开发,先来看看智能合约数据是怎么存的

每个multi_index容器可以理解为传统数据库中的一张表,只是行和列略有不同。 与传统的多列表不同,multi_index 只有一列。 这一列的每一行代表一个对象,通常对象是struct或class类型,有多个成员变量。 因此,虽然只有一列,但multi_index的灵活性不亚于传统数据表。

以太坊钱包如何设置子账户_sitechainnews.com 以太坊挖矿数据_以太坊账户存储了哪些数据

例如,采用以下结构:

// @abi table proposal i64
struct Proposal {
  uint64_t id;
  account_name owner = 0;
  string description;
  std::vector votes;
  uint64_t primary_key() const { return id; }

以太坊钱包如何设置子账户_以太坊账户存储了哪些数据_sitechainnews.com 以太坊挖矿数据

EOSLIB_SERIALIZE( Proposal, (id)(owner)(description)(votes)) }; typedef eosio::multi_index proposals;

先看第一行:

// @abi table proposal i64

在部署合约之前,我们会使用eosiocpp生成ABI,EOS智能合约编译器可以读取struct结构和公共方法前的注解。 在注解中,我们可以传入两种类型:action和table,ABI会根据我们的语句自动在生成的ABI中添加相应的方法或table定义。

第二个proposal是表名,第三个i64是表主键的类型。 这里的主键是id。

帐户名称

sitechainnews.com 以太坊挖矿数据_以太坊账户存储了哪些数据_以太坊钱包如何设置子账户

注意第二个成员变量owner:

account_name owner = 0;

这里的account_name是EOS自己定义的类型,也就是我们之前创建的账户名。 可以理解为以太坊中的地址类型。

向量

std::vector votes;

这里的Vector可以理解为以太坊中的映射——一个自定义的映射集合。

主键

uint64_t primary_key() const { return id; }

eosio::multi_index 规定每一行必须有一个类型为64位无符号整数的主键。 表中的对象按照主键升序或降序排序。 通过在结构中定义 primary_key() 方法来获取它。 在这个例子中,提案的主键是 id,它是 uint64_t 类型。 当然主键的类型也可以是account_name等。 (account_name在eos中存储为uint64_int类型)。

数据序列化

sitechainnews.com 以太坊挖矿数据_以太坊账户存储了哪些数据_以太坊钱包如何设置子账户

EOSLIB_SERIALIZE( Proposal, (id)(owner)(description)(votes))

通过阅读contracts/eosiolib/serialize.hpp文件以太坊账户存储了哪些数据,可以知道它实际上使用了BOOST_PP_SEQ_FOR_EACH宏。 它的作用基本上就是给struct附加操作,可以将数据序列化到multi_index或者从multi_index反序列化。

multi_index相关操作

multi_index虽然没有SQL语句那么丰富,但还是提供了一些基本的操作:

一个示例查询:

auto itr = proposals.find(proposal_id)

上面的语句查询一个特定id的proposal以太坊账户存储了哪些数据,它返回一个iterator迭代器。 这就涉及到我们如何使用表中的数据了,答案就是迭代器。

EOS入门指南PART6——别忙着开发,先来看看智能合约数据是怎么存的

迭代器可以想象成一个电梯,在整个数据表中上下滑动(定位数据),任何对数据的操作都必须经过迭代器。

结论

本章虽然概念很多,但值得仔细研究。 在本章中,我们学习了:

这一章理论内容比较多,理解起来可能没有前几章那么直观。 在下一篇文章中,我们将学习如何操作multi_index,带大家更深入的了解multi_index,正式开启我们的智能合约开发之旅。