注:本文的运行环境为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,加入技术布道群
线下活动推荐