JSON-RPC是一种无状态的,轻量级的远程过程访问协议,并使用JSON作为其数据格式。
JSON-RPC主要是在处理过程中定义了一些数据结构和规则,能够在不同的消息传递环境中如Sockets、HTTP中传递信息。
这里将介绍如何使用JSON RPC接口在以太坊私链中部署调用合约。
编译合约:
首先需要在一个终端中(A终端)开启以太坊私链;然后再开启另一个终端(B终端)并输入以下命令来调用以太坊中的JSON-RPC接口。
所有JSON-RPC都需要使用curl的方式来调用,jsonrpc输入的是版本号,目前一般使用2.0;method中的"eth_compileSolidity"是要调用的JSON-RPC接口方法名;params中是调用方法需要传入的参数,如果有多个参数,也会包含多个字段;最后的localhost:8545是要调用的以太坊地址,由于我们开启的是私有链,默认以太坊go-ethereum客户端端口号为8545。B终端中返回结果,返回的结果中最重要的数据就是code字节码和abiDefinition数据。
curl --data '{"jsonrpc":"2.0","method": "eth_compileSolidity", "params": ["contract SimpleTest {uint data;function set(uint n) public {data = n*3;}function get() public returns (uint) {return data;}}"], "id": 5}' localhost:8545报错:
查询原因,因为端口8545未打开,按以下命令重新启动geth:
geth --datadir "~/.ethereum" --networkid 16 --rpc console出现如下错误:
将编译命令改为:
curl -X POST -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method": "eth_compileSolidity", "params": ["contract SimpleTest {uint data;function set(uint n) public {data = n*3;}function get() public returns (uint) {return data;}}"], "id": 5}' localhost:8545又报错如下:
因为在geth 1.6版之后就废弃了”eth_compileSolidity“这个函数,所以采取了别的方法进行编译——在线编译
https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.9+commit.364da425.js&optimize=false。
获得调用账户:
curl -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method":"eth_coinbase", "id":1}' localhost:8545所以,0x6815515f32312f65718bc0b1ee8d900c27167d85就是要进行交易的账户。
新打开一个终端中执行以下命令,params参数中的from就是发起该笔交易的账户,data参数中就是该合约的字节码。
curl -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from":"0x6815515f32312f65718bc0b1ee8d900c27167d85", "gas": "0xbb8a9", "data":"0x608060405234801561001057600080fd5b5060e28061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60ad565b6040518082815260200191505060405180910390f35b6003810260008190555050565b600080549050905600a165627a7a7230582010be0b1da73b1ecf4cbced8c6ff8eb9b29d01034260ab552932800bd69a575fa0029"}],"id": 6}' localhost:8545在新终端执行上述命令后,交易需要被挖矿才能确认:在之前geth命令行中执行”miner.start()”启动挖矿。执行命令后geth命令行会显示出当前合约部署成功后的合约地址,使用该合约地址调用合约中的方法。新终端返回结果中的result是本次交易(部署合约)的交易Hash。
报错,需要先将该账户进行解锁
personal.unlockAccount(eth.accounts[0],"qhh666888")
由上图可知,本次交易(部署合约)的交易Hash为:
0x35b30794b23c55754f271cfe97a2692f3001e9a36c2a5734a5b80ffdf1790068
在geth命令行中查看,显示成功提交合约:
结果为:
fullhash=0x35b30794b23c55754f271cfe97a2692f3001e9a36c2a5734a5b80ffdf1790068 contract=0x671b14461CC576e682F32738f5D51448f56Ce822
其中contract就是合约号。
to参数中为合约地址,data为调用合约需要传入的参数。data参数中包括了调用合约中的哪个方法和参数值,简称为payload。 确认该交易也需要在geth命令行挖矿。
在geth命令行中计算payload中的方法选择符对应的字节,选取Keccak散列表的前4个字节,并进行十六进制编码:
web3.sha3("set(uint256)").substring(0, 10)
得到:"0x60fe47b1"
curl -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from":"0x6815515f32312f65718bc0b1ee8d900c27167d85", "to":"0x671b14461CC576e682F32738f5D51448f56Ce822", "data":"0x60fe47b10000000000000000000000000000000000000000000000000000000000000064"}], "id": 8}' localhost:8545再调用get方法:
curl -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from":"0x6815515f32312f65718bc0b1ee8d900c27167d85", "to":"0x671b14461CC576e682F32738f5D51448f56Ce822", "data":"0x6d4ce63c"}], "id": 8}' localhost:8545得到get的交易hash为:0x613fa507d89634b4b0fb9f1e037ba3576190897b929d3c3c46c58c048a1aec93
curl -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x613fa507d89634b4b0fb9f1e037ba3576190897b929d3c3c46c58c048a1aec93"],"id":1}' localhost:8545
但是此处看不到结果,log为空,真正的结果在decoded output之中,答案为300.