上一章我們學(xué)習(xí)了開發(fā)智能合約之前需要知道的必要概念:
- 什么是webAssembly以及它在智能合約上下游中的位置邮弹;
- 什么是ABI以及怎樣使用eosiocpp工具產(chǎn)生ABI和wasm弯洗、wast
hello
智能合約的簡單入門:部署和調(diào)用如果說智能合約開發(fā)是一個鎖著門的圖書館耳标,那么之前的學(xué)習(xí)就是鑰匙〕冢現(xiàn)在我們終于可以拿著鑰匙打開大門胜嗓,走進去一探究竟。
摘要
說到智能合約開發(fā)钩乍,大家首先想到的肯定是寫代碼辞州、像solidity開發(fā)一樣教語法。EOS的智能合約是用C++寫的寥粹,基本語法大家可以去買本C++的書变过;這一篇主要介紹EOS智能合約的數(shù)據(jù)存儲,為大家掃清智能合約開發(fā)道路上的最后一道障礙涝涤。
什么是RAM
之前我們在學(xué)習(xí)如何在主網(wǎng)創(chuàng)建賬戶
時媚狰,曾經(jīng)接觸到RAM
的概念。我們不能像操作以太坊那樣阔拳,憑空生成一個地址作為自己的賬戶崭孤,而是要先有一個賬戶,再去創(chuàng)建另一個賬戶糊肠。其中就涉及到一個關(guān)于RAM很關(guān)鍵的知識點:創(chuàng)建賬戶需要消耗RAM辨宠。
當(dāng)時我們只是很模糊地知道,RAM大概是內(nèi)存的意思货裹。
RAM is used to store data in an in-memory database. DApps will use this to store state information so it is quickly available to their app.
RAM是EOS主網(wǎng)中的內(nèi)存嗤形,用于存儲用戶在EOS中使用頻率高的數(shù)據(jù)(賬戶余額、合約狀態(tài)等)弧圆。
BM對EOS的期望是成為區(qū)塊鏈世界中的【操作系統(tǒng)】赋兵,因此可以把計算機的一些概念對標到EOS中笔咽,其中計算機中的運行內(nèi)存,在EOS中就可以看做是RAM霹期;而硬盤就可以對標EOS區(qū)塊鏈數(shù)據(jù)庫叶组。
所以高訪問量的決策類數(shù)據(jù),例如賬戶余額经伙、智能合約的當(dāng)前狀態(tài)等就會被存儲在RAM中扶叉,并且這部分數(shù)據(jù)將長期占用RAM;而低訪問的費決策性存證數(shù)據(jù)帕膜,例如交易數(shù)據(jù)枣氧,就會存儲在EOS系統(tǒng)的硬盤中,也就是區(qū)塊鏈中垮刹。當(dāng)存儲賬號狀態(tài)的空間不足达吞,即RAM不足時,轉(zhuǎn)賬或部署合約等相關(guān)操作就無法執(zhí)行荒典。
什么是EOS數(shù)據(jù)庫
之前我們曾經(jīng)介紹過transaction和action酪劫,action是智能合約執(zhí)行的基本單元,transaction可以認為是一個或幾個action組成的原子性操作寺董。action在被稱為action上下文
的環(huán)境中執(zhí)行覆糟,action上下文
提供了執(zhí)行action所需的一些條件,其中一個就是action的工作內(nèi)存遮咖,這是action保存工作狀態(tài)的地方滩字。在處理一個action之前,eosio會先為它清理一次內(nèi)存御吞,因此當(dāng)變量在一個action中被賦值后麦箍,另一個action的上下文是拿不到這個值的。那么在action之間傳遞狀態(tài)的唯一方法就是把它持久存儲到EOS數(shù)據(jù)庫中陶珠,如下圖:
這個持久化存儲就是數(shù)據(jù)庫存儲數(shù)據(jù)挟裂。EOS允許智能合約定義自己的私有數(shù)據(jù)庫表。比如上圖揍诽,Apply Context的內(nèi)容都是一次性的诀蓉,一次action執(zhí)行完成,對象就釋放了,只有存儲到EOSIO database的才被保存暑脆。
什么是multi_index
接著上面介紹的數(shù)據(jù)庫往下說交排, 這個私有數(shù)據(jù)表是通過multi_index
來訪問和交互的。EOS的multi_index
類似boost的multi_index
饵筑,即多索引容器。有了多級索引处坪,智能合約就具備了操作類似數(shù)據(jù)庫模塊的功能根资。
multi_index是一個非常方便的架专、可以和數(shù)據(jù)庫交互的容器。
從字面意思來看玄帕,multi_index就是一個可以使用多索引的數(shù)據(jù)表部脚。
如下圖:
每一個multi_index容器都可以理解成傳統(tǒng)數(shù)據(jù)庫中的一張表,但是行和列稍有不同裤纹。和傳統(tǒng)的多列的表不同的是委刘,multi_index只有一列。這一列中的每一行都表示一個對象鹰椒,通常這個對象是struct
或者是class
類型的锡移,有多個成員變量。因此雖然只有一列漆际,但是multi_index的靈活性絲毫不亞于傳統(tǒng)的數(shù)據(jù)表淆珊。
舉個例子,比如下面的這個struct
:
// @abi table proposal i64
struct Proposal {
uint64_t id;
account_name owner = 0;
string description;
std::vector<account_name, uint32_t> votes;
uint64_t primary_key() const { return id; }
EOSLIB_SERIALIZE( Proposal, (id)(owner)(description)(votes))
};
typedef eosio::multi_index<N(Proposal), Proposal> proposals;
首先看第一行:
// @abi table proposal i64
在部署合約之前奸汇,我們都會用eosiocpp
來生成ABI施符,EOS智能合約編譯器可以讀取struct
結(jié)構(gòu)體和public
方法之前的注。在注釋中我們可以傳入兩種類型:action
和table
擂找,ABI就會根據(jù)我們的聲明戳吝,自動在生成的ABI中添加相應(yīng)的方法或者表定義。
第二個proposal
就是表名贯涎,而第三個i64
就是表的主鍵的類型听哭。在這里主鍵就是id
。
account_name
注意到第二個成員變量owner
:
account_name owner = 0;
這里的account_name
是EOS自己定義的類型柬采,也就是之前我們曾經(jīng)創(chuàng)建過的賬戶名欢唾。可以理解成以太坊中的address
類型粉捻。
vector
std::vector<account_name, uint32_t> votes;
vector
這里可以理解成以太坊中的mapping
- 自定義的一個映射集合礁遣。
Primary Keys
uint64_t primary_key() const { return id; }
eosio::multi_index
規(guī)定,每行必須有一個主鍵肩刃,類型為64位的無符號整型祟霍。表中的對象都會根據(jù)主鍵,升序或者降序排列盈包。通過在struct
中定義primary_key()
方法來獲取沸呐。在這個例子中,Proposal
的主鍵就是id
呢燥,類型為uint64_t
崭添。當(dāng)然主鍵的類型也可以是account_name
等。(account_name在eos中被存儲為uint64_int
類型)叛氨。
數(shù)據(jù)序列化
EOSLIB_SERIALIZE( Proposal, (id)(owner)(description)(votes))
通過閱讀contracts/eosiolib/serialize.hpp
文件可以知道呼渣,它其實是使用了BOOST_PP_SEQ_FOR_EACH
宏棘伴。它的作用基本上就是賦予了struct
額外的操作,可以把數(shù)據(jù)序列化到multi_index
屁置,或者從multi_index
中反序列化出來焊夸。
multi_index相關(guān)操作
雖然不想SQL語句那樣豐富,但是multi_index依然提供了一些基礎(chǔ)的操作:
- 創(chuàng)建:使用
.emplace
- 查詢:使用
.find
- 修改已存在的入口:使用
.modify
舉個查詢的例子:
auto itr = proposals.find(proposal_id)
以上語句查詢了特定id的proposal蓝角,它返回的是一個迭代器iterator
阱穗。這就涉及到我們?nèi)绾问褂帽碇械臄?shù)據(jù),答案就是迭代器使鹅。
可以把迭代器想象成一個電梯揪阶,在整個數(shù)據(jù)表中上下滑動(來定位數(shù)據(jù)),任何對數(shù)據(jù)的操作都必須通過迭代器并徘。
結(jié)束語
這一章概念雖然有些多遣钳,但是值得大家仔細研究。這一章我們學(xué)習(xí)了:
- RAM的概念:存儲用戶高頻使用的數(shù)據(jù)的地方麦乞,比如當(dāng)前狀態(tài)蕴茴;
- EOS數(shù)據(jù)庫的概念以及如何存儲;
- multi_index是什么 - 和數(shù)據(jù)庫交互的容器
這一章理論性的內(nèi)容偏多姐直,理解上可能不如之前的幾篇直觀倦淀。下一篇我們將學(xué)習(xí)如何操作multi_index,以此帶大家更加深入地理解multi_index声畏,同時正式開啟我們的智能合約開發(fā)之旅撞叽。