以太坊学习路线——(四、上)Truffle安装、truffle项目创建、编译、部署
這篇博客演示的基本操作系統環境是CentOS 7,參考書籍:以太坊開發實戰——以太坊關鍵技術與案例分析 第十章(吳壽鶴、馮翔、劉濤、周廣益?? 著)。鑒于內容較多,分成兩篇,下一篇博文請見:以太坊學習路線——(四、下)truffle項目合約交互、合約測試、配置文件、依賴管理
文章結構:
一、Truffle簡介
二、安裝Truffle
三、創建并初始化項目
四、創建合約
五、編譯合約
六、遷移合約
?
一、Truffle簡介
- Solidity學習網站
- 通過密碼僵尸游戲學習Solidity
- Truffle學習網站
Truffle是一套針對以太坊Solidity語言的開發框架,本身基于javascript。Truffle為以太坊提供了開發環境、測試框架和資產管道(pipeline),旨在使以太坊開發更加容易。Truffle特性:
- 內置的智能合約編譯,鏈接,部署和二進制文件的管理。
- 快速開發下的自動合約測試。
- 腳本化的,可擴展的部署與發布框架。
- 部署到不管多少的公網或私網的網絡環境管理功能
- 使用EthPM&NPM提供的包管理,使用ERC190標準。
- 與合約直接通信的直接交互控制臺(寫完合約就可以命令行里驗證了)。
- 可配的構建流程,支持緊密集成。
- 在Truffle環境里支持執行外部的腳本。
二、安裝Truffle
$ npm install -g truffle檢查Turffle是否正確安裝:
[root@localhost myproject]# truffle Truffle v5.0.10 - a development framework for EthereumUsage: truffle <command> [options]Commands:build Execute build pipeline (if configuration present)compile Compile contract source filesconfig Set user-level configuration optionsconsole Run a console with contract abstractions and commands availablecreate Helper to create new contracts, migrations and testsdebug Interactively debug any transaction on the blockchain(experimental)deploy (alias for migrate)develop Open a console with a local development blockchainexec Execute a JS module within this Truffle environmenthelp List all commands or provide information about a specific commandinit Initialize new and empty Ethereum projectinstall Install a package from the Ethereum Package Registrymigrate Run migrations to deploy contractsnetworks Show addresses for deployed contracts on each networkobtain Fetch and cache a specified compileropcode Print the compiled opcodes for a given contractpublish Publish a package to the Ethereum Package Registryrun Run a third-party commandtest Run JavaScript and Solidity testsunbox Download a Truffle Box, a pre-built Truffle projectversion Show version number and exitwatch Watch filesystem for changes and rebuild the projectautomaticallySee more at http://truffleframework.com/docs //我的truffle版本 [root@localhost myproject]# truffle version Truffle v5.0.10 (core: 5.0.10) Solidity v0.5.0 (solc-js) Node v11.13.0 Web3.js v1.0.0-beta.37?三、創建并初始化項目
$ mkdir myproject $ cd myproject $ truffle init//完成后目錄結構如下: [root@localhost myproject1]# tree ./ ./ ├── contracts │?? └── Migrations.sol ├── migrations │?? └── 1_initial_migration.js ├── test └── truffle-config.js- contracts/:存放我們編寫的合約。
- migrations/:存放遷移部署腳本
- test/:存放合約測試腳本。
- truffle-config.js/:存放truffle配置文件。
較早版本truffle init會在目錄中創建一個名叫MetaCoin的代幣應用。將這個應用相關文件刪除,直到和上面的目錄結構相同。
四、創建合約
在contracts目錄下創建自己的合約Storage.sol:
$ cd contracts/ $ vi Storage.sol//合約內容如下:根據編譯器版本不同,可能會出現不同的錯誤與警告,請自己核實處理 pragma solidity >=0.4.21 <0.6.0;contract Storage {uint256 public storedData;function set(uint256 data) public {storedData = data;}function get() public view returns (uint256) {return storedData;} }五、編譯合約
[root@localhost myproject]# truffle compileCompiling your contracts... =========================== > Compiling ./contracts/Storage.sol > Artifacts written to /opt/myproject/build/contracts > Compiled successfully using:- solc: 0.5.0+commit.1d4f565a.Emscripten.clang?從輸出結果可以看到,合約編譯后的文件會寫入./build/contracts目錄中,這些合約編譯好之后的文件對于Truffle框架能否正常工作至關重要。請不要手動修改這些文件,因為即使修改了,再次執行編譯命令時又會被覆蓋。
Truffle默認只編譯自上次編譯后修改過的合約,目的是減少不必要的編譯。如果你想編譯全部合約,可以使用--all選項。
$ truffle compile --all六、遷移合約
遷移腳本是由一些javascript文件組成,在truffle中部署合約需要用到遷移腳本。這是因為你的部署需求會隨著時間改變。隨著項目的發展,你可以創建新的遷移腳本把這些變化的合約部署到區塊鏈上。之前你運行的遷移歷史記錄,會被一個特殊的Migrations.sol合約記錄在區塊鏈。
遷移合約命名規則:文件以數字開頭,以一個描述性的后綴結尾。數字前綴是必須的,用于記錄移植是否成功。后綴僅僅是為了提高可讀性,以方便理解。
下面進入migrations目錄中為Storage合約創建一個遷移腳本:
$ cd migrations $ touch 2_storage_migrations.js//遷移腳本2_storage_migrations.js內容: const Migrations = artifacts.require("Storage");module.exports = function(deployer) {deployer.deploy(Migrations); };1.artifacts.require()
在遷移腳本中的最開始,通過artifacts.require()方法告訴truffle我們將要與哪個合約交互。這個方法類似于Nodejs中的require,但在這里,它返回的是一個合約抽象。我們可以在遷移腳本的其余部分中使用這個合約抽象。artifacts.require()參數中使用的名字不是必須與合約源文件的文件名相同,相反,它應該與在合約源代碼中定義的合約類定義的合約類的名稱相同。
2.module.exports
在遷移合約腳本最后,我們通過module.exports導出一個函數,被遷移腳本導出的函數都應高接受一個depoyer對象作為其第一個參數。
3.遷移合約
至此就可以把Storage.sol部署到區塊鏈上了,這次把智能合約部署到Testrpc環境中。
//如果你還沒有安裝Testrpc那么先執行下面的命令,其需要Node較高版本的環境依賴 $ npm install -g ethereumjs-testrpc//安裝完成后啟動Testrpc: $ testrpctestrpc啟動后,回到myproject項目的目錄中,通過執行下面的命令就可以完成合約遷移:
$ truffle migrate但是由于的truffle版本是,所以出現了如下問題:
Compiling your contracts... =========================== > Everything is up to date, there is nothing to compile.Could not connect to your Ethereum client with the following parameters:- host > 127.0.0.1- port > 7545- network_id > 5777 Please check that your Ethereum client:- is running- is accepting RPC connections (i.e., "--rpc" option is used in geth)- is accessible over the network- is properly configured in your Truffle configuration file (truffle-config.js)Truffle v5.0.10 (core: 5.0.10) Node v11.13.0猜測可能是提示檢測的最后一條選項,所以打開truffle-config.js,設置其中部分內容如下:
networks: {// Useful for testing. The `development` name is special - truffle uses it by default// if it's defined here and no other network is specified at the command line.// You should run a client (like ganache-cli, geth or parity) in a separate terminal// tab if you use this network and you must also set the `host`, `port` and `network_id`// options below to some value.//development: {host: "127.0.0.1", // Localhost (default: none)port: 8545, // Standard Ethereum port (default: none)network_id: "*", // Any network (default: none)},修改后重新遷移,部分顯示結果如下:
2_storage_migration.js ======================Deploying 'Storage'-------------------> transaction hash: 0x92cb91d96ddce4c5f5f73ba7b31a6d26b7f92e6a9b559f5e624281e35be8a50c> Blocks: 0 Seconds: 0> contract address: 0x92Afc835189BAf7a82AFfa45282eFbAa449da4c6> account: 0xF8A0A572fF93C87A711D7B6FD71b7b81650daCE1> balance: 99.99084662> gas used: 130727> gas price: 20 gwei> value sent: 0 ETH> total cost: 0.00261454 ETH> Saving migration to chain.> Saving artifacts-------------------------------------> Total cost: 0.00261454 ETH?從顯示信息可以看出在部署Storage合約時,是以交易的形式將合約發布到測試網絡中,可以看到發布合約的交易地址hash,合約地址、合約用戶account帳號……,而且在testrpc終端也可以看到相同的操作記錄:
Transaction: 0x92cb91d96ddce4c5f5f73ba7b31a6d26b7f92e6a9b559f5e624281e35be8a50cContract created: 0x92afc835189baf7a82affa45282efbaa449da4c6Gas usage: 130727Block Number: 3Block Time: Tue Apr 02 2019 09:26:46 GMT+0800 (Hong Kong Standard Time)truffle migrate命令會執行所有位于migrates目錄內的遷移腳本。如果你之前已經成功執行過遷移腳本,那么truffle migrage僅會執行新創建的遷移。如果沒有新的遷移腳本,這個命令不會執行任何操作,可使用選項--reset來重新執行全部遷移腳本。
$ truffle migrate --reset4.初始化性的遷移合約
為了使用遷移功能,Truffle要求你要有一個遷移合約。這個合約必須包含一個特定的接口,對于大多數項目來說,這個合約只會在第一次做遷移的時被部署,以后都不會做任何更改了。這個合約就是在一開始truffle init之后在contracts目錄下默認創建的那個Migrations.sol文件。
為了利用遷移的特性,首先必須部署這個Migrations.sol合約,所以truffle init時也默認在migrations目錄下創建了該合約的遷移腳本:1_initial_migrations.js????? 要部署其他合約你可以遞增數字編號前綴來創建新的遷移腳本。
5.部署器(deployer)
你的遷移腳本會使用deployer對象來組織部署任務。deployer對象會同步執行部署任務,故你可以按順序編寫部署任務。
//先部署A,后部署B deployer.deploy(A); deployer.deploy(B);另外,deployer上的每一個函數都會返回一個promise,通過promise可以把有執行順序依賴關系的部署任務組成隊列。
//先部署A,然后部署B,把A部署后的地址傳給B deployer.deploy(A).then( function () {return deployer.deploy(B,A.address); });6.deployer API
(1).deployer.deploy(CONTRACT,ARGS…,OPTIONS)
這個API用來部署合約,contract參數傳入需要部署的合約名字,args參數傳入合約的構造函數需要的參數,options是一個可選參數,它的值是{overwrite:true/false}。如果overwrite被設置為false,那么當這個合約之前已經部署過了,這個deployer就不會再部署這個合約,這在一個合約的依賴由另一個外部地址提供的情況下是有用的。為了快速進行部署多個合約,你可以向deployer。deploy(…)函數中傳入一個或多個數組。eg:
//部署單個合約,不帶任何構造參數 deployer.deploy(A);//部署單個合約帶有構造參數 deployer.deploy(A,arg1,arg2,……);//部署多個合約,有的帶有構造參數,有的不帶構造參數 //比寫三次deployer.deploy()語句更快,因為deployer可以把所有的合約部署一次性打包提交 deployer.deploy([[A,arg1,arg2,…],[B],[C,arg1] ]);//外部依賴的例子: //overwrite:false表示如果SomeDependency合約之前已經被部署過,那么不再重復部署,之結使用之前已經部署好的地址 //如果合約要運行在自己的測試鏈上,或者將要運行的鏈上沒有SomeDependency合約, //那么把overwrite:false改為ovwewrite:true,表示不再檢查之前SomeDependency有沒有部署過,一律覆蓋部署 deployer.deploy(SomeDependency,{overwrite:false});(2).deployer.link(LIBRARY,DESTINATIONS)
把一個已部署好的庫鏈接到一個或多個合約里。destinations可以傳入一個合約,也可以傳入一組合約。如果destinations中的某個合約不依賴這個庫,那么deployer的link函數就會忽略這個合約。
//部署庫LibA,然后把LibA鏈接到合約B,然后部署合約B deployer.deploy(LibA); deployer.link(LibA,B); deployer.deploy(B);//庫LibA鏈接到多個合約 deployer.link(LibA,[B,C,D]);(3).deployer.then(function() {…})
在遷移過程中使用它調用特定合約的函數來部署新的合約,為已部署的合約做一些初始化工作等。eg:
var a,b; deployer.then(function () {//部署合約A的一個新版本到網絡上return A.new(); }).then(function (instance) {a = instance;//獲取已部署的合約B的實例return B.deployed(); }).then(function (instance) {b = instance;//使用合約B的setA()方法設置A的地址的新實例return b.setA(a.address); });(4).網絡相關
在執行遷移時,Truffle會把truffle-config.js里配置的networks傳遞給遷移腳本,你可以在遷移腳本中的module.exports導出函數中的第二個參數位置接受這個networks參數值。
//truffle-config.js文件 module.exports = {networks: {development: {host: "127.0.0.1", // Localhost (default: none)port: 8545, // Standard Ethereum port (default: none)network_id: "*", // Any network (default: none)}} };//在遷移腳本中接受networks: module.exports = function(deployer.network) {if (network == "live") {//TODO} else {//TODO} }(5).可用的賬戶
在執行遷移時,Truffle會把當前以太坊客戶端或web3.provider中可用的賬戶列表傳遞給遷移腳本,這個賬戶列表與web3.eth.getAccount()返回的賬戶列表完全一樣。你可以在遷移腳本中的module.exports導出函數中第三個參數位置接受這個accounts參數值。
module.exports = function(deployer,networks,accounts) {//在你的遷移腳本中使用賬戶 }?
總結
以上是生活随笔為你收集整理的以太坊学习路线——(四、上)Truffle安装、truffle项目创建、编译、部署的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: onkeyup+onafterpaste
- 下一篇: Esp8266 Node Mcu 一直乱