mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-09 23:38:08 -05:00
Introduce transaction validator interface (phase 2) (#5682)
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
This commit is contained in:
@@ -1136,7 +1136,7 @@ public class RunnerBuilder {
|
||||
permissioningController ->
|
||||
besuController
|
||||
.getProtocolSchedule()
|
||||
.setTransactionFilter(permissioningController::isPermitted));
|
||||
.setPermissionTransactionFilter(permissioningController::isPermitted));
|
||||
|
||||
return accountPermissioningController;
|
||||
} else {
|
||||
|
||||
@@ -51,7 +51,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolFactory;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
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.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
|
||||
@@ -79,6 +79,7 @@ import com.google.common.base.Suppliers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@@ -99,7 +100,10 @@ public class BesuEventsImplTest {
|
||||
@Mock private EthContext mockEthContext;
|
||||
@Mock private EthMessages mockEthMessages;
|
||||
@Mock private EthScheduler mockEthScheduler;
|
||||
@Mock private TransactionValidator mockTransactionValidator;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private TransactionValidatorFactory mockTransactionValidatorFactory;
|
||||
|
||||
@Mock private ProtocolSpec mockProtocolSpec;
|
||||
@Mock private WorldStateArchive mockWorldStateArchive;
|
||||
@Mock private MutableWorldState mockWorldState;
|
||||
@@ -128,11 +132,12 @@ public class BesuEventsImplTest {
|
||||
when(mockProtocolContext.getBlockchain()).thenReturn(blockchain);
|
||||
when(mockProtocolContext.getWorldStateArchive()).thenReturn(mockWorldStateArchive);
|
||||
when(mockProtocolSchedule.getByBlockHeader(any())).thenReturn(mockProtocolSpec);
|
||||
when(mockProtocolSpec.getTransactionValidator()).thenReturn(mockTransactionValidator);
|
||||
when(mockProtocolSpec.getTransactionValidatorFactory())
|
||||
.thenReturn(mockTransactionValidatorFactory);
|
||||
when(mockProtocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0L));
|
||||
when(mockTransactionValidator.validate(any(), any(Optional.class), any()))
|
||||
when(mockTransactionValidatorFactory.get().validate(any(), any(Optional.class), any()))
|
||||
.thenReturn(ValidationResult.valid());
|
||||
when(mockTransactionValidator.validateForSender(any(), any(), any()))
|
||||
when(mockTransactionValidatorFactory.get().validateForSender(any(), any(), any()))
|
||||
.thenReturn(ValidationResult.valid());
|
||||
when(mockWorldStateArchive.getMutable(any(), anyBoolean()))
|
||||
.thenReturn(Optional.of(mockWorldState));
|
||||
|
||||
@@ -219,9 +219,11 @@ public class TransitionProtocolSchedule implements ProtocolSchedule {
|
||||
* @param permissionTransactionFilter the transaction filter
|
||||
*/
|
||||
@Override
|
||||
public void setTransactionFilter(final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
public void setPermissionTransactionFilter(
|
||||
final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
transitionUtils.dispatchConsumerAccordingToMergeState(
|
||||
protocolSchedule -> protocolSchedule.setTransactionFilter(permissionTransactionFilter));
|
||||
protocolSchedule ->
|
||||
protocolSchedule.setPermissionTransactionFilter(permissionTransactionFilter));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,7 @@ public class ClassicProtocolSpecs {
|
||||
.gasCalculator(TangerineWhistleGasCalculator::new)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
new TransactionValidatorFactory(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
.name("ClassicTangerineWhistle");
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public class ClassicProtocolSpecs {
|
||||
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_REMOVED)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
new TransactionValidatorFactory(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
.name("DefuseDifficultyBomb");
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ public class ClassicProtocolSpecs {
|
||||
.gasCalculator(BerlinGasCalculator::new)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
true,
|
||||
|
||||
@@ -111,11 +111,12 @@ public class DefaultProtocolSchedule implements ProtocolSchedule {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransactionFilter(final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
public void setPermissionTransactionFilter(
|
||||
final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
protocolSpecs.forEach(
|
||||
spec ->
|
||||
spec.spec()
|
||||
.getTransactionValidator()
|
||||
.getTransactionValidatorFactory()
|
||||
.setPermissionTransactionFilter(permissionTransactionFilter));
|
||||
}
|
||||
|
||||
|
||||
@@ -124,16 +124,16 @@ public abstract class MainnetProtocolSpecs {
|
||||
0))
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator, gasLimitCalculator, false, Optional.empty()))
|
||||
.transactionProcessorBuilder(
|
||||
(gasCalculator,
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor) ->
|
||||
new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
false,
|
||||
@@ -142,12 +142,12 @@ public abstract class MainnetProtocolSpecs {
|
||||
FeeMarket.legacy(),
|
||||
CoinbaseFeePriceCalculator.frontier()))
|
||||
.privateTransactionProcessorBuilder(
|
||||
(transactionValidator,
|
||||
(transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
privateTransactionValidator) ->
|
||||
new PrivateTransactionProcessor(
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
false,
|
||||
@@ -199,7 +199,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
0))
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator, gasLimitCalculator, true, Optional.empty()))
|
||||
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
|
||||
.name("Homestead");
|
||||
@@ -277,7 +277,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
new TransactionValidatorFactory(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
.transactionProcessorBuilder(
|
||||
(gasCalculator,
|
||||
transactionValidator,
|
||||
@@ -412,7 +412,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
.gasCalculator(BerlinGasCalculator::new)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
true,
|
||||
@@ -452,7 +452,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
new LondonTargetingGasLimitCalculator(londonForkBlockNumber, londonFeeMarket))
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
londonFeeMarket,
|
||||
@@ -613,7 +613,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
// Contract creation rules for EIP-3860 Limit and meter intitcode
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
londonFeeMarket,
|
||||
@@ -696,7 +696,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
// change to check for max data gas per block for EIP-4844
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
new TransactionValidatorFactory(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
cancunFeeMarket,
|
||||
|
||||
@@ -64,7 +64,7 @@ public class MainnetTransactionProcessor {
|
||||
|
||||
protected final GasCalculator gasCalculator;
|
||||
|
||||
protected final TransactionValidator transactionValidator;
|
||||
protected final TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
private final AbstractMessageProcessor contractCreationProcessor;
|
||||
|
||||
@@ -81,7 +81,7 @@ public class MainnetTransactionProcessor {
|
||||
|
||||
public MainnetTransactionProcessor(
|
||||
final GasCalculator gasCalculator,
|
||||
final TransactionValidator transactionValidator,
|
||||
final TransactionValidatorFactory transactionValidatorFactory,
|
||||
final AbstractMessageProcessor contractCreationProcessor,
|
||||
final AbstractMessageProcessor messageCallProcessor,
|
||||
final boolean clearEmptyAccounts,
|
||||
@@ -90,7 +90,7 @@ public class MainnetTransactionProcessor {
|
||||
final FeeMarket feeMarket,
|
||||
final CoinbaseFeePriceCalculator coinbaseFeePriceCalculator) {
|
||||
this.gasCalculator = gasCalculator;
|
||||
this.transactionValidator = transactionValidator;
|
||||
this.transactionValidatorFactory = transactionValidatorFactory;
|
||||
this.contractCreationProcessor = contractCreationProcessor;
|
||||
this.messageCallProcessor = messageCallProcessor;
|
||||
this.clearEmptyAccounts = clearEmptyAccounts;
|
||||
@@ -271,6 +271,7 @@ public class MainnetTransactionProcessor {
|
||||
final PrivateMetadataUpdater privateMetadataUpdater,
|
||||
final Wei dataGasPrice) {
|
||||
try {
|
||||
final var transactionValidator = transactionValidatorFactory.get();
|
||||
LOG.trace("Starting execution of {}", transaction);
|
||||
ValidationResult<TransactionInvalidReason> validationResult =
|
||||
transactionValidator.validate(
|
||||
@@ -498,10 +499,6 @@ public class MainnetTransactionProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
public TransactionValidator getTransactionValidator() {
|
||||
return transactionValidator;
|
||||
}
|
||||
|
||||
protected void process(final MessageFrame frame, final OperationTracer operationTracer) {
|
||||
final AbstractMessageProcessor executor = getMessageProcessor(frame.getType());
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.TransactionType;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.GasLimitCalculator;
|
||||
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
@@ -49,40 +48,10 @@ public class MainnetTransactionValidator implements TransactionValidator {
|
||||
|
||||
private final Optional<BigInteger> chainId;
|
||||
|
||||
private Optional<PermissionTransactionFilter> permissionTransactionFilter = Optional.empty();
|
||||
private final Set<TransactionType> acceptedTransactionTypes;
|
||||
|
||||
private final int maxInitcodeSize;
|
||||
|
||||
public MainnetTransactionValidator(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId) {
|
||||
this(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
Set.of(TransactionType.FRONTIER));
|
||||
}
|
||||
|
||||
public MainnetTransactionValidator(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Set<TransactionType> acceptedTransactionTypes) {
|
||||
this(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
FeeMarket.legacy(),
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
acceptedTransactionTypes,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public MainnetTransactionValidator(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
@@ -239,12 +208,6 @@ public class MainnetTransactionValidator implements TransactionValidator {
|
||||
transaction.getSender()));
|
||||
}
|
||||
|
||||
if (!isSenderAllowed(transaction, validationParams)) {
|
||||
return ValidationResult.invalid(
|
||||
TransactionInvalidReason.TX_SENDER_NOT_AUTHORIZED,
|
||||
String.format("Sender %s is not on the Account Allowlist", transaction.getSender()));
|
||||
}
|
||||
|
||||
return ValidationResult.valid();
|
||||
}
|
||||
|
||||
@@ -286,26 +249,4 @@ public class MainnetTransactionValidator implements TransactionValidator {
|
||||
}
|
||||
return ValidationResult.valid();
|
||||
}
|
||||
|
||||
private boolean isSenderAllowed(
|
||||
final Transaction transaction, final TransactionValidationParams validationParams) {
|
||||
if (validationParams.checkLocalPermissions() || validationParams.checkOnchainPermissions()) {
|
||||
return permissionTransactionFilter
|
||||
.map(
|
||||
c ->
|
||||
c.permitted(
|
||||
transaction,
|
||||
validationParams.checkLocalPermissions(),
|
||||
validationParams.checkOnchainPermissions()))
|
||||
.orElse(true);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermissionTransactionFilter(
|
||||
final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
this.permissionTransactionFilter = Optional.of(permissionTransactionFilter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.mainnet;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Validates a transaction based on Frontier protocol runtime requirements.
|
||||
*
|
||||
* <p>The {@link PermissionTransactionValidator} performs the intrinsic gas cost check on the given
|
||||
* {@link Transaction}.
|
||||
*/
|
||||
public class PermissionTransactionValidator implements TransactionValidator {
|
||||
private final TransactionValidator delegate;
|
||||
private final PermissionTransactionFilter permissionTransactionFilter;
|
||||
|
||||
public PermissionTransactionValidator(
|
||||
final TransactionValidator delegate,
|
||||
final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
this.delegate = delegate;
|
||||
this.permissionTransactionFilter = permissionTransactionFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult<TransactionInvalidReason> validate(
|
||||
final Transaction transaction,
|
||||
final Optional<Wei> baseFee,
|
||||
final TransactionValidationParams transactionValidationParams) {
|
||||
return delegate.validate(transaction, baseFee, transactionValidationParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValidationResult<TransactionInvalidReason> validateForSender(
|
||||
final Transaction transaction,
|
||||
final Account sender,
|
||||
final TransactionValidationParams validationParams) {
|
||||
|
||||
if (!isSenderAllowed(transaction, validationParams)) {
|
||||
return ValidationResult.invalid(
|
||||
TransactionInvalidReason.TX_SENDER_NOT_AUTHORIZED,
|
||||
String.format("Sender %s is not on the Account Allowlist", transaction.getSender()));
|
||||
}
|
||||
|
||||
return delegate.validateForSender(transaction, sender, validationParams);
|
||||
}
|
||||
|
||||
private boolean isSenderAllowed(
|
||||
final Transaction transaction, final TransactionValidationParams validationParams) {
|
||||
if (validationParams.checkLocalPermissions() || validationParams.checkOnchainPermissions()) {
|
||||
return permissionTransactionFilter.permitted(
|
||||
transaction,
|
||||
validationParams.checkLocalPermissions(),
|
||||
validationParams.checkOnchainPermissions());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,8 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
|
||||
public interface PrivacySupportingProtocolSchedule {
|
||||
|
||||
void setTransactionFilter(final PermissionTransactionFilter permissionTransactionFilter);
|
||||
void setPermissionTransactionFilter(
|
||||
final PermissionTransactionFilter permissionTransactionFilter);
|
||||
|
||||
void setPublicWorldStateArchiveForPrivacyBlockProcessor(
|
||||
final WorldStateArchive publicWorldStateArchive);
|
||||
|
||||
@@ -38,7 +38,7 @@ public class ProtocolSpec {
|
||||
|
||||
private final GasLimitCalculator gasLimitCalculator;
|
||||
|
||||
private final TransactionValidator transactionValidator;
|
||||
private final TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
private final MainnetTransactionProcessor transactionProcessor;
|
||||
|
||||
@@ -87,7 +87,7 @@ public class ProtocolSpec {
|
||||
*
|
||||
* @param name the protocol specification name
|
||||
* @param evm the EVM supporting the appropriate operations for this specification
|
||||
* @param transactionValidator the transaction validator to use
|
||||
* @param transactionValidatorFactory the transaction validator factory to use
|
||||
* @param transactionProcessor the transaction processor to use
|
||||
* @param privateTransactionProcessor the private transaction processor to use
|
||||
* @param blockHeaderValidator the block header validator to use
|
||||
@@ -118,7 +118,7 @@ public class ProtocolSpec {
|
||||
public ProtocolSpec(
|
||||
final String name,
|
||||
final EVM evm,
|
||||
final TransactionValidator transactionValidator,
|
||||
final TransactionValidatorFactory transactionValidatorFactory,
|
||||
final MainnetTransactionProcessor transactionProcessor,
|
||||
final PrivateTransactionProcessor privateTransactionProcessor,
|
||||
final BlockHeaderValidator blockHeaderValidator,
|
||||
@@ -146,7 +146,7 @@ public class ProtocolSpec {
|
||||
final boolean isReplayProtectionSupported) {
|
||||
this.name = name;
|
||||
this.evm = evm;
|
||||
this.transactionValidator = transactionValidator;
|
||||
this.transactionValidatorFactory = transactionValidatorFactory;
|
||||
this.transactionProcessor = transactionProcessor;
|
||||
this.privateTransactionProcessor = privateTransactionProcessor;
|
||||
this.blockHeaderValidator = blockHeaderValidator;
|
||||
@@ -184,12 +184,12 @@ public class ProtocolSpec {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transaction validator used in this specification.
|
||||
* Returns the transaction validator factory used in this specification.
|
||||
*
|
||||
* @return the transaction validator
|
||||
* @return the transaction validator factory
|
||||
*/
|
||||
public TransactionValidator getTransactionValidator() {
|
||||
return transactionValidator;
|
||||
public TransactionValidatorFactory getTransactionValidatorFactory() {
|
||||
return transactionValidatorFactory;
|
||||
}
|
||||
|
||||
public boolean isReplayProtectionSupported() {
|
||||
|
||||
@@ -53,8 +53,8 @@ public class ProtocolSpecBuilder {
|
||||
private DifficultyCalculator difficultyCalculator;
|
||||
private EvmConfiguration evmConfiguration;
|
||||
private BiFunction<GasCalculator, EvmConfiguration, EVM> evmBuilder;
|
||||
private BiFunction<GasCalculator, GasLimitCalculator, TransactionValidator>
|
||||
transactionValidatorBuilder;
|
||||
private BiFunction<GasCalculator, GasLimitCalculator, TransactionValidatorFactory>
|
||||
transactionValidatorFactoryBuilder;
|
||||
private Function<FeeMarket, BlockHeaderValidator.Builder> blockHeaderValidatorBuilder;
|
||||
private Function<FeeMarket, BlockHeaderValidator.Builder> ommerHeaderValidatorBuilder;
|
||||
private Function<ProtocolSchedule, BlockBodyValidator> blockBodyValidatorBuilder;
|
||||
@@ -126,9 +126,9 @@ public class ProtocolSpecBuilder {
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder transactionValidatorBuilder(
|
||||
final BiFunction<GasCalculator, GasLimitCalculator, TransactionValidator>
|
||||
transactionValidatorBuilder) {
|
||||
this.transactionValidatorBuilder = transactionValidatorBuilder;
|
||||
final BiFunction<GasCalculator, GasLimitCalculator, TransactionValidatorFactory>
|
||||
transactionValidatorFactoryBuilder) {
|
||||
this.transactionValidatorFactoryBuilder = transactionValidatorFactoryBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ public class ProtocolSpecBuilder {
|
||||
checkNotNull(gasLimitCalculator, "Missing gasLimitCalculator");
|
||||
checkNotNull(evmBuilder, "Missing operation registry");
|
||||
checkNotNull(evmConfiguration, "Missing evm configuration");
|
||||
checkNotNull(transactionValidatorBuilder, "Missing transaction validator");
|
||||
checkNotNull(transactionValidatorFactoryBuilder, "Missing transaction validator");
|
||||
checkNotNull(privateTransactionValidatorBuilder, "Missing private transaction validator");
|
||||
checkNotNull(contractCreationProcessorBuilder, "Missing contract creation processor");
|
||||
checkNotNull(precompileContractRegistryBuilder, "Missing precompile contract registry");
|
||||
@@ -309,8 +309,8 @@ public class ProtocolSpecBuilder {
|
||||
final EVM evm = evmBuilder.apply(gasCalculator, evmConfiguration);
|
||||
final PrecompiledContractConfiguration precompiledContractConfiguration =
|
||||
new PrecompiledContractConfiguration(gasCalculator, privacyParameters);
|
||||
final TransactionValidator transactionValidator =
|
||||
transactionValidatorBuilder.apply(gasCalculator, gasLimitCalculator);
|
||||
final TransactionValidatorFactory transactionValidatorFactory =
|
||||
transactionValidatorFactoryBuilder.apply(gasCalculator, gasLimitCalculator);
|
||||
final AbstractMessageProcessor contractCreationProcessor =
|
||||
contractCreationProcessorBuilder.apply(gasCalculator, evm);
|
||||
final PrecompileContractRegistry precompileContractRegistry =
|
||||
@@ -319,7 +319,10 @@ public class ProtocolSpecBuilder {
|
||||
messageCallProcessorBuilder.apply(evm, precompileContractRegistry);
|
||||
final MainnetTransactionProcessor transactionProcessor =
|
||||
transactionProcessorBuilder.apply(
|
||||
gasCalculator, transactionValidator, contractCreationProcessor, messageCallProcessor);
|
||||
gasCalculator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor);
|
||||
|
||||
final BlockHeaderValidator blockHeaderValidator =
|
||||
createBlockHeaderValidator(blockHeaderValidatorBuilder);
|
||||
@@ -333,7 +336,7 @@ public class ProtocolSpecBuilder {
|
||||
// Set private Tx Processor
|
||||
PrivateTransactionProcessor privateTransactionProcessor =
|
||||
createPrivateTransactionProcessor(
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
precompileContractRegistry);
|
||||
@@ -357,7 +360,7 @@ public class ProtocolSpecBuilder {
|
||||
return new ProtocolSpec(
|
||||
name,
|
||||
evm,
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
transactionProcessor,
|
||||
privateTransactionProcessor,
|
||||
blockHeaderValidator,
|
||||
@@ -386,7 +389,7 @@ public class ProtocolSpecBuilder {
|
||||
}
|
||||
|
||||
private PrivateTransactionProcessor createPrivateTransactionProcessor(
|
||||
final TransactionValidator transactionValidator,
|
||||
final TransactionValidatorFactory transactionValidatorFactory,
|
||||
final AbstractMessageProcessor contractCreationProcessor,
|
||||
final AbstractMessageProcessor messageCallProcessor,
|
||||
final PrecompileContractRegistry precompileContractRegistry) {
|
||||
@@ -396,7 +399,7 @@ public class ProtocolSpecBuilder {
|
||||
privateTransactionValidatorBuilder.apply();
|
||||
privateTransactionProcessor =
|
||||
privateTransactionProcessorBuilder.apply(
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
privateTransactionValidator);
|
||||
@@ -443,14 +446,14 @@ public class ProtocolSpecBuilder {
|
||||
public interface TransactionProcessorBuilder {
|
||||
MainnetTransactionProcessor apply(
|
||||
GasCalculator gasCalculator,
|
||||
TransactionValidator transactionValidator,
|
||||
TransactionValidatorFactory transactionValidatorFactory,
|
||||
AbstractMessageProcessor contractCreationProcessor,
|
||||
AbstractMessageProcessor messageCallProcessor);
|
||||
}
|
||||
|
||||
public interface PrivateTransactionProcessorBuilder {
|
||||
PrivateTransactionProcessor apply(
|
||||
TransactionValidator transactionValidator,
|
||||
TransactionValidatorFactory transactionValidatorFactory,
|
||||
AbstractMessageProcessor contractCreationProcessor,
|
||||
AbstractMessageProcessor messageCallProcessor,
|
||||
PrivateTransactionValidator privateTransactionValidator);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
@@ -53,13 +52,4 @@ public interface TransactionValidator {
|
||||
*/
|
||||
ValidationResult<TransactionInvalidReason> validateForSender(
|
||||
Transaction transaction, Account sender, TransactionValidationParams validationParams);
|
||||
|
||||
/**
|
||||
* Set the permission transaction filter. This way of setting the filter is deprecated and will be
|
||||
* removed.
|
||||
*
|
||||
* @param permissionTransactionFilter the permission transaction filter
|
||||
*/
|
||||
@Deprecated
|
||||
void setPermissionTransactionFilter(PermissionTransactionFilter permissionTransactionFilter);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.mainnet;
|
||||
|
||||
import org.hyperledger.besu.datatypes.TransactionType;
|
||||
import org.hyperledger.besu.ethereum.GasLimitCalculator;
|
||||
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
public class TransactionValidatorFactory {
|
||||
private final GasCalculator gasCalculator;
|
||||
private final GasLimitCalculator gasLimitCalculator;
|
||||
private final FeeMarket feeMarket;
|
||||
private final boolean disallowSignatureMalleability;
|
||||
private final Optional<BigInteger> chainId;
|
||||
private final Set<TransactionType> acceptedTransactionTypes;
|
||||
private final int maxInitcodeSize;
|
||||
private Optional<PermissionTransactionFilter> permissionTransactionFilter = Optional.empty();
|
||||
|
||||
public TransactionValidatorFactory(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId) {
|
||||
this(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
Set.of(TransactionType.FRONTIER));
|
||||
}
|
||||
|
||||
public TransactionValidatorFactory(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Set<TransactionType> acceptedTransactionTypes) {
|
||||
this(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
FeeMarket.legacy(),
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
acceptedTransactionTypes,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public TransactionValidatorFactory(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final FeeMarket feeMarket,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Set<TransactionType> acceptedTransactionTypes,
|
||||
final int maxInitcodeSize) {
|
||||
this.gasCalculator = gasCalculator;
|
||||
this.gasLimitCalculator = gasLimitCalculator;
|
||||
this.feeMarket = feeMarket;
|
||||
this.disallowSignatureMalleability = checkSignatureMalleability;
|
||||
this.chainId = chainId;
|
||||
this.acceptedTransactionTypes = acceptedTransactionTypes;
|
||||
this.maxInitcodeSize = maxInitcodeSize;
|
||||
}
|
||||
|
||||
public void setPermissionTransactionFilter(
|
||||
final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
this.permissionTransactionFilter = Optional.of(permissionTransactionFilter);
|
||||
}
|
||||
|
||||
public TransactionValidator get() {
|
||||
return Suppliers.memoize(this::createTransactionValidator).get();
|
||||
}
|
||||
|
||||
private TransactionValidator createTransactionValidator() {
|
||||
final TransactionValidator baseValidator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
feeMarket,
|
||||
disallowSignatureMalleability,
|
||||
chainId,
|
||||
acceptedTransactionTypes,
|
||||
maxInitcodeSize);
|
||||
if (permissionTransactionFilter.isPresent()) {
|
||||
return new PermissionTransactionValidator(baseValidator, permissionTransactionFilter.get());
|
||||
}
|
||||
return baseValidator;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
|
||||
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.processing.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
@@ -49,7 +49,7 @@ public class PrivateTransactionProcessor {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PrivateTransactionProcessor.class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final TransactionValidator transactionValidator;
|
||||
private final TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
private final PrivateTransactionValidator privateTransactionValidator;
|
||||
|
||||
@@ -63,13 +63,13 @@ public class PrivateTransactionProcessor {
|
||||
private final boolean clearEmptyAccounts;
|
||||
|
||||
public PrivateTransactionProcessor(
|
||||
final TransactionValidator transactionValidator,
|
||||
final TransactionValidatorFactory transactionValidatorFactory,
|
||||
final AbstractMessageProcessor contractCreationProcessor,
|
||||
final AbstractMessageProcessor messageCallProcessor,
|
||||
final boolean clearEmptyAccounts,
|
||||
final int maxStackSize,
|
||||
final PrivateTransactionValidator privateTransactionValidator) {
|
||||
this.transactionValidator = transactionValidator;
|
||||
this.transactionValidatorFactory = transactionValidatorFactory;
|
||||
this.contractCreationProcessor = contractCreationProcessor;
|
||||
this.messageCallProcessor = messageCallProcessor;
|
||||
this.clearEmptyAccounts = clearEmptyAccounts;
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
@@ -53,7 +54,10 @@ public class MainnetTransactionProcessorTest {
|
||||
private static final int MAX_STACK_SIZE = 1024;
|
||||
|
||||
private final GasCalculator gasCalculator = new LondonGasCalculator();
|
||||
@Mock private TransactionValidator transactionValidator;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
@Mock private AbstractMessageProcessor contractCreationProcessor;
|
||||
@Mock private AbstractMessageProcessor messageCallProcessor;
|
||||
|
||||
@@ -69,7 +73,7 @@ public class MainnetTransactionProcessorTest {
|
||||
MainnetTransactionProcessor createTransactionProcessor(final boolean warmCoinbase) {
|
||||
return new MainnetTransactionProcessor(
|
||||
gasCalculator,
|
||||
transactionValidator,
|
||||
transactionValidatorFactory,
|
||||
contractCreationProcessor,
|
||||
messageCallProcessor,
|
||||
false,
|
||||
@@ -92,8 +96,9 @@ public class MainnetTransactionProcessorTest {
|
||||
when(transaction.getPayload()).thenReturn(Bytes.EMPTY);
|
||||
when(transaction.getSender()).thenReturn(senderAddress);
|
||||
when(transaction.getValue()).thenReturn(Wei.ZERO);
|
||||
when(transactionValidator.validate(any(), any(), any())).thenReturn(ValidationResult.valid());
|
||||
when(transactionValidator.validateForSender(any(), any(), any()))
|
||||
when(transactionValidatorFactory.get().validate(any(), any(), any()))
|
||||
.thenReturn(ValidationResult.valid());
|
||||
when(transactionValidatorFactory.get().validateForSender(any(), any(), any()))
|
||||
.thenReturn(ValidationResult.valid());
|
||||
when(worldState.getOrCreate(any())).thenReturn(senderAccount);
|
||||
when(worldState.getOrCreateSenderAccount(any())).thenReturn(senderAccount);
|
||||
@@ -168,9 +173,12 @@ public class MainnetTransactionProcessorTest {
|
||||
private ArgumentCaptor<TransactionValidationParams> transactionValidationParamCaptor() {
|
||||
final ArgumentCaptor<TransactionValidationParams> txValidationParamCaptor =
|
||||
ArgumentCaptor.forClass(TransactionValidationParams.class);
|
||||
when(transactionValidator.validate(any(), any(), any())).thenReturn(ValidationResult.valid());
|
||||
when(transactionValidatorFactory.get().validate(any(), any(), any()))
|
||||
.thenReturn(ValidationResult.valid());
|
||||
// returning invalid transaction to halt method execution
|
||||
when(transactionValidator.validateForSender(any(), any(), txValidationParamCaptor.capture()))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(any(), any(), txValidationParamCaptor.capture()))
|
||||
.thenReturn(ValidationResult.invalid(TransactionInvalidReason.NONCE_TOO_HIGH));
|
||||
return txValidationParamCaptor;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair;
|
||||
@@ -36,7 +35,6 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.TransactionType;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.GasLimitCalculator;
|
||||
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
@@ -53,7 +51,6 @@ import com.google.common.base.Suppliers;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@@ -74,10 +71,43 @@ public class MainnetTransactionValidatorTest {
|
||||
.chainId(Optional.of(BigInteger.ONE))
|
||||
.createTransaction(senderKeys);
|
||||
|
||||
protected TransactionValidator createTransactionValidator(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final FeeMarket feeMarket,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Set<TransactionType> acceptedTransactionTypes,
|
||||
final int maxInitcodeSize) {
|
||||
return new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
feeMarket,
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
acceptedTransactionTypes,
|
||||
maxInitcodeSize);
|
||||
}
|
||||
|
||||
protected TransactionValidator createTransactionValidator(
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId) {
|
||||
return createTransactionValidator(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
FeeMarket.legacy(),
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
Set.of(TransactionType.FRONTIER),
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
@@ -94,7 +124,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionWhenTransactionHasChainIdAndValidatorDoesNot() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
assertThat(validator.validate(basicTransaction, Optional.empty(), transactionValidationParams))
|
||||
.isEqualTo(
|
||||
@@ -105,7 +135,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionWhenTransactionHasIncorrectChainId() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
@@ -117,7 +147,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionWhenSenderAccountDoesNotExist() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
assertThat(validator.validateForSender(basicTransaction, null, processingBlockParams))
|
||||
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE));
|
||||
@@ -126,7 +156,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionWhenTransactionNonceBelowAccountNonce() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Account account = accountWithNonce(basicTransaction.getNonce() + 1);
|
||||
@@ -138,7 +168,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void
|
||||
shouldRejectTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsNotAllowed() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
|
||||
@@ -150,7 +180,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void
|
||||
shouldAcceptTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsAllowed() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
|
||||
@@ -161,7 +191,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionWhenNonceExceedsMaximumAllowedNonce() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Transaction transaction =
|
||||
@@ -175,7 +205,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void transactionWithNullSenderCanBeValidIfGasPriceAndValueIsZero() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final TransactionTestFixture builder = new TransactionTestFixture();
|
||||
@@ -192,9 +222,8 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionIfAccountIsNotEOA() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setPermissionTransactionFilter(transactionFilter(false));
|
||||
|
||||
Account invalidEOA =
|
||||
when(account(basicTransaction.getUpfrontCost(0L), basicTransaction.getNonce())
|
||||
@@ -202,42 +231,15 @@ public class MainnetTransactionValidatorTest {
|
||||
.thenReturn(Hash.fromHexStringLenient("0xdeadbeef"))
|
||||
.getMock();
|
||||
|
||||
assertThat(validator.validateForSender(basicTransaction, invalidEOA, transactionPoolParams))
|
||||
assertThat(validator.validateForSender(basicTransaction, invalidEOA, processingBlockParams))
|
||||
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.TX_SENDER_NOT_AUTHORIZED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRejectTransactionIfAccountIsNotPermitted() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setPermissionTransactionFilter(transactionFilter(false));
|
||||
|
||||
assertThat(
|
||||
validator.validateForSender(
|
||||
basicTransaction, accountWithNonce(0), transactionPoolParams))
|
||||
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.TX_SENDER_NOT_AUTHORIZED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptValidTransactionIfAccountIsPermitted() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setPermissionTransactionFilter(transactionFilter(true));
|
||||
|
||||
assertThat(
|
||||
validator.validateForSender(
|
||||
basicTransaction, accountWithNonce(0), transactionPoolParams))
|
||||
.isEqualTo(ValidationResult.valid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRejectTransactionWithMaxFeeTimesGasLimitGreaterThanBalance() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setPermissionTransactionFilter(transactionFilter(true));
|
||||
|
||||
assertThat(
|
||||
validator.validateForSender(
|
||||
@@ -260,7 +262,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionWithMaxPriorityFeeGreaterThanMaxFee() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L),
|
||||
@@ -271,7 +273,6 @@ public class MainnetTransactionValidatorTest {
|
||||
TransactionType.FRONTIER, TransactionType.ACCESS_LIST, TransactionType.EIP1559
|
||||
}),
|
||||
Integer.MAX_VALUE);
|
||||
validator.setPermissionTransactionFilter(transactionFilter(true));
|
||||
|
||||
final Transaction transaction =
|
||||
Transaction.builder()
|
||||
@@ -294,62 +295,10 @@ public class MainnetTransactionValidatorTest {
|
||||
.isEqualTo("max priority fee per gas cannot be greater than max fee per gas");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPropagateCorrectStateChangeParamToTransactionFilter() {
|
||||
final ArgumentCaptor<Boolean> stateChangeLocalParamCaptor =
|
||||
ArgumentCaptor.forClass(Boolean.class);
|
||||
final ArgumentCaptor<Boolean> stateChangeOnchainParamCaptor =
|
||||
ArgumentCaptor.forClass(Boolean.class);
|
||||
final PermissionTransactionFilter permissionTransactionFilter =
|
||||
mock(PermissionTransactionFilter.class);
|
||||
when(permissionTransactionFilter.permitted(
|
||||
any(Transaction.class),
|
||||
stateChangeLocalParamCaptor.capture(),
|
||||
stateChangeOnchainParamCaptor.capture()))
|
||||
.thenReturn(true);
|
||||
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setPermissionTransactionFilter(permissionTransactionFilter);
|
||||
|
||||
final TransactionValidationParams validationParams =
|
||||
ImmutableTransactionValidationParams.builder().checkOnchainPermissions(true).build();
|
||||
|
||||
validator.validateForSender(basicTransaction, accountWithNonce(0), validationParams);
|
||||
|
||||
assertThat(stateChangeLocalParamCaptor.getValue()).isTrue();
|
||||
assertThat(stateChangeOnchainParamCaptor.getValue()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCheckAccountPermissionIfBothValidationParamsCheckPermissionsAreFalse() {
|
||||
final PermissionTransactionFilter permissionTransactionFilter =
|
||||
mock(PermissionTransactionFilter.class);
|
||||
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setPermissionTransactionFilter(permissionTransactionFilter);
|
||||
|
||||
final TransactionValidationParams validationParams =
|
||||
ImmutableTransactionValidationParams.builder()
|
||||
.checkOnchainPermissions(false)
|
||||
.checkLocalPermissions(false)
|
||||
.build();
|
||||
|
||||
validator.validateForSender(basicTransaction, accountWithNonce(0), validationParams);
|
||||
|
||||
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), validationParams))
|
||||
.isEqualTo(ValidationResult.valid());
|
||||
|
||||
verifyNoInteractions(permissionTransactionFilter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptOnlyTransactionsInAcceptedTransactionTypes() {
|
||||
final TransactionValidator frontierValidator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.legacy(),
|
||||
@@ -392,7 +341,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTransactionIfEIP1559TransactionGasPriceLessBaseFee() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L),
|
||||
@@ -416,7 +365,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldAcceptZeroGasPriceTransactionIfBaseFeeIsZero() {
|
||||
final Optional<Wei> zeroBaseFee = Optional.of(Wei.ZERO);
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L, zeroBaseFee),
|
||||
@@ -439,7 +388,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldAcceptValidEIP1559() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L),
|
||||
@@ -464,7 +413,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldValidate1559TransactionWithPriceLowerThanBaseFeeForTransactionPool() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L),
|
||||
@@ -490,7 +439,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldRejectTooLargeInitcode() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L),
|
||||
@@ -517,7 +466,7 @@ public class MainnetTransactionValidatorTest {
|
||||
@Test
|
||||
public void shouldAcceptTransactionWithAtLeastOneBlob() {
|
||||
final TransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
createTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
FeeMarket.london(0L),
|
||||
@@ -547,12 +496,4 @@ public class MainnetTransactionValidatorTest {
|
||||
when(account.getNonce()).thenReturn(nonce);
|
||||
return account;
|
||||
}
|
||||
|
||||
private PermissionTransactionFilter transactionFilter(final boolean permitted) {
|
||||
final PermissionTransactionFilter permissionTransactionFilter =
|
||||
mock(PermissionTransactionFilter.class);
|
||||
when(permissionTransactionFilter.permitted(any(Transaction.class), anyBoolean(), anyBoolean()))
|
||||
.thenReturn(permitted);
|
||||
return permissionTransactionFilter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.mainnet;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams.transactionPoolParams;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.GasLimitCalculator;
|
||||
import org.hyperledger.besu.ethereum.core.PermissionTransactionFilter;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PermissionTransactionValidatorTest extends MainnetTransactionValidatorTest {
|
||||
|
||||
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
|
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
|
||||
private static final KeyPair senderKeys = SIGNATURE_ALGORITHM.get().generateKeyPair();
|
||||
@Mock private GasCalculator gasCalculator;
|
||||
|
||||
private final Transaction basicTransaction =
|
||||
new TransactionTestFixture()
|
||||
.chainId(Optional.of(BigInteger.ONE))
|
||||
.createTransaction(senderKeys);
|
||||
|
||||
@Test
|
||||
public void shouldRejectTransactionIfAccountIsNotPermitted() {
|
||||
final TransactionValidator baseValidator =
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
final TransactionValidator validator =
|
||||
new PermissionTransactionValidator(baseValidator, transactionFilter(false));
|
||||
|
||||
assertThat(
|
||||
validator.validateForSender(
|
||||
basicTransaction, accountWithNonce(0), transactionPoolParams))
|
||||
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.TX_SENDER_NOT_AUTHORIZED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptValidTransactionIfAccountIsPermitted() {
|
||||
final TransactionValidator baseValidator =
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
final TransactionValidator validator =
|
||||
new PermissionTransactionValidator(baseValidator, transactionFilter(true));
|
||||
|
||||
assertThat(
|
||||
validator.validateForSender(
|
||||
basicTransaction, accountWithNonce(0), transactionPoolParams))
|
||||
.isEqualTo(ValidationResult.valid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPropagateCorrectStateChangeParamToTransactionFilter() {
|
||||
final ArgumentCaptor<Boolean> stateChangeLocalParamCaptor =
|
||||
ArgumentCaptor.forClass(Boolean.class);
|
||||
final ArgumentCaptor<Boolean> stateChangeOnchainParamCaptor =
|
||||
ArgumentCaptor.forClass(Boolean.class);
|
||||
final PermissionTransactionFilter permissionTransactionFilter =
|
||||
mock(PermissionTransactionFilter.class);
|
||||
when(permissionTransactionFilter.permitted(
|
||||
any(Transaction.class),
|
||||
stateChangeLocalParamCaptor.capture(),
|
||||
stateChangeOnchainParamCaptor.capture()))
|
||||
.thenReturn(true);
|
||||
|
||||
final TransactionValidator baseValidator =
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
final TransactionValidator validator =
|
||||
new PermissionTransactionValidator(baseValidator, permissionTransactionFilter);
|
||||
|
||||
final TransactionValidationParams validationParams =
|
||||
ImmutableTransactionValidationParams.builder().checkOnchainPermissions(true).build();
|
||||
|
||||
validator.validateForSender(basicTransaction, accountWithNonce(0), validationParams);
|
||||
|
||||
assertThat(stateChangeLocalParamCaptor.getValue()).isTrue();
|
||||
assertThat(stateChangeOnchainParamCaptor.getValue()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCheckAccountPermissionIfBothValidationParamsCheckPermissionsAreFalse() {
|
||||
final PermissionTransactionFilter permissionTransactionFilter =
|
||||
mock(PermissionTransactionFilter.class);
|
||||
|
||||
final TransactionValidator baseValidator =
|
||||
createTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
final TransactionValidator validator =
|
||||
new PermissionTransactionValidator(baseValidator, permissionTransactionFilter);
|
||||
|
||||
final TransactionValidationParams validationParams =
|
||||
ImmutableTransactionValidationParams.builder()
|
||||
.checkOnchainPermissions(false)
|
||||
.checkLocalPermissions(false)
|
||||
.build();
|
||||
|
||||
validator.validateForSender(basicTransaction, accountWithNonce(0), validationParams);
|
||||
|
||||
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), validationParams))
|
||||
.isEqualTo(ValidationResult.valid());
|
||||
|
||||
verifyNoInteractions(permissionTransactionFilter);
|
||||
}
|
||||
|
||||
private Account accountWithNonce(final long nonce) {
|
||||
return account(basicTransaction.getUpfrontCost(0L), nonce);
|
||||
}
|
||||
|
||||
private Account account(final Wei balance, final long nonce) {
|
||||
final Account account = mock(Account.class);
|
||||
when(account.getBalance()).thenReturn(balance);
|
||||
when(account.getNonce()).thenReturn(nonce);
|
||||
return account;
|
||||
}
|
||||
|
||||
private PermissionTransactionFilter transactionFilter(final boolean permitted) {
|
||||
final PermissionTransactionFilter permissionTransactionFilter =
|
||||
mock(PermissionTransactionFilter.class);
|
||||
when(permissionTransactionFilter.permitted(any(Transaction.class), anyBoolean(), anyBoolean()))
|
||||
.thenReturn(permitted);
|
||||
return permissionTransactionFilter;
|
||||
}
|
||||
}
|
||||
@@ -364,7 +364,8 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
private TransactionValidator getTransactionValidator() {
|
||||
return protocolSchedule
|
||||
.getByBlockHeader(protocolContext.getBlockchain().getChainHeadHeader())
|
||||
.getTransactionValidator();
|
||||
.getTransactionValidatorFactory()
|
||||
.get();
|
||||
}
|
||||
|
||||
private ValidationResultAndAccount validateLocalTransaction(final Transaction transaction) {
|
||||
|
||||
@@ -61,7 +61,7 @@ import org.hyperledger.besu.ethereum.eth.messages.EthPV65;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
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.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
@@ -81,6 +81,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@@ -97,7 +98,10 @@ public abstract class AbstractTransactionPoolTest {
|
||||
|
||||
private static final KeyPair KEY_PAIR2 =
|
||||
SignatureAlgorithmFactory.getInstance().generateKeyPair();
|
||||
@Mock protected TransactionValidator transactionValidator;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
protected TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
@Mock protected PendingTransactionAddedListener listener;
|
||||
@Mock protected MiningParameters miningParameters;
|
||||
@Mock protected TransactionsMessageSender transactionsMessageSender;
|
||||
@@ -136,7 +140,7 @@ public abstract class AbstractTransactionPoolTest {
|
||||
protocolContext = executionContext.getProtocolContext();
|
||||
blockchain = executionContext.getBlockchain();
|
||||
transactions = spy(createPendingTransactionsSorter());
|
||||
when(protocolSpec.getTransactionValidator()).thenReturn(transactionValidator);
|
||||
when(protocolSpec.getTransactionValidatorFactory()).thenReturn(transactionValidatorFactory);
|
||||
when(protocolSpec.getFeeMarket()).thenReturn(getFeeMarket());
|
||||
protocolSchedule = spy(executionContext.getProtocolSchedule());
|
||||
doReturn(protocolSpec).when(protocolSchedule).getByBlockHeader(any());
|
||||
@@ -364,13 +368,13 @@ public abstract class AbstractTransactionPoolTest {
|
||||
transactionPool.addRemoteTransactions(singletonList(transaction));
|
||||
|
||||
assertTransactionNotPending(transaction);
|
||||
verifyNoMoreInteractions(transactionValidator);
|
||||
verifyNoMoreInteractions(transactionValidatorFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotAddRemoteTransactionsWhenThereIsAnLowestInvalidNonceForTheSender() {
|
||||
givenTransactionIsValid(transaction2);
|
||||
when(transactionValidator.validate(eq(transaction1), any(Optional.class), any()))
|
||||
when(transactionValidatorFactory.get().validate(eq(transaction1), any(Optional.class), any()))
|
||||
.thenReturn(ValidationResult.invalid(NONCE_TOO_LOW));
|
||||
|
||||
transactionPool.addRemoteTransactions(asList(transaction1, transaction2));
|
||||
@@ -384,20 +388,23 @@ public abstract class AbstractTransactionPoolTest {
|
||||
public void shouldNotAddRemoteTransactionsThatAreInvalidAccordingToStateDependentChecks() {
|
||||
givenTransactionIsValid(transaction1);
|
||||
givenTransactionIsValid(transaction2);
|
||||
when(transactionValidator.validateForSender(
|
||||
eq(transaction2), eq(null), any(TransactionValidationParams.class)))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(eq(transaction2), eq(null), any(TransactionValidationParams.class)))
|
||||
.thenReturn(ValidationResult.invalid(NONCE_TOO_LOW));
|
||||
transactionPool.addRemoteTransactions(asList(transaction1, transaction2));
|
||||
|
||||
assertTransactionPending(transaction1);
|
||||
assertTransactionNotPending(transaction2);
|
||||
verify(transactionBroadcaster).onTransactionsAdded(singletonList(transaction1));
|
||||
verify(transactionValidator).validate(eq(transaction1), any(Optional.class), any());
|
||||
verify(transactionValidator)
|
||||
verify(transactionValidatorFactory.get())
|
||||
.validate(eq(transaction1), any(Optional.class), any());
|
||||
verify(transactionValidatorFactory.get())
|
||||
.validateForSender(eq(transaction1), eq(null), any(TransactionValidationParams.class));
|
||||
verify(transactionValidator).validate(eq(transaction2), any(Optional.class), any());
|
||||
verify(transactionValidator).validateForSender(eq(transaction2), any(), any());
|
||||
verifyNoMoreInteractions(transactionValidator);
|
||||
verify(transactionValidatorFactory.get())
|
||||
.validate(eq(transaction2), any(Optional.class), any());
|
||||
verify(transactionValidatorFactory.get()).validateForSender(eq(transaction2), any(), any());
|
||||
verifyNoMoreInteractions(transactionValidatorFactory.get());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -440,7 +447,7 @@ public abstract class AbstractTransactionPoolTest {
|
||||
transactionPool.addRemoteTransactions(singletonList(transaction1));
|
||||
|
||||
verify(transactions).containsTransaction(transaction1);
|
||||
verifyNoInteractions(transactionValidator);
|
||||
verifyNoInteractions(transactionValidatorFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -584,9 +591,11 @@ public abstract class AbstractTransactionPoolTest {
|
||||
final ArgumentCaptor<TransactionValidationParams> txValidationParamCaptor =
|
||||
ArgumentCaptor.forClass(TransactionValidationParams.class);
|
||||
|
||||
when(transactionValidator.validate(eq(transaction1), any(Optional.class), any()))
|
||||
when(transactionValidatorFactory.get().validate(eq(transaction1), any(Optional.class), any()))
|
||||
.thenReturn(valid());
|
||||
when(transactionValidator.validateForSender(any(), any(), txValidationParamCaptor.capture()))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(any(), any(), txValidationParamCaptor.capture()))
|
||||
.thenReturn(valid());
|
||||
|
||||
final TransactionValidationParams expectedValidationParams =
|
||||
@@ -685,10 +694,12 @@ public abstract class AbstractTransactionPoolTest {
|
||||
}
|
||||
|
||||
protected void givenTransactionIsValid(final Transaction transaction) {
|
||||
when(transactionValidator.validate(eq(transaction), any(Optional.class), any()))
|
||||
when(transactionValidatorFactory.get().validate(eq(transaction), any(Optional.class), any()))
|
||||
.thenReturn(valid());
|
||||
when(transactionValidator.validateForSender(
|
||||
eq(transaction), nullable(Account.class), any(TransactionValidationParams.class)))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(
|
||||
eq(transaction), nullable(Account.class), any(TransactionValidationParams.class)))
|
||||
.thenReturn(valid());
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ import org.hyperledger.besu.ethereum.eth.messages.EthPV65;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
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.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
@@ -80,6 +80,7 @@ import java.util.function.Consumer;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
@@ -93,7 +94,10 @@ public abstract class AbstractTransactionsLayeredPendingTransactionsTest {
|
||||
|
||||
private static final KeyPair KEY_PAIR2 =
|
||||
SignatureAlgorithmFactory.getInstance().generateKeyPair();
|
||||
@Mock protected TransactionValidator transactionValidator;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
protected TransactionValidatorFactory transactionValidatorFactory;
|
||||
|
||||
@Mock protected PendingTransactionAddedListener listener;
|
||||
@Mock protected MiningParameters miningParameters;
|
||||
@Mock protected TransactionsMessageSender transactionsMessageSender;
|
||||
@@ -135,7 +139,7 @@ public abstract class AbstractTransactionsLayeredPendingTransactionsTest {
|
||||
protocolContext = executionContext.getProtocolContext();
|
||||
blockchain = executionContext.getBlockchain();
|
||||
|
||||
when(protocolSpec.getTransactionValidator()).thenReturn(transactionValidator);
|
||||
when(protocolSpec.getTransactionValidatorFactory()).thenReturn(transactionValidatorFactory);
|
||||
when(protocolSpec.getFeeMarket()).thenReturn(getFeeMarket());
|
||||
protocolSchedule = spy(executionContext.getProtocolSchedule());
|
||||
doReturn(protocolSpec).when(protocolSchedule).getByBlockHeader(any());
|
||||
@@ -362,27 +366,30 @@ public abstract class AbstractTransactionsLayeredPendingTransactionsTest {
|
||||
transactionPool.addRemoteTransactions(singletonList(transaction));
|
||||
|
||||
assertTransactionNotPending(transaction);
|
||||
verifyNoMoreInteractions(transactionValidator);
|
||||
verifyNoMoreInteractions(transactionValidatorFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotAddRemoteTransactionsThatAreInvalidAccordingToStateDependentChecks() {
|
||||
givenTransactionIsValid(transaction0);
|
||||
givenTransactionIsValid(transaction1);
|
||||
when(transactionValidator.validateForSender(
|
||||
eq(transaction1), eq(null), any(TransactionValidationParams.class)))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(eq(transaction1), eq(null), any(TransactionValidationParams.class)))
|
||||
.thenReturn(ValidationResult.invalid(NONCE_TOO_LOW));
|
||||
transactionPool.addRemoteTransactions(asList(transaction0, transaction1));
|
||||
|
||||
assertTransactionPending(transaction0);
|
||||
assertTransactionNotPending(transaction1);
|
||||
verify(transactionBroadcaster).onTransactionsAdded(singletonList(transaction0));
|
||||
verify(transactionValidator).validate(eq(transaction0), any(Optional.class), any());
|
||||
verify(transactionValidator)
|
||||
verify(transactionValidatorFactory.get())
|
||||
.validate(eq(transaction0), any(Optional.class), any());
|
||||
verify(transactionValidatorFactory.get())
|
||||
.validateForSender(eq(transaction0), eq(null), any(TransactionValidationParams.class));
|
||||
verify(transactionValidator).validate(eq(transaction1), any(Optional.class), any());
|
||||
verify(transactionValidator).validateForSender(eq(transaction1), any(), any());
|
||||
verifyNoMoreInteractions(transactionValidator);
|
||||
verify(transactionValidatorFactory.get())
|
||||
.validate(eq(transaction1), any(Optional.class), any());
|
||||
verify(transactionValidatorFactory.get()).validateForSender(eq(transaction1), any(), any());
|
||||
verifyNoMoreInteractions(transactionValidatorFactory.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -423,7 +430,7 @@ public abstract class AbstractTransactionsLayeredPendingTransactionsTest {
|
||||
transactionPool.addRemoteTransactions(singletonList(transaction0));
|
||||
|
||||
verify(transactions).containsTransaction(transaction0);
|
||||
verifyNoInteractions(transactionValidator);
|
||||
verifyNoInteractions(transactionValidatorFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -551,9 +558,11 @@ public abstract class AbstractTransactionsLayeredPendingTransactionsTest {
|
||||
final ArgumentCaptor<TransactionValidationParams> txValidationParamCaptor =
|
||||
ArgumentCaptor.forClass(TransactionValidationParams.class);
|
||||
|
||||
when(transactionValidator.validate(eq(transaction0), any(Optional.class), any()))
|
||||
when(transactionValidatorFactory.get().validate(eq(transaction0), any(Optional.class), any()))
|
||||
.thenReturn(valid());
|
||||
when(transactionValidator.validateForSender(any(), any(), txValidationParamCaptor.capture()))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(any(), any(), txValidationParamCaptor.capture()))
|
||||
.thenReturn(valid());
|
||||
|
||||
final TransactionValidationParams expectedValidationParams =
|
||||
@@ -647,10 +656,12 @@ public abstract class AbstractTransactionsLayeredPendingTransactionsTest {
|
||||
}
|
||||
|
||||
protected void givenTransactionIsValid(final Transaction transaction) {
|
||||
when(transactionValidator.validate(eq(transaction), any(Optional.class), any()))
|
||||
when(transactionValidatorFactory.get().validate(eq(transaction), any(Optional.class), any()))
|
||||
.thenReturn(valid());
|
||||
when(transactionValidator.validateForSender(
|
||||
eq(transaction), nullable(Account.class), any(TransactionValidationParams.class)))
|
||||
when(transactionValidatorFactory
|
||||
.get()
|
||||
.validateForSender(
|
||||
eq(transaction), nullable(Account.class), any(TransactionValidationParams.class)))
|
||||
.thenReturn(valid());
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public class TransactionTest {
|
||||
return REFERENCE_TEST_PROTOCOL_SCHEDULES
|
||||
.getByName(name)
|
||||
.getByBlockHeader(BlockHeaderBuilder.createDefault().buildBlockHeader())
|
||||
.getTransactionValidator();
|
||||
.getTransactionValidatorFactory().get();
|
||||
}
|
||||
|
||||
private static final String TEST_CONFIG_FILE_DIR_PATH = "TransactionTests/";
|
||||
|
||||
@@ -62,7 +62,7 @@ public class NoRewardProtocolScheduleWrapper implements ProtocolSchedule {
|
||||
return new ProtocolSpec(
|
||||
original.getName(),
|
||||
original.getEvm(),
|
||||
original.getTransactionValidator(),
|
||||
original.getTransactionValidatorFactory(),
|
||||
original.getTransactionProcessor(),
|
||||
original.getPrivateTransactionProcessor(),
|
||||
original.getBlockHeaderValidator(),
|
||||
@@ -121,8 +121,9 @@ public class NoRewardProtocolScheduleWrapper implements ProtocolSchedule {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransactionFilter(final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
delegate.setTransactionFilter(permissionTransactionFilter);
|
||||
public void setPermissionTransactionFilter(
|
||||
final PermissionTransactionFilter permissionTransactionFilter) {
|
||||
delegate.setPermissionTransactionFilter(permissionTransactionFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user