-
Notifications
You must be signed in to change notification settings - Fork 860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement engine_getBlobsV1 #7553
Conversation
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
...src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlobAndProofV1.java
Outdated
Show resolved
Hide resolved
return blobQuad; | ||
} | ||
|
||
public void onTransactionAdded(final Transaction transaction) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idk if the RPC should be itself managing the blob cache?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering where that should live. The other option would be the TransactionPool. The BlobCache is taken care of in the TransactionPool, because these blobs are needed in case we have a reorg.
The blobMap is not needed by the TransactionPool. Here we just keep track of the blobs that we have available in our transaction pool and we have to update the map when blob transactions are added or removed from the pool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved that logic into the TransactionPool
.../org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetBlobsV1Test.java
Outdated
Show resolved
Hide resolved
@@ -371,7 +372,8 @@ private TransactionPool createTransactionPool( | |||
mock(TransactionBroadcaster.class), | |||
ethContext, | |||
new TransactionPoolMetrics(metricsSystem), | |||
poolConf); | |||
poolConf, | |||
new BlobCache()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jflo can we daggerise the BlobCache or does it need other infra first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is kind of daggerised. It is available in BesuComponent, but I did not know how to use that in the engine RPC. Maybe @jflo can tell us!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make this a more complete approach, the RPC and the TransactionPool would need to be daggerized as well, which would allow all intermediate references to be removed.
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
…sonrpc/internal/methods/engine/EngineGetBlobsV1Test.java Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, see the note on the of passing blobCache
, then add a changelog entry and doc-change-required label
if (blobQuad == null) { | ||
blobQuad = blobCache.get(vh); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in theory this fallback should not be necessary, and removing the need to have the blobCache
will simplify a lot the change, removing the need to pass it around, or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't understand. It seems to me that blobMap is redundant, and this RPC should just use the same instance of the blobCache that the transactionpool does. Management of the cache contents should be ignored by the RPC and treated as a "read only" concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The blob cache does contain all the blobs that have been put into a block recently. These blobs are used to re-add the blob transactions in case of a reorg, as the blobs are not part of the block. After 3 epochs these blobs are removed from the cache. Blobs that are in the cache are not part of Transactions that are in the pool.
The blob map keeps track of all the blobs that are part of transactions that are in our transaction pool. These are the blobs that the CL will most likely ask for. We do keep them in the map for as long as their transactions are in the transaction pool.
@fab-10 @jflo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the specification of the new method, the CL should be interested in blobs that are in the txpool, and not blobs that have been already included in a block, so blobMap
should be enough, because in case of a reorg a new add notification will be sent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to remove the responsibility of managing blobs from the RPC method.
if (blobQuad == null) { | ||
blobQuad = blobCache.get(vh); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't understand. It seems to me that blobMap is redundant, and this RPC should just use the same instance of the blobCache that the transactionpool does. Management of the cache contents should be ignored by the RPC and treated as a "read only" concern.
*/ | ||
public class EngineGetBlobsV1 extends ExecutionEngineJsonRpcMethod { | ||
|
||
private final Map<VersionedHash, BlobsWithCommitments.BlobQuad> blobMap = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think naming this something more specific would help me understand why it is necessary. As is, it reads like a synonym for blobCache, and seems like duplication.
@@ -371,7 +372,8 @@ private TransactionPool createTransactionPool( | |||
mock(TransactionBroadcaster.class), | |||
ethContext, | |||
new TransactionPoolMetrics(metricsSystem), | |||
poolConf); | |||
poolConf, | |||
new BlobCache()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make this a more complete approach, the RPC and the TransactionPool would need to be daggerized as well, which would allow all intermediate references to be removed.
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
@@ -104,6 +107,7 @@ 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> blobMap = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about a more talking name, like liveBlobs
or pendingBlobs
?
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 -> blobMap.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 -> blobMap.remove(bq.versionedHash())); | ||
} | ||
|
||
public BlobsWithCommitments.BlobQuad getBlobQuad(final VersionedHash vh) { | ||
BlobsWithCommitments.BlobQuad blobQuad = blobMap.get(vh); | ||
if (blobQuad == null) { | ||
blobQuad = blobCache.get(vh); | ||
} | ||
return blobQuad; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is better to have the logic here, and I am tempted to suggest to go a step further and extending the current BlobCache
to manage both the confirmed blobs, as it does now, plus those pending blobs. (However not a blocking request, just a suggestion to manage blobs in a single place)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about that as well, but it felt like these are two different concerns and I think that the "map" should be part of the Transaction pool, as it points to the blobs of transactions in the pool.
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better. The only suggestion I have would be to consider using another instance of BlobCache internally for the pooled transaction, instead of just a map. That would afford some protection from unexpected cache growth, but I think trusting the add/drop tx events is a safe assumption.
That's a good point, and in the related PRs that are fixing the notifications in the layered txpool, I will make sure they are reliable, but I think it is worth to export a metrics with the size of the map, so we can monitor its growth, but this could be part of a following PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just move the changelog entry to the right place, and add doc-change-required
label
CHANGELOG.md
Outdated
@@ -26,6 +26,7 @@ | |||
- Performance optimzation for ECMUL (2 of 2) [#7543](https://github.com/hyperledger/besu/pull/7543) | |||
- Include current chain head block when computing `eth_maxPriorityFeePerGas` [#7485](https://github.com/hyperledger/besu/pull/7485) | |||
- Remove (old) documentation updates from the changelog [#7562](https://github.com/hyperledger/besu/pull/7562) | |||
- Add `engine_getBlobsV1` method to the Engine API [#7553](https://github.com/hyperledger/besu/pull/7553) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to move this to the Unreleased section
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ups! Fixed!
FYI: task for adding the metrics #7578 |
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
@@ -40,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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
} | ||
final List<BlobsWithCommitments.BlobQuad> blobQuads = | ||
maybeBlobsWithCommitments.get().getBlobQuads(); | ||
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.put(bq.versionedHash(), bq)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be used my a malicious transaction to corrupt the mapping by sending the same blobs as a benign tx. Then send a replacement to nuke out all blobs, and the original correct mapping disappears, making the blob non-retrievable any more.
PR description
Implements the engine RPC engine_getBlobsV1 as described in ethereum/execution-apis#559
Fixed Issue(s)
#7445