From 0cca642bc56b887dfd59d263883b04a581896c03 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 20 May 2024 00:56:51 -0600 Subject: [PATCH] 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 Co-authored-by: Lucas Saldanha Co-authored-by: Gabriel-Trintinalia Co-authored-by: Justin Florentine Co-authored-by: Jason Frame Co-authored-by: Jason Frame --- .../test-cases/06_prague_getPayloadV4.json | 12 ++-- ...invalid_null_deposits_execute_payload.json | 8 +-- .../test-cases/09_prague_newPayloadV4.json | 8 +-- .../10_prague_forkchoiceUpdatedV3.json | 12 ++-- .../test-cases/11_prague_getPayloadV4.json | 8 +-- .../test-cases/12_cancun_newPayloadV4.json | 8 +-- .../14_prague_forkchoiceUpdatedV3.json | 12 ++-- .../test-cases/15_prague_getPayloadV4.json | 10 +-- .../besu/services/TraceServiceImpl.java | 3 +- .../methods/ExecuteTransactionStep.java | 6 +- .../internal/processor/BlockReplay.java | 12 ++-- .../internal/processor/BlockTracer.java | 6 +- .../internal/processor/TransactionTracer.java | 6 +- .../processor/TransactionTracerTest.java | 3 - .../txselection/BlockTransactionSelector.java | 7 +- ...acyPrecompiledContractIntegrationTest.java | 2 +- .../vm/TraceTransactionIntegrationTest.java | 13 ++-- .../mainnet/AbstractBlockProcessor.java | 4 +- .../mainnet/ClassicProtocolSpecs.java | 2 - .../mainnet/MainnetProtocolSpecs.java | 9 +-- .../mainnet/MainnetTransactionProcessor.java | 14 ---- .../mainnet/blockhash/BlockHashProcessor.java | 4 -- .../blockhash/CancunBlockHashProcessor.java | 9 --- .../blockhash/FrontierBlockHashProcessor.java | 9 --- .../blockhash/PragueBlockHashProcessor.java | 72 +++---------------- .../privacy/PrivateStateRehydration.java | 3 +- .../privacy/PrivateTransactionSimulator.java | 3 +- .../migration/PrivateStorageMigration.java | 3 +- .../transaction/TransactionSimulator.java | 5 +- .../ethereum/vm/CachingBlockHashLookup.java | 22 +----- .../MainnetTransactionProcessorTest.java | 1 - .../mainnet/PrivacyBlockProcessorTest.java | 3 - .../blockhash/BlockHashProcessorTest.java | 65 ++--------------- .../vm/CachingBlockHashLookupTest.java | 49 ++++--------- .../besu/evmtool/EvmToolCommand.java | 6 +- .../besu/evmtool/StateTestSubCommand.java | 23 +----- .../hyperledger/besu/evmtool/T8nExecutor.java | 18 +---- .../evmtool/benchmarks/BenchmarkExecutor.java | 2 +- .../vm/GeneralStateReferenceTestTools.java | 5 +- .../besu/evm/fluent/EVMExecutor.java | 2 +- .../besu/evm/frame/MessageFrame.java | 5 +- .../gascalculator/FrontierGasCalculator.java | 2 +- .../besu/evm/gascalculator/GasCalculator.java | 3 +- .../gascalculator/PragueGasCalculator.java | 22 ------ .../evm/operation/BlockHashOperation.java | 49 ++++++++----- .../hyperledger/besu/evm/code/CodeV0Test.java | 2 +- .../besu/evm/fluent/EVMExecutorTest.java | 2 +- .../besu/evm/frame/MessageFrameTest.java | 2 +- .../AbstractCreateOperationTest.java | 2 +- .../operations/BlockHashOperationTest.java | 37 ++++++++-- .../evm/operations/Create2OperationTest.java | 4 +- .../evm/operations/CreateOperationTest.java | 2 +- .../operations/SelfDestructOperationTest.java | 2 +- .../besu/evm/precompile/Benchmarks.java | 2 +- .../testutils/TestMessageFrameBuilder.java | 4 +- .../besu/evm/toy/EvmToyCommand.java | 2 +- 56 files changed, 190 insertions(+), 421 deletions(-) diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json index 99289d34b78..b0bc6ffeeb5 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json @@ -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": { diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/08_prague_invalid_null_deposits_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/08_prague_invalid_null_deposits_execute_payload.json index 3eeccb01b5d..7263aea00f7 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/08_prague_invalid_null_deposits_execute_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/08_prague_invalid_null_deposits_execute_payload.json @@ -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 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json index 630b8518945..27885c1c81b 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json @@ -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 } }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/10_prague_forkchoiceUpdatedV3.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/10_prague_forkchoiceUpdatedV3.json index c0eaebd2a41..d8594f62800 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/10_prague_forkchoiceUpdatedV3.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/10_prague_forkchoiceUpdatedV3.json @@ -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 } \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/11_prague_getPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/11_prague_getPayloadV4.json index f93425a7e16..6a22938a693 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/11_prague_getPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/11_prague_getPayloadV4.json @@ -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" }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/12_cancun_newPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/12_cancun_newPayloadV4.json index f5e1c6c2d4d..5d9f96c53b3 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/12_cancun_newPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/12_cancun_newPayloadV4.json @@ -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 } }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/14_prague_forkchoiceUpdatedV3.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/14_prague_forkchoiceUpdatedV3.json index 32fc288b0c0..bf2b3dca5ad 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/14_prague_forkchoiceUpdatedV3.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/14_prague_forkchoiceUpdatedV3.json @@ -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 } \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json index d4c53779e3d..1450ac4bba9 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json @@ -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": { diff --git a/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java index 41a7aa49c3f..6a0804b6f46 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java @@ -31,6 +31,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.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 @@ private List trace( transaction, protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(header), tracer, - protocolSpec.getBlockHashProcessor().getBlockHashLookup(header, blockchain), + new CachingBlockHashLookup(header, blockchain), false, blobGasPrice); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java index 492d58abbb1..db062a64d95 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java @@ -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.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 TransactionTrace apply(final TransactionTrace transactionTrace) { 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(), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java index ef81b5e2899..b1a9be021e9 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java @@ -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.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 Optional beforeTransactionInBlock( 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 Optional afterTransactionInBlock( blockHeader, transaction, spec.getMiningBeneficiaryCalculator().calculateBeneficiary(blockHeader), - spec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain), + new CachingBlockHashLookup(blockHeader, blockchain), false, TransactionValidationParams.blockReplay(), blobGasPrice); @@ -180,10 +180,6 @@ private Optional getBlock(final Hash blockHash) { return Optional.empty(); } - public ProtocolSpec getProtocolSpec(final BlockHeader header) { - return protocolSchedule.getByBlockHeader(header); - } - @FunctionalInterface public interface BlockAction { Optional perform( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java index 4917ebe157a..5ede2d4a7b2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java @@ -19,6 +19,7 @@ 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 @@ private BlockReplay.TransactionAction prepareReplayAction( transaction, header.getCoinbase(), tracer, - blockReplay - .getProtocolSpec(header) - .getBlockHashProcessor() - .getBlockHashLookup(header, blockchain), + new CachingBlockHashLookup(header, blockchain), false, blobGasPrice); final List traceFrames = tracer.copyTraceFrames(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java index 54d4f1c0bef..6524109ac6f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java @@ -29,6 +29,7 @@ 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 @@ private TransactionProcessingResult processTransaction( transaction, header.getCoinbase(), tracer, - blockReplay - .getProtocolSpec(header) - .getBlockHashProcessor() - .getBlockHashLookup(header, blockchain), + new CachingBlockHashLookup(header, blockchain), false, ImmutableTransactionValidationParams.builder().isAllowFutureNonce(true).build(), blobGasPrice); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java index e099f4b4927..6626a66bb09 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java @@ -36,7 +36,6 @@ 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 void setUp() throws Exception { 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); } diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java index 3f4d3f753bf..22d75e27aaa 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java @@ -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.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 @@ private TransactionSelectionResult evaluatePostProcessing( 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(), diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java index f2ca7c16095..090c24e26e2 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java @@ -16,7 +16,6 @@ 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.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; diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java index 14608af5679..edae52f35a9 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java @@ -33,7 +33,6 @@ 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 void setUp() { 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 diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java index 923b2bdf96d..888bc848f15 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java @@ -35,6 +35,7 @@ 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 BlockProcessingResult processBlock( 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); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java index 21ca375c68f..7575c7fe314 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java @@ -183,7 +183,6 @@ public static ProtocolSpecBuilder atlantisDefinition( messageCallProcessor, true, false, - false, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.frontier())) @@ -373,7 +372,6 @@ public static ProtocolSpecBuilder spiralDefinition( messageCallProcessor, true, true, - false, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.frontier())) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index 5e8b6e70de7..5c1d399264f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -143,7 +143,6 @@ public static ProtocolSpecBuilder frontierDefinition( messageCallProcessor, false, false, - false, stackSizeLimit, FeeMarket.legacy(), CoinbaseFeePriceCalculator.frontier())) @@ -298,7 +297,6 @@ public static ProtocolSpecBuilder spuriousDragonDefinition( messageCallProcessor, true, false, - false, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.frontier())) @@ -492,7 +490,6 @@ static ProtocolSpecBuilder londonDefinition( messageCallProcessor, true, false, - false, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.eip1559())) @@ -630,7 +627,6 @@ static ProtocolSpecBuilder shanghaiDefinition( messageCallProcessor, true, true, - false, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.eip1559())) @@ -707,7 +703,6 @@ static ProtocolSpecBuilder cancunDefinition( messageCallProcessor, true, true, - false, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.eip1559())) @@ -786,7 +781,6 @@ static ProtocolSpecBuilder pragueDefinition( messageCallProcessor, true, true, - true, stackSizeLimit, feeMarket, CoinbaseFeePriceCalculator.eip1559())) @@ -795,8 +789,7 @@ static ProtocolSpecBuilder pragueDefinition( .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::prague) .requestsValidator(pragueRequestsValidator(depositContractAddress)) .requestProcessorCoordinator(pragueRequestsProcessors(depositContractAddress)) - .blockHashProcessor( - new PragueBlockHashProcessor(genesisConfigOptions.getPragueTime().orElse(0))) + .blockHashProcessor(new PragueBlockHashProcessor()) .name("Prague"); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 62f4abc6eae..0027c51b79d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -27,7 +27,6 @@ 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.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 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 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 TransactionProcessingResult processTransaction( 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( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java index 943de19280d..e64b51afa41 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java @@ -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 @@ void processBlockHashes( Blockchain blockchain, MutableWorldState worldState, ProcessableBlockHeader currentBlockHeader); - - BlockHashLookup getBlockHashLookup(ProcessableBlockHeader currentHeader, Blockchain blockchain); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java index 915de6369d1..0e8b1ae8afa 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java @@ -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, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java index 954aea4ad64..f1722936b58 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java @@ -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 void processBlockHashes( final ProcessableBlockHeader currentBlockHeader) { // do nothing } - - @Override - public BlockHashLookup getBlockHashLookup( - final ProcessableBlockHeader currentHeader, final Blockchain blockchain) { - return new CachingBlockHashLookup(currentHeader, blockchain); - } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java index 98ea102dc26..634a7441596 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java @@ -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 void processBlockHashes( 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 @@ private void storeParentHash(final MutableAccount account, final ProcessableBloc 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 @@ private void storeBlockHeaderHash(final MutableAccount account, final BlockHeade * @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); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java index 53760f649ff..6d4811a4bca 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java @@ -25,6 +25,7 @@ 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 void rehydrate( privateStateStorage, privateStateRootResolver, block, - protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain), + new CachingBlockHashLookup(blockHeader, blockchain), pmtHashToPrivateTransactionMap, block.getBody().getOmmers()); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java index 8e4b70fc1fc..061c56353fb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java @@ -28,6 +28,7 @@ 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 @@ private Optional process( transaction, protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(header), OperationTracer.NO_TRACING, - protocolSpec.getBlockHashProcessor().getBlockHashLookup(header, blockchain), + new CachingBlockHashLookup(header, blockchain), privacyGroupId); return Optional.of(result); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java index eb4f0205bf2..834633a997d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java @@ -29,6 +29,7 @@ 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 void migratePrivateStorage() { privateMigrationBlockProcessor.processBlock( blockchain, publicWorldState, - protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain), + new CachingBlockHashLookup(blockHeader, blockchain), blockHeader, transactionsToProcess, ommers); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index a4cb32ff75d..070c1dcf771 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -34,6 +34,7 @@ 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 Optional processWithWorldUpdater( protocolSpec .getMiningBeneficiaryCalculator() .calculateBeneficiary(blockHeaderToProcess), - protocolSpec - .getBlockHashProcessor() - .getBlockHashLookup(blockHeaderToProcess, blockchain), + new CachingBlockHashLookup(blockHeaderToProcess, blockchain), false, transactionValidationParams, operationTracer, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java index 5229885ac3a..c70af6b836b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java @@ -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 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; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java index bd19208ac13..77466587314 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java @@ -84,7 +84,6 @@ MainnetTransactionProcessor createTransactionProcessor(final boolean warmCoinbas messageCallProcessor, false, warmCoinbase, - false, MAX_STACK_SIZE, FeeMarket.legacy(), CoinbaseFeePriceCalculator.frontier()); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java index a46943e5acb..2749b37fcdc 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java @@ -34,7 +34,6 @@ 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 @@ private ProtocolSpec mockProtocolSpec() { when(protocolSpec.getMiningBeneficiaryCalculator()) .thenReturn(mock(MiningBeneficiaryCalculator.class)); when(protocolSpec.isSkipZeroBlockRewards()).thenReturn(true); - BlockHashProcessor blockHashProcessor = mock(BlockHashProcessor.class); - when(protocolSpec.getBlockHashProcessor()).thenReturn(blockHashProcessor); return protocolSpec; } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java index 87fe348d9d0..8ef178559a9 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java @@ -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 @@ void setUp() { @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 @@ void shouldStoreParentBlockHash() { 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 @@ void shouldNotStoreBlockHashForGenesisBlock() { 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 @@ void shouldStoreAncestorBlockHashesAtForkCorrectlyParentIsGenesis() { 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 @@ void shouldWriteGenesisHashAtSlot0() { .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; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java index b5fab977fcd..9ea4219a1ac 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java @@ -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.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.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 @@ void setUp() { 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 @@ void shouldGetHashOfImmediateParent() { } @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 @@ void shouldReturnEmptyHashWhenParentBlockNotOnchain() { 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 @@ void shouldCacheBlockHashesWhileIteratingBackToPreviousHeader() { } private void assertHashForBlockNumber(final int blockNumber) { - Assertions.assertThat(lookup.apply(messageFrame, (long) blockNumber)) + Assertions.assertThat(lookup.apply((long) blockNumber)) .isEqualTo(headers[blockNumber].getHash()); } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index f889ec77e5f..9e322c61d08 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -29,6 +29,7 @@ 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 void run() { .blockValues(blockHeader) .completer(c -> {}) .miningBeneficiary(blockHeader.getCoinbase()) - .blockHashLookup( - protocolSpec - .getBlockHashProcessor() - .getBlockHashLookup(blockHeader, component.getBlockchain())) + .blockHashLookup(new CachingBlockHashLookup(blockHeader, component.getBlockchain())) .accessListWarmAddresses(addressList) .build(); Deque messageFrameStack = initialMessageFrame.getMessageFrameStack(); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java index 8a1444f0f59..3e1b0270a0b 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java @@ -32,13 +32,10 @@ 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 @@ private void traceTestSpecs(final String test, final List { - 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, diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index 158e7bc1bcc..e5d3e2c0b9f 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -47,11 +47,9 @@ 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 @@ static T8nResult runTest( 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, diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java index ae02ba3d6b6..8c68295993e 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java @@ -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) diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java index ceb54bd3299..20cc4710dcc 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java @@ -106,9 +106,6 @@ private static ProtocolSpec protocolSpec(final String name) { // 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 static void executeTest(final GeneralStateTestCaseEipSpec spec) { blockHeader, transaction, blockHeader.getCoinbase(), - protocolSpec.getBlockHashProcessor().getBlockHashLookup(blockHeader, blockchain), + new CachingBlockHashLookup(blockHeader, blockchain), false, TransactionValidationParams.processingBlock(), blobGasPrice); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java index 71d003c94cf..087038d52f4 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java @@ -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> versionedHashes = Optional.empty(); private OperationTracer tracer = OperationTracer.NO_TRACING; private boolean requireDeposit = true; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java index 52d09c78fce..9b6f4884c6e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java @@ -16,7 +16,6 @@ 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.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 static class Builder { private Optional> 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 diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java index ffe25ce80fd..0808841c8e7 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java @@ -392,7 +392,7 @@ public long getBalanceOperationGasCost() { } @Override - public long getBlockHashOperationGasCost(final MessageFrame frame) { + public long getBlockHashOperationGasCost() { return BLOCKHASH_OPERATION_GAS_COST; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java index 6e8ff5c9106..7a3f57c81dd 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java @@ -345,10 +345,9 @@ default long authCallOperationGasCost( /** * 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}. diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java index e37effcd515..9dde4bdb66a 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java @@ -21,8 +21,6 @@ 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 long authCallOperationGasCost( 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()); - } - } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java index 7905f815639..019e1a7237e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/BlockHashOperation.java @@ -16,27 +16,29 @@ 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. * - *

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. + *

