diff --git a/CHANGELOG.md b/CHANGELOG.md index 59a45cb751b..2851dfa57e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ and in case a rollback is needed, before installing a previous version, the migr - "Big-EOF" (the EOF version initially slotted for Shanghai) has been moved from Cancun to FutureEIPs [#5429](https://github.com/hyperledger/besu/pull/5429) - EIP-4844: Zero blob transactions are invalid [#5425](https://github.com/hyperledger/besu/pull/5425) - Transaction pool flag to disable specific behaviors for locally submitted transactions [#5418](https://github.com/hyperledger/besu/pull/5418) +- Added In-Protocol Deposit prototype (EIP-6110) in the experimental eip. [#5005](https://github.com/hyperledger/besu/pull/5055) [#5295](https://github.com/hyperledger/besu/pull/5295) - New optional feature to save the txpool content to file on shutdown and reloading it on startup [#5434](https://github.com/hyperledger/besu/pull/5434) - New option to send SNI header in TLS ClientHello message [#5439](https://github.com/hyperledger/besu/pull/5439) - Early access - layered transaction pool implementation [#5290](https://github.com/hyperledger/besu/pull/5290) diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineEip6110AcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineEip6110AcceptanceTest.java new file mode 100644 index 00000000000..d1771ac5990 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/ExecutionEngineEip6110AcceptanceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.acceptance.jsonrpc; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class ExecutionEngineEip6110AcceptanceTest extends AbstractJsonRpcTest { + private static final String GENESIS_FILE = "/jsonrpc/engine/eip6110/genesis.json"; + private static final String TEST_CASE_PATH = "/jsonrpc/engine/eip6110/test-cases/"; + + private static JsonRpcTestsContext testsContext; + + public ExecutionEngineEip6110AcceptanceTest(final String ignored, final URI testCaseFileURI) { + super(ignored, testsContext, testCaseFileURI); + } + + @BeforeClass + public static void init() throws IOException { + testsContext = new JsonRpcTestsContext(GENESIS_FILE); + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable testCases() throws URISyntaxException { + return testCases(TEST_CASE_PATH); + } + + @AfterClass + public static void tearDown() { + testsContext.cluster.close(); + } +} diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/genesis.json new file mode 100644 index 00000000000..b6a16b71a40 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/genesis.json @@ -0,0 +1,38 @@ +{ + "config": { + "chainId":1, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "terminalTotalDifficulty":0, + "shanghaiTime":0, + "experimentalEipsTime":20, + "clique": { + "period": 5, + "epoch": 30000 + }, + "depositContractAddress": "0x00000000219ab540356cbb839cbe05303d7705fa" + }, + "nonce":"0x42", + "timestamp":"0x0", + "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit":"0x1C9C380", + "difficulty":"0x400000000", + "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase":"0x0000000000000000000000000000000000000000", + "alloc":{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"} + }, + "number":"0x0", + "gasUsed":"0x0", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas":"0x7" +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/01_shanghai_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/01_shanghai_prepare_payload.json new file mode 100644 index 00000000000..960194fcae0 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/01_shanghai_prepare_payload.json @@ -0,0 +1,46 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "safeBlockHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x10", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "validationError": null + }, + "payloadId": "0x0065bd1bbeaff359" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/02_shanghai_getPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/02_shanghai_getPayloadV2.json new file mode 100644 index 00000000000..9d25e3f5e84 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/02_shanghai_getPayloadV2.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV2", + "params": [ + "0x0065bd1bbeaff359" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "executionPayload": { + "parentHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xc8c8e840369eac89a610bfe2ec21fcdee4c9c43bec4876f0129fcd4b5311f6dd", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ], + "deposits": null, + "blockNumber": "0x1", + "blockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "blockValue": "0x0" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/03_shanghai_newPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/03_shanghai_newPayloadV2.json new file mode 100644 index 00000000000..938362327ba --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/03_shanghai_newPayloadV2.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xfe950635b1bd2a416ff6283b0bbd30176e1b1125ad06fa729da9f3f4c1c61710", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0xc8c8e840369eac89a610bfe2ec21fcdee4c9c43bec4876f0129fcd4b5311f6dd", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x10", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x3" + }, + { + "index": "0x1", + "validatorIndex": "0x1", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x4" + } + ], + "blockNumber": "0x1", + "blockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/04_shanghai_forkchoiceUpdatedV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/04_shanghai_forkchoiceUpdatedV2.json new file mode 100644 index 00000000000..871832b9c99 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/04_shanghai_forkchoiceUpdatedV2.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "safeBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "finalizedBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13" + }, + null + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "validationError": null + }, + "payloadId": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/05_eip6110_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/05_eip6110_prepare_payload.json new file mode 100644 index 00000000000..d3d7ee37e30 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/05_eip6110_prepare_payload.json @@ -0,0 +1,46 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_forkchoiceUpdatedV2", + "params": [ + { + "headBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "safeBlockHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "timestamp": "0x20", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ] + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "payloadStatus": { + "status": "VALID", + "latestValidHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "validationError": null + }, + "payloadId": "0x0065bd63871ad606" + } + }, + "statusCode" : 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/06_eip6110_get_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/06_eip6110_get_payload.json new file mode 100644 index 00000000000..89b7cf65b2e --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/06_eip6110_get_payload.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_getPayloadV2", + "params": [ + "0x0065bd63871ad606" + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "executionPayload": { + "parentHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x21395692fae33414143728c9ffc0aed8dcc76eb6731dd0f5a3239977478ca969", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x20", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits" : [], + "blockNumber": "0x2", + "blockHash": "0x58ea3e01b03ac17c68ed3e3d724a021408273fac8a86f42cb30a26be8e93fbe9", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "blockValue": "0x0" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/07_eip6110_invalid_null_deposits_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/07_eip6110_invalid_null_deposits_execute_payload.json new file mode 100644 index 00000000000..ebdd0ad81c2 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/07_eip6110_invalid_null_deposits_execute_payload.json @@ -0,0 +1,49 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0x4f88d512a0045bc6d447ba74a18eac0ed2ebb8d9faca325f5f55b2ca84be0705", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x1a10dba514dc4faff7ec13edd9b5ef653c1cd14eb26608bfc2b37717730a55a4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x20", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits": null, + "blockNumber": "0x3", + "blockHash": "0x1475ca311179652e44b10b7e2d7b72f3708f3201f8d729880a83f3eb397910e8", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "error": { + "code": -32602, + "message": "Invalid params" + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/08_eip6110_execute_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/08_eip6110_execute_payload.json new file mode 100644 index 00000000000..6fe5f5a5640 --- /dev/null +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/eip6110/test-cases/08_eip6110_execute_payload.json @@ -0,0 +1,50 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "engine_newPayloadV2", + "params": [ + { + "parentHash": "0xfdd94e3620a88f08927bffb318981a36b663a26e6fd62ab273eb800b90723c13", + "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "stateRoot": "0x21395692fae33414143728c9ffc0aed8dcc76eb6731dd0f5a3239977478ca969", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "gasUsed": "0x0", + "timestamp": "0x20", + "extraData": "0x", + "baseFeePerGas": "0x7", + "transactions": [], + "withdrawals": [ + { + "index": "0x0", + "validatorIndex": "0x0", + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "amount": "0x1" + }, + { + "index": "0x1", + "validatorIndex": "0x0", + "address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", + "amount": "0x2" + } + ], + "deposits": [], + "blockNumber": "0x2", + "blockHash": "0xdfdf57a09e352c38bb2873c5fd7d0d199481c6e13661c4a004d116417377b2e5", + "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } + ], + "id": 67 + }, + "response": { + "jsonrpc": "2.0", + "id": 67, + "result": { + "status": "VALID", + "latestValidHash": "0xdfdf57a09e352c38bb2873c5fd7d0d199481c6e13661c4a004d116417377b2e5", + "validationError": null + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json index 98a1201c9aa..085b69a1dd5 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/paris/genesis.json @@ -12,12 +12,11 @@ "muirGlacierBlock":0, "berlinBlock":0, "londonBlock":0, - "shanghaiTime":10, + "terminalTotalDifficulty":0, "clique": { "period": 5, "epoch": 30000 - }, - "terminalTotalDifficulty":0 + } }, "nonce":"0x42", "timestamp":"0x0", diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json index 9e9ecaeabe3..6b596fee607 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/genesis.json @@ -12,12 +12,12 @@ "muirGlacierBlock":0, "berlinBlock":0, "londonBlock":0, + "terminalTotalDifficulty":0, "shanghaiTime":10, "clique": { "period": 5, "epoch": 30000 - }, - "terminalTotalDifficulty":0 + } }, "nonce":"0x42", "timestamp":"0x0", @@ -35,20 +35,6 @@ "storage" : { } }, - "0x0000000000000000000000000000000000000200" : { - "balance" : "0x00", - "code" : "0x5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f17171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171760019055", - "nonce" : "0x00", - "storage" : { - } - }, - "0x0000000000000000000000000000000000000300" : { - "balance" : "0x00", - "code" : "0x5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f", - "nonce" : "0x00", - "storage" : { - } - }, "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "0x00", "code" : "0x6000806000806000803560601c620186a0f160005560018055", diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json index 0963be92f92..314dbd2e4e4 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/01_paris_prepare_payload.json @@ -4,7 +4,7 @@ "method": "engine_forkchoiceUpdatedV1", "params": [ { - "headBlockHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "headBlockHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", "safeBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, @@ -22,10 +22,10 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "latestValidHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", "validationError": null }, - "payloadId": "0x0065bd0f33f00bfb" + "payloadId": "0x0065bd3490dd4505" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json index 139f6b4849d..9a6d96f884a 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/02_paris_getPayloadV1.json @@ -3,7 +3,7 @@ "jsonrpc": "2.0", "method": "engine_getPayloadV1", "params": [ - "0x0065bd0f33f00bfb" + "0x0065bd3490dd4505" ], "id": 67 }, @@ -11,9 +11,9 @@ "jsonrpc": "2.0", "id": 67, "result": { - "parentHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "parentHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0x5afd1528d9c9051e96a41fd77be366428a9fd6ea0bd6670720c1ff32c9484b47", + "stateRoot": "0xbe4b5fae64ef4f22db6639c62b4ce120f3d4adda1bc536d317d1ada680b574ef", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -23,7 +23,7 @@ "timestamp": "0x5", "extraData": "0x", "baseFeePerGas": "0x7", - "blockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "blockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "transactions": [] } }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json index 8fbe4d9039b..6f7bc724f22 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/03_paris_newPayloadV1.json @@ -4,9 +4,9 @@ "method": "engine_newPayloadV1", "params": [ { - "parentHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e", + "parentHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0x5afd1528d9c9051e96a41fd77be366428a9fd6ea0bd6670720c1ff32c9484b47", + "stateRoot": "0xbe4b5fae64ef4f22db6639c62b4ce120f3d4adda1bc536d317d1ada680b574ef", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -16,7 +16,7 @@ "timestamp": "0x5", "extraData": "0x", "baseFeePerGas": "0x7", - "blockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "blockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "transactions": [] } ], @@ -27,7 +27,7 @@ "id": 67, "result": { "status": "VALID", - "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "validationError": null } }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json index 92833b37c4e..1bba4a092a3 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/04_paris_forkchoiceUpdatedV1.json @@ -4,9 +4,9 @@ "method": "engine_forkchoiceUpdatedV1", "params": [ { - "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", - "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", - "finalizedBlockHash": "0x7de476d27c2977a4f04c6cd29f7b8a26444c3a8efbc339ce24a9150e0f6ecb6e" + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "finalizedBlockHash": "0x274b386b1b268ebb5ca1f717c1279a536faf1f74dda959143dd8a779f8d8a908" }, null ], @@ -18,7 +18,7 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "validationError": null }, "payloadId": null diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json index f6da7401ad6..ac5947c79be 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/05_shanghai_prepare_payload_invalid_null_withdrawals.json @@ -4,8 +4,8 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", - "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json index caf4fe3ebdd..456a9a74264 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/06_shanghai_prepare_payload.json @@ -4,8 +4,8 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", - "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { @@ -36,10 +36,10 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "validationError": null }, - "payloadId": "0x0065bd547ba05c59" + "payloadId": "0x0065bd2db6663f59" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json index 457a3452794..dcb022e1a62 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/07_shanghai_prepare_payload_replay_different_withdrawals.json @@ -4,8 +4,8 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", - "safeBlockHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "headBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", + "safeBlockHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000" }, { @@ -36,10 +36,10 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "latestValidHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "validationError": null }, - "payloadId": "0x0065bd547ba05dd9" + "payloadId": "0x0065bd2db6663ed9" } }, "statusCode" : 200 diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json index 1d1ad35eba0..2da9be48f4e 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/08_shanghai_getPayloadV2.json @@ -3,7 +3,7 @@ "jsonrpc": "2.0", "method": "engine_getPayloadV2", "params": [ - "0x0065bd547ba05dd9" + "0x0065bd2db6663ed9" ], "id": 67 }, @@ -12,9 +12,9 @@ "id": 67, "result": { "executionPayload": { - "parentHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "parentHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0xb478b6884d890760bb1abc5e0c4df9973df70c39f32c8e7a9e7d11cf4b0a0c7e", + "stateRoot": "0xa61c2a422a4f7d7d7f456c1a83d5484eaf0d49e2b6b6d5716f875e782c66a9f0", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -37,8 +37,9 @@ "amount": "0x2" } ], + "deposits": null, "blockNumber": "0x2", - "blockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "blockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" }, "blockValue": "0x0" diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json index 25cd2b295a2..b682b05c369 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/09_shanghai_newPayloadV2_invalid_null_withdrawals.json @@ -4,9 +4,9 @@ "method": "engine_newPayloadV2", "params": [ { - "parentHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "parentHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0xb478b6884d890760bb1abc5e0c4df9973df70c39f32c8e7a9e7d11cf4b0a0c7e", + "stateRoot": "0xa61c2a422a4f7d7d7f456c1a83d5484eaf0d49e2b6b6d5716f875e782c66a9f0", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -17,7 +17,7 @@ "transactions": [], "withdrawals": null, "blockNumber": "0x2", - "blockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "blockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" } ], diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json index 3b68eba4b63..f17a98a5631 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/10_shanghai_newPayloadV2.json @@ -4,9 +4,9 @@ "method": "engine_newPayloadV2", "params": [ { - "parentHash": "0x9392d866ef80eb0d7a1700362326e3396cc9550b757bda2191548fb1447f5d26", + "parentHash": "0xf4a1d287dd3bb7e877c57476912e6a6052bc4eed8ea70d032b55d77f26ee985f", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0xb478b6884d890760bb1abc5e0c4df9973df70c39f32c8e7a9e7d11cf4b0a0c7e", + "stateRoot": "0xa61c2a422a4f7d7d7f456c1a83d5484eaf0d49e2b6b6d5716f875e782c66a9f0", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -30,7 +30,7 @@ } ], "blockNumber": "0x2", - "blockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "blockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" } ], @@ -41,7 +41,7 @@ "id": 67, "result": { "status": "VALID", - "latestValidHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "latestValidHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", "validationError": null } }, diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json index 3c2bfc96a2a..938372b0ce6 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/11_shanghai_forkchoiceUpdatedV2.json @@ -4,9 +4,9 @@ "method": "engine_forkchoiceUpdatedV2", "params": [ { - "headBlockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", - "safeBlockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", - "finalizedBlockHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8" + "headBlockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "safeBlockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", + "finalizedBlockHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20" }, null ], @@ -18,7 +18,7 @@ "result": { "payloadStatus": { "status": "VALID", - "latestValidHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "latestValidHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", "validationError": null }, "payloadId": null diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json index 1a3e8fcdb92..788aad210b8 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/shanghai/test-cases/14_shanghai_newPayloadV2_push0_tx.json @@ -4,9 +4,9 @@ "method": "engine_newPayloadV2", "params": [ { - "parentHash": "0xa6df103af38454a1b423d1d66444a60be92bc0b2dd9c4f0977b4d8a840cc20d8", + "parentHash": "0x612abd8615f544759d4aeb3dbab32f5f198a8b818e9c5436e9f7a674ef3b0f20", "feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "stateRoot": "0x4705976c675e1e7bd50e8a13aab940a35f805475a5f74d0394801ae1151e7521", + "stateRoot": "0xf8e89cc49d51d0bbbfd75fe214712e04f3b70e7c447261a2290262a8e1c4d0e1", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x1c9c380", @@ -19,7 +19,7 @@ ], "withdrawals": [], "blockNumber": "0x3", - "blockHash": "0x3aa97e152d34227654a4bab1bd5018fcebb06acb82b2af2754a3a98eff3a03cb", + "blockHash": "0x85a4410f70b315e85382c7def115df2742348734f14c91bfbad0f2c67e9de4a2", "receiptsRoot": "0x1668c1a230c3e0aaa4c52af3bada02571dabb4e1743ebd6eaf4bbe8008e8cc3e" } ], @@ -30,7 +30,7 @@ "id": 67, "result": { "status": "VALID", - "latestValidHash": "0x3aa97e152d34227654a4bab1bd5018fcebb06acb82b2af2754a3a98eff3a03cb", + "latestValidHash": "0x85a4410f70b315e85382c7def115df2742348734f14c91bfbad0f2c67e9de4a2", "validationError": null } }, diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 656d39b01e0..aed7e9cb8bb 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -124,7 +124,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides () -> Optional.ofNullable(genesisConfig) .map(conf -> conf.getConfigOptions(genesisConfigOverrides)) - .orElseGet(genesisConfig::getConfigOptions); + .orElseThrow(); /** The Sync config. */ protected SynchronizerConfiguration syncConfig; diff --git a/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java index 7760efb6811..3ff13a472f2 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.consensus.merge.PostMergeContext; import org.hyperledger.besu.consensus.merge.TransitionBestPeerComparator; import org.hyperledger.besu.consensus.merge.blockcreation.MergeCoordinator; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; @@ -162,6 +163,10 @@ protected MiningCoordinator createTransitionMiningCoordinator( final ExecutorService blockBuilderExecutor = MonitoredExecutors.newSingleThreadExecutor("PoS-Block-Builder", metricsSystem); + final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get(); + final Optional
depositContractAddress = + genesisConfigOptions.getDepositContractAddress(); + return new MergeCoordinator( protocolContext, protocolSchedule, @@ -171,7 +176,8 @@ protected MiningCoordinator createTransitionMiningCoordinator( }, transactionPool.getPendingTransactions(), miningParameters, - backwardSyncContext); + backwardSyncContext, + depositContractAddress); } @Override diff --git a/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java index 1ee211be808..4e1d87f4a68 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -103,7 +104,7 @@ public void mustCreateCombinedProtocolScheduleUsingProtocolSchedulesOrderedByBlo final StubGenesisConfigOptions genesisConfigOptions = new StubGenesisConfigOptions(); genesisConfigOptions.chainId(BigInteger.TEN); - when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); + when(genesisConfigFile.getConfigOptions(anyMap())).thenReturn(genesisConfigOptions); final ConsensusScheduleBesuControllerBuilder consensusScheduleBesuControllerBuilder = new ConsensusScheduleBesuControllerBuilder( diff --git a/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java index be1c9382b21..9fc337095f2 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; +import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.consensus.clique.BlockHeaderValidationRulesetFactory; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.common.EpochManager; @@ -53,7 +54,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; /** @@ -73,10 +73,10 @@ public class TransitionControllerBuilderTest { @Mock PostMergeContext mergeContext; StorageProvider storageProvider = new InMemoryKeyValueStorageProvider(); - @Spy CliqueBesuControllerBuilder cliqueBuilder = new CliqueBesuControllerBuilder(); - @Spy BesuControllerBuilder powBuilder = new MainnetBesuControllerBuilder(); - @Spy MergeBesuControllerBuilder postMergeBuilder = new MergeBesuControllerBuilder(); - @Spy MiningParameters miningParameters = new MiningParameters.Builder().build(); + CliqueBesuControllerBuilder cliqueBuilder = new CliqueBesuControllerBuilder(); + BesuControllerBuilder powBuilder = new MainnetBesuControllerBuilder(); + MergeBesuControllerBuilder postMergeBuilder = new MergeBesuControllerBuilder(); + MiningParameters miningParameters; TransitionProtocolSchedule transitionProtocolSchedule; @@ -88,6 +88,9 @@ public void setup() { preMergeProtocolSchedule, postMergeProtocolSchedule, mergeContext)); transitionProtocolSchedule.setProtocolContext(protocolContext); cliqueBuilder.nodeKey(NodeKeyUtils.generate()); + cliqueBuilder.genesisConfigFile(GenesisConfigFile.DEFAULT); + powBuilder.genesisConfigFile(GenesisConfigFile.DEFAULT); + postMergeBuilder.genesisConfigFile(GenesisConfigFile.DEFAULT); postMergeBuilder.storageProvider(storageProvider); when(protocolContext.getBlockchain()).thenReturn(mockBlockchain); when(transitionProtocolSchedule.getPostMergeSchedule()).thenReturn(postMergeProtocolSchedule); @@ -96,6 +99,7 @@ public void setup() { .thenReturn(mock(CliqueContext.class)); when(protocolContext.getConsensusContext(PostMergeContext.class)).thenReturn(mergeContext); when(protocolContext.getConsensusContext(MergeContext.class)).thenReturn(mergeContext); + miningParameters = new MiningParameters.Builder().miningEnabled(false).build(); } @Test @@ -114,7 +118,7 @@ public void assertPoWIsNotMiningPreMerge() { @Test public void assertPowMiningPreMerge() { - when(miningParameters.isMiningEnabled()).thenReturn(Boolean.TRUE); + miningParameters = new MiningParameters.Builder().miningEnabled(true).build(); var transCoordinator = buildTransitionCoordinator(powBuilder, postMergeBuilder); assertThat(transCoordinator.isMiningBeforeMerge()).isTrue(); } @@ -239,6 +243,7 @@ void assertDetachedRulesForPostMergeBlocks(final BlockHeaderValidator validator) TransitionCoordinator buildTransitionCoordinator( final BesuControllerBuilder preMerge, final MergeBesuControllerBuilder postMerge) { var builder = new TransitionBesuControllerBuilder(preMerge, postMerge); + builder.genesisConfigFile(GenesisConfigFile.mainnet()); builder.storageProvider(storageProvider); builder.metricsSystem(new NoOpMetricsSystem()); var coordinator = diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index d5acee99fb4..41f385fc4f5 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.config; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -494,4 +495,12 @@ default boolean isConsensusMigration() { * @return true, if you want the next block to use zero for the base fee. */ boolean isZeroBaseFee(); + + /** + * The deposit contract address that should be in the logger field in Receipt of Deposit + * transaction + * + * @return the deposit address + */ + Optional
getDepositContractAddress(); } diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 7db62667776..f9cf0696290 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -17,6 +17,7 @@ import static java.util.Collections.emptyMap; import static java.util.Objects.isNull; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -47,6 +48,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { private static final String DISCOVERY_CONFIG_KEY = "discovery"; private static final String CHECKPOINT_CONFIG_KEY = "checkpoint"; private static final String ZERO_BASE_FEE_KEY = "zerobasefee"; + private static final String DEPOSIT_CONTRACT_ADDRESS_KEY = "depositcontractaddress"; private final ObjectNode configRoot; private final Map configOverrides = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -418,6 +420,12 @@ public boolean isZeroBaseFee() { return getOptionalBoolean(ZERO_BASE_FEE_KEY).orElse(false); } + @Override + public Optional
getDepositContractAddress() { + Optional inputAddress = JsonUtil.getString(configRoot, DEPOSIT_CONTRACT_ADDRESS_KEY); + return inputAddress.map(Address::fromHexString); + } + @Override public Map asMap() { final ImmutableMap.Builder builder = ImmutableMap.builder(); @@ -462,6 +470,8 @@ public Map asMap() { getEvmStackSize().ifPresent(l -> builder.put("evmstacksize", l)); getEcip1017EraRounds().ifPresent(l -> builder.put("ecip1017EraRounds", l)); + getDepositContractAddress().ifPresent(l -> builder.put("depositContractAddress", l)); + if (isClique()) { builder.put("clique", getCliqueConfigOptions().asMap()); } diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 0288392545f..949205e9b04 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.config; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -371,6 +372,7 @@ public Map asMap() { getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l)); getEvmStackSize().ifPresent(l -> builder.put("evmStackSize", l)); + getDepositContractAddress().ifPresent(l -> builder.put("depositContractAddress", l)); if (isClique()) { builder.put("clique", getCliqueConfigOptions().asMap()); } @@ -423,6 +425,11 @@ public List getForkBlockTimestamps() { return Collections.emptyList(); } + @Override + public Optional
getDepositContractAddress() { + return Optional.empty(); + } + /** * Homestead block stub genesis config options. * diff --git a/config/src/main/resources/experimental.json b/config/src/main/resources/experimental.json index f73b46d84ee..43eff251000 100644 --- a/config/src/main/resources/experimental.json +++ b/config/src/main/resources/experimental.json @@ -10,7 +10,8 @@ "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "number": 0, "totalDifficulty": "0x0" - } + }, + "depositContractAddress": "0x00000000219ab540356cbb839cbe05303d7705fa" }, "nonce": "0x42", "timestamp": "0x0", diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java index 9e60a40db80..a775c78e301 100644 --- a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java @@ -19,6 +19,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import org.hyperledger.besu.datatypes.Address; + import java.math.BigInteger; import java.util.HashMap; import java.util.Map; @@ -291,6 +293,30 @@ public void asMapIncludesZeroBaseFee() { assertThat(config.asMap()).containsOnlyKeys("zeroBaseFee").containsValue(true); } + @Test + public void shouldGetDepositContractAddress() { + final GenesisConfigOptions config = + fromConfigOptions( + singletonMap("depositContractAddress", "0x00000000219ab540356cbb839cbe05303d7705fa")); + assertThat(config.getDepositContractAddress()) + .hasValue(Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa")); + } + + @Test + public void shouldNotHaveDepositContractAddressWhenEmpty() { + final GenesisConfigOptions config = fromConfigOptions(emptyMap()); + assertThat(config.getDepositContractAddress()).isEmpty(); + } + + @Test + public void asMapIncludesDepositContractAddress() { + final GenesisConfigOptions config = fromConfigOptions(Map.of("depositContractAddress", "0x0")); + + assertThat(config.asMap()) + .containsOnlyKeys("depositContractAddress") + .containsValue(Address.ZERO); + } + private GenesisConfigOptions fromConfigOptions(final Map configOptions) { final ObjectNode rootNode = JsonUtil.createEmptyObjectNode(); final ObjectNode options = JsonUtil.objectNodeFromMap(configOptions); diff --git a/config/src/test/resources/valid_config_with_custom_forks.json b/config/src/test/resources/valid_config_with_custom_forks.json index dd31babf8bc..b3853086c6f 100644 --- a/config/src/test/resources/valid_config_with_custom_forks.json +++ b/config/src/test/resources/valid_config_with_custom_forks.json @@ -6,6 +6,7 @@ "byzantiumBlock": 1035301, "londonBlock": 2222222, "zeroBaseFee": true, + "depositContractAddress": "0x00000000219ab540356cbb839cbe05303d7705fa", "ibft2": { "blockperiodseconds": 2, "epochlength": 30000, diff --git a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java index 861b7aad061..97bc962e6b7 100644 --- a/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java +++ b/consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java @@ -83,7 +83,8 @@ public CliqueBlockCreator( protocolSchedule, minTransactionGasPrice, minBlockOccupancyRatio, - parentHeader); + parentHeader, + Optional.empty()); this.nodeKey = nodeKey; this.epochManager = epochManager; } diff --git a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java index d83d92743ce..b1b374b69ff 100644 --- a/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java +++ b/consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreator.java @@ -76,7 +76,8 @@ public BftBlockCreator( protocolSchedule, minTransactionGasPrice, minBlockOccupancyRatio, - parentHeader); + parentHeader, + Optional.empty()); this.bftExtraDataCodec = bftExtraDataCodec; } diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java index 52f5900d375..21922727788 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeBlockCreator.java @@ -67,7 +67,8 @@ public MergeBlockCreator( final ProtocolSchedule protocolSchedule, final Wei minTransactionGasPrice, final Address miningBeneficiary, - final BlockHeader parentHeader) { + final BlockHeader parentHeader, + final Optional
depositContractAddress) { super( miningBeneficiary, __ -> miningBeneficiary, @@ -78,7 +79,8 @@ public MergeBlockCreator( protocolSchedule, minTransactionGasPrice, TRY_FILL_BLOCK, - parentHeader); + parentHeader, + depositContractAddress); } /** diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java index e069448d0ba..c1069fc6ce9 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java @@ -104,6 +104,7 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene * @param pendingTransactions the pending transactions * @param miningParams the mining params * @param backwardSyncContext the backward sync context + * @param depositContractAddress the address of the deposit contract */ public MergeCoordinator( final ProtocolContext protocolContext, @@ -111,7 +112,8 @@ public MergeCoordinator( final ProposalBuilderExecutor blockBuilderExecutor, final PendingTransactions pendingTransactions, final MiningParameters miningParams, - final BackwardSyncContext backwardSyncContext) { + final BackwardSyncContext backwardSyncContext, + final Optional
depositContractAddress) { this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; this.blockBuilderExecutor = blockBuilderExecutor; @@ -136,7 +138,8 @@ public MergeCoordinator( protocolSchedule, this.miningParameters.getMinTransactionGasPrice(), address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - parentHeader); + parentHeader, + depositContractAddress); this.backwardSyncContext.subscribeBadChainListener(this); } diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index eaf83c3cef3..6389a1677f3 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -206,7 +206,8 @@ public void setUp() { proposalBuilderExecutor, transactions, miningParameters, - backwardSyncContext); + backwardSyncContext, + Optional.empty()); } @Test @@ -255,7 +256,8 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid() protocolSchedule, this.miningParameters.getMinTransactionGasPrice(), address.or(miningParameters::getCoinbase).orElse(Address.ZERO), - parentHeader)); + parentHeader, + Optional.empty())); doCallRealMethod() .doCallRealMethod() @@ -656,7 +658,8 @@ public void shouldUseExtraDataFromMiningParameters() { proposalBuilderExecutor, transactions, miningParameters, - backwardSyncContext); + backwardSyncContext, + Optional.empty()); final PayloadIdentifier payloadId = this.coordinator.preparePayload( @@ -939,7 +942,8 @@ public void assertNonGenesisTerminalBlockSatisfiesDescendsFromTerminal() { CompletableFuture::runAsync, transactions, new MiningParameters.Builder().coinbase(coinbase).build(), - mock(BackwardSyncContext.class)); + mock(BackwardSyncContext.class), + Optional.empty()); var blockZero = mockHeaderBuilder.number(0L).difficulty(Difficulty.of(1336L)).buildHeader(); var blockOne = @@ -1000,7 +1004,8 @@ public void assertMergeAtGenesisSatisifiesTerminalPoW() { CompletableFuture::runAsync, transactions, new MiningParameters.Builder().coinbase(coinbase).build(), - mock(BackwardSyncContext.class)); + mock(BackwardSyncContext.class), + Optional.empty()); var blockZero = mockHeaderBuilder.number(0L).buildHeader(); var blockOne = mockHeaderBuilder.number(1L).parentHash(blockZero.getHash()).buildHeader(); @@ -1147,7 +1152,8 @@ MergeCoordinator terminalAncestorMock(final long chainDepth, final boolean hasTe CompletableFuture::runAsync, transactions, new MiningParameters.Builder().coinbase(coinbase).build(), - mock(BackwardSyncContext.class))); + mock(BackwardSyncContext.class), + Optional.empty())); return mockCoordinator; } diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java index e4a1d7a4144..2e5509cdf57 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java @@ -91,7 +91,8 @@ public void setUp() { CompletableFuture::runAsync, mockPendingTransactions, new MiningParameters.Builder().coinbase(coinbase).build(), - mock(BackwardSyncContext.class)); + mock(BackwardSyncContext.class), + Optional.empty()); mergeContext.setIsPostMerge(genesisState.getBlock().getHeader().getDifficulty()); blockchain.observeBlockAdded( blockAddedEvent -> diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index 62b918863f2..ba463759a69 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -20,6 +20,7 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID_BLOCK_HASH; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.SYNCING; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.DepositsValidatorProvider.getDepositsValidator; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.WithdrawalsValidatorProvider.getWithdrawalsValidator; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.INVALID_PARAMS; @@ -30,6 +31,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; @@ -41,6 +43,7 @@ import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Withdrawal; @@ -111,6 +114,15 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) return new JsonRpcErrorResponse(reqId, INVALID_PARAMS); } + final Optional> maybeDeposits = + Optional.ofNullable(blockParam.getDeposits()) + .map(ds -> ds.stream().map(DepositParameter::toDeposit).collect(toList())); + if (!getDepositsValidator( + protocolSchedule, blockParam.getTimestamp(), blockParam.getBlockNumber()) + .validateDepositParameter(maybeDeposits)) { + return new JsonRpcErrorResponse(reqId, INVALID_PARAMS); + } + if (mergeContext.get().isSyncing()) { LOG.debug("We are syncing"); return respondWith(reqId, blockParam, null, SYNCING); @@ -161,7 +173,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) 0, maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null), null, - null, + maybeDeposits.map(BodyValidation::depositsRoot).orElse(null), headerFunctions); // ensure the block hash matches the blockParam hash @@ -205,8 +217,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) final var block = new Block( newBlockHeader, - new BlockBody( - transactions, Collections.emptyList(), maybeWithdrawals, Optional.empty())); + new BlockBody(transactions, Collections.emptyList(), maybeWithdrawals, maybeDeposits)); if (maybeParentHeader.isEmpty()) { LOG.atDebug() @@ -340,6 +351,10 @@ private void logImportedBlockInfo(final Block block, final double timeInS) { message.append(" / %d ws"); messageArgs.add(block.getBody().getWithdrawals().get().size()); } + if (block.getBody().getDeposits().isPresent()) { + message.append(" / %d ds"); + messageArgs.add(block.getBody().getDeposits().get().size()); + } message.append(" / base fee %s / %,d (%01.1f%%) gas / (%s) in %01.3fs. Peers: %d"); messageArgs.addAll( List.of( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/DepositsValidatorProvider.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/DepositsValidatorProvider.java new file mode 100644 index 00000000000..36c29bd26a1 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/DepositsValidatorProvider.java @@ -0,0 +1,44 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; + +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.mainnet.DepositsValidator; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; + +import java.util.Optional; + +public class DepositsValidatorProvider { + + static DepositsValidator getDepositsValidator( + final ProtocolSchedule protocolSchedule, final long blockTimestamp, final long blockNumber) { + + final BlockHeader blockHeader = + BlockHeaderBuilder.createDefault() + .timestamp(blockTimestamp) + .number(blockNumber) + .buildBlockHeader(); + return getDepositsValidator(protocolSchedule.getByBlockHeader(blockHeader)); + } + + private static DepositsValidator getDepositsValidator(final ProtocolSpec protocolSchedule) { + return Optional.ofNullable(protocolSchedule) + .map(ProtocolSpec::getDepositsValidator) + .orElseGet(DepositsValidator.ProhibitedDeposits::new); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java index acfc4fee81a..c13bc0435fc 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java @@ -40,8 +40,8 @@ public class DepositParameter { @JsonCreator public DepositParameter( - @JsonProperty("pubKey") final String pubKey, - @JsonProperty("withdrawal_credentials") final String withdrawalCredentials, + @JsonProperty("pubkey") final String pubKey, + @JsonProperty("withdrawalCredentials") final String withdrawalCredentials, @JsonProperty("amount") final String amount, @JsonProperty("signature") final String signature, @JsonProperty("index") final String index) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java index d6e5923b539..13197d92b93 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java @@ -47,6 +47,7 @@ public class EnginePayloadParameter { private final LogsBloomFilter logsBloom; private final List transactions; private final List withdrawals; + private final List deposits; @JsonCreator public EnginePayloadParameter( @@ -64,7 +65,8 @@ public EnginePayloadParameter( @JsonProperty("logsBloom") final LogsBloomFilter logsBloom, @JsonProperty("prevRandao") final String prevRandao, @JsonProperty("transactions") final List transactions, - @JsonProperty("withdrawals") final List withdrawals) { + @JsonProperty("withdrawals") final List withdrawals, + @JsonProperty("deposits") final List deposits) { this.blockHash = blockHash; this.parentHash = parentHash; this.feeRecipient = feeRecipient; @@ -80,6 +82,7 @@ public EnginePayloadParameter( this.prevRandao = Bytes32.fromHexString(prevRandao); this.transactions = transactions; this.withdrawals = withdrawals; + this.deposits = deposits; } public Hash getBlockHash() { @@ -141,4 +144,8 @@ public List getTransactions() { public List getWithdrawals() { return withdrawals; } + + public List getDeposits() { + return deposits; + } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java index 2685f888a37..0b6d112dade 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java @@ -115,6 +115,7 @@ public EngineGetPayloadResultV2 payloadTransactionCompleteV2( blockWithReceipts.getHeader(), txs, blockWithReceipts.getBlock().getBody().getWithdrawals(), + blockWithReceipts.getBlock().getBody().getDeposits(), Quantity.create(blockValue)); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV2.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV2.java index e3919517f3b..b5e9fafabe2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV2.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV2.java @@ -14,8 +14,10 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Withdrawal; import java.util.List; @@ -39,8 +41,9 @@ public EngineGetPayloadResultV2( final BlockHeader header, final List transactions, final Optional> withdrawals, + final Optional> deposits, final String blockValue) { - this.executionPayload = new PayloadResult(header, transactions, withdrawals); + this.executionPayload = new PayloadResult(header, transactions, withdrawals, deposits); this.blockValue = blockValue; } @@ -71,11 +74,13 @@ public static class PayloadResult { private final String baseFeePerGas; protected final List transactions; private final List withdrawals; + private final List deposits; public PayloadResult( final BlockHeader header, final List transactions, - final Optional> withdrawals) { + final Optional> withdrawals, + final Optional> deposits) { this.blockNumber = Quantity.create(header.getNumber()); this.blockHash = header.getHash().toString(); this.parentHash = header.getParentHash().toString(); @@ -98,6 +103,11 @@ public PayloadResult( .map(WithdrawalParameter::fromWithdrawal) .collect(Collectors.toList())) .orElse(null); + this.deposits = + deposits + .map( + ds -> ds.stream().map(DepositParameter::fromDeposit).collect(Collectors.toList())) + .orElse(null); } @JsonGetter(value = "blockNumber") @@ -170,6 +180,11 @@ public List getWithdrawals() { return withdrawals; } + @JsonGetter(value = "deposits") + public List getDeposits() { + return deposits; + } + @JsonGetter(value = "feeRecipient") @JsonInclude(JsonInclude.Include.NON_NULL) public String getFeeRecipient() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV6110.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV6110.java deleted file mode 100644 index 75d3e4bbe26..00000000000 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV6110.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright contributors to Hyperledger Besu - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; - -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.Deposit; -import org.hyperledger.besu.ethereum.core.Withdrawal; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import org.apache.tuweni.bytes.Bytes32; - -@JsonPropertyOrder({ - "executionPayload", - "blockValue", -}) -public class EngineGetPayloadResultV6110 { - protected final PayloadResult executionPayload; - private final String blockValue; - - public EngineGetPayloadResultV6110( - final BlockHeader header, - final List transactions, - final Optional> withdrawals, - final Optional> deposits, - final String blockValue) { - this.executionPayload = new PayloadResult(header, transactions, withdrawals, deposits); - this.blockValue = blockValue; - } - - @JsonGetter(value = "executionPayload") - public PayloadResult getExecutionPayload() { - return executionPayload; - } - - @JsonGetter(value = "blockValue") - public String getBlockValue() { - return blockValue; - } - - public static class PayloadResult { - - protected final String blockHash; - private final String parentHash; - private final String feeRecipient; - private final String stateRoot; - private final String receiptsRoot; - private final String logsBloom; - private final String prevRandao; - private final String blockNumber; - private final String gasLimit; - private final String gasUsed; - private final String timestamp; - private final String extraData; - private final String baseFeePerGas; - protected final List transactions; - private final List withdrawals; - - private final List deposits; - - public PayloadResult( - final BlockHeader header, - final List transactions, - final Optional> withdrawals, - final Optional> deposits) { - this.blockNumber = Quantity.create(header.getNumber()); - this.blockHash = header.getHash().toString(); - this.parentHash = header.getParentHash().toString(); - this.logsBloom = header.getLogsBloom().toString(); - this.stateRoot = header.getStateRoot().toString(); - this.receiptsRoot = header.getReceiptsRoot().toString(); - this.extraData = header.getExtraData().toString(); - this.baseFeePerGas = header.getBaseFee().map(Quantity::create).orElse(null); - this.gasLimit = Quantity.create(header.getGasLimit()); - this.gasUsed = Quantity.create(header.getGasUsed()); - this.timestamp = Quantity.create(header.getTimestamp()); - this.transactions = transactions; - this.feeRecipient = header.getCoinbase().toString(); - this.prevRandao = header.getPrevRandao().map(Bytes32::toHexString).orElse(null); - this.withdrawals = - withdrawals - .map( - ws -> - ws.stream() - .map(WithdrawalParameter::fromWithdrawal) - .collect(Collectors.toList())) - .orElse(null); - this.deposits = - deposits - .map( - ws -> ws.stream().map(DepositParameter::fromDeposit).collect(Collectors.toList())) - .orElse(null); - } - - @JsonGetter(value = "blockNumber") - public String getNumber() { - return blockNumber; - } - - @JsonGetter(value = "blockHash") - public String getHash() { - return blockHash; - } - - @JsonGetter(value = "parentHash") - public String getParentHash() { - return parentHash; - } - - @JsonGetter(value = "logsBloom") - public String getLogsBloom() { - return logsBloom; - } - - @JsonGetter(value = "prevRandao") - public String getPrevRandao() { - return prevRandao; - } - - @JsonGetter(value = "stateRoot") - public String getStateRoot() { - return stateRoot; - } - - @JsonGetter(value = "receiptsRoot") - public String getReceiptRoot() { - return receiptsRoot; - } - - @JsonGetter(value = "extraData") - public String getExtraData() { - return extraData; - } - - @JsonGetter(value = "baseFeePerGas") - public String getBaseFeePerGas() { - return baseFeePerGas; - } - - @JsonGetter(value = "gasLimit") - public String getGasLimit() { - return gasLimit; - } - - @JsonGetter(value = "gasUsed") - public String getGasUsed() { - return gasUsed; - } - - @JsonGetter(value = "timestamp") - public String getTimestamp() { - return timestamp; - } - - @JsonGetter(value = "transactions") - public List getTransactions() { - return transactions; - } - - @JsonGetter(value = "withdrawals") - public List getWithdrawals() { - return withdrawals; - } - - @JsonGetter(value = "deposits") - public List getDeposits() { - return deposits; - } - - @JsonGetter(value = "feeRecipient") - @JsonInclude(JsonInclude.Include.NON_NULL) - public String getFeeRecipient() { - return feeRecipient; - } - } -} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java index c66a408a86a..e31c96871b1 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java @@ -87,9 +87,20 @@ public AbstractEngineGetPayloadTest(final MethodFactory methodFactory) { Collections.emptyList(), Optional.of(Collections.emptyList()), Optional.empty())); + private static final Block mockBlockWithDeposits = + new Block( + mockHeader, + new BlockBody( + Collections.emptyList(), + Collections.emptyList(), + Optional.empty(), + Optional.of(Collections.emptyList()))); protected static final BlockWithReceipts mockBlockWithReceiptsAndWithdrawals = new BlockWithReceipts(mockBlockWithWithdrawals, Collections.emptyList()); + protected static final BlockWithReceipts mockBlockWithReceiptsAndDeposits = + new BlockWithReceipts(mockBlockWithDeposits, Collections.emptyList()); + @Mock private ProtocolContext protocolContext; @Mock protected MergeContext mergeContext; diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index bf5a6c6c04f..e8fb1409e4d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -19,6 +19,7 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.SYNCING; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameterTestFixture.DEPOSIT_PARAM_1; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameterTestFixture.WITHDRAWAL_PARAM_1; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.INVALID_PARAMS; import static org.mockito.ArgumentMatchers.any; @@ -31,6 +32,7 @@ import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.BlockProcessingOutputs; @@ -40,6 +42,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; @@ -54,9 +57,11 @@ import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; +import org.hyperledger.besu.ethereum.mainnet.DepositsValidator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.WithdrawalsValidator; @@ -102,6 +107,8 @@ public AbstractEngineNewPayloadTest(final MethodFactory methodFactory) { private static final Vertx vertx = Vertx.vertx(); private static final Hash mockHash = Hash.hash(Bytes32.fromHexStringLenient("0x1337deadbeef")); + private static final Address depositContractAddress = + Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); @Mock private ProtocolSpec protocolSpec; @Mock private ProtocolSchedule protocolSchedule; @@ -123,6 +130,8 @@ public void before() { when(protocolContext.getBlockchain()).thenReturn(blockchain); when(protocolSpec.getWithdrawalsValidator()) .thenReturn(new WithdrawalsValidator.ProhibitedWithdrawals()); + when(protocolSpec.getDepositsValidator()) + .thenReturn(new DepositsValidator.ProhibitedDeposits()); when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); when(ethPeers.peerCount()).thenReturn(1); this.method = @@ -143,6 +152,7 @@ public void shouldReturnValid() { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), + Optional.empty(), Optional.empty()); var resp = resp(mockPayload(mockHeader, Collections.emptyList())); @@ -153,7 +163,8 @@ public void shouldReturnValid() { @Test public void shouldReturnInvalidOnBlockExecutionError() { BlockHeader mockHeader = - setupValidPayload(new BlockProcessingResult("error 42"), Optional.empty()); + setupValidPayload( + new BlockProcessingResult("error 42"), Optional.empty(), Optional.empty()); var resp = resp(mockPayload(mockHeader, Collections.emptyList())); @@ -166,7 +177,7 @@ public void shouldReturnInvalidOnBlockExecutionError() { @Test public void shouldReturnAcceptedOnLatestValidAncestorEmpty() { - BlockHeader mockHeader = createBlockHeader(Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); @@ -201,7 +212,7 @@ public void shouldReturnSuccessOnAlreadyPresent() { @Test public void shouldReturnInvalidWithLatestValidHashIsABadBlock() { - BlockHeader mockHeader = createBlockHeader(Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); Hash latestValidHash = Hash.hash(Bytes32.fromHexStringLenient("0xcafebabe")); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); @@ -222,6 +233,7 @@ public void shouldNotReturnInvalidOnStorageException() { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.empty(), new StorageException("database bedlam")), + Optional.empty(), Optional.empty()); var resp = resp(mockPayload(mockHeader, Collections.emptyList())); @@ -237,6 +249,7 @@ public void shouldNotReturnInvalidOnHandledMerkleTrieException() { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.empty(), new MerkleTrieException("missing leaf")), + Optional.empty(), Optional.empty()); var resp = resp(mockPayload(mockHeader, Collections.emptyList())); @@ -249,7 +262,7 @@ public void shouldNotReturnInvalidOnHandledMerkleTrieException() { @Test public void shouldNotReturnInvalidOnThrownMerkleTrieException() { - BlockHeader mockHeader = createBlockHeader(Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); @@ -405,9 +418,10 @@ public void shouldReturnInvalidIfWithdrawalsIsNotNull_WhenWithdrawalsProhibited( var resp = resp( mockPayload( - createBlockHeader(Optional.of(Collections.emptyList())), + createBlockHeader(Optional.of(Collections.emptyList()), Optional.empty()), Collections.emptyList(), - withdrawals)); + withdrawals, + null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -422,9 +436,10 @@ public void shouldReturnValidIfWithdrawalsIsNull_WhenWithdrawalsProhibited() { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), + Optional.empty(), Optional.empty()); - var resp = resp(mockPayload(mockHeader, Collections.emptyList(), withdrawals)); + var resp = resp(mockPayload(mockHeader, Collections.emptyList(), withdrawals, null)); assertValidResponse(mockHeader, resp); } @@ -437,7 +452,11 @@ public void shouldReturnInvalidIfWithdrawalsIsNull_WhenWithdrawalsAllowed() { var resp = resp( - mockPayload(createBlockHeader(Optional.empty()), Collections.emptyList(), withdrawals)); + mockPayload( + createBlockHeader(Optional.empty(), Optional.empty()), + Collections.emptyList(), + withdrawals, + null)); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -452,9 +471,80 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), - Optional.of(withdrawals)); + Optional.of(withdrawals), + Optional.empty()); + + var resp = resp(mockPayload(mockHeader, Collections.emptyList(), withdrawalsParam, null)); + + assertValidResponse(mockHeader, resp); + } + + @Test + public void shouldReturnInvalidIfDepositsIsNotNull_WhenDepositsProhibited() { + final List deposits = List.of(); + when(protocolSpec.getDepositsValidator()) + .thenReturn(new DepositsValidator.ProhibitedDeposits()); + + var resp = + resp( + mockPayload( + createBlockHeader(Optional.empty(), Optional.of(Collections.emptyList())), + Collections.emptyList(), + null, + deposits)); + + final JsonRpcError jsonRpcError = fromErrorResp(resp); + assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); + verify(engineCallListener, times(1)).executionEngineCalled(); + } + + @Test + public void shouldReturnValidIfDepositsIsNull_WhenDepositsProhibited() { + final List deposits = null; + when(protocolSpec.getDepositsValidator()) + .thenReturn(new DepositsValidator.ProhibitedDeposits()); + BlockHeader mockHeader = + setupValidPayload( + new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), + Optional.empty(), + Optional.empty()); + + var resp = resp(mockPayload(mockHeader, Collections.emptyList(), null, deposits)); + + assertValidResponse(mockHeader, resp); + } + + @Test + public void shouldReturnInvalidIfDepositsIsNull_WhenDepositsAllowed() { + final List deposits = null; + when(protocolSpec.getDepositsValidator()) + .thenReturn(new DepositsValidator.AllowedDeposits(depositContractAddress)); + + var resp = + resp( + mockPayload( + createBlockHeader(Optional.empty(), Optional.empty()), + Collections.emptyList(), + null, + deposits)); + + assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); + verify(engineCallListener, times(1)).executionEngineCalled(); + } + + @Test + public void shouldReturnValidIfDepositsIsNotNull_WhenDepositsAllowed() { + final List depositsParam = List.of(DEPOSIT_PARAM_1); + final List deposits = List.of(DEPOSIT_PARAM_1.toDeposit()); + when(protocolSpec.getDepositsValidator()) + .thenReturn(new DepositsValidator.AllowedDeposits(depositContractAddress)); + BlockHeader mockHeader = + setupValidPayload( + new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), + Optional.empty(), + Optional.of(deposits)); - var resp = resp(mockPayload(mockHeader, Collections.emptyList(), withdrawalsParam)); + var resp = resp(mockPayload(mockHeader, Collections.emptyList(), null, depositsParam)); assertValidResponse(mockHeader, resp); } @@ -465,6 +555,7 @@ public void shouldReturnValidIfProtocolScheduleIsEmpty() { BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))), + Optional.empty(), Optional.empty()); var resp = resp(mockPayload(mockHeader, Collections.emptyList())); @@ -495,13 +586,15 @@ protected EnginePayloadParameter mockPayload(final BlockHeader header, final Lis header.getLogsBloom(), header.getPrevRandao().map(Bytes32::toHexString).orElse("0x0"), txs, + null, null); } private EnginePayloadParameter mockPayload( final BlockHeader header, final List txs, - final List withdrawals) { + final List withdrawals, + final List deposits) { return new EnginePayloadParameter( header.getHash(), header.getParentHash(), @@ -517,13 +610,16 @@ private EnginePayloadParameter mockPayload( header.getLogsBloom(), header.getPrevRandao().map(Bytes32::toHexString).orElse("0x0"), txs, - withdrawals); + withdrawals, + deposits); } @NotNull private BlockHeader setupValidPayload( - final BlockProcessingResult value, final Optional> maybeWithdrawals) { - BlockHeader mockHeader = createBlockHeader(maybeWithdrawals); + final BlockProcessingResult value, + final Optional> maybeWithdrawals, + final Optional> maybeDeposits) { + BlockHeader mockHeader = createBlockHeader(maybeWithdrawals, maybeDeposits); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); @@ -562,7 +658,9 @@ private JsonRpcError fromErrorResp(final JsonRpcResponse resp) { .get(); } - protected BlockHeader createBlockHeader(final Optional> maybeWithdrawals) { + protected BlockHeader createBlockHeader( + final Optional> maybeWithdrawals, + final Optional> maybeDeposits) { BlockHeader parentBlockHeader = new BlockHeaderTestFixture().baseFeePerGas(Wei.ONE).buildHeader(); BlockHeader mockHeader = @@ -572,6 +670,7 @@ protected BlockHeader createBlockHeader(final Optional> maybeWi .number(parentBlockHeader.getNumber() + 1) .timestamp(parentBlockHeader.getTimestamp() + 1) .withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null)) + .depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null)) .buildHeader(); return mockHeader; } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java index c4c4253ecdd..2250f63e718 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java @@ -69,6 +69,30 @@ public void shouldReturnBlockForKnownPayloadId() { verify(engineCallListener, times(1)).executionEngineCalled(); } + @Test + public void shouldReturnBlockForKnownPayloadIdPostV6110() { + // should return deposits for a post-V6110 block + when(mergeContext.retrieveBlockById(mockPid)) + .thenReturn(Optional.of(mockBlockWithReceiptsAndDeposits)); + + final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V2.getMethodName(), mockPid); + assertThat(resp).isInstanceOf(JsonRpcSuccessResponse.class); + Optional.of(resp) + .map(JsonRpcSuccessResponse.class::cast) + .ifPresent( + r -> { + assertThat(r.getResult()).isInstanceOf(EngineGetPayloadResultV2.class); + final EngineGetPayloadResultV2 res = (EngineGetPayloadResultV2) r.getResult(); + assertThat(res.getExecutionPayload().getDeposits()).isNotNull(); + assertThat(res.getExecutionPayload().getHash()) + .isEqualTo(mockHeader.getHash().toString()); + assertThat(res.getBlockValue()).isEqualTo(Quantity.create(0)); + assertThat(res.getExecutionPayload().getPrevRandao()) + .isEqualTo(mockHeader.getPrevRandao().map(Bytes32::toString).orElse("")); + }); + verify(engineCallListener, times(1)).executionEngineCalled(); + } + @Test public void shouldReturnExecutionPayloadWithoutWithdrawals_PreShanghaiBlock() { final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V2.getMethodName(), mockPid); @@ -80,6 +104,25 @@ public void shouldReturnExecutionPayloadWithoutWithdrawals_PreShanghaiBlock() { assertThat(r.getResult()).isInstanceOf(EngineGetPayloadResultV2.class); final EngineGetPayloadResultV2 res = (EngineGetPayloadResultV2) r.getResult(); assertThat(res.getExecutionPayload().getWithdrawals()).isNull(); + assertThat(res.getExecutionPayload().getDeposits()).isNull(); + }); + verify(engineCallListener, times(1)).executionEngineCalled(); + } + + @Test + public void shouldReturnExecutionPayloadWithoutDeposits_PreV6110Block() { + when(mergeContext.retrieveBlockById(mockPid)) + .thenReturn(Optional.of(mockBlockWithReceiptsAndWithdrawals)); + + final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V2.getMethodName(), mockPid); + assertThat(resp).isInstanceOf(JsonRpcSuccessResponse.class); + Optional.of(resp) + .map(JsonRpcSuccessResponse.class::cast) + .ifPresent( + r -> { + assertThat(r.getResult()).isInstanceOf(EngineGetPayloadResultV2.class); + final EngineGetPayloadResultV2 res = (EngineGetPayloadResultV2) r.getResult(); + assertThat(res.getExecutionPayload().getDeposits()).isNull(); }); verify(engineCallListener, times(1)).executionEngineCalled(); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1Test.java index 09f4ab16daf..f9a9200d57e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV1Test.java @@ -51,7 +51,7 @@ public void shouldReturnExpectedMethodName() { @Test public void shouldReturnInvalidOnBadTerminalBlock() { - BlockHeader mockHeader = createBlockHeader(Optional.empty()); + BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty()); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index 95736130b6f..5f4af0bf49d 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -32,9 +32,11 @@ import org.hyperledger.besu.ethereum.core.SealableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Withdrawal; +import org.hyperledger.besu.ethereum.core.encoding.DepositDecoder; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; +import org.hyperledger.besu.ethereum.mainnet.DepositsValidator; import org.hyperledger.besu.ethereum.mainnet.DifficultyCalculator; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -56,6 +58,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -83,6 +86,7 @@ public interface ExtraDataCalculator { private final Wei minTransactionGasPrice; private final Double minBlockOccupancyRatio; protected final BlockHeader parentHeader; + private final Optional
depositContractAddress; private final AtomicBoolean isCancelled = new AtomicBoolean(false); @@ -96,7 +100,8 @@ protected AbstractBlockCreator( final ProtocolSchedule protocolSchedule, final Wei minTransactionGasPrice, final Double minBlockOccupancyRatio, - final BlockHeader parentHeader) { + final BlockHeader parentHeader, + final Optional
depositContractAddress) { this.coinbase = coinbase; this.miningBeneficiaryCalculator = miningBeneficiaryCalculator; this.targetGasLimitSupplier = targetGasLimitSupplier; @@ -107,6 +112,7 @@ protected AbstractBlockCreator( this.minTransactionGasPrice = minTransactionGasPrice; this.minBlockOccupancyRatio = minBlockOccupancyRatio; this.parentHeader = parentHeader; + this.depositContractAddress = depositContractAddress; blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); } @@ -198,8 +204,14 @@ protected BlockCreationResult createBlock( throwIfStopped(); - final Optional> maybeDeposits = - Optional.empty(); // TODO 6110: Extract deposits from transaction receipts + final DepositsValidator depositsValidator = newProtocolSpec.getDepositsValidator(); + Optional> maybeDeposits = Optional.empty(); + if (depositsValidator instanceof DepositsValidator.AllowedDeposits + && depositContractAddress.isPresent()) { + maybeDeposits = Optional.of(findDepositsFromReceipts(transactionResults)); + } + + throwIfStopped(); if (rewardCoinbase && !rewardBeneficiary( @@ -235,7 +247,7 @@ protected BlockCreationResult createBlock( withdrawalsCanBeProcessed ? BodyValidation.withdrawalsRoot(maybeWithdrawals.get()) : null) - .depositsRoot(null) // TODO 6110: Derive deposit roots from deposits + .depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null)) .excessDataGas(newExcessDataGas) .buildSealableBlockHeader(); @@ -259,6 +271,15 @@ protected BlockCreationResult createBlock( } } + @VisibleForTesting + List findDepositsFromReceipts(final TransactionSelectionResults transactionResults) { + return transactionResults.getReceipts().stream() + .flatMap(receipt -> receipt.getLogsList().stream()) + .filter(log -> depositContractAddress.get().equals(log.getLogger())) + .map(DepositDecoder::decodeFromLog) + .toList(); + } + private DataGas computeExcessDataGas( TransactionSelectionResults transactionResults, ProtocolSpec newProtocolSpec) { diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java index 5a421e8988b..90f529256ef 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreator.java @@ -60,7 +60,8 @@ public PoWBlockCreator( protocolSchedule, minTransactionGasPrice, minBlockOccupancyRatio, - parentHeader); + parentHeader, + Optional.empty()); this.nonceSolver = nonceSolver; } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index 30cafa78897..6a832cf011c 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -14,37 +14,49 @@ */ package org.hyperledger.besu.ethereum.blockcreation; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSpecs.DEFAULT_DEPOSIT_CONTRACT_ADDRESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.BLSPublicKey; +import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.SealableBlockHeader; +import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.sorter.AbstractPendingTransactionsSorter; import org.hyperledger.besu.ethereum.eth.transactions.sorter.GasPricePendingTransactionsSorter; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; +import org.hyperledger.besu.ethereum.mainnet.DepositsValidator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.evm.log.Log; +import org.hyperledger.besu.evm.log.LogTopic; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.math.BigInteger; @@ -55,6 +67,7 @@ import java.util.function.Supplier; import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -63,8 +76,122 @@ @ExtendWith(MockitoExtension.class) abstract class AbstractBlockCreatorTest { + private static final Optional
EMPTY_DEPOSIT_CONTRACT_ADDRESS = Optional.empty(); @Mock private WithdrawalsProcessor withdrawalsProcessor; + @Test + void findDepositsFromReceipts() { + final AbstractBlockCreator blockCreator = + blockCreatorWithAllowedDeposits(Optional.of(DEFAULT_DEPOSIT_CONTRACT_ADDRESS)); + final BlockTransactionSelector.TransactionSelectionResults transactionResults = + mock(BlockTransactionSelector.TransactionSelectionResults.class); + BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); + TransactionReceipt receiptWithoutDeposit1 = blockDataGenerator.receipt(); + TransactionReceipt receiptWithoutDeposit2 = blockDataGenerator.receipt(); + final Log depositLog = + new Log( + DEFAULT_DEPOSIT_CONTRACT_ADDRESS, + Bytes.fromHexString( + "0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483000000000000000000000000000000000000000000000000000000000000000800405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb500000000000000000000000000000000000000000000000000000000000000083f3d080000000000000000000000000000000000000000000000000000000000"), + List.of( + LogTopic.fromHexString( + "0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"))); + final TransactionReceipt receiptWithDeposit = blockDataGenerator.receipt(List.of(depositLog)); + when(transactionResults.getReceipts()) + .thenReturn(List.of(receiptWithoutDeposit1, receiptWithDeposit, receiptWithoutDeposit2)); + + Deposit expectedDeposit = + new Deposit( + BLSPublicKey.fromHexString( + "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), + Bytes32.fromHexString( + "0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"), + GWei.of(32000000000L), + BLSSignature.fromHexString( + "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), + UInt64.valueOf(539967)); + final List expectedDeposits = List.of(expectedDeposit); + + final List depositsFromReceipts = + blockCreator.findDepositsFromReceipts(transactionResults); + + assertThat(depositsFromReceipts).isEqualTo(expectedDeposits); + } + + @Test + void withAllowedDepositsAndContractAddress_DepositsAreParsed() { + final AbstractBlockCreator blockCreator = + blockCreatorWithAllowedDeposits(Optional.of(DEFAULT_DEPOSIT_CONTRACT_ADDRESS)); + + final BlockCreationResult blockCreationResult = + blockCreator.createBlock( + Optional.empty(), + Optional.empty(), + Optional.of(emptyList()), + Optional.empty(), + 1L, + false); + + List deposits = emptyList(); + final Hash depositsRoot = BodyValidation.depositsRoot(deposits); + assertThat(blockCreationResult.getBlock().getHeader().getDepositsRoot()).hasValue(depositsRoot); + assertThat(blockCreationResult.getBlock().getBody().getDeposits()).hasValue(deposits); + } + + @Test + void withAllowedDepositsAndNoContractAddress_DepositsAreNotParsed() { + final AbstractBlockCreator blockCreator = blockCreatorWithAllowedDeposits(Optional.empty()); + + final BlockCreationResult blockCreationResult = + blockCreator.createBlock( + Optional.empty(), + Optional.empty(), + Optional.of(emptyList()), + Optional.empty(), + 1L, + false); + + assertThat(blockCreationResult.getBlock().getHeader().getDepositsRoot()).isEmpty(); + assertThat(blockCreationResult.getBlock().getBody().getDeposits()).isEmpty(); + } + + @Test + void withProhibitedDeposits_DepositsAreNotParsed() { + final AbstractBlockCreator blockCreator = blockCreatorWithProhibitedDeposits(); + + final BlockCreationResult blockCreationResult = + blockCreator.createBlock( + Optional.empty(), + Optional.empty(), + Optional.of(emptyList()), + Optional.empty(), + 1L, + false); + + assertThat(blockCreationResult.getBlock().getHeader().getDepositsRoot()).isEmpty(); + assertThat(blockCreationResult.getBlock().getBody().getDeposits()).isEmpty(); + } + + private AbstractBlockCreator blockCreatorWithAllowedDeposits( + final Optional
depositContractAddress) { + final ProtocolSpecAdapters protocolSpecAdapters = + ProtocolSpecAdapters.create( + 0, + specBuilder -> + specBuilder.depositsValidator( + new DepositsValidator.AllowedDeposits(depositContractAddress.orElse(null)))); + return createBlockCreator(protocolSpecAdapters, depositContractAddress); + } + + private AbstractBlockCreator blockCreatorWithProhibitedDeposits() { + final ProtocolSpecAdapters protocolSpecAdapters = + ProtocolSpecAdapters.create( + 0, + specBuilder -> + specBuilder.depositsValidator(new DepositsValidator.ProhibitedDeposits())); + return createBlockCreator(protocolSpecAdapters, Optional.of(DEFAULT_DEPOSIT_CONTRACT_ADDRESS)); + } + @Test void withProcessorAndEmptyWithdrawals_NoWithdrawalsAreProcessed() { final AbstractBlockCreator blockCreator = blockCreatorWithWithdrawalsProcessor(); @@ -130,14 +257,16 @@ private AbstractBlockCreator blockCreatorWithWithdrawalsProcessor() { final ProtocolSpecAdapters protocolSpecAdapters = ProtocolSpecAdapters.create( 0, specBuilder -> specBuilder.withdrawalsProcessor(withdrawalsProcessor)); - return createBlockCreator(protocolSpecAdapters); + return createBlockCreator(protocolSpecAdapters, EMPTY_DEPOSIT_CONTRACT_ADDRESS); } private AbstractBlockCreator blockCreatorWithoutWithdrawalsProcessor() { - return createBlockCreator(new ProtocolSpecAdapters(Map.of())); + return createBlockCreator(new ProtocolSpecAdapters(Map.of()), EMPTY_DEPOSIT_CONTRACT_ADDRESS); } - private AbstractBlockCreator createBlockCreator(final ProtocolSpecAdapters protocolSpecAdapters) { + private AbstractBlockCreator createBlockCreator( + final ProtocolSpecAdapters protocolSpecAdapters, + final Optional
depositContractAddress) { final GenesisConfigOptions genesisConfigOptions = GenesisConfigFile.DEFAULT.getConfigOptions(); final ExecutionContextTestFixture executionContextTestFixture = ExecutionContextTestFixture.builder() @@ -170,7 +299,8 @@ private AbstractBlockCreator createBlockCreator(final ProtocolSpecAdapters proto executionContextTestFixture.getProtocolSchedule(), Wei.of(1L), 0d, - blockchain.getChainHeadHeader()); + blockchain.getChainHeadHeader(), + depositContractAddress); } static class TestBlockCreator extends AbstractBlockCreator { @@ -185,7 +315,8 @@ protected TestBlockCreator( final ProtocolSchedule protocolSchedule, final Wei minTransactionGasPrice, final Double minBlockOccupancyRatio, - final BlockHeader parentHeader) { + final BlockHeader parentHeader, + final Optional
depositContractAddress) { super( coinbase, miningBeneficiaryCalculator, @@ -196,7 +327,8 @@ protected TestBlockCreator( protocolSchedule, minTransactionGasPrice, minBlockOccupancyRatio, - parentHeader); + parentHeader, + depositContractAddress); } @Override diff --git a/ethereum/core/build.gradle b/ethereum/core/build.gradle index 690aad04106..2804b2648d0 100644 --- a/ethereum/core/build.gradle +++ b/ethereum/core/build.gradle @@ -29,6 +29,7 @@ jar { dependencies { api 'org.slf4j:slf4j-api' + api 'org.web3j:core' annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess' diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/DepositContract.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/DepositContract.java new file mode 100644 index 00000000000..9f36df7ca97 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/DepositContract.java @@ -0,0 +1,63 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.ethereum.core; + +import org.hyperledger.besu.evm.log.LogTopic; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.DynamicBytes; +import org.web3j.abi.datatypes.Event; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.methods.response.Log; +import org.web3j.tx.Contract; +import org.web3j.tx.TransactionManager; +import org.web3j.tx.gas.ContractGasProvider; + +public class DepositContract extends Contract { + + public static final Event DEPOSITEVENT_EVENT = + new Event( + "DepositEvent", + Arrays.asList( + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {}, + new TypeReference() {})); + + DepositContract( + final String contractBinary, + final String contractAddress, + final Web3j web3j, + final TransactionManager transactionManager, + final ContractGasProvider gasProvider) { + super(contractBinary, contractAddress, web3j, transactionManager, gasProvider); + } + + public static EventValuesWithLog staticExtractDepositEventWithLog( + final org.hyperledger.besu.evm.log.Log log) { + Log web3jLog = new Log(); + web3jLog.setTopics( + log.getTopics().stream().map(LogTopic::toHexString).collect(Collectors.toList())); + web3jLog.setData(log.getData().toHexString()); + + return staticExtractEventParametersWithLog(DEPOSITEVENT_EVENT, web3jLog); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java index 90b4b482c15..cb8410d3d28 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java @@ -18,12 +18,17 @@ import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositContract; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPInput; +import org.hyperledger.besu.evm.log.Log; + +import java.nio.ByteOrder; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; +import org.web3j.tx.Contract; public class DepositDecoder { @@ -39,6 +44,26 @@ public static Deposit decode(final RLPInput rlpInput) { return new Deposit(publicKey, depositWithdrawalCredential, amount, signature, index); } + public static Deposit decodeFromLog(final Log log) { + Contract.EventValuesWithLog eventValues = DepositContract.staticExtractDepositEventWithLog(log); + final byte[] rawPublicKey = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); + final byte[] rawWithdrawalCredential = + (byte[]) eventValues.getNonIndexedValues().get(1).getValue(); + final byte[] rawAmount = (byte[]) eventValues.getNonIndexedValues().get(2).getValue(); + final byte[] rawSignature = (byte[]) eventValues.getNonIndexedValues().get(3).getValue(); + final byte[] rawIndex = (byte[]) eventValues.getNonIndexedValues().get(4).getValue(); + + return new Deposit( + BLSPublicKey.wrap(Bytes.wrap(rawPublicKey)), + Bytes32.wrap(Bytes.wrap(rawWithdrawalCredential)), + GWei.of( + Bytes.wrap(rawAmount) + .toLong( + ByteOrder.LITTLE_ENDIAN)), // Amount is little endian as per Deposit Contract + BLSSignature.wrap(Bytes.wrap(rawSignature)), + UInt64.valueOf(Bytes.wrap(rawIndex).reverse().toLong())); + } + public static Deposit decodeOpaqueBytes(final Bytes input) { return decode(RLP.input(input)); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidator.java index 30c0694a45d..befa2231083 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidator.java @@ -18,10 +18,15 @@ import static com.google.common.base.Preconditions.checkArgument; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.core.encoding.DepositDecoder; +import org.hyperledger.besu.evm.log.Log; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -30,7 +35,9 @@ public interface DepositsValidator { - boolean validateDeposits(Optional> deposits); + boolean validateDepositParameter(Optional> deposits); + + boolean validateDeposits(Block block, List receipts); boolean validateDepositsRoot(Block block); @@ -39,10 +46,16 @@ class ProhibitedDeposits implements DepositsValidator { private static final Logger LOG = LoggerFactory.getLogger(ProhibitedDeposits.class); @Override - public boolean validateDeposits(final Optional> deposits) { + public boolean validateDepositParameter(final Optional> deposits) { + return deposits.isEmpty(); + } + + @Override + public boolean validateDeposits(final Block block, final List receipts) { + Optional> deposits = block.getBody().getDeposits(); final boolean isValid = deposits.isEmpty(); if (!isValid) { - LOG.warn("Deposits must be null when Deposits are prohibited but were: {}", deposits); + LOG.warn("Deposits must be empty when Deposits are prohibited but were: {}", deposits); } return isValid; } @@ -64,10 +77,49 @@ public boolean validateDepositsRoot(final Block block) { class AllowedDeposits implements DepositsValidator { private static final Logger LOG = LoggerFactory.getLogger(AllowedDeposits.class); + private final Address depositContractAddress; + + public AllowedDeposits(final Address depositContractAddress) { + this.depositContractAddress = depositContractAddress; + } @Override - public boolean validateDeposits(final Optional> deposits) { - return true; // TODO 6110: Validate deposits in the next PR + public boolean validateDepositParameter(final Optional> deposits) { + return deposits.isPresent(); + } + + @Override + public boolean validateDeposits(final Block block, final List receipts) { + if (block.getBody().getDeposits().isEmpty()) { + LOG.warn("Deposits must not be empty when Deposits are activated"); + return false; + } + + List actualDeposits = new ArrayList<>(block.getBody().getDeposits().get()); + List expectedDeposits = new ArrayList<>(); + + for (TransactionReceipt receipt : receipts) { + for (Log log : receipt.getLogsList()) { + if (depositContractAddress.equals(log.getLogger())) { + Deposit deposit = DepositDecoder.decodeFromLog(log); + expectedDeposits.add(deposit); + } + } + } + + boolean isValid = actualDeposits.equals(expectedDeposits); + + if (!isValid) { + LOG.warn( + "Deposits validation failed. Deposits from block body do not match deposits from logs. Block hash: {}", + block.getHash()); + LOG.debug( + "Deposits from logs: {}, deposits from block body: {}", + expectedDeposits, + actualDeposits); + } + + return isValid; } @Override @@ -83,7 +135,7 @@ public boolean validateDepositsRoot(final Block block) { final Hash expectedDepositsRoot = BodyValidation.depositsRoot(deposits); if (!expectedDepositsRoot.equals(depositsRoot.get())) { LOG.info( - "Invalid block: transaction root mismatch (expected={}, actual={})", + "Invalid block: depositsRoot mismatch (expected={}, actual={})", expectedDepositsRoot, depositsRoot.get()); return false; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java index 893e811a5c1..abaab920666 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java @@ -104,7 +104,7 @@ public boolean validateBodyLight( return false; } - if (!validateDeposits(block)) { + if (!validateDeposits(block, receipts)) { return false; } @@ -309,7 +309,18 @@ private boolean validateWithdrawals(final Block block) { return true; } - private boolean validateDeposits(final Block unusedBlock) { - return true; // TODO 6110: Implement deposit validation + private boolean validateDeposits(final Block block, final List receipts) { + final DepositsValidator depositsValidator = + protocolSchedule.getByBlockHeader(block.getHeader()).getDepositsValidator(); + + if (!depositsValidator.validateDeposits(block, receipts)) { + return false; + } + + if (!depositsValidator.validateDepositsRoot(block)) { + return false; + } + + return true; } } 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 6d9fb63cea2..889b82eaf3b 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 @@ -98,6 +98,9 @@ public abstract class MainnetProtocolSpecs { private static final Wei CONSTANTINOPLE_BLOCK_REWARD = Wei.fromEth(2); + public static final Address DEFAULT_DEPOSIT_CONTRACT_ADDRESS = + Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); + private MainnetProtocolSpecs() {} public static ProtocolSpecBuilder frontierDefinition( @@ -747,6 +750,9 @@ static ProtocolSpecBuilder experimentalEipsDefinition( final GenesisConfigOptions genesisConfigOptions, final EvmConfiguration evmConfiguration) { + final Address depositContractAddress = + genesisConfigOptions.getDepositContractAddress().orElse(DEFAULT_DEPOSIT_CONTRACT_ADDRESS); + return futureEipsDefinition( chainId, configContractSizeLimit, @@ -758,7 +764,7 @@ static ProtocolSpecBuilder experimentalEipsDefinition( (gasCalculator, jdCacheConfig) -> MainnetEVMs.experimentalEips( gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) - .depositsValidator(new DepositsValidator.AllowedDeposits()) + .depositsValidator(new DepositsValidator.AllowedDeposits(depositContractAddress)) .name("ExperimentalEips"); } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java index 4976184a8a7..d6778a2eaa4 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java @@ -49,6 +49,7 @@ public class BlockHeaderTestFixture { private Hash mixHash = Hash.EMPTY; private long nonce = 0; private Optional withdrawalsRoot = Optional.empty(); + private Optional depositsRoot = Optional.empty(); private BlockHeaderFunctions blockHeaderFunctions = new MainnetBlockHeaderFunctions(); public BlockHeader buildHeader() { @@ -71,6 +72,7 @@ public BlockHeader buildHeader() { builder.mixHash(mixHash); builder.nonce(nonce); withdrawalsRoot.ifPresent(builder::withdrawalsRoot); + depositsRoot.ifPresent(builder::depositsRoot); builder.blockHeaderFunctions(blockHeaderFunctions); return builder.buildBlockHeader(); @@ -166,6 +168,11 @@ public BlockHeaderTestFixture withdrawalsRoot(final Hash withdrawalsRoot) { return this; } + public BlockHeaderTestFixture depositsRoot(final Hash depositsRoot) { + this.depositsRoot = Optional.ofNullable(depositsRoot); + return this; + } + public BlockHeaderTestFixture blockHeaderFunctions( final BlockHeaderFunctions blockHeaderFunctions) { this.blockHeaderFunctions = blockHeaderFunctions; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java index 79c11099e52..a441408c240 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java @@ -210,7 +210,8 @@ private TestBlockCreator( protocolSchedule, minTransactionGasPrice, minBlockOccupancyRatio, - parentHeader); + parentHeader, + Optional.empty()); } static TestBlockCreator forHeader( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java index d2aba9bdd1f..5939611c5e9 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java @@ -16,10 +16,15 @@ import static org.assertj.core.api.Assertions.assertThat; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BLSPublicKey; import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.evm.log.Log; +import org.hyperledger.besu.evm.log.LogTopic; + +import java.util.List; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -47,4 +52,32 @@ void shouldDecodeDeposit() { assertThat(deposit).isEqualTo(expectedDeposit); } + + @Test + void shouldDecodeDepositFromLog() { + final Address address = Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); + final List topics = + List.of( + LogTopic.fromHexString( + "0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")); + final Bytes data = + Bytes.fromHexString( + "0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483000000000000000000000000000000000000000000000000000000000000000800405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb500000000000000000000000000000000000000000000000000000000000000083f3d080000000000000000000000000000000000000000000000000000000000"); + + final Log log = new Log(address, data, topics); + final Deposit deposit = DepositDecoder.decodeFromLog(log); + + final Deposit expectedDeposit = + new Deposit( + BLSPublicKey.fromHexString( + "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), + Bytes32.fromHexString( + "0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"), + GWei.of(32000000000L), + BLSSignature.fromHexString( + "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), + UInt64.valueOf(539967)); + + assertThat(deposit).isEqualTo(expectedDeposit); + } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java index 16d3dac1cbd..09bd5a110b7 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java @@ -15,25 +15,88 @@ package org.hyperledger.besu.ethereum.mainnet; -import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.BLSPublicKey; +import org.hyperledger.besu.datatypes.BLSSignature; +import org.hyperledger.besu.datatypes.GWei; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockDataGenerator; +import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.evm.log.Log; +import org.hyperledger.besu.evm.log.LogTopic; import java.util.Collections; +import java.util.List; import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt64; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; public class DepositsValidatorTest { private final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); + private static Deposit DEPOSIT_1; + private static Deposit DEPOSIT_2; + private static Log LOG_1; + private static Log LOG_2; + private static Address DEPOSIT_CONTRACT_ADDRESS; + + @BeforeAll + public static void setup() { + DEPOSIT_1 = + new Deposit( + BLSPublicKey.fromHexString( + "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), + Bytes32.fromHexString( + "0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"), + GWei.of(32000000000L), + BLSSignature.fromHexString( + "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), + UInt64.valueOf(539967)); + + DEPOSIT_2 = + new Deposit( + BLSPublicKey.fromHexString( + "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243"), + Bytes32.fromHexString( + "0x006a8dc800c6d8dd6977ef53264e2d030350f0145a91bcd167b4f1c3ea21b271"), + GWei.of(32000000000L), + BLSSignature.fromHexString( + "0x801b08ca107b623eca32ee9f9111b4e50eb9cfe19e38204b72de7dc04c5a5e00f61bab96f10842576f66020ce851083f1583dd9a6b73301bea6c245cf51f27cf96aeb018852c5f70bf485d16b957cfe49ca008913346b431e7653ae3ddb23b07"), + UInt64.valueOf(559887)); + + LOG_1 = + new Log( + Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"), + Bytes.fromHexString( + "0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483000000000000000000000000000000000000000000000000000000000000000800405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb500000000000000000000000000000000000000000000000000000000000000083f3d080000000000000000000000000000000000000000000000000000000000"), + List.of( + LogTopic.fromHexString( + "0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"))); + + LOG_2 = + new Log( + Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"), + Bytes.fromHexString( + "0x00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000308706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020006a8dc800c6d8dd6977ef53264e2d030350f0145a91bcd167b4f1c3ea21b271000000000000000000000000000000000000000000000000000000000000000800405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060801b08ca107b623eca32ee9f9111b4e50eb9cfe19e38204b72de7dc04c5a5e00f61bab96f10842576f66020ce851083f1583dd9a6b73301bea6c245cf51f27cf96aeb018852c5f70bf485d16b957cfe49ca008913346b431e7653ae3ddb23b0700000000000000000000000000000000000000000000000000000000000000080f8b080000000000000000000000000000000000000000000000000000000000"), + List.of( + LogTopic.fromHexString( + "0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"))); + DEPOSIT_CONTRACT_ADDRESS = Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); + } @Test public void validateProhibitedDeposits() { - assertThat(new DepositsValidator.ProhibitedDeposits().validateDeposits(Optional.empty())) - .isTrue(); + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create().setDeposits(Optional.empty()); + final Block block = blockDataGenerator.block(blockOptions); + assertThat(new DepositsValidator.ProhibitedDeposits().validateDeposits(block, null)).isTrue(); } @Test @@ -44,9 +107,10 @@ public void validateProhibitedDepositsRoot() { @Test public void invalidateProhibitedDeposits() { - assertThat( - new DepositsValidator.ProhibitedDeposits().validateDeposits(Optional.of(emptyList()))) - .isFalse(); + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create().setDeposits(Optional.of(List.of(DEPOSIT_1))); + final Block block = blockDataGenerator.block(blockOptions); + assertThat(new DepositsValidator.ProhibitedDeposits().validateDeposits(block, null)).isFalse(); } @Test @@ -59,7 +123,36 @@ public void invalidateProhibitedDepositsRoot() { @Test public void validateAllowedDeposits() { - // TODO 6110: Validate deposits in AllowedDeposits to be included in next PR + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create() + .setDeposits(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt = + new TransactionReceipt(null, 0L, List.of(LOG_1, LOG_2), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDeposits(block, List.of(receipt))) + .isTrue(); + } + + @Test + public void validateAllowedDepositsSeparateReceipts() { + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create() + .setDeposits(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt1 = + new TransactionReceipt(null, 0L, List.of(LOG_1), Optional.empty()); + final TransactionReceipt receipt2 = + new TransactionReceipt(null, 0L, List.of(LOG_2), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDeposits(block, List.of(receipt1, receipt2))) + .isTrue(); } @Test @@ -69,16 +162,139 @@ public void validateAllowedDepositsRoot() { .setDeposits(Optional.of(Collections.emptyList())) .setDepositsRoot(Hash.EMPTY_TRIE_HASH); final Block block = blockDataGenerator.block(blockOptions); - assertThat(new DepositsValidator.AllowedDeposits().validateDepositsRoot(block)).isTrue(); + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDepositsRoot(block)) + .isTrue(); } @Test public void invalidateAllowedDeposits() { - // TODO 6110: Validate deposits in AllowedDeposits to be included in next PR + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create().setDeposits(Optional.of(List.of(DEPOSIT_1))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt1 = + new TransactionReceipt(null, 0L, List.of(LOG_2), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDeposits(block, List.of(receipt1))) + .isFalse(); + } + + @Test + public void invalidateAllowedDepositsMissingLogInReceipt() { + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create() + .setDeposits(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt1 = + new TransactionReceipt(null, 0L, List.of(LOG_2), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDeposits(block, List.of(receipt1))) + .isFalse(); + } + + @Test + public void invalidateAllowedDepositsExtraLogInReceipt() { + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create().setDeposits(Optional.of(List.of(DEPOSIT_1))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt1 = + new TransactionReceipt(null, 0L, List.of(LOG_1, LOG_2), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDeposits(block, List.of(receipt1))) + .isFalse(); + } + + @Test + public void invalidateAllowedDepositsWrongOrder() { + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create() + .setDeposits(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt1 = + new TransactionReceipt(null, 0L, List.of(LOG_2, LOG_1), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDeposits(block, List.of(receipt1))) + .isFalse(); + } + + @Test + public void invalidateAllowedDepositsMismatchContractAddress() { + + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create() + .setDeposits(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + final Block block = blockDataGenerator.block(blockOptions); + + final TransactionReceipt receipt1 = + new TransactionReceipt(null, 0L, List.of(LOG_1, LOG_2), Optional.empty()); + + assertThat( + new DepositsValidator.AllowedDeposits(Address.ZERO) + .validateDeposits(block, List.of(receipt1))) + .isFalse(); } @Test public void invalidateAllowedDepositsRoot() { - // TODO 6110: Validate deposits in AllowedDeposits to be included in next PR + final BlockDataGenerator.BlockOptions blockOptions = + BlockDataGenerator.BlockOptions.create() + .setDeposits(Optional.of(Collections.emptyList())) + .setDepositsRoot(Hash.ZERO); // this is invalid it should be empty trie hash + final Block block = blockDataGenerator.block(blockOptions); + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDepositsRoot(block)) + .isFalse(); + } + + @Test + public void validateProhibitedDepositParams() { + final Optional> deposits = Optional.empty(); + assertThat(new DepositsValidator.ProhibitedDeposits().validateDepositParameter(deposits)) + .isTrue(); + } + + @Test + public void invalidateProhibitedDepositParams() { + final Optional> deposits = Optional.of(List.of(DEPOSIT_1, DEPOSIT_2)); + assertThat(new DepositsValidator.ProhibitedDeposits().validateDepositParameter(deposits)) + .isFalse(); + } + + @Test + public void validateAllowedDepositParams() { + final Optional> deposits = Optional.of(List.of(DEPOSIT_1, DEPOSIT_2)); + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDepositParameter(deposits)) + .isTrue(); + + final Optional> emptyDeposits = Optional.of(List.of()); + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDepositParameter(emptyDeposits)) + .isTrue(); + } + + @Test + public void invalidateAllowedDepositParams() { + final Optional> deposits = Optional.empty(); + assertThat( + new DepositsValidator.AllowedDeposits(DEPOSIT_CONTRACT_ADDRESS) + .validateDepositParameter(deposits)) + .isFalse(); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java index 1df20268177..8543321b470 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java @@ -45,9 +45,11 @@ class MainnetBlockBodyValidatorTest { private final BlockchainSetupUtil blockchainSetupUtil = BlockchainSetupUtil.forMainnet(); private final List withdrawals = List.of(new Withdrawal(UInt64.ONE, UInt64.ONE, Address.ZERO, GWei.ONE)); + @Mock private ProtocolSchedule protocolSchedule; @Mock private ProtocolSpec protocolSpec; @Mock private WithdrawalsValidator withdrawalsValidator; + @Mock private DepositsValidator depositsValidator; @Test void validatesWithdrawals() { @@ -67,8 +69,11 @@ void validatesWithdrawals() { when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); when(protocolSpec.getWithdrawalsValidator()).thenReturn(withdrawalsValidator); + when(protocolSpec.getDepositsValidator()).thenReturn(depositsValidator); when(withdrawalsValidator.validateWithdrawals(Optional.of(withdrawals))).thenReturn(true); when(withdrawalsValidator.validateWithdrawalsRoot(block)).thenReturn(true); + when(depositsValidator.validateDeposits(any(), any())).thenReturn(true); + when(depositsValidator.validateDepositsRoot(block)).thenReturn(true); assertThat( new MainnetBlockBodyValidator(protocolSchedule)