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

eip-7709 implement BLOCKHASH opcode from system contract state #7971

Conversation

lu-pinto
Copy link
Contributor

@lu-pinto lu-pinto commented Dec 2, 2024

PR description

Refactor BlockHashLookup to store it in BlockHashProcessor so one can have different implementations for it. These changes are supposedly side-effect free so no changes to integration test assertions are required.
Also BlockHashLookup now takes the Frame so that it can lookup the hash in the system contract storage.
Implementation for EIP-7709 BlockHashLookup is provided but still with no updated costs.

Gas costs update and wiring will be done in the verkle branch.

Fixed Issue(s)

fixes #7811

Thanks for sending a pull request! Have you done the following?

  • Checked out our contribution guidelines?
  • Considered documentation and added the doc-change-required label to this PR if updates are required.
  • Considered the changelog and included an update if required.
  • For database changes (e.g. KeyValueSegmentIdentifier) considered compatibility and performed forwards and backwards compatibility tests

Locally, you can run these tests to catch failures early:

  • unit tests: ./gradlew build
  • acceptance tests: ./gradlew acceptanceTest
  • integration tests: ./gradlew integrationTest
  • reference tests: ./gradlew ethereum:referenceTests:referenceTests

@lu-pinto lu-pinto marked this pull request as ready for review December 2, 2024 23:11
@lu-pinto lu-pinto force-pushed the eip-7709-implement-blockhash-system-contract branch from 6bb3371 to 04678ff Compare December 4, 2024 11:10
@lu-pinto lu-pinto mentioned this pull request Dec 4, 2024
8 tasks
lu-pinto added a commit to lu-pinto/besu that referenced this pull request Dec 10, 2024
…rom system contract state