Arg is the current block number. The Result is the Hash, which may be zero based on lookup + * rules. */ - public interface BlockHashLookup extends BiFunction {} + public interface BlockHashLookup extends Function {} + + /** 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 interface BlockHashLookup extends BiFunction {} * @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; } } diff --git a/evm/src/test/java/org/hyperledger/besu/evm/code/CodeV0Test.java b/evm/src/test/java/org/hyperledger/besu/evm/code/CodeV0Test.java index 1e99caebbe3..36416329d12 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/code/CodeV0Test.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/code/CodeV0Test.java @@ -97,7 +97,7 @@ private MessageFrame createJumpFrame(final CodeV0 getsCached) { .blockValues(mock(BlockValues.class)) .completer(f -> {}) .miningBeneficiary(Address.ZERO) - .blockHashLookup((f, n) -> Hash.EMPTY) + .blockHashLookup(l -> Hash.EMPTY) .build(); frame.setPC(CURRENT_PC); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java index 47c4e4a596f..97a2a4b8367 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java @@ -188,7 +188,7 @@ void giantExecuteStack() { .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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/frame/MessageFrameTest.java b/evm/src/test/java/org/hyperledger/besu/evm/frame/MessageFrameTest.java index 4a5b1fb8b9e..b41883f2a9c 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/frame/MessageFrameTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/frame/MessageFrameTest.java @@ -48,7 +48,7 @@ void setUp() { .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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java index e7eb6a6091b..2ba4ea918f2 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java @@ -169,7 +169,7 @@ private void executeOperation(final Bytes contract, final EVM evm) { .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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java index f21378510f7..d19e94e0a62 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/BlockHashOperationTest.java @@ -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 @@ 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( diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java index 122b7f8320a..6298aa245a7 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/Create2OperationTest.java @@ -155,7 +155,7 @@ public void setUp(final String sender, final String salt, final String code) { .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 @@ private MessageFrame testMemoryFrame(final UInt256 memoryOffset, final UInt256 m .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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java index 089cc810bc7..f1de36cc563 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/CreateOperationTest.java @@ -289,7 +289,7 @@ private MessageFrame testMemoryFrame( .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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java index 62c338bc8a1..66598ab5c7d 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/SelfDestructOperationTest.java @@ -82,7 +82,7 @@ void checkContractDeletionCommon( .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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java b/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java index 61934b3b40a..458f0c95587 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/precompile/Benchmarks.java @@ -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) diff --git a/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java b/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java index 90a4e24539e..fb4f56dbeac 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/testutils/TestMessageFrameBuilder.java @@ -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.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 MessageFrame build() { .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); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java index d463fa6488c..4fc4d6bf6c7 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/toy/EvmToyCommand.java @@ -190,7 +190,7 @@ public void run() { .blockValues(new ToyBlockValues()) .completer(c -> {}) .miningBeneficiary(Address.ZERO) - .blockHashLookup((f, n) -> null) + .blockHashLookup(n -> null) .build(); final MessageCallProcessor mcp = new MessageCallProcessor(evm, precompileContractRegistry);