Skip to content

implement engine_getBlobsV1#7553

Merged
pinges merged 16 commits intobesu-eth:mainfrom
pinges:engine_getBlobV1
Sep 6, 2024
Merged

implement engine_getBlobsV1#7553
pinges merged 16 commits intobesu-eth:mainfrom
pinges:engine_getBlobV1

Conversation

@pinges
Copy link
Copy Markdown
Contributor

@pinges pinges commented Sep 2, 2024

PR description

Implements the engine RPC engine_getBlobsV1 as described in ethereum/execution-apis#559

Fixed Issue(s)

#7445

Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
return blobQuad;
}

public void onTransactionAdded(final Transaction transaction) {
Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Contributor Author

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.

Copy link
Copy Markdown
Contributor Author

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

new TransactionPoolMetrics(metricsSystem),
poolConf);
poolConf,
new BlobCache());
Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Contributor Author

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!

Copy link
Copy Markdown
Contributor

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.

pinges and others added 3 commits September 3, 2024 13:20
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>
Copy link
Copy Markdown
Contributor

@fab-10 fab-10 left a 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

Comment on lines +127 to +129
if (blobQuad == null) {
blobQuad = blobCache.get(vh);
}
Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Contributor Author

@pinges pinges Sep 4, 2024

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

Copy link
Copy Markdown
Contributor

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.

@fab-10
Copy link
Copy Markdown
Contributor

fab-10 commented Sep 3, 2024

@pinges note that #7539 and #7538 are a prerequisite for this one, otherwise it will not work correctly, so please do not merge it before the other 2 are in.

Copy link
Copy Markdown
Contributor

@jflo jflo left a 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.

Comment on lines +127 to +129
if (blobQuad == null) {
blobQuad = blobCache.get(vh);
}
Copy link
Copy Markdown
Contributor

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<>();
Copy link
Copy Markdown
Contributor

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.

new TransactionPoolMetrics(metricsSystem),
poolConf);
poolConf,
new BlobCache());
Copy link
Copy Markdown
Contributor

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.

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<>();
Copy link
Copy Markdown
Contributor

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?

Comment on lines +656 to +687
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;
}

Copy link
Copy Markdown
Contributor

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)

Copy link
Copy Markdown
Contributor Author

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.

@pinges pinges requested a review from jflo September 5, 2024 10:00
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Copy link
Copy Markdown
Contributor

@jflo jflo left a 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.

@fab-10
Copy link
Copy Markdown
Contributor

fab-10 commented Sep 5, 2024

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.

Copy link
Copy Markdown
Contributor

@fab-10 fab-10 left a 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
- 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)
Copy link
Copy Markdown
Contributor

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ups! Fixed!

@fab-10
Copy link
Copy Markdown
Contributor

fab-10 commented Sep 5, 2024

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>
@pinges pinges enabled auto-merge (squash) September 5, 2024 23:43
@pinges pinges added the doc-change-required Indicates an issue or PR that requires doc to be updated label Sep 5, 2024
- 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)

### Bug fixes
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

@pinges pinges merged commit cf592c4 into besu-eth:main Sep 6, 2024
@m4sterbunny m4sterbunny removed the doc-change-required Indicates an issue or PR that requires doc to be updated label Sep 23, 2024
}
final List<BlobsWithCommitments.BlobQuad> blobQuads =
maybeBlobsWithCommitments.get().getBlobQuads();
blobQuads.forEach(bq -> mapOfBlobsInTransactionPool.put(bq.versionedHash(), bq));
Copy link
Copy Markdown

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants