第一行代碼:以太坊(3)-使用更多的工具編寫和測試智能合約


《第一行代碼:以太坊》開始連載了
javascript

 

在上文中已經使用了Remix環境運行和測試了本書編寫的第一個智能合約程序,不過編寫和測試智能合約的測試方式不少,例如,在testrpc環境測試;在Intellij IDEA集成開發環境中用Solidity語言編寫智能合約;在純Web環境中測試智能合約;使用AJAX方式測試智能合約等。本文將詳細介紹這些用於編寫和測試智能合約的方法。css

1.安裝本地remix環境(Windows、Mac OS X和Linux)

在本節使用Remix環境運行和測試了Calc智能合約,不過使用的是在線Remix環境。因爲某些緣由(如沒有網絡,或網絡速度很慢),咱們但願使用本地的Remix環境運行和測試智能合約,這就要就將Remix環境安裝在本地。Remix是跨平臺的,因此本節介紹的安裝方法同時適用於Windows、Mac OS X和Linux。html

不論是在什麼操做系統下安裝Remix,都必須安裝Node.js,讀者能夠到https://nodejs.org下載Node.js的最新版直接安裝便可。java

安裝完Node.js後,須要使用git命令下載Remix的代碼庫(browser-solidity),命令行以下:node

git clone https://github.com/ethereum/browser-soliditygit

在Mac OS X和Linux下,通常會集成git命令,但在Windows下,默認是沒有git命令的,因此須要到下面的頁面下載Windows版的git工具,下載完後直接安裝便可。github

https://git-scm.com/download/winweb

使用git命令下載完Remix的代碼庫後,使用cd命令進入browser-solidity目錄,該目錄在下載Remix代碼庫的過程當中自動在當前目錄中建立。npm

在browser-solidity目錄中執行下面的命令安裝browser-solidity。編程

npm install

安裝browser-solidity的過程比較漫長,讀者要耐心等待。下圖是在Windows下安裝browser-solidity環境的效果。

image.png

若是成功安裝了browser-solidity,可使用下面的命令啓動Remix服務。

npm start

下圖是Mac OS X下啓動Remix服務後的輸出信息,Windows和Linux會輸出相似的信息。

image.png

Remix服務默認的端口號是8080,若是在瀏覽器地址欄中輸入下面的Url,就可使用本地的Remix環境編寫和測試智能合約。

http://localhost:8080

2. 安裝testrpc

testrpc與geth不一樣,geth是真正的以太坊環境,而testrpc是在本地模擬的一個以太坊環境,主要用於開發調試。當智能合約使用testrpc調試經過後,能夠部署在真正的以太坊環境中。
安裝testrpc仍然須要Node.js環境,因此讀者應該事先安裝好Node.js,而後使用下面的命令安裝testrpc。
npm install -g ethereumjs-testrpc

安裝好testrpc後,可使用testrpc命令運行testrpc。下圖是Mac OS X下啓動testrpc服務的效果。

image.png

下圖是Windows下啓動testrpc服務的效果。

image.png

咱們能夠看到,不論是在哪個平臺上啓動testrpc服務,都會自動生成10個帳號(Accounts)和10個私鑰(Private Keys)。這些帳號和私鑰都是用於測試的,並且每個帳號擁有的以太幣幾乎是無限大的,所以,不用擔憂進行某些操做後沒有以太幣可用。

testrpc自己是一個服務,默認的端口號是8545,這個端口號是用於像web3.js、web3.py同樣的程序庫鏈接以太坊節點的,testrpc其實也至關於一個用於測試的以太坊節點。

3.使用testrpc測試智能合約

本節會將智能合約部署到testrpc服務上,而後使用web3.js鏈接testrpc服務,並調用智能合約中的函數。具體的操做步驟以下:

(1)編寫智能合約

啓動本地的Remix環境,而後在Remix環境中輸入下面的智能合約代碼。

本例編寫了一個名爲Factorial的智能合約程序,在該智能合約中有一個factorial函數,用於計算n的階乘。

pragma solidity ^0.4.0; contract Factorial { /* 計算n的階乘 */ function factorial(uint n) returns (uint) { if (n == 0 || n == 1) return 1; else return n * factorial(n - 1); } }

這個智能合約用於計算n的階乘。

(2)將智能合約部署在testrpc節點上

在Remix環境的右側進入「Run」頁面,並在「Environment」列表中選擇「Web3 Provider」,以下圖所示。

image.png

