15

以太坊中GraphQL简介及使用 | 登链社区 | 深入浅出区块链技术

 4 years ago
source link: https://learnblockchain.cn/article/1062?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

以太坊在去年升级的go-ethereum(geth)1.9.0大版本,除了性能得到大幅提升之外,引入了GraphQL,一种节点接口查询机制,用以补充JSON-RPC。

以太坊在去年升级的 go-ethereum(geth)1.9.0 大版本,除了性能得到大幅提升之外,引入了 GraphQL,一种节点接口查询机制,用以补充 JSON-RPC。

本文将会介绍 GraphQL 是什么,Geth 为什么要引入 GraphQL 以及如何使用 GraphQL 三个方面对以太坊的 GraphQL 做一个介绍。

一、GraphQL 是什么

GraphQL 官网对 GraphQL 的介绍是:GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

GraphQL 有以下特点:

1、请求你所要的数据,不多不少

目前大部分的项目都是采用前后端分离的开发模式,前后端采用 API 进行数据交流。API 返回数据往往是前后端协商定义的,而后端为了满足不同的客户端,减小后端请求的复杂性,往往会给出一些冗余数据。GraphQL 很强大的一个功能就是能够指定所需要的 API 数据并获得可预测的结果。

2、获取多个资源,只用一个请求

在使用 REST API 时,我们如果需要多个资源,则会分别请求不同的接口,而使用 GraphQL 可以通过一次请求就获取你应用所需的所有数据。

3、使用类型描述所有的可能

GraphQL API 基于类型和字段的方式进行组织,而非入口端点。你可以通过一个单一入口端点得到你所有的数据能力。GraphQL 使用类型来保证应用只请求可能的数据,还提供了清晰的辅助性错误信息。应用可以使用类型,而避免编写手动解析代码。

二、以太坊为什么要使用 GraphQL

以太坊在 EIP1767 中描述了“在以太坊节点中使用 GraphQL”的提案,在以太坊节点中使用 GraphQL 模式目的时完全替代使用 JSON-RPC 获取只读信息,使用 GraphQL 具有高可用性、一致性、高效率和面向未来的优势。

之所以引入 GraphQL,是因为使用 JSON-RPC 有一些不足,这些不足包括:

1、对一些异常请求数据的判断的复杂性

如对空字符的判断,不同的地方对(""、"0x"、"0x0")的判断是不同的,会导致一些不必要的工作。

2、为了返回数据全面而额外增加资源消耗

例如,我们在调用 eth_getBlock 时会返回 totalDifficulty 字段,而该字段与块头是分开存储,需要单独读取磁盘,许多调用者不需要此字段,但是 RPC 服务器无法知道用户是否需要此字段,只能对每次调用 eth_getBlock 检索此字段。

3、接口重复调用,重复浪费资源

例如,我们在发起一笔交易后,通常会以轮询的方式调用 eth_getTransactionReceipt 接口,来判断交易是否上链。以太坊中的交易收据作为每个块的单个二进制 Blob 存储在磁盘上,获取单个交易的收据需要获取并反序列化此 blob,然后找到相关条目并返回,重复调用时,节点实现要重复获取和反序列化相同数据,造成资源浪费。

针对 JSON-RPC 的这些不足,有的同学会说,那我通过修改 JSON-RPC 的接口,也可以避免上边的问题,但是这样增加接口的复杂性。而 API 查询语言 GraphQL 就能很好的解决上边的问题。

三、如何使用 GraphQL

3.1 开启 Geth 对 GraphQL 的支持

Geth 在 1.9.0 及以上版本支持了 GraphQL,要开启 GraphQL 支持,在启动 Geth 客户端时增加 --graphql

Geth 与 GraphQL 相关的配置命令有:

  • --graphql ,在节点中开启 GraphQL 服务
  • --graphql.addr value,GraphQL 服务地址,默认时 localhost
  • --graphql.port value,GraphQL 服务端口号,默认 8547
  • --graphql.corsdomain value,GraphQL 服务访问的跨域配置
  • --graphql.vhosts value,主机名白名单配置

默认配置启动 GraphQL 服务后,在浏览器中访问 http://localhost:8547
会看到如下界面。

image.png

3.2 GraphQL 使用示例

GraphQL 的语法详见官网,这里不赘述。https://spec.graphql.cn
另外,在 GraphQL 浏览器中,也有请求的示例和补全,使用起来相对比较简单。

1、查询网络区块同步状态

query {
  syncing {
    currentBlock
    highestBlock
    knownStates
    pulledStates
    startingBlock
  }
}

2、查询事件

{
  logs(filter: {fromBlock: 0,
    addresses: ["0xf105795bf5d1b1894e70bd04dc846898ab19fa62"],
    topics: [["0x0f0c27adfd84b60b6f456b0e87cdccb1e5fb9603991588d87fa99f5b6b61e670"]]}
  ) {
    transaction {
      hash
      from {
        address
      }
      block{
        number
        timestamp
      }
    }
  }
}

3、查询区块信息

query c{
  blocks(from:100, to:120) {
    number
    hash
    timestamp
  }
}

4、查询交易

