区块链EOS|智能合约入门4——了解数据持久性

本文通过一个简单的地址簿应用实例,介绍如何在EOS区块链上实现数据的持久化存储。首先创建一个名为addressbook的合约,定义person结构体作为数据表,配置multi_index表,然后编写添加、修改和删除记录的方法。最后,编译合约,部署到addressbook账户,并进行测试,展示数据操作的过程和结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击查看该系列文章


正文

  本文将使用一个简单的例子帮助理解EOSIO中的数据持久性。

1. 在你的contract目录下创建addressbook文件夹,并在其中创建addressbook.cpp文件。

cd /Users/yourUserName/Documents/EOS/contracts
mkdir addressbook
cd addressbook
touch addressbook.cpp

2. 在cpp文件中编写一个继承自eosio::contract的addressbook类。
  同时,在public方法中继承eosio::contract的构造函数。

#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:
  using contract::contract;
private:
  
};  

3. 添加person表结构。
  使用name类型来定义一个叫做key的变量,同时,编写一个叫做primary_key()的方法(返回key的值),于是key就是该结构的主键。

struct person {
 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.value;}
};

4. 配置multi_index表。

typedef eosio::multi_index<"people"_n, person> address_index;

  “people”是该表的名称(_n表示为name类型),person是前面定义的结构体,address_index是该类型的类型名(后面将使用其实例化表)。


5. 编写添加修改记录的方法。

[[eosio::action]]
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user ); //只能操作自己的记录,所以需要验证操作的记录是不是自己的。
  //multi_index的实例化需要两个参数,code和scope。
  //code是拥有该合约的账户,scope是用于逻辑上的划分(目前没什么作用)
  address_index addresses(get_self(), get_first_receiver().value);
  //创建一个查询,使用find()方法查询user并返回一个迭代器。
  auto iterator = addresses.find(user.value);
  //end()相当于null
  if( iterator == addresses.end() )
  {
    //使用multi_index的emplace方法来添加一条记录,需要两个参数:user和callback function。
    //user为payer,这里为添加修改记录的人;回调函数必须使用lamba函数创建引用。
    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 {
    //使用multi_index的modify方法来修改记录。
    //回调函数将修改该用户的记录。
    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;
    });
  }
}

6. 添加删除记录的方法

[[eosio::action]]
void erase(name user) {
    require_auth(user);
    address_index addresses(get_self(), get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    //若结果为fail,会给出后半部分给出的文字提醒。
    check(iterator != addresses.end(), "Record does not exist");
    //将记录删除。
    addresses.erase(iterator);
  }

  完整代码如下。

#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  // addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}
  using contract::contract;

  [[eosio::action]]
  void upsert(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( get_self(), get_first_receiver().value );
    // print("hi,",get_self());
    print("hello,",get_first_receiver());
    auto iterator = addresses.find(user.value);
    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.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(name user) {
    require_auth(user);

    address_index addresses( get_self(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
  }

private:
  struct [[eosio::table]] person {
    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.value; }
  };
  typedef eosio::multi_index<"people"_n, person> address_index;

};  

7. 编译并部署到addressbook账户
  编译。

eosio-cpp addressbook.cpp -o addressbook.wasm

  创建一个叫addressbook的账户。

cleos create account eosio addressbook EOS6GwYrUANGhouVRR97W8ukiCPX49Z74toqMTTxGH8mViYiPuuPi -p eosio@active

  将合约部署到该账户。

cleos set contract addressbook /Users/yourUserName/Documents/EOS/contracts/addressbook -p addressbook@active

  若提示没有解锁的钱包,需要先解锁一下(cleos wallet unlock解锁默认钱包)。


8. 测试合约
  (1) alice为自己添加记录。

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

  结果如下。

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...

  (2) 查询一下alice的记录。

cleos get table addressbook addressbook people --lower alice --limit 1

  结果如下。

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

  (3) 如果alice想为bob添加记录,测试一下。

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

  结果是失败的,显示如下。

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.
Error Details:
missing authority of bob

  (4) alice删除自己的记录。

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

  显示如下。

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    ]

  再次查询。

cleos get table addressbook addressbook people --lower alice --limit 1

  结果如下。

{
  "rows": [],
  "more": false,
  "next_key": ""
}

注:参考自官方开发文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值