【許曉笛】開發第一個 EOS 智慧合約

圓方圓區塊鏈發表於2018-11-17

Hello World!

稍微瞭解 EOS 系統,你就會知道 EOS 的智慧合約基於 WebAssembly(WASM) 技術,這種技術在效能和跨平臺相容性之間取得了很好的平衡,通過將原始程式碼編譯成位元組碼,使得程式碼可以在多種平臺的 WASM 虛擬機器(或者叫直譯器)中執行。得到了蘋果和谷歌等科技巨頭的支援,被譽為下一代網際網路前端技術。目前的 WebAssembly 技術支援 C/C++ 語言,並開發了 JavaScript 介面,並被 Chrome、Edge、Safari、Firefox 等幾乎所有的主流瀏覽器支援。

因為使用了 WebAssembly,目前的 EOS 智慧合約只支援 C/C++ 語言,簡單的智慧合約由 3 種檔案組成:.hpp檔案、.cpp檔案、.abi 檔案。其中 hpp 為 C++ 標頭檔案,一般用來定義類及其成員變數與成員函式。cpp 為 C++ 檔案,用來實現 hpp 中宣告的成員函式,實現智慧合約的業務邏輯。abi(Application Binary Interface) 檔案為二進位制介面檔案,檔案格式類似 JSON,用來定義智慧合約與 EOS 系統外部互動的資料介面。

如果智慧合約的非常簡單,只有一個 cpp 檔案,可以省略 hpp 檔案,將類與成員定義在 cpp 檔案中。abi 檔案應該由 C++ 程式需要的資料庫空間和外部介面生成,不過 EOS 開發了 abi 自動生成工具,可以根據智慧合約程式碼自動生成 abi 檔案,減輕了開發工作量。所以最簡單的智慧合約只需實現 cpp 檔案。

【許曉笛】開發第一個 EOS 智慧合約

Hello 智慧合約

一般的作業系統上手時,慣例是編寫一個 Hello World 程式,結果是主動輸出一句話。但我們不一樣,我們編寫的是一個智慧合約,智慧合約強調的是互動,在 EOS 裡叫做 Action,Action 表示別人可以對合約做什麼動作,所有智慧合約程式碼都是對 Action 的迴應,是被動的。下面就是第一個 Hello 智慧合約:

hello.cpp:

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

class hello : public eosio::contract {
  public:
      using contract::contract;

      /// @abi action 
      void hi( account_name user ) {
         print( "Hello, ", name{user} );
      }
};

EOSIO_ABI( hello, (hi) )
複製程式碼

我們在程式碼中定義了一個類:hello,這個類名與合約的賬戶名沒關係,類中只有一個簡單的方法:

void hi( account_name user ) {
         print( "Hello, ", name{user} );
      }
複製程式碼

這就是 EOS 智慧合約裡所謂的 Action,我們定義了一個叫 hi 的 Action,引數是另一個賬戶名,函式體是列印一句話,迴應 hello。 也就是說別的賬戶可以呼叫這個合約的 hi Action,這個 hello 合約就會列印一句 hello 來回應。

最後一行程式碼:

EOSIO_ABI( hello, (hi) )
複製程式碼

EOSIO_ABI 是一個巨集,將特定類的特定方法暴露給系統,成為別的賬戶可以呼叫的 Action。

編譯智慧合約

我們使用 eosiocpp 工具將寫好的 hello.cpp 編譯成為位元組碼檔案(.wast):

$ eosiocpp -o hello.wast hello.cpp
複製程式碼

然後使用 eosiocpp 工具自動生成 abi 檔案:

$ eosiocpp -g hello.abi hello.cpp
Generated hello.abi
複製程式碼

看一下生成的 abi 檔案內容:

{
  "____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-04-16T13:37:55",
  "types": [],
  "structs": [{
      "name": "hi",
      "base": "",
      "fields": [{
          "name": "user",
          "type": "account_name"
        }
      ]
    }
  ],
  "actions": [{
      "name": "hi",
      "type": "hi",
      "ricardian_contract": "# CONTRACT FOR hello::hi## ACTION NAME: hi\n 
      ### Parameters### Parameters\nInput paramters:Input paramters:\n 
      \n 
      * `user` (string to include in the output)* `user` (string to include in the output)\n
      \n 
      Implied parameters: Implied parameters: \n 
      \n 
      * `account_name` (name of the party invoking and signing the contract)* `account_name` (name of the party invoking and signing the contract)\n 
      \n 
      ### Intent### Intent\n 
      INTENT. The intention of the author and the invoker of this contract is to print output. It shall have no other effect.INTENT. The intention of the author and the invoker of this contract is to print output. It shall have no other effect.\n 
      \n 
      ### Term### Term\n 
      TERM. This Contract expires at the conclusion of code execution.TERM. This Contract expires at the conclusion of code execution.\n" 
    }
  ],
  "tables": [],
  "ricardian_clauses": [

   ...
   ...
   ...

  ]
}
複製程式碼

我們省略了 ricardian_clauses ,也就是李嘉圖條款部分(李嘉圖合約指的是人與機器都能讀懂的合同,EOS 最近才將其加入智慧合約中)。我們看到 abi 檔案中已經宣告瞭 hi 這個 Action,並說明了這個 Action 的李嘉圖合約,大概意思是本合約的輸入為一串字元(user),本合約意圖是列印輸出,沒有其他效果。

上傳智慧合約

上傳智慧合約之前,我們要先給智慧合約建立一個賬戶 EOS 裡賬戶和智慧合約是一一對應的。使用 EOS 的 cleos 命令列工具建立賬戶:

$ cleos create account eosio hello.code EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4 EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4
複製程式碼

命令中,hello.code 就是這個智慧合約的賬戶名,EOS系統的賬戶名要求 12 字元以內。後面兩個公鑰是在本地測試網路中有建立賬戶許可權的公鑰(對應本地測試網路中的 eosio 賬戶)。

然後就可以上傳智慧合約了:

$ cleos set contract hello.code ../hello -p hello.code
複製程式碼

使用智慧合約

我們使用 user 賬戶呼叫 hello.codehi Action:

$ cleos push action hello.code hi '["user"]' -p user
複製程式碼

hello.code 表示執行 hello.code 合約,hi 表示執行合約裡的 hi Action,'["user"]' 是根據 abi 寫的傳入引數, -p 參數列示使用哪個賬戶的許可權 (permission)。

以下是系統迴應:

executed transaction: 4c10c1426c16b1656e802f3302677594731b380b18a44851d38e8b5275072857  244 bytes  1000 cycles
#    hello.code <= hello.code::hi               {"user":"user"}
>> Hello, user

複製程式碼

說明執行了 hello.code 合約的 hi Action,並且系統輸出為 Hello, user,智慧合約成功對 Action 進行了迴應。


相關文章和視訊推薦

【許曉笛】EOS 新增的 WebAssembly 直譯器,是什麼鬼?

圓方圓學院彙集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。

公開課地址:ke.qq.com/course/3451…

相關文章