1. 程式人生 > >區塊鏈入門(5)Truffle 項目實戰,Solidity IDE, 智能合約部署

區塊鏈入門(5)Truffle 項目實戰,Solidity IDE, 智能合約部署

第四章 margin 其中 exports nba 接口 ive 另一個 date

在上一張我們學習了Truffle項目的創建,部署等相關內容,今天我們就來實戰一下.

今天我們要做3件事: 
        1) 學習搭建一個Solidity IDE(Remix).
        2) 使用這個Solidity Ide編寫一份智能合約.
        3) 在我們前面第1,2,3章中部署的私有網絡節點集群中部署這個合約,並能夠在不同的節點中調用這個合約.

Remix,是一個Solidity開發語言的Ide, 它是一款運行在瀏覽器端的solidity ide,也是官方推薦使用的ide.

另外還有其它的solidiy ide,比如:Ethereum Studio, IntelliJ IDEA Plugin, Vistual studio extension...等這些ide的詳細情況請參考官方文檔:
https://solidity.readthedocs.io/en/latest/index.html

我們主要講解Remix.

官方推薦的Solidity基於瀏覽器端的Ide(Remix)

運行Remix有兩種方式,一種是直接用瀏覽器打開網址: https://remix.ethereum.org/
直接打開官方部署的編輯器,進行開發.

另外一種方式就是在本地部署Remix服務, 順序運行下面的命令:
> git clone https://github.com/ethereum/remix
> cd remix
> npm install
> npm start
Remix服務就部署好了,然後在瀏覽器中打開:http://127.0.0.1:8080
就可以直接使用本地部署Remix進行開發了.

本地搭建Rmix 編輯器的好處,是可以隨意修改編輯器中,源代碼的字體.
vim ./node_modules/brace/index.js

找到下面的內容:
var editorCss = ".ace_editor {    position: relative;    overflow: hidden;    font: 10px/normal ‘Ubuntu Mono‘, ‘Monaco‘, ‘Menlo‘, ‘Consolas‘, ‘source-code-pro‘, monospace;    direction: ltr;}.ace_scroller {    position: absolute;    overflow: hidden;    top: 0;    bottom: 0;    background-color: inherit;    -ms-user-select: none;    -moz-user-select: none;    -webkit-user-select: none;    user-select: none;    cursor: text;}
在font這這一行,把字體修改成自己喜歡的大小和樣式.

然後重新執行命令:
npm install
npm start

重新打開網頁,即可看到效果:

技術分享

在Remix上編寫第一份智能合約

打開瀏覽器,訪問http://127.0.0.1:8080, 新建文件‘SimpleStorage.sol‘
pragma solidity ^0.4.0;
contract SimpleStorage {
    uint storeddata;
    function set(uint x) {
        storeddata = x; 
    }
    function get() constant returns(uint retVal)  {
        return storeddata;
    } 
    function multiply(uint a) returns(uint d) {
        return a * 7;
    }
}

技術分享

 
這個SimpleStorage功能很簡單,把一個數乘以7並保存起來,提供獲取和設置它的接口.

大家最好手動輸入以上內容體驗一下Remix的效果.也可以故意輸錯,看看Remix是如何提醒錯誤的.

Remix調試模式

第一種是默認模式:javascript vm
第二種,是通過本地私有網絡的rpc端口,鏈接到本地私有網絡進行調試
還記得我們第2章中創建的以太坊私有網絡節點集群嗎?  進入之前的私有網絡目錄,並使用我們講過的方法啟動節點:
cd ~/Documents/private-chain/
geth --datadir ./data/00 --networkid 314590 --ipcdisable --port 61910 --rpcport 8200 console
回到Remix瀏覽器Ide中,選中右側邊欄的‘Contact‘選項卡.在‘Execution environment‘選項中,選擇:‘web3 provider‘, ide會彈出提示,讓你輸入之前我們啟動的私有網絡的rpc地址和端口, 輸入: 
http://localhost:8200

