mirror of https://github.com/hyperledger/besu
Cached blob txs (#6147)
* basic test coverage * blob caching on tx removal in legacy pool * blob caching on tx removal in layered pool * blob restoral in both legacy and layered implementations and test coverage of tx copy in builder * refactors into reusable BlobCache, and rekeys on versioned hash --------- Signed-off-by: Justin Florentine <justin+github@florentine.us> Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net>pull/6172/head
parent
0ccb4d4400
commit
488755a728
@ -0,0 +1,91 @@ |
|||||||
|
/* |
||||||
|
* 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.eth.transactions; |
||||||
|
|
||||||
|
import org.hyperledger.besu.datatypes.BlobsWithCommitments; |
||||||
|
import org.hyperledger.besu.datatypes.VersionedHash; |
||||||
|
import org.hyperledger.besu.ethereum.core.Transaction; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache; |
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
public class BlobCache { |
||||||
|
private final Cache<VersionedHash, BlobsWithCommitments.BlobQuad> cache; |
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(BlobCache.class); |
||||||
|
|
||||||
|
public BlobCache() { |
||||||
|
this.cache = |
||||||
|
Caffeine.newBuilder() |
||||||
|
.maximumSize(6 * 32 * 3L) // 6 blobs max per 32 slots per 3 epochs
|
||||||
|
.expireAfterWrite( |
||||||
|
3 * 32 * 12L, TimeUnit.SECONDS) // 3 epochs of 32 slots which take 12 seconds each.
|
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
public void cacheBlobs(final Transaction t) { |
||||||
|
if (t.getType().supportsBlob()) { |
||||||
|
var bwc = t.getBlobsWithCommitments(); |
||||||
|
if (bwc.isPresent()) { |
||||||
|
bwc.get().getBlobQuads().stream() |
||||||
|
.forEach(blobQuad -> this.cache.put(blobQuad.versionedHash(), blobQuad)); |
||||||
|
} else { |
||||||
|
LOG.debug("transaction is missing blobs, cannot cache"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Optional<Transaction> restoreBlob(final Transaction transaction) { |
||||||
|
if (transaction.getType().supportsBlob()) { |
||||||
|
Optional<List<VersionedHash>> maybeHashes = transaction.getVersionedHashes(); |
||||||
|
if (maybeHashes.isPresent()) { |
||||||
|
if (!maybeHashes.get().isEmpty()) { |
||||||
|
Transaction.Builder txBuilder = Transaction.builder(); |
||||||
|
txBuilder.copiedFrom(transaction); |
||||||
|
List<BlobsWithCommitments.BlobQuad> blobQuads = |
||||||
|
maybeHashes.get().stream().map(cache::getIfPresent).toList(); |
||||||
|
final BlobsWithCommitments bwc = new BlobsWithCommitments(blobQuads); |
||||||
|
if (blobQuads.stream() |
||||||
|
.map(BlobsWithCommitments.BlobQuad::versionedHash) |
||||||
|
.toList() |
||||||
|
.containsAll(maybeHashes.get())) { |
||||||
|
txBuilder.blobsWithCommitments(bwc); |
||||||
|
return Optional.of(txBuilder.build()); |
||||||
|
} else { |
||||||
|
LOG.debug("did not find all versioned hashes to restore from cache"); |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
LOG.warn("can't restore blobs for transaction with empty list of versioned hashes"); |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
LOG.warn("can't restore blobs for transaction without list of versioned hashes"); |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
LOG.debug( |
||||||
|
"can't restore blobs for non-blob transaction of type {}", transaction.getType().name()); |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* |
||||||
|
* 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.eth.transactions; |
||||||
|
|
||||||
|
import javax.inject.Singleton; |
||||||
|
|
||||||
|
import dagger.Module; |
||||||
|
import dagger.Provides; |
||||||
|
|
||||||
|
@Module |
||||||
|
public class BlobCacheModule { |
||||||
|
|
||||||
|
@Provides |
||||||
|
@Singleton |
||||||
|
public BlobCache provideBlobCache() { |
||||||
|
return new BlobCache(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue