EOS开发中区块链数据持久性(上)

本教程假定你已经完成了EOS开发从智能合约开始c++

要了解数据持久性,请编写一个简单的智能合约,做为地址记录。虽然这个用例因为各类缘由而不太适合做为生产智能合约,但开始学习数据持久性如何在EOSIO上运行而不被与eosio的multi_index功能无关的业务逻辑分心,这也算的上一个很好的合约。shell

第1步:建立一个新目录

以前,你建立了一个合约目录,如今就在那里开始。编程

//shell
cd CONTRACTS_DIR

为咱们的合约建立一个新目录并进入目录:api

//c++
mkdir addressbook
cd addressbook

第2步:建立并打开一个新文件

//c++
touch addressbook.cpp

在你喜欢的编辑器中打开文件。安全

第3步:编写扩展标准类并包含EOSIO

在以前的教程中,你建立了一个hello world合约,并学习了基础知识。你将熟悉下面的结构,该类已分别命名为addressbook数据结构

//c++

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
using namespace eosio;

class addressbook : public eosio::contract {
  public:
       
  private: 
  
};

第4步:为表建立数据结构

在配置和实例化表以前,须要编写表示地址簿数据结构的结构。 将此视为“schema”。 因为它是一个地址簿,该表将包含人,所以建立一个名为“person”的struct架构

//c++
struct person {};

定义multi_index表的模式时,须要使用惟一值做为主键。编辑器

对于此合约,请使用类型为account_name的名为“key”的字段。此合约将为每一个用户提供一个惟一条目,所以该密钥将是基于用户的account_name保证一致性且有惟一值。函数

//c++
struct person {
	account_name key; 
};

因为该合约是地址簿,所以可能应该为每一个条目或人员存储一些相关的详细信息。工具

//c++
struct person {
 account_name key;
 string first_name;
 string last_name;
 string street;
 string city;
 string state;
};

ok。基本schema架构现已完成。接下来,定义一个primary_key方法,该方法将由multi_index迭代器使用。每一个multi_index架构都须要一个主键。要实现此目的,只需建立一个名为primary_key()的方法,并返回一个值,在本例中为结构中定义的成员key

//c++
struct person {
 account_name key;
 string first_name;
 string last_name;
 string street;
 string city;
 string state;
 
 uint64_t primary_key() const { return key; }
};

步骤5:配置多索引表

如今已经使用结构定义了表的模式,咱们须要配置表。须要对eosio::multi_index构造函数进行命名和配置,以使用咱们以前定义的结构。

//c++
typedef eosio::multi_index<N(people), person> address_index;
  • 咱们把N(N(base32 X),用于从X的base32编码的字符串解释生成编译时uint64_t)命名为表。该表包含许多不一样的个体“persons”,所以将表命名为“people”。
  • 传入上一步中定义的单person结构
  • 声明此表的类型。此类型将用于稍后实例化此表。
//c++
//configure the table
typedef eosio::multi_index<N(people), person> address_index;

使用上述multi_index配置,有一个名为peoplemulti_index表,该表基于使用struct person的该表的单个行的模式或数据结构。

到目前为止,咱们的文件应该是这样的。

//c++

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

using namespace eosio;

class addressbook : public eosio::contract {

  public:

  private:
    struct [[eosio::table]] person {
      account_name key;
      std::string first_name;
      std::string last_name;
      std::string street;
      std::string city;
      std::string state;

      uint64_t primary_key() const { return key; }
    };

    typedef eosio::multi_index<N(people), person> address_index;

};

第6步:构造函数

使用C++类时,你应该建立的第一个公共方法是构造函数。

咱们的构造函数将负责最初设置合约。

EOSIO合约扩展了合约类。使用合约范围初始化咱们的父合约类。咱们的构造函数传递的范围参数是正在部署合约的区块链上的账户。

//c++
addressbook(account_name self): contract(self){}

第7步:向表中添加记录