確定, 可以看到ide彈出提示:
Invalid JSON RPC response: "" 
我們按照官方提供的方法,增加幾個選項,啟動命令修改之後如下:
geth --datadir ./data/00 --networkid 314590 --ipcdisable --port 61910 --rpc --rpcapi ‘web3,eth,debug‘ --rpccorsdomain ‘*‘ --rpcport 8200 console
####我們增加了以下幾個命令選項:####
--rpc --rpcapi ‘web3,eth,debug‘ --rpccorsdomain ‘*‘
 
然後Remix重新鏈接私有網絡的RPC地址, Idea沒有了錯誤提示. 回到剛才啟動的網絡節點,在命令行輸入命令查看賬號:
> eth.accounts ["0x5fba50fce50baf0b8a7314200ba46336958ac97e"]
觀察Remix中, 有側邊欄‘Contract‘ tab頁中的‘Transaction origin‘,這裏顯示的就是這個賬號地址.  
點擊下方的‘create‘按鈕.錯誤又來了:

    callback contain no result Error: authentication needed: password or unlock

提示賬號被鎖定,需要‘Transaction origin‘中指定的賬號的密碼,或者解鎖賬戶.
回到geth命令行,執行下面的命令解鎖賬戶:
> personal.unlockAccount("0x5fba50fce50baf0b8a7314200ba46336958ac97e", ‘password of account‘)
true
再次點擊‘Create‘, 出現提示:
    

技術分享

並且在geth命令行中,看到了一個提示: 
    > INFO [06-19|00:21:11] Submitted contract creation              fullhash=0x5aaf0021c94f52e37eda6c17cfbea2995c1ad1935816e7cac84c73448bd6ab2d contract=0xa7fdc326fa65a15665e3637ff33a120ff3758cdb
    > 

就像之前我們在第三章中,從一個賬戶發送以太幣到另一個賬戶,需要調用miner.start(),挖礦來確認我們的交易一樣.
這裏我們調用一下:
    > miner.start(3); admin.sleepBlocks(1); miner.stop();
    INFO [06-19|00:22:31] Updated mining threads                   threads=3
    INFO [06-19|00:27:08] Successfully sealed new block            number=38 hash=b7fdac…eb3c3f
    INFO [06-19|00:27:08] ?? mined potential block                  number=38 hash=b7fdac…eb3c3f
    INFO [06-19|00:27:08] Commit new mining work                   number=39 txs=0 uncles=0 elapsed=1.836ms
    INFO [06-19|00:27:08] Successfully sealed new block            number=39 hash=210027…1218e0
    INFO [06-19|00:27:08] ?? mined potential block                  number=39 hash=210027…1218e0
    INFO [06-19|00:27:08] Commit new mining work                   number=40 txs=0 uncles=0 elapsed=183.453μs
    true
    > 
    這裏這一串語句表示啟動3個線程來挖礦,挖到第一個區塊就停止.

####查看未確認的交易數量####
    >txpool.status

回到Remix中,我們可以看到,合約已經創建成功了.  

技術分享

其中,有get, multiply, 和set 3個按鈕分別對應了SimpleStorage合約中的3個函數,用於測試函數的功能.
下面在set按鈕後面的的輸入框中,輸入參數‘106‘,點擊‘set‘按鈕.

合約就被調用了.但是任然需要挖礦來確認.繼續運行這個命令:
    miner.start(3); admin.sleepBlocks(1); miner.stop();

等到挖礦完成,我們可以在瀏覽器的Remix中看到合約的set()函數的運行結果.  
點擊‘get‘按鈕,獲取SimpleStorage合約中‘storeddata‘的值,可以看到我們獲取到的結果是‘106‘,說明我們的合約沒有問題.
另外‘multiply‘,大家可以自行測試.

技術分享

在私有鏈中部署智能合約

首先創建truffle項目,依次輸入以下命令:
    mkdir SimpleStorage
    cd SimpleStorage
    truffle init
以上命令創建並初始化truffle項目,在第4章中有說明, 這裏不在重復.

把Remix中的SimpleStorage.sol保存到SimpleStorage/contracts目錄中.

