前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Geth GraphQL使用说明

Geth GraphQL使用说明

作者头像
用户1408045
发布2019-10-10 17:35:42
1.7K0
发布2019-10-10 17:35:42
举报
文章被收录于专栏:汇智网教程汇智网教程

Geth V1.9.x增加了GraphQL的支持,开发者可以在经典的JSON RPC API和GraphQL API之间根据自己的去中心化应用具体需求进行选择。本文将介绍Geth 1.9新增GraphQL API的原因,并介绍其使用方法。

要快速掌握以太坊区块链应用开发,推荐汇智网的在线互动教程:

1、JSON-RPC API有什么问题?

让我们先了解下经典的JSON-RPC API存在什么问题。

正如其名称所示,JSON-RPC是一种远程过程调用协议,它被设计用来调用远端的函数并返回计算结果。JSON-RPC是相当宽泛的协议,你需要在它之上设计自己的调用接口。

但是JSON-RPC的问题在于它不支持灵活的查询,这会导致计算资源和数据传输方面的双重浪费:

  • 即使用户只需要部分数据,RPC调用也需要返回大量数据,造成带宽的 浪费。例如你调用eth_getBlock的目的只是获取矿工地址,但是它依然 需要返回完整的区块数据。
  • 如果用户重复调用某个RPC接口,即使每次调用只返回一点点数据,也会 浪费节点的CPU。例如当你调用eth_getTransactionReceipt接口轮询某个 交易的收据时。

对于以太坊的JSON-RPC API,由于区块链数据的结构特点,上面的问题被进一步放大了,多次执行一个查询(例如eth_getBalance)需要确保查询是同一世界状态甚至是在同一个节点上:当你使用多个节点进行负载均衡处理时,不同的后台节点可能有不同的同步延迟,从而可能对相同的RPC请求返回不同的内容。

为了解决这些问题,以太坊EIP 1767提出了以太坊节点的GraphQL接口建议,Geth在1.9.0版本中引入了对EIP 1767的支持,实现了完整的原生GraphQL支持。

2、什么是GraphQL?

GraphSQL是为了解决REST API存在的问题而提出的一种新的查询语言。GraphQL将数据对象关系 映射到一个图(Graph),并设计了一种查询语言(Query Language)来遍历图中关系 —— 这也是GraphQL 名称的来源。

这篇文章非常适合不熟悉GraphQL的开发者快速理解GraphQL的基本概念,以及如何利用NodeJS技术栈实现GraphQL的服务端与客户端:从SQL到GraphQL

3、开启Geth的GraphQL支持

Geth 1.9.0引入的对GraphQL的原生支持。在启动geth时,使用--graphql命令行标志就可以开启GraphQL API接口了。例如,执行下面的命令来接入以太坊Görli测试链并开启GraphQL API支持:

代码语言:javascript
复制
~$ geth --goerli --graphql

4、Geth GraphQL浏览器

一旦开启了Geth的GraphQL支持,就可以通过Geth预置的GraphQL浏览器来进行测试,GraphQL服务默认在8547端口监听,API访问路径为/graphql。可以使用如下URL访问Geth的GraphQL浏览器:

代码语言:javascript
复制
http://localhost:8547

界面如下所示,最左边就是输入的GraphQL查询:

在这里插入图片描述
在这里插入图片描述

为了便于查看,这里列出左边的GraphQL查询语句:

代码语言:javascript
复制
{
  logs(filter: {fromBlock: 0,
    addresses: ["0xf105795bf5d1b1894e70bd04dc846898ab19fa62"],
    topics: [["0x0f0c27adfd84b60b6f456b0e87cdccb1e5fb9603991588d87fa99f5b6b61e670"]]}
  ) {
    transaction {
      hash
      from {
        address
      }
      block{
        number
        timestamp
      }
    }
  }
}

你可以这样理解上面的GraphQL语句:

  • 查询日志logs
    • 查询条件:使用filter对象指定
    • 返回字段:transaction,其结构如上所示

5、实例对比JSON-RPC API和Geth GraphQL

假设我们要查询最新的10个区块的矿工账号以及这些账号的余额,使用JSON-RPC的实现代码如下:

