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

feat: support l2 plus #1157

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open

feat: support l2 plus #1157

wants to merge 26 commits into from

Conversation

karlem
Copy link
Contributor

@karlem karlem commented Sep 26, 2024

Part of #1080

This PR focuses on:

Integration Tests in Solidity (L3-Level Testing)

  • Write and run integration tests to cover the following scenarios:
    • Happy Path Scenarios:
      • From root to L3. - DONE
      • From L3 to root. - DONE
      • Between sibling L3 nodes. - DONE
    • Failure Scenarios:
      • Errors at the destination. - DONE
      • Errors midway through execution. Not sure this is really an issue.
    • Edge Case Testing:
      • Supply source mismatches. - This should really not be an issue - as the only cross net messages allowed are Call kind. (not trasfers)
      • Non-existent destinations. - DONE
    • Ensure all error cases propagate correctly. - DONE

Improvements

  • Improved visibility by adding new events into the cross-message propagation process. A cross-message ID has been added to each event for better tracking and transparency:
    • CheckpointCommitted
    • NewBottomUpMessage
    • MessageStoredInPostbox
    • MessagePropagatedFromPostbox
  • Automated cross-message propagation from the postbox. Previously, this process required an external caller to propagate the message, but now the IPC automatically propagates them after a checkpoint has been committed or after top-down messages have been applied.
  • Added a check to verify that the destination address is indeed a contract and not an EOA (Externally Owned Account).
  • Changed the behavior when applying messages: instead of reverting when a message is invalid, a result receipt is returned. This ensures that one invalid message does not disrupt the entire checkpoint submission process.
  • Extracted message validation into a separate function to ensure validation is completed before committing the message. The validation function does not revert since reversion is only desirable when the message is directly triggered by a user. In scenarios where the message originates from a different subnet (e.g., in the form of a checkpoint), reversion is not appropriate. For the same reason, the commit functions (top-down, bottom-up) should also not revert, as they are triggered by automatic postbox propagation. Instead, validation is performed beforehand.

@karlem karlem changed the title Support l2 plus feat: support l2 plus Oct 11, 2024
@karlem karlem marked this pull request as ready for review October 11, 2024 20:03
@karlem karlem requested a review from a team as a code owner October 11, 2024 20:03
Copy link
Contributor

@raulk raulk left a comment

Choose a reason for hiding this comment

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

Some minor comments.

