注:本文的運行環境爲MacOS。javascript
brew tap ethereum/ethereum brew install ethereumjava
完成以後,經過如下命令驗證:git
geth version
所謂運行,是指運行一個節點並加入以太坊網絡,它有兩個選擇:公鏈和測試鏈,這兩個網絡都在互聯網上。github
2.1 公鏈web
geth --fast --cache=512 --datadir "你的目錄" consolenpm
2.2 測試鏈編程
geth --testnet --fast --cache=512 --datadir "你的目錄" consolejson
這兩種方式都須要同步區塊,它們存放於datadir指定的目錄之下,所以請確保有足夠的空間。api
搭建私鏈的目的主要是出於測試的目的,不建議搭建以運營爲目的的私鏈。整個步驟以下:安全
**3.1 編寫genesis.json,定義初始信息。**內容示例以下:
{ "config": { "chainId": 20, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "alloc": { "0xeb680f30715f347d4eb5cd03ac5eced297ac5046": { "balance":"100000000000000000000000000000000" } }, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty": "0x01", "extraData": "0x777573686f756865", "gasLimit": "0xffffffff", "nonce": "0x0000000000000001", "mixhase": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00" }
3.2 初始化
geth --datadir "your dir" init genesis.json
3.3 啓動,見到小錘子後,表示已經開始挖礦。
geth --datadir "你的目錄" --rpc --rpcaddr=0.0.0.0 --rpcport 8545 --rpccorsdomain "*" --rpcapi "eth,net,web3,personal,admin,shh,txpool,debug,miner" --nodiscover --maxpeers 30 --networkid 1981 --port 30303 --mine --minerthreads 1 --etherbase "0xeb680f30715f347d4eb5cd03ac5eced297ac5046" console
這裏須要注意的是,在此命令行下「ctrl-c」並不會終止進程。若是要終止運行,在命令行下輸入「exit」。
geth還提供了控制檯,輸入以下命令可進入:
geth --datadir "你的目錄" attach ipc:你的目錄/geth.ipc
該控制檯提供的接口包括:帳戶、交易、合約調用、區塊。
本節以vscode爲IDE,geth-cli簡要說明智能合約的開發過程。
4.1 環境準備
安裝語言包
brew install solidity
準備IDE插件
https://github.com/juanfranblanco/vscode-solidity,進入「擴展」,搜索「solidity」,第一個就是。
4.2 合約開發
編輯(simpledata.sol),內容以下:
pragma solidity ^0.4.23; contract SimpleData { uint data; function set(uint x) public{ data = x; } function get() view public returns (uint) { return data; } }
編譯
echo "var output=solc --optimize --combined-json abi,bin,interface simpledata.sol
" > simpledata.js
部署(利用前面搭建好的私鏈)
啓動私鏈
進入控制檯,如下全部步驟均在控制檯裏完成,採用js語法。
加載編譯過的js:
loadScript('.../simpledata.js')
var contractAbi = output.contracts['simpledata.sol:SimpleData'].abi var contract = eth.contract(JSON.parse(contractAbi)) var binCode = "0x" + output.contracts['simpledata.sol:SimpleData'].bin
personal.newAccount("123456") // 參數爲密碼 miner.setEtherbase(eth.accounts[0]) // 設置建立的用戶爲礦工 web3.fromWei(eth.getBalance(eth.accounts[0]), "ether") // 查看餘額
var deployTx = { from: eth.accounts[0], data: binCode, gas: 1000000}; var instance = contract.new(deployTx) var contractAddress = eth.getTransactionReceipt(instance.transactionHash).contractAddress // 合約地址
調用(仍在同一條私鏈上,一樣在控制檯執行)
var simpleData = contract.at(contractAddress) simpleData.get.call() personal.unlockAccount(eth.accounts[0]) // 此步必需 simpleData.set.sendTransaction(33, {from: eth.accounts[0], gas: 100000}) simpleData.get.call()
此處須要注意的有兩點:
鏈上的變動經過交易完成,同時執行合約是有代價的,即gas,這是與傳統開發很大的不一樣。也是爲什麼前面在部署以前先建立用戶,並將其設置爲礦工,得到餘額的緣由。
注意:gas和eth不是一類東西,合約最終消耗的eth由:步驟和gasPrice來決定。
執行交易以前須要先解鎖帳戶,這相似我們在用網銀時轉帳前須要輸入「取款密碼」。同時,解鎖是有時限的,爲了不頻繁解鎖能夠用下面的語句:
personal.unlockAccount(eth.accounts[0], 密碼, 時限)
這裏出現了交易,所以也說明一下安全性的問題:
以太坊上全部的交易都是公開可查看的,全部交易歷史能夠經過Etherscan看到。
全部交易執行都是要用發起者的私鑰簽名的,所以只要私鑰能獲得妥善保存,就不會有什麼大問題。在上面的步驟中沒有出現用私鑰簽名,這是由於帳戶自己是由控制檯建立的,在建立的同時也建立了相應的公鑰和私鑰。
能夠看得出上面的整個過程至關繁瑣,Truffle則正是爲解決這些問題而生的。
安裝
npm install -g truffle
開發部署
mkdir dapp
cd dapp
truffle init
進入contracts目錄,建立下面的文件
pragma solidity ^0.4.23; contract Storage { uint256 storageData; function set(uint256 data) public { storageData = data; } function get() view public returns (uint256) { return storageData; } }
truffle compile
合約的部署經過migration完成,假如用過諸如liquidbase之類的dbmigration工具,對此應該不陌生。進入migrations目錄,建立相應的文件,以「數字_」開頭,如「2_deploy_storage.js」。內容以下:
var Storage = artifacts.require("Storage"); module.exports = function(deployer) { deployer.deploy(Storage); }
npm install -g ganache-cli // 安裝
ganache-cli //運行
module.exports = { networks: { development: { host: "127.0.0.1", port: 8545, network_id: "*" // Match any network id } } };
至此,部署完畢,讓咱們手動測試一下。
JSON-RPC接口能夠用curl完成,其特色在於:合約的方法是rpc請求的數據。若是以爲這有點拗口,不妨將這種方式與利用Java Reflection來調用某個類的方法作類比。
要調用上面的合約,首先須要得到合約方法(get和set)的簽名:
get方法
curl -X POST -i http://localhost:8545 --data '{ "jsonrpc":"2.0", "method":"web3_sha3", "params":["get()"], "id":1 }' **set方法** curl -X POST -i http://localhost:8545 --data '{ "jsonrpc":"2.0", "method":"web3_sha3", "params":["set(uint256)"], "id":1 }'
方法簽名利用「web3_sha3」獲得,其簽名爲返回值的0x後的8位。上面兩個調用對應的結果以下:
get:6d4ce63c
set:60fe47b1
調用合約須要合約的地址,這個值能夠從ganache終端中得到。在其終端輸出中查找相似下面的語句,其中created以後的即爲地址。
Contract created: 0x59322f0c1235719b4c0044b0c67f2437674b8c69
剩下的就是合約調用了(其中from帳戶直接使用ganache啓動時初始化的帳戶,to爲合約地址):
get方法
curl -X POST -i http://localhost:8545 --data '{ "jsonrpc":"2.0", "method":"eth_call", "params":[ { "from":"0x2fe84a7fb107ade77adfeb351b92615597b68f52", "to":"0x59322f0c1235719b4c0044b0c67f2437674b8c69", "data":"0x6d4ce63c0000000000000000000000000000000000000000000000000000000000000000" }, "latest" ], "id":1 }'
set方法
curl -X POST -i http://localhost:8545 --data '{ "jsonrpc":"2.0", "method":"eth_sendTransaction", "params":[ { "from":"0x2fe84a7fb107ade77adfeb351b92615597b68f52", "to":"0x59322f0c1235719b4c0044b0c67f2437674b8c69", "gas":"0xc350", "gaslimit":"0xc350", "data":"0x60fe47b10000000000000000000000000000000000000000000000000000000000000005" } ], "id":1 }'
注意兩次調用的「method」的不一樣。同時,「data」參數中的0x後的前8位爲對應的方法簽名,後面則爲實際傳入到對應方法的數據。
若是要在js文件中與智能合約交互,則須要相應的包:
web3.js,其封裝了json-rpc接口
truffle-contract模塊,truffle的合約抽象
truffle支持兩類自動化測試:使用javascript和使用solidity,都至關簡單,這裏再也不贅述。測試文件統一放在test目錄下,測試命令:
truffle test // 所有測試 truffle test 文件 // 單個測試
js包用普通的npm,略
智能合約的包用ethpm
truffle install 包名 truffle publish 包名
Truffle(https://truffleframework.com/)
solidity(https://solidity.readthedocs.io/en/v0.4.24/)
《區塊鏈開發實戰:以太坊關鍵技術與案例分析》,部份內容過期,好比TestRPC目前已經被Ganache替代。
本文做者:HiBlock區塊鏈技術佈道羣-胡鍵
原文發佈於簡書
原文連接:https://www.jianshu.com/p/bec173e6cf73
加微信baobaotalk_com,加入技術佈道羣
線下活動推薦