IPSE 2.0:Transaction Lifecycle-Substrate交易生命周期逻辑基础

863 阅读5分钟

Transaction Lifecycle

简述

IPSE是面向IPFS网络的搜索引擎,现在的IPSE 2.0 玩过正在基于Substrate进行跨链生态开发。Substrate是一个高扩展、模块化的开发框架,能帮助开发者快速开发区块链,构建分布式应用。

交易逻辑路劲

通过Substrate的模块设计获得高扩展特性。通过Substrate,开发人员可以创建自定义的runtime - 或应用逻辑 - 可以将任何类型的信息放入区块中。 尽管Substrate Core和SRML中提供了一些原生功能,但是链开发人员有责任验证进入区块中但还没有最终确认的信息。

本文将介绍Substrate提供的工具以及如何在你的runtime中放置检查逻辑的一些指导。

区块中的任何信息都称为“extrinsic”,该术语分为两种类型:

  • Transaction 是经过签名的信息,可以看作类似比特币或以太坊上的 Transaction。 交易在网络上传播,可以由任何节点提交以包含在一个区块中。
  • Inherents 是未经签名的信息,其来源、真实性和内容无法得到证明,出块者可以自行决定将其添加到区块中。 示例 inherent 如时间戳修改(处于状态中)或达成共识所需的验证人列表。 它们是“真实的”,因为被包含在区块之中,并且网络中的其他参与者通过验证该区块并同意在该区块之上继续构建新的区块。 Inherents 不会在网络上传播;而是出块者将它们写入区块中。 但是,inherents 仍然会影响状态,因此你需要一种方法,能够在最终确定它们之前,验证存储按照预期的那样被影响。

交易可以遵循两种路径:

  1. 从网络接收到一个区块
  2. 我们自己生成一个区块

在第一种情况下,该区块通过运行execute_block,整个区块要么成功,要么失败。

在第二种情况下,在发布区块之前,我们还有更多检查要执行。

  1. 我们在网络上监听交易。
  2. 我们通过validate_transaction函数验证每笔交易,并将有效交易放入交易池中。
  3. 交易池负责对交易进行排序,并返回准备好包含在区块中的交易。 1. 我们使用准备好的交易并通过BlockBuilder构造一个区块。
  4. BlockBuilder使用apply_extrinsic函数执行交易,并在本地内存中应用状态更改。
  5. 构造的区块将被发布到网络(所有其他参与者都使用execute_block运行它)。

在第2步中,validate_transaction进行了一些基本检查,并返回了一个枚举,它的变体有Valid,InvalidUnknownruntime 调用validate_transaction函数,并检查有效的签名和随机数(或者UTXO链的交易输出),但不检查对模块的任何调用是否成功。 validate_transaction孤立地检查每一笔交易,因此它不会捕获如同一输出两次被使用这样的错误。

实际上,通常可以使用validate_transaction检查对模块的调用,因为它在runtime可用。 但是,我们不建议这样做,因为它是一个潜在的DoS攻击载体,网络中的所有交易都将传递到validate_transaction中。 validate_transaction函数应侧重于为交易池提供必要的信息,以便对交易进行排序和优先级处理,并迅速拒绝所有肯定无效或过时的交易。 请注意,该函数将被频繁调用(对于同一交易,也可能多次调用)。 validate_transaction也有可能使依赖交易失败,如果该交易以正确的顺序执行,该交易将通过execute_block

我们使用validate_transaction的输出来排序交易池中的交易,并使用BlockBuilder[(代码)构造一个候选区块。 构造的区块中的所有extrinsics都通过apply_extrinsic(代码)执行,这将进行所有模块调用并将状态转换应用于我们的本地内存。 如果一切顺利,则该区块将传播到网络,就像第一种情况一样,每个人都将运行execute_block(此处为示例)。 在本地,将区块导入到链中,而无需运行execute_block(我们重用内存中的更改集)。

请记住,对于Substrate,通证转账不是唯一的状态转换:任何信息都可以写入一个区块中。 execute_block绝不应panic,并且如果对模块的调用返回Err,它将被最终确定并且对存储的更改将不会恢复。 这是因为恢复更改将要求每个节点在每个区块上复制存储。

当你要修改存储时,最佳实践是进行所有必要的检查,以确保调用成功,执行所有存储更改并最终发出事件,以便你知道该函数没有提前返回。

有关示例,请参见balances模块中的transfer(代码)功能 - 所有检查均在进行存储之前执行。

如果你正在设计自己的模块,那么你有责任确保无效的extrinsics永远不会panic,并且在返回Err时也不会修改模块状态。 正确的模块实现还可以通过担保机制,对提交无效extrinsics的恶意方进行惩罚(防止DoS攻击)。

Substrate为开发人员在区块和存储结构中提供了极大的自由度。 结果是,由于runtime的数量实际上是无限的,所有并非所有错误都可以在Substrate工具包中捕获。 应用程序开发人员需要实现自己的错误检查,以防止错误的存储修改。

IPSE

Substrate