Signed-off-by: Luis Pinto <[email protected]>
@lu-pinto lu-pinto force-pushed the eip-7709-implement-blockhash-system-contract branch from 04678ff to e310147 Compare December 10, 2024 14:02
final long currentBlockNumber = blockHeader.getNumber();
final long minBlockServe = Math.max(0, currentBlockNumber - blockHashServeWindow);
if (blockNumber >= currentBlockNumber || blockNumber < minBlockServe) {
LOG.debug("failed to read hash from system account for block {}", blockNumber);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe trace instead of debug?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure i can change. What is debug used for then? When this happens there's a problem with the smart contract's code but no consensus issue occurs since all clients should behave like this from spec

final WorldUpdater worldUpdater = frame.getWorldUpdater();
Account account = worldUpdater.get(contractAddress);
if (account == null) {
LOG.error("cannot query system contract {}", contractAddress);
Copy link
Contributor

Choose a reason for hiding this comment

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

This a valid scenario, correct? In case a network does not have this contract, should we log a warn/trace instead here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would be a problem that we are not storing hashes in the system contract storage or we are storing in wrong account. I feel it should be an error as it will cause a consensus issue

Copy link
Contributor

Choose a reason for hiding this comment

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

Per EIP-7709 The BLOCKHASH opcode semantics remains the same as before.
Then it lists three options:

ONLY if the arg is within the correct BLOCKHASH window, clients can choose to either

- do a direct SLOAD from state, or
- do a system call to [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) contract via its get mechanism (caller other than SYSTEM_ADDRESS) or
- serve from memory or as per current designs if maintaining requisite history (full clients for e.g.)

None of those depend on if the system contract is deployed, and if there is no deployed system contract we can get get different results if different paths are chosen. Rather than warn/trace I think Fatal should be considered instead as this is attempting to resolve a non-determinstic blockchain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In normal cases it should not occur as the PragueBlockHashProcessor that stores hashes in system contract storage should ship with Pectra and populate the contract storage within a day or so, but I would code defensively against it.

  • serve from memory or as per current designs if maintaining requisite history (full clients for e.g.)

There is always this option though. If I get that sentence right, it mentions that we could fallback to the previous approach of finding hashes from blockchain building. That was something I thought about actually but wasn't sure whether add the previous approach as fallback. But I agree with @shemnon, that this is not totally clear. By fatal, did you mean halting execution if this happens? I would agree with that

Copy link
Contributor

Choose a reason for hiding this comment

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

Not halting execution, but a level of warning that is not usually muted. Fatal indicates that recovery should not be expected, whereas "error" typically means an error has occured, but a reliable recovery has been done. Fatal also indicates that intervention is generally required.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Decided privately to leave it as is, since there's no higher logging than error and EIP-7709 does not provide clarity on what to do in case the contract or its storage does not exist. Hopefully there will be more clarity when EIP is closer to production.

Copy link
Contributor

@shemnon shemnon left a comment

Choose a reason for hiding this comment

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

Just a sanity check, this isn't wired into any existing forks yet, right? Is it still just a Verkle thing? Would it be better to work it out in the Verkle branch?

* Retrieves block hashes from system contract storage and caches hashes by number, used by
* BLOCKHASH operation.
*/
public class ContractBasedBlockHashLookup implements BlockHashLookup {
Copy link
Contributor

Choose a reason for hiding this comment

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

The specific semantics may change in the future, and are tightly aligned with the needs of EIP7709BlockHashProcessor. Consider EIP7709BlockHashLookup as a name instead.

final WorldUpdater worldUpdater = frame.getWorldUpdater();
Account account = worldUpdater.get(contractAddress);
if (account == null) {
LOG.error("cannot query system contract {}", contractAddress);
Copy link
Contributor

Choose a reason for hiding this comment

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

Per EIP-7709 The BLOCKHASH opcode semantics remains the same as before.
Then it lists three options:

ONLY if the arg is within the correct BLOCKHASH window, clients can choose to either

- do a direct SLOAD from state, or
- do a system call to [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) contract via its get mechanism (caller other than SYSTEM_ADDRESS) or
- serve from memory or as per current designs if maintaining requisite history (full clients for e.g.)

None of those depend on if the system contract is deployed, and if there is no deployed system contract we can get get different results if different paths are chosen. Rather than warn/trace I think Fatal should be considered instead as this is attempting to resolve a non-determinstic blockchain.

*/
@VisibleForTesting
ContractBasedBlockHashLookup(
final ProcessableBlockHeader currentBlock,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why pass the processable block header into the constructor? We have the MessageFrame and can get the current block number from that value.

Then we can re-use this object across multiple blocks, and even use it concurrently across multiple blocks.

@lu-pinto
Copy link
Contributor Author

Just a sanity check, this isn't wired into any existing forks yet, right? Is it still just a Verkle thing? Would it be better to work it out in the Verkle branch?

That's right, EIP is still in draft and is a hard dependency for Verkle. Don't think there's any case to have it sooner. We have a Verkle branch but have decided to start bringing stable parts of Verkle into main because of the high amount of conflicts while merging and time it takes to review these merges. But I'll defer to @matkt on that.

@matkt
Copy link
Contributor

matkt commented Dec 17, 2024

Just a sanity check, this isn't wired into any existing forks yet, right? Is it still just a Verkle thing? Would it be better to work it out in the Verkle branch?

That's right, EIP is still in draft and is a hard dependency for Verkle. Don't think there's any case to have it sooner. We have a Verkle branch but have decided to start bringing stable parts of Verkle into main because of the high amount of conflicts while merging and time it takes to review these merges. But I'll defer to @matkt on that.

We're trying to merge things step by step into the main branch to reduce the size of the Verkle branch and also minimize futur conflicts, etc. The goal is to avoid having a branch that keeps growing if certain things can be merged without impacting Besu's codebase. Maybe we can add a comment to indicate that it's part of the Verkle work to prevent a future PR from trying to remove it as not used.

@lu-pinto lu-pinto force-pushed the eip-7709-implement-blockhash-system-contract branch from e310147 to 71e2965 Compare December 17, 2024 16:44
@lu-pinto lu-pinto force-pushed the eip-7709-implement-blockhash-system-contract branch from 515bc57 to a4c1b7f Compare December 17, 2024 17:13
Copy link
Contributor

@Gabriel-Trintinalia Gabriel-Trintinalia left a comment

Choose a reason for hiding this comment

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

lgtm

 reimplement blockhashlookup with MessageFrame instead of WorldUpdater

Signed-off-by: Luis Pinto <[email protected]>
 add comment about unused BlockHashProcessor

Signed-off-by: Luis Pinto <[email protected]>
@lu-pinto lu-pinto force-pushed the eip-7709-implement-blockhash-system-contract branch from a4c1b7f to 069096f Compare December 20, 2024 10:02
@lu-pinto lu-pinto enabled auto-merge (squash) December 20, 2024 10:03
@lu-pinto lu-pinto merged commit b3b33da into hyperledger:main Dec 20, 2024
43 checks passed
garyschulte pushed a commit that referenced this pull request Dec 20, 2024
* eip-7709 implement BLOCKHASH opcode from system contract state

Signed-off-by: Luis Pinto <[email protected]>

* fixup! eip-7709 implement BLOCKHASH opcode from system contract state

 reimplement blockhashlookup with MessageFrame instead of WorldUpdater

Signed-off-by: Luis Pinto <[email protected]>

* fixup! eip-7709 implement BLOCKHASH opcode from system contract state

 address review comments

Signed-off-by: Luis Pinto <[email protected]>

* fixup! eip-7709 implement BLOCKHASH opcode from system contract state

 add comment about unused BlockHashProcessor

Signed-off-by: Luis Pinto <[email protected]>

---------

Signed-off-by: Luis Pinto <[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.

Implement EIP-7709
4 participants