1. 程式人生 > >EOS開發中的資料永續性問題(上)

EOS開發中的資料永續性問題(上)

要了解資料永續性,請編寫一個簡單的智慧合約,作為地址記錄。雖然這個用例由於各種原因而不太適合作為生產智慧合約,但開始學習資料永續性如何在EOSIO上執行而不被與eosio的multi_index功能無關的業務邏輯分心,這也算的上一個很好的合約。

第1步:建立一個新目錄

之前,你建立了一個合約目錄,現在就在那裡開始。

//shell
cd CONTRACTS_DIR

為我們的合約建立一個新目錄並進入目錄:

//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智慧合約與DApp開發入門

EOS教程

本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智慧合約開發與部署、使用程式碼與智慧合約互動等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。

  • C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智慧合約開發與互動、過濾器和交易等。
  • java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Java程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
  • java以太坊開發教程,主要是針對java和android程式設計師進行區塊鏈以太坊開發的web3j詳解。
  • php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Php程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
  • php以太坊,主要是介紹使用php進行智慧合約開發互動,進行賬號建立、交易、轉賬、代幣開發以及過濾器和交易等內容。
  • python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
  • 以太坊入門教程,主要介紹智慧合約與dapp應用開發,適合入門。
  • 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
  • EOS入門教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智慧合約開發與部署、使用程式碼與智慧合約互動等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。

匯智網原創翻譯,轉載請標明出處。這裡是原文