EIP-2935 Nyota updates (#7120)

Bring implementation up to nyota version of the EIP,
and remove invasive change into the EVM code.

Signed-off-by: Danno Ferrin <danno@numisight.com>

Co-authored-by: Lucas Saldanha <lucascrsaldanha@gmail.com>
Co-authored-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
Co-authored-by: Justin Florentine <justin+github@florentine.us>
Co-authored-by: Jason Frame <jason.frame@consensys.net>
Co-authored-by: Jason Frame <jasonwframe@gmail.com>
pull/7126/head 24.5.2
Danno Ferrin 6 months ago committed by GitHub
parent d7123ce5b4
commit 0cca642bc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 12
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json
  2. 8
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/08_prague_invalid_null_deposits_execute_payload.json
  3. 8
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json
  4. 12
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/10_prague_forkchoiceUpdatedV3.json
  5. 8
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/11_prague_getPayloadV4.json
  6. 8
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/12_cancun_newPayloadV4.json
  7. 12
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/14_prague_forkchoiceUpdatedV3.json
  8. 10
      acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json
  9. 3
      besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java
  10. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java
  11. 12
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java
  12. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java
  13. 6
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java
  14. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java
  15. 7
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java
  16. 2
      ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java
  17. 13
      ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java
  18. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java
  19. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java
  20. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java
  21. 14
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
  22. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java
  23. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java
  24. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java
  25. 72
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java
  26. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java
  27. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java
  28. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java
  29. 5
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java
  30. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java
  31. 1
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java
  32. 3
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java
  33. 65
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java
  34. 49
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java
  35. 6
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
  36. 23
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java
  37. 18
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java
  38. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java
  39. 5
      ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java
  40. 2
      evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java
  41. 5
      evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java
  42. 2
      evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java
  43. 3
      evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java
  44. 22
      evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java
  45. 49
      evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java
  46. 2
      evm/src/test/java/org/hyperledger/besu/evm/code/CodeV0Test.java
  47. 2
      evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java
  48. 2
      evm/src/test/java/org/hyperledger/besu/evm/frame/MessageFrameTest.java
  49. 2
      evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java
  50. 37
      evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java
  51. 4
      evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java
  52. 2
      evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java
  53. 2
      evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java
  54. 2
      evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java
  55. 4
      evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java
  56. 2
      evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java

@ -14,7 +14,7 @@
"executionPayload": {
"parentHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x3057566307e82861160cd217c71c18a93023a752d268113a4e50148fe6f19be6",
"stateRoot": "0x546ac65b9d37c72d7185f8dd67419803c636dd4e5ddf9b325fb64e9ecf570871",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@ -30,14 +30,14 @@
"withdrawalRequests": [
{
"sourceAddress": "0xa4664c40aacebd82a2db79f0ea36c06bc6a19adb",
"amount" : "0x0",
"validatorPublicKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"
"validatorPublicKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e",
"amount": "0x0"
}
],
"blockNumber": "0x2",
"blockHash": "0xdce2f62925b5ebb218943e71fa87af2aaeb6dab2d8aee12ea7f9f24eeae7b4c7",
"blobGasUsed": "0x0",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
"blockHash": "0xa7a92cc82e1d876476ad6433538599b0d592f88ba0823c23e80af93fb1748f14",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"blobGasUsed": "0x0"
},
"blockValue": "0x0",
"blobsBundle": {

@ -4,7 +4,7 @@
"method": "engine_newPayloadV4",
"params": [
{
"parentHash": "0x45811fa27a100ce9035e5e086b9669275041a4ec0ebbd920be028fd7b0aa2356",
"parentHash": "0xa7a92cc82e1d876476ad6433538599b0d592f88ba0823c23e80af93fb1748f14",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x9b8c4a9a86cb49252075c0db2f0e72fb1e49350a0f70ea36f26f700201961e62",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
@ -17,9 +17,9 @@
"excessBlobGas": "0x0",
"transactions": [],
"withdrawals": [],
"depositRequests" : null,
"depositRequests": null,
"blockNumber": "0x2",
"blockHash": "0xf6c3f1180ba58d6ea4c69c9328c7afb1fda41df06c368741c1f8310567879de7",
"blockHash": "0x2331b2dc9c453e9a33685099742cbbcd529d42bd5681969f45754f06866c6766",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"blobGasUsed": "0x0"
},
@ -34,7 +34,7 @@
"error": {
"code": -32602,
"message": "Invalid params",
"data" : "Missing deposit field"
"data": "Missing deposit field"
}
},
"statusCode": 200

@ -6,7 +6,7 @@
{
"parentHash": "0x74e8ce9d96d325a605675a34175adfa34581f35091dcd7b107c525a82b0b9950",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x778ccbc3adc59876b76489cdc1a2ff76ef2a31ae9d3bf761bc55bbab7d59c489",
"stateRoot": "0xdb2a9bb9097dd6946525203a14437cd925ef549289e1fe17c6ed845c53647a26",
"logsBloom": "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@ -31,12 +31,12 @@
"withdrawalRequests": [
{
"sourceAddress": "0xa4664c40aacebd82a2db79f0ea36c06bc6a19adb",
"amount" : "0x0",
"amount": "0x0",
"validatorPublicKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"
}
],
"blockNumber": "0x2",
"blockHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"blockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"receiptsRoot": "0x79ee3424eb720a3ad4b1c5a372bb8160580cbe4d893778660f34213c685627a9",
"blobGasUsed": "0x0"
},
@ -50,7 +50,7 @@
"id": 67,
"result": {
"status": "VALID",
"latestValidHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"latestValidHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"validationError": null
}
},

@ -4,9 +4,9 @@
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"safeBlockHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"finalizedBlockHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852"
"headBlockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"safeBlockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"finalizedBlockHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d"
},
{
"timestamp": "0x30",
@ -24,11 +24,11 @@
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"latestValidHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"validationError": null
},
"payloadId": "0x282643ead6ad5331"
"payloadId": "0x282643e2da21a7cf"
}
},
"statusCode" : 200
"statusCode": 200
}