代码语言:javascript
复制
async function main() {
  const lastBlock = await web3.eth.getBlockNumber()
  result = []

  for (let i = lastBlock; i >= lastBlock - 10; i--) {
    let block = await web3.eth.getBlock(i)
    let blockRes = {}
    blockRes.number = i
    blockRes.miner = {}
    blockRes.miner.address = block.miner
    blockRes.miner.balance = await web3.eth.getBalance(block.miner)
    result.push(blockRes)
  }
  console.log(result);
}

我们需要进行10次循环,逐个查询每个区块的矿工账号及其余额。在每次循环中,我们需要调用两次RPC API,分别查询区块数据和账户余额,因此总共需要10*2 = 20 次调用。

下面是获取同样数据的GraphQL查询:

代码语言:javascript
复制
{
  blocks(from:lastBlock-10, to:lastBlock) {
    number
    miner{
      address
      balance
    }
  }
}

你可以在Geth GraphQL浏览器中输入并执行上面的查询语句。令人震惊的是,我们只进行1次调用就完成了之前采用JSON-RPC时20次调用才完成的任务!

6、Geth GraphQL的后向兼容性

在Geth源代码中,schema.go文件中包含了当前的GraphQL语法支持。下表列出了Geth GraphQL目前的实现状态,其中简要说明栏目描述了JSON-RPC对应的Geth GraphQL语句:

