Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore messages with duplicated nonces #2375

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

MitchTurner
Copy link
Member

@MitchTurner MitchTurner commented Oct 21, 2024

Linked Issues/PRs

Closes #1834

Description

Ignore new messages that share a nonce with an old message.

This isn't the only way to solve the issue but it was the solution proposed

we should probably just skip nonces that have already been seen before

Checklist

  • Breaking changes are clearly marked as such in the PR description and changelog
  • New behavior is reflected in tests
  • The specification matches the implemented behavior (link update PR if changes are needed)

Before requesting review

  • I have reviewed the code myself
  • I have created follow-up issues caused by this PR and linked them here

@MitchTurner MitchTurner changed the base branch from release/v0.40.0 to master October 21, 2024 12:38
@MitchTurner
Copy link
Member Author

Is this actually a breaking change? The contract is kinda changing, but only on the code side. It was implicitly the same before.

@MitchTurner MitchTurner marked this pull request as ready for review October 21, 2024 13:13
@MitchTurner MitchTurner requested a review from a team October 21, 2024 13:13
AurelienFT
AurelienFT previously approved these changes Oct 21, 2024
Copy link
Contributor

@AurelienFT AurelienFT left a comment

Choose a reason for hiding this comment

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

LGTM, little proposition in test.

crates/fuel-core/src/executor.rs Outdated Show resolved Hide resolved
block_storage_tx
.storage_as_mut::<Messages>()
.insert(message_nonce, &message)?;
}
execution_data
.events
.push(ExecutorEvent::MessageImported(message));
Copy link
Contributor

Choose a reason for hiding this comment

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

should this also be conditional to the message_nonce not being already present in the block storage?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. I've moved it.

This makes me wonder if we should be including an event in the case that a message is skipped. Or add it to a list of skipped messages, similar to the skipped tx.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should have the info somewhere that we manage a message with this nonce at this height and ignored this can be important to debug, index...

Copy link
Member Author

Choose a reason for hiding this comment

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

Added.

@MitchTurner MitchTurner requested a review from a team October 22, 2024 08:50
Copy link
Collaborator

@xgreenx xgreenx left a comment

Choose a reason for hiding this comment

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

I think it is a bad idea to just ignore the error. If the message is emitted by the contract, it means that someone deposited some funds. Ignoring the messages means that funds are lost forever.

I think we need to return an error if the message already exists in the table and insert it otherwise. It is not our responsibility to track the validity of how messages are emitted on the L1. We just need to be sure that it will not override the state.

Comment on lines +134 to +140
/// Ignored a message from the relayer.
MessageIgnored {
/// Ignored message
message: Message,
/// The reason for ignoring the message
reason: String,
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

We shouldn't add a new event at the middle since it is a breaking change for the WASM interface, basically you break all nodes in the network with this update and forces them to use a new fuel-core node.

Plus, I don't think that we even need MessageIgnored event since it doesn't change the state of the chain.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's fair. It was an afterthought and added a breaking section the the CHANGELOG to flag for this reason.

Comment on lines +920 to +932
let message_event = if !block_storage_tx
.storage_as_ref::<Messages>()
.contains_key(message_nonce)?
{
block_storage_tx
.storage_as_mut::<Messages>()
.insert(message_nonce, &message)?;
ExecutorEvent::MessageImported(message)
} else {
let reason =
"Message with the same nonce already exists".to_string();
ExecutorEvent::MessageIgnored { message, reason }
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure even how do we want to handle this case.

Right now you don't handle the situation mentioned by @Voxelot .

we should probably just skip nonces that have already been seen before

The Messages table contains only the list of unspent messages. If a message was seen before but spent after, it can still be inserted into the state in this solution.

Copy link
Member Author

Choose a reason for hiding this comment

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

If a message was seen before but spent after, it can still be inserted into the state in this solution.

You mean if a message with the same nonce gets spent before we check for nonce collisions, it will get added still. Right?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes. And I think it is okay behavior if L1 contracts emit the message with the same nonce. It is not our business to decide is it bad or not in this situation=D

Copy link
Member Author

Choose a reason for hiding this comment

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

Then maybe we want a data structure that allows us to store multiple messages with colliding nonces?

Copy link
Collaborator

Choose a reason for hiding this comment

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

No, only one message should be active at the time.

Copy link
Collaborator

@xgreenx xgreenx left a comment

Choose a reason for hiding this comment

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

Also will block this PR until we agreed on what is expected behavior

&ConsensusParameters::default(),
);
db.storage_as_mut::<Messages>()
.insert(message.id(), message)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
.insert(message.id(), message)
.insert(message.nonce(), message)

May I ask you to rename this method please?=D message.id() for me means MessageId return type, while it is not true.

Copy link
Member Author

Choose a reason for hiding this comment

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

There is already a nonce method that returns the same thing as id. Very silly.

@MitchTurner MitchTurner self-assigned this Oct 22, 2024
@xgreenx xgreenx marked this pull request as draft October 29, 2024 17:31
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.

Check Nonce of messages received by relayer
4 participants