您好,登錄后才能下訂單哦!
《第一行代碼:以太坊》開始連載了
在上文中已經使用了Remix環境運行和測試了本書編寫的第一個智能合約程序,不過編寫和測試智能合約的測試方式很多,例如,在testrpc環境測試;在Intellij IDEA集成開發環境中用Solidity語言編寫智能合約;在純Web環境中測試智能合約;使用AJAX方式測試智能合約等。本文將詳細介紹這些用于編寫和測試智能合約的方法。
在本節使用Remix環境運行和測試了Calc智能合約,不過使用的是在線Remix環境。由于某些原因(如沒有網絡,或網絡速度很慢),我們希望使用本地的Remix環境運行和測試智能合約,這就要就將Remix環境安裝在本地。Remix是跨平臺的,所以本節介紹的安裝方法同時適用于Windows、Mac OS X和Linux。
不管是在什么操作系統下安裝Remix,都必須安裝Node.js,讀者可以到https://nodejs.org下載Node.js的最新版直接安裝即可。
安裝完Node.js后,需要使用git命令下載Remix的代碼庫(browser-solidity),命令行如下:
git clone https://github.com/ethereum/browser-solidity
在Mac OS X和Linux下,一般會集成git命令,但在Windows下,默認是沒有git命令的,所以需要到下面的頁面下載Windows版的git工具,下載完后直接安裝即可。
https://git-scm.com/download/win
使用git命令下載完Remix的代碼庫后,使用cd命令進入browser-solidity目錄,該目錄在下載Remix代碼庫的過程中自動在當前目錄中創建。
在browser-solidity目錄中執行下面的命令安裝browser-solidity。
npm install
安裝browser-solidity的過程比較漫長,讀者要耐心等待。下圖是在Windows下安裝browser-solidity環境的效果。
如果成功安裝了browser-solidity,可以使用下面的命令啟動Remix服務。
npm start
下圖是Mac OS X下啟動Remix服務后的輸出信息,Windows和Linux會輸出類似的信息。
Remix服務默認的端口號是8080,如果在瀏覽器地址欄中輸入下面的Url,就可以使用本地的Remix環境編寫和測試智能合約。
http://localhost:8080
testrpc與geth不同,geth是真正的以太坊環境,而testrpc是在本地模擬的一個以太坊環境,主要用于開發調試。當智能合約使用testrpc調試通過后,可以部署在真正的以太坊環境中。
安裝testrpc仍然需要Node.js環境,所以讀者應該事先安裝好Node.js,然后使用下面的命令安裝testrpc。
npm install -g ethereumjs-testrpc
安裝好testrpc后,可以使用testrpc命令運行testrpc。下圖是Mac OS X下啟動testrpc服務的效果。
下圖是Windows下啟動testrpc服務的效果。
我們可以看到,不管是在哪一個平臺上啟動testrpc服務,都會自動生成10個賬號(Accounts)和10個私鑰(Private Keys)。這些賬號和私鑰都是用于測試的,而且每一個賬號擁有的以太幣幾乎是無限大的,因此,不用擔心進行某些操作后沒有以太幣可用。
testrpc本身是一個服務,默認的端口號是8545,這個端口號是用于像web3.js、web3.py一樣的程序庫連接以太坊節點的,testrpc其實也相當于一個用于測試的以太坊節點。
本節會將智能合約部署到testrpc服務上,然后使用web3.js連接testrpc服務,并調用智能合約中的函數。具體的操作步驟如下:
啟動本地的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的階乘。
在Remix環境的右側進入“Run”頁面,并在“Environment”列表中選擇“Web3 Provider”,如下圖所示。
在Web3 Provider環境下,Remix可以將智能合約直接部署到testrpc服務上。進入Web3 Provider之前,會彈出一個對話框,詢問是否連接以太坊節點,單擊“OK”按鈕,會彈出如下圖所示的對話框。在該對話框中有一個文本框,默認值是http://localhost:8545,如果要連接本地的testrpc節點或以太坊節點,直接單擊“OK”按鈕即可。如果testrpc節點已經啟動,那么Remix本地環境會成功連接到testrpc節點上。
單擊“Run”頁面的“Deploy”按鈕,會將Factorial智能合約部署到testrpc上。部署成功后,會在“Run”頁面的下方出現“factorial”按鈕,如下圖所示。在按鈕右側的文本框輸入要計算階乘的n的值,然后點擊該按鈕即可在以太坊測試環境(testrpc)下執行factorial函數,不過在日志區域點擊“Details”按鈕后,并沒有看到factorial函數的輸出結果,這是因為factoria函數是直接在以太坊網絡中運行的,所有的數據都存在于以太坊網絡中,并不會直接將數據返回給以太坊客戶端。
在“factorial”按鈕的上方是Factorial智能合約的地址,如果在客戶端要訪問這個智能合約,需要使用這個地址。
Solidity編譯器是用于編譯Solidity源代碼文件(.sol文件)的,可以將Solidity源代碼文件編譯成多種目標文件。使用下面的命令行可以安裝Solidity編譯器。
npm install -g solc
在當前目錄創建一個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文件。
在使用Web3.js之前必須安裝Web3.js,Web3.js是Node.js的一個模塊,所以需要使用下面的命令安裝。
npm install web3
使用上面的命令會安裝web3的最新版,如果讀者使用web3最新版不太習慣,可以使用下面的命令安裝指定版本。
npm install web3@0.20.6
現在執行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節點的核心步驟(與連接以太坊節點的步驟相同)如下。
var Web3 = require("web3");
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var abi = JSON.parse(fs.readFileSync("Factorial_sol_Factorial.abi").toString());
var contract = eth.contract(abi);
var instance = contract.at('0x371f45db1a077bbcbeb50d2a21bc85e4e18c1f1f')
其中at方法的參數值就是圖3-12所示的factorial方法上方的智能合約地址,也是以太坊中唯一能定位特定智能合約的標識。點擊地址右側的按鈕可以將該地址復制到剪貼板上。
instance.factorial.call(3)
本地調用智能合約,不會對以太坊網絡造成任何影響。本地調用智能合約中的函數會直接輸出函數的返回值,如果函數返回的是數值類型,會以BigNumber類型返回,這是一個JavaScript擴展,允許JavaScript操作任何的數值,BigNumber類型會在本書后面的章節詳細講解。
執行上面的代碼,會輸出如下內容,很明顯,3的階乘是6。
[String: '6'] s: 1, e: 0, c: [ 6 ] }
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菜單項,如下圖所示。
如果是Windows版的Intellij IDEA,需要單擊File菜單的Settings菜單項。單擊該菜單項后,會彈出偏好(設置)窗口,如下圖所示。
Preferences窗口中間的列表列出了Intellij IDEA已經安裝的所有插件。單擊窗口下方的Browse repositories按鈕,會彈出Browse Repositories窗口,在窗口左上角的文本框中輸入Solidity,會在線搜索相關的插件,如下圖所示,如果找到,會在右側顯示當前選中插件的詳細信息,如果沒有安裝該插件,會在右側顯示install按鈕,單擊install按鈕即可安裝插件。
安裝完插件后,在Intellij IDEA中創建一個Java或其他工程(Solidity插件并沒有提供Solidity工程),然后在工程右鍵菜單中單擊new菜單項,會顯示如下圖所示的子菜單。在子菜單上會找到一個Smart contract菜單項。
單擊Smart contract菜單項,會顯示如下圖所示的New Solidity File窗口,從Kind列表框可以選擇Solidity文件類型(Smart contract或Solidity library),本例選擇Smart contract。
在Name文本框中輸入Solidity文件名后,單擊OK按鈕創建Solidity文件。然后在Intellij IDEA左側的工程樹中雙擊剛才創建的Solidity文件,會在右側顯示代碼編輯區域,并輸入如下圖所示的Solidity代碼。
盡管可以在Intellij IDEA中編寫Solidity代碼,也支持代碼高亮顯示和智能提示,但編譯Solidity源代碼文件仍然需要切換到終端,使用solcjs命令編譯,很麻煩,所以在下一節會教大家如何將solcjs命令集成進Intellij IDEA,無需切換到終端就可以編譯Solidity源代碼文件。
Intellij IDEA有一個擴展工具功能,可以將可執行程序與Intellij IDEA集成,也就是說,不用切換到終端,就可以執行這些程序。
現在打開偏好窗口(Windows中是設置窗口),在左側區域找到Tools > External Tools節點,單擊該節點后,會在右側顯示當前集成的擴展工具列表,默認是空。然后單擊該區域下方“+”按鈕,會彈出一個Create Tool窗口,在該窗口需要填寫如下4個字段。
填寫后的效果如下圖所示,最后單擊OK按鈕創建擴展工具。
創建擴展工具應該了解如下幾點。
如果是在Mac OS X下,$OutputPath$指向工程目錄的out子目錄,與工程相關的生成文件都放在這個目錄中,目錄結構與src目錄相同。圖3-20是out目錄的結構,注意,讀者機器上的目錄結構可能有差異,但.abi和.bin文件都在out/production目錄或其子目錄中。
如果在Windows下,并不能執行solcjs文件,因為這個文件是在Mac OS X和Linux使用的,Windows下是solcjs.cmd,所以要將Program改成solcjs.cmd。而Windows版的Intellij IDEA并沒有內置的$OutputPath$變量,所以可以將這個變量改成其他的值,如$FileDir$,這樣以來,就會在.sol文件同一個目錄生成.abi和.bin文件。所以Windows版的Intellij IDEA需要按下面的內容設置擴展工具。
按前面的方式設置完擴展工具后,選中一個.sol文件(假設文件名是MyCalc.sol,里面的智能合約名是Calc),在Intellij IDEA的Tools > External Tools 菜單中出現了一個solidity菜單項,如圖3-21所示,單擊該菜單項,就會調用solcjs編譯MyCalc.sol文件,并在相應的目錄生成MyCalc_sol_Calc.abi和MyCalc_sol_Calc.bin文件。
其實在工程的右鍵菜單中也可以找到External Tools > solidity菜單項,如下圖所示,單擊該菜單項,效果是一樣的。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。