相同信息 — 就lotus团队所知问题源自于有两条消息有相同的发送者/收到者详细信息、相同的nonce但拥有不同的Gas参数——被包含在同一tipset中。像这样两个类似的消息是非常常见的,比如以改变与消息的Gas费来替代消息就会形成这样两条类似的消息。这样的情况会由Filecoin网络安全、正确地处理,不会导致两次转账:两条消息中的一条会被执行,另一条被忽略。
错误使用API — 然而,根据人们对链的检查方式,这会呈现出消息被处理了两次的样子。具体来说,有关交易所使用了一种错误的处理链状态的方式——在tipset的每个块上调用ChainGetBlockMessages,然后在这些消息上调用StateGetReceipt。
错误的API期望 — 容易引发错误的地方是,当StateGetReceipt被调用在两个相似的消息上(其中一个被执行,另一个被跳过),它将提供相同的结果给人感觉两种消息都被执行了。这诚然是一种违背直觉思维的行为,但却是有意为之。StateGetReceipt的主要应用场景是在Lotus矿工和处理交易过程中使用的事件处理程序中。在消息被替换的情况下,这些模块并不关心返回的信息是对应原始消息,还是对应替换的消息——它们只是想知道消息是否在链上成功执行。我们已经在这里的文档中增加了澄清:https://github.com/filecoin-project/lotus/pull/5838。
使用正确的API — 大多数交易所都是正确使用了ChainGetParentMessages和ChainGetParentReceipts来记账,以计算出链上执行了什么消息、哪些消息成功了。这些都是Lotus本身在链state计算过程中使用的API,以保证使用者能通过这种方式正确反映链状态。对每一条消息执行StateReplay,可以得到完整的调用结果,这样使用者就可以将返回的InvocResult中的MsgCid与查询消息的CID进行比较。这是推荐交易所的正确检查链状态并保持内部报告系统同步的步骤。