1. 程式人生 > >以太坊智慧合約學習筆記:使用Truffle框架開發部署智慧合約

以太坊智慧合約學習筆記:使用Truffle框架開發部署智慧合約

truffle是一個智慧合約的開發框架,具體的就不介紹了,我們主要是說說怎麼使用這個框架來進行智慧合約的開發,官網戳這裡

文章目錄


#安裝
首先我們要先安裝npm和truffle,安裝命令如下

 sudo apt install npm
 sudo npm install -g truffle

#建立專案
首先建立一個空目錄,然後進去,終端執行

truffle init

該命令一定要在空目錄下執行,否則會出錯
命令執行完畢後會下載一些初始檔案,這些檔案不用動,目錄結構如下
初始化後的目錄結構

#編譯合約
在contracts目錄下建立Voting.sol,將上一篇

以太坊智慧合約學習筆記:開發流程及工具鏈使用中我們用到的合約的內容寫進去
然後在migrations目錄下建立2_deploy_contracts.js,寫入如下內容

var Voting = artifacts.require("./Voting.sol");
  
module.exports = function(deployer) {
          deployer.deploy(Voting,["Rama","Nick","Jose"]);
};

其中[“Rama”,“Nick”,“Jose”]是合約的構造引數
然後編輯truffle.js,將其中的內容修改如下

module.exports = {
        networks: {
                development: {
                        host: "127.0.0.1",
                        port: 8545,
                        network_id: "*", // Match any network id
                        gas:500000
                }
        }
};

最後,執行“truffle test”命令進行測試,測試沒問題了執行“truffle compile”命令進行編譯。
#部署
##部署到geth
另啟一個終端,換個其他目錄,執行下面的命令

geth --datadir testNet --dev --rpc console 2>>test.log

和上一篇不用truffle的命令相比,多了一個–rpc引數
啟動geth監聽後,回到truffle專案目錄,執行“truffle migrate”命令進行部署,如果成功,將輸出如下內容

Using network 'development'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0x39ffa2af2418c0c4ccc2cd2ad4514cd529f6bc9cba055e409e76538eada2da98
  Migrations: 0xec910e955228312bf018f845fe402444881b6723
Saving successful migration to network...
  ... 0x80f21dbda606d0fbd2a7c9ff3e45bb6356ef8ac04fb6aec052018edf57495ac9
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying Voting...
  ... 0x2143e82ca657417e388a30ed0db4fb5b36928ea979da7f366537f6de374820d1
  Voting: 0xa2ac81866309c37b5e8d54e275df07fa7bdd74b5
Saving successful migration to network...
  ... 0x855c0c19ee0a8baf0dfb42a88203d5307bb1b3ed772f901ed843c20999964d64
Saving artifacts...

記住 Voting: 0xa2ac81866309c37b5e8d54e275df07fa7bdd74b5這個地址,後面我們還會用到。
接下來開啟build/contracts/Voting.json,找到abi欄位的內容,將內容壓縮成一行,內容如下

[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]

然後回到geth控制檯,定義變數abi,並將上面的json值賦值給變數abi,即在geth的控制檯中輸入如下內容

abi = [{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]

合約的abi定義完成,接下來是使用部署時返回的合約地址去例項化合約,geth的控制檯中輸入如下內容

voting = eth.contract(abi).at('0xa2ac81866309c37b5e8d54e275df07fa7bdd74b5')

至此,geth合約部署完成。
##部署到truffle的內建測試網路
自帶了一個測試網路,不與乙太網絡相連,只是一個單機的測試網路。
將工作目錄切換到truffle工程目錄,在終端輸入truffle develop進入測試控制檯
測試網路會初始化10個賬戶用於測試,然後在測試控制檯輸入“migrate”進行部署
部署的完成後的返回結果和上面的geth返回的結果完全相同,同樣包含一個合約地址
##部署到Ganache
Ganache也是一個用於測試的工具,分為命令列和圖形介面兩種
圖形介面的下載戳這裡
命令列下載用這條命令

sudo npm install -g ganache-cli

由於我是使用ssh在遠端機器上做測試,圖形介面用著不方便,我們這裡使用命令列
新開個終端,在終端中輸入“ganache-cli”,同樣會建立10個測試賬戶
看輸出資訊的最後一行顯示的IP和埠

Listening on 127.0.0.1:8545

修改truffle.js的內容如下

module.exports = {
	networks: {
	    development: {
	        host: "127.0.0.1",
	        port: 8545,
	        network_id: "*"
	    }
	}
};

host和port改成上面輸出的IP和埠
然後回到truffle工程目錄的控制檯,終端輸入truffle migrate進行部署,同樣要記住返回的合約地址,部署完成。
#互動
##geth控制檯合約互動
互動和前面一篇沒有使用truffle的互動一樣,可以檢視前一篇以太坊智慧合約學習筆記:開發流程及工具鏈使用的內容。
##truffle的內建測試網路互動
部署完成後,返回一個合約地址,我們就可以用這個合約地址進行互動了,比如要查詢Rama的票數可以這樣寫

Voting.at("0x345ca3e014aaf5dca488057592ee47305d9b3e10").totalVotesFor("Rama")

然後返回如下結果

BigNumber { s: 1, e: 0, c: [ 0 ] }

其中c的值就是查詢的值了
但是這樣使用合約有點麻煩,所以我們用一個變數儲存合約例項

voting = Voting.at("0x345ca3e014aaf5dca488057592ee47305d9b3e10")

以後就可以直接用變數voting來呼叫合約的方法了,例如

voting.voteForCandidate('Rama', {from: web3.eth.accounts[0]})
voting.totalVotesFor('Rama')

還可以使用下面的方法查詢餘額

web3.eth.getBalance(web3.eth.accounts[0])

其他就和geth的用法差不多了
##Ganache測試網路互動
輸入命令“truffle console”進入truffle控制檯
輸入“voting = Voting.at(“0x27f77eeae7d192c300d5776acb782cc971fc8423”)”,那個大長串的十六進位制就是合約的地址
然後就和在truffle的內建測試網路互動一樣了。