Skip to content

Conversation

@olegrok
Copy link
Contributor

@olegrok olegrok commented Apr 10, 2025

⚠️ Note: This patch is not intended to be merged as-is. It serves only as a demonstration of how a Message Queue contract could be implemented.

There are several issues that arise with this approach, and not all of them have been resolved yet.


Summary of Changes

  • A Message Queue contract is deployed on each shard.
  • The contract currently provides only basic functionality:
    • Adding messages to the queue.
    • Clearing the queue.
  • Queue clearing is performed at the beginning of each block via a system call sent by proposer.
  • The most interesting part is message persistence: both the message data and the sender’s address are saved.
  • Only SmartAccount.send method is ported to this approach.
  • At the end of the block production cycle, all messages from the queue are collected and included in the "out transaction tree".
    • In the future, we might completely remove the transaction tree.
    • For now, with both approaches coexisting, this hybrid implementation is used.
  • Malformed or invalid messages are currently dropped silently.

Potential Next Steps

  • Reduce and consolidate existing message-sending interfaces.
  • Replace the Nil.sendTransaction interface with MessageQueue.sendRawTransaction.
  • Improve error handling and diagnostics.
  • ...

g.executionState.AppendForwardTransaction(txn)
}

messages, err := GetMessageQueueContent(g.executionState)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we get messages queue from other shards targeting to our shard?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do that by proposer. I suggest to implement step-by-step solution. It's the first step in this directon.

Right now an approach doesn't break existing code. We just copy a message queue content to an existing outbound messages tree. Ideally, we need to drop old approach and then it will be possible to use only queue account state.

delete queue;
}

Message[] private queue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is worth to separate this array by shard. So the other shard can fetch only messages addressed to him: getMessages(uint shardId)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now we don't have a special interface to send data to specific shard. Our smart accounts operates with raw calldata and we can extract destination shard only after decoding a message. But we don't have a SSZ decoder in Solidity. So here we have single queue for all messages. In future then we will pass destination shards/address explicitly it will be possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the limits on the size of the queue or message size in queue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also how would this compare to another approach such as emitting an event instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the limits on the size of the queue or message size in queue?

Right now there is no any limits but we can add them

Also how would this compare to another approach such as emitting an event instead?

I didn't think about emitting events but this looks like an attempt to move all magic out of EVM. Sounds interesting but I'm not sure it's what we expect. Should be discussed. Thanks for idea.

Comment on lines +7 to +8
bytes data;
address sender;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it may be convenient to introduce more fields here (e.g. tokens)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the first version I'd just want to check that it will work at all. basic test passed. We can discussed it and extends current implementation.

if err != nil {
return fmt.Errorf("failed to create MQ prune transaction: %w", err)
}
p.proposal.SpecialTxns = append(p.proposal.SpecialTxns, txn)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the tx fails or if the block containing the tx is not finalized?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If such TX fail we fail block validation on consensus and then new block in the next round will be suggested.

delete queue;
}

Message[] private queue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the limits on the size of the queue or message size in queue?

delete queue;
}

Message[] private queue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also how would this compare to another approach such as emitting an event instead?

}

contract MessageQueue is IMessageQueue{
function sendRawTransaction(bytes calldata _message) external override {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are thoughts around supporting attaching value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Value is attached inside this message. It's out InternalTransactionPayload encoded with SSZ.
We can try to send messages encoded in EVM serialization but it's also should be discussed.

Do we need to send SSZ inside EVM at all. Or should be accept only ABI packed data and only then we need to repack into SSZ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants