以太坊提供JSONRPC和web3.js俩种方式与区块链节点进行交互,详细接口说明文档可看官方用户文档。
这里得先了解下JSONRPC的调用。
对JSONRPC协议不熟悉的朋友可以看这俩个博客1,博客2
启动测试节点
geth --datadir "D:\blockchain\devchain" --dev --rpc --rpcaddr 172.30.34.102 --rpcapi 'db,eth,net,web3,personal,admin,miner' --rpccorsdomain * console
–rpc,标志启动HTTP JSON-RPC
–rpcaddr –rpcport ,更改默认端口(8545)和列表地址(本地主机)
–rpcapi来设置节点开放哪些方法
–rpccorsdomain ,如果从浏览器访问RPC,CORS将需要启用相应的域集。否则,JavaScript调用受到同源策略的限制,请求将失败,‘’表示所有域名可访问
JSON RPC也可以使用该命令从geth控制台启动admin.startRPC(addr, port)。
测试访问节点
节点启动后,可以测试下是否可已正常访问节点,这里我用Postman做了个测试。
调用web3_clientVersion方法,来获取节点客户端的版本信息。
根据接口说明发送POST请求,请求内容为JSON格式。
这里解释下请求参数
jsonrpc:标识协议的版本,建议都填2.0
method:需要调用的接口名
params:方法的请求参数,不同方法的参数要去不一样,可看接口文档
id:请求标识,发起接口方设置,来标记请求。比如有可能同时发送多个接口请求,可以用这个di来识别每个请求的响应
成功返回
这里可以多测试几个接口,来熟悉下用法,
部署智能合约
节点已经可以访问了,现在我们可以部署个智能合约,来看看与自能合约的交互。
这里我用remix solidity来部署智能合约。
写合约
pragma solidity ^0.4.20;//当前solidity版本
contract hello {
string greeting;
//构造函数
function hello(string _greeting) public {
greeting = _greeting;
}
//获取greeting,无需gas
function getGreeting() constant public returns (string) {
return greeting;
}
//设置改变greeting,需要gas
function setGreeting(string _greeting) public payable{
greeting = _greeting;
}
}
注意这里需要节点已经开通了的RPC协议,否则无法链接
输入节点rpc的访问地址http://172.30.34.102:8545
输入构造函数的入参,点击creat创建合约
可以看到节点控制台的输出,说明已经部署成功。
交易哈希值=0x47adcb93847acce2c02b680b96447aacd5ebd83b9f2436e7b496038824439771
合约的地址=0xcF9b0ea3D6Cd99C17531eaC74D9B8C845520D688
与智能合约进行交互
调用getGreeting需要使用接口eth.call
图片描述](//img-blog.csdn.net/20180315111059639?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L3UwMTIxMTc2NTY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
这里说明下请求参数params和响应参数result
{“jsonrpc”:”2.0”,”method”:”eth_call”,”params”:[{“to”:”0xcF9b0ea3D6Cd99C17531eaC74D9B8C845520D688”,”data”:”0xfe50cc72”},”latest”],”id”:67}
to:合约地址
data:根据ABI二进制编码规则得到的字符串,用来描述请求方法和入参,详情可看ABI文档和博客
latest:是说明从最新的区块开始查找合约,可以根据需要填不同的参数,节省查询时间
result:放回的是经过ABI二进制编码规则编码过得数据,需要根据规则再进行解码,这里解码后得到‘你好’
这里贴个代码
JAVA使用JSONPRC与以太坊节点进行交互-用例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.http.util.TextUtils;
public class EthereumController {
public static void main(String[] args) {
String url="http://172.30.34.102:8545";
String paramJson="{\"jsonrpc\":\"2.0\",\"method\":\"web3_clientVersion\",\"params\":[{\"to\":\"0x3b37B585D69720a10241b0690310daED9FBD521E\",\"data\":\"0xfe50cc72\"},\"latest\"],\"id\":67}";
System.out.println( doJsonPost(url,paramJson)) ;
}
//发送JSON字符串 如果成功则返回成功标识。
public static String doJsonPost(String urlPath, String Json) {
// HttpClient 6.0被抛弃了
String result = "";
BufferedReader reader = null;
try {
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Charset", "UTF-8");
// 设置文件类型:
conn.setRequestProperty("Content-Type","application/json; charset=UTF-8");
// 设置接收类型否则返回415错误
//conn.setRequestProperty("accept","*/*")此处为暴力方法设置接受所有类型,以此来防范返回415;
conn.setRequestProperty("accept","application/json");
// 往服务器里面发送数据
if (Json != null && !TextUtils.isEmpty(Json)) {
byte[] writebytes = Json.getBytes();
// 设置文件长度
conn.setRequestProperty("Content-Length", String.valueOf(writebytes.length));
OutputStream outwritestream = conn.getOutputStream();
outwritestream.write(Json.getBytes());
outwritestream.flush();
outwritestream.close();
System.out.println( "doJsonPost: conn"+conn.getResponseCode());
}
if (conn.getResponseCode() == 200) {
reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
result = reader.readLine();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
从这里就可以了解到用JSONRPC调用接口,需要手动对数据进行编码和解码,不易理解且非常麻烦。建议使用web3.js或web3J与节点进行交互。它底层也是用JSONRPC进行交互,屏蔽了复杂的编码解码过程,提供更易用的接口。不过用JSONRPC最自由,不限定语言。