主页 > 苹果手机下载imtoken钱包流程 > Web3j的智能合约可以解决java后端事件是目前最简单的方法

Web3j的智能合约可以解决java后端事件是目前最简单的方法

什么是智能合约事件? 您可以从交易触发的任何智能合约函数中发出事件,它们是以太坊应用程序架构难题的重要组成部分。这些事件由名称和

什么是智能合约事件?

您可以从交易触发的任何智能合约函数发出事件,它们是以太坊应用程序架构难题的重要组成部分。

这些事件包含一个名称和最多 17 个参数,其内容由发射函数提供。 参数可以是索引的或非索引的; 使用索引参数可以实现高效的链下查找。

例如,如果事件 x 包含一个索引字符串参数 y,那么在链下,我可以使用过滤器来检索 y == "foo" 的所有事件。 (稍后会详细介绍过滤器)

事件存储为日志而不是 EVM 存储,因此,它们具有您应该注意的属性:

由于智能合约无法访问:虽然智能合约功能会发出事件,但智能合约在发布后无法访问此事件信息。 这对于排放合同以及任何其他外部合同都是如此。 因此,您不能使用事件进行智能合约间通信。

事件很便宜!:由于事件存储为日志,因此与更新 EVM 存储状态的传统方法相比,它们非常便宜。 确切的成本取决于事件规范和事件中数据的大小。

事件的常见用途

异步链下触发器

大多数企业 Java 开发人员都熟悉事件总线模式,其中事件被发布到队列(例如 RabByMQ 或 Amazon SQL)。 这种模式允许对特定事件感兴趣的服务在总线之外异步地使用它们并执行进一步的处理,而发布者和消费者服务之间没有任何耦合。

事件总线模式

怎么查以太坊公链查智能合约_以太坊智能合约执行时的手续费_图解以太坊智能合约

服务可以以类似的方式使用以太坊智能合约事件,以太坊网络充当一种消息队列。 链下服务可以向节点注册事件过滤器,每次在以太坊网络中发出此事件时都会通知该节点。 然后以太坊智能合约执行时的手续费,您可以将这些事件通知用作进一步链下处理的触发器,例如更新基于 NoSQL 的智能合约状态缓存。

以太坊作为“事件总线”

用于链下消费的廉价数据存储

如上所述,将数据存储在事件中比存储在 EVM 合约中要便宜得多。

作为对比,稍微深挖一下,保存32个字节的数据到合约存储需要20000个gas,而发送一个事件需要375个gas加上每个索引参数375个gas,每个字节的数据额外需要8个gas。

由于这些成本的节省,将链上智能合约函数永远不会读取的数据存储在事件中而不是合约存储中是一种常见的模式。

可能出现这种情况的一个例子是公证服务,其中将 IPF 哈希提交给以太坊区块链以证明创建日期。 在发出包含文档的 IPFS 哈希的事件后,如果存在争议,可以通过查询合约事件(而不是合约状态)来验证链下公证时间戳。

定义和发出事件

以太坊智能合约中的定义、发送和事件都是一段代码:

定义

事件公证(地址索引公证,字符串文档哈希)

在此示例中,我们定义了一个名为 Notarized 的事件,其中包含一个索引地址参数 notary 和一个非索引字符串参数 documentHash。

发送

函数 notarizeDocument(string_documentHash) public {

发出 Notarized(msg.sender, _documentHash);

}

emit 关键字触发事件,参数以类似于函数调用的方式传递给事件。 这里通过msg.sender设置公证人地址为交易的发送方地址,documentHash与调用函数的参数相同。

使用 Web3J 监听发出的事件

到目前为止,使用 web3j 收听以太坊智能合约事件的最简单方法是使用库的合约包装器功能。

下面的代码片段连接到本地以太坊节点并监听从已部署的公证合约发出的所有公证事件:

Web3j web3j = Web3j.build(new HttpService("http://localhost:8545"));

//通过包装器部署公证合约

最终公证人 notaryContract = deployNotaryContract(web3j);

公证合同

.notarizedEventFlowable(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST)

.subscribe(事件 -> {

最终字符串公证人 = 事件。 公证人;

final String documentHash = event.documentHash;

//根据事件值进行处理

});

自动生成的合约包装器代码包含使用命名模式 EventFlowable 为智能合约中定义的每个事件提供的便捷方法。 此方法采用开始和结束块参数,在此示例中,使用 DefaultBlockParameterName.LATEST 值指示 web3j 继续无限期地侦听新块的事件。 如果您需要特定的块范围,可以使用 DefaultBlockParameter.valueOf(BigInteger.valueOf(...)) 。 返回一个 Flowable 对象,然后可以订阅该对象以对发出的事件执行处理逻辑。

此方法简化了事件侦听过程,因为它会自动将原始日志消息转换为具有反映已定义事件参数的字段的对象。 如果没有这个,你必须自己解码这些值,尽管 web3j 为此提供了辅助方法,但事情很快就会变得复杂。

按索引参数值过滤

将事件的参数设置为索引有助于通过参数值高效地查询事件。 Web3J 通过手动构建 ethfilter 对象来支持此查询。 以下代码用于侦听针对特定以太坊地址公证的事件:

final EthFilter ethFilter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST,

公证合同。 getContractAddress());

ethFilter.addSingleTopic(EventEncoder.encode(notaryContract.NOTARIZED_EVENT));

ethFilter.addOptionalTopics("0x" + TypeEncoder.encode(新地址("0x00a329c0648769a73afac7f9381e08fb43dbea72")));

公证合同

.notarizedEventFlowable(ethFilter)

.subscribe(事件 -> {

最终字符串公证人 = 事件。 公证人;

final String documentHash = event.documentHash;

//根据事件值进行处理

});

notarizedEventFlowable 被重载并且可以接受 EthFilter 作为参数而不是块范围。 此过滤器用于以更细粒度的方式定义要侦听的事件,并使用与先前传递给该方法的相同块范围构造。

还有一些主题可以设置在过滤器上。 在以太坊过滤器中,第一个主题始终定义为事件签名的 keccak 哈希,在我们的例子中是“Notarised(address, string)”。 这是借助 Web3j 提供的 EventEncoder.encode(..) 方法和包装类中自动生成的事件规范 NOTARIZED_EVENT 计算得出的。

可以使用 addOptionalTopics(..) 方法添加其他主题,该方法指定要匹配的索引参数的值,顺序与事件规范中定义的顺序相同。 编码根据参数的类型略有不同,但幸运的是 Web3j 提供了 TypeEncoder 类来为我们处理这个问题。 在提供的示例中以太坊智能合约执行时的手续费,我们仅监听具有地址 0x00a329c0648769a73afac7f9381e08fb43dbea72 的公证值的事件。

总结

事件是后端(和前端)服务异步通知智能合约更改和交互的好方法,也是一种经济的方式将数据存储在以太坊区块链上,不需要被智能合约有效地消耗。

与许多以太坊交互一样,Web3j 生成的智能合约包装器是迄今为止订阅和处理 java 后端发出的事件的最简单方法。 (链三丰)

怎么查以太坊公链查智能合约_图解以太坊智能合约_以太坊智能合约执行时的手续费

关键词: