Skip to content

7702 refactor, remove CodeDelegationAccount abstraction#8408

Merged
daniellehrner merged 22 commits intohyperledger:mainfrom
daniellehrner:feat/issue-8392/remove_code_delegation_abstraction
Apr 1, 2025
Merged

7702 refactor, remove CodeDelegationAccount abstraction#8408
daniellehrner merged 22 commits intohyperledger:mainfrom
daniellehrner:feat/issue-8392/remove_code_delegation_abstraction

Conversation

@daniellehrner
Copy link
Contributor

PR description

Removes the CodeDelegationAbstraction to avoid calling Account.getCode() every time that we retrieve an account.

Fixed Issue(s)

fixes #8392

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:

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

@daniellehrner daniellehrner requested a review from Copilot March 12, 2025 10:12
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors code delegation handling by removing the CodeDelegationAccount abstraction and centralizing delegation logic into helper classes and services. Key changes include:

  • Removal of CodeDelegationAccount, MutableCodeDelegationDelegationAccount, and related files.
  • Introduction of CodeDelegationHelper and a simplified CodeDelegationService.
  • Updates to tests, protocol spec configurations, and transaction processing logic to use the new delegation approach.

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
evm/src/main/java/org/hyperledger/besu/evm/operation/InsufficientGasException.java New exception class for signaling insufficient gas during delegation resolution.
evm/src/main/java/org/hyperledger/besu/evm/worldstate/CodeDelegationHelper.java Introduces helper methods for code delegation resolution.
ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java Refactored to use WorldUpdater and a newly instantiated CodeDelegationService.
evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java Updates to delegate code resolution, integrating the new helper methods and exception handling.
Other files Removal of legacy code delegation account abstractions and adjustments in tests and transaction processing.
Comments suppressed due to low confidence (1)

evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java:264

  • Consider replacing RuntimeException with a more specific exception type to clearly indicate the missing target account condition and improve downstream error handling.
throw new RuntimeException("A delegated code account must have a target account");

