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

Rename sequence number #1290

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
264 changes: 132 additions & 132 deletions contracts/gas-snapshots/ccip.gas-snapshot

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ pragma solidity ^0.8.0;
import {IEVM2AnyOnRampClient} from "./IEVM2AnyOnRampClient.sol";

interface IEVM2AnyOnRamp is IEVM2AnyOnRampClient {
/// @notice Gets the next sequence number to be used in the onRamp
/// @return the next sequence number to be used
function getExpectedNextSequenceNumber() external view returns (uint64);
/// @notice Gets the next message number to be used in the onRamp
/// @return the next message number to be used
function getExpectedNextMessageNumber() external view returns (uint64);

/// @notice Get the next nonce for a given sender
/// @param sender The sender to get the nonce for
Expand Down
10 changes: 5 additions & 5 deletions contracts/src/v0.8/ccip/libraries/Internal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ library Internal {
uint64 sourceChainSelector; // ────────╮ the chain selector of the source chain, note: not chainId
address sender; // ────────────────────╯ sender address on the source chain
address receiver; // ──────────────────╮ receiver address on the destination chain
uint64 sequenceNumber; // ─────────────╯ sequence number, not unique across lanes
uint64 messageNumber; // ──────────────╯ message number, not unique across lanes
uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution
bool strict; // ───────────────────────╮ DEPRECATED
uint64 nonce; // │ nonce for this lane for this sender, not unique across senders/lanes
Expand Down Expand Up @@ -164,7 +164,7 @@ library Internal {
abi.encode(
original.sender,
original.receiver,
original.sequenceNumber,
original.messageNumber,
original.gasLimit,
original.strict,
original.nonce,
Expand Down Expand Up @@ -205,7 +205,7 @@ library Internal {
original.header.messageId,
original.sender,
original.receiver,
original.header.sequenceNumber,
original.header.messageNumber,
original.gasLimit,
original.header.nonce
)
Expand All @@ -227,7 +227,7 @@ library Internal {
abi.encode(
original.sender,
original.receiver,
original.header.sequenceNumber,
original.header.messageNumber,
original.header.nonce,
original.feeToken,
original.feeTokenAmount
Expand Down Expand Up @@ -302,7 +302,7 @@ library Internal {
bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded)
uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId
uint64 destChainSelector; // | the chain selector of the destination chain, note: not chainId
uint64 sequenceNumber; // │ sequence number, not unique across lanes
uint64 messageNumber; // │ messages number, not unique across lanes
uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes
}

Expand Down
88 changes: 43 additions & 45 deletions contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
error ZeroChainSelectorNotAllowed();
error ExecutionError(bytes32 messageId, bytes err);
error SourceChainNotEnabled(uint64 sourceChainSelector);
error TokenDataMismatch(uint64 sourceChainSelector, uint64 sequenceNumber);
error TokenDataMismatch(uint64 sourceChainSelector, uint64 messageNumber);
error UnexpectedTokenData();
error ManualExecutionNotYetEnabled(uint64 sourceChainSelector);
error ManualExecutionGasLimitMismatch();
Expand All @@ -52,7 +52,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
error CursedByRMN(uint64 sourceChainSelector);
error NotACompatiblePool(address notPool);
error InvalidDataLength(uint256 expected, uint256 got);
error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState);
error InvalidNewState(uint64 sourceChainSelector, uint64 messageNumber, Internal.MessageExecutionState newState);
error InvalidStaticConfig(uint64 sourceChainSelector);
error StaleCommitReport();
error InvalidInterval(uint64 sourceChainSelector, Interval interval);
Expand All @@ -65,15 +65,15 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
/// @dev RMN depends on this event, if changing, please notify the RMN maintainers.
event ExecutionStateChanged(
uint64 indexed sourceChainSelector,
uint64 indexed sequenceNumber,
uint64 indexed messageNumber,
bytes32 indexed messageId,
Internal.MessageExecutionState state,
bytes returnData
);
event SourceChainSelectorAdded(uint64 sourceChainSelector);
event SourceChainConfigSet(uint64 indexed sourceChainSelector, SourceChainConfig sourceConfig);
event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber);
event AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber);
event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 messageNumber);
event AlreadyAttempted(uint64 sourceChainSelector, uint64 messageNumber);
/// @dev RMN depends on this event, if changing, please notify the RMN maintainers.
event CommitReportAccepted(CommitReport report);
event RootRemoved(bytes32 root);
Expand All @@ -91,7 +91,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
struct SourceChainConfig {
IRouter router; // ──────────╮ Local router to use for messages coming from this source chain
bool isEnabled; // | Flag whether the source chain is enabled or not
uint64 minSeqNr; // ─────────╯ The min sequence number expected for future messages
uint64 minMsgNr; // ─────────╯ The min message number expected for future messages
bytes onRamp; // OnRamp address on the source chain
}

Expand All @@ -113,11 +113,11 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator)
}

