使用JSONRPC与以太坊智能合约交互

以太坊提供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与以太坊智能合约交互_第1张图片
这里解释下请求参数
jsonrpc:标识协议的版本,建议都填2.0
method:需要调用的接口名
params:方法的请求参数,不同方法的参数要去不一样,可看接口文档
id:请求标识,发起接口方设置,来标记请求。比如有可能同时发送多个接口请求,可以用这个di来识别每个请求的响应
成功返回
使用JSONRPC与以太坊智能合约交互_第2张图片
这里可以多测试几个接口,来熟悉下用法,

部署智能合约
节点已经可以访问了,现在我们可以部署个智能合约,来看看与自能合约的交互。
这里我用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;
    }
}

链接测试节点
使用JSONRPC与以太坊智能合约交互_第3张图片
弹出提示,选择ok,

注意这里需要节点已经开通了的RPC协议,否则无法链接

使用JSONRPC与以太坊智能合约交互_第4张图片
输入节点rpc的访问地址http://172.30.34.102:8545
使用JSONRPC与以太坊智能合约交互_第5张图片
输入构造函数的入参,点击creat创建合约
使用JSONRPC与以太坊智能合约交互_第6张图片
可以看到节点控制台的输出,说明已经部署成功。
使用JSONRPC与以太坊智能合约交互_第7张图片
交易哈希值=0x47adcb93847acce2c02b680b96447aacd5ebd83b9f2436e7b496038824439771
合约的地址=0xcF9b0ea3D6Cd99C17531eaC74D9B8C845520D688

在At Address上输入合约地址,调用合约方法
使用JSONRPC与以太坊智能合约交互_第8张图片

与智能合约进行交互
调用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最自由,不限定语言。

你可能感兴趣的:(以太坊)