在Web3 Provider環境下,Remix能夠將智能合約直接部署到testrpc服務上。進入Web3 Provider以前,會彈出一個對話框,詢問是否鏈接以太坊節點,單擊「OK」按鈕,會彈出以下圖所示的對話框。在該對話框中有一個文本框,默認值是http://localhost:8545,若是要鏈接本地的testrpc節點或以太坊節點,直接單擊「OK」按鈕便可。若是testrpc節點已經啓動,那麼Remix本地環境會成功鏈接到testrpc節點上。

image.png

單擊「Run」頁面的「Deploy」按鈕,會將Factorial智能合約部署到testrpc上。部署成功後,會在「Run」頁面的下方出現「factorial」按鈕,以下圖所示。在按鈕右側的文本框輸入要計算階乘的n的值,而後點擊該按鈕便可在以太坊測試環境(testrpc)下執行factorial函數,不過在日誌區域點擊「Details」按鈕後,並無看到factorial函數的輸出結果,這是由於factoria函數是直接在以太坊網絡中運行的,全部的數據都存在於以太坊網絡中,並不會直接將數據返回給以太坊客戶端。

在「factorial」按鈕的上方是Factorial智能合約的地址,若是在客戶端要訪問這個智能合約,須要使用這個地址。

image.png

(3)安裝Solidity編譯器

Solidity編譯器是用於編譯Solidity源代碼文件(.sol文件)的,能夠將Solidity源代碼文件編譯成多種目標文件。使用下面的命令行能夠安裝Solidity編譯器。

npm install -g solc

(4)編譯Solidity源代碼文件

在當前目錄建立一個Factorial.sol文件,而後將例3.2中的代碼複製到Factorial.sol文件中。接下來會使用上一步安裝的Solidity編譯器對Factorial.sol文件進行編譯。要注意,儘管安裝的是solc,但編譯器命令行工具是solcjs。這個工具能夠將Solidity源代碼文件編譯成多種目標文件,對於本例來講,只須要abi文件便可,該文件是智能合約的接口文件。也就是說,使用Web3.js調用智能合約,須要使用abi文件才能調用智能合約中函數。

使用下面的命令能夠將Factorial.sol文件編譯生成abi文件。其中--abi是命令行參數,表示生成的目標文件類型是abi。

solcjs --abi Factorial.sol

執行完上面的命令後,會在當前目錄生成一個Factorial_sol_Factorial.abi文件,該文件就是Factorial.sol對應的abi文件。

(5)安裝Web3.js

在使用Web3.js以前必須安裝Web3.js,Web3.js是Node.js的一個模塊,因此須要使用下面的命令安裝。

npm install web3

使用上面的命令會安裝web3的最新版,若是讀者使用web3最新版不太習慣,可使用下面的命令安裝指定版本。

npm install web3@0.20.6

(6)用Web3.js鏈接testrpc節點

如今執行node命令進入Node.js的REPL環境(命令行交互環境),而後在Node的REPL環境執行下面的命令。要注意,在執行這些命令以前,要先啓動testrpc節點,而且利用Remix環境將例3.2中的智能合約部署到testrpc節點上。

> var Web3 = require("web3"); > var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); undefined > var eth = web3.eth undefined > var abi = JSON.parse(fs.readFileSync("Factorial_sol_Factorial.abi").toString()); undefined > var contract = eth.contract(abi); undefined > var instance = contract.at('0x371f45db1a077bbcbeb50d2a21bc85e4e18c1f1f') undefined > instance.factorial.call(3) { [String: '6'] s: 1, e: 0, c: [ 6 ] } > instance.factorial(10, {from:eth.accounts[0]}) '0xbb291fec53c4c5aefc87e2d7e8475c4abd4c54d03ef06e857665a10db0c1a3ff'

上面的內容中「>」表示命令提示符,後面是輸入的代碼,下面是輸出值,undefined是Node輸出的,表示當前語句什麼也沒有輸出(定義變量的JavaScript語句不會輸出任何東西)。從這幾行代碼能夠了解經過Web3.js鏈接testrpc節點的核心步驟(與鏈接以太坊節點的步驟相同)以下。

(1)導入web3模塊,代碼以下:

var Web3 = require("web3");

(2)建立Web3類的實例,並經過該類的構造方法參數指定testrpc節點的Url(IP和端口號),代碼以下:

var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

(3)讀取Factorial_sol_Factorial.abi文件的內容,並將文件的內容轉換爲JSON對象,代碼以下:

var abi = JSON.parse(fs.readFileSync("Factorial_sol_Factorial.abi").toString());

(4)使用abi建立智能合約對象,代碼以下:

var contract = eth.contract(abi);

(5)將智能合約與testrpc中部署的智能合約綁定,代碼以下:

var instance = contract.at('0x371f45db1a077bbcbeb50d2a21bc85e4e18c1f1f') 

