跳到主要内容

外部消息

外部消息是从外部发送到 TON 区块链中的智能合约,以使它们执行特定操作。

例如,钱包智能合约期望接收包含钱包所有者签名的订单的外部消息(例如,从钱包智能合约发送的内部消息)。当这样的外部消息被钱包智能合约接收时,它首先检查签名,然后接受消息(通过运行 TVM 原语 ACCEPT),然后执行所需的任何操作。

危险

请注意,所有外部消息必须受到保护,以防止重放攻击。验证者通常会从建议的外部消息池中移除一条外部消息(从网络接收);然而,在某些情况下,另一个验证者可能会两次处理同一个外部消息(从而为同一个外部消息创建第二个交易,导致原始操作的重复)。更糟糕的是,恶意行为者可以从包含要处理的交易的区块中提取外部消息并稍后重新发送。这可能会迫使钱包智能合约重复付款,例如。

保护智能合约免受与外部消息相关的重放攻击的最简单方法 是在智能合约的持久数据中存储一个 32 位计数器 cur-seqno,并在任何入站外部消息的(已签名部分)中获取一个 req-seqno 值。然后只有在签名有效且 req-seqno 等于 cur-seqno 时,才接受外部消息。在成功处理后,持久数据中的 cur-seqno 值增加一,因此相同的外部消息将不再被接受

而且也可以在外部消息中包含一个 expire-at 字段,并且只有在当前 Unix 时间小于此字段的值时,才接受外部消息。这种方法可以与 seqno 结合使用;或者,接收信息的智能合约可以在其持久数据中存储所有最近(未过期)接受的外部消息的(哈希)集合,如果它是存储消息之一的副本会拒绝新的外部消息。此集合中对过期消息的一些垃圾回收也应该执行,以避免持久数据膨胀。

备注

一般来说,外部消息以一个 256 位签名(如果需要)、一个 32 位 req-seqno(如果需要)、一个 32 位 expire-at(如果需要),以及可能的 32 位 op 和其他根据 op 所需的参数开始。外部消息的布局不需要像内部消息那样标准化,因为外部消息不用于不同(由不同开发者编写和不同所有者管理)智能合约之间的互动。