增加SimpleStorage的部署
在migrations中增加部署SimpleStorage的功能.在第四章中曾經詳細介紹Migration以及合約的部署.這裏直接提供代碼.  打開migration/2_deploy_contracts.js, 修改為:
var ConvertLib = artifacts.require("./ConvertLib.sol");
var MetaCoin = artifacts.require("./MetaCoin.sol");
var SimpleStorage = artifacts.require("./SimpleStorage.sol")

module.exports = function(deployer) {
  deployer.deploy(ConvertLib);
  deployer.link(ConvertLib, MetaCoin);
  deployer.deploy(MetaCoin);
  deployer.deploy(SimpleStorage);
};
編譯
    cd SimpleStorage
    truflle compile

編譯之後,我們開始把合約SipleStorage部署到我們的私有鏈中:
用我們第二章中的方法啟動節點:
    > geth --datadir ./data/00 --networkid 314590 --ipcdisable --port 61910 --rpcport 8200 console
節點啟動成功後,我們執行部署合約的命令.

    cd SimpleStorage
    truffle migrate

我靠,什麽鬼意思...他媽的執行失敗,顯示下面的信息.  
    Error: Invalid JSON RPC response: ""
        at Object.InvalidResponse (/usr/local/node-v6.10.2-linux-x64/lib/node_modules/truffle/node_modules/web3/lib/web3/errors.js:35:16)

[image023]

查看大量資料後,發現在部署合約到私有鏈時,需要要註意以下幾點:

    1) geth啟動節點的時候,必須帶有--rpcapi選項,並且選項的值必須包含有:"web3", "net", "eth"這3個設置,另外為了保證rpc為啟用,還應該帶有"--rpc"等一系列相關的參數.

    2) 註意SimpleStorage項目目錄中:SimpleStorage/truffle.js(項目的配置文件),關於"rpcport"的配置必須要與啟動節點時,設置的端口號一致.
        module.exports = {
          networks: {
            development: {
              host: "localhost",
              port: 8545,
              network_id: "*" // Match any network id
            }
          }
        };
        我們需要把prot: 8545,修改為geth啟動節點時設置的:8200

    3) 啟動節點後,節點中默認的賬戶是被鎖定的,無法執行部署合約的操作,需要調用下面的命令解鎖賬戶:

        > personal.unlockAccount(eth.accounts[0],"password", 1000*60*20)
    
        第一個參數是賬戶地址.
        第二個參數:賬戶密碼.
        第三個參數:賬戶解鎖持續的時間, 以毫秒為單位,這裏這樣只是為了更方便的設置以分鐘為單位(20分鐘)
    我們把賬戶解鎖持續時間稍微設置久一點,以免在部署的過程中,賬戶突然被鎖定,導致意外的出現.

有了以上3個需要註意的地方,我們重新執行部署:

調整啟動命令後,用下面的命令啟動:
    > geth --datadir ./data/00 --networkid 314590 --ipcdisable --port 61910 --rpc --rpcapi ‘web3,eth,net‘ --rpccorsdomain ‘*‘ --rpcport 8200 console
    INFO [06-24|19:15:09] Starting peer-to-peer node               instance=Geth/v1.6.1-stable-021c3c28/linux-amd64/go1.8.1
#####....這裏是很多書輸出的日誌信息....#####
    Welcome to the Geth JavaScript console!

    instance: Geth/v1.6.1-stable-021c3c28/linux-amd64/go1.8.1
    coinbase: 0x5fba50fce50baf0b8a7314200ba46336958ac97e
    at block: 41 (Sat, 24 Jun 2017 00:34:18 CST)
     datadir: /home/zl/Documents/private-chain/data/00
     modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
#####....啟動完成,我們執行解鎖賬戶unlock.....#####
    > personal.unlockAccount(eth.accounts[0], "ko2005", 20*(60*1000))
    true


私有網絡節點的操作完成後,回到剛才SimpleStorage所在的命令行, 執行部署命令:
    > truffle migrate    
    Using network ‘development‘.

    Running migration: 1_initial_migration.js
      Deploying Migrations...

