Skip to content

WEB3-458: Update the Steel beacon block commit validation to always revert on invalid timestamps #605

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

Merged
merged 10 commits into from
Jun 2, 2025

Conversation

nategraf
Copy link
Contributor

On main, the Beacon.parentBlockRoot(uint256 timestamp) function returns zero bytes if the timestamp given is invalid. This allows the Steel.validateCommitment to return true if given a commitment suchas Commitment { id: Encoding.encodeVersionID(block.timestamp - 1, 1), bytes32(0), configID } where the digest is zero and the timestamp is within the last ~24 hours but does not correspond to a valid block.

This violates the semantics of validateCommitment in that this does not commitment to a block that is in the current chain. Because the digest is zero, it does not correspond to any block and there exist no known openings. As a result, this commitment will never be produced by a correct zkVM guest using Steel. As a result, leveraging this bug to compromise the soundness of a program using Steel would require a separate bug or misuse of the Steel API.

As a fix for this issue, this PR checks whether the EIP-4788 contract call reverts, and reverts with InvalidBlockTimestamp if so. We choose this error message as this is the only case in which the EIP-4788 contract will revert when called from the Beacon contract. With this, this PR removes the explicit check that the timestamp is recent, as it is redundant.

As a drive-by change, this PR also drops the explicit check for the block number being too old when using execution block commitments. Instead, this checks the return value of the blockhash opcode, which will return zeroes if the block number is too old. This should not result in any change of behavior on Ethereum.

@nategraf nategraf requested a review from a team as a code owner May 30, 2025 00:16
@github-actions github-actions bot changed the title Update the Steel beacon block commit validation to always revert on invalid timestamps WEB3-458: Update the Steel beacon block commit validation to always revert on invalid timestamps May 30, 2025
nategraf and others added 2 commits May 30, 2025 10:56
@nategraf nategraf requested a review from Wollac May 30, 2025 17:57
Copy link
Contributor

@Wollac Wollac left a comment

Choose a reason for hiding this comment

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

Very nice improvement.

