-
Notifications
You must be signed in to change notification settings - Fork 860
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
eip-7709 implement BLOCKHASH opcode from system contract state #7971
Conversation
6bb3371
to
04678ff
Compare
…rom system contract state Signed-off-by: Luis Pinto <[email protected]>
04678ff
to
e310147
Compare
ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java
Show resolved
Hide resolved
ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java
Show resolved
Hide resolved
evm/src/main/java/org/hyperledger/besu/evm/blockhash/BlockHashLookup.java
Show resolved
Hide resolved
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); |
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.
Maybe trace instead of debug?
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.
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); |
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 a valid scenario, correct? In case a network does not have this contract, should we log a warn/trace instead here?
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 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
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.
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.
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.
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
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.
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.
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.
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.
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.
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 { |
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.
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); |
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.
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, |
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.
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.
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 |
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. |
e310147
to
71e2965
Compare
515bc57
to
a4c1b7f
Compare
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.
lgtm
Signed-off-by: Luis Pinto <[email protected]>
reimplement blockhashlookup with MessageFrame instead of WorldUpdater Signed-off-by: Luis Pinto <[email protected]>
address review comments Signed-off-by: Luis Pinto <[email protected]>
add comment about unused BlockHashProcessor Signed-off-by: Luis Pinto <[email protected]>
a4c1b7f
to
069096f
Compare
* 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]>
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?
doc-change-required
label to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew build
./gradlew acceptanceTest
./gradlew integrationTest
./gradlew ethereum:referenceTests:referenceTests