mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-08 23:08:15 -05:00
implement engine_getBlobsV1 (#7553)
* implement engine_getBlobsV1 Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net> Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
### Additions and Improvements
|
||||
- Update Java and Gradle dependecies [#7571](https://github.com/hyperledger/besu/pull/7571)
|
||||
- Layered txpool: new options `--tx-pool-min-score` to remove a tx from pool when its score is lower than the specified value [#7576](https://github.com/hyperledger/besu/pull/7576)
|
||||
- Add `engine_getBlobsV1` method to the Engine API [#7553](https://github.com/hyperledger/besu/pull/7553)
|
||||
|
||||
### Bug fixes
|
||||
- Layered txpool: do not send notifications when moving tx between layers [#7539](https://github.com/hyperledger/besu/pull/7539)
|
||||
@@ -39,7 +40,7 @@
|
||||
- Correctly drops messages that exceeds local message size limit [#5455](https://github.com/hyperledger/besu/pull/7507)
|
||||
- **DebugMetrics**: Fixed a `ClassCastException` occurring in `DebugMetrics` when handling nested metric structures. Previously, `Double` values within these structures were incorrectly cast to `Map` objects, leading to errors. This update allows for proper handling of both direct values and nested structures at the same level. Issue# [#7383](https://github.com/hyperledger/besu/pull/7383)
|
||||
- `evmtool` was not respecting the `--genesis` setting, resulting in unexpected trace results. [#7433](https://github.com/hyperledger/besu/pull/7433)
|
||||
- The genesis config override `contractSizeLimit` was not wired into code size limits [#7557](https://github.com/hyperledger/besu/pull/7557)
|
||||
- The genesis config override `contractSizeLimit`q was not wired into code size limits [#7557](https://github.com/hyperledger/besu/pull/7557)
|
||||
- Fix incorrect key filtering in LayeredKeyValueStorage stream [#7535](https://github.com/hyperledger/besu/pull/7557)
|
||||
|
||||
## 24.8.0
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Util;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -245,7 +246,8 @@ public class CliqueBlockCreatorTest {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
conf);
|
||||
conf,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
return transactionPool;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Util;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -233,7 +234,8 @@ public class CliqueMinerExecutorTest {
|
||||
mock(TransactionBroadcaster.class),
|
||||
cliqueEthContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
conf);
|
||||
conf,
|
||||
new BlobCache());
|
||||
|
||||
transactionPool.setEnabled();
|
||||
return transactionPool;
|
||||
|
||||
@@ -84,6 +84,7 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Util;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -371,7 +372,8 @@ public class TestContextBuilder {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
|
||||
transactionPool.setEnabled();
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitV
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -152,7 +153,8 @@ public class BftBlockCreatorTest {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
|
||||
transactionPool.setEnabled();
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardSyncContext;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
@@ -214,7 +215,8 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
|
||||
this.transactionPool.setEnabled();
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Util;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -480,7 +481,8 @@ public class TestContextBuilder {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
|
||||
transactionPool.setEnabled();
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
|
||||
@@ -121,7 +122,8 @@ public class EthGetFilterChangesIntegrationTest {
|
||||
batchAddedListener,
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
TransactionPoolConfiguration.DEFAULT);
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
final BlockchainQueries blockchainQueries =
|
||||
new BlockchainQueries(
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
|
||||
@@ -121,7 +122,8 @@ public class EthGetFilterChangesIntegrationTest {
|
||||
batchAddedListener,
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
TransactionPoolConfiguration.DEFAULT);
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
final BlockchainQueries blockchainQueries =
|
||||
new BlockchainQueries(
|
||||
|
||||
@@ -51,6 +51,7 @@ public enum RpcMethod {
|
||||
DEBUG_GET_RAW_BLOCK("debug_getRawBlock"),
|
||||
DEBUG_GET_RAW_RECEIPTS("debug_getRawReceipts"),
|
||||
DEBUG_GET_RAW_TRANSACTION("debug_getRawTransaction"),
|
||||
ENGINE_GET_BLOBS_V1("engine_getBlobsV1"),
|
||||
ENGINE_GET_PAYLOAD_V1("engine_getPayloadV1"),
|
||||
ENGINE_GET_PAYLOAD_V2("engine_getPayloadV2"),
|
||||
ENGINE_GET_PAYLOAD_V3("engine_getPayloadV3"),
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.methods.engine;
|
||||
|
||||
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
|
||||
import org.hyperledger.besu.datatypes.VersionedHash;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlobAndProofV1;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import io.vertx.core.Vertx;
|
||||
|
||||
/**
|
||||
* #### Specification
|
||||
*
|
||||
* <p>1. Given an array of blob versioned hashes client software **MUST** respond with an array of
|
||||
* `BlobAndProofV1` objects with matching versioned hashes, respecting the order of versioned hashes
|
||||
* in the input array.
|
||||
*
|
||||
* <p>2. Client software **MUST** place responses in the order given in the request, using `null`
|
||||
* for any missing blobs. For instance, if the request is `[A_versioned_hash, B_versioned_hash,
|
||||
* C_versioned_hash]` and client software has data for blobs `A` and `C`, but doesn't have data for
|
||||
* `B`, the response **MUST** be `[A, null, C]`.
|
||||
*
|
||||
* <p>3. Client software **MUST** support request sizes of at least 128 blob versioned hashes. The
|
||||
* client **MUST** return `-38004: Too large request` error if the number of requested blobs is too
|
||||
* large.
|
||||
*
|
||||
* <p>4. Client software **MAY** return an array of all `null` entries if syncing or otherwise
|
||||
* unable to serve blob pool data.
|
||||
*
|
||||
* <p>5. Callers **MUST** consider that execution layer clients may prune old blobs from their pool,
|
||||
* and will respond with `null` if a blob has been pruned.
|
||||
*/
|
||||
public class EngineGetBlobsV1 extends ExecutionEngineJsonRpcMethod {
|
||||
|
||||
private final TransactionPool transactionPool;
|
||||
|
||||
public EngineGetBlobsV1(
|
||||
final Vertx vertx,
|
||||
final ProtocolContext protocolContext,
|
||||
final EngineCallListener engineCallListener,
|
||||
final TransactionPool transactionPool) {
|
||||
super(vertx, protocolContext, engineCallListener);
|
||||
this.transactionPool = transactionPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "engine_getBlobsV1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) {
|
||||
final VersionedHash[] versionedHashes;
|
||||
try {
|
||||
versionedHashes = requestContext.getRequiredParameter(0, VersionedHash[].class);
|
||||
} catch (JsonRpcParameter.JsonRpcParameterException e) {
|
||||
throw new InvalidJsonRpcParameters(
|
||||
"Invalid versioned hashes parameter (index 0)",
|
||||
RpcErrorType.INVALID_VERSIONED_HASHES_PARAMS,
|
||||
e);
|
||||
}
|
||||
|
||||
if (versionedHashes.length > 128) {
|
||||
return new JsonRpcErrorResponse(
|
||||
requestContext.getRequest().getId(),
|
||||
RpcErrorType.INVALID_ENGINE_GET_BLOBS_V1_TOO_LARGE_REQUEST);
|
||||
}
|
||||
|
||||
final List<BlobAndProofV1> result = getBlobV1Result(versionedHashes);
|
||||
|
||||
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result);
|
||||
}
|
||||
|
||||
private @Nonnull List<BlobAndProofV1> getBlobV1Result(final VersionedHash[] versionedHashes) {
|
||||
return Arrays.stream(versionedHashes)
|
||||
.map(transactionPool::getBlobQuad)
|
||||
.map(this::getBlobAndProofV1)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private @Nullable BlobAndProofV1 getBlobAndProofV1(final BlobsWithCommitments.BlobQuad bq) {
|
||||
if (bq == null) {
|
||||
return null;
|
||||
}
|
||||
return new BlobAndProofV1(
|
||||
bq.blob().getData().toHexString(), bq.kzgProof().getData().toHexString());
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ public enum RpcErrorType implements RpcMethodError {
|
||||
INVALID_ENGINE_NEW_PAYLOAD_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid engine payload parameter"),
|
||||
INVALID_ENGINE_PREPARE_PAYLOAD_PARAMS(
|
||||
INVALID_PARAMS_ERROR_CODE, "Invalid engine prepare payload parameter"),
|
||||
INVALID_ENGINE_GET_BLOBS_V1_TOO_LARGE_REQUEST(-38004, "Too large request"),
|
||||
INVALID_ENODE_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid enode params"),
|
||||
INVALID_EXCESS_BLOB_GAS_PARAMS(
|
||||
INVALID_PARAMS_ERROR_CODE, "Invalid excess blob gas params (missing or invalid)"),
|
||||
@@ -109,6 +110,7 @@ public enum RpcErrorType implements RpcMethodError {
|
||||
INVALID_TRANSACTION_LIMIT_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid transaction limit params"),
|
||||
INVALID_TRANSACTION_TRACE_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid transaction trace params"),
|
||||
INVALID_VERSIONED_HASH_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid versioned hash params"),
|
||||
INVALID_VERSIONED_HASHES_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid versioned hashes params"),
|
||||
INVALID_VOTE_TYPE_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid vote type params"),
|
||||
INVALID_WITHDRAWALS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid withdrawals"),
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
/**
|
||||
* The result of the eth_getBlobAndProofV1 JSON-RPC method contains an array of BlobAndProofV1.
|
||||
* BlobAndProofV1 contains the blob data and the kzg proof for the blob.
|
||||
*/
|
||||
@JsonPropertyOrder({"blob", "proof"})
|
||||
public class BlobAndProofV1 {
|
||||
|
||||
private final String blob;
|
||||
|
||||
private final String proof;
|
||||
|
||||
public BlobAndProofV1(final String blob, final String proof) {
|
||||
this.blob = blob;
|
||||
this.proof = proof;
|
||||
}
|
||||
|
||||
public String getProof() {
|
||||
return proof;
|
||||
}
|
||||
|
||||
public String getBlob() {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineE
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV1;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV2;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV3;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetBlobsV1;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetClientVersionV1;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetPayloadBodiesByHashV1;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetPayloadBodiesByRangeV1;
|
||||
@@ -39,6 +40,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineQ
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -60,6 +62,7 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
private final Vertx consensusEngineServer;
|
||||
private final String clientVersion;
|
||||
private final String commit;
|
||||
private final TransactionPool transactionPool;
|
||||
|
||||
ExecutionEngineJsonRpcMethods(
|
||||
final MiningCoordinator miningCoordinator,
|
||||
@@ -68,7 +71,8 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
final EthPeers ethPeers,
|
||||
final Vertx consensusEngineServer,
|
||||
final String clientVersion,
|
||||
final String commit) {
|
||||
final String commit,
|
||||
final TransactionPool transactionPool) {
|
||||
this.mergeCoordinator =
|
||||
Optional.ofNullable(miningCoordinator)
|
||||
.filter(mc -> mc.isCompatibleWithEngineApi())
|
||||
@@ -79,6 +83,7 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
this.consensusEngineServer = consensusEngineServer;
|
||||
this.clientVersion = clientVersion;
|
||||
this.commit = commit;
|
||||
this.transactionPool = transactionPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,7 +161,9 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
new EnginePreparePayloadDebug(
|
||||
consensusEngineServer, protocolContext, engineQosTimer, mergeCoordinator.get()),
|
||||
new EngineGetClientVersionV1(
|
||||
consensusEngineServer, protocolContext, engineQosTimer, clientVersion, commit)));
|
||||
consensusEngineServer, protocolContext, engineQosTimer, clientVersion, commit),
|
||||
new EngineGetBlobsV1(
|
||||
consensusEngineServer, protocolContext, engineQosTimer, transactionPool)));
|
||||
|
||||
if (protocolSchedule.anyMatch(p -> p.spec().getName().equalsIgnoreCase("cancun"))) {
|
||||
executionEngineApisSupported.add(
|
||||
|
||||
@@ -119,7 +119,8 @@ public class JsonRpcMethodsFactory {
|
||||
ethPeers,
|
||||
consensusEngineServer,
|
||||
clientVersion,
|
||||
commit),
|
||||
commit,
|
||||
transactionPool),
|
||||
new EthJsonRpcMethods(
|
||||
blockchainQueries,
|
||||
synchronizer,
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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.methods.engine;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair;
|
||||
import org.hyperledger.besu.crypto.SECPPrivateKey;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.TransactionType;
|
||||
import org.hyperledger.besu.datatypes.VersionedHash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
|
||||
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.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlobAndProofV1;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlobTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.plugin.services.rpc.RpcResponseType;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import io.vertx.core.Vertx;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
public class EngineGetBlobsV1Test {
|
||||
|
||||
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
|
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
|
||||
private static final SECPPrivateKey PRIVATE_KEY1 =
|
||||
SIGNATURE_ALGORITHM
|
||||
.get()
|
||||
.createPrivateKey(
|
||||
Bytes32.fromHexString(
|
||||
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"));
|
||||
private static final KeyPair KEYS1 =
|
||||
new KeyPair(PRIVATE_KEY1, SIGNATURE_ALGORITHM.get().createPublicKey(PRIVATE_KEY1));
|
||||
public static final VersionedHash VERSIONED_HASH_ZERO = new VersionedHash((byte) 1, Hash.ZERO);
|
||||
|
||||
@Mock private ProtocolContext protocolContext;
|
||||
@Mock private EngineCallListener engineCallListener;
|
||||
@Mock private MutableBlockchain blockchain;
|
||||
@Mock private TransactionPool transactionPool;
|
||||
|
||||
private EngineGetBlobsV1 method;
|
||||
|
||||
private static final Vertx vertx = Vertx.vertx();
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
when(protocolContext.getBlockchain()).thenReturn(blockchain);
|
||||
this.method =
|
||||
spy(new EngineGetBlobsV1(vertx, protocolContext, engineCallListener, transactionPool));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnExpectedMethodName() {
|
||||
assertThat(method.getName()).isEqualTo("engine_getBlobsV1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnBlobsAndProofsForKnownVersionedHashesFromMap() {
|
||||
final Transaction blobTransaction = createBlobTransaction();
|
||||
|
||||
final BlobsWithCommitments blobsWithCommitments =
|
||||
blobTransaction.getBlobsWithCommitments().get();
|
||||
|
||||
mockTransactionPoolMethod(blobsWithCommitments);
|
||||
|
||||
VersionedHash[] versionedHashes =
|
||||
blobsWithCommitments.getVersionedHashes().toArray(new VersionedHash[0]);
|
||||
|
||||
final JsonRpcResponse jsonRpcResponse = resp(versionedHashes);
|
||||
|
||||
final List<BlobAndProofV1> blobAndProofV1s = fromSuccessResp(jsonRpcResponse);
|
||||
|
||||
assertThat(blobAndProofV1s.size()).isEqualTo(versionedHashes.length);
|
||||
// for loop to check each blob and proof
|
||||
for (int i = 0; i < versionedHashes.length; i++) {
|
||||
assertThat(Bytes.fromHexString(blobAndProofV1s.get(i).getBlob()))
|
||||
.isEqualTo(blobsWithCommitments.getBlobQuads().get(i).blob().getData());
|
||||
assertThat(Bytes.fromHexString(blobAndProofV1s.get(i).getProof()))
|
||||
.isEqualTo(blobsWithCommitments.getBlobQuads().get(i).kzgProof().getData());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnNullForBlobsAndProofsForUnknownVersionedHashes() {
|
||||
final Transaction blobTransaction = createBlobTransaction();
|
||||
|
||||
final BlobsWithCommitments blobsWithCommitments =
|
||||
blobTransaction.getBlobsWithCommitments().get();
|
||||
|
||||
mockTransactionPoolMethod(blobsWithCommitments);
|
||||
|
||||
List<VersionedHash> versionedHashesList =
|
||||
blobsWithCommitments.getVersionedHashes().stream().toList();
|
||||
|
||||
final VersionedHash[] hashes = versionedHashesList.toArray(new VersionedHash[0]);
|
||||
hashes[1] = VERSIONED_HASH_ZERO;
|
||||
|
||||
final JsonRpcResponse jsonRpcResponse = resp(hashes);
|
||||
|
||||
final List<BlobAndProofV1> blobAndProofV1s = fromSuccessResp(jsonRpcResponse);
|
||||
|
||||
assertThat(blobAndProofV1s.size()).isEqualTo(versionedHashesList.size());
|
||||
// for loop to check each blob and proof
|
||||
for (int i = 0; i < versionedHashesList.size(); i++) {
|
||||
if (i != 1) {
|
||||
assertThat(Bytes.fromHexString(blobAndProofV1s.get(i).getBlob()))
|
||||
.isEqualTo(blobsWithCommitments.getBlobQuads().get(i).blob().getData());
|
||||
assertThat(Bytes.fromHexString(blobAndProofV1s.get(i).getProof()))
|
||||
.isEqualTo(blobsWithCommitments.getBlobQuads().get(i).kzgProof().getData());
|
||||
} else {
|
||||
assertThat(blobAndProofV1s.get(i)).isNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnOnlyNullsForBlobsAndProofsIfAllVersionedHashesUnknown() {
|
||||
final Transaction blobTransaction = createBlobTransaction();
|
||||
|
||||
final BlobsWithCommitments blobsWithCommitments =
|
||||
blobTransaction.getBlobsWithCommitments().get();
|
||||
|
||||
mockTransactionPoolMethod(blobsWithCommitments);
|
||||
|
||||
List<VersionedHash> versionedHashesList =
|
||||
blobsWithCommitments.getVersionedHashes().stream().toList();
|
||||
|
||||
final VersionedHash[] versionedHashes = new VersionedHash[6];
|
||||
Arrays.fill(versionedHashes, VERSIONED_HASH_ZERO);
|
||||
final JsonRpcResponse jsonRpcResponse = resp(versionedHashes);
|
||||
|
||||
final List<BlobAndProofV1> blobAndProofV1s = fromSuccessResp(jsonRpcResponse);
|
||||
|
||||
assertThat(blobAndProofV1s.size()).isEqualTo(versionedHashesList.size());
|
||||
// for loop to check each blob and proof
|
||||
for (int i = 0; i < versionedHashes.length; i++) {
|
||||
assertThat(blobAndProofV1s.get(i)).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEmptyResponseForEmptyRequest() {
|
||||
final VersionedHash[] versionedHashes = new VersionedHash[0];
|
||||
|
||||
final JsonRpcResponse jsonRpcResponse = resp(versionedHashes);
|
||||
|
||||
assertThat(fromSuccessResp(jsonRpcResponse).size()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailWhenRequestingMoreThan128() {
|
||||
final VersionedHash[] versionedHashes = new VersionedHash[129];
|
||||
for (int i = 0; i < 129; i++) {
|
||||
versionedHashes[i] = new VersionedHash((byte) 1, Hash.ZERO);
|
||||
}
|
||||
|
||||
final JsonRpcResponse jsonRpcResponse = resp(versionedHashes);
|
||||
|
||||
assertThat(fromErrorResp(jsonRpcResponse).getCode())
|
||||
.isEqualTo(RpcErrorType.INVALID_ENGINE_GET_BLOBS_V1_TOO_LARGE_REQUEST.getCode());
|
||||
assertThat(fromErrorResp(jsonRpcResponse).getMessage())
|
||||
.isEqualTo(RpcErrorType.INVALID_ENGINE_GET_BLOBS_V1_TOO_LARGE_REQUEST.getMessage());
|
||||
}
|
||||
|
||||
Transaction createBlobTransaction() {
|
||||
BlobTestFixture blobTestFixture = new BlobTestFixture();
|
||||
BlobsWithCommitments bwc = blobTestFixture.createBlobsWithCommitments(6);
|
||||
TransactionTestFixture ttf = new TransactionTestFixture();
|
||||
Transaction fullOfBlobs =
|
||||
ttf.to(Optional.of(Address.ZERO))
|
||||
.type(TransactionType.BLOB)
|
||||
.chainId(Optional.of(BigInteger.valueOf(42)))
|
||||
.gasLimit(21000)
|
||||
.maxFeePerGas(Optional.of(Wei.of(15)))
|
||||
.maxFeePerBlobGas(Optional.of(Wei.of(128)))
|
||||
.maxPriorityFeePerGas(Optional.of(Wei.of(1)))
|
||||
.versionedHashes(Optional.of(bwc.getVersionedHashes()))
|
||||
.blobsWithCommitments(Optional.of(bwc))
|
||||
.createTransaction(KEYS1);
|
||||
return fullOfBlobs;
|
||||
}
|
||||
|
||||
private void mockTransactionPoolMethod(final BlobsWithCommitments blobsWithCommitments) {
|
||||
blobsWithCommitments
|
||||
.getBlobQuads()
|
||||
.forEach(
|
||||
blobQuad ->
|
||||
when(transactionPool.getBlobQuad(blobQuad.versionedHash())).thenReturn(blobQuad));
|
||||
}
|
||||
|
||||
private JsonRpcResponse resp(final VersionedHash[] versionedHashes) {
|
||||
return method.response(
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest(
|
||||
"2.0",
|
||||
RpcMethod.ENGINE_GET_BLOBS_V1.getMethodName(),
|
||||
new Object[] {versionedHashes})));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private List<BlobAndProofV1> fromSuccessResp(final JsonRpcResponse resp) {
|
||||
assertThat(resp.getType()).isEqualTo(RpcResponseType.SUCCESS);
|
||||
final List list =
|
||||
Optional.of(resp)
|
||||
.map(JsonRpcSuccessResponse.class::cast)
|
||||
.map(JsonRpcSuccessResponse::getResult)
|
||||
.map(List.class::cast)
|
||||
.get();
|
||||
final ArrayList<BlobAndProofV1> blobAndProofV1s = new ArrayList<>();
|
||||
list.forEach(obj -> blobAndProofV1s.add((BlobAndProofV1) obj));
|
||||
return blobAndProofV1s;
|
||||
}
|
||||
|
||||
private RpcErrorType fromErrorResp(final JsonRpcResponse resp) {
|
||||
assertThat(resp.getType()).isEqualTo(RpcResponseType.ERROR);
|
||||
return Optional.of(resp)
|
||||
.map(JsonRpcErrorResponse.class::cast)
|
||||
.map(JsonRpcErrorResponse::getErrorType)
|
||||
.get();
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Withdrawal;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -419,7 +420,8 @@ abstract class AbstractBlockCreatorTest {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
|
||||
final MiningParameters miningParameters =
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
@@ -94,7 +95,8 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
return transactionPool;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
@@ -101,7 +102,8 @@ public class LondonFeeMarketBlockTransactionSelectorTest
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
return transactionPool;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
|
||||
import org.hyperledger.besu.ethereum.difficulty.fixed.FixedDifficultyCalculators;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -371,7 +372,8 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
|
||||
return transactionPool;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
@@ -117,7 +118,8 @@ public class PoWMinerExecutorTest {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
poolConf);
|
||||
poolConf,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
|
||||
return transactionPool;
|
||||
|
||||
@@ -181,7 +181,8 @@ public abstract class AbstractIsolationTests {
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
txPoolMetrics,
|
||||
poolConfiguration);
|
||||
poolConfiguration,
|
||||
new BlobCache());
|
||||
transactionPool.setEnabled();
|
||||
}
|
||||
|
||||
|
||||
@@ -87,4 +87,8 @@ public class BlobCache {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public BlobsWithCommitments.BlobQuad get(final VersionedHash vh) {
|
||||
return cache.getIfPresent(vh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TRANSACTION_ALREADY_KNOWN;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.TransactionType;
|
||||
import org.hyperledger.besu.datatypes.VersionedHash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.BlockAddedEvent;
|
||||
@@ -55,6 +57,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.IntSummaryStatistics;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -89,6 +92,7 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TransactionPool.class);
|
||||
private static final Logger LOG_FOR_REPLAY = LoggerFactory.getLogger("LOG_FOR_REPLAY");
|
||||
private final Supplier<PendingTransactions> pendingTransactionsSupplier;
|
||||
private final BlobCache cacheForBlobsOfTransactionsAddedToABlock;
|
||||
private volatile PendingTransactions pendingTransactions = new DisabledPendingTransactions();
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final ProtocolContext protocolContext;
|
||||
@@ -103,6 +107,8 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
private final SaveRestoreManager saveRestoreManager = new SaveRestoreManager();
|
||||
private final Set<Address> localSenders = ConcurrentHashMap.newKeySet();
|
||||
private final EthScheduler.OrderedProcessor<BlockAddedEvent> blockAddedEventOrderedProcessor;
|
||||
private final Map<VersionedHash, BlobsWithCommitments.BlobQuad> mapOfBlobsInTransactionPool =
|
||||
new HashMap<>();
|
||||
|
||||
public TransactionPool(
|
||||
final Supplier<PendingTransactions> pendingTransactionsSupplier,
|
||||
@@ -111,7 +117,8 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
final TransactionBroadcaster transactionBroadcaster,
|
||||
final EthContext ethContext,
|
||||
final TransactionPoolMetrics metrics,
|
||||
final TransactionPoolConfiguration configuration) {
|
||||
final TransactionPoolConfiguration configuration,
|
||||
final BlobCache blobCache) {
|
||||
this.pendingTransactionsSupplier = pendingTransactionsSupplier;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.protocolContext = protocolContext;
|
||||
@@ -121,7 +128,10 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
this.configuration = configuration;
|
||||
this.blockAddedEventOrderedProcessor =
|
||||
ethContext.getScheduler().createOrderedProcessor(this::processBlockAddedEvent);
|
||||
this.cacheForBlobsOfTransactionsAddedToABlock = blobCache;
|
||||
initLogForReplay();
|
||||
subscribePendingTransactions(this::mapBlobsOnTransactionAdded);
|
||||
subscribeDroppedTransactions(this::unmapBlobsOnTransactionDropped);
|
||||
}
|
||||
|
||||
private void initLogForReplay() {
|
||||
@@ -640,6 +650,38 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
private void mapBlobsOnTransactionAdded(
|
||||
final org.hyperledger.besu.datatypes.Transaction transaction) {
|
||||
final Optional<BlobsWithCommitments> maybeBlobsWithCommitments =
|
||||
transaction.getBlobsWithCommitments();
|
||||
if (maybeBlobsWithCommitments.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final List<BlobsWithCommitments.BlobQuad> blobQuads =
|
||||
maybeBlobsWithCommitments.get().getBlobQuads();
|
||||
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.put(bq.versionedHash(), bq));
|
||||
}
|
||||
|
||||
private void unmapBlobsOnTransactionDropped(
|
||||
final org.hyperledger.besu.datatypes.Transaction transaction) {
|
||||
final Optional<BlobsWithCommitments> maybeBlobsWithCommitments =
|
||||
transaction.getBlobsWithCommitments();
|
||||
if (maybeBlobsWithCommitments.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final List<BlobsWithCommitments.BlobQuad> blobQuads =
|
||||
maybeBlobsWithCommitments.get().getBlobQuads();
|
||||
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.remove(bq.versionedHash()));
|
||||
}
|
||||
|
||||
public BlobsWithCommitments.BlobQuad getBlobQuad(final VersionedHash vh) {
|
||||
BlobsWithCommitments.BlobQuad blobQuad = mapOfBlobsInTransactionPool.get(vh);
|
||||
if (blobQuad == null) {
|
||||
blobQuad = cacheForBlobsOfTransactionsAddedToABlock.get(vh);
|
||||
}
|
||||
return blobQuad;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return isPoolEnabled.get();
|
||||
}
|
||||
|
||||
@@ -118,7 +118,8 @@ public class TransactionPoolFactory {
|
||||
newPooledTransactionHashesMessageSender),
|
||||
ethContext,
|
||||
metrics,
|
||||
transactionPoolConfiguration);
|
||||
transactionPoolConfiguration,
|
||||
blobCache);
|
||||
|
||||
final TransactionsMessageHandler transactionsMessageHandler =
|
||||
new TransactionsMessageHandler(
|
||||
|
||||
@@ -293,7 +293,8 @@ public abstract class AbstractTransactionPoolTest {
|
||||
transactionBroadcaster,
|
||||
ethContext,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConfig);
|
||||
poolConfig,
|
||||
new BlobCache());
|
||||
txPool.setEnabled();
|
||||
return txPool;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user