diff --git a/besu/src/main/java/org/hyperledger/besu/components/BesuComponent.java b/besu/src/main/java/org/hyperledger/besu/components/BesuComponent.java index 005008ef62..0edc5f15e4 100644 --- a/besu/src/main/java/org/hyperledger/besu/components/BesuComponent.java +++ b/besu/src/main/java/org/hyperledger/besu/components/BesuComponent.java @@ -19,6 +19,8 @@ package org.hyperledger.besu.components; import org.hyperledger.besu.cli.BesuCommand; import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoaderModule; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule; import org.hyperledger.besu.metrics.MetricsSystemModule; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.services.BesuPluginContextImpl; @@ -36,7 +38,8 @@ import org.slf4j.Logger; BesuCommandModule.class, MetricsSystemModule.class, CachedMerkleTrieLoaderModule.class, - BesuPluginContextModule.class + BesuPluginContextModule.class, + BlobCacheModule.class }) public interface BesuComponent { @@ -72,8 +75,15 @@ public interface BesuComponent { /** * Besu plugin context for doing plugin service discovery. * - * @return BesuComponent + * @return BesuPluginContextImpl */ @Named("besuPluginContext") BesuPluginContextImpl getBesuPluginContext(); + + /** + * Cache to store blobs in for re-use after reorgs. + * + * @return BlobCache + */ + BlobCache getBlobCache(); } diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 1d3c96aea6..ab05e7d9df 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -73,6 +73,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint; import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.ImmutableCheckpoint; import org.hyperledger.besu.ethereum.eth.sync.fullsync.SyncTerminationCondition; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory; @@ -722,7 +723,8 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides syncState, miningParameters, transactionPoolConfiguration, - pluginTransactionValidatorFactory); + pluginTransactionValidatorFactory, + besuComponent.map(BesuComponent::getBlobCache).orElse(new BlobCache())); final List peerValidators = createPeerValidators(protocolSchedule); diff --git a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java index 921d4e7fbe..6eaa113893 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java @@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.sync.BlockBroadcaster; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; @@ -161,7 +162,8 @@ public class BesuEventsImplTest { MutableInitValues.builder().minTransactionGasPrice(Wei.ZERO).build()) .build(), txPoolConfig, - null); + null, + new BlobCache()); serviceImpl = new BesuEventsImpl(blockchain, blockBroadcaster, transactionPool, syncState); } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Blob.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Blob.java index 5b08991970..b753f2dc16 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Blob.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Blob.java @@ -17,6 +17,8 @@ package org.hyperledger.besu.datatypes; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; +import java.util.Objects; + import org.apache.tuweni.bytes.Bytes; /** Arbitrary data for use in the KZG scheme. */ @@ -61,4 +63,17 @@ public class Blob { public Bytes getData() { return data; } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Blob blob = (Blob) o; + return Objects.equals(getData(), blob.getData()); + } + + @Override + public int hashCode() { + return Objects.hash(getData()); + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobsWithCommitments.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobsWithCommitments.java index 7a4f0f4de6..281d3ada68 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobsWithCommitments.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobsWithCommitments.java @@ -15,15 +15,18 @@ package org.hyperledger.besu.datatypes; import java.security.InvalidParameterException; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** A class to hold the blobs, commitments, proofs and versioned hashes for a set of blobs. */ public class BlobsWithCommitments { - private final List kzgCommitments; - private final List blobs; - private final List kzgProofs; - private final List versionedHashes; + /** A record to hold the blob, commitment, proof and versioned hash for a blob. */ + public record BlobQuad( + Blob blob, KZGCommitment kzgCommitment, KZGProof kzgProof, VersionedHash versionedHash) {} + + private final List blobQuads; /** * A class to hold the blobs, commitments and proofs for a set of blobs. @@ -38,7 +41,7 @@ public class BlobsWithCommitments { final List blobs, final List kzgProofs, final List versionedHashes) { - if (blobs.size() == 0) { + if (blobs.isEmpty()) { throw new InvalidParameterException( "There needs to be a minimum of one blob in a blob transaction with commitments"); } @@ -48,10 +51,22 @@ public class BlobsWithCommitments { throw new InvalidParameterException( "There must be an equal number of blobs, commitments, proofs, and versioned hashes"); } - this.kzgCommitments = kzgCommitments; - this.blobs = blobs; - this.kzgProofs = kzgProofs; - this.versionedHashes = versionedHashes; + List toBuild = new ArrayList<>(blobs.size()); + for (int i = 0; i < blobs.size(); i++) { + toBuild.add( + new BlobQuad( + blobs.get(i), kzgCommitments.get(i), kzgProofs.get(i), versionedHashes.get(i))); + } + this.blobQuads = toBuild; + } + + /** + * Construct the class from a list of BlobQuads. + * + * @param quads the list of blob quads to be attached to the transaction + */ + public BlobsWithCommitments(final List quads) { + this.blobQuads = quads; } /** @@ -60,7 +75,7 @@ public class BlobsWithCommitments { * @return the blobs */ public List getBlobs() { - return blobs; + return blobQuads.stream().map(BlobQuad::blob).toList(); } /** @@ -69,7 +84,7 @@ public class BlobsWithCommitments { * @return the commitments */ public List getKzgCommitments() { - return kzgCommitments; + return blobQuads.stream().map(BlobQuad::kzgCommitment).toList(); } /** @@ -78,7 +93,7 @@ public class BlobsWithCommitments { * @return the proofs */ public List getKzgProofs() { - return kzgProofs; + return blobQuads.stream().map(BlobQuad::kzgProof).toList(); } /** @@ -87,6 +102,28 @@ public class BlobsWithCommitments { * @return the hashes */ public List getVersionedHashes() { - return versionedHashes; + return blobQuads.stream().map(BlobQuad::versionedHash).toList(); + } + + /** + * Get the list of BlobQuads. + * + * @return blob quads + */ + public List getBlobQuads() { + return blobQuads; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BlobsWithCommitments that = (BlobsWithCommitments) o; + return Objects.equals(getBlobQuads(), that.getBlobQuads()); + } + + @Override + public int hashCode() { + return Objects.hash(getBlobQuads()); } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java index de2195887b..d9d2e477da 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java @@ -17,6 +17,8 @@ package org.hyperledger.besu.datatypes; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; +import java.util.Objects; + import org.apache.tuweni.bytes.Bytes48; /** This class contains the data for a KZG commitment. */ @@ -60,4 +62,17 @@ public class KZGCommitment { public Bytes48 getData() { return data; } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + KZGCommitment that = (KZGCommitment) o; + return Objects.equals(getData(), that.getData()); + } + + @Override + public int hashCode() { + return Objects.hash(getData()); + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java index 6410609e23..7d8b3aa186 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java @@ -17,6 +17,8 @@ package org.hyperledger.besu.datatypes; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; +import java.util.Objects; + import org.apache.tuweni.bytes.Bytes48; /** This class contains the data for a KZG proof for a KZG commitment. */ @@ -60,4 +62,17 @@ public class KZGProof { public Bytes48 getData() { return data; } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + KZGProof kzgProof = (KZGProof) o; + return Objects.equals(getData(), kzgProof.getData()); + } + + @Override + public int hashCode() { + return Objects.hash(getData()); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index 9d51e1a3c1..f2c9d59e9b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -1096,6 +1096,26 @@ public class Transaction protected List versionedHashes = null; private BlobsWithCommitments blobsWithCommitments; + public Builder copiedFrom(final Transaction toCopy) { + this.transactionType = toCopy.transactionType; + this.nonce = toCopy.nonce; + this.gasPrice = toCopy.gasPrice.orElse(null); + this.maxPriorityFeePerGas = toCopy.maxPriorityFeePerGas.orElse(null); + this.maxFeePerGas = toCopy.maxFeePerGas.orElse(null); + this.maxFeePerBlobGas = toCopy.maxFeePerBlobGas.orElse(null); + this.gasLimit = toCopy.gasLimit; + this.to = toCopy.to; + this.value = toCopy.value; + this.signature = toCopy.signature; + this.payload = toCopy.payload; + this.accessList = toCopy.maybeAccessList; + this.sender = toCopy.sender; + this.chainId = toCopy.chainId; + this.versionedHashes = toCopy.versionedHashes.orElse(null); + this.blobsWithCommitments = toCopy.blobsWithCommitments.orElse(null); + return this; + } + public Builder type(final TransactionType transactionType) { this.transactionType = transactionType; return this; @@ -1260,5 +1280,10 @@ public class Transaction new BlobsWithCommitments(kzgCommitments, blobs, kzgProofs, versionedHashes); return this; } + + public Builder blobsWithCommitments(final BlobsWithCommitments blobsWithCommitments) { + this.blobsWithCommitments = blobsWithCommitments; + return this; + } } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java index 933e6b3ce0..d016b7f4e5 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java @@ -85,12 +85,12 @@ public class TransactionTestFixture { builder.maxFeePerGas(maxFeePerGas.orElse(Wei.of(5000))); builder.accessList(accessListEntries.orElse(List.of())); builder.maxFeePerBlobGas(maxFeePerBlobGas.orElse(Wei.ONE)); - builder.versionedHashes( - versionedHashes.orElse(List.of(VersionedHash.DEFAULT_VERSIONED_HASH))); - blobs.ifPresent( - bwc -> { - builder.kzgBlobs(bwc.getKzgCommitments(), bwc.getBlobs(), bwc.getKzgProofs()); - }); + if (blobs.isPresent()) { + builder.kzgBlobs( + blobs.get().getKzgCommitments(), blobs.get().getBlobs(), blobs.get().getKzgProofs()); + } else if (versionedHashes.isPresent()) { + builder.versionedHashes(versionedHashes.get()); + } break; } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java index 62ce7a56d7..5fe3b43404 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/AbstractIsolationTests.java @@ -50,6 +50,7 @@ import org.hyperledger.besu.ethereum.core.Transaction; 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.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; @@ -127,7 +128,8 @@ public abstract class AbstractIsolationTests { poolConfiguration, new EndLayer(txPoolMetrics), txPoolMetrics, - transactionReplacementTester)); + transactionReplacementTester, + new BlobCache())); protected final List accounts = GenesisConfigFile.development() diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionBuilderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionBuilderTest.java index b06a63cb95..91d19c28dc 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionBuilderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionBuilderTest.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.core; import static java.util.stream.Collectors.toUnmodifiableSet; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import org.hyperledger.besu.crypto.KeyPair; @@ -25,6 +26,7 @@ import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import java.math.BigInteger; import java.util.List; @@ -36,13 +38,13 @@ import java.util.stream.Stream; import com.google.common.base.Suppliers; import org.junit.jupiter.api.Test; -public class TransactionBuilderTest { +class TransactionBuilderTest { private static final Supplier SIGNATURE_ALGORITHM = Suppliers.memoize(SignatureAlgorithmFactory::getInstance); private static final KeyPair senderKeys = SIGNATURE_ALGORITHM.get().generateKeyPair(); @Test - public void guessTypeCanGuessAllTypes() { + void guessTypeCanGuessAllTypes() { final BlockDataGenerator gen = new BlockDataGenerator(); final Transaction.Builder frontierBuilder = Transaction.builder(); final Transaction.Builder eip1559Builder = Transaction.builder().maxFeePerGas(Wei.of(5)); @@ -61,19 +63,36 @@ public class TransactionBuilderTest { } @Test - public void zeroBlobTransactionIsInvalid() { + void zeroBlobTransactionIsInvalid() { + TransactionTestFixture ttf = + new TransactionTestFixture() + .type(TransactionType.BLOB) + .chainId(Optional.of(BigInteger.ONE)) + .versionedHashes(Optional.of(List.of())) + .maxFeePerGas(Optional.of(Wei.of(5))) + .maxPriorityFeePerGas(Optional.of(Wei.of(5))) + .maxFeePerBlobGas(Optional.of(Wei.of(5))); try { - new TransactionTestFixture() - .type(TransactionType.BLOB) - .chainId(Optional.of(BigInteger.ONE)) - .versionedHashes(Optional.of(List.of())) - .maxFeePerGas(Optional.of(Wei.of(5))) - .maxPriorityFeePerGas(Optional.of(Wei.of(5))) - .maxFeePerBlobGas(Optional.of(Wei.of(5))) - .createTransaction(senderKeys); + ttf.createTransaction(senderKeys); fail(); } catch (IllegalArgumentException iea) { assertThat(iea).hasMessage("Blob transaction must have at least one versioned hash"); } } + + @Test + @SuppressWarnings("ReferenceEquality") + void copyFromIsIdentical() { + final TransactionTestFixture fixture = new TransactionTestFixture(); + final Transaction transaction = fixture.createTransaction(senderKeys); + final Transaction.Builder builder = Transaction.builder(); + final Transaction copy = builder.copiedFrom(transaction).build(); + assertThat(copy).isEqualTo(transaction).isNotSameAs(transaction); + assertThat(copy.getHash()).isEqualTo(transaction.getHash()); + BytesValueRLPOutput sourceRLP = new BytesValueRLPOutput(); + transaction.writeTo(sourceRLP); + BytesValueRLPOutput copyRLP = new BytesValueRLPOutput(); + copy.writeTo(copyRLP); + assertEquals(sourceRLP.encoded(), copyRLP.encoded()); + } } diff --git a/ethereum/eth/build.gradle b/ethereum/eth/build.gradle index 1919efdd4f..b51088f4cf 100644 --- a/ethereum/eth/build.gradle +++ b/ethereum/eth/build.gradle @@ -59,6 +59,9 @@ dependencies { implementation 'io.tmio:tuweni-units' implementation 'io.tmio:tuweni-rlp' implementation 'org.rocksdb:rocksdbjni' + implementation 'com.github.ben-manes.caffeine:caffeine' + implementation 'com.google.dagger:dagger' + annotationProcessor 'com.google.dagger:dagger-compiler' annotationProcessor "org.immutables:value" implementation "org.immutables:value-annotations" diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java new file mode 100644 index 0000000000..980f01ed7a --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCache.java @@ -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 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 restoreBlob(final Transaction transaction) { + if (transaction.getType().supportsBlob()) { + Optional> maybeHashes = transaction.getVersionedHashes(); + if (maybeHashes.isPresent()) { + if (!maybeHashes.get().isEmpty()) { + Transaction.Builder txBuilder = Transaction.builder(); + txBuilder.copiedFrom(transaction); + List 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(); + } + } +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCacheModule.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCacheModule.java new file mode 100644 index 0000000000..29ca246232 --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/BlobCacheModule.java @@ -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(); + } +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/DisabledPendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/DisabledPendingTransactions.java index de9d6a07e8..c52876ced7 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/DisabledPendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/DisabledPendingTransactions.java @@ -116,4 +116,9 @@ public class DisabledPendingTransactions implements PendingTransactions { public String logStats() { return "Disabled"; } + + @Override + public Optional restoreBlob(final Transaction transaction) { + return Optional.empty(); + } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java index dbc461ecc3..a622507b19 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java @@ -44,7 +44,7 @@ public abstract class PendingTransaction static final int BASE_OPTIONAL_SIZE = 16; static final int KZG_COMMITMENT_OR_PROOF_SIZE = 112; static final int BLOB_SIZE = 131136; - static final int BLOBS_WITH_COMMITMENTS_SIZE = 32; + static final int BLOBS_WITH_COMMITMENTS_SIZE = 40; static final int PENDING_TRANSACTION_MEMORY_SIZE = 40; private static final AtomicLong TRANSACTIONS_ADDED = new AtomicLong(); private final Transaction transaction; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java index 256a8af75a..dbb95edd82 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactions.java @@ -72,6 +72,8 @@ public interface PendingTransactions { String logStats(); + Optional restoreBlob(Transaction transaction); + @FunctionalInterface interface TransactionSelector { TransactionSelectionResult evaluateTransaction(PendingTransaction pendingTransaction); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java index a8b6122e5a..779523ae27 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java @@ -373,8 +373,11 @@ public class TransactionPool implements BlockAddedObserver { private void reAddTransactions(final List reAddTransactions) { if (!reAddTransactions.isEmpty()) { + // if adding a blob tx, and it is missing its blob, is a re-org and we should restore the blob + // from cache. var txsByOrigin = reAddTransactions.stream() + .map(t -> pendingTransactions.restoreBlob(t).orElse(t)) .collect(Collectors.partitioningBy(tx -> isLocalSender(tx.getSender()))); var reAddLocalTxs = txsByOrigin.get(true); var reAddRemoteTxs = txsByOrigin.get(false); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java index 12cd2dc7e0..0f620653f1 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactory.java @@ -56,7 +56,8 @@ public class TransactionPoolFactory { final SyncState syncState, final MiningParameters miningParameters, final TransactionPoolConfiguration transactionPoolConfiguration, - final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) { + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory, + final BlobCache blobCache) { final TransactionPoolMetrics metrics = new TransactionPoolMetrics(metricsSystem); @@ -79,7 +80,8 @@ public class TransactionPoolFactory { transactionTracker, transactionsMessageSender, newPooledTransactionHashesMessageSender, - pluginTransactionValidatorFactory); + pluginTransactionValidatorFactory, + blobCache); } static TransactionPool createTransactionPool( @@ -94,7 +96,8 @@ public class TransactionPoolFactory { final PeerTransactionTracker transactionTracker, final TransactionsMessageSender transactionsMessageSender, final NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender, - final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) { + final PluginTransactionValidatorFactory pluginTransactionValidatorFactory, + final BlobCache blobCache) { final TransactionPool transactionPool = new TransactionPool( @@ -104,7 +107,8 @@ public class TransactionPoolFactory { protocolContext, clock, metrics, - transactionPoolConfiguration), + transactionPoolConfiguration, + blobCache), protocolSchedule, protocolContext, new TransactionBroadcaster( @@ -195,7 +199,8 @@ public class TransactionPoolFactory { final ProtocolContext protocolContext, final Clock clock, final TransactionPoolMetrics metrics, - final TransactionPoolConfiguration transactionPoolConfiguration) { + final TransactionPoolConfiguration transactionPoolConfiguration, + final BlobCache blobCache) { boolean isFeeMarketImplementBaseFee = protocolSchedule.anyMatch( @@ -207,7 +212,8 @@ public class TransactionPoolFactory { protocolContext, metrics, transactionPoolConfiguration, - isFeeMarketImplementBaseFee); + isFeeMarketImplementBaseFee, + blobCache); } else { return createPendingTransactionSorter( protocolContext, @@ -244,7 +250,8 @@ public class TransactionPoolFactory { final ProtocolContext protocolContext, final TransactionPoolMetrics metrics, final TransactionPoolConfiguration transactionPoolConfiguration, - final boolean isFeeMarketImplementBaseFee) { + final boolean isFeeMarketImplementBaseFee, + final BlobCache blobCache) { final TransactionPoolReplacementHandler transactionReplacementHandler = new TransactionPoolReplacementHandler(transactionPoolConfiguration.getPriceBump()); @@ -258,14 +265,19 @@ public class TransactionPoolFactory { final SparseTransactions sparseTransactions = new SparseTransactions( - transactionPoolConfiguration, endLayer, metrics, transactionReplacementTester); + transactionPoolConfiguration, + endLayer, + metrics, + transactionReplacementTester, + blobCache); final ReadyTransactions readyTransactions = new ReadyTransactions( transactionPoolConfiguration, sparseTransactions, metrics, - transactionReplacementTester); + transactionReplacementTester, + blobCache); final AbstractPrioritizedTransactions pendingTransactionsSorter; if (isFeeMarketImplementBaseFee) { @@ -281,14 +293,16 @@ public class TransactionPoolFactory { readyTransactions, metrics, transactionReplacementTester, - feeMarket); + feeMarket, + blobCache); } else { pendingTransactionsSorter = new GasPricePrioritizedTransactions( transactionPoolConfiguration, readyTransactions, metrics, - transactionReplacementTester); + transactionReplacementTester, + blobCache); } return new LayeredPendingTransactions(transactionPoolConfiguration, pendingTransactionsSorter); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java index f57e6f9506..7d59f40afb 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractPrioritizedTransactions.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.eth.transactions.layered; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; @@ -41,8 +42,9 @@ public abstract class AbstractPrioritizedTransactions extends AbstractSequential final TransactionsLayer prioritizedTransactions, final TransactionPoolMetrics metrics, final BiFunction - transactionReplacementTester) { - super(poolConfig, prioritizedTransactions, transactionReplacementTester, metrics); + transactionReplacementTester, + final BlobCache blobCache) { + super(poolConfig, prioritizedTransactions, transactionReplacementTester, metrics, blobCache); this.orderByFee = new TreeSet<>(this::compareByFee); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractSequentialTransactionsLayer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractSequentialTransactionsLayer.java index 7b1915020b..9596f6fefb 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractSequentialTransactionsLayer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractSequentialTransactionsLayer.java @@ -18,6 +18,7 @@ import static org.hyperledger.besu.ethereum.eth.transactions.layered.Transaction import static org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer.RemovalReason.FOLLOW_INVALIDATED; import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -36,8 +37,9 @@ public abstract class AbstractSequentialTransactionsLayer extends AbstractTransa final TransactionsLayer nextLayer, final BiFunction transactionReplacementTester, - final TransactionPoolMetrics metrics) { - super(poolConfig, nextLayer, transactionReplacementTester, metrics); + final TransactionPoolMetrics metrics, + final BlobCache blobCache) { + super(poolConfig, nextLayer, transactionReplacementTester, metrics, blobCache); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java index 136f80499c..a323b6833e 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractTransactionsLayer.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionAddedListener; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionDroppedListener; @@ -74,12 +75,15 @@ public abstract class AbstractTransactionsLayer implements TransactionsLayer { private OptionalLong nextLayerOnDroppedListenerId = OptionalLong.empty(); protected long spaceUsed = 0; - public AbstractTransactionsLayer( + private final BlobCache blobCache; + + protected AbstractTransactionsLayer( final TransactionPoolConfiguration poolConfig, final TransactionsLayer nextLayer, final BiFunction transactionReplacementTester, - final TransactionPoolMetrics metrics) { + final TransactionPoolMetrics metrics, + final BlobCache blobCache) { this.poolConfig = poolConfig; this.nextLayer = nextLayer; this.transactionReplacementTester = transactionReplacementTester; @@ -87,6 +91,7 @@ public abstract class AbstractTransactionsLayer implements TransactionsLayer { metrics.initSpaceUsed(this::getLayerSpaceUsed, name()); metrics.initTransactionCount(pendingTransactions::size, name()); metrics.initUniqueSenderCount(txsBySender::size, name()); + this.blobCache = blobCache; } protected abstract boolean gapsAllowed(); @@ -361,6 +366,7 @@ public abstract class AbstractTransactionsLayer implements TransactionsLayer { final Transaction transaction, final RemovalReason removalReason) { final PendingTransaction removedTx = pendingTransactions.remove(transaction.getHash()); + if (removedTx != null) { decreaseSpaceUsed(removedTx); metrics.incrementRemoved(removedTx, removalReason.label(), name()); @@ -428,6 +434,9 @@ public abstract class AbstractTransactionsLayer implements TransactionsLayer { while (itConfirmedTxs.hasNext()) { final var confirmedTx = itConfirmedTxs.next(); itConfirmedTxs.remove(); + if (confirmedTx.getTransaction().getBlobsWithCommitments().isPresent()) { + this.blobCache.cacheBlobs(confirmedTx.getTransaction()); + } processRemove(senderTxs, confirmedTx.getTransaction(), CONFIRMED); metrics.incrementRemoved(confirmedTx, "confirmed", name()); @@ -598,4 +607,8 @@ public abstract class AbstractTransactionsLayer implements TransactionsLayer { protected abstract void internalConsistencyCheck( final Map> prevLayerTxsBySender); + + public BlobCache getBlobCache() { + return blobCache; + } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java index f5ee0de2ae..c1e9bec63d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactions.java @@ -19,6 +19,7 @@ import static org.hyperledger.besu.ethereum.eth.transactions.layered.Transaction import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -45,8 +46,9 @@ public class BaseFeePrioritizedTransactions extends AbstractPrioritizedTransacti final TransactionPoolMetrics metrics, final BiFunction transactionReplacementTester, - final FeeMarket feeMarket) { - super(poolConfig, nextLayer, metrics, transactionReplacementTester); + final FeeMarket feeMarket, + final BlobCache blobCache) { + super(poolConfig, nextLayer, metrics, transactionReplacementTester, blobCache); this.nextBlockBaseFee = Optional.of(calculateNextBlockBaseFee(feeMarket, chainHeadHeaderSupplier.get())); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java index 762e7469f4..c6c402a110 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactions.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.eth.transactions.layered; import static java.util.Comparator.comparing; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -37,8 +38,9 @@ public class GasPricePrioritizedTransactions extends AbstractPrioritizedTransact final TransactionsLayer nextLayer, final TransactionPoolMetrics metrics, final BiFunction - transactionReplacementTester) { - super(poolConfig, nextLayer, metrics, transactionReplacementTester); + transactionReplacementTester, + final BlobCache blobCache) { + super(poolConfig, nextLayer, metrics, transactionReplacementTester, blobCache); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java index bd93f0d9fa..d9b6b60814 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactions.java @@ -535,4 +535,9 @@ public class LayeredPendingTransactions implements PendingTransactions { public synchronized String logStats() { return prioritizedTransactions.logStats(); } + + @Override + public Optional restoreBlob(final Transaction transaction) { + return prioritizedTransactions.getBlobCache().restoreBlob(transaction); + } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java index 484f131b0b..2820fe64b6 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReadyTransactions.java @@ -19,6 +19,7 @@ import static org.hyperledger.besu.ethereum.eth.transactions.layered.Transaction import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; @@ -52,8 +53,9 @@ public class ReadyTransactions extends AbstractSequentialTransactionsLayer { final TransactionsLayer nextLayer, final TransactionPoolMetrics metrics, final BiFunction - transactionReplacementTester) { - super(poolConfig, nextLayer, transactionReplacementTester, metrics); + transactionReplacementTester, + final BlobCache blobCache) { + super(poolConfig, nextLayer, transactionReplacementTester, metrics, blobCache); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java index 3567fb8426..41e2f6d9c3 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/layered/SparseTransactions.java @@ -20,6 +20,7 @@ import static org.hyperledger.besu.ethereum.eth.transactions.layered.Transaction import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; @@ -60,8 +61,9 @@ public class SparseTransactions extends AbstractTransactionsLayer { final TransactionsLayer nextLayer, final TransactionPoolMetrics metrics, final BiFunction - transactionReplacementTester) { - super(poolConfig, nextLayer, transactionReplacementTester, metrics); + transactionReplacementTester, + final BlobCache blobCache) { + super(poolConfig, nextLayer, transactionReplacementTester, metrics, blobCache); orderByGap = new ArrayList<>(poolConfig.getMaxFutureBySender()); IntStream.range(0, poolConfig.getMaxFutureBySender()) .forEach(i -> orderByGap.add(new SendersByPriority())); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java index 48b7ba5c02..bb53a8e4fb 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/sorter/AbstractPendingTransactionsSorter.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionAddedListener; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionDroppedListener; @@ -93,6 +94,8 @@ public abstract class AbstractPendingTransactionsSorter implements PendingTransa protected final TransactionPoolReplacementHandler transactionReplacementHandler; protected final Supplier chainHeadHeaderSupplier; + private final BlobCache blobCache; + public AbstractPendingTransactionsSorter( final TransactionPoolConfiguration poolConfig, final Clock clock, @@ -126,6 +129,8 @@ public abstract class AbstractPendingTransactionsSorter implements PendingTransa "transactions", "Current size of the transaction pool", pendingTransactions::size); + + this.blobCache = new BlobCache(); } @Override @@ -393,6 +398,10 @@ public abstract class AbstractPendingTransactionsSorter implements PendingTransa removePendingTransactionBySenderAndNonce(removedPendingTx); incrementTransactionRemovedCounter( removedPendingTx.isReceivedFromLocalSource(), addedToBlock); + if (removedPendingTx.getTransaction().getBlobsWithCommitments().isPresent() + && addedToBlock) { + this.blobCache.cacheBlobs(removedPendingTx.getTransaction()); + } } } } @@ -485,4 +494,13 @@ public abstract class AbstractPendingTransactionsSorter implements PendingTransa return sb.toString(); } } + /** + * @param transaction to restore blobs onto + * @return an optional copy of the supplied transaction, but with the BlobsWithCommitments + * restored. If none could be restored, empty. + */ + @Override + public Optional restoreBlob(final Transaction transaction) { + return blobCache.restoreBlob(transaction); + } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java index a218f3483c..66d34e4561 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java @@ -60,6 +60,7 @@ import org.hyperledger.besu.ethereum.eth.messages.TransactionsMessage; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory; @@ -1118,7 +1119,8 @@ public final class EthProtocolManagerTest { new SyncState(blockchain, ethManager.ethContext().getEthPeers()), MiningParameters.newDefault(), TransactionPoolConfiguration.DEFAULT, - null) + null, + new BlobCache()) .setEnabled(); // Send just a transaction message. diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java index 9361440554..5ff8d22dc3 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java @@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory; @@ -137,7 +138,8 @@ public abstract class AbstractMessageTaskTest { syncState, MiningParameters.newDefault(), TransactionPoolConfiguration.DEFAULT, - null); + null, + new BlobCache()); transactionPool.setEnabled(); ethProtocolManager = diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java index 99121a2b8d..a1597df193 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTest.java @@ -122,7 +122,6 @@ import org.mockito.junit.jupiter.MockitoSettings; @MockitoSettings(strictness = LENIENT) public abstract class AbstractTransactionPoolTest { - protected static final int MAX_TRANSACTIONS = 5; protected static final KeyPair KEY_PAIR1 = SignatureAlgorithmFactory.getInstance().generateKeyPair(); private static final KeyPair KEY_PAIR2 = @@ -150,7 +149,7 @@ public abstract class AbstractTransactionPoolTest { protected PendingTransactions transactions; protected final Transaction transaction0 = createTransaction(0); protected final Transaction transaction1 = createTransaction(1); - protected final Transaction transactionBlob = createBlobTransaction(0); + protected final Transaction transactionBlob = createBlobTransaction(2); protected final Transaction transactionOtherSender = createTransaction(1, KEY_PAIR2); private ExecutionContextTestFixture executionContext; @@ -326,7 +325,7 @@ public abstract class AbstractTransactionPoolTest { assertThat(transactions.size()).isEqualTo(3); assertThat(transactions.getLocalTransactions()).contains(localTransaction2); - assertThat(transactions.getPriorityTransactions().size()).isEqualTo(noLocalPriority ? 0 : 1); + assertThat(transactions.getPriorityTransactions()).hasSize(noLocalPriority ? 0 : 1); } @Test @@ -462,14 +461,14 @@ public abstract class AbstractTransactionPoolTest { } @Test - public void shouldNotReAddBlobTxsWhenReorgHappens() { + public void shouldReAddBlobTxsWhenReorgHappens() { givenTransactionIsValid(transaction0); givenTransactionIsValid(transaction1); givenTransactionIsValid(transactionBlob); addAndAssertRemoteTransactionsValid(transaction0); addAndAssertRemoteTransactionsValid(transaction1); - addAndAssertRemoteTransactionInvalid(transactionBlob); + addAndAssertRemoteTransactionsValid(transactionBlob); final BlockHeader commonParent = getHeaderForCurrentChainHead(); final Block originalFork1 = appendBlock(Difficulty.of(1000), commonParent, transaction0); @@ -490,9 +489,16 @@ public abstract class AbstractTransactionPoolTest { final Block reorgFork3 = appendBlock(Difficulty.of(3000), reorgFork2.getHeader()); verifyChainHeadIs(reorgFork3); - assertTransactionNotPending(transactionBlob); assertTransactionPending(transaction0); assertTransactionPending(transaction1); + assertTransactionPending(transactionBlob); + + Optional maybeBlob = transactions.getTransactionByHash(transactionBlob.getHash()); + assertThat(maybeBlob).isPresent(); + Transaction restoredBlob = maybeBlob.get(); + assertThat(restoredBlob).isEqualTo(transactionBlob); + assertThat(restoredBlob.getBlobsWithCommitments().get().getBlobQuads()) + .isEqualTo(transactionBlob.getBlobsWithCommitments().get().getBlobQuads()); } @ParameterizedTest @@ -1217,7 +1223,7 @@ public abstract class AbstractTransactionPoolTest { assertThat( add1559TxAndGetPendingTxsCount( genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, false, hasPriority)) - .isEqualTo(0); + .isZero(); } @ParameterizedTest @@ -1245,7 +1251,7 @@ public abstract class AbstractTransactionPoolTest { assertThat( add1559TxAndGetPendingTxsCount( genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, true, true)) - .isEqualTo(0); + .isZero(); } @Test @@ -1460,7 +1466,7 @@ public abstract class AbstractTransactionPoolTest { .maxFeePerGas(Optional.of(Wei.of(5000L))) .maxPriorityFeePerGas(Optional.of(Wei.of(1000L))) .type(TransactionType.BLOB) - .blobsWithCommitments(Optional.of(new BlobTestFixture().createBlobsWithCommitments(1))) + .blobsWithCommitments(Optional.of(new BlobTestFixture().createBlobsWithCommitments(6))) .createTransaction(KEY_PAIR1); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java index dde45d0a95..c9c81543a6 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java @@ -256,8 +256,12 @@ public class PendingTransactionEstimatedMemorySizeTest extends BaseTransactionPo final ClassLayout cl = ClassLayout.parseInstance(bwc); System.out.println(cl.toPrintable()); System.out.println("BlobsWithCommitments size: " + cl.instanceSize()); + final ClassLayout rl = ClassLayout.parseInstance(bwc.getBlobs()); + System.out.println(rl.toPrintable()); + System.out.println("BlobQuad size:" + rl.instanceSize()); - assertThat(cl.instanceSize()).isEqualTo(PendingTransaction.BLOBS_WITH_COMMITMENTS_SIZE); + assertThat(cl.instanceSize() + rl.instanceSize()) + .isEqualTo(PendingTransaction.BLOBS_WITH_COMMITMENTS_SIZE); } @Test diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java index 90f77a783f..02fd3613c0 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java @@ -164,7 +164,8 @@ public class TestNode implements Closeable { syncState, MiningParameters.newDefault(), TransactionPoolConfiguration.DEFAULT, - null); + null, + new BlobCache()); final EthProtocolManager ethProtocolManager = new EthProtocolManager( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java index e902c2c1dd..b3d2de98be 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java @@ -252,7 +252,8 @@ public class TransactionPoolFactoryTest { peerTransactionTracker, transactionsMessageSender, newPooledTransactionHashesMessageSender, - null); + null, + new BlobCache()); ethProtocolManager = new EthProtocolManager( @@ -359,7 +360,8 @@ public class TransactionPoolFactoryTest { .txMessageKeepAliveSeconds(1) .build()) .build(), - null); + null, + new BlobCache()); txPool.setEnabled(); return txPool; diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractLayeredTransactionPoolTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractLayeredTransactionPoolTest.java index 6245fe83ed..ee45b4998e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractLayeredTransactionPoolTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/AbstractLayeredTransactionPoolTest.java @@ -19,6 +19,7 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.transactions.AbstractTransactionPoolTest; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; @@ -40,9 +41,14 @@ public abstract class AbstractLayeredTransactionPoolTest extends AbstractTransac final var txPoolMetrics = new TransactionPoolMetrics(metricsSystem); final TransactionsLayer sparseLayer = new SparseTransactions( - poolConfig, new EndLayer(txPoolMetrics), txPoolMetrics, transactionReplacementTester); + poolConfig, + new EndLayer(txPoolMetrics), + txPoolMetrics, + transactionReplacementTester, + new BlobCache()); final TransactionsLayer readyLayer = - new ReadyTransactions(poolConfig, sparseLayer, txPoolMetrics, transactionReplacementTester); + new ReadyTransactions( + poolConfig, sparseLayer, txPoolMetrics, transactionReplacementTester, new BlobCache()); return new LayeredPendingTransactions( poolConfig, createPrioritizedTransactions( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactionsTest.java index adbc7077d9..4529f7f36e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseFeePrioritizedTransactionsTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -58,7 +59,8 @@ public class BaseFeePrioritizedTransactionsTest extends AbstractPrioritizedTrans nextLayer, txPoolMetrics, transactionReplacementTester, - FeeMarket.london(0L)); + FeeMarket.london(0L), + new BlobCache()); } @Override diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactionsTest.java index e41130f4f6..89e986678f 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/GasPricePrioritizedTransactionsTest.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -44,7 +45,7 @@ public class GasPricePrioritizedTransactionsTest extends AbstractPrioritizedTran transactionReplacementTester) { return new GasPricePrioritizedTransactions( - poolConfig, nextLayer, txPoolMetrics, transactionReplacementTester); + poolConfig, nextLayer, txPoolMetrics, transactionReplacementTester, new BlobCache()); } @Override diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java index c878184370..9f86cfc920 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredPendingTransactionsTest.java @@ -40,6 +40,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; 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.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactionAddedListener; @@ -113,11 +114,19 @@ public class LayeredPendingTransactionsTest extends BaseTransactionPoolTest { final SparseTransactions sparseTransactions = new SparseTransactions( - poolConfig, evictCollector, txPoolMetrics, transactionReplacementTester); + poolConfig, + evictCollector, + txPoolMetrics, + transactionReplacementTester, + new BlobCache()); final ReadyTransactions readyTransactions = new ReadyTransactions( - poolConfig, sparseTransactions, txPoolMetrics, transactionReplacementTester); + poolConfig, + sparseTransactions, + txPoolMetrics, + transactionReplacementTester, + new BlobCache()); final BaseFeePrioritizedTransactions prioritizedTransactions = new BaseFeePrioritizedTransactions( @@ -126,7 +135,8 @@ public class LayeredPendingTransactionsTest extends BaseTransactionPoolTest { readyTransactions, txPoolMetrics, transactionReplacementTester, - FeeMarket.london(0L)); + FeeMarket.london(0L), + new BlobCache()); return new CreatedLayers( prioritizedTransactions, readyTransactions, sparseTransactions, evictCollector); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolBaseFeeTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolBaseFeeTest.java index e30d881411..b70f3c24ac 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolBaseFeeTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolBaseFeeTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -44,7 +45,8 @@ public class LayeredTransactionPoolBaseFeeTest extends AbstractLayeredTransactio nextLayer, txPoolMetrics, transactionReplacementTester, - FeeMarket.london(0L)); + FeeMarket.london(0L), + new BlobCache()); } @Override diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolGasPriceTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolGasPriceTest.java index 34022ea0f9..e0066e0370 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolGasPriceTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayeredTransactionPoolGasPriceTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolMetrics; @@ -38,7 +39,7 @@ public class LayeredTransactionPoolGasPriceTest extends AbstractLayeredTransacti final BiFunction transactionReplacementTester) { return new GasPricePrioritizedTransactions( - poolConfig, nextLayer, txPoolMetrics, transactionReplacementTester); + poolConfig, nextLayer, txPoolMetrics, transactionReplacementTester, new BlobCache()); } @Override diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java index 666a5d6600..7a22683ec4 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java @@ -30,6 +30,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Util; +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.TransactionPoolConfiguration; @@ -71,11 +72,19 @@ public class LayersTest extends BaseTransactionPoolTest { private final EvictCollectorLayer evictCollector = new EvictCollectorLayer(txPoolMetrics); private final SparseTransactions sparseTransactions = new SparseTransactions( - poolConfig, evictCollector, txPoolMetrics, this::transactionReplacementTester); + poolConfig, + evictCollector, + txPoolMetrics, + this::transactionReplacementTester, + new BlobCache()); private final ReadyTransactions readyTransactions = new ReadyTransactions( - poolConfig, sparseTransactions, txPoolMetrics, this::transactionReplacementTester); + poolConfig, + sparseTransactions, + txPoolMetrics, + this::transactionReplacementTester, + new BlobCache()); private final BaseFeePrioritizedTransactions prioritizedTransactions = new BaseFeePrioritizedTransactions( @@ -84,7 +93,8 @@ public class LayersTest extends BaseTransactionPoolTest { readyTransactions, txPoolMetrics, this::transactionReplacementTester, - FeeMarket.london(0L)); + FeeMarket.london(0L), + new BlobCache()); private final LayeredPendingTransactions pendingTransactions = new LayeredPendingTransactions(poolConfig, prioritizedTransactions); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReplayTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReplayTest.java index 589818398b..10595b6fd7 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReplayTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/ReplayTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; 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.PendingTransaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult; @@ -187,10 +188,12 @@ public class ReplayTest { final BiFunction txReplacementTester = (tx1, tx2) -> transactionReplacementTester(poolConfig, tx1, tx2); final SparseTransactions sparseTransactions = - new SparseTransactions(poolConfig, evictCollector, txPoolMetrics, txReplacementTester); + new SparseTransactions( + poolConfig, evictCollector, txPoolMetrics, txReplacementTester, new BlobCache()); final ReadyTransactions readyTransactions = - new ReadyTransactions(poolConfig, sparseTransactions, txPoolMetrics, txReplacementTester); + new ReadyTransactions( + poolConfig, sparseTransactions, txPoolMetrics, txReplacementTester, new BlobCache()); return new BaseFeePrioritizedTransactions( poolConfig, @@ -198,7 +201,8 @@ public class ReplayTest { readyTransactions, txPoolMetrics, txReplacementTester, - baseFeeMarket); + baseFeeMarket, + new BlobCache()); } // ToDo: commented since not always working, needs fix diff --git a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java index dfe26f5c3c..3f88fd63ec 100644 --- a/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java +++ b/ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java @@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthMessages; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCache; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; @@ -252,7 +253,8 @@ public class RetestethContext { syncState, miningParameters, transactionPoolConfiguration, - null); + null, + new BlobCache()); if (LOG.isTraceEnabled()) { LOG.trace("Genesis Block {} ", genesisState.getBlock()); diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 744e8b420e..99ff123821 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -350,15 +350,15 @@ - - - + + + - - + + - - + + @@ -803,6 +803,14 @@ + + + + + + + + @@ -842,6 +850,11 @@ + + + + + @@ -3579,15 +3592,15 @@ - - - + + + - - + + - - + + @@ -4735,6 +4748,9 @@ + + + @@ -4756,6 +4772,9 @@ + + + @@ -4783,6 +4802,9 @@ + + + @@ -4812,6 +4834,9 @@ + + + @@ -4833,6 +4858,9 @@ + + + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 5a80ea3c79..34a56730ee 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -27,7 +27,7 @@ dependencyManagement { entry 'jackson-datatype-jdk8' } - dependency 'com.github.ben-manes.caffeine:caffeine:3.1.5' + dependency 'com.github.ben-manes.caffeine:caffeine:3.1.8' dependencySet(group: 'com.github.tomakehurst', version: '2.35.0') { entry'wiremock-jre8-standalone'