@ -3,7 +3,7 @@
"jsonrpc": "2.0",
"method": "engine_getPayloadV4",
"params": [
"0x282643ead6ad5331"
"0x282643e2da21a7cf"
],
"id": 67
},
@ -12,9 +12,9 @@
"id": 67,
"result": {
"executionPayload": {
"parentHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"parentHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x61d2011dc13b003c48193f0902653fd4f7b67fa949dc0fa6eab9e69e349700fd",
"stateRoot": "0xcd9f15de5f17cf87a02bf795a0dc98c108eead4651eca57fc7195bda0d9c20ee",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@ -29,7 +29,7 @@
"depositRequests": [],
"withdrawalRequests": [],
"blockNumber": "0x3",
"blockHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"blockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"blobGasUsed": "0x0"
},

@ -4,9 +4,9 @@
"method": "engine_newPayloadV3",
"params": [
{
"parentHash": "0xb56ecf32963d4160799d4db6fe3723f01226635d058ab86a11eaa9f8234af852",
"parentHash": "0x5200df2eb24d08e7bceec64194d073e81a6e9c00c4f61d323fad5d70b40e6d6d",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x61d2011dc13b003c48193f0902653fd4f7b67fa949dc0fa6eab9e69e349700fd",
"stateRoot": "0xcd9f15de5f17cf87a02bf795a0dc98c108eead4651eca57fc7195bda0d9c20ee",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@ -19,7 +19,7 @@
"depositRequests": [],
"withdrawalRequests": [],
"blockNumber": "0x3",
"blockHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"blockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"excessBlobGas": "0x0",
"blobGasUsed": "0x0"
@ -34,7 +34,7 @@
"id": 67,
"result": {
"status": "VALID",
"latestValidHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"latestValidHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"validationError": null
}
},

@ -4,9 +4,9 @@
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"safeBlockHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"finalizedBlockHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9"
"headBlockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"safeBlockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"finalizedBlockHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42"
},
{
"timestamp": "0x40",
@ -24,11 +24,11 @@
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"latestValidHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"validationError": null
},
"payloadId": "0x2826438a3f8a7741"
"payloadId": "0x282643de0e3d43bf"
}
},
"statusCode" : 200
"statusCode": 200
}

@ -3,7 +3,7 @@
"jsonrpc": "2.0",
"method": "engine_getPayloadV4",
"params": [
"0x2826438a3f8a7741"
"0x282643de0e3d43bf"
],
"id": 67
},
@ -12,9 +12,9 @@
"id": 67,
"result": {
"executionPayload": {
"parentHash": "0x7a619ef406633a6d6589602009b5d242e1273fd8259cebcac4ab006edfdf81f9",
"parentHash": "0x79858f6eb8e82f0ec11087983ce4eb8c7edc10c9363a2a124dd78fd2c305dc42",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x847db08c6b9e6dcc91288bd963eb5623aea5387232016ef81fddb3ebc994c72f",
"stateRoot": "0xe4642cc58d61f2392fe056042c226e286f22a25e3104f4a4acb423dad9a43311",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@ -37,9 +37,9 @@
}
],
"blockNumber": "0x4",
"blobGasUsed": "0x0",
"receiptsRoot": "0x765bd9d63cc10fa47117d6cc0958f15e55a3bde540d4ed15d220f573fbb82cba",
"blockHash": "0xd0b81acdb3016abbc05599b083c8b090323efaf0b2aeab8d0755780e20214159"
"blobGasUsed": "0x0",
"blockHash": "0xb2d60adb2a0c73313ebdacf425b1d6bbd810c3ec6b28ad0d62a73cdc34cb696a"
},
"blockValue": "0x12855dcd153473b",
"blobsBundle": {

@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.data.BlockTraceResult;
@ -216,7 +217,7 @@ public class TraceServiceImpl implements TraceService {
transaction,
protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(header),
tracer,
protocolSpec.getBlockHashProcessor().getBlockHashLookup(header, blockchain),
new CachingBlockHashLookup(header, blockchain),
false,
blobGasPrice);

@ -15,7 +15,6 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
@ -27,7 +26,9 @@ import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import java.util.List;
import java.util.Optional;
@ -94,8 +95,7 @@ public class ExecuteTransactionStep implements Function<TransactionTrace, Transa
maybeParentHeader
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
final BlockHashLookup blockHashLookup =
protocolSpec.getBlockHashProcessor().getBlockHashLookup(header, blockchain);
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(header, blockchain);
result =
transactionProcessor.processTransaction(
chainUpdater.getNextUpdater(),

@ -15,7 +15,6 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
@ -31,6 +30,8 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import java.util.List;
import java.util.Optional;
@ -89,8 +90,7 @@ public class BlockReplay {
return performActionWithBlock(
blockHash,
(body, header, blockchain, transactionProcessor, protocolSpec) -> {
final BlockHashLookup blockHashLookup =
protocolSpec.getBlockHashProcessor().getBlockHashLookup(header, blockchain);
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(header, blockchain);
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
@ -137,7 +137,7 @@ public class BlockReplay {
blockHeader,
transaction,
spec.getMiningBeneficiaryCalculator().calculateBeneficiary(blockHeader),
spec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain),
new CachingBlockHashLookup(blockHeader, blockchain),
false,
TransactionValidationParams.blockReplay(),
blobGasPrice);
@ -180,10 +180,6 @@ public class BlockReplay {
return Optional.empty();
}
public ProtocolSpec getProtocolSpec(final BlockHeader header) {
return protocolSchedule.getByBlockHeader(header);
}
@FunctionalInterface
public interface BlockAction<T> {
Optional<T> perform(

@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@ -68,10 +69,7 @@ public class BlockTracer {
transaction,
header.getCoinbase(),
tracer,
blockReplay
.getProtocolSpec(header)
.getBlockHashProcessor()
.getBlockHashLookup(header, blockchain),
new CachingBlockHashLookup(header, blockchain),
false,
blobGasPrice);
final List<TraceFrame> traceFrames = tracer.copyTraceFrames();

@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.tracing.StandardJsonTracer;
@ -191,10 +192,7 @@ public class TransactionTracer {
transaction,
header.getCoinbase(),
tracer,
blockReplay
.getProtocolSpec(header)
.getBlockHashProcessor()
.getBlockHashLookup(header, blockchain),
new CachingBlockHashLookup(header, blockchain),
false,
ImmutableTransactionValidationParams.builder().isAllowFutureNonce(true).build(),
blobGasPrice);

@ -36,7 +36,6 @@ import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.blockhash.BlockHashProcessor;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
@ -88,7 +87,6 @@ public class TransactionTracerTest {
@Mock private ProtocolSpec protocolSpec;
@Mock private GasCalculator gasCalculator;
@Mock private BlockHashProcessor blockHashProcessor;
@Mock private Tracer.TraceableState mutableWorldState;
@ -125,7 +123,6 @@ public class TransactionTracerTest {
when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0L));
when(blockchain.getChainHeadHeader()).thenReturn(blockHeader);
when(protocolSpec.getGasCalculator()).thenReturn(gasCalculator);
when(protocolSpec.getBlockHashProcessor()).thenReturn(blockHashProcessor);
when(protocolContext.getBadBlockManager()).thenReturn(badBlockManager);
lenient().when(gasCalculator.computeExcessBlobGas(anyLong(), anyInt())).thenReturn(0L);
}

@ -14,7 +14,6 @@
*/
package org.hyperledger.besu.ethereum.blockcreation.txselection;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_SELECTION_TIMEOUT;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_EVALUATION_TOO_LONG;
@ -43,7 +42,9 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.blockhash.BlockHashProcessor;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
@ -326,9 +327,7 @@ public class BlockTransactionSelector {
private TransactionProcessingResult processTransaction(
final PendingTransaction pendingTransaction, final WorldUpdater worldStateUpdater) {
final BlockHashLookup blockHashLookup =
blockSelectionContext
.blockHashProcessor()
.getBlockHashLookup(blockSelectionContext.processableBlockHeader(), blockchain);
new CachingBlockHashLookup(blockSelectionContext.processableBlockHeader(), blockchain);
return transactionProcessor.processTransaction(
worldStateUpdater,
blockSelectionContext.processableBlockHeader(),

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.mainnet.precompiles.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
@ -47,6 +46,7 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.precompile.PrecompiledContract;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;

@ -33,7 +33,6 @@ import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
@ -74,13 +73,11 @@ public class TraceTransactionIntegrationTest {
blockchain = contextTestFixture.getBlockchain();
worldStateArchive = contextTestFixture.getStateArchive();
final ProtocolSchedule protocolSchedule = contextTestFixture.getProtocolSchedule();
ProtocolSpec protocolSpec =
protocolSchedule.getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader());
transactionProcessor = protocolSpec.getTransactionProcessor();
blockHashLookup =
protocolSpec
.getBlockHashProcessor()
.getBlockHashLookup(genesisBlock.getHeader(), blockchain);
transactionProcessor =
protocolSchedule
.getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader())
.getTransactionProcessor();
blockHashLookup = new CachingBlockHashLookup(genesisBlock.getHeader(), blockchain);
}
@Test

@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldState;
@ -114,8 +115,7 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
final WorldUpdater worldStateUpdater = worldState.updater();
final BlockHashLookup blockHashLookup =
protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain);
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(blockHeader, blockchain);
final Address miningBeneficiary =
miningBeneficiaryCalculator.calculateBeneficiary(blockHeader);

@ -183,7 +183,6 @@ public class ClassicProtocolSpecs {
messageCallProcessor,
true,
false,
false,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.frontier()))
@ -373,7 +372,6 @@ public class ClassicProtocolSpecs {
messageCallProcessor,
true,
true,
false,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.frontier()))

@ -143,7 +143,6 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
false,
false,
false,
stackSizeLimit,
FeeMarket.legacy(),
CoinbaseFeePriceCalculator.frontier()))
@ -298,7 +297,6 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
true,
false,
false,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.frontier()))
@ -492,7 +490,6 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
true,
false,
false,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
@ -630,7 +627,6 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
true,
true,
false,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
@ -707,7 +703,6 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
true,
true,
false,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
@ -786,7 +781,6 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
true,
true,
true,
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
@ -795,8 +789,7 @@ public abstract class MainnetProtocolSpecs {
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::prague)
.requestsValidator(pragueRequestsValidator(depositContractAddress))
.requestProcessorCoordinator(pragueRequestsProcessors(depositContractAddress))
.blockHashProcessor(
new PragueBlockHashProcessor(genesisConfigOptions.getPragueTime().orElse(0)))
.blockHashProcessor(new PragueBlockHashProcessor())
.name("Prague");
}

