-
Notifications
You must be signed in to change notification settings - Fork 58
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
MultiOffRamp - family-agnostic messages #1117
Conversation
_metadataHash(sourceChainSelector, sourceConfigUpdate.onRamp, Internal.EVM_2_EVM_MESSAGE_HASH); | ||
currentConfig.onRamp = sourceConfigUpdate.onRamp; | ||
if (currentOnRamp.length == 0) { | ||
// TODO: is this check sufficient / is an all-0 check needed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on this? Do we need a more complex validation that checks that at least 1 byte is non-zero? I'm thinking it would add much more complexity and contract size, maybe we could do this validation off-chain instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think this is fine. If the configured onramp is junk then messages will be unexecutable until we configure the correct one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This validation adds about ~6.4k gas to applySourceChainConfigUpdates
in the median case, and a 0.07KB contract size increase.
function validateNonZeroBytesAddress(bytes memory data) public pure {
uint256 length = data.length;
uint256 chunkCount = length / 32;
// Iterate over the `bytes` array in chunks of 32 bytes
for (uint256 i = 0; i < chunkCount; i++) {
bytes32 chunk;
assembly {
chunk := mload(add(data, add(32, mul(i, 32))))
}
if (chunk != 0) {
return;
}
}
// Check any remaining bytes that do not fit into a `bytes32` chunk
for (uint256 i = chunkCount * 32; i < length; i++) {
if (data[i] != 0) {
return;
}
}
revert ZeroAddressNotAllowed();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
until we configure the correct one
We are disallowing on ramp updates though (since we assume onramp change = offramp upgrade), so a misconfig would force us into a re-deployment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mean code change, I mean just like we accidentally configure say 0xa as the onramp when the real one is 0x123. Messages just will fail to execute, then we adjust offramp to point to 0x123 and they will succeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then we adjust offramp to point to 0x123 and they will succeed
Yeah so this is not possible because of this check:
if (currentOnRamp.length == 0) {
// new chain selector
} else if (
keccak256(currentOnRamp) != keccak256(newOnRamp)
) {
revert InvalidStaticConfig(sourceChainSelector);
}
The offramp adjustment would be a complete redeployment of the offramp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah and that check is there because we want to prevent minSeqNr overwrites?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah if we allowed overwriting the OnRamp, it would have some implications:
chain => seqNumbers => executionStates
would still be kept even though the OnRamp has changed (maybe not an issue since it's off-ramp specific)- The same message could accidentally be included in the OffRamp and be replayed (since the
_hash
changes due to the different OnRamp, i.e. metadataHash) - Committed roots are not cleared, so we would have different commit roots with different metadata hashes
I was always going under the assumption that the metadataHash must remain immutable for each OffRamp, to preserve the OnRamp <-> OffRamp dependency
LCOV of commit
|
26a19fb
to
7e3a8a0
Compare
0566ee7
to
ffefa01
Compare
02fd574
to
766a569
Compare
## Motivation Recent PR #1117 implemented Any2EVM message hashing, so we need to update the MessageHasher for EVM to match the new onchain implementation. ## Solution Update the message hasher to match the `_hash(Any2EVMRampMessage)` implementation in Internal.sol.
currentConfig.onRamp = sourceConfigUpdate.onRamp; | ||
currentConfig.minSeqNr = 1; | ||
if (currentOnRamp.length == 0) { | ||
if (newOnRamp.length == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think will be more efficient to check the newOnRamp first. Most probably the currentOnRamp will already have an address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Length checks are cheap so it wouldn't be substantial, but in this case this order makes sense because the onRamp
can only be set if it was never set before (we treat it as immutable). newOnRamp.length == 0
checks are not required if the currentOnRamp is checked because we're checking equality directly
84494ec
to
1cfc21e
Compare
Motivation
The Multi-OffRamp can be converted to be family agnostic by using more generic
Any2EVM
structures and breaking the reliance on abi hashingSolution
metadataHash
and use an implicit metadata hash composed of(prefix, srcChainSelector, destChainSelector, onRampAddress)
EVM2EVMMessage
toAny2EVMRampMessage
, which uses a genericbytes sender
messageId
fromhash(message)
Sample on why hashes between Any2X and X2Any are no longer equivalent: