第03课:以太坊常见 JSON-RPC 接口解析

第03课:以太坊常见 JSON-RPC 接口解析

以太坊提供了一套基于 JSON-RPC 的接口调用,通过这些接口调用我们可以方便的进行相关的查询、挖矿、发起交易等操作。今天带大家了解一下比较常见的一些 JSON-RPC 接口。

什么是 JSON-RPC

JSON RPC(Remote Protocol Call)是一种以 JSON 为协议的远程调用服务,具有开发调试简单、多平台通用的特性。

很明显是通过 JSON 格式的消息来调用远程的服务器,可以通过 HTTP 传输协议来调用,请求的基本格式如下:

{ 
    "jsonrpc" : 2.0,
    "method" : "sayHello", 
    "params" : ["Hello JSON-RPC"], 
    "id" : 1
} 
  • jsonrpc:定义 JSON-RPC 版本。
  • method:调用的方法名。
  • params:方法传入的参数,若无参数则为 null。
  • id:调用标识符,可以为字符串,不推荐包含小数(不能准确二进制化),或为 null(可能引起混乱)。

相应结果格式:

{
    "jsonrpc" : 2.0,
    "result" : "HelloJSON-RPC",
    "error" : null,
    "id" : 1
}
  • jsonrpc:定义 JSON-RPC 版本。
  • result:方法返回值,调用成功时,不能为 null,调用错误时,必须为 null。
  • error:调用时错误,无错误返回 null,有错误时则返回一个错误对象。
  • id:调用标识符,与调用方传入的标识一致,当请求中的 id 检查发生错误时(转换错误/无效请求),则必须返回 null。

以太坊的 JSON-RPC 官方文档

以太坊 JSON-RPC 官方文档地址详见这里,需要注意的是,此链接所对应的 JSON-RPC 只是针对 ETH 角色可操作的一些方法。

以太坊的常见操作角色

在以太坊启动的章节中我们介绍了 rpcapi 的使用,其中它的参数值便是以太坊可以操作的角色。只有在启动时添加了对应的角色,才能获得相应的操作权限。

  • eth:最常见最普遍的操作,也就是上面我们提供的链接里面指定的操作;
  • admin:geth 节点管理;
  • debug:可开启 debug 模式;
  • miner:挖矿和 DAG 管理;
  • personal:账户管理;
  • txpool:交易池检查;
  • net:节点网络情况。

net 常用接口

net_peerCount

查看当前节点所链接的其他节点数,在同步的过程中经常使用到。对应控制台的操作为:

> net.peerCount
0

ETH 常用接口

对于 ETH 常用的接口,我们已经在前面的章节中使用到过,这里介绍一下一些常用接口的基本功能,至于具体参数使用可参考官方文档。

(1)eth_syncing

查看同步情况的接口,在同步的过程中经常使用到。

>eth.syncing
false

(2)eth_coinbase

查看 coinbase 地址使用:

> eth.coinbase
"0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45"

(3)eth_accounts

查看当前节点下的所有账户:

> eth.accounts
["0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45"]

(4)eth_blockNumber

查看当前区块的高度,这也是我们经常使用的一个接口:

> eth.blockNumber
17

(5)eth_getBalance

查询地址余额:

> eth.getBalance("0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45")
1.15792089237316195423570985008687907853269984665640564039457584007913129639927e+77

(6)eth_sign

对交易或数据进行签名操作,签名之前需要对账户进行解锁操作:

> eth.sign("0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45",web3.sha3("abc"))
"0x55998b5f4ac28fc61ea245b9430ac9310d8eec50d72a34e2bb6478c15539211f6da254978a19ab054b99860658d439b58949e8d0d8f7751c67b747cb6f18f2f71c"

(7)eth_sendTransaction

发起一笔交易,需要注意的是发起交易之前需要对发起交易的账户进行解锁操作:

eth.sendTransaction({from:"0x1ece51bdb1f056f929da51c2fe0a31beeea89ab3",to:"0xdae19174969a7404e222c24b6726e4d089c12768",value:web3.toWei(10,"ether")});