可以看到,執行的輸出結果與上一次不太一樣了,好像離成功更近了.我們繼續等一會兒.
[過了一分鐘,還是沒反應,先來放一首歌....]
[....等啊等....
[草它大爺的,等了快10分鐘還是沒有反應....]
[.....好像不按我們的套路來啊.....]
[........]

突然想起來一件事,我們在之前的私有網絡中,用戶之間轉賬都是要通過挖礦來確認的...
這尼瑪..
回到剛才啟動的私有網絡命令行,執行挖礦:

    > miner.start(3); admin.sleepBlocks(1); miner.stop();
    INFO [06-24|19:16:43] Updated mining threads                   threads=3
    INFO [06-24|19:16:43] Starting mining operation 
    INFO [06-24|19:16:43] Commit new mining work                   number=42 txs=1 uncles=0 elapsed=3.079ms

這行命令的意思: 啟動挖礦程序,在挖到一個區塊之後,停止挖礦.

[挖礦又是一個耗時間的操作...]

一會兒,私有網絡所在的命令行挖礦成功,並輸出內容:
一會兒, 部署合約的命令行輸出內容:
      Migrations: 0xbc14f4725810403de4b31cdaf00a84e2ea7252dc
    Saving successful migration to network...

同時,查看私有網絡的命令行,輸出內容: 
    > miner.start(3); admin.sleepBlocks(1); miner.stop();
    INFO [06-24|19:16:43] Updated mining threads                   threads=3
    INFO [06-24|19:16:43] Starting mining operation 
    INFO [06-24|19:16:43] Commit new mining work                   number=42 txs=1 uncles=0 elapsed=3.079ms
    INFO [06-24|19:32:05] Successfully sealed new block            number=42 hash=de460c…aefbfb
    INFO [06-24|19:32:05] ?? mined potential block                  number=42 hash=de460c…aefbfb
    INFO [06-24|19:32:05] Commit new mining work                   number=43 txs=0 uncles=0 elapsed=2.730ms
    true
    > INFO [06-24|19:32:06] Submitted transaction                    fullhash=0xdf799ee7e5981011125dca4e5edcdbbf344dfbc81f466be7e69ba266572e2724 recipient=0xbc14f4725810403de4b31cdaf00a84e2ea7252dc

看這命令行輸出"Submitted transaction",意思又的讓我們挖礦確認吧, ,老套路,我們懂, 再挖,命令行我就不打出來了.跟之前一樣的.
又等一會兒..

SimpleStorage命令行輸出: 
    Saving artifacts...

區塊鏈網絡命令行輸出: 
    > INFO [06-24|19:49:31] Submitted contract creation              fullhash=0xb399d73bb5ed563e4acf6ad0b8ffc5e28ef114a1643df90b6218e568473c0b66 contract=0x6853da42bccdee332f180be1dd1e118e825ac57e

這尼瑪套路我們算是明白了,但這尼瑪套路也太長了吧. 用周星馳的話來說就是:
我走過最長的路,就是這尼瑪以太坊的套路....

反正我就這樣一直走下去,最後總算是部署成功了,這就是我的執行結果:

技術分享

合約部署成功後,我們嘗試執行以下合約..今天就到這裏吧...
這一章我們了解了以下幾點:
    1) 基於瀏覽器端的solidity ide "Remix",以及如何搭建本地版本的"Remix"
    2) Remix 的大概使用方法
    3) 使用Remix部署智能合約到Debug網絡中
    4) 如何創建一個簡單的truffle 項目, 進行項目創建,編寫部署代碼, 編譯..到執行部署的詳細流程.
    5) 在部署智能合約到以太坊私有鏈時,需要註意的許多地方.
    6) 我們成功部署了一個智能合約在以太坊私有鏈中....

下一次我們講一下如何在私有鏈中調用已經部署好的智能合約....
工作忙的時候,更新會稍慢,大家敬請期待..  

區塊鏈入門(5)Truffle 項目實戰,Solidity IDE, 智能合約部署