之前,多索引表的主键被定义为强制执行此合约将仅为每一个用户存储一条记录。为了使其所有工做,须要创建一些关于设计的假设。

  • 受权修改通信簿的惟一账户是用户。
  • 咱们表的primary_key是惟一的,基于用户名。
  • 对于可用性,合约应该可以经过单个操做建立和修改表行。

在eosio中,区块链具备惟一的账户,所以在此特定用例中,account_name是做为primary_key的理想候选者。account_name类型是uint64_t

接下来,为用户定义添加或更新记录的操做。此操做须要接受此操做须要可以放置(建立)或修改的任何值。

格式化定义以使其更容易阅读。为了简化用户体验和界面,有一个方法负责建立和修改行。所以,将其命名为“upsert”,即“update”和“insert”的组合。

//c++

void upsert(
  account_name user, 
  std::string first_name, 
  std::string last_name, 
  std::string street, 
  std::string city, 
  std::string state
) {}

早些时候,有人提到只有用户才能控制本身的记录,由于这个合约是选择加入的。为此,请使用eosio.cdt提供的require_auth方法。此方法接受一个参数,即account_name类型,并断言执行交易的账户等于提供的值。

//c++
void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
}

实例化表。以前,配置了multi_index表,并将其声明为address_index。要实例化一个表,请考虑这两个必需参数:

  • “code”,表明合约的账户。能够经过做用域_self变量访问此值。
  • 定义合约付款人的范围“scope”,该用例中的合约负责支付ram费用。
//c++
void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(_self, _self );
}

接下来,查询迭代器,将其设置为变量,由于此迭代器将被屡次使用。

//c++
void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(_self, _self );
  auto iterator = addresses.find(user);
}

安全性已经创建而且表格实例化了,太棒了!

接下来,编写用于建立或修改表的逻辑。检测特定用户是否已存在。

为此,请经过传递user参数来使用表的find方法。find方法将返回一个迭代器。使用该迭代器对end方法进行测试。end方法是“null”的别名。

//c++
void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  auto iterator = addresses.find( user );
  address_index addresses(_self, _self );
  if( addresses.find( user ) == addresses.end() )
  {
    //The user isn't in the table
  }
  else {
    //The user is in the table
  }
}

使用multi_index方法emplace在表中建立记录。此方法接受两个参数,即此记录的范围“scope”和回调函数。

emplace方法的回调函数必须使用lamba来建立接口。在body中分配行的值和提供给upsert的值。

//c++
void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(_self, _self );
  auto iterator = addresses.find( user );
  if( iterator == addresses.end() )
  {
		addresses.emplace(user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
  else {
    //The user is in the table
  }
}

接下来,处理“upsert”函数的修改或更新。使用modify方法,传递一些参数

  • 前面定义的迭代器,在调用此操做时设置为声明的用户。
  • 范围“scope”或“ram payer”ram消费者,在这种状况下是用户,如先前在提出该合约的设计时所决定的那样。
  • 回调函数用于处理表的修改。
//c++
void upsert(account_name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user );
  address_index addresses(_self, _self );
  auto iterator = addresses.find( user );
  if( iterator == addresses.end() )
  {
   addresses.emplace(user, [&]( auto& row ) {
     row.key = user;
     row.first_name = first_name;
     row.last_name = last_name;
     row.street = street;
     row.city = city;
     row.state = state;
   });
  }
  else {
   addresses.modify(iterator, user, [&]( auto& row ) {
     row.first_name = first_name;
     row.last_name = last_name;
     row.street = street;
     row.city = city;
     row.state = state;
   });
  }
}

地址簿合约如今具备一个功能操做,若是该记录尚不存在,将容许用户在表中建立一行,若是已存在则修改它。

可是若是用户想要彻底删除记录呢?请看EOS的数据持久性(下)

对了,文中调用的各类eos方法能够参考EOS.IO C语言API手册

======================================================================

分享一个交互式的在线编程实战,EOS智能合约与DApp开发入门

EOS教程

本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、帐户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。

汇智网原创翻译,转载请标明出处。这里是原文

相关文章
相关标签/搜索