contracts/contracts/gateway/GatewayMessengerFacet.sol Outdated Show resolved Hide resolved
contracts/contracts/gateway/GatewayMessengerFacet.sol Outdated Show resolved Hide resolved
contracts/contracts/gateway/router/CheckpointingFacet.sol Outdated Show resolved Hide resolved
contracts/contracts/lib/AssetHelper.sol Outdated Show resolved Hide resolved
contracts/contracts/lib/CrossMsgHelper.sol Show resolved Hide resolved
function down(SubnetID calldata subnet1, SubnetID calldata subnet2) public pure returns (SubnetID memory) {
if (subnet1.root != subnet2.root) {
revert DifferentRootNetwork();
return SubnetID({root: 0, route: new address[](0)});
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a reason why it's not reverted? Feels like it's an error that should be handled instead of introducing root = 0 as invalid subnet. Probably in some use cases root: 0, route: [] is a valid use case.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds like this needs multi-return? SubnetID + bool?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem here is that if I revert, I lose control elsewhere. The method is also used invalidateCrossMessage, where reverting is not desirable. Additionally, commonParent method here returns the empty subnet ID instead of reverting. But I understand your point—if this were deployed on Ethereum, the root could be zero. Would returning a boolean (indicating whether it was found or not) help?

contracts/contracts/lib/LibGateway.sol Show resolved Hide resolved
contracts/contracts/lib/CrossMsgHelper.sol Show resolved Hide resolved
contracts/test/integration/L2PlusSubnet.t.sol Outdated Show resolved Hide resolved
contracts/test/integration/L2PlusSubnet.t.sol Show resolved Hide resolved
contracts/test/integration/L2PlusSubnet.t.sol Show resolved Hide resolved
contracts/test/integration/L2PlusSubnet.t.sol Show resolved Hide resolved
contracts/test/integration/L2PlusSubnet.t.sol Outdated Show resolved Hide resolved
@cryptoAtwill
Copy link
Contributor

@karlem Another question I have is regarding nonce. Say a bottom up message is created in L3, the nonce will be set by the local network. Then in L2, will the cross network message nonce change? If so, then the id (keccak) will change too?

Copy link
Contributor

@raulk raulk left a comment

Choose a reason for hiding this comment

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

Some initial comments.

contracts/contracts/errors/IPCErrors.sol Show resolved Hide resolved
contracts/contracts/lib/LibGateway.sol Show resolved Hide resolved
contracts/contracts/lib/LibGateway.sol Outdated Show resolved Hide resolved
contracts/contracts/lib/LibGateway.sol Outdated Show resolved Hide resolved
contracts/contracts/lib/LibGateway.sol Show resolved Hide resolved
contracts/test/helpers/TestUtils.sol Outdated Show resolved Hide resolved
contracts/test/helpers/TestUtils.sol Outdated Show resolved Hide resolved
IPCAddress({
subnetId: gatewayDiamond.getter().getNetworkName().getParentSubnet(),
rawAddress: FvmAddressHelper.from(receipient)
}),
IPCAddress({subnetId: id, rawAddress: FvmAddressHelper.from(address(this))}),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because it was labeled as a top-down message, but the path (from, to) made it a bottom-up message, the test was incorrect. Since we now have checks ensuring that top-down messages are indeed top-down (as a parent can't send a message to itself), this would cause a revert.

contracts/test/integration/L2PlusSubnet.t.sol Outdated Show resolved Hide resolved
contracts/test/integration/L2PlusSubnet.t.sol Outdated Show resolved Hide resolved
@karlem
Copy link
Contributor Author

karlem commented Oct 24, 2024

@karlem Another question I have is regarding nonce. Say a bottom up message is created in L3, the nonce will be set by the local network. Then in L2, will the cross network message nonce change? If so, then the id (keccak) will change too?

Hmm that's a good point. I will think about how to mitigate this.

@karlem
Copy link
Contributor Author

karlem commented Oct 28, 2024

@cryptoAtwill should be ready for another review :)

Copy link
Contributor

@cryptoAtwill cryptoAtwill left a comment

Choose a reason for hiding this comment

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

LGTM. But I do have a few follow up questions though:

  1. Does it work in calibration with a live 3 level network? Is there a testnet we can try or planned?
  2. propagateAll is called in the parent as part of bottom up checkpoint. Bottom up checkpoint is already quite gas costly, not sure if this will burst the gas even more.

@@ -131,6 +135,22 @@ library CrossMsgHelper {
return keccak256(abi.encode(crossMsg));
}

/// @notice Returns a deterministic hash for the given cross message. The hash remains the same accross different networks
/// because it doesn't include the network-specific nonce.
function toDeterministicHash(IpcEnvelope memory crossMsg) internal pure returns (bytes32) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess most of the time this is ok, but will this cause conflict if say someone sends the same message twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It might collide, but it is only for logging so it should not matter.

/// `Call` cross-messages also trigger receipts if they are successful.
/// @param arrivingFrom - the immediate subnet from which this message is arriving
/// @param crossMsg - the cross message to be executed
/// @param expectTopDownOnly - whether the message should be top-down only. Reverts if it is not.
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 I was misled by the comment here. The idea is whether the message should be top-down only. Reverts if this flag is true but the crossmsg is actually bottom up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverts if it's both - not only top down :)

@karlem
Copy link
Contributor Author

karlem commented Nov 20, 2024

Does it work in calibration with a live 3 level network? Is there a testnet we can try or planned?

It should. Whether is Calibration or not.

propagateAll is called in the parent as part of bottom up checkpoint. Bottom up checkpoint is already quite gas costly, not sure if this will burst the gas even more.

We don't really have any other option here. I don't think we really optimise for gas efficiency at this stage. Moving forward we might re-write the contracts L2+ as native actors to make it cheaper.

Copy link
Contributor

@cryptoAtwill cryptoAtwill 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 this is no longer correct: https://github.com/consensus-shipyard/ipc/pull/1157/files#diff-71559bfe927afaf1a3980c01ffe9f4d15c77d58650b2d850bbae821de9c009d0R49.

This implicitly assumes the token behind envelop.value is the native token in the origin subnet. If say I want to trigger transfer from address A to address B in L1 and I'm sending from L3, why should I attach that amount in msg.value?

It comes back to the definition of envelop.value, is it just the native token transfer in the target subnet. If this is the case, it does not make sense to have this check.

@karlem
Copy link
Contributor Author

karlem commented Nov 27, 2024

@cryptoAtwill The issue was resolved by not using or supporting native token transfers in the Call message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

Successfully merging this pull request may close these issues.

3 participants