/// @notice a sequenceNumber interval
/// @notice a messageNumber interval
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct Interval {
uint64 min; // ───╮ Minimum sequence number, inclusive
uint64 max; // ───╯ Maximum sequence number, inclusive
uint64 min; // ───╮ Minimum message number, inclusive
uint64 max; // ───╯ Maximum message number, inclusive
}

/// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport.
Expand Down Expand Up @@ -159,10 +159,10 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs;

// STATE
/// @dev A mapping of sequence numbers (per source chain) to execution state using a bitmap with each execution
/// @dev A mapping of message numbers (per source chain) to execution state using a bitmap with each execution
/// state only taking up 2 bits of the uint256, packing 128 states into a single slot.
/// Message state is tracked to ensure message can only be executed successfully once.
mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => uint256 executionStateBitmap)) internal
mapping(uint64 sourceChainSelector => mapping(uint64 msgNum => uint256 executionStateBitmap)) internal
s_executionStates;

// sourceChainSelector => merkleRoot => timestamp when received
Expand Down Expand Up @@ -209,52 +209,52 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// │ Execution │
// ================================================================

/// @notice Returns the current execution state of a message based on its sequenceNumber.
/// @notice Returns the current execution state of a message based on its messageNumber.
/// @param sourceChainSelector The source chain to get the execution state for
/// @param sequenceNumber The sequence number of the message to get the execution state for.
/// @param messageNumber The message number of the message to get the execution state for.
/// @return The current execution state of the message.
/// @dev we use the literal number 128 because using a constant increased gas usage.
function getExecutionState(
uint64 sourceChainSelector,
uint64 sequenceNumber
uint64 messageNumber
) public view returns (Internal.MessageExecutionState) {
return Internal.MessageExecutionState(
(
_getSequenceNumberBitmap(sourceChainSelector, sequenceNumber)
>> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH)
_getMessageNumberBitmap(sourceChainSelector, messageNumber)
>> ((messageNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH)
) & MESSAGE_EXECUTION_STATE_MASK
);
}

/// @notice Sets a new execution state for a given sequence number. It will overwrite any existing state.
/// @notice Sets a new execution state for a given message number. It will overwrite any existing state.
/// @param sourceChainSelector The source chain to set the execution state for
/// @param sequenceNumber The sequence number for which the state will be saved.
/// @param messageNumber The message number for which the state will be saved.
/// @param newState The new value the state will be in after this function is called.
/// @dev we use the literal number 128 because using a constant increased gas usage.
function _setExecutionState(
uint64 sourceChainSelector,
uint64 sequenceNumber,
uint64 messageNumber,
Internal.MessageExecutionState newState
) internal {
uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH;
uint256 bitmap = _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber);
uint256 offset = (messageNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH;
uint256 bitmap = _getMessageNumberBitmap(sourceChainSelector, messageNumber);
// to unset any potential existing state we zero the bits of the section the state occupies,
// then we do an AND operation to blank out any existing state for the section.
bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset);
// Set the new state
bitmap |= uint256(newState) << offset;

s_executionStates[sourceChainSelector][sequenceNumber / 128] = bitmap;
s_executionStates[sourceChainSelector][messageNumber / 128] = bitmap;
}

/// @param sourceChainSelector remote source chain selector to get sequence number bitmap for
/// @param sequenceNumber sequence number to get bitmap for
/// @return bitmap Bitmap of the given sequence number for the provided source chain selector. One bitmap represents 128 sequence numbers
function _getSequenceNumberBitmap(
/// @param sourceChainSelector remote source chain selector to get message number bitmap for
/// @param messageNumber message number to get bitmap for
/// @return bitmap Bitmap of the given message number for the provided source chain selector. One bitmap represents 128 message numbers
function _getMessageNumberBitmap(
uint64 sourceChainSelector,
uint64 sequenceNumber
uint64 messageNumber
) internal view returns (uint256 bitmap) {
return s_executionStates[sourceChainSelector][sequenceNumber / 128];
return s_executionStates[sourceChainSelector][messageNumber / 128];
}

/// @notice Manually executes a set of reports.
Expand Down Expand Up @@ -375,7 +375,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
Internal.Any2EVMRampMessage memory message = report.messages[i];

Internal.MessageExecutionState originalState =
getExecutionState(sourceChainSelector, message.header.sequenceNumber);
getExecutionState(sourceChainSelector, message.header.messageNumber);
// Two valid cases here, we either have never touched this message before, or we tried to execute
// and failed. This check protects against reentry and re-execution because the other state is
// IN_PROGRESS which should not be allowed to execute.
Expand All @@ -388,7 +388,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// If the message has already been executed, we skip it. We want to not revert on race conditions between
// executing parties. This will allow us to open up manual exec while also attempting with the DON, without
// reverting an entire DON batch when a user manually executes while the tx is inflight.
emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber);
emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.messageNumber);
continue;
}

