開發 DApp 時要調用在區塊鏈上的 Ethereum 智能合約,就須要智能合約的 ABI。本文但願更多瞭解 ABI,如爲何須要 ABI?如何解讀 Ethereum 的智能合約 ABI?以及如何取得智能的 ABI?git
若是理解 API 就很容易瞭解 ABI。簡單來講,API 是程序與程序間互動的接口。這個接口包含程序提供外界存取所需的 functions、variables 等。ABI 也是程序間互動的接口,但程序是被編譯後的 binary code。因此一樣的接口,但傳遞的是 binary 格式的信息。因此 ABI 就要描述如何 decode/encode 程序間傳遞的 binary 信息。下圖以 Linux 爲例,描述 Linux 中 API、ABI 和程序的關係。github
在 Ethereum 智能合約能夠被你們使用前,必須先被部署到區塊鏈上。npm
從智能合約的代碼到使用智能合約,大概包含幾個步驟:api
而要如何知道這這個智能合約提供哪些 function 以及應該要傳入什麼樣的參數呢?這些信息就是記錄在智能合約的 ABI!區塊鏈
Ethereum 智能合約 ABI 用一個 array 表示,其中會包含數個用 JSON 格式表示的 Function 或 Event。根據最新的 Solidity 文件:ui
共有 7 個參數:3d
name
:a string,function 名稱code
type
:a string,"function", "constructor", or "fallback"component
inputs
:an array,function 輸入的參數,包含:教程
name
:a string,參數名
type
:a string,參數的 data type(e.g. uint256)
components
:an array,若是輸入的參數是 tuple(struct) type 纔會有這個參數。描述 struct 中包含的參數類型
outputs
:an array,function 的返回值,和 inputs
使用相同表示方式。若是沒有返回值可忽略,值爲 []
payable
:true
,function 是否可收 Ether,預設爲 false
constant
:true
,function 是否會改寫區塊鏈狀態,反之爲 false
stateMutability
:a string,其值可能爲如下其中之一:"pure"(不會讀寫區塊鏈狀態)、"view"(只讀不寫區塊鏈狀態)、"payable" and "nonpayable"(會改區塊鏈狀態,且如可收 Ether 爲 "payable",反之爲 "nonpayable")
仔細看會發現 payable
和 constant
這兩個參數所描述的內容,彷佛已包含在 stateMutability
中。
事實也確實是這樣的,在 Solidity v0.4.16 中把 constant
這個修飾function 的 key words 分紅: view
(neither reads from nor writes to the state)和 pure
(does not modify the state),並從 v0.4.17 開始 Type Checker 會強制檢查。constant
改成只用來修飾不能被修改的 variable。並在 ABI 中加入 stateMutability
這個參數統一表示,payable
和 constant
目前保留是爲了向後兼容。這個改動詳細的內容和討論可參考: https://github.com/ethereum/solidity/issues/992
共有 4 個參數:
name
: a string,event 的名稱
type
: a string,always "event"
inputs
: an array,輸入參數,包含:
name
: a string,參數名稱
type
: a string,參數的 data type(e.g. uint256)
components
: an array,若是輸入參數是 tuple(struct) type 纔會有這個參數。描述 struct 中包含的信息類型
indexed
: true
,若是這個參數被定義爲 indexed ,反之爲 false
anonymous
: true
,若是 event 被定義爲 anonymous
更新智能合約狀態須要發送 transaction,transaction 須要等待驗證,因此更新合約狀態是非同步的,沒法立刻取得返回值。使用 Event 能夠在狀態更新成功後,將相關信息記錄到 Log,並讓監聽這個 Event 的 DApp 或任何應用這個接口的程序收到通知。每筆 transaction 都有對應的 Log。
因此簡單來講,Event 可用來:1. 取得 function 更新合約狀態的返回值 2. 也可做爲合約另外的存儲空間。
Event 的參數分爲:有 indexed
,和其餘沒有 indexed
的。有 indexed
的參數可使用 filter,例如同一個 Event,我能夠選擇只監遵從特定 address 發出來的交易。每筆 Log 的信息一樣分爲兩個部分:Topics(長度最多爲 4 的 array) 和 Data。有 indexed
的參數會存儲存在 Log 的 Topics,其餘的存在 Data。若是定義爲 anonymous
,就不會產生如下示例中的 Topics[0],其值爲 Event signature 的 hash,做爲這個 Event 的 ID。
event Set(address indexed _from, uint value)
這個智能合約包含:
data
:一個可修改的 state variable,會自動產生一個只能讀取的 data()
functionset()
:一個修改 data
值的 functionSet()
:一個在每次修寫 data
時記錄 Log 的 event智能合約 Source Code:
pragma solidity ^0.4.20; contract SimpleStorage { uint public data; event Set(address indexed _from, uint value); function set(uint x) public { data = x; Set(msg.sender, x); } }
智能合約 ABI:
[{ "constant": true, "inputs": [], "name": "data", "outputs": [{"name": "","type": "uint256"}], "payable": false, "stateMutabㄒility": "view", "type": "function" }, { "anonymous": false, "inputs": [{"indexed": true,"name": "_from","type": "address"},{"indexed": false,"name": "value","type": "uint256"}], "name": "Set", "type": "event" }, { "constant": false, "inputs": [{"name": "x","type": "uint256"}], "name": "set", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }]
能夠用 Solidity Compiler 取得合約 ABI,我使用 JavaScript 版本的 Compiler 爲例。
安裝:
npm install solc -g
取得合約 ABI:
solcjs simpleStorage.sol --abi
會生成一個 simpleStorage_sol_SimpleStorage.abi 文件,裏面就是合約ABI 內容。
也能夠取得合約的 binary code:
solcjs your_contract.sol --bin
一樣的使用 Solidity Compiler,也能夠用 Remix。在合約的 Details 能夠看到完整的 ABI。能夠在 Settings 中指定 Compiler 版本。
許多知名合約會把合約 source code 放上 Etherscan 作驗證,能夠同時看到h 合約ABI。
另外 Etherscan 提供 API,可用來取得通過驗證的合約 ABI。
安利兩個區塊鏈、以太坊開發DApp的實戰教程: 1.適合區塊鏈新手的以太坊DApp開發:
http://xc.hubwiz.com/course/5a952991adb3847553d205d1
2.用區塊鏈、星際文件系統(IPFS)、Node.js和MongoDB來構建電商平臺: