TheGraph 新的去中心化网络是什么以及如何使用它?
- 原文:https://soliditydeveloper.com/thedecentralizedgraph
- 译文出自:登链翻译计划
- 译者:翻译小组
- 校对:Tiny 熊
- 本文永久链接:learnblockchain.cn/article…
之前我们翻译过TheGraph的上一篇文章:使用 TheGraph 进行事件数据检索,已经过去了相当长的时间。如果你不知道TheGraph是什么,为什么TheGraph是有用的,可以读读那篇文章,在那篇文章详细解释了为什么需要TheGraph以及如何在中心化托管服务(Hosted Service)中使用它。
简短的说:区块链上的事件是一种非常有效的添加数据的方式,而不必将其存储在每个节点上(这很昂贵)。事件是通过使用bloom filter来实现的,客户端能够解析区块和交易,以快速找到其要找的数据。但仍然需要解析大量的区块,所以一个替代方案是让服务器对这些数据进行索引并将其存储在数据库中。加上把GraphQL作为一种非常方便的查询语言放在上面,这就是The Graph了,不过是作为一种中心化服务。
总之,The Graph允许以一种更有效的方式查询区块链的数据。这在构建前端和显示区块链中发生的数据时是非常重要的,而不必将数据直接存储在智能合约中。
现在,The Graph开始了一个新的去中心化的网络,也增加了更多的功能。托管服务(Hosted Service)将在2023年第一季度结束,所以现在是时候了解The Graph去中心化网络是如何工作的,如何使用它,以及作为开发者的你需要了解有哪些新功能。
最初The Graph只有一个中心化的托管服务,但从长远来看,这当然不是我们想要的。毕竟,如果你完全依赖一个中心化的服务器来查询数据,那么Dapp的意义何在。尽管这仍然比完全中心的基础设施要好,但我们仍然可以做得更好!
为了解决这个问题,The Graph拥有自己的去中心化网络和自己的GRT ERC-20代币。
消费者可以根据运行时间和价格等因素,自由地选择使用哪个索引器。当然,一个Dapp甚至可以使用多个索引器以获得最高的安全性。
GRT代币本身是用于质押:
以下是各方参与示意图:
为了帮助引导那些还没有需求的新subgraph,GRT 质押是通货膨胀的,新铸造的代币被给予那些对查询需求非常低的subgraph进行索引的索引器。为了确保索引器确实在做索引这些低需求subgraph的工作,有一个额外的机制叫做索引证明(POI)。POI是对subgraph状态哈希的签名,索引器需要它来获得奖励。POI被乐观地接受,但以后可以被罚没。在网络的第一个版本中,通过治理设置的仲裁员将决定这些争端。
subgraph配置(称为清单)通常被上传到IPFS。但是,当清单根本无法使用时,我们能做什么?那么就不可能验证这些POI了。对于这一点,有一个subgraph可用性Oracle。它将查看几个有名的IPFS端点,如果清单不可用,subgraph就不能用于索引器获取奖励。
常用的支付通道(状态通道技术)是一种很好的支持规模支付方式。像The Graph那样为每个查询付费时,我们显然需要这样的东西。在The Graph中,支付通道有一个额外的安全层:WAVE。
WAVE 支付的几个部分:
查询验证
现在的问题是,你如何验证The Graph查询的正确性?最初在The Graph中,这是由链上争议解决程序处理的,通过仲裁决定。渔夫们将寻找不正确的查询,并将证明与保证金一起提交给仲裁。
在未来,与其依靠仲裁来解决查询纠纷,不如利用多项式承诺或Merkle树等技术的加密证明来保证查询的有效性。同样,即使是POI也可以使用类似于乐观 Rollup的机制来自动验证。两者结合起来,就可以完全摆脱目前网络中比较集中的对仲裁的需要。
Subgraph Studio是迈向去中心化 TheGraph的第一步,但它仍然包含中心化的组件。在其目前的设计中,支付是由The Graph团队直接处理的,你创建一个API密钥来查询数据。以后一旦实现了可验证的查询,用户将直接付款。
如果你有已经在托管服务上的subgraph,可以看看这个迁移指南。
$ npm install -g @graphprotocol/graph-cli
。npx hardhat run scripts/deploy.ts --network rinkeby
。$ graph init --studio <created-subgraph-name>
。artifacts/contracts/Game.sol/Game.json
。$ graph auth --studio <my-subgraph-id>
(见Subgraph Studio UI)$ graph codegen && graph build
。$ graph deploy --studio <my-subgraph-id>
。现在你可以在Subgraph Studio中点击 发布
。要获得Rinkeby testnet GRT,请到The Graph Discord #roles,点击'T',然后到#testnet-faucet,输入!grt <自己的以太坊地址>。然后你就可以立即开始策展subgraph了。请注意,在写这篇文章的时候,还不支持通过去中心化网络对Rinkeby进行实际查询,但对于主网来说是支持的。
新的AssemblyScript版本:Graph已经更新了用于编写映射的AssemblyScript。如果你习惯于旧版本,你可以遵循迁移指南。
调试克隆(Forking):一个名为debug forking的新功能允许克隆一个已部署的subgraph并改变其对特定块的映射。因此,如果你部署了一个新的subgraph而它失败了,现在你可以从该区块进行本地调试,而不是从头开始重新同步,浪费大量的时间。
新的区块链:虽然在去中心化网络上还不能使用,但The Graph已经为新公链增加了索引支持,最需要了解的是Cosmos、NEAR 和Arweave。
subgraph映射单元测试: 一个名为matchstick的新单元测试功能可以测试subgraph映射,详情见下文。
要开始在现有的subgraph中进行单元测试。
$ yarn add --dev matchstick-as
。$ brew install postgresql
(Mac) 或 $ sudo apt install postgresql
(Linux) /tests
文件夹中创建测试文件。$ graph test
。以下是之前的上一篇 TheGraph文章的Bet映射的单元测试例子:
import {
assert,
describe,
clearStore,
test,
newMockEvent,
} from "matchstick-as/assembly/index";
import { BetPlaced } from "../generated/Game/Game";
import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts";
import { handleBetPlaced } from "../src/mapping";
function createBetPlacedEvent(
player: string,
value: BigInt,
hasWon: boolean
): BetPlaced {
const mockEvent = newMockEvent();
const BetPlacedEvent = new BetPlaced(
mockEvent.address,
mockEvent.logIndex,
mockEvent.transactionLogIndex,
mockEvent.logType,
mockEvent.block,
mockEvent.transaction,
mockEvent.parameters,
null
);
BetPlacedEvent.parameters = new Array();
const playerParam = new ethereum.EventParam(
"player",
ethereum.Value.fromAddress(Address.fromString(player))
);
const valueParam = new ethereum.EventParam(
"value",
ethereum.Value.fromUnsignedBigInt(value)
);
const hasWonParam = new ethereum.EventParam(
"hasWon",
ethereum.Value.fromBoolean(hasWon)
);
BetPlacedEvent.parameters.push(playerParam);
BetPlacedEvent.parameters.push(valueParam);
BetPlacedEvent.parameters.push(hasWonParam);
BetPlacedEvent.transaction.from = Address.fromString(player);
return BetPlacedEvent;
}
describe("handleBetPlaced()", () => {
test("Should create a new Bet entity", () => {
const player = "0x7c812f921954680af410d86ab3856f8d6565fc69";
const hasWon = true;
const mockedBetPlacedEvent = createBetPlacedEvent(
player,
BigInt.fromI32(100),
hasWon
);
handleBetPlaced(mockedBetPlacedEvent);
const betId =
mockedBetPlacedEvent.transaction.hash.toHex() +
"-" +
mockedBetPlacedEvent.logIndex.toString();
// fieldEquals(entityType: string, id: string, fieldName: string, expectedVal: string)
assert.fieldEquals("Bet", betId, "id", betId);
assert.fieldEquals("Bet", betId, "player", player);
assert.fieldEquals("Bet", betId, "playerHasWon", "true");
assert.fieldEquals(
"Bet",
betId,
"time",
mockedBetPlacedEvent.block.timestamp.toString()
);
clearStore();
});
});
你可以首先使用newMockEvent
创建模拟事件。
然后以你喜欢的方式修改模拟的事件。
然后从映射中调用处理事件函数。
断言新的状态符合预期。
事后清理存储。
你可以在https://github.com/soliditylabs/the-graph-studio-example 找到完整的例子。
本翻译由 Duet Protocol 赞助支持。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!