其中at方法的參數值就是圖3-12所示的factorial方法上方的智能合約地址,也是以太坊中惟一能定位特定智能合約的標識。點擊地址右側的按鈕能夠將該地址複製到剪貼板上。

(6)本地調用智能合約中的factorial函數,代碼以下:

instance.factorial.call(3)

本地調用智能合約,不會對以太坊網絡形成任何影響。本地調用智能合約中的函數會直接輸出函數的返回值,若是函數返回的是數值類型,會以BigNumber類型返回,這是一個JavaScript擴展,容許JavaScript操做任何的數值,BigNumber類型會在本書後面的章節詳細講解。

執行上面的代碼,會輸出以下內容,很明顯,3的階乘是6。

[String: '6'] s: 1, e: 0, c: [ 6 ] }

(7)在以太坊網絡上調用智能合約,代碼以下:

instance.factorial(10, {from:eth.accounts[0]})

在以太坊網絡上調用智能合約的函數不會在客戶端直接獲得函數的返回值,而會獲得一個以下的交易地址。

0xbb291fec53c4c5aefc87e2d7e8475c4abd4c54d03ef06e857665a10db0c1a3ff

由於任何在以太坊網絡上進行的操做都被視做一次交易,既然有交易,就須要有交易地址,能夠經過相應的API根據交易地址查詢交易狀況。在以太坊網絡中有不少類型的地址,如礦工地址、智能合約地址、交易地址等。每一類地址都由若干位十六進制數組成,但不一樣類型地址的位數可能不一樣。

在真正的以太坊網絡中,任何交易都須要礦工挖礦進行處理,同時每一筆交易會給與完成工做的礦工必定的獎勵,也就是礦工的挖礦所得。不過在testrpc節點中因爲是模擬以太坊網絡和挖礦,因此不須要挖礦,直接會執行以太坊網絡上的操做,所以,若是客戶端鏈接的是testrpc節點,發起交易後,會馬上執行。另外,在以太坊網絡上調用智能合約,須要指定是誰(一個表示用戶的地址)發起的交易,由於在實際的以太坊網絡中,要從這個地址扣除相應的以太幣給礦工。本例使用eth.accounts[0]指定的地址。其中eth.accounts能夠獲取testrpc節點啓動時生成的10個測試帳戶的地址,eth.accounts[0]就是第一個測試帳戶的地址。

從本節的案例來看,客戶端訪問以太坊網絡的步驟就是鏈接以太坊節點和發起交易兩步,固然,以太坊網絡要處理交易,就須要礦工挖礦(爭奪處理交易的權利,同時得到回報)了。
3.2.4 Intellij IDEA Solidity插件
不論是Remix,仍是Windows記事本,或是其餘的文本編輯器,都不會用於開發複雜的智能合約,一是界面並不友好,二是也沒有必要的智能提示功能,並且若是智能合約的代碼量很大,可能會形成Remix死掉。因此前面介紹的工具只是爲了測試智能合約的,並非用來開發實際的智能合約項目的。若是要開發大型的智能合約項目,一般會使用本地的IDE,如Intellij IDEA。這款IDE最初是爲開發Java項目推出的,不過因爲Intellij IDEA支持第三方插件,因此從理論上,Intellij IDEA能夠支持任何的編程語言。

可能不少讀者對Intellij IDEA並不熟悉,實際上,這款IDE就是大名鼎鼎的JetBrains公司推出的,若是不瞭解JetBrains以及它的產品,那麼對Android和Google推出的Android開發工具Android Studio必定不陌生,Android Studio就是在Intellij IDEA社區版的基礎上開發的。並且JetBrains公司還開發出了大名鼎鼎的Kotlin語言,如今已經成爲開發Android App的官方推薦編程語言。

讀者能夠到下面的頁面下載Intellij IDEA的免費版本(社區版)。
https://www.jetbrains.com/idea/download

Solidity語言一樣提供了Intellij IDEA插件,建議使用在線安裝方式。若是是Mac OSX版本的Intellij IDEA,單擊左上角的IntelliJ IDEA菜單的Preferences菜單項,以下圖所示。

image.png

若是是Windows版的Intellij IDEA,須要單擊File菜單的Settings菜單項。單擊該菜單項後,會彈出偏好(設置)窗口,以下圖所示。

image.png

Preferences窗口中間的列表列出了Intellij IDEA已經安裝的全部插件。單擊窗口下方的Browse repositories按鈕,會彈出Browse Repositories窗口,在窗口左上角的文本框中輸入Solidity,會在線搜索相關的插件,以下圖所示,若是找到,會在右側顯示當前選中插件的詳細信息,若是沒有安裝該插件,會在右側顯示install按鈕,單擊install按鈕便可安裝插件。

