很难说数据工程文化在Web3.0开发人员社区中已经根深蒂固。并不是每个开发人员都能很容易地确定索引在Web3.0上下文中意味着什么。我想定义一些关于这个话题的细节,并谈谈The Graph,它已经成为DApp开发者在区块链上访问数据的事实上的行业标准。
让我们从索引开始。
数据库中的索引是创建一个数据结构的过程,该数据结构对数据库中的数据进行排序和组织,以便能够有效地执行搜索查询。通过在数据库表上创建索引,数据库服务器可以更快地搜索和检索与查询中指定的条件匹配的数据。这有助于提高数据库的性能,并减少检索信息所需的时间。
但是区块链中的索引呢?最流行的区块链架构是EVM(以太坊虚拟机)。
以太坊虚拟机(EVM)是在以太坊区块链上执行智能合约的运行时环境。它是一个在以太坊网络上的每个节点上运行的计算机程序。它负责执行智能合约的代码,还提供sandbox和gas使用控制等安全功能。EVM确保以太坊网络上的所有参与者都能以一致和安全的方式执行智能合约。
你可能知道,区块链上的数据以区块的形式存储,其中包含交易。另外,你可能知道有两种类型的账户:
如果您从您的帐户发送一些以太币到任何其他外部所有者的帐户-没有任何中间件环节。但是,如果您将一些以太币发送到具有任何有效载荷的智能合约地址,您实际上会在智能合约上运行一些方法,这些方法实际上会创建一些“内部”交易。
好吧,如果在区块链上可以找到任何交易,为什么不把所有数据转换成一个不断更新的大数据库,可以用类似sql的格式查询呢?
问题是,只有当你有“钥匙”来破译它时,你才能访问智能合约的数据。没有这个“密钥”,区块链上的智能合约数据实际上是一团糟。这个密钥被称为ABI(应用程序二进制接口)。
ABI(应用程序二进制接口)是一个标准,它定义了智能合约与外部世界的通信方式,包括其他智能合约和用户界面。它定义了智能合约的数据结构、函数签名和参数类型,以实现合约与用户之间正确有效的通信。
任何链上智能合约都有ABI。问题是,您可能没有您感兴趣的智能合约的ABI。有时,您可以找到一个ABI文件(它实际上是一个JSON文件,其中包含智能合约的函数和变量的名称-就像一个用于通信的接口)。
当然,如果您是智能合约的开发人员,您就拥有ABI,因为它是在编译时生成的。
但是我们不要停留在ABI的概念上。如果我们从智能合约开发者的角度来看待这个话题呢?什么是智能合约?答案比你想象的要简单得多。对于熟悉面向对象编程的人,这里有一个简单的解释:
开发人员代码中的智能合约是一个带有字段和方法的类(对于evm兼容的链,智能合约通常用Solidity编写)。而部署在链上的智能合约则成为该类的对象。因此,它允许用户调用它的方法并更改它的内部字段。
值得强调的是,智能合约状态发生变化的任何方法调用都意味着一个事务,通常紧随其后的是开发人员从代码中发出的事件。让我们举例说明ERC-721(不可替代的令牌集合的通常标准,如BoredApeYachtClub)智能合约的函数调用,该合约在转移NFT的所有权时发出事件。
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
address owner = ownerOf(tokenId);
if (owner != from) {
revert ERC721IncorrectOwner(from, tokenId, owner);
}
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
owner = ownerOf(tokenId);
if (owner != from) {
revert ERC721IncorrectOwner(from, tokenId, owner);
}
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
// Decrease balance with checked arithmetic, because an `ownerOf` override may
// invalidate the assumption that `_balances[from] >= 1`.
_balances[from] -= 1;
unchecked {
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
我们在这里可以看到。要将NFT从你的地址转移到任何其他地址,你需要调用_transfer函数,传递这两个地址的值和这个NFT的ID。在代码中,您可以看到将执行一些检查,然后用户的余额将被更改。但重要的是,在函数代码的末尾,有一行
emit Transfer(from, to, tokenId);
这意味着这三个值将被“发出”到外部,并且可以在区块链的日志中找到。以这种方式保存所需的历史数据效率要高得多,因为将数据直接存储在区块链上太昂贵了。
现在我们已经定义了所有需要的概念来展示索引是什么。
考虑到任何智能合约(作为某个类的对象)在其生命周期中不断被用户(和其他智能合约)调用并改变状态(同时发出事件),我们可以将索引定义为在智能合约的生命周期内收集智能合约数据(其中的任何内部变量,而不仅仅是那些显式发出的变量)的过程,将这些数据与交易id(哈希)和区块号保存在一起,以便能够在将来找到有关它的任何细节。
值得注意的是,如果智能合约没有明确存储这些数据(我们知道它非常昂贵),那么就不可能访问钱包“A”的第一笔交易,代币“B”,或者智能合约“C”(或任何其他东西)中最大的交易。
这就是我们需要索引的原因。我们可以在SQL数据库中做的简单事情在区块链中变得不可能。因为没有索引。
换句话说,这里的“索引”是智能合约数据收集的同义词,因为在Web3.0中没有索引意味着没有数据访问。
过去开发人员是如何编制索引的。他们白手起家:
正如您所注意到的,它不仅不容易开发,而且不容易实时维护,因为每个节点故障都可能需要一些步骤才能再次实现数据一致性。这就是《the Graph》出现的原因。这是一个简单的想法,开发人员和最终用户需要轻松访问智能合约数据,而不需要所有这些麻烦。
Graph项目定义了一个称为“子图”的范式,为了从区块链中提取智能合约数据,您需要描述3件事:
这三件事可以在以下三个文件中优雅地定义:
多亏了这个标准,按照这些教程中的任何一个描述整个索引都非常容易:
在这里可以找到更多的教程(https://docs.chainstack.com/docs/chainstack-subgraphs-tutorials)。
它是什么样子的?
正如你在这里看到的,Graph负责索引工作。但是你仍然需要运行一个图节点(它是The Graph的开源软件)。这是另一个范式转变。
由于过去的开发人员一直在运行自己的区块链节点,并且不再这样做,将这个麻烦交给了区块链节点提供商。该图显示了另一种架构简化。Graph托管服务以这种方式寻找开发人员(这里的“用户”):
在这种情况下,用户(或开发人员)不需要运行自己的索引器或图形节点,但仍然可以控制所有算法,甚至不会进入供应商锁定,因为不同的提供商使用相同的the graph描述格式(Chainstack与the graph完全兼容,但值得与您的web3.0基础设施提供商检查此声明)。这是一件大事,因为它可以帮助开发人员加快开发过程并降低操作维护成本。
但在这种范式中,很酷的一点是,任何时候开发人员想让他们的应用程序真正去中心化,他们都可以使用相同的子图无缝地迁移到The Graph去中心化网络。
我在之前的叙述中漏掉了什么。
页面更新:2024-05-09
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号