Внешние сообщения
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Внешние сообщения отправляются извне
в смарт-контракты, находящиеся в блокчейне 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
. Структура внешних сообщений не обязательно должна быть такой же стандартизированной, как структура внутренних сообщений, поскольку внешние сообщения не используются для взаимодействия между различными смарт-контрактами (написанными разными разработчиками и управляемыми разными владельцами).