外部消息
外部消息是从外部发送
到 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
所需的参数开始。外部消息的布局不需要像内部消息那样标准化,因为外部消息不用于不同(由不同开发者编写和不同所有者管理)智能合约之间的互动。