@ -27,7 +27,6 @@ import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator;
import org.hyperledger.besu.ethereum.mainnet.blockhash.PragueBlockHashProcessor;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
@ -53,7 +52,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -74,7 +72,6 @@ public class MainnetTransactionProcessor {
private final boolean clearEmptyAccounts;
protected final boolean warmCoinbase;
protected final boolean warmBlockhash;
protected final FeeMarket feeMarket;
private final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator;
@ -86,7 +83,6 @@ public class MainnetTransactionProcessor {
final AbstractMessageProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final boolean warmCoinbase,
final boolean warmBlockhash,
final int maxStackSize,
final FeeMarket feeMarket,
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
@ -96,7 +92,6 @@ public class MainnetTransactionProcessor {
this.messageCallProcessor = messageCallProcessor;
this.clearEmptyAccounts = clearEmptyAccounts;
this.warmCoinbase = warmCoinbase;
this.warmBlockhash = warmBlockhash;
this.maxStackSize = maxStackSize;
this.feeMarket = feeMarket;
this.coinbaseFeePriceCalculator = coinbaseFeePriceCalculator;
@ -327,15 +322,6 @@ public class MainnetTransactionProcessor {
if (warmCoinbase) {
addressList.add(miningBeneficiary);
}
if (warmBlockhash) {
addressList.add(PragueBlockHashProcessor.HISTORY_STORAGE_ADDRESS);
storageList.putAll(
PragueBlockHashProcessor.HISTORY_STORAGE_ADDRESS,
List.of(
UInt256.valueOf(
(blockHeader.getNumber() - 1)
% PragueBlockHashProcessor.HISTORY_SERVE_WINDOW)));
}
final long intrinsicGas =
gasCalculator.transactionIntrinsicGasCost(

@ -14,8 +14,6 @@
*/
package org.hyperledger.besu.ethereum.mainnet.blockhash;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
@ -26,6 +24,4 @@ public interface BlockHashProcessor {
Blockchain blockchain,
MutableWorldState worldState,
ProcessableBlockHeader currentBlockHeader);
BlockHashLookup getBlockHashLookup(ProcessableBlockHeader currentHeader, Blockchain blockchain);
}

@ -14,24 +14,15 @@
*/
package org.hyperledger.besu.ethereum.mainnet.blockhash;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.mainnet.ParentBeaconBlockRootHelper;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
/** Processes the beacon block storage if it is present in the block header. */
public class CancunBlockHashProcessor implements BlockHashProcessor {
@Override
public BlockHashLookup getBlockHashLookup(
final ProcessableBlockHeader currentHeader, final Blockchain blockchain) {
return new CachingBlockHashLookup(currentHeader, blockchain);
}
@Override
public void processBlockHashes(
final Blockchain blockchain,

@ -14,11 +14,8 @@
*/
package org.hyperledger.besu.ethereum.mainnet.blockhash;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
public class FrontierBlockHashProcessor implements BlockHashProcessor {
@ -29,10 +26,4 @@ public class FrontierBlockHashProcessor implements BlockHashProcessor {
final ProcessableBlockHeader currentBlockHeader) {
// do nothing
}
@Override
public BlockHashLookup getBlockHashLookup(
final ProcessableBlockHeader currentHeader, final Blockchain blockchain) {
return new CachingBlockHashLookup(currentHeader, blockchain);
}
}

@ -14,12 +14,9 @@
*/
package org.hyperledger.besu.ethereum.mainnet.blockhash;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@ -44,53 +41,28 @@ public class PragueBlockHashProcessor extends CancunBlockHashProcessor {
/** The HISTORY_SERVE_WINDOW */
public static final long HISTORY_SERVE_WINDOW = 8192;
private final long forkTimestamp;
private final long historySaveWindow;
private final Address historyStorageAddress;
/**
* Constructs a BlockHashProcessor with a specified fork timestamp.
*
* @param forkTimestamp The timestamp at which the fork becomes active.
*/
public PragueBlockHashProcessor(final long forkTimestamp) {
this(forkTimestamp, HISTORY_STORAGE_ADDRESS, HISTORY_SERVE_WINDOW);
/** Constructs a BlockHashProcessor. */
public PragueBlockHashProcessor() {
this(HISTORY_STORAGE_ADDRESS, HISTORY_SERVE_WINDOW);
}
/**
* Constructs a BlockHashProcessor with a specified fork timestamp and history save window. This
* constructor is primarily used for testing.
* Constructs a BlockHashProcessor with a specified history save window. This constructor is
* primarily used for testing.
*
* @param forkTimestamp The timestamp at which the fork becomes active.
* @param historyStorageAddress the address of the contract storing the history
* @param historySaveWindow The number of blocks for which history should be saved.
*/
@VisibleForTesting
public PragueBlockHashProcessor(
final long forkTimestamp, final Address historyStorageAddress, final long historySaveWindow) {
this.forkTimestamp = forkTimestamp;
final Address historyStorageAddress, final long historySaveWindow) {
this.historyStorageAddress = historyStorageAddress;
this.historySaveWindow = historySaveWindow;
}
@Override
public BlockHashLookup getBlockHashLookup(
final ProcessableBlockHeader currentHeader, final Blockchain blockchain) {
return (frame, blockNumber) -> {
long currentBlockNumber = frame.getBlockValues().getNumber();
if (currentBlockNumber <= blockNumber
|| currentBlockNumber - blockNumber > historySaveWindow
|| blockNumber < 0) {
return Hash.ZERO;
}
return Hash.wrap(
frame
.getWorldUpdater()
.get(historyStorageAddress)
.getStorageValue(UInt256.valueOf(blockNumber % historySaveWindow)));
};
}
@Override
public void processBlockHashes(
final Blockchain blockchain,
@ -99,21 +71,10 @@ public class PragueBlockHashProcessor extends CancunBlockHashProcessor {
super.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader);
WorldUpdater worldUpdater = mutableWorldState.updater();
final MutableAccount historyStorageAccount = worldUpdater.getOrCreate(HISTORY_STORAGE_ADDRESS);
final MutableAccount historyStorageAccount = worldUpdater.getOrCreate(historyStorageAddress);
if (currentBlockHeader.getNumber() > 0) {
storeParentHash(historyStorageAccount, currentBlockHeader);
BlockHeader ancestor =
blockchain.getBlockHeader(currentBlockHeader.getParentHash()).orElseThrow();
// If fork block, add the parent's direct `HISTORY_SERVE_WINDOW - 1`
if (ancestor.getTimestamp() < forkTimestamp) {
for (int i = 0; i < (historySaveWindow - 1) && ancestor.getNumber() > 0; i++) {
ancestor = blockchain.getBlockHeader(ancestor.getParentHash()).orElseThrow();
storeBlockHeaderHash(historyStorageAccount, ancestor);
}
}
}
worldUpdater.commit();
}
@ -128,16 +89,6 @@ public class PragueBlockHashProcessor extends CancunBlockHashProcessor {
storeHash(account, header.getNumber() - 1, header.getParentHash());
}
/**
* Stores the hash of a block in the world state.
*
* @param account The account associated with the historical block hash storage.
* @param header The block header whose hash is to be stored.
*/
private void storeBlockHeaderHash(final MutableAccount account, final BlockHeader header) {
storeHash(account, header.getNumber(), header.getHash());
}
/**
* Stores the hash in the world state.
*
@ -146,11 +97,10 @@ public class PragueBlockHashProcessor extends CancunBlockHashProcessor {
* @param hash The hash to be stored.
*/
private void storeHash(final MutableAccount account, final long number, final Hash hash) {
UInt256 slot = UInt256.valueOf(number % historySaveWindow);
UInt256 value = UInt256.fromBytes(hash);
LOG.trace(
"Writing to {} {}=%{}",
account.getAddress(),
UInt256.valueOf(number % historySaveWindow).toDecimalString(),
UInt256.fromBytes(hash).toHexString());
account.setStorageValue(UInt256.valueOf(number % historySaveWindow), UInt256.fromBytes(hash));
"Writing to {} {}=%{}", account.getAddress(), slot.toDecimalString(), value.toHexString());
account.setStorageValue(slot, value);
}
}

@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.LinkedHashMap;
@ -166,7 +167,7 @@ public class PrivateStateRehydration {
privateStateStorage,
privateStateRootResolver,
block,
protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain),
new CachingBlockHashLookup(blockHeader, blockchain),
pmtHashToPrivateTransactionMap,
block.getBody().getOmmers());

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.tracing.OperationTracer;
@ -139,7 +140,7 @@ public class PrivateTransactionSimulator {
transaction,
protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(header),
OperationTracer.NO_TRACING,
protocolSpec.getBlockHashProcessor().getBlockHashLookup(header, blockchain),
new CachingBlockHashLookup(header, blockchain),
privacyGroupId);
return Optional.of(result);

@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver;
import org.hyperledger.besu.ethereum.privacy.storage.LegacyPrivateStateStorage;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.List;
@ -112,7 +113,7 @@ public class PrivateStorageMigration {
privateMigrationBlockProcessor.processBlock(
blockchain,
publicWorldState,
protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain),
new CachingBlockHashLookup(blockHeader, blockchain),
blockHeader,
transactionsToProcess,
ommers);

@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.account.Account;
@ -279,9 +280,7 @@ public class TransactionSimulator {
protocolSpec
.getMiningBeneficiaryCalculator()
.calculateBeneficiary(blockHeaderToProcess),
protocolSpec
.getBlockHashProcessor()
.getBlockHashLookup(blockHeaderToProcess, blockchain),
new CachingBlockHashLookup(blockHeaderToProcess, blockchain),
false,
transactionValidationParams,
operationTracer,

@ -15,13 +15,12 @@
package org.hyperledger.besu.ethereum.vm;
import static org.hyperledger.besu.datatypes.Hash.ZERO;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.evm.operation.BlockHashOperation;
import org.hyperledger.besu.plugin.data.ProcessableBlockHeader;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import java.util.HashMap;
import java.util.Map;
@ -38,32 +37,17 @@ public class CachingBlockHashLookup implements BlockHashLookup {
private ProcessableBlockHeader searchStartHeader;
private final Blockchain blockchain;
private final long maxLookback;
private final Map<Long, Hash> hashByNumber = new HashMap<>();
public CachingBlockHashLookup(
final ProcessableBlockHeader currentBlock, final Blockchain blockchain) {
this(currentBlock, blockchain, BlockHashOperation.MAX_RELATIVE_BLOCK);
}
public CachingBlockHashLookup(
final ProcessableBlockHeader currentBlock,
final Blockchain blockchain,
final int maxLookback) {
this.searchStartHeader = currentBlock;
this.blockchain = blockchain;
this.maxLookback = maxLookback;
hashByNumber.put(currentBlock.getNumber() - 1, currentBlock.getParentHash());
}
@Override
public Hash apply(final MessageFrame frame, final Long blockNumber) {
long currentBlockNumber = frame.getBlockValues().getNumber();
long lookback = currentBlockNumber - blockNumber;
if (currentBlockNumber <= blockNumber || lookback > maxLookback) {
return Hash.ZERO;
}
public Hash apply(final Long blockNumber) {
final Hash cachedHash = hashByNumber.get(blockNumber);
if (cachedHash != null) {
return cachedHash;

@ -84,7 +84,6 @@ class MainnetTransactionProcessorTest {
messageCallProcessor,
false,
warmCoinbase,
false,
MAX_STACK_SIZE,
FeeMarket.legacy(),
CoinbaseFeePriceCalculator.frontier());

@ -34,7 +34,6 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.blockhash.BlockHashProcessor;
import org.hyperledger.besu.ethereum.privacy.PrivateStateGenesisAllocator;
import org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor;
@ -222,8 +221,6 @@ class PrivacyBlockProcessorTest {
when(protocolSpec.getMiningBeneficiaryCalculator())
.thenReturn(mock(MiningBeneficiaryCalculator.class));
when(protocolSpec.isSkipZeroBlockRewards()).thenReturn(true);
BlockHashProcessor blockHashProcessor = mock(BlockHashProcessor.class);
when(protocolSpec.getBlockHashProcessor()).thenReturn(blockHashProcessor);
return protocolSpec;
}
}

@ -42,7 +42,7 @@ class BlockHashProcessorTest {
private MutableAccount account;
private BlockHashProcessor processor;
private long historicalWindow = 8192;
private final long historicalWindow = 255;
@BeforeEach
void setUp() {
@ -57,9 +57,8 @@ class BlockHashProcessorTest {
@Test
void shouldStoreParentBlockHash() {
long forkTimestamp = 0;
long currentBlock = 3;
processor = new PragueBlockHashProcessor(forkTimestamp);
processor = new PragueBlockHashProcessor();
BlockHeader currentBlockHeader = mockBlockHeader(currentBlock);
mockAncestorHeaders(currentBlockHeader, 3);
processor.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader);
@ -72,9 +71,8 @@ class BlockHashProcessorTest {
void shouldNotStoreBlockHashForGenesisBlock() {
// For the fork to be activated at genesis, no history is written to the genesis state, and at
// the start of block 1, genesis hash will be written as a normal operation to slot 0.
long forkTimestamp = 0;
long currentBlock = 0;
processor = new PragueBlockHashProcessor(forkTimestamp);
processor = new PragueBlockHashProcessor();
BlockHeader currentBlockHeader = mockBlockHeader(currentBlock);
mockAncestorHeaders(currentBlockHeader, 0);
@ -86,9 +84,8 @@ class BlockHashProcessorTest {
void shouldStoreAncestorBlockHashesAtForkCorrectlyParentIsGenesis() {
// for activation at block 1, only genesis hash will be written at slot 0 as there is no
// additional history that needs to be persisted.
long forkTimestamp = 1;
long currentBlock = 1;
processor = new PragueBlockHashProcessor(forkTimestamp);
processor = new PragueBlockHashProcessor();
BlockHeader currentBlockHeader = mockBlockHeader(currentBlock);
mockAncestorHeaders(currentBlockHeader, 10);
@ -97,46 +94,9 @@ class BlockHashProcessorTest {
verifyAccount(0, historicalWindow);
}
@Test
void shouldStoreAncestorBlockHashesAtForkCorrectly() {
// for activation at block 32, block 31’s hash will be written to slot 31 and additional history
// for 0..30’s hashes will be persisted, so all in all 0..31’s hashes.
long forkTimestamp = 32;
long currentBlock = 32;
processor = new PragueBlockHashProcessor(forkTimestamp);
BlockHeader currentBlockHeader = mockBlockHeader(currentBlock);
mockAncestorHeaders(currentBlockHeader, 32);
processor.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader);
verifyAncestor(currentBlock, 32, historicalWindow);
}
@Test
void shouldStoreAncestorBlockHashesAtForkCorrectlyMaxWindows() {
long forkTimestamp = 10000;
long currentBlock = 10000;
historicalWindow = 8192;
processor =
new PragueBlockHashProcessor(
forkTimestamp, PragueBlockHashProcessor.HISTORY_STORAGE_ADDRESS, historicalWindow);
BlockHeader currentBlockHeader = mockBlockHeader(currentBlock);
mockAncestorHeaders(currentBlockHeader, 10000);
processor.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader);
// Total of historicalWindow hashes were stored
verify(account, times((int) historicalWindow)).setStorageValue(any(), any());
// for activation at block 10000, block 1808-9999’s hashes will be presisted in the slot
verifyAccount(1808, historicalWindow);
verifyAccount(9999, historicalWindow);
// BLOCKHASH for 1807 or less would resolve to 0 as only HISTORY_SERVE_WINDOW are persisted.
verifyAccountNoIteraction(1807, historicalWindow);
verifyAccountNoIteraction(10000, historicalWindow);
}
@Test
void shouldWriteGenesisHashAtSlot0() {
processor = new PragueBlockHashProcessor(0);
processor = new PragueBlockHashProcessor();
BlockHeader header = mockBlockHeader(1);
mockAncestorHeaders(header, 1);
processor.processBlockHashes(blockchain, mutableWorldState, header);
@ -144,26 +104,11 @@ class BlockHashProcessorTest {
.setStorageValue(UInt256.valueOf(0), UInt256.fromHexString(Hash.ZERO.toHexString()));
}
private void verifyAncestor(
final long blockNumber, final int count, final long historicalWindow) {
int totalTouchedSlots = (int) (blockNumber - count <= 0 ? blockNumber : count);
long firstAncestor = Math.max(blockNumber - count - 1, 0);
verify(account, times(totalTouchedSlots)).setStorageValue(any(), any());
for (long i = firstAncestor; i < blockNumber; i++) {
verifyAccount(i, historicalWindow);
}
}
private void verifyAccount(final long number, final long historicalWindow) {
verify(account)
.setStorageValue(UInt256.valueOf(number % historicalWindow), UInt256.valueOf(number));
}
private void verifyAccountNoIteraction(final long number, final long historicalWindow) {
verify(account, times(0))
.setStorageValue(UInt256.valueOf(number % historicalWindow), UInt256.valueOf(number));
}
private void mockAncestorHeaders(final BlockHeader blockHeader, final int count) {
long firstAncestor = Math.max(blockHeader.getNumber() - count, 0);
var block = blockHeader;

@ -14,9 +14,8 @@
*/
package org.hyperledger.besu.ethereum.vm;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@ -27,8 +26,7 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.evm.frame.BlockValues;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import java.util.Optional;
@ -37,17 +35,13 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class CachingBlockHashLookupTest {
@Mock private Blockchain blockchain;
@Mock private MessageFrame messageFrame;
@Mock private BlockValues blockValues;
private static final int CURRENT_BLOCK_NUMBER = 300;
private static final int CURRENT_BLOCK_NUMBER = 256;
private final Blockchain blockchain = mock(Blockchain.class);
private final BlockHeader[] headers = new BlockHeader[CURRENT_BLOCK_NUMBER];
private BlockHashLookup lookup;
@ -56,13 +50,10 @@ class CachingBlockHashLookupTest {
BlockHeader parentHeader = null;
for (int i = 0; i < headers.length; i++) {
final BlockHeader header = createHeader(i, parentHeader);
lenient().when(blockchain.getBlockHeader(header.getHash())).thenReturn(Optional.of(header));
when(blockchain.getBlockHeader(header.getHash())).thenReturn(Optional.of(header));
headers[i] = header;
parentHeader = headers[i];
}
when(messageFrame.getBlockValues()).thenReturn(blockValues);
when(blockValues.getNumber()).thenReturn((long) CURRENT_BLOCK_NUMBER);
lookup =
new CachingBlockHashLookup(
createHeader(CURRENT_BLOCK_NUMBER, headers[headers.length - 1]), blockchain);
@ -81,32 +72,19 @@ class CachingBlockHashLookupTest {
}
@Test
void shouldGetHashForRecentBlockAfterOlderBlock() {
assertHashForBlockNumber(100);
assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 1);
}
@Test
void shouldReturnEmptyHashWhenRequestedGenesis() {
Assertions.assertThat(lookup.apply(messageFrame, 0L)).isEqualTo(Hash.ZERO);
void shouldGetHashOfGenesisBlock() {
assertHashForBlockNumber(0);
}
@Test
void shouldReturnEmptyHashWhenRequestedTooFarBack() {
Assertions.assertThat(lookup.apply(messageFrame, CURRENT_BLOCK_NUMBER - 260L))
.isEqualTo(Hash.ZERO);
}
@Test
void shouldReturnEmptyHashWhenRequestedCurrentBlock() {
Assertions.assertThat(lookup.apply(messageFrame, (long) CURRENT_BLOCK_NUMBER))
.isEqualTo(Hash.ZERO);
void shouldGetHashForRecentBlockAfterOlderBlock() {
assertHashForBlockNumber(10);
assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 1);
}
@Test
void shouldReturnEmptyHashWhenRequestedBlockNotOnchain() {
Assertions.assertThat(lookup.apply(messageFrame, CURRENT_BLOCK_NUMBER + 20L))
.isEqualTo(Hash.ZERO);
Assertions.assertThat(lookup.apply(CURRENT_BLOCK_NUMBER + 20L)).isEqualTo(Hash.ZERO);
}
@Test
@ -115,8 +93,7 @@ class CachingBlockHashLookupTest {
new CachingBlockHashLookup(
new BlockHeaderTestFixture().number(CURRENT_BLOCK_NUMBER + 20).buildHeader(),
blockchain);
Assertions.assertThat(
lookupWithUnavailableParent.apply(messageFrame, (long) CURRENT_BLOCK_NUMBER))
Assertions.assertThat(lookupWithUnavailableParent.apply((long) CURRENT_BLOCK_NUMBER))
.isEqualTo(Hash.ZERO);
}
@ -137,7 +114,7 @@ class CachingBlockHashLookupTest {
}
private void assertHashForBlockNumber(final int blockNumber) {
Assertions.assertThat(lookup.apply(messageFrame, (long) blockNumber))
Assertions.assertThat(lookup.apply((long) blockNumber))
.isEqualTo(headers[blockNumber].getHash());
}

@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.Code;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.EvmSpecVersion;
@ -429,10 +430,7 @@ public class EvmToolCommand implements Runnable {
.blockValues(blockHeader)
.completer(c -> {})
.miningBeneficiary(blockHeader.getCoinbase())
.blockHashLookup(
protocolSpec
.getBlockHashProcessor()
.getBlockHashLookup(blockHeader, component.getBlockchain()))
.blockHashLookup(new CachingBlockHashLookup(blockHeader, component.getBlockchain()))
.accessListWarmAddresses(addressList)
.build();
Deque<MessageFrame> messageFrameStack = initialMessageFrame.getMessageFrameStack();

@ -32,13 +32,10 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseEipSpec;
import org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseSpec;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.operation.BlockHashOperation;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.tracing.StandardJsonTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@ -251,31 +248,13 @@ public class StateTestSubCommand implements Runnable {
final Stopwatch timer = Stopwatch.createStarted();
// Todo: EIP-4844 use the excessBlobGas of the parent instead of BlobGas.ZERO
final Wei blobGasPrice = protocolSpec.getFeeMarket().blobGasPricePerGas(BlobGas.ZERO);
BlockHashOperation.BlockHashLookup blockHashLookup =
protocolSpec
.getBlockHashProcessor()
.getBlockHashLookup(
blockHeader, new ReferenceTestBlockchain(blockHeader.getNumber()));
if (blockHashLookup instanceof CachingBlockHashLookup) {
blockHashLookup =
(messageFrame, number) -> {
long lookback = messageFrame.getBlockValues().getNumber() - number;
if (lookback <= 0 || lookback > BlockHashOperation.MAX_RELATIVE_BLOCK) {
return Hash.ZERO;
} else {
return Hash.hash(Bytes.wrap(Long.toString(number).getBytes(UTF_8)));
}
};
}
final TransactionProcessingResult result =
processor.processTransaction(
worldStateUpdater,
blockHeader,
transaction,
blockHeader.getCoinbase(),
blockHashLookup,
blockNumber -> Hash.hash(Bytes.wrap(Long.toString(blockNumber).getBytes(UTF_8))),
false,
TransactionValidationParams.processingBlock(),
tracer,

@ -47,11 +47,9 @@ import org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.operation.BlockHashOperation;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.evmtool.exception.UnsupportedForkException;
@ -291,27 +289,13 @@ public class T8nExecutor {
tracer = tracerManager.getManagedTracer(i, transaction.getHash());
tracer.tracePrepareTransaction(worldStateUpdater, transaction);
tracer.traceStartTransaction(worldStateUpdater, transaction);
BlockHashOperation.BlockHashLookup blockHashLookup =
protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain);
if (blockHashLookup instanceof CachingBlockHashLookup) {
// caching lookup won't work, use our own secret sauce
blockHashLookup =
(frame, number) -> {
long lookback = frame.getBlockValues().getNumber() - number;
if (lookback <= 0 || lookback > BlockHashOperation.MAX_RELATIVE_BLOCK) {
return Hash.ZERO;
} else {
return referenceTestEnv.getBlockhashByNumber(number).orElse(Hash.ZERO);
}
};
}
result =
processor.processTransaction(
worldStateUpdater,
blockHeader,
transaction,
blockHeader.getCoinbase(),
blockHashLookup,
number -> referenceTestEnv.getBlockhashByNumber(number).orElse(Hash.ZERO),
false,
TransactionValidationParams.processingBlock(),
tracer,

@ -62,7 +62,7 @@ public abstract class BenchmarkExecutor {
.code(CodeV0.EMPTY_CODE)
.completer(__ -> {})
.address(Address.ZERO)
.blockHashLookup((f, n) -> null)
.blockHashLookup(n -> null)
.blockValues(new SimpleBlockValues())
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)

@ -106,9 +106,6 @@ public class GeneralStateReferenceTestTools {
// EOF tests are written against an older version of the spec
params.ignore("/stEOF/");
// None of the Prague tests have withdrawls and deposits handling
params.ignore("-Prague$");
}
private GeneralStateReferenceTestTools() {
@ -160,7 +157,7 @@ public class GeneralStateReferenceTestTools {
blockHeader,
transaction,
blockHeader.getCoinbase(),
protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain),
new CachingBlockHashLookup(blockHeader, blockchain),
false,
TransactionValidationParams.processingBlock(),
blobGasPrice);

@ -72,7 +72,7 @@ public class EVMExecutor {
private Wei ethValue = Wei.ZERO;
private Code code = CodeV0.EMPTY_CODE;
private BlockValues blockValues = new SimpleBlockValues();
private BlockHashLookup blockHashLookup = (h, n) -> null;
private BlockHashLookup blockHashLookup = n -> null;
private Optional<List<VersionedHash>> versionedHashes = Optional.empty();
private OperationTracer tracer = OperationTracer.NO_TRACING;
private boolean requireDeposit = true;

@ -16,7 +16,6 @@ package org.hyperledger.besu.evm.frame;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Collections.emptySet;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.collections.trie.BytesTrieSet;
import org.hyperledger.besu.collections.undo.UndoScalar;
@ -33,6 +32,7 @@ import org.hyperledger.besu.evm.internal.ReturnStack;
import org.hyperledger.besu.evm.internal.StorageEntry;
import org.hyperledger.besu.evm.internal.UnderflowException;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.operation.Operation;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@ -1427,9 +1427,6 @@ public class MessageFrame {
private Optional<List<VersionedHash>> versionedHashes = Optional.empty();
/** Instantiates a new Builder. */
public Builder() {}
/**
* The "parent" message frame. When present some fields will be populated from the parent and
* ignored if passed in via builder

@ -392,7 +392,7 @@ public class FrontierGasCalculator implements GasCalculator {
}
@Override
public long getBlockHashOperationGasCost(final MessageFrame frame) {
public long getBlockHashOperationGasCost() {
return BLOCKHASH_OPERATION_GAS_COST;
}

@ -345,10 +345,9 @@ public interface GasCalculator {
/**
* Returns the cost for executing a {@link BlockHashOperation}.
*
* @param frame The current frame
* @return the cost for executing the block hash operation
*/
long getBlockHashOperationGasCost(MessageFrame frame);
long getBlockHashOperationGasCost();
/**
* Returns the cost for executing a {@link ExpOperation}.

@ -21,8 +21,6 @@ import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.apache.tuweni.units.bigints.UInt256;
/**
* Gas Calculator for Prague
*
@ -101,24 +99,4 @@ public class PragueGasCalculator extends CancunGasCalculator {
return cost;
}
/** Address of the contract historic block hashes are stored in. */
public static final Address HISTORY_STORAGE_ADDRESS =
Address.fromHexString("0x25a219378dad9b3503c8268c9ca836a52427a4fb");
/** The HISTORY_SERVE_WINDOW */
public static final long HISTORY_SERVE_WINDOW = 8192;
@Override
public long getBlockHashOperationGasCost(final MessageFrame frame) {
if (frame == null) {
return super.getBlockHashOperationGasCost(null);
} else {
UInt256 slot = UInt256.valueOf(frame.getBlockValues().getNumber() % HISTORY_SERVE_WINDOW);
return BLOCKHASH_OPERATION_GAS_COST
+ (frame.warmUpStorage(HISTORY_STORAGE_ADDRESS, slot)
? getWarmStorageReadCost()
: getColdSloadCost());
}
}
}

@ -16,27 +16,29 @@ package org.hyperledger.besu.evm.operation;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.BlockValues;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
/** The Block hash operation. */
public class BlockHashOperation extends AbstractOperation {
/** Frontier maximum relative block delta */
public static final int MAX_RELATIVE_BLOCK = 256;
public class BlockHashOperation extends AbstractFixedCostOperation {
/**
* Function that gets the block hash, passed in as part of TxValues.
*
* <p>First arg is the current block number, second is the block argument from the stack. The
* Result is the Hash, which may be zero based on lookup rules.
* <p>Arg is the current block number. The Result is the Hash, which may be zero based on lookup
* rules.
*/
public interface BlockHashLookup extends BiFunction<MessageFrame, Long, Hash> {}
public interface BlockHashLookup extends Function<Long, Hash> {}
/** Frontier maximum relative block delta */
public static final int MAX_RELATIVE_BLOCK = 256;
private static final int MAX_BLOCK_ARG_SIZE = 8;
@ -46,25 +48,36 @@ public class BlockHashOperation extends AbstractOperation {
* @param gasCalculator the gas calculator
*/
public BlockHashOperation(final GasCalculator gasCalculator) {
super(0x40, "BLOCKHASH", 1, 1, gasCalculator);
super(0x40, "BLOCKHASH", 1, 1, gasCalculator, gasCalculator.getBlockHashOperationGasCost());
}
@Override
public OperationResult execute(MessageFrame frame, EVM evm) {
public Operation.OperationResult executeFixedCostOperation(
final MessageFrame frame, final EVM evm) {
final Bytes blockArg = frame.popStackItem().trimLeadingZeros();
// Short-circuit if value exceeds long
// Short-circuit if value is unreasonably large
if (blockArg.size() > MAX_BLOCK_ARG_SIZE) {
frame.pushStackItem(UInt256.ZERO);
return new OperationResult(gasCalculator().getBlockHashOperationGasCost(null), null);
return successResponse;
}
final long soughtBlock = blockArg.toLong();
final BlockHashLookup blockHashLookup = frame.getBlockHashLookup();
final Hash blockHash = blockHashLookup.apply(frame, soughtBlock);
frame.pushStackItem(blockHash);
return new OperationResult(
gasCalculator().getBlockHashOperationGasCost(Hash.ZERO.equals(blockHash) ? null : frame),
null);
final BlockValues blockValues = frame.getBlockValues();
final long currentBlockNumber = blockValues.getNumber();
// If the current block is the genesis block or the sought block is
// not within the last 256 completed blocks, zero is returned.
if (currentBlockNumber == 0
|| soughtBlock >= currentBlockNumber
|| soughtBlock < (currentBlockNumber - MAX_RELATIVE_BLOCK)) {
frame.pushStackItem(Bytes32.ZERO);
} else {
final BlockHashLookup blockHashLookup = frame.getBlockHashLookup();
final Hash blockHash = blockHashLookup.apply(soughtBlock);
frame.pushStackItem(blockHash);
}
return successResponse;
}
}

@ -97,7 +97,7 @@ class CodeV0Test {
.blockValues(mock(BlockValues.class))
.completer(f -> {})
.miningBeneficiary(Address.ZERO)
.blockHashLookup((f, n) -> Hash.EMPTY)
.blockHashLookup(l -> Hash.EMPTY)
.build();
frame.setPC(CURRENT_PC);

@ -188,7 +188,7 @@ class EVMExecutorTest {
.number(1)
.timestamp(100L)
.gasLimit(15_000_000L)
.blockHashLookup((height, number) -> Hash.ZERO)
.blockHashLookup(number -> Hash.ZERO)
.versionedHashes(Optional.empty())
.precompileContractRegistry(new PrecompileContractRegistry())
.requireDeposit(false)

@ -48,7 +48,7 @@ class MessageFrameTest {
.blobGasPrice(Wei.ONE)
.blockValues(new ToyBlockValues())
.miningBeneficiary(Address.ZERO)
.blockHashLookup((f, n) -> Hash.ZERO)
.blockHashLookup((l) -> Hash.ZERO)
.type(MessageFrame.Type.MESSAGE_CALL)
.initialGas(1)
.address(Address.ZERO)

@ -169,7 +169,7 @@ class AbstractCreateOperationTest {
.code(CodeFactory.createCode(SIMPLE_CREATE, 0, true))
.completer(__ -> {})
.address(Address.fromHexString(SENDER))
.blockHashLookup((f, n) -> Hash.hash(Words.longBytes(n)))
.blockHashLookup(n -> Hash.hash(Words.longBytes(n)))
.blockValues(mock(BlockValues.class))
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)

@ -15,12 +15,12 @@
package org.hyperledger.besu.evm.operations;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator;
import org.hyperledger.besu.evm.operation.BlockHashOperation;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.testutils.FakeBlockValues;
import org.hyperledger.besu.evm.testutils.TestMessageFrameBuilder;
@ -31,20 +31,49 @@ import org.junit.jupiter.api.Test;
class BlockHashOperationTest {
private static final int MAXIMUM_COMPLETE_BLOCKS_BEHIND = 256;
private final BlockHashOperation blockHashOperation =
new BlockHashOperation(new FrontierGasCalculator());
@Test
void shouldReturnZeroWhenArgIsBiggerThanALong() {
assertBlockHash(
Bytes32.fromHexString("F".repeat(64)), Bytes32.ZERO, 100, (h, n) -> Hash.EMPTY_LIST_HASH);
Bytes32.fromHexString("F".repeat(64)), Bytes32.ZERO, 100, n -> Hash.EMPTY_LIST_HASH);
}
@Test
void shouldReturnZeroWhenCurrentBlockIsGenesis() {
assertBlockHash(Bytes32.ZERO, Bytes32.ZERO, 0, block -> Hash.EMPTY_LIST_HASH);
}
@Test
void shouldReturnZeroWhenRequestedBlockAheadOfCurrent() {
assertBlockHash(250, Bytes32.ZERO, 100, block -> Hash.EMPTY_LIST_HASH);
}
@Test
void shouldReturnZeroWhenRequestedBlockTooFarBehindCurrent() {
final int requestedBlock = 10;
// Our block is the one after the chain head (it's a new block), hence the + 1.
final int importingBlockNumber = MAXIMUM_COMPLETE_BLOCKS_BEHIND + requestedBlock + 1;
assertBlockHash(
requestedBlock, Bytes32.ZERO, importingBlockNumber, block -> Hash.EMPTY_LIST_HASH);
}
@Test
void shouldReturnZeroWhenRequestedBlockGreaterThanImportingBlock() {
assertBlockHash(101, Bytes32.ZERO, 100, block -> Hash.EMPTY_LIST_HASH);
}
@Test
void shouldReturnZeroWhenRequestedBlockEqualToImportingBlock() {
assertBlockHash(100, Bytes32.ZERO, 100, block -> Hash.EMPTY_LIST_HASH);
}
@Test
void shouldReturnBlockHashUsingLookupFromFrameWhenItIsWithinTheAllowedRange() {
final Hash blockHash = Hash.hash(Bytes.fromHexString("0x1293487297"));
assertBlockHash(
100, blockHash, 200, (h, block) -> block == 100 ? blockHash : Hash.EMPTY_LIST_HASH);
assertBlockHash(100, blockHash, 200, block -> block == 100 ? blockHash : Hash.EMPTY_LIST_HASH);
}
private void assertBlockHash(

@ -155,7 +155,7 @@ public class Create2OperationTest {
.code(CodeFactory.createCode(codeBytes, 0, true))
.completer(__ -> {})
.address(Address.fromHexString(sender))
.blockHashLookup((f, n) -> Hash.hash(Words.longBytes(n)))
.blockHashLookup(n -> Hash.hash(Words.longBytes(n)))
.blockValues(mock(BlockValues.class))
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)
@ -269,7 +269,7 @@ public class Create2OperationTest {
.code(CodeFactory.createCode(SIMPLE_CREATE, 0, true))
.completer(__ -> {})
.address(Address.fromHexString(SENDER))
.blockHashLookup((f, n) -> Hash.hash(Words.longBytes(n)))
.blockHashLookup(n -> Hash.hash(Words.longBytes(n)))
.blockValues(mock(BlockValues.class))
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)

@ -289,7 +289,7 @@ class CreateOperationTest {
.code(CodeFactory.createCode(SIMPLE_CREATE, 0, true))
.completer(__ -> {})
.address(Address.fromHexString(SENDER))
.blockHashLookup((f, n) -> Hash.hash(Words.longBytes(n)))
.blockHashLookup(n -> Hash.hash(Words.longBytes(n)))
.blockValues(mock(BlockValues.class))
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)

@ -82,7 +82,7 @@ public class SelfDestructOperationTest {
.code(CodeFactory.createCode(SELFDESTRUCT_CODE, 0, true))
.completer(__ -> {})
.address(originatorAddress)
.blockHashLookup((f, n) -> Hash.hash(Words.longBytes(n)))
.blockHashLookup(n -> Hash.hash(Words.longBytes(n)))
.blockValues(mock(BlockValues.class))
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)

@ -65,7 +65,7 @@ public class Benchmarks {
.code(CodeV0.EMPTY_CODE)
.completer(__ -> {})
.address(Address.ZERO)
.blockHashLookup((f, n) -> null)
.blockHashLookup(n -> null)
.blockValues(new SimpleBlockValues())
.gasPrice(Wei.ZERO)
.miningBeneficiary(Address.ZERO)

@ -15,7 +15,6 @@
package org.hyperledger.besu.evm.testutils;
import static org.hyperledger.besu.evm.frame.MessageFrame.DEFAULT_MAX_STACK_SIZE;
import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
@ -25,6 +24,7 @@ import org.hyperledger.besu.evm.code.CodeV0;
import org.hyperledger.besu.evm.frame.BlockValues;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.internal.Words;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.toy.ToyWorld;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@ -161,7 +161,7 @@ public class TestMessageFrameBuilder {
.blockValues(blockValues.orElseGet(() -> new FakeBlockValues(1337)))
.completer(c -> {})
.miningBeneficiary(Address.ZERO)
.blockHashLookup(blockHashLookup.orElse((f, n) -> Hash.hash(Words.longBytes(n))))
.blockHashLookup(blockHashLookup.orElse(number -> Hash.hash(Words.longBytes(number))))
.maxStackSize(maxStackSize)
.build();
frame.setPC(pc);

@ -190,7 +190,7 @@ public class EvmToyCommand implements Runnable {
.blockValues(new ToyBlockValues())
.completer(c -> {})
.miningBeneficiary(Address.ZERO)
.blockHashLookup((f, n) -> null)
.blockHashLookup(n -> null)
.build();
final MessageCallProcessor mcp = new MessageCallProcessor(evm, precompileContractRegistry);

Loading…
Cancel
Save