在非生成环境中常用此种模式操作,但在真是生产中不建议使用此方法进行操作。

(8)eth_sendRawTransaction

广播已经签名的交易信息:

> eth.sendRawTransaction("0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675")

(9)eth_getBlockByNumber/eth_getBlockByHash

根据区块编号或区块 hash 值查询区块信息:

> eth.getBlock(1)
{
  difficulty: 2,
  extraData: "0xd883010703846765746887676f312e392e328664617277696e00000000000000a688730e4607f919aaaf066924841a3301915e6a3c1027f159b2144d4de3776631ddcc14da21367d32965b5f8fa1a62e4651f73bfbc78fdf037fc2df6d176d3a00",
  gasLimit: 6277051,
  gasUsed: 0,
  hash: "0x3fe3df4301921aea1cd45b3f05cb07f312127f09a5ccf86a8aef12900a3a0a53",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000000",
  number: 1,
  parentHash: "0x419c07af30010de2e402dd92ce8e75c44a01f6c6a5f2be31f9ca9cc757e277dd",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 606,
  stateRoot: "0x90b4c8110bb9a2b2e79ff708419f9e9fe4aba5d68e2c835bf9cc619b882d588c",
  timestamp: 1522632839,
  totalDifficulty: 3,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

(10)eth_getTransactionByHash

根据交易 hash 查询交易信息:

> eth.getTransaction("0x33ea5ff9bd71de24bab82a9adc5cd9482ddd0fa3ad62e35497039b28019c6ab1")
{
  blockHash: "0x8e78b71ec851395dae17fbf80709b0ce4d88a8ef86e893a2510ae8fa3d9d2990",
  blockNumber: 18,
  from: "0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45",
  gas: 90000,
  gasPrice: 1,
  hash: "0x33ea5ff9bd71de24bab82a9adc5cd9482ddd0fa3ad62e35497039b28019c6ab1",
  input: "0x",
  nonce: 0,
  r: "0xfc5d47a02921a42fae148d9aeb5673371acb9f5b72adbaa6ccf3a75598fcea6",
  s: "0x17379fd37ca9992f1184a8c024f52584720dba0cdbc10342ff68c24d4cde6aa7",
  to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
  transactionIndex: 0,
  v: "0xa95",
  value: 10000000000000000
}

(11)ETH 其他接口

ETH 还提供了丰富的其他操作接口,比如智能合约的发布调用,Filter 的监听使用等,不在这里一一展开,大家可以参考文档自行研究,后面针对 Java 版本,我们还会讲到 Java 版本中的 Web3j 调用,智能合约使用。

admin 常用接口

(1)addPeer 接口

给当前节点添加其他节点链接,在前面的章节中我们已经使用到了:

>admin.addPeer("enode://0d1b9eed7afe2d5878d5d8a4c2066b600a3bcac2e5730586421af224e93a58cd03cac75bf0b2a62fd8049cd3692a085758cc1e407c8b2c94bb069814a5e8d0f0@209.9.106.245:30303")
true

(2)peers 接口

查看当前节点链接的节点:

> admin.peers
[]

debug 常用接口

(1)traceTransaction

traceTransaction 调试方法将尝试以与在网络上执行相同的方式运行事务,也就是说会回放之前的交易:

> debug.traceTransaction("0x2059dd53ecac9827faad14d364f9e04b1d5fe5b506e3acc886eff7a6f88a696a")
{
  gas: 85301,
  returnValue: "",
  structLogs: [{
      depth: 1,
      error: "",
      gas: 162106,
      gasCost: 3,
      memory: null,
      op: "PUSH1",
      pc: 0,
      stack: [],
      storage: {}
  },
    /* snip */
  {
      depth: 1,
      error: "",
      gas: 100000,
      gasCost: 0,
      memory: ["0000000000000000000000000000000000000000000000000000000000000006", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000060"],
      op: "STOP",
      pc: 120,
      stack: ["00000000000000000000000000000000000000000000000000000000d67cbec9"],
      storage: {
        0000000000000000000000000000000000000000000000000000000000000004: "8241fa522772837f0d05511f20caa6da1d5a3209000000000000000400000001",
        0000000000000000000000000000000000000000000000000000000000000006: "0000000000000000000000000000000000000000000000000000000000000001",
        f652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f: "00000000000000000000000002e816afc1b5c0f39852131959d946eb3b07b5ad"
      }
  }]

通过此方法,可以查看到交易花费的 Gas,是否有错误,错误信息是什么等,对于验证发出的交易是否成功有很大帮助。

miner 常用接口

(1)setGasPrice

设置默认的 GasPrice,这样当发出交易时未指定 Gas Price,则使用默认的。

> miner.setGasPrice(2)
true

(2)start/stop

这两个操作已经在前面提到过,就是启动挖矿和停止挖矿:

miner.start()
// 或
miner.start(1)

miner.stop()

(3)setEtherbase

修改 coinbase,如果挖矿的接收地址变了,可使用此方法来进行修改:

> miner.setEtherbase("0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45")
true

personal 常用接口

(1)listAccounts

查看当前节点下面的所有账号信息:

> personal.listAccounts
["0xadce6e0e1ee491e7c1945e76d3dc5975418c4e45", "0x1ece51bdb1f056f929da51c2fe0a31beeea89ab3", "0xdae19174969a7404e222c24b6726e4d089c12768"]

(2)newAccount

创建一个新的账号,此方法有两种模式,一个是把密码当做参数直接传入,一种是先执行命令,然后在控制台写入密码:

> personal.newAccount("123456")
"0x1ece51bdb1f056f929da51c2fe0a31beeea89ab3"

(3)unlockAccount

解锁账户,上面已经提到,某些操作需要先将账户解锁,然后才能进行相应的操作:

> personal.unlockAccount("0xdae19174969a7404e222c24b6726e4d089c12768")
Unlock account 0xdae19174969a7404e222c24b6726e4d089c12768
Passphrase:
true
实战经验

此处需注意的是解锁账户是有时间限制的,默认解锁 5 分钟,可通过参数进行限制,建议解锁之后完成相应的操作马上把账户锁定。很多同学由于 JSON-RPC 公网开放,结果在解锁期间被黑客调用转账接口将余额全部转走,导致资产严重损失。

lockAccount

锁定账户:

> personal.lockAccount("0xdae19174969a7404e222c24b6726e4d089c12768")
true

对应上面的解锁账户。

sendTransaction

发送交易,与上面的 eth.sendTransaction 功能一样,不过此方法在 personal 下,可以直接通过密码解锁发送交易:

> personal.sendTransaction({from:"0x1ece51bdb1f056f929da51c2fe0a31beeea89ab3",to:"0xdae19174969a7404e222c24b6726e4d089c12768",value:web3.toWei(1,"ether")},"123456")
"0x3c662d12a67a1d68a3db2747abd346d0a058596217b7637ea474c2e7f801077f"

需要注意的是在真实生产环境中慎用此接口,很容易导致密码泄露或资金安全的问题。

txpool 常用接口

content

查看 txpool 中待打包交易的情况,其中 txpool 又包含 pending 和 queued 两个队列:

> txpool.content
{
  pending: {
    0xdAE19174969A7404e222c24B6726E4D089c12768: {
      0: {
        blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
        blockNumber: null,
        from: "0xdae19174969a7404e222c24b6726e4d089c12768",
        gas: "0x15f90",
        gasPrice: "0x1",
        hash: "0x2784a79a8c454c72700e7be3b31c1c98ceaea232ca4992a6830b0fc999ebb653",
        input: "0x",
        nonce: "0x0",
        r: "0xdabcd46d8d0b61e468d9f10119d544437f89cd094c35a89e5cbed298faf52c4a",
        s: "0x3670f23ecfb0a12e982a60438640fe042eefc50646a077de0244a8d67a84af9e",
        to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
        transactionIndex: "0x0",
        v: "0xa95",
        value: "0x2386f26fc10000"
      }
    }
  },
  queued: {
    0xdAE19174969A7404e222c24B6726E4D089c12768: {
      2: {
        blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
        blockNumber: null,
        from: "0xdae19174969a7404e222c24b6726e4d089c12768",
        gas: "0x15f90",
        gasPrice: "0x4e3b29200",
        hash: "0x7db7883bb23a31deb9f01b5e6fb28363b1aee1b9b6797ea8b5706be170a1187c",
        input: "0x",
        nonce: "0x2",
        r: "0xa8953a87c326c02da9d7a712d6c7ac0cd415cbc71ea0c24423f9e01b1fec65bd",
        s: "0x3faefc3a0db585a67f02996a7167890e41ff5fd8fd4be6efff3bea7a797fad29",
        to: "0x5929a871f57a1c5f7e4ea304cae92dacd1c1556b",
        transactionIndex: "0x0",
        v: "0xa96",
        value: "0x2386f26fc10000"
      }
    }
  }
}
实战经验

txpool 内容的查看涉及 nonce 值错误或交易迟迟未打包情况的排查,通过 txpool 还可以让一些因手续费过低未被打包的交易失效,有下面两种情况:

  • 如果不传入 nonce 值,那么 Geth 节点会默认计算当前地址已经发起了的交易中最大的 nonce 值为多少,然后将其 +1,然后将此交易放置在 pending 中,等待节点打包。
  • 如果传入的 nonce 值过大,在进入 txpool 中检查到它之前的 nonce 并没有使用过,那么此笔交易不会发送到 pending 中,而且放置在 queued 中。只有当前面的 nonce 补齐之后,才会进入到 pending 中。

另外,可以通过设置 txpool.lifetime 参数来让发出的迟迟未成功的交易失效。

安全

最后还是要强调一下,JSON-RPC 接口的访问权限控制一定要进行严格的网络限制,不然会很容易导致资产损失。最好只开放部分 RPC 接口,并且要限制仅内网指定 IP 访问,其他服务器安全措施也要相应跟上。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Java中使用sslKey文件调用JSON-RPC 2.0接口,可以按照以下步骤进行操作: 1. 导入必要的库 需要导入以下库: - org.apache.http.client.HttpClient - org.apache.http.client.methods.HttpPost - org.apache.http.entity.StringEntity - org.apache.http.impl.client.HttpClients - org.apache.http.util.EntityUtils - org.json.JSONObject - java.security.KeyStore - javax.net.ssl.SSLContext - javax.net.ssl.TrustManagerFactory - javax.net.ssl.KeyManagerFactory 2. 加载sslKey文件 使用Java的KeyStore类加载sslKey文件,例如: KeyStore keyStore = KeyStore.getInstance("PKCS12"); FileInputStream fis = new FileInputStream("sslKey.p12"); keyStore.load(fis, "password".toCharArray()); 3. 创建SSLContext 使用KeyManagerFactory和TrustManagerFactory创建SSLContext,例如: KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keyStore, "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 4. 创建HttpClient 使用HttpClients.createDefault()创建HttpClient,并使用刚刚创建的SSLContext设置其SSL socket factory,例如: HttpClient httpClient = HttpClients.createDefault(); HttpClient httpClient = HttpClients.custom() .setSSLContext(sslContext) .build(); 5. 发送POST请求 使用HttpPost类创建POST请求,并将请求体设置为JSON-RPC 2.0请求体,例如: HttpPost request = new HttpPost("https://example.com/api"); request.setHeader("Content-type", "application/json"); String json = "{\"jsonrpc\":\"2.0\",\"method\":\"getUser\",\"params\":[\"user123\"],\"id\":1}"; request.setEntity(new StringEntity(json)); 6. 解析响应 执行请求并获取响应,然后解析JSON格式的响应体,例如: HttpResponse response = httpClient.execute(request); String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); JSONObject jsonResponse = new JSONObject(responseString); if (jsonResponse.has("result")) { JSONObject result = jsonResponse.getJSONObject("result"); // do something with result } else if (jsonResponse.has("error")) { JSONObject error = jsonResponse.getJSONObject("error"); // handle error } 以上就是使用sslKey文件调用JSON-RPC 2.0接口的步骤,需要注意的是,要根据实际情况替换示例中的URL、请求体和响应体解析逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值