@nategraf nategraf enabled auto-merge (squash) June 2, 2025 22:00
@nategraf nategraf merged commit 3bbac85 into main Jun 2, 2025
10 of 11 checks passed
@nategraf nategraf deleted the victorgraf/may28-ccfbde9d branch June 2, 2025 22:05
nategraf added a commit that referenced this pull request Jun 4, 2025
…evert on invalid timestamps (#605)

On `main`, the `Beacon.parentBlockRoot(uint256 timestamp)` function
returns zero bytes if the timestamp given is invalid. This allows the
`Steel.validateCommitment` to return true if given a commitment suchas
`Commitment { id: Encoding.encodeVersionID(block.timestamp - 1, 1),
bytes32(0), configID }` where the digest is zero and the timestamp is
within the last ~24 hours but does not correspond to a valid block.

This violates the semantics of `validateCommitment` in that this does
not commitment to a block that is in the current chain. Because the
digest is zero, it does not correspond to any block and there exist no
known openings. As a result, this commitment will never be produced by a
correct zkVM guest using Steel. As a result, leveraging this bug to
compromise the soundness of a program using Steel would require a
separate bug or misuse of the Steel API.

As a fix for this issue, this PR checks whether the EIP-4788 contract
call reverts, and reverts with `InvalidBlockTimestamp` if so. We choose
this error message as this is the only case in which the EIP-4788
contract will revert when called from the `Beacon` contract. With this,
this PR removes the explicit check that the timestamp is recent, as it
is redundant.

As a drive-by change, this PR also drops the explicit check for the
block number being too old when using execution block commitments.
Instead, this checks the return value of the `blockhash` opcode, which
will return zeroes if the block number is too old. This should not
result in any change of behavior on Ethereum.

---------

Co-authored-by: Angelo Capossele <[email protected]>
Co-authored-by: Wolfgang Welz <[email protected]>
nategraf added a commit that referenced this pull request Jun 7, 2025
…evert on invalid timestamps (#605)

On `main`, the `Beacon.parentBlockRoot(uint256 timestamp)` function
returns zero bytes if the timestamp given is invalid. This allows the
`Steel.validateCommitment` to return true if given a commitment suchas
`Commitment { id: Encoding.encodeVersionID(block.timestamp - 1, 1),
bytes32(0), configID }` where the digest is zero and the timestamp is
within the last ~24 hours but does not correspond to a valid block.

This violates the semantics of `validateCommitment` in that this does
not commitment to a block that is in the current chain. Because the
digest is zero, it does not correspond to any block and there exist no
known openings. As a result, this commitment will never be produced by a
correct zkVM guest using Steel. As a result, leveraging this bug to
compromise the soundness of a program using Steel would require a
separate bug or misuse of the Steel API.

As a fix for this issue, this PR checks whether the EIP-4788 contract
call reverts, and reverts with `InvalidBlockTimestamp` if so. We choose
this error message as this is the only case in which the EIP-4788
contract will revert when called from the `Beacon` contract. With this,
this PR removes the explicit check that the timestamp is recent, as it
is redundant.

As a drive-by change, this PR also drops the explicit check for the
block number being too old when using execution block commitments.
Instead, this checks the return value of the `blockhash` opcode, which
will return zeroes if the block number is too old. This should not
result in any change of behavior on Ethereum.

---------

Co-authored-by: Angelo Capossele <[email protected]>
Co-authored-by: Wolfgang Welz <[email protected]>
nategraf added a commit that referenced this pull request Jun 7, 2025
…evert on invalid timestamps (#605)

On `main`, the `Beacon.parentBlockRoot(uint256 timestamp)` function
returns zero bytes if the timestamp given is invalid. This allows the
`Steel.validateCommitment` to return true if given a commitment suchas
`Commitment { id: Encoding.encodeVersionID(block.timestamp - 1, 1),
bytes32(0), configID }` where the digest is zero and the timestamp is
within the last ~24 hours but does not correspond to a valid block.

This violates the semantics of `validateCommitment` in that this does
not commitment to a block that is in the current chain. Because the
digest is zero, it does not correspond to any block and there exist no
known openings. As a result, this commitment will never be produced by a
correct zkVM guest using Steel. As a result, leveraging this bug to
compromise the soundness of a program using Steel would require a
separate bug or misuse of the Steel API.

As a fix for this issue, this PR checks whether the EIP-4788 contract
call reverts, and reverts with `InvalidBlockTimestamp` if so. We choose
this error message as this is the only case in which the EIP-4788
contract will revert when called from the `Beacon` contract. With this,
this PR removes the explicit check that the timestamp is recent, as it
is redundant.

As a drive-by change, this PR also drops the explicit check for the
block number being too old when using execution block commitments.
Instead, this checks the return value of the `blockhash` opcode, which
will return zeroes if the block number is too old. This should not
result in any change of behavior on Ethereum.

---------

Co-authored-by: Angelo Capossele <[email protected]>
Co-authored-by: Wolfgang Welz <[email protected]>
nategraf added a commit that referenced this pull request Jun 7, 2025
…evert on invalid timestamps (#605)

On `main`, the `Beacon.parentBlockRoot(uint256 timestamp)` function
returns zero bytes if the timestamp given is invalid. This allows the
`Steel.validateCommitment` to return true if given a commitment suchas
`Commitment { id: Encoding.encodeVersionID(block.timestamp - 1, 1),
bytes32(0), configID }` where the digest is zero and the timestamp is
within the last ~24 hours but does not correspond to a valid block.

This violates the semantics of `validateCommitment` in that this does
not commitment to a block that is in the current chain. Because the
digest is zero, it does not correspond to any block and there exist no
known openings. As a result, this commitment will never be produced by a
correct zkVM guest using Steel. As a result, leveraging this bug to
compromise the soundness of a program using Steel would require a
separate bug or misuse of the Steel API.

As a fix for this issue, this PR checks whether the EIP-4788 contract
call reverts, and reverts with `InvalidBlockTimestamp` if so. We choose
this error message as this is the only case in which the EIP-4788
contract will revert when called from the `Beacon` contract. With this,
this PR removes the explicit check that the timestamp is recent, as it
is redundant.

As a drive-by change, this PR also drops the explicit check for the
block number being too old when using execution block commitments.
Instead, this checks the return value of the `blockhash` opcode, which
will return zeroes if the block number is too old. This should not
result in any change of behavior on Ethereum.

---------

Co-authored-by: Angelo Capossele <[email protected]>
Co-authored-by: Wolfgang Welz <[email protected]>
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.

3 participants