EOS开发中的数据持久性(下)

上文EOS的数据持久性(上)中提到,如果用户想要完全删除记录怎么办?我们接着来看下面的步骤:

第8步:从表中删除记录

与前面的步骤类似,在地址簿中创建一个公共方法,确保包含ABI声明和针对操作的参数用户进行测试的require_auth,以验证只有记录的所有者可以修改其帐户。

//c++
void erase(account_name user){
      require_auth(user);
    }

实例化表。在addressbook中,每个帐户只有一个记录。使用find设置iterator

//c++
...
    void erase(account_name user){
      require_auth(user);
      address_index addresses(_self, _self);
      auto iterator = addresses.find(user);
    }
...

合约不能删除不存在的记录,因此在继续之前断言记录确实存在。

//c++
...
    void erase(account_name user){
      require_auth(user);
      address_index addresses(_self, _self);
      auto iterator = addresses.find( user );
      eosio_assert(iterator != addresses.end(), "Record does not exist");
    }
...

最后,调用erase方法,擦除迭代器iterator。

//c++
...
    void erase(account_name user){
      require_auth(user);
      address_index addresses(_self, _self);
      auto iterator = addresses.find( user );
      eosio_assert(iterator != addresses.end(), "Record does not exist");
      addresses.erase(iterator);
    }
...

合约现在基本完成。 用户可以创建,修改和删除记录。但是,合约还没有为编译做好准备。

第9步:准备ABI

完成以下步骤以完成合约。

9.1 EOSIO_ABI

在文件的底部,使用EOSIO_ABI宏程序,传递合约的名称,以及我们的单独操作“upsert”。

此宏程序处理wasm用于将调用分派给我们的合约中的特定方法的应用处理程序。

将以下内容添加到addressbook.cpp的底部将使我们的cpp文件与EOSIO的wasm解释器兼容。未能包含此声明可能会在部署合约时导致错误。

//c++
EOSIO_ABI( addressbook, (upsert) )

9.2 ABI action 声明

eosio.cdt包含一个ABI Generator,但为了它的工作,我们的合同需要一些小的声明。

upserterase函数之上添加以下C++11声明:

//c++
[[eosio::action]]

上述声明将提取操作的参数,并在生成的ABI文件中创建必要的ABI结构描述。

9.3 ABI表声明

向表中添加ABI声明。修改合约私有区域中定义的以下行:

//c++
struct person {

改成这样:

//c++
struct [[eosio::table]] person {

[[eosio.table]]声明将向ABI文件添加必要的描述。

现在我们的合约已经准备好了。

以下是我们的addressbook合约的最终状态:

//c++
#include 
#include 

using namespace eosio;

class addressbook : public eosio::contract {

public:
  using contract::contract;

  addressbook(account_name self): contract(self) {}

  [[eosio::action]]
  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 {
      std::string changes;
      addresses.modify(iterator, 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;
      });
    }
  }

  [[eosio::action]]
  void erase(account_name user){
    // require_auth(user);
    address_index addresses(_self, _self);
    auto iterator = addresses.find( user );
    eosio_assert(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
  }

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 address_index;

};

EOSIO_ABI( addressbook, (upsert)(erase) )

第10步:编译合约

从终端执行以下命令:

//shell
eosio-cpp -o addressbook.wasm addressbook.cpp --abigen

第11步:部署合约

为合约创建一个帐户,执行以下shell命令:

//shell
cleos create account eosio addressbook YOUR_PUBLIC_KEY

部署addressbook合约。

//shell
cleos set contract addressbook CONTRACTS_DIR/addressbook

结果:

//Result
5f78f9aea400783342b41a989b1b4821ffca006cd76ead38ebdf97428559daa0  5152 bytes  727 us
#         eosio <= eosio::setcode               {"account":"addressbook","vmtype":0,"vmversion":0,"code":"0061736d010000000191011760077f7e7f7f7f7f7f...
#         eosio <= eosio::setabi                {"account":"addressbook","abi":"0e656f73696f3a3a6162692f312e30010c6163636f756e745f6e616d65046e616d65...
warning: transaction executed locally, but may not be confirmed by the network yet    ]

第12步:测试合约

在表中添加一行:

//shell
cleos push action addressbook upsert '["alice", "alice", "liddell", "123 drink me way", "wonderland", "amsterdam"]' -p alice@active

结果:

////Result
executed transaction: 003f787824c7823b2cc8210f34daed592c2cfa66cbbfd4b904308b0dfeb0c811  152 bytes  692 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddell","street":"123 drink me way","city":"wonde...

检查alice是否无法为其他用户添加记录。

//shell
cleos push action addressbook upsert '["bob", "bob", "is a loser", "doesn't exist", "somewhere", "someplace"]' -p alice@active

正如预期的那样,我们合约中的require_auth阻止了alice创建/修改另一个用户的行。

//Result
Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the relevant authority using -p option.

查询爱丽丝的记录。

//shell
cleos get table addressbook addressbook people -k alice

结果:

//Result
{
  "rows": [{
      "key": "3773036822876127232",
      "first_name": "alice",
      "last_name": "liddell",
      "street": "123 drink me way",
      "city": "wonderland",
      "state": "amsterdam"
    }
  ],
  "more": false
}

测试看到爱丽丝可以删除记录。

//shell
cleos push action addressbook erase '["alice"]' -p alice@active

结果:

//Result
executed transaction: 0a690e21f259bb4e37242cdb57d768a49a95e39a83749a02bced652ac4b3f4ed  104 bytes  1623 us
#   addressbook <= addressbook::erase           {"user":"alice"}
warning: transaction executed locally, but may not be confirmed by the network yet    ]

检查记录是否已删除:

//shell
cleos get table addressbook addressbook people -k alice

结果:

//Result
{
  "rows": [],
  "more": false
}

看起来不错!

总结下

你已经学习了如何配置表,实例化表,创建新行,修改现有行以及如何使用迭代器。你已经学习了如何针对空迭代器结果进行测试,以及如何配置合约的ABI。

文中调用的各种eos方法可以参考:EOS.IO C语言API手册。

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

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

EOS教程

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

C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
  • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
  • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。

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

你可能感兴趣的:(EOS开发中的数据持久性(下))