@daniellehrner daniellehrner force-pushed the feat/issue-8392/remove_code_delegation_abstraction branch 2 times, most recently from f8b0f59 to b7304b2 Compare March 14, 2025 12:40
@daniellehrner daniellehrner marked this pull request as ready for review March 19, 2025 13:19
Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
@daniellehrner daniellehrner force-pushed the feat/issue-8392/remove_code_delegation_abstraction branch from 2888729 to 1897206 Compare March 19, 2025 13:20
@daniellehrner daniellehrner requested review from Copilot and removed request for Copilot March 19, 2025 13:24
Comment on lines 266 to 268
if (maybeTargetAccount.isEmpty()) {
throw new RuntimeException("A delegated code account must have a target account");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm struggling to reconcile this error case with with the EIP spec or EELS - can you point out the relevant part of the spec please?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also think we are doing it twice: here and in CodeDelegationGasCostHelper.codeDelegationGasCost

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is not part of the spec, just defensive programming. So whenever we get an optional we should check if it's empty before calling get()

Copy link
Contributor

@siladu siladu Mar 22, 2025

Choose a reason for hiding this comment

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

Is this a condition where we could diverge from other client behaviour and it could lead to consensus issues? If there are error conditions missing should we update the spec?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think so . Theoretically between line 259 where we call hasCodeDelegation() and between 266 where we call maybeTargetAccount.isEmpty() a bit could flip in memory and we are unable to recover the target account. I've just added it because AFAIK it best practive to always call isPresent() / !isEMpty() before getting an optional, but I can remove it if you think it's confusing.

Copy link
Contributor

@siladu siladu Mar 25, 2025

Choose a reason for hiding this comment

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

I don't think we should code around hardware bugs. But I think the error conditions should match across client implementations, and ideally be part of the spec.
If this can truly never happen then maybe it shouldn't be Optional?

Copy link
Contributor Author

@daniellehrner daniellehrner Mar 25, 2025

Choose a reason for hiding this comment

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

I've only just now realized that maybeTargetAccount isn't needed any further down the code and have completely removed it. It seems it was a leftover from a refactoring.

In any case I've removed the Optional from getTargetAccount to make it clear that it should only be used with accounts that have code delegation.

…the constructor

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
…t of gas during code delegation resolution

Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net>
Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Copy link
Contributor

@matkt matkt left a comment

Choose a reason for hiding this comment

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

Added comment but I will take more time tomorrow to check the code

…rdered balance check for code delegation resolution, reordered recId check

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
…too deep to be spec compliant

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
@macfarla
Copy link
Contributor

macfarla commented Mar 28, 2025

running hive tests on this PR - docker image 25.3-develop-07da3dc
7702 all passing

locally ran some other randomly chosen EIPs, no failures

EIP7702
./hive --sim "ethereum/eest/consume-engine" --client "besu" --client-file="clients_pectra.yaml" --sim.buildarg "fixtures=https://github.com/ethereum/execution-spec-tests/releases/download/v4.1.0/fixtures_develop.tar.gz" --client.checktimelimit=60s --sim.parallelism=4 -sim.limit ".*tests/prague/eip7702.*"
...
Mar 28 13:41:31.457 INF simulation ethereum/eest/consume-engine finished suites=1 tests=476 failed=0
EIP6110
Mar 28 13:50:38.078 INF simulation ethereum/eest/consume-engine finished suites=1 tests=38 failed=0
EIP2935
Mar 28 15:54:20.039 INF simulation ethereum/eest/consume-engine finished suites=1 tests=19 failed=0 
EIP7516
➜  hive git:(master) ✗ ./hive --sim "ethereum/eest/consume-engine" --client "besu" --client-file="clients_pectra.yaml" --sim.buildarg "fixtures=https://github.com/ethereum/execution-spec-tests/releases/download/v4.1.0/fixtures_develop.tar.gz" --client.checktimelimit=60s --sim.parallelism=4 -sim.limit ".*tests/prague/eip7516.*"

@macfarla
Copy link
Contributor

full run all passed

Mar 28 16:59:51.881 INF simulation ethereum/eest/consume-engine finished suites=1 tests=1742 failed=0
./hive --sim "ethereum/eest/consume-engine" --client "besu"  --sim.buildarg    7.53s user 20.81s system 1% cpu 34:33.76 total

…s with empty code hashes, remove unused methods from AccountState, reorder processCodeFromAccount to make it easier to read

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
@daniellehrner daniellehrner marked this pull request as draft March 28, 2025 20:28
@daniellehrner
Copy link
Contributor Author

daniellehrner commented Mar 30, 2025

I ran the Hive tests again after the latest changes, all are still passing:

./hive --sim "ethereum/eest/consume-engine" --client "besu" --client-file="./besu_local.yaml" --sim.buildarg fixtures=https://github.com/ethereum/execution-spec-tests/releases/download/v4.1.0/fixtures_develop.tar.gz --client.checktimelimit=120s --sim.parallelism=4 --sim.limit ".*fork_Prague.*"
Screenshot 2025-03-29 at 13 20 28

@daniellehrner daniellehrner marked this pull request as ready for review March 30, 2025 08:25
Copy link
Contributor

@ahamlat ahamlat left a comment

Choose a reason for hiding this comment

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

From a performance perspective, it looks good to me.
@matkt Could you take a last look

.thenReturn(ValidationResult.valid());
when(worldState.getOrCreateSenderAccount(senderAddress)).thenReturn(senderAccount);
when(worldState.get(toAddress.get())).thenReturn(receiverAccount);
when(receiverAccount.getCodeHash()).thenReturn(Hash.fromHexStringLenient("0x1"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this needed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The test assumes that messageCallProcessor.getCodeFromEVM() is called and prepares the mock for it in line 186. Therefor we need to return an non-empty code hash when receiverAccount.getCodeHash() is called.

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Copy link
Contributor

@matkt matkt left a comment

Choose a reason for hiding this comment

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

LGTM on my side

@daniellehrner daniellehrner merged commit 5bb4e9e into hyperledger:main Apr 1, 2025
43 checks passed
@daniellehrner daniellehrner deleted the feat/issue-8392/remove_code_delegation_abstraction branch April 1, 2025 15:12
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.

Remove getCode() from CodeDelegationService.processAccount

6 participants