Transaction and receipt ordering

Hello everyone, I’ve been doing a deep research into how Near sequences transactions. I’ve read all the documentation and nomicon and went through the nearcore code a bit. However, the guarantees and logic about transaction and receipt ordering are not clear anywhere.

Near’s sharded and asynchronous nature is very different to reason about than other L1 blockchains. In synchronous blockchains the order of execution of transactions is basically the order in which they are inserted into a block. On Near, however, the specification is completely different.

According to source RuntimeSpec/ApplyingChunk in the protocol specs, the processing order in a chunk is:

  1. Process all transactions, converting them into receipts;
    1.1 Whenever signer_id == receiver_id those receipts are considered local_receipts and marked for execution acording to nearcore code (near/nearcore/blob/master/runtime/runtime/src/ line 251, process_transaction)
    1.2 Whenever signer_id != receiver_id those receipts are stored in outgoing receipts (near/nearcore/blob/master/runtime/runtime/src/ line 251, process_transaction)

  2. local_receipts are processed in the same order of the transactions that generated them

  3. delayed_receipts that haven’t been processed in previous blocks, according to the order in which they are stored

  4. incoming_receipts - according to the specifications they are ordered by incoming_receipts which doesn’t add much information

By reading this specification I came to the following conclusions:

  1. Whenever a transaction is issued it is directed to the shard where the signer_id for that transaction lives
  2. If the transaction’s receiver is the signer itself, the transaction is converted into a receipt and then immediately processed in the block
  3. If the transaction’s recipient is a different account, the receipt is routed to the shard of that specific account.

And here is the trick, how can nodes know the correct ordering of outgoing receipts? Let’s say shards 1, 2 and 3 generate outgoing receipts in block N for a receiver account that is in shard 4 - In block N + 1 are there any guarantees of order to process the receipts in shard 4? Moreover, is it guaranteed that shard 4 is going to have received all the pending receipts by block N + 1?

This issue is extremely important to understand the threat model of validators and chunk producers. If there is no guarantee of order in the protocol itself they could reorder receipts to their liking and use it to manipulate the network. Also, if there are guarantees, they are buried deep in the code and not easy to understand when reading the whitepaper and specifications.

Would appreciate it if protocol devs could help me figure this out. I’d also love to maybe write a session in the docs explaining this once I’ve found the answer. Thanks everyone!