Expand All @@ -409,7 +409,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// DON can only execute a message once
// Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE
if (originalState != Internal.MessageExecutionState.UNTOUCHED) {
emit AlreadyAttempted(sourceChainSelector, message.header.sequenceNumber);
emit AlreadyAttempted(sourceChainSelector, message.header.messageNumber);
continue;
}
}
Expand All @@ -435,13 +435,13 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// when executing as a defense in depth measure.
bytes[] memory offchainTokenData = report.offchainTokenData[i];
if (message.tokenAmounts.length != offchainTokenData.length) {
revert TokenDataMismatch(sourceChainSelector, message.header.sequenceNumber);
revert TokenDataMismatch(sourceChainSelector, message.header.messageNumber);
}

_setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS);
_setExecutionState(sourceChainSelector, message.header.messageNumber, Internal.MessageExecutionState.IN_PROGRESS);

(Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData);
_setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState);
_setExecutionState(sourceChainSelector, message.header.messageNumber, newState);

// Since it's hard to estimate whether manual execution will succeed, we
// revert the entire transaction if it fails. This will show the user if
Expand All @@ -460,12 +460,12 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
// The only valid post states are FAILURE and SUCCESS (checked below)
if (newState != Internal.MessageExecutionState.SUCCESS) {
if (newState != Internal.MessageExecutionState.FAILURE) {
revert InvalidNewState(sourceChainSelector, message.header.sequenceNumber, newState);
revert InvalidNewState(sourceChainSelector, message.header.messageNumber, newState);
}
}

emit ExecutionStateChanged(
sourceChainSelector, message.header.sequenceNumber, message.header.messageId, newState, returnData
sourceChainSelector, message.header.messageNumber, message.header.messageId, newState, returnData
);
}
}
Expand Down Expand Up @@ -554,13 +554,13 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
/// @param report serialized commit report
/// @dev A commitReport can have two distinct parts (batched together to amortize the cost of checking sigs):
/// 1. Price updates
/// 2. A batch of merkle root and sequence number intervals (per-source)
/// Both have their own, separate, staleness checks, with price updates using the epoch and round
/// number of the latest price update. The merkle root checks for staleness based on the seqNums.
/// 2. A batch of merkle root and message number intervals (per-source)
/// Both have their own, separate, staleness checks, with price updates using the OCR sequence
/// number from the latest price update. The merkle root checks for staleness based on the message numbers.
/// They need to be separate because a price report for round t+2 might be included before a report
/// containing a merkle root for round t+1. This merkle root report for round t+1 is still valid
/// and should not be rejected. When a report with a stale root but valid price updates is submitted,
/// we are OK to revert to preserve the invariant that we always revert on invalid sequence number ranges.
/// we are OK to revert to preserve the invariant that we always revert on invalid message number ranges.
/// If that happens, prices will be updates in later rounds.
function commit(
bytes32[3] calldata reportContext,
Expand Down Expand Up @@ -598,7 +598,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector);

// If we reached this section, the report should contain a valid root
if (sourceChainConfig.minSeqNr != root.interval.min || root.interval.min > root.interval.max) {
if (sourceChainConfig.minMsgNr != root.interval.min || root.interval.min > root.interval.max) {
revert InvalidInterval(root.sourceChainSelector, root.interval);
}

Expand All @@ -611,7 +611,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
revert RootAlreadyCommitted(root.sourceChainSelector, merkleRoot);
}

sourceChainConfig.minSeqNr = root.interval.max + 1;
sourceChainConfig.minMsgNr = root.interval.max + 1;
s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp;
}

Expand Down Expand Up @@ -681,8 +681,6 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
if (ocrPluginType == uint8(Internal.OCRPluginType.Commit)) {
// When the OCR config changes, we reset the sequence number
// since it is scoped per config digest.
// Note that s_minSeqNr/roots do not need to be reset as the roots persist
// across reconfigurations and are de-duplicated separately.
s_latestPriceSequenceNumber = 0;
}
}
Expand Down Expand Up @@ -748,7 +746,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
}

currentConfig.onRamp = newOnRamp;
currentConfig.minSeqNr = 1;
currentConfig.minMsgNr = 1;
emit SourceChainSelectorAdded(sourceChainSelector);
} else if (keccak256(currentOnRamp) != keccak256(newOnRamp)) {
revert InvalidStaticConfig(sourceChainSelector);
Expand Down
Loading
Loading