以太坊中GraphQL简介及使用 | 登链社区 | 深入浅出区块链技术
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.
以太坊在去年升级的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
会看到如下界面。
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
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK