Skip to content

Commit 3ffe31d

Browse files
mirgeematkt
andauthored
Add eth_getBlockAccessListBy* methods (besu-eth#9643)
Signed-off-by: Miroslav Kovar <miroslavkovar@protonmail.com> Co-authored-by: Karim Taam <karim.t2am@gmail.com>
1 parent 2f6d7f2 commit 3ffe31d

11 files changed

Lines changed: 837 additions & 71 deletions

File tree

app/src/main/java/org/hyperledger/besu/cli/options/BalConfigurationOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public BalConfigurationOptions() {}
6262
names = {"--Xbal-api-enabled"},
6363
hidden = true,
6464
description =
65-
"Set to enable eth_getBlockAccessListByNumber method and Block Access Lists in simulation results")
65+
"Set to enable eth_getBlockAccessListByBlockNumber and eth_getBlockAccessListByBlockHash methods and Block Access Lists in simulation results")
6666
private final Boolean balApiEnabled = false;
6767

6868
@CommandLine.Option(

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ public enum RpcMethod {
8787
ETH_GAS_PRICE("eth_gasPrice"),
8888
ETH_BLOB_BASE_FEE("eth_blobBaseFee"),
8989
ETH_GET_BALANCE("eth_getBalance"),
90-
ETH_GET_BLOCK_ACCESS_LIST_BY_NUMBER("eth_getBlockAccessListByNumber"),
90+
ETH_GET_BLOCK_ACCESS_LIST_BY_BLOCK_HASH("eth_getBlockAccessListByBlockHash"),
91+
ETH_GET_BLOCK_ACCESS_LIST_BY_BLOCK_NUMBER("eth_getBlockAccessListByBlockNumber"),
9192
ETH_GET_BLOCK_BY_HASH("eth_getBlockByHash"),
9293
ETH_GET_BLOCK_BY_NUMBER("eth_getBlockByNumber"),
9394
ETH_GET_BLOCK_RECEIPTS("eth_getBlockReceipts"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright contributors to Hyperledger Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
16+
17+
import org.hyperledger.besu.datatypes.Hash;
18+
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
19+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
20+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
21+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException;
22+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
23+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
24+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
25+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
26+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockAccessListResult;
27+
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
28+
import org.hyperledger.besu.ethereum.core.BlockHeader;
29+
30+
public class EthGetBlockAccessListByBlockHash implements JsonRpcMethod {
31+
32+
private final BlockchainQueries blockchainQueries;
33+
34+
public EthGetBlockAccessListByBlockHash(final BlockchainQueries blockchainQueries) {
35+
this.blockchainQueries = blockchainQueries;
36+
}
37+
38+
@Override
39+
public String getName() {
40+
return RpcMethod.ETH_GET_BLOCK_ACCESS_LIST_BY_BLOCK_HASH.getMethodName();
41+
}
42+
43+
@Override
44+
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
45+
final Hash blockHash;
46+
try {
47+
blockHash = requestContext.getRequiredParameter(0, Hash.class);
48+
} catch (JsonRpcParameterException e) {
49+
throw new InvalidJsonRpcParameters(
50+
"Invalid block hash parameter (index 0)", RpcErrorType.INVALID_BLOCK_HASH_PARAMS, e);
51+
}
52+
53+
final var requestId = requestContext.getRequest().getId();
54+
final var maybeHeader = blockchainQueries.getBlockHeaderByHash(blockHash);
55+
if (maybeHeader.isEmpty()) {
56+
return new JsonRpcErrorResponse(requestId, RpcErrorType.BLOCK_NOT_FOUND);
57+
}
58+
59+
final BlockHeader header = maybeHeader.get();
60+
if (!blockchainQueries.isBlockAccessListSupported(header)) {
61+
return new JsonRpcErrorResponse(
62+
requestId, RpcErrorType.BLOCK_ACCESS_LIST_NOT_AVAILABLE_FOR_PRE_AMSTERDAM_BLOCKS);
63+
}
64+
65+
return blockchainQueries
66+
.getBlockchain()
67+
.getBlockAccessList(blockHash)
68+
.<JsonRpcResponse>map(
69+
bal ->
70+
new JsonRpcSuccessResponse(
71+
requestId, BlockAccessListResult.fromBlockAccessList(bal)))
72+
.orElseGet(
73+
() -> new JsonRpcErrorResponse(requestId, RpcErrorType.PRUNED_HISTORY_UNAVAILABLE));
74+
}
75+
}

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockAccessListByNumber.java renamed to ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockAccessListByBlockNumber.java

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@
1919
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
2020
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
2121
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException;
22+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
2223
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
2324
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockAccessListResult;
24-
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.GetBlockAccessListResult;
2525
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
26-
import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
26+
import org.hyperledger.besu.ethereum.core.BlockHeader;
2727

28-
public class EthGetBlockAccessListByNumber extends AbstractBlockParameterMethod {
28+
public class EthGetBlockAccessListByBlockNumber extends AbstractBlockParameterMethod {
2929

30-
public EthGetBlockAccessListByNumber(final BlockchainQueries blockchainQueries) {
30+
public EthGetBlockAccessListByBlockNumber(final BlockchainQueries blockchainQueries) {
3131
super(blockchainQueries);
3232
}
3333

3434
@Override
3535
public String getName() {
36-
return RpcMethod.ETH_GET_BLOCK_ACCESS_LIST_BY_NUMBER.getMethodName();
36+
return RpcMethod.ETH_GET_BLOCK_ACCESS_LIST_BY_BLOCK_NUMBER.getMethodName();
3737
}
3838

3939
@Override
@@ -49,18 +49,26 @@ protected BlockParameter blockParameter(final JsonRpcRequestContext requestConte
4949
@Override
5050
protected Object resultByBlockNumber(
5151
final JsonRpcRequestContext requestContext, final long blockNumber) {
52-
return getBlockchainQueries()
53-
.getBlockHashByNumber(blockNumber)
54-
.flatMap(
55-
hash ->
56-
getBlockchainQueries()
57-
.getBlockchain()
58-
.getBlockAccessList(hash)
59-
.map(
60-
bal ->
61-
new GetBlockAccessListResult(
62-
BodyValidation.balHash(bal).toString(),
63-
BlockAccessListResult.fromBlockAccessList(bal))))
64-
.orElse(null);
52+
final var maybeHeader = getBlockchainQueries().getBlockHeaderByNumber(blockNumber);
53+
final var requestId = requestContext.getRequest().getId();
54+
55+
if (maybeHeader.isEmpty()) {
56+
return new JsonRpcErrorResponse(requestId, RpcErrorType.BLOCK_NOT_FOUND);
57+
}
58+
59+
final BlockHeader header = maybeHeader.get();
60+
if (!getBlockchainQueries().isBlockAccessListSupported(header)) {
61+
return new JsonRpcErrorResponse(
62+
requestId, RpcErrorType.BLOCK_ACCESS_LIST_NOT_AVAILABLE_FOR_PRE_AMSTERDAM_BLOCKS);
63+
}
64+
65+
final var maybeAccessList =
66+
getBlockchainQueries().getBlockchain().getBlockAccessList(header.getHash());
67+
68+
if (maybeAccessList.isEmpty()) {
69+
return new JsonRpcErrorResponse(requestId, RpcErrorType.PRUNED_HISTORY_UNAVAILABLE);
70+
}
71+
72+
return BlockAccessListResult.fromBlockAccessList(maybeAccessList.get());
6573
}
6674
}

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ public enum RpcErrorType implements RpcMethodError {
124124

125125
// eth_getBlockByNumber specific error message
126126
UNKNOWN_BLOCK(-39001, "Unknown block"),
127+
PRUNED_HISTORY_UNAVAILABLE(4444, "Pruned history unavailable"),
128+
BLOCK_ACCESS_LIST_NOT_AVAILABLE_FOR_PRE_AMSTERDAM_BLOCKS(
129+
4445, "Block access list not available for pre-Amsterdam blocks"),
127130

128131
// eth_sendTransaction specific error message
129132
ETH_SEND_TX_NOT_AVAILABLE(

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/GetBlockAccessListResult.java

Lines changed: 0 additions & 42 deletions
This file was deleted.

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthFeeHistory;
3030
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGasPrice;
3131
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBalance;
32-
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockAccessListByNumber;
32+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockAccessListByBlockHash;
33+
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockAccessListByBlockNumber;
3334
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockByHash;
3435
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockByNumber;
3536
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetBlockReceipts;
@@ -183,9 +184,13 @@ protected Map<String, JsonRpcMethod> create() {
183184
miningConfiguration,
184185
apiConfiguration));
185186
if (balConfiguration.isBalApiEnabled()) {
186-
final EthGetBlockAccessListByNumber method =
187-
new EthGetBlockAccessListByNumber(blockchainQueries);
188-
map.put(method.getName(), method);
187+
final EthGetBlockAccessListByBlockNumber blockNumberMethod =
188+
new EthGetBlockAccessListByBlockNumber(blockchainQueries);
189+
map.put(blockNumberMethod.getName(), blockNumberMethod);
190+
191+
final EthGetBlockAccessListByBlockHash blockHashMethod =
192+
new EthGetBlockAccessListByBlockHash(blockchainQueries);
193+
map.put(blockHashMethod.getName(), blockHashMethod);
189194
}
190195
return map;
191196
}

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
4141
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
4242
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
43+
import org.hyperledger.besu.ethereum.mainnet.block.access.list.BlockAccessListFactory;
4344
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
4445
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
4546
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
@@ -535,6 +536,14 @@ public Optional<BlockHeader> getBlockHeaderByNumber(final long number) {
535536
return blockchain.getBlockHeader(number);
536537
}
537538

539+
public boolean isBlockAccessListSupported(final BlockHeader header) {
540+
return protocolSchedule
541+
.getByBlockHeader(header)
542+
.getBlockAccessListFactory()
543+
.map(BlockAccessListFactory::isForkActivated)
544+
.orElse(false);
545+
}
546+
538547
public boolean blockIsOnCanonicalChain(final Hash hash) {
539548
return blockchain.blockIsOnCanonicalChain(hash);
540549
}

0 commit comments

Comments
 (0)