image.png

安裝完插件後,在Intellij IDEA中建立一個Java或其餘工程(Solidity插件並無提供Solidity工程),而後在工程右鍵菜單中單擊new菜單項,會顯示以下圖所示的子菜單。在子菜單上會找到一個Smart contract菜單項。

image.png

單擊Smart contract菜單項,會顯示以下圖所示的New Solidity File窗口,從Kind列表框能夠選擇Solidity文件類型(Smart contract或Solidity library),本例選擇Smart contract。

image.png

在Name文本框中輸入Solidity文件名後,單擊OK按鈕建立Solidity文件。而後在Intellij IDEA左側的工程樹中雙擊剛纔建立的Solidity文件,會在右側顯示代碼編輯區域,並輸入以下圖所示的Solidity代碼。

image.png

儘管能夠在Intellij IDEA中編寫Solidity代碼,也支持代碼高亮顯示和智能提示,但編譯Solidity源代碼文件仍然須要切換到終端,使用solcjs命令編譯,很麻煩,因此在下一節會教你們如何將solcjs命令集成進Intellij IDEA,無需切換到終端就能夠編譯Solidity源代碼文件。

5.將Solidity編譯工具與Intellij IDEA集成

Intellij IDEA有一個擴展工具功能,能夠將可執行程序與Intellij IDEA集成,也就是說,不用切換到終端,就能夠執行這些程序。

如今打開偏好窗口(Windows中是設置窗口),在左側區域找到Tools > External Tools節點,單擊該節點後,會在右側顯示當前集成的擴展工具列表,默認是空。而後單擊該區域下方「+」按鈕,會彈出一個Create Tool窗口,在該窗口須要填寫以下4個字段。

  • Name:solidity
  • Program:solcjs
  • Parameters:--abi --bin $FileName$ -o $OutputPath$
  • Working directory:$FileDir$

填寫後的效果以下圖所示,最後單擊OK按鈕建立擴展工具。

image.png

建立擴展工具應該瞭解以下幾點。

  • Name只是用於顯示的擴展工具名字,能夠任意指定,甚至能夠與已經存在的擴展工具重名。
  • Program指定的solcjs命令要在終端能夠直接執行,不然會出現沒法執行該命令的錯誤。因此在建立擴展工具以前,先要使用npm install -g solc命令安裝solcjs。
  • Parameters表示solcjs的命令行參數,其中--abi表示將Solidity源代碼文件編譯成接口文件(.abi文件),--bin表示將Solidity源代碼文件編譯成二進制文件(.bin文件),用於發佈智能合約。儘管這兩類文件並非在任什麼時候候都須要,但爲了省事,乾脆將它們一塊兒生成吧。
  • -o表示生成的目標文件(.abi和.bin文件)的路徑。
  • $FileName$、$OutputPath$和$FileDir$都是Intellij IDEA提供的環境變量,$FileName$表示當前選擇的文件名,$OutputPath$表示文件的輸出目錄,$FileDir$表示當前選擇文件所在的目錄。

若是是在Mac OS X下,$OutputPath$指向工程目錄的out子目錄,與工程相關的生成文件都放在這個目錄中,目錄結構與src目錄相同。圖3-20是out目錄的結構,注意,讀者機器上的目錄結構可能有差別,但.abi和.bin文件都在out/production目錄或其子目錄中。

image.png

若是在Windows下,並不能執行solcjs文件,由於這個文件是在Mac OS X和Linux使用的,Windows下是solcjs.cmd,因此要將Program改爲solcjs.cmd。而Windows版的Intellij IDEA並無內置的$OutputPath$變量,因此能夠將這個變量改爲其餘的值,如$FileDir$,這樣以來,就會在.sol文件同一個目錄生成.abi和.bin文件。因此Windows版的Intellij IDEA須要按下面的內容設置擴展工具。

  • Name:solidity
  • Program:solcjs.cmd
  • Parameters:--abi --bin $FileName$ -o $FileDir$
  • Working directory:$FileDir$

按前面的方式設置完擴展工具後,選中一個.sol文件(假設文件名是MyCalc.sol,裏面的智能合約名是Calc),在Intellij IDEA的Tools > External Tools 菜單中出現了一個solidity菜單項,如圖3-21所示,單擊該菜單項,就會調用solcjs編譯MyCalc.sol文件,並在相應的目錄生成MyCalc_sol_Calc.abi和MyCalc_sol_Calc.bin文件。

image.png

其實在工程的右鍵菜單中也能夠找到External Tools > solidity菜單項,以下圖所示,單擊該菜單項,效果是同樣的。

image.png

相關文章
相關標籤/搜索