diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java index ab311c3fb38..c106b7aff16 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.AbstractTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlobPriceTransactionSelector; +import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlobSizeTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.BlockSizeTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.MinPriorityFeePerGasTransactionSelector; import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.PriceTransactionSelector; @@ -146,6 +147,7 @@ private List createTransactionSelectors( final BlockSelectionContext context) { return List.of( new BlockSizeTransactionSelector(context), + new BlobSizeTransactionSelector(context), new PriceTransactionSelector(context), new BlobPriceTransactionSelector(context), new MinPriorityFeePerGasTransactionSelector(context), diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java new file mode 100644 index 00000000000..44f7d8ce3d9 --- /dev/null +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java @@ -0,0 +1,94 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.blockcreation.txselection.selectors; + +import org.hyperledger.besu.ethereum.blockcreation.txselection.BlockSelectionContext; +import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionEvaluationContext; +import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults; +import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; +import org.hyperledger.besu.plugin.data.TransactionSelectionResult; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class extends AbstractTransactionSelector and provides a specific implementation for + * evaluating transactions based on blobs size. It checks if a transaction supports blobs, and if + * so, checks that there is enough remaining data gas in the block to fit the blobs of the tx. + */ +public class BlobSizeTransactionSelector extends AbstractTransactionSelector { + private static final Logger LOG = LoggerFactory.getLogger(BlobSizeTransactionSelector.class); + + public BlobSizeTransactionSelector(final BlockSelectionContext context) { + super(context); + } + + /** + * Evaluates a transaction considering other transactions in the same block. If the tx does not + * support blobs, no check is performed, and SELECTED is returned, otherwise SELECTED is returned + * only if there is enough remaining data gas to fit the blobs of the tx, otherwise a specific not + * selected result is returned, depending on the fact that the block already contains the max + * number of blobs or not. + * + * @param evaluationContext The current selection session data. + * @param transactionSelectionResults The results of other transaction evaluations in the same + * block. + * @return The result of the transaction selection. + */ + @Override + public TransactionSelectionResult evaluateTransactionPreProcessing( + final TransactionEvaluationContext evaluationContext, + final TransactionSelectionResults transactionSelectionResults) { + + final var remainingDataGas = + context.gasLimitCalculator().currentBlobGasLimit() + - transactionSelectionResults.getCumulativeBlobGasUsed(); + + final var tx = evaluationContext.getTransaction(); + if (tx.getType().supportsBlob()) { + if (remainingDataGas == 0) { + LOG.atTrace() + .setMessage("The block already contains the max number of allowed blobs") + .addArgument(evaluationContext.getPendingTransaction()::toTraceLog) + .log(); + return TransactionSelectionResult.BLOBS_FULL; + } + + final long requestedDataGas = context.gasCalculator().blobGasCost(tx.getBlobCount()); + + if (requestedDataGas > remainingDataGas) { + LOG.atTrace() + .setMessage( + "There is not enough data gas available to fit the blobs of the transaction {} in the block." + + " Available {} / Requested {}") + .addArgument(evaluationContext.getPendingTransaction()::toTraceLog) + .addArgument(remainingDataGas) + .addArgument(requestedDataGas) + .log(); + return TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_DATA_GAS; + } + } + return TransactionSelectionResult.SELECTED; + } + + @Override + public TransactionSelectionResult evaluateTransactionPostProcessing( + final TransactionEvaluationContext evaluationContext, + final TransactionSelectionResults blockTransactionResults, + final TransactionProcessingResult processingResult) { + // All necessary checks were done in the pre-processing method, so nothing to do here. + return TransactionSelectionResult.SELECTED; + } +} diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java index 7f0b13e8b99..793f3e93842 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlockSizeTransactionSelector.java @@ -89,15 +89,8 @@ public TransactionSelectionResult evaluateTransactionPostProcessing( private boolean transactionTooLargeForBlock( final Transaction transaction, final TransactionSelectionResults transactionSelectionResults) { - final long blobGasUsed = context.gasCalculator().blobGasCost(transaction.getBlobCount()); - if (blobGasUsed - > context.gasLimitCalculator().currentBlobGasLimit() - - transactionSelectionResults.getCumulativeBlobGasUsed()) { - return true; - } - - return transaction.getGasLimit() + blobGasUsed + return transaction.getGasLimit() > context.processableBlockHeader().getGasLimit() - transactionSelectionResults.getCumulativeGasUsed(); } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index 68d13987bb3..2444d9db7de 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -26,8 +26,9 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.GenesisConfigFile; -import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECPPrivateKey; +import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BLSPublicKey; @@ -73,13 +74,18 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidator; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidatorFactory; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor; -import org.hyperledger.besu.ethereum.mainnet.feemarket.CancunFeeMarket; import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestProcessor; import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestValidator; import org.hyperledger.besu.ethereum.mainnet.requests.ProcessRequestContext; import org.hyperledger.besu.ethereum.mainnet.requests.RequestProcessorCoordinator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestsValidatorCoordinator; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; +import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.log.Log; import org.hyperledger.besu.evm.log.LogTopic; @@ -89,13 +95,13 @@ import java.math.BigInteger; import java.time.Clock; import java.util.List; -import java.util.Map; import java.util.Optional; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -103,6 +109,17 @@ @ExtendWith(MockitoExtension.class) abstract class AbstractBlockCreatorTest { + private static final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + private static final SECPPrivateKey PRIVATE_KEY1 = + SIGNATURE_ALGORITHM + .get() + .createPrivateKey( + Bytes32.fromHexString( + "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63")); + private static final KeyPair KEYS1 = + new KeyPair(PRIVATE_KEY1, SIGNATURE_ALGORITHM.get().createPublicKey(PRIVATE_KEY1)); + @Mock private WithdrawalsProcessor withdrawalsProcessor; protected EthScheduler ethScheduler = new DeterministicEthScheduler(); @@ -301,10 +318,8 @@ void withNoProcessorAndWithdrawals_WithdrawalsAreNotProcessed() { assertThat(blockCreationResult.getBlock().getBody().getWithdrawals()).isEmpty(); } - @Disabled @Test public void computesGasUsageFromIncludedTransactions() { - final KeyPair senderKeys = SignatureAlgorithmFactory.getInstance().generateKeyPair(); final AbstractBlockCreator blockCreator = blockCreatorWithBlobGasSupport(); BlobTestFixture blobTestFixture = new BlobTestFixture(); BlobsWithCommitments bwc = blobTestFixture.createBlobsWithCommitments(6); @@ -313,13 +328,14 @@ public void computesGasUsageFromIncludedTransactions() { ttf.to(Optional.of(Address.ZERO)) .type(TransactionType.BLOB) .chainId(Optional.of(BigInteger.valueOf(42))) + .gasLimit(21000) .maxFeePerGas(Optional.of(Wei.of(15))) .maxFeePerBlobGas(Optional.of(Wei.of(128))) .maxPriorityFeePerGas(Optional.of(Wei.of(1))) .versionedHashes(Optional.of(bwc.getVersionedHashes())) - .createTransaction(senderKeys); + .blobsWithCommitments(Optional.of(bwc)) + .createTransaction(KEYS1); - ttf.blobsWithCommitments(Optional.of(bwc)); final BlockCreationResult blockCreationResult = blockCreator.createBlock( Optional.of(List.of(fullOfBlobs)), @@ -336,13 +352,17 @@ public void computesGasUsageFromIncludedTransactions() { } private AbstractBlockCreator blockCreatorWithBlobGasSupport() { + final var alwaysValidTransactionValidatorFactory = mock(TransactionValidatorFactory.class); + when(alwaysValidTransactionValidatorFactory.get()) + .thenReturn(new AlwaysValidTransactionValidator()); final ProtocolSpecAdapters protocolSpecAdapters = ProtocolSpecAdapters.create( 0, specBuilder -> { - specBuilder.feeMarket(new CancunFeeMarket(0, Optional.empty())); specBuilder.isReplayProtectionSupported(true); specBuilder.withdrawalsProcessor(withdrawalsProcessor); + specBuilder.transactionValidatorFactoryBuilder( + (evm, gasLimitCalculator, feeMarket) -> alwaysValidTransactionValidatorFactory); return specBuilder; }); return createBlockCreator(protocolSpecAdapters); @@ -356,16 +376,19 @@ private AbstractBlockCreator blockCreatorWithWithdrawalsProcessor() { } private AbstractBlockCreator blockCreatorWithoutWithdrawalsProcessor() { - return createBlockCreator(new ProtocolSpecAdapters(Map.of())); + final ProtocolSpecAdapters protocolSpecAdapters = + ProtocolSpecAdapters.create(0, specBuilder -> specBuilder.withdrawalsProcessor(null)); + return createBlockCreator(protocolSpecAdapters); } private AbstractBlockCreator createBlockCreator(final ProtocolSpecAdapters protocolSpecAdapters) { - final GenesisConfigOptions genesisConfigOptions = GenesisConfigFile.DEFAULT.getConfigOptions(); + + final var genesisConfigFile = GenesisConfigFile.fromResource("/block-creation-genesis.json"); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder() + ExecutionContextTestFixture.builder(genesisConfigFile) .protocolSchedule( new ProtocolScheduleBuilder( - genesisConfigOptions, + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(42), protocolSpecAdapters, PrivacyParameters.DEFAULT, @@ -452,4 +475,24 @@ protected BlockHeader createFinalBlockHeader(final SealableBlockHeader sealableB .buildBlockHeader(); } } + + static class AlwaysValidTransactionValidator implements TransactionValidator { + + @Override + public ValidationResult validate( + final Transaction transaction, + final Optional baseFee, + final Optional blobBaseFee, + final TransactionValidationParams transactionValidationParams) { + return ValidationResult.valid(); + } + + @Override + public ValidationResult validateForSender( + final Transaction transaction, + final Account sender, + final TransactionValidationParams validationParams) { + return ValidationResult.valid(); + } + } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java index 3b1ae938f7f..62063845342 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java @@ -42,10 +42,6 @@ import java.time.ZoneId; import java.util.function.Function; -import org.junit.jupiter.api.Disabled; - -@Disabled( - "disabled since it's flaky with a timeout see https://github.com/hyperledger/besu/issues/6850") public class LegacyFeeMarketBlockTransactionSelectorTest extends AbstractBlockTransactionSelectorTest { diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index f7fd4486d1b..2cd5bc5e9e2 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -21,7 +21,6 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.GenesisConfigFile; -import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -38,6 +37,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; +import org.hyperledger.besu.ethereum.difficulty.fixed.FixedDifficultyCalculators; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster; @@ -75,6 +75,7 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { private static final long BLOCK_1_TIMESTAMP = Long.parseUnsignedLong("55ba4224", 16); private static final long BLOCK_1_NONCE = Long.parseLong("539bd4979fef1ec4", 16); + private static final long FIXED_DIFFICULTY_NONCE = 26; private static final Bytes BLOCK_1_EXTRA_DATA = Bytes.fromHexString("0x476574682f76312e302e302f6c696e75782f676f312e342e32"); @@ -82,24 +83,25 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { @Test void createMainnetBlock1() throws IOException { - final GenesisConfigOptions genesisConfigOptions = GenesisConfigFile.DEFAULT.getConfigOptions(); + final var genesisConfigFile = GenesisConfigFile.mainnet(); + + final MiningParameters miningParameters = createMiningParameters(BLOCK_1_NONCE); + final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder() + ExecutionContextTestFixture.builder(genesisConfigFile) .protocolSchedule( new ProtocolScheduleBuilder( - genesisConfigOptions, + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(42), ProtocolSpecAdapters.create(0, Function.identity()), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, - MiningParameters.MINING_DISABLED, + miningParameters, new BadBlockManager()) .createProtocolSchedule()) .build(); - final MiningParameters miningParameters = createMiningParameters(); - final PoWSolver solver = new PoWSolver( miningParameters, @@ -136,26 +138,31 @@ void createMainnetBlock1() throws IOException { @Test void createMainnetBlock1_fixedDifficulty1() { - final GenesisConfigOptions genesisConfigOptions = - GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}") - .getConfigOptions(); + final var genesisConfigFile = + GenesisConfigFile.fromResource("/block-creation-fixed-difficulty-genesis.json"); + + final MiningParameters miningParameters = createMiningParameters(FIXED_DIFFICULTY_NONCE); + final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder() + ExecutionContextTestFixture.builder(genesisConfigFile) .protocolSchedule( new ProtocolScheduleBuilder( - genesisConfigOptions, + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(42), - ProtocolSpecAdapters.create(0, Function.identity()), + ProtocolSpecAdapters.create( + 0, + specBuilder -> + specBuilder.difficultyCalculator( + FixedDifficultyCalculators.calculator( + genesisConfigFile.getConfigOptions()))), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, - MiningParameters.MINING_DISABLED, + miningParameters, new BadBlockManager()) .createProtocolSchedule()) .build(); - final MiningParameters miningParameters = createMiningParameters(); - final PoWSolver solver = new PoWSolver( miningParameters, @@ -184,24 +191,31 @@ void createMainnetBlock1_fixedDifficulty1() { @Test void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { - final GenesisConfigOptions genesisConfigOptions = - GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}") - .getConfigOptions(); + final var genesisConfigFile = + GenesisConfigFile.fromResource("/block-creation-fixed-difficulty-genesis.json"); + + final MiningParameters miningParameters = createMiningParameters(FIXED_DIFFICULTY_NONCE); + ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( - genesisConfigOptions, + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(42), - ProtocolSpecAdapters.create(0, Function.identity()), + ProtocolSpecAdapters.create( + 0, + specBuilder -> + specBuilder.difficultyCalculator( + FixedDifficultyCalculators.calculator( + genesisConfigFile.getConfigOptions()))), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, - MiningParameters.MINING_DISABLED, + miningParameters, new BadBlockManager()) .createProtocolSchedule(); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); - - final MiningParameters miningParameters = createMiningParameters(); + ExecutionContextTestFixture.builder(genesisConfigFile) + .protocolSchedule(protocolSchedule) + .build(); final PoWSolver solver = new PoWSolver( @@ -253,24 +267,31 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { @Test void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { - final GenesisConfigOptions genesisConfigOptions = - GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}") - .getConfigOptions(); + final var genesisConfigFile = + GenesisConfigFile.fromResource("/block-creation-fixed-difficulty-genesis.json"); + + final MiningParameters miningParameters = createMiningParameters(FIXED_DIFFICULTY_NONCE); + ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( - genesisConfigOptions, + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(42), - ProtocolSpecAdapters.create(0, Function.identity()), + ProtocolSpecAdapters.create( + 0, + specBuilder -> + specBuilder.difficultyCalculator( + FixedDifficultyCalculators.calculator( + genesisConfigFile.getConfigOptions()))), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, - MiningParameters.MINING_DISABLED, + miningParameters, new BadBlockManager()) .createProtocolSchedule(); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); - - final MiningParameters miningParameters = createMiningParameters(); + ExecutionContextTestFixture.builder(genesisConfigFile) + .protocolSchedule(protocolSchedule) + .build(); final PoWSolver solver = new PoWSolver( @@ -348,11 +369,12 @@ private TransactionPool createTransactionPool( return transactionPool; } - private MiningParameters createMiningParameters() { + private MiningParameters createMiningParameters(final long nonce) { return ImmutableMiningParameters.builder() .mutableInitValues( MutableInitValues.builder() - .nonceGenerator(Lists.newArrayList(BLOCK_1_NONCE)) + .nonceGenerator(Lists.newArrayList(nonce)) + // .nonceGenerator(new IncrementingNonceGenerator(0)) .extraData(BLOCK_1_EXTRA_DATA) .minTransactionGasPrice(Wei.ONE) .coinbase(BLOCK_1_COINBASE) diff --git a/ethereum/blockcreation/src/test/resources/block-creation-fixed-difficulty-genesis.json b/ethereum/blockcreation/src/test/resources/block-creation-fixed-difficulty-genesis.json new file mode 100644 index 00000000000..5f9a821a8e1 --- /dev/null +++ b/ethereum/blockcreation/src/test/resources/block-creation-fixed-difficulty-genesis.json @@ -0,0 +1,34 @@ +{ + "config": { + "chainId": 42, + "frontierBlock": 0, + "ethash": { + "fixeddifficulty":10 + } + }, + "nonce": "0x42", + "timestamp": "0x0", + "extraData": "", + "gasLimit": "0x1fffffffffffff", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "0x7", + "alloc": { + "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { + "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + }, + "627306090abaB3A6e1400e9345bC60c78a8BEf57": { + "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + }, + "f17f52151EbEF6C7334FAD080c5704D77216b732": { + "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + } + } +} diff --git a/ethereum/blockcreation/src/test/resources/block-creation-genesis.json b/ethereum/blockcreation/src/test/resources/block-creation-genesis.json new file mode 100644 index 00000000000..4a26c5ae025 --- /dev/null +++ b/ethereum/blockcreation/src/test/resources/block-creation-genesis.json @@ -0,0 +1,32 @@ +{ + "config": { + "chainId": 42, + "cancunTime": 0, + "terminalTotalDifficulty": 0 + }, + "nonce": "0x42", + "timestamp": "0x0", + "extraData": "", + "gasLimit": "0x1fffffffffffff", + "difficulty": "0x10000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "0x7", + "alloc": { + "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { + "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "0xad78ebc5ac6200000" + }, + "627306090abaB3A6e1400e9345bC60c78a8BEf57": { + "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + }, + "f17f52151EbEF6C7334FAD080c5704D77216b732": { + "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", + "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", + "balance": "90000000000000000000000" + } + } +} diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java index edae52f35a9..a029c4b4a49 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.entry; import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; +import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.TransactionType; @@ -68,7 +69,9 @@ public class TraceTransactionIntegrationTest { @BeforeEach public void setUp() { - final ExecutionContextTestFixture contextTestFixture = ExecutionContextTestFixture.create(); + final ExecutionContextTestFixture contextTestFixture = + ExecutionContextTestFixture.builder(GenesisConfigFile.fromResource("/genesis-it.json")) + .build(); genesisBlock = contextTestFixture.getGenesis(); blockchain = contextTestFixture.getBlockchain(); worldStateArchive = contextTestFixture.getStateArchive(); diff --git a/ethereum/core/src/integration-test/resources/genesis-it.json b/ethereum/core/src/integration-test/resources/genesis-it.json new file mode 100644 index 00000000000..70c42b39fe5 --- /dev/null +++ b/ethereum/core/src/integration-test/resources/genesis-it.json @@ -0,0 +1,13 @@ +{ + "config": { + "petersburgBlock": 0 + }, + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x0000001", + "extraData": "", + "gasLimit": "0x2fefd8", + "nonce": "0x0000000000000107", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x00" +} diff --git a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java index 8307a8fef4a..4289a91a3c8 100644 --- a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java +++ b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java @@ -16,6 +16,7 @@ import static java.util.Collections.emptyList; +import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; @@ -74,7 +75,9 @@ public static OperationBenchmarkHelper create() throws IOException { KeyValueSegmentIdentifier.BLOCKCHAIN, optimisticRocksDBColumnarKeyValueStorage); final ExecutionContextTestFixture executionContext = - ExecutionContextTestFixture.builder().blockchainKeyValueStorage(keyValueStorage).build(); + ExecutionContextTestFixture.builder(GenesisConfigFile.fromResource("/genesis-jmh.json")) + .blockchainKeyValueStorage(keyValueStorage) + .build(); final MutableBlockchain blockchain = executionContext.getBlockchain(); for (int i = 1; i < 256; i++) { diff --git a/ethereum/core/src/jmh/resources/genesis-jmh.json b/ethereum/core/src/jmh/resources/genesis-jmh.json new file mode 100644 index 00000000000..70c42b39fe5 --- /dev/null +++ b/ethereum/core/src/jmh/resources/genesis-jmh.json @@ -0,0 +1,13 @@ +{ + "config": { + "petersburgBlock": 0 + }, + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x0000001", + "extraData": "", + "gasLimit": "0x2fefd8", + "nonce": "0x0000000000000107", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x00" +} diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java index 3aa483e1a9e..5aa00d0ed64 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java @@ -17,7 +17,6 @@ import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive; import org.hyperledger.besu.config.GenesisConfigFile; -import org.hyperledger.besu.config.StubGenesisConfigOptions; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; @@ -48,9 +47,9 @@ public class ExecutionContextTestFixture { private final ProtocolSchedule protocolSchedule; private final ProtocolContext protocolContext; - private static final GenesisConfigFile genesisConfigFile = GenesisConfigFile.mainnet(); private ExecutionContextTestFixture( + final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule, final KeyValueStorage blockchainKeyValueStorage, final KeyValueStorage variablesKeyValueStorage) { @@ -76,11 +75,11 @@ private ExecutionContextTestFixture( } public static ExecutionContextTestFixture create() { - return new Builder().build(); + return new Builder(GenesisConfigFile.mainnet()).build(); } - public static Builder builder() { - return new Builder(); + public static Builder builder(final GenesisConfigFile genesisConfigFile) { + return new Builder(genesisConfigFile); } public Block getGenesis() { @@ -112,10 +111,15 @@ public ProtocolContext getProtocolContext() { } public static class Builder { + private final GenesisConfigFile genesisConfigFile; private KeyValueStorage variablesKeyValueStorage; private KeyValueStorage blockchainKeyValueStorage; private ProtocolSchedule protocolSchedule; + public Builder(final GenesisConfigFile genesisConfigFile) { + this.genesisConfigFile = genesisConfigFile; + } + public Builder variablesKeyValueStorage(final KeyValueStorage keyValueStorage) { this.variablesKeyValueStorage = keyValueStorage; return this; @@ -135,7 +139,7 @@ public ExecutionContextTestFixture build() { if (protocolSchedule == null) { protocolSchedule = new ProtocolScheduleBuilder( - new StubGenesisConfigOptions().petersburgBlock(0), + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(42), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), @@ -152,7 +156,7 @@ public ExecutionContextTestFixture build() { variablesKeyValueStorage = new InMemoryKeyValueStorage(); } return new ExecutionContextTestFixture( - protocolSchedule, variablesKeyValueStorage, blockchainKeyValueStorage); + genesisConfigFile, protocolSchedule, variablesKeyValueStorage, blockchainKeyValueStorage); } } } 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 39b47bf9dde..23eb9d02bf6 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 @@ -43,7 +43,7 @@ import static org.mockito.Mockito.when; import static org.mockito.quality.Strictness.LENIENT; -import org.hyperledger.besu.config.StubGenesisConfigOptions; +import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Address; @@ -191,9 +191,10 @@ protected TransactionTestFixture createBaseTransactionBaseFeeMarket(final int no protected abstract ExecutionContextTestFixture createExecutionContextTestFixture(); protected static ExecutionContextTestFixture createExecutionContextTestFixtureBaseFeeMarket() { + final var genesisConfigFile = GenesisConfigFile.fromResource("/txpool-test-genesis.json"); final ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( - new StubGenesisConfigOptions().londonBlock(0L).baseFeePerGas(10L), + genesisConfigFile.getConfigOptions(), BigInteger.valueOf(1), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), @@ -203,7 +204,9 @@ protected static ExecutionContextTestFixture createExecutionContextTestFixtureBa new BadBlockManager()) .createProtocolSchedule(); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); + ExecutionContextTestFixture.builder(genesisConfigFile) + .protocolSchedule(protocolSchedule) + .build(); final Block block = new Block( diff --git a/ethereum/eth/src/test/resources/txpool-test-genesis.json b/ethereum/eth/src/test/resources/txpool-test-genesis.json new file mode 100644 index 00000000000..d6a19fe7052 --- /dev/null +++ b/ethereum/eth/src/test/resources/txpool-test-genesis.json @@ -0,0 +1,15 @@ +{ + "config": { + "chainId": 1, + "cancunTime": 0, + "terminalTotalDifficulty": 0 + }, + "nonce": "0x42", + "timestamp": "0x0", + "extraData": "", + "gasLimit": "0x1fffffffffffff", + "difficulty": "0x10000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "baseFeePerGas": "0xA" +} diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index d55efa7fc99..530e3dd15ad 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -70,7 +70,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'yH50m+z1tnzshJQPdwR86pb2EU3m6iZxwkqoy/5spcs=' + knownHash = 'dx/CsrwsixajUIS3oxIoiLGTbkHxqtV6WMKVLhJegH0=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java index 112df57a498..cfd948f1608 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java @@ -53,9 +53,10 @@ protected interface Status { private enum BaseStatus implements Status { SELECTED, BLOCK_FULL(true, false), + BLOBS_FULL(false, false), BLOCK_OCCUPANCY_ABOVE_THRESHOLD(true, false), BLOCK_SELECTION_TIMEOUT(true, false), - TX_EVALUATION_TOO_LONG(false, true), + TX_EVALUATION_TOO_LONG(true, true), INVALID_TRANSIENT(false, false), INVALID(false, true); @@ -96,6 +97,10 @@ public boolean discard() { public static final TransactionSelectionResult BLOCK_FULL = new TransactionSelectionResult(BaseStatus.BLOCK_FULL); + /** The block already contains the max number of allowed blobs. */ + public static final TransactionSelectionResult BLOBS_FULL = + new TransactionSelectionResult(BaseStatus.BLOBS_FULL); + /** There was no more time to add transaction to the block */ public static final TransactionSelectionResult BLOCK_SELECTION_TIMEOUT = new TransactionSelectionResult(BaseStatus.BLOCK_SELECTION_TIMEOUT); @@ -118,6 +123,13 @@ public boolean discard() { public static final TransactionSelectionResult TX_TOO_LARGE_FOR_REMAINING_GAS = TransactionSelectionResult.invalidTransient("TX_TOO_LARGE_FOR_REMAINING_GAS"); + /** + * The transaction has not been selected since there is not enough remaining data gas in the block + * to fit the blobs of the tx, but selection should continue. + */ + public static final TransactionSelectionResult TX_TOO_LARGE_FOR_REMAINING_DATA_GAS = + TransactionSelectionResult.invalidTransient("TX_TOO_LARGE_FOR_REMAINING_DATA_GAS"); + /** * The transaction has not been selected since its current price is below the configured min * price, but the selection should continue.