<table class="table table-striped"> <thead> <tr> <th>JSON-RPC</th> <th>GraphQL状态</th> <th>简要说明</th> </tr> </thead> <tbody> <tr> <td>eth_blockNumber</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block { number } }</code></td> </tr> <tr> <td>eth_call</td> <td>已实现</td> <td><code class="highlighter-rouge">{ call(data: { to: "0x...", data: "0x..." }) { data status gasUsed } }</code></td> </tr> <tr> <td>eth_estimateGas</td> <td>已实现</td> <td><code class="highlighter-rouge">{ estimateGas(data: { to: "0x...", data: "0x..." }) }</code></td> </tr> <tr> <td>eth_gasPrice</td> <td>已实现</td> <td><code class="highlighter-rouge">{ gasPrice }</code></td> </tr> <tr> <td>eth_getBalance</td> <td>已实现</td> <td><code class="highlighter-rouge">{ account(address: "0x...") { balance } }</code></td> </tr> <tr> <td>eth_getBlockByHash</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(hash: "0x...") { ... } }</code></td> </tr> <tr> <td>eth_getBlockByNumber</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(number: 123) { ... } }</code></td> </tr> <tr> <td>eth_getBlockTransactionCountByHash</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(hash: "0x...") { transactionCount } }</code></td> </tr> <tr> <td>eth_getBlockTransactionCountByNumber</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(number: x) { transactionCounnt } }</code></td> </tr> <tr> <td>eth_getCode</td> <td>已实现</td> <td><code class="highlighter-rouge">{ account(address: "0x...") { code } }</code></td> </tr> <tr> <td>eth_getLogs</td> <td>已实现</td> <td><code class="highlighter-rouge">{ logs(filter: { ... }) { ... } }</code> or <code class="highlighter-rouge">{ block(...) { logs(filter: { ... }) { ... } } }</code></td> </tr> <tr> <td>eth_getStorageAt</td> <td>已实现</td> <td><code class="highlighter-rouge">{ account(address: "0x...") { storage(slot: "0x...") } }</code></td> </tr> <tr> <td>eth_getTransactionByBlockHashAndIndex</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(hash: "0x...") { transactionAt(index: x) { ... } } }</code></td> </tr> <tr> <td>eth_getTransactionByBlockNumberAndIndex</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(number: n) { transactionAt(index: x) { ... } } }</code></td> </tr> <tr> <td>eth_getTransactionByHash</td> <td>已实现</td> <td><code class="highlighter-rouge">{ transaction(hash: "0x...") { ... } }</code></td> </tr> <tr> <td>eth_getTransactionCount</td> <td>已实现</td> <td><code class="highlighter-rouge">{ account(address: "0x...") { transactionCount } }</code></td> </tr> <tr> <td>eth_getTransactionReceipt</td> <td>已实现</td> <td><code class="highlighter-rouge">{ transaction(hash: "0x...") { ... } }</code></td> </tr> <tr> <td>eth_getUncleByBlockHashAndIndex</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(hash: "0x...") { ommerAt(index: x) { ... } } }</code></td> </tr> <tr> <td>eth_getUncleByBlockNumberAndIndex</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(number: n) { ommerAt(index: x) { ... } } }</code></td> </tr> <tr> <td>eth_getUncleCountByBlockHash</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(hash: "0x...") { ommerCount } }</code></td> </tr> <tr> <td>eth_getUncleCountByBlockNumber</td> <td>已实现</td> <td><code class="highlighter-rouge">{ block(number: x) { ommerCount } }</code></td> </tr> <tr> <td>eth_protocolVersion</td> <td>已实现</td> <td><code class="highlighter-rouge">{ protocolVersion }</code></td> </tr> <tr> <td>eth_sendRawTransaction</td> <td>已实现</td> <td><code class="highlighter-rouge">mutation { sendRawTransaction(data: data) }</code></td> </tr> <tr> <td>eth_syncing</td> <td>已实现</td> <td><code class="highlighter-rouge">{ syncing { ... } }</code></td> </tr> <tr> <td>eth_getCompilers</td> <td>未实现</td> <td>JSON-RPC已废弃编译器功能</td> </tr> <tr> <td>eth_compileLLL</td> <td>未实现</td> <td>JSON-RPC已废弃编译器功能</td> </tr> <tr> <td>eth_compileSolidity</td> <td>未实现</td> <td>JSON-RPC已废弃编译器功能</td> </tr> <tr> <td>eth_compileSerpent</td> <td>未实现</td> <td>JSON-RPC已废弃编译器功能</td> </tr> <tr> <td>eth_newFilter</td> <td>未实现</td> <td>过滤器功能可能在未来EIP中约定</td> </tr> <tr> <td>eth_newBlockFilter</td> <td>未实现</td> <td>过滤器功能可能在未来EIP中约定</td> </tr> <tr> <td>eth_newPendingTransactionFilter</td> <td>未实现</td> <td>过滤器功能可能在未来EIP中约定</td> </tr> <tr> <td>eth_uninstallFilter</td> <td>未实现</td> <td>过滤器功能可能在未来EIP中约定</td> </tr> <tr> <td>eth_getFilterChanges</td> <td>未实现</td> <td>过滤器功能可能在未来EIP中约定</td> </tr> <tr> <td>eth_getFilterLogs</td> <td>未实现</td> <td>过滤器功能可能在未来EIP中约定</td> </tr> <tr> <td>eth_accounts</td> <td>未实现</td> <td>账户功能不属于节点核心API</td> </tr> <tr> <td>eth_sign</td> <td>未实现</td> <td>账户功能不属于节点核心API</td> </tr> <tr> <td>eth_sendTransaction</td> <td>未实现</td> <td>账户功能不属于节点核心API</td> </tr> <tr> <td>eth_coinbase</td> <td>未实现</td> <td>挖矿相关功能将单独定义</td> </tr> <tr> <td>eth_getWork</td> <td>未实现</td> <td>挖矿相关功能将单独定义</td> </tr> <tr> <td>eth_hashRate</td> <td>未实现</td> <td>挖矿相关功能将单独定义</td> </tr> <tr> <td>eth_mining</td> <td>未实现</td> <td>挖矿相关功能将单独定义</td> </tr> <tr> <td>eth_submitHashrate</td> <td>未实现</td> <td>挖矿相关功能将单独定义</td> </tr> <tr> <td>eth_submitWork</td> <td>未实现</td> <td>挖矿相关功能将单独定义</td> </tr> </tbody> </table>


原文链接:Geth GraphQL - 汇智网

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、JSON-RPC API有什么问题?
  • 2、什么是GraphQL?
  • 3、开启Geth的GraphQL支持
  • 4、Geth GraphQL浏览器
  • 5、实例对比JSON-RPC API和Geth GraphQL
  • 6、Geth GraphQL的后向兼容性
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档