{
  transaction(hash:"0x0f0c27adfd84b60b6f456b0e87cdccb1e5fb9603991588d87fa99f5b6b61e670") {
    nonce
    from {
      address
    }
    to {
      address
    }
  }
}

3.3 GraphQL 对 JSON-RPC 的向后兼容

GraphQL 实现了 JSON-RPC 节点接口提供的大部分只读功能。可以将现有的 RPC 调用映射到 GraphQL 查询,如下所示:

RPC 状态 描述
eth_blockNumber 已实施 { block { number } }
eth_call 已实施 { call(data: { to: "0x...", data: "0x..." }) { data status gasUsed } }
eth_estimateGas 已实施 { estimateGas(data: { to: "0x...", data: "0x..." }) }
eth_gasPrice 已实施 { gasPrice }
eth_getBalance 已实施 { account(address: "0x...") { balance } }
eth_getBlockByHash 已实施 { block(hash: "0x...") { ... } }
eth_getBlockByNumber 已实施 { block(number: 123) { ... } }
eth_getBlockTransactionCountByHash 已实施 { block(hash: "0x...") { transactionCount } }
eth_getBlockTransactionCountByNumber 已实施 { block(number: x) { transactionCounnt } }
eth_getCode 已实施 { account(address: "0x...") { code } }
eth_getLogs 已实施 { logs(filter: { ... }) { ... } } 要么 { block(...) { logs(filter: { ... }) { ... } } }
eth_getStorageAt 已实施 { account(address: "0x...") { storage(slot: "0x...") } }
eth_getTransactionByBlockHashAndIndex 已实施 { block(hash: "0x...") { transactionAt(index: x) { ... } } }
eth_getTransactionByBlockNumberAndIndex 已实施 { block(number: n) { transactionAt(index: x) { ... } } }
eth_getTransactionByHash 已实施 { transaction(hash: "0x...") { ... } }
eth_getTransactionCount 已实施 { account(address: "0x...") { transactionCount } }
eth_getTransactionReceipt 已实施 { transaction(hash: "0x...") { ... } }
eth_getUncleByBlockHashAndIndex 已实施 { block(hash: "0x...") { ommerAt(index: x) { ... } } }
eth_getUncleByBlockNumberAndIndex 已实施 { block(number: n) { ommerAt(index: x) { ... } } }
eth_getUncleCountByBlockHash 已实施 { block(hash: "0x...") { ommerCount } }
eth_getUncleCountByBlockNumber 已实施 { block(number: x) { ommerCount } }
eth_protocolVersion 已实施 { protocolVersion }
eth_sendRawTransaction 已实施 mutation { sendRawTransaction(data: data) }
eth_syncing 已实施 { syncing { ... } }
eth_getCompilers 未实现 JSON-RPC 中不推荐使用编译器功能。
eth_compileLLL 未实现 JSON-RPC 中不推荐使用编译器功能。
eth_compileSolidity 未实现 JSON-RPC 中不推荐使用编译器功能。
eth_compileSerpent 未实现 JSON-RPC 中不推荐使用编译器功能。
eth_newFilter 未实现 可以在以后的 EIP 中指定过滤器功能。
eth_newBlockFilter 未实现 可以在以后的 EIP 中指定过滤器功能。
eth_newPendingTransactionFilter 未实现 可以在以后的 EIP 中指定过滤器功能。
eth_uninstallFilter 未实现 可以在以后的 EIP 中指定过滤器功能。
eth_getFilterChanges 未实现 可以在以后的 EIP 中指定过滤器功能。
eth_getFilterLogs 未实现 可以在以后的 EIP 中指定过滤器功能。
eth_accounts 未实现 帐户功能不是核心节点 API 的一部分。
eth_sign 未实现 帐户功能不是核心节点 API 的一部分。
eth_sendTransaction 未实现 帐户功能不是核心节点 API 的一部分。
eth_coinbase 未实现 挖掘功能将单独定义。
eth_getWork 未实现 挖掘功能将单独定义。
eth_hashRate 未实现 挖掘功能将单独定义。
eth_mining 未实现 挖掘功能将单独定义。
eth_submitHashrate 未实现 挖掘功能将单独定义。
eth_submitWork 未实现 挖掘功能将单独定义。

3.4 Quorum 对 GraphQL 的支持

Quorum 在 v2.6.0 版本中将 Geth 升级到了 1.9.7,并支持 GraphQL。在以太坊 GraphQL 服务的基础上,增加了对隐私交易的支持。

# Transaction is an Ethereum transaction.
type Transaction {
    ...
    # IsPrivate is an indicator of Quorum private transaction
    isPrivate: Boolean
    # PrivateInputData is the actual payload of Quorum private transaction
    privateInputData: Bytes
}

查询隐私交易的语法:

transaction(hash: "0x58462fa0b6074a8feb5d9b8cd0e6bb7ef4d1528471396070d9ae617c5dee40a8") {
	isPrivate
	inputData 
	privateInputData
}

GraphQL 官网:https://graphql.cn/learn/

以太坊 GraphQL 提案: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1767.md

Ethereum, meet GraphQL:https://medium.com/dsys/ethereum-meet-graphql-c28f3402fe8f

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2020-05-27 20:16
  • 阅读 ( 1128 )
  • 学分 ( 342 )
  • 分类:Geth

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK