以太坊智慧合約學習筆記:使用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的內建測試網路互動一樣了。