On-chain message ordering using Teleporter #195
Replies: 1 comment 1 reply
-
Hi @vikinatora thank you for opening this discussion! We especially appreciate the detailed consideration of the tradeoffs with each approach. Our strong preference for message ordering is to do so at the dapp level, rather than at the Teleporter protocol level. For the reasons you mentioned, as well as the increased implementation complexity in the Your second approach - Ordering on the dapp layer - uses the Teleporter message ID as the sequence number within the dapp. This introduces edge cases with respect to new versions of Rather, we suggest implementing ordering entirely at the dapp level by including a sequence number as part of the Teleporter payload itself. The dapp would therefore have full control over the sequence number generated on the sending side, regardless of which (uint256 sequenceNumber, bytes memory callData) = abi.decode(
message,
(uint256, bytes)
);
require(latestReceivedSequenceNumber + 1 == sequenceNumber, "Strict ordering of messages is enforced"); |
Beta Was this translation helpful? Give feedback.
-
Context
As stated in #42:
This discussion aims to present two approaches, along with their respective pros and cons. I hope this will stimulate a discussion, dissecting possible solutions, and hopefully, we can converge on a reliable and effective one.
Approach 1 - Ordering on the Messenger layer
Overview
This approach implements the ordering on the Messenger(
ITeleporterMessenger
) layer. This is a higher-level approach, resulting in abstracting away the complexities away from the users. As long as, the message is sent and delivered using this Messenger, the messages are guaranteed to be delivered to dapps in corect order.However, it’s a slightly riskier approach(than the 2nd approach) because a bug would compromise all subnets and dapps that use this specific Messenger. Additionally, if this approach is chosen, then the Messenger’s contract address would be different than the standard one between subnets after deployment as byte code will be different, following Nick’s method. This is not an issue as
TeleporterRegistry
exists, allowing for new Messengers to be deployed. Dapps can decide for themselves which versions of Messenger to allow. Time means that this approach couples origin subnets to have the same Messenger deployed and it must be the one used to send the message because of a validation.Implementation
The steps below are not an exhaustive list of the changes required. They serve to highlight the main differences with the current Messenger implementation.
Modify Messenger protocol(
receiveCrossChainMessage
) to feature ordering of messages:teleporterMessage.messageID
receivedFailedMessageHashes
so it can be reexecuted usingretryMessageExecution
Issues
Issue 1: When two messages are sent in a quick succession, a reordering of the messages can happen on the relayer layer(f.e because of incentivization). In that case, the messenger contract will receive the message with id 2 before the message with id 1. This blocks the execution of messages with id greater than 2 because 2 won’t be executed as it arrived first.
Possible solutions:
Approach 2 - Ordering on the dapp layer
Overview
This approach implements the ordering on the Receiver(
ITeleporterReceiver
) layer. Less risky approach as risk of bugs is isolated in the dapp contract itself. Additionally, ordering isn’t tied to Messenger layer’smessageID
, lowering the security assumptions and trust between the two layers. This way a dapp can have it’s own custom ordering functionality.Implementation
A possible implementation would have some additional logic inside
receiveTeleporterMessage
:id
field in each teleporter message (different thanmessageID
becauseITeleporterReceiver
doesn’t have access tomessageID
)Issues
The real message execution order could be tricked. Let’s take these two messages that are sent in quick succession. Message A is sent by a good actor and Message B by a bad one, looking to take advantage of the dapp’s protocol.
If for some reason(f.e incentivization) message B arrives to the destination subnet’s dapp before message A, then the dapp can be tricked to believe that B has been sent earlier than A because it doesn’t have access to
messageID
.Possible Solution
messageID
and previousmessageID
accessible on the Receiver Layer by changing signature ofreceiveTeleporterMessage
and modifying Messenger layer’s_handleInitialMessageExecution
payload encodingNote: The reason
lastSentMessageID
is made accessible is becausemessageID
is an identifier on a subnet level. A dapp could receive message ID 1 and message ID 4 after, and that would be completely fine, as long as the other 2 messages(IDs 2 and 3) were meant to be delivered to other dapps.uint256 latestReceivedMessageID;
receiveTeleporterMessage
Note: If we just want to make sure ordering is correct, the 2nd validation isn’t required and can be removed.
latestReceivedMessageID
latestReceivedMessageID = messageID
One approach would be to store them in a field and expose a function that executes them as long as it’s their order. Storing only the message bytes may be an oversimplification but it gets the point across.
Open questions
Edit: fixed links not showing up correctly
Beta Was this translation helpful? Give feedback.
All reactions