Added zero gasPrice validation for Quorum compatibility mode. (#1554)

* Added zero gasPrice validation + configuration checks for GoQuorum compatibility mode.

Signed-off-by: Mark Terry <mark.terry@consensys.net>
pull/1574/head
mark-terry 4 years ago committed by GitHub
parent 0bedfffe02
commit e783dd7294
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  2. 27
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  3. 3
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/CliqueProtocolSchedule.java
  4. 3
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/IbftProtocolSchedule.java
  5. 3
      consensus/ibftlegacy/src/main/java/org/hyperledger/besu/consensus/ibftlegacy/IbftProtocolSchedule.java
  6. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverter.java
  7. 1
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java
  8. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcErrorConverterTest.java
  9. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSendRawTransactionTest.java
  10. 37
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/EthHashBlockCreatorTest.java
  11. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java
  12. 70
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java
  13. 7
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSchedule.java
  14. 112
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java
  15. 17
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java
  16. 112
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java
  17. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionInvalidReason.java
  18. 7
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java
  19. 87
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java
  20. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/VMReferenceTest.java
  21. 7
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java
  22. 4
      util/src/test/java/org/hyperledger/besu/util/SubscribersTest.java

@ -1416,6 +1416,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private BesuCommand configure() throws Exception {
checkPortClash();
checkGoQuorumCompatibilityConfig();
syncMode =
Optional.ofNullable(syncMode)
.orElse(
@ -2168,9 +2169,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
// If no chain id is found in the genesis as it's an optional, we use mainnet
// network id.
try {
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(genesisConfig());
builder.setNetworkId(
genesisConfigFile
getGenesisConfigFile()
.getConfigOptions(genesisConfigOverrides)
.getChainId()
.orElse(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId()));
@ -2218,6 +2218,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return builder.build();
}
private GenesisConfigFile getGenesisConfigFile() {
return GenesisConfigFile.fromConfig(genesisConfig());
}
private String genesisConfig() {
try {
return Resources.toString(genesisFile.toURI().toURL(), UTF_8);
@ -2329,6 +2333,16 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
});
}
private void checkGoQuorumCompatibilityConfig() {
if (genesisFile != null
&& getGenesisConfigFile().getConfigOptions().isQuorum()
&& !minTransactionGasPrice.isZero()) {
throw new ParameterException(
this.commandLine,
"--min-gas-price must be set to zero if GoQuorum compatibility is enabled in the genesis config.");
}
}
@VisibleForTesting
Level getLogLevel() {
return logLevel;

@ -120,6 +120,8 @@ public class BesuCommandTest extends CommandTestAbstract {
.put("config", (new JsonObject()).put("chainId", GENESIS_CONFIG_TEST_CHAINID));
private static final JsonObject GENESIS_INVALID_DATA =
(new JsonObject()).put("config", new JsonObject());
private static final JsonObject GENESIS_QUORUM_INTEROP_ENABLED =
(new JsonObject()).put("config", new JsonObject().put("isquorum", true));
private static final String ENCLAVE_PUBLIC_KEY_PATH =
BesuCommand.class.getResource("/orion_publickey.pub").getPath();
@ -3832,4 +3834,29 @@ public class BesuCommandTest extends CommandTestAbstract {
"Enable the legacy Eth/64 fork id. (default: false)");
assertThat(commandErrorOutput.toString()).isEmpty();
}
@Test
public void quorumInteropEnabledFailsWithoutGasPriceSet() throws IOException {
final Path genesisFile = createFakeGenesisFile(GENESIS_QUORUM_INTEROP_ENABLED);
parseCommand("--genesis-file", genesisFile.toString());
assertThat(commandErrorOutput.toString())
.contains(
"--min-gas-price must be set to zero if GoQuorum compatibility is enabled in the genesis config.");
}
@Test
public void quorumInteropEnabledFailsWithoutGasPriceSetToZero() throws IOException {
final Path genesisFile = createFakeGenesisFile(GENESIS_QUORUM_INTEROP_ENABLED);
parseCommand("--genesis-file", genesisFile.toString(), "--min-gas-price", "1");
assertThat(commandErrorOutput.toString())
.contains(
"--min-gas-price must be set to zero if GoQuorum compatibility is enabled in the genesis config.");
}
@Test
public void quorumInteropEnabledSucceedsWithGasPriceSetToZero() throws IOException {
final Path genesisFile = createFakeGenesisFile(GENESIS_QUORUM_INTEROP_ENABLED);
parseCommand("--genesis-file", genesisFile.toString(), "--min-gas-price", "0");
assertThat(commandErrorOutput.toString()).isEmpty();
}
}

@ -72,7 +72,8 @@ public class CliqueProtocolSchedule {
builder,
eip1559),
privacyParameters,
isMetadataEnabled)
isMetadataEnabled,
config.isQuorum())
.createProtocolSchedule();
}

@ -45,7 +45,8 @@ public class IbftProtocolSchedule {
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(config.getIbft2ConfigOptions(), builder),
privacyParameters,
isMetadataEnabled)
isMetadataEnabled,
config.isQuorum())
.createProtocolSchedule();
}

@ -46,7 +46,8 @@ public class IbftProtocolSchedule {
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder),
privacyParameters,
isMetadataEnabled)
isMetadataEnabled,
config.isQuorum())
.createProtocolSchedule();
}

@ -55,6 +55,8 @@ public class JsonRpcErrorConverter {
return JsonRpcError.ETH_SEND_TX_ALREADY_KNOWN;
case TRANSACTION_REPLACEMENT_UNDERPRICED:
return JsonRpcError.ETH_SEND_TX_REPLACEMENT_UNDERPRICED;
case GAS_PRICE_MUST_BE_ZERO:
return JsonRpcError.GAS_PRICE_MUST_BE_ZERO;
default:
return JsonRpcError.INVALID_PARAMS;
}

@ -61,6 +61,7 @@ public enum JsonRpcError {
REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED(-32000, "ChainId not supported"),
TX_FEECAP_EXCEEDED(-32000, "Transaction fee cap exceeded"),
REVERT_ERROR(-32000, "Execution reverted"),
GAS_PRICE_MUST_BE_ZERO(-3200, "gasPrice must be set to zero on a GoQuorum compatible network"),
// Miner failures
COINBASE_NOT_SET(-32010, "Coinbase not set. Unable to start mining without a coinbase"),

@ -73,7 +73,8 @@ public class JsonRpcErrorConverterTest {
{
TransactionInvalidReason.TRANSACTION_REPLACEMENT_UNDERPRICED,
JsonRpcError.ETH_SEND_TX_REPLACEMENT_UNDERPRICED
}
},
{TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO, JsonRpcError.GAS_PRICE_MUST_BE_ZERO}
});
}

@ -176,6 +176,12 @@ public class EthSendRawTransactionTest {
TransactionInvalidReason.TX_FEECAP_EXCEEDED, JsonRpcError.TX_FEECAP_EXCEEDED);
}
@Test
public void transactionWithNonZeroGasWithGoQuorumCompatibilityIsRejected() {
verifyErrorForInvalidTransaction(
TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO, JsonRpcError.GAS_PRICE_MUST_BE_ZERO);
}
private void verifyErrorForInvalidTransaction(
final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) {
when(transactionPool.addLocalTransaction(any(Transaction.class)))

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.blockcreation;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
@ -64,15 +65,17 @@ public class EthHashBlockCreatorTest {
@Test
public void createMainnetBlock1() throws IOException {
final GenesisConfigOptions genesisConfigOptions = GenesisConfigFile.DEFAULT.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
new ProtocolScheduleBuilder(
GenesisConfigFile.DEFAULT.getConfigOptions(),
genesisConfigOptions,
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT,
false)
false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule())
.build();
@ -120,17 +123,19 @@ public class EthHashBlockCreatorTest {
@Test
public void createMainnetBlock1_fixedDifficulty1() {
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
new ProtocolScheduleBuilder(
GenesisConfigFile.fromConfig(
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
genesisConfigOptions,
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT,
false)
false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule())
.build();
@ -173,17 +178,19 @@ public class EthHashBlockCreatorTest {
@Test
public void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() {
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
new ProtocolScheduleBuilder(
GenesisConfigFile.fromConfig(
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
genesisConfigOptions,
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT,
false)
false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule())
.build();
@ -242,17 +249,19 @@ public class EthHashBlockCreatorTest {
@Test
public void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() {
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(
new ProtocolScheduleBuilder(
GenesisConfigFile.fromConfig(
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
genesisConfigOptions,
BigInteger.valueOf(42),
Function.identity(),
PrivacyParameters.DEFAULT,
false)
false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule())
.build();

@ -30,7 +30,8 @@ public class FixedDifficultyProtocolSchedule {
config,
builder -> builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config)),
privacyParameters,
isMetadataEnabled)
isMetadataEnabled,
config.isQuorum())
.createProtocolSchedule();
}

@ -34,8 +34,11 @@ public class ClassicProtocolSpecs {
private static final Wei MAX_BLOCK_REWARD = Wei.fromEth(5);
public static ProtocolSpecBuilder classicRecoveryInitDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return MainnetProtocolSpecs.homesteadDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
return MainnetProtocolSpecs.homesteadDefinition(
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator.createClassicValidator())
.name("ClassicRecoveryInit");
}
@ -43,19 +46,25 @@ public class ClassicProtocolSpecs {
public static ProtocolSpecBuilder tangerineWhistleDefinition(
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit) {
return MainnetProtocolSpecs.homesteadDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
return MainnetProtocolSpecs.homesteadDefinition(
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(TangerineWhistleGasCalculator::new)
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, chainId))
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
.name("ClassicTangerineWhistle");
}
public static ProtocolSpecBuilder dieHardDefinition(
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit) {
return tangerineWhistleDefinition(chainId, OptionalInt.empty(), configStackSizeLimit)
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
return tangerineWhistleDefinition(
chainId, OptionalInt.empty(), configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(DieHardGasCalculator::new)
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_PAUSED)
.name("DieHard");
@ -65,8 +74,10 @@ public class ClassicProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final OptionalLong ecip1017EraRounds) {
return dieHardDefinition(chainId, contractSizeLimit, configStackSizeLimit)
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
return dieHardDefinition(
chainId, contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.blockReward(MAX_BLOCK_REWARD)
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_DELAYED)
.blockProcessorBuilder(
@ -90,11 +101,19 @@ public class ClassicProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final OptionalLong ecip1017EraRounds) {
return gothamDefinition(chainId, contractSizeLimit, configStackSizeLimit, ecip1017EraRounds)
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
return gothamDefinition(
chainId,
contractSizeLimit,
configStackSizeLimit,
ecip1017EraRounds,
quorumCompatibilityMode)
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_REMOVED)
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, chainId))
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
.name("DefuseDifficultyBomb");
}
@ -103,12 +122,17 @@ public class ClassicProtocolSpecs {
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final OptionalLong ecip1017EraRounds) {
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
final int contractSizeLimit =
configContractSizeLimit.orElse(MainnetProtocolSpecs.SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
return gothamDefinition(
chainId, configContractSizeLimit, configStackSizeLimit, ecip1017EraRounds)
chainId,
configContractSizeLimit,
configStackSizeLimit,
ecip1017EraRounds,
quorumCompatibilityMode)
.evmBuilder(MainnetEvmRegistries::byzantium)
.gasCalculator(SpuriousDragonGasCalculator::new)
.skipZeroBlockRewards(true)
@ -152,13 +176,15 @@ public class ClassicProtocolSpecs {
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final OptionalLong ecip1017EraRounds) {
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
return atlantisDefinition(
chainId,
configContractSizeLimit,
configStackSizeLimit,
enableRevertReason,
ecip1017EraRounds)
ecip1017EraRounds,
quorumCompatibilityMode)
.evmBuilder(MainnetEvmRegistries::constantinople)
.gasCalculator(ConstantinopleFixGasCalculator::new)
.evmBuilder(gasCalculator -> MainnetEvmRegistries.constantinople(gasCalculator))
@ -171,13 +197,15 @@ public class ClassicProtocolSpecs {
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final OptionalLong ecip1017EraRounds) {
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
return aghartaDefinition(
chainId,
configContractSizeLimit,
configStackSizeLimit,
enableRevertReason,
ecip1017EraRounds)
ecip1017EraRounds,
quorumCompatibilityMode)
.gasCalculator(IstanbulGasCalculator::new)
.evmBuilder(
gasCalculator ->
@ -191,13 +219,15 @@ public class ClassicProtocolSpecs {
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final OptionalLong ecip1017EraRounds) {
final OptionalLong ecip1017EraRounds,
final boolean quorumCompatibilityMode) {
return phoenixDefinition(
chainId,
configContractSizeLimit,
configStackSizeLimit,
enableRevertReason,
ecip1017EraRounds)
ecip1017EraRounds,
quorumCompatibilityMode)
.blockHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createBlockHeaderValidator(
block -> EthHash.epoch(block, EthHash.EPOCH_LENGTH * 2)))

@ -50,7 +50,12 @@ public class MainnetProtocolSchedule {
return FixedDifficultyProtocolSchedule.create(config, privacyParameters, isMetadataEnabled);
}
return new ProtocolScheduleBuilder(
config, DEFAULT_CHAIN_ID, Function.identity(), privacyParameters, isMetadataEnabled)
config,
DEFAULT_CHAIN_ID,
Function.identity(),
privacyParameters,
isMetadataEnabled,
config.isQuorum())
.createProtocolSchedule();
}

@ -79,7 +79,9 @@ public abstract class MainnetProtocolSpecs {
private MainnetProtocolSpecs() {}
public static ProtocolSpecBuilder frontierDefinition(
final OptionalInt configContractSizeLimit, final OptionalInt configStackSizeLimit) {
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
return new ProtocolSpecBuilder()
@ -97,7 +99,8 @@ public abstract class MainnetProtocolSpecs {
0))
.transactionValidatorBuilder(
gasCalculator ->
new MainnetTransactionValidator(gasCalculator, false, Optional.empty()))
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), quorumCompatibilityMode))
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,
@ -144,9 +147,12 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder homesteadDefinition(
final OptionalInt configContractSizeLimit, final OptionalInt configStackSizeLimit) {
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
return frontierDefinition(configContractSizeLimit, configStackSizeLimit)
return frontierDefinition(
configContractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(HomesteadGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::homestead)
.contractCreationProcessorBuilder(
@ -158,14 +164,18 @@ public abstract class MainnetProtocolSpecs {
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
0))
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, Optional.empty()))
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, Optional.empty(), quorumCompatibilityMode))
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
.name("Homestead");
}
public static ProtocolSpecBuilder daoRecoveryInitDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator.createDaoValidator())
.blockProcessorBuilder(
(transactionProcessor,
@ -186,15 +196,20 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder daoRecoveryTransitionDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return daoRecoveryInitDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
return daoRecoveryInitDefinition(
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.blockProcessorBuilder(MainnetBlockProcessor::new)
.name("DaoRecoveryTransition");
}
public static ProtocolSpecBuilder tangerineWhistleDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(TangerineWhistleGasCalculator::new)
.name("TangerineWhistle");
}
@ -202,12 +217,14 @@ public abstract class MainnetProtocolSpecs {
public static ProtocolSpecBuilder spuriousDragonDefinition(
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit) {
final OptionalInt configStackSizeLimit,
final boolean quorumCompatibilityMode) {
final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
return tangerineWhistleDefinition(OptionalInt.empty(), configStackSizeLimit)
return tangerineWhistleDefinition(
OptionalInt.empty(), configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(SpuriousDragonGasCalculator::new)
.skipZeroBlockRewards(true)
.messageCallProcessorBuilder(
@ -226,7 +243,9 @@ public abstract class MainnetProtocolSpecs {
1,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, chainId))
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator, true, chainId, quorumCompatibilityMode))
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,
@ -249,9 +268,11 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final boolean enableRevertReason,
final boolean quorumCompatibilityMode) {
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
return spuriousDragonDefinition(chainId, contractSizeLimit, configStackSizeLimit)
return spuriousDragonDefinition(
chainId, contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode)
.gasCalculator(ByzantiumGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::byzantium)
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
@ -284,8 +305,14 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
return byzantiumDefinition(chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
final boolean enableRevertReason,
final boolean quorumCompatibilityMode) {
return byzantiumDefinition(
chainId,
contractSizeLimit,
configStackSizeLimit,
enableRevertReason,
quorumCompatibilityMode)
.difficultyCalculator(MainnetDifficultyCalculators.CONSTANTINOPLE)
.gasCalculator(ConstantinopleGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::constantinople)
@ -297,9 +324,14 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final boolean enableRevertReason,
final boolean quorumCompatibilityMode) {
return constantinopleDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
chainId,
contractSizeLimit,
configStackSizeLimit,
enableRevertReason,
quorumCompatibilityMode)
.gasCalculator(ConstantinopleFixGasCalculator::new)
.name("ConstantinopleFix");
}
@ -308,11 +340,16 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final boolean enableRevertReason,
final boolean quorumCompatibilityMode) {
final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
return constantinopleFixDefinition(
chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason)
chainId,
configContractSizeLimit,
configStackSizeLimit,
enableRevertReason,
quorumCompatibilityMode)
.gasCalculator(IstanbulGasCalculator::new)
.evmBuilder(
gasCalculator ->
@ -334,8 +371,14 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
return istanbulDefinition(chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
final boolean enableRevertReason,
final boolean quorumCompatibilityMode) {
return istanbulDefinition(
chainId,
contractSizeLimit,
configStackSizeLimit,
enableRevertReason,
quorumCompatibilityMode)
.difficultyCalculator(MainnetDifficultyCalculators.MUIR_GLACIER)
.name("MuirGlacier");
}
@ -344,12 +387,17 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final boolean enableRevertReason,
final boolean quorumCompatibilityMode) {
if (!ExperimentalEIPs.berlinEnabled) {
throw new RuntimeException("Berlin feature flag must be enabled --Xberlin-enabled");
}
return muirGlacierDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
chainId,
contractSizeLimit,
configStackSizeLimit,
enableRevertReason,
quorumCompatibilityMode)
.gasCalculator(BerlinGasCalculator::new)
.evmBuilder(
gasCalculator ->
@ -365,12 +413,17 @@ public abstract class MainnetProtocolSpecs {
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final GenesisConfigOptions genesisConfigOptions) {
final GenesisConfigOptions genesisConfigOptions,
final boolean quorumCompatibilityMode) {
ExperimentalEIPs.eip1559MustBeEnabled();
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
final EIP1559 eip1559 = new EIP1559(genesisConfigOptions.getEIP1559BlockNumber().orElse(0));
return muirGlacierDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
chainId,
contractSizeLimit,
configStackSizeLimit,
enableRevertReason,
quorumCompatibilityMode)
.transactionValidatorBuilder(
gasCalculator ->
new MainnetTransactionValidator(
@ -379,7 +432,8 @@ public abstract class MainnetProtocolSpecs {
true,
chainId,
Optional.of(eip1559),
AcceptedTransactionTypes.FEE_MARKET_TRANSITIONAL_TRANSACTIONS))
AcceptedTransactionTypes.FEE_MARKET_TRANSITIONAL_TRANSACTIONS,
genesisConfigOptions.isQuorum()))
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,

@ -48,18 +48,21 @@ public class MainnetTransactionValidator {
private Optional<TransactionFilter> transactionFilter = Optional.empty();
private final Optional<EIP1559> maybeEip1559;
private final AcceptedTransactionTypes acceptedTransactionTypes;
private final boolean goQuorumCompatibilityMode;
public MainnetTransactionValidator(
final GasCalculator gasCalculator,
final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId) {
final Optional<BigInteger> chainId,
final boolean goQuorumCompatibilityMode) {
this(
gasCalculator,
Optional.empty(),
checkSignatureMalleability,
chainId,
Optional.empty(),
AcceptedTransactionTypes.FRONTIER_TRANSACTIONS);
AcceptedTransactionTypes.FRONTIER_TRANSACTIONS,
goQuorumCompatibilityMode);
}
public MainnetTransactionValidator(
@ -68,13 +71,15 @@ public class MainnetTransactionValidator {
final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId,
final Optional<EIP1559> maybeEip1559,
final AcceptedTransactionTypes acceptedTransactionTypes) {
final AcceptedTransactionTypes acceptedTransactionTypes,
final boolean goQuorumCompatibilityMode) {
this.gasCalculator = gasCalculator;
this.transactionPriceCalculator = transactionPriceCalculator;
this.disallowSignatureMalleability = checkSignatureMalleability;
this.chainId = chainId;
this.maybeEip1559 = maybeEip1559;
this.acceptedTransactionTypes = acceptedTransactionTypes;
this.goQuorumCompatibilityMode = goQuorumCompatibilityMode;
}
/**
@ -94,6 +99,12 @@ public class MainnetTransactionValidator {
return signatureResult;
}
if (goQuorumCompatibilityMode && !transaction.getGasPrice().isZero()) {
return ValidationResult.invalid(
TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO,
"gasPrice must be set to zero on a GoQuorum compatible network");
}
if (ExperimentalEIPs.eip1559Enabled && maybeEip1559.isPresent()) {
final EIP1559 eip1559 = maybeEip1559.get();
if (!eip1559.isValidFormat(transaction, acceptedTransactionTypes)) {

@ -38,27 +38,37 @@ public class ProtocolScheduleBuilder {
private final PrivacyParameters privacyParameters;
private final boolean isMetadataEnabled;
private final BadBlockManager badBlockManager = new BadBlockManager();
private final boolean quorumCompatibilityMode;
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final BigInteger defaultChainId,
final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isMetadataEnabled) {
final boolean isMetadataEnabled,
final boolean quorumCompatibilityMode) {
this(
config,
Optional.of(defaultChainId),
protocolSpecAdapter,
privacyParameters,
isMetadataEnabled);
isMetadataEnabled,
quorumCompatibilityMode);
}
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isMetadataEnabled) {
this(config, Optional.empty(), protocolSpecAdapter, privacyParameters, isMetadataEnabled);
final boolean isMetadataEnabled,
final boolean quorumCompatibilityMode) {
this(
config,
Optional.empty(),
protocolSpecAdapter,
privacyParameters,
isMetadataEnabled,
quorumCompatibilityMode);
}
private ProtocolScheduleBuilder(
@ -66,12 +76,14 @@ public class ProtocolScheduleBuilder {
final Optional<BigInteger> defaultChainId,
final Function<ProtocolSpecBuilder, ProtocolSpecBuilder> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isMetadataEnabled) {
final boolean isMetadataEnabled,
final boolean quorumCompatibilityMode) {
this.config = config;
this.defaultChainId = defaultChainId;
this.protocolSpecAdapter = protocolSpecAdapter;
this.privacyParameters = privacyParameters;
this.isMetadataEnabled = isMetadataEnabled;
this.quorumCompatibilityMode = quorumCompatibilityMode;
}
public ProtocolSchedule createProtocolSchedule() {
@ -85,12 +97,12 @@ public class ProtocolScheduleBuilder {
protocolSchedule,
OptionalLong.of(0),
MainnetProtocolSpecs.frontierDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getHomesteadBlockNumber(),
MainnetProtocolSpecs.homesteadDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), quorumCompatibilityMode));
config
.getDaoForkBlock()
@ -102,12 +114,16 @@ public class ProtocolScheduleBuilder {
protocolSchedule,
OptionalLong.of(daoBlockNumber),
MainnetProtocolSpecs.daoRecoveryInitDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(),
config.getEvmStackSize(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
OptionalLong.of(daoBlockNumber + 1),
MainnetProtocolSpecs.daoRecoveryTransitionDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(),
config.getEvmStackSize(),
quorumCompatibilityMode));
// Return to the previous protocol spec after the dao fork has completed.
protocolSchedule.putMilestone(daoBlockNumber + 10, originalProtocolSpec);
@ -117,44 +133,71 @@ public class ProtocolScheduleBuilder {
protocolSchedule,
config.getTangerineWhistleBlockNumber(),
MainnetProtocolSpecs.tangerineWhistleDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getSpuriousDragonBlockNumber(),
MainnetProtocolSpecs.spuriousDragonDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize()));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getByzantiumBlockNumber(),
MainnetProtocolSpecs.byzantiumDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getConstantinopleBlockNumber(),
MainnetProtocolSpecs.constantinopleDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getConstantinopleFixBlockNumber(),
MainnetProtocolSpecs.constantinopleFixDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getIstanbulBlockNumber(),
MainnetProtocolSpecs.istanbulDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getMuirGlacierBlockNumber(),
MainnetProtocolSpecs.muirGlacierDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
quorumCompatibilityMode));
if (ExperimentalEIPs.berlinEnabled) {
addProtocolSpec(
protocolSchedule,
config.getBerlinBlockNumber(),
MainnetProtocolSpecs.berlinDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), isMetadataEnabled));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
quorumCompatibilityMode));
}
if (ExperimentalEIPs.eip1559Enabled) {
@ -169,7 +212,8 @@ public class ProtocolScheduleBuilder {
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
config));
config,
quorumCompatibilityMode));
}
// specs for classic network
@ -183,7 +227,9 @@ public class ProtocolScheduleBuilder {
protocolSchedule,
OptionalLong.of(classicBlockNumber),
ClassicProtocolSpecs.classicRecoveryInitDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(),
config.getEvmStackSize(),
quorumCompatibilityMode));
protocolSchedule.putMilestone(classicBlockNumber + 1, originalProtocolSpce);
});
@ -191,12 +237,18 @@ public class ProtocolScheduleBuilder {
protocolSchedule,
config.getEcip1015BlockNumber(),
ClassicProtocolSpecs.tangerineWhistleDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize()));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getDieHardBlockNumber(),
ClassicProtocolSpecs.dieHardDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize()));
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getGothamBlockNumber(),
@ -204,7 +256,8 @@ public class ProtocolScheduleBuilder {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
config.getEcip1017EraRounds()));
config.getEcip1017EraRounds(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getDefuseDifficultyBombBlockNumber(),
@ -212,7 +265,8 @@ public class ProtocolScheduleBuilder {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
config.getEcip1017EraRounds()));
config.getEcip1017EraRounds(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getAtlantisBlockNumber(),
@ -221,7 +275,8 @@ public class ProtocolScheduleBuilder {
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
config.getEcip1017EraRounds()));
config.getEcip1017EraRounds(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getAghartaBlockNumber(),
@ -230,7 +285,8 @@ public class ProtocolScheduleBuilder {
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
config.getEcip1017EraRounds()));
config.getEcip1017EraRounds(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getPhoenixBlockNumber(),
@ -239,7 +295,8 @@ public class ProtocolScheduleBuilder {
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
config.getEcip1017EraRounds()));
config.getEcip1017EraRounds(),
quorumCompatibilityMode));
addProtocolSpec(
protocolSchedule,
config.getThanosBlockNumber(),
@ -248,7 +305,8 @@ public class ProtocolScheduleBuilder {
config.getContractSizeLimit(),
config.getEvmStackSize(),
isMetadataEnabled,
config.getEcip1017EraRounds()));
config.getEcip1017EraRounds(),
quorumCompatibilityMode));
LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones());
return protocolSchedule;

@ -42,5 +42,7 @@ public enum TransactionInvalidReason {
TX_FEECAP_EXCEEDED,
PRIVATE_VALUE_NOT_ZERO,
PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE,
INTERNAL_ERROR;
INTERNAL_ERROR,
// Quroum Compatibility Invalid Reasons
GAS_PRICE_MUST_BE_ZERO
}

@ -43,11 +43,11 @@ public class ExecutionContextTestFixture {
private final ProtocolSchedule protocolSchedule;
private final ProtocolContext protocolContext;
private static final GenesisConfigFile genesisConfigFile = GenesisConfigFile.mainnet();
private ExecutionContextTestFixture(
final ProtocolSchedule protocolSchedule, final KeyValueStorage keyValueStorage) {
final GenesisState genesisState =
GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule);
final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
this.genesis = genesisState.getBlock();
this.keyValueStorage = keyValueStorage;
this.blockchain =
@ -118,7 +118,8 @@ public class ExecutionContextTestFixture {
BigInteger.valueOf(42),
Function.identity(),
new PrivacyParameters(),
false)
false,
genesisConfigFile.getConfigOptions().isQuorum())
.createProtocolSchedule();
}
if (keyValueStorage == null) {

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.mainnet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
@ -60,6 +61,8 @@ public class MainnetTransactionValidatorTest {
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
private final boolean defaultGoQuorumCompatibilityMode = false;
@After
public void reset() {
ExperimentalEIPs.eip1559Enabled = ExperimentalEIPs.EIP1559_ENABLED_DEFAULT_VALUE;
@ -68,7 +71,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture()
.gasLimit(10)
@ -84,7 +88,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenTransactionHasChainIdAndValidatorDoesNot() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
assertThat(validator.validate(basicTransaction, Optional.empty()))
.isEqualTo(
ValidationResult.invalid(
@ -94,7 +99,11 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenTransactionHasIncorrectChainId() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.valueOf(2)));
new MainnetTransactionValidator(
gasCalculator,
false,
Optional.of(BigInteger.valueOf(2)),
defaultGoQuorumCompatibilityMode);
assertThat(validator.validate(basicTransaction, Optional.empty()))
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.WRONG_CHAIN_ID));
}
@ -102,7 +111,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenSenderAccountDoesNotExist() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
assertThat(validator.validateForSender(basicTransaction, null, false))
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE));
}
@ -110,7 +120,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenTransactionNonceBelowAccountNonce() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
final Account account = accountWithNonce(basicTransaction.getNonce() + 1);
assertThat(validator.validateForSender(basicTransaction, account, false))
@ -121,7 +132,8 @@ public class MainnetTransactionValidatorTest {
public void
shouldRejectTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsNotAllowed() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
assertThat(validator.validateForSender(basicTransaction, account, false))
@ -132,7 +144,8 @@ public class MainnetTransactionValidatorTest {
public void
shouldAcceptTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsAllowed() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
assertThat(validator.validateForSender(basicTransaction, account, true))
@ -142,7 +155,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionWhenNonceExceedsMaximumAllowedNonce() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture().nonce(11).createTransaction(senderKeys);
@ -155,7 +169,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void transactionWithNullSenderCanBeValidIfGasPriceAndValueIsZero() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.of(BigInteger.ONE));
new MainnetTransactionValidator(
gasCalculator, false, Optional.of(BigInteger.ONE), defaultGoQuorumCompatibilityMode);
final TransactionTestFixture builder = new TransactionTestFixture();
final KeyPair senderKeyPair = KeyPair.generate();
@ -169,7 +184,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldRejectTransactionIfAccountIsNotPermitted() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter(false));
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), true))
@ -179,7 +195,8 @@ public class MainnetTransactionValidatorTest {
@Test
public void shouldAcceptValidTransactionIfAccountIsPermitted() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter(true));
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), true))
@ -200,7 +217,8 @@ public class MainnetTransactionValidatorTest {
.thenReturn(true);
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter);
final TransactionValidationParams validationParams =
@ -217,7 +235,8 @@ public class MainnetTransactionValidatorTest {
final TransactionFilter transactionFilter = mock(TransactionFilter.class);
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty());
new MainnetTransactionValidator(
gasCalculator, false, Optional.empty(), defaultGoQuorumCompatibilityMode);
validator.setTransactionFilter(transactionFilter);
final TransactionValidationParams validationParams =
@ -246,7 +265,8 @@ public class MainnetTransactionValidatorTest {
false,
Optional.empty(),
Optional.of(eip1559),
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS);
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS,
defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture()
.gasLimit(21000)
@ -269,7 +289,8 @@ public class MainnetTransactionValidatorTest {
false,
Optional.empty(),
Optional.of(eip1559),
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS);
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS,
defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture()
.gasPremium(Optional.of(Wei.of(1)))
@ -293,7 +314,8 @@ public class MainnetTransactionValidatorTest {
false,
Optional.empty(),
Optional.empty(),
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS);
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS,
defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture()
.gasPremium(Optional.of(Wei.of(1)))
@ -317,7 +339,8 @@ public class MainnetTransactionValidatorTest {
false,
Optional.empty(),
Optional.of(eip1559),
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS);
AcceptedTransactionTypes.FEE_MARKET_TRANSACTIONS,
defaultGoQuorumCompatibilityMode);
final Transaction transaction =
new TransactionTestFixture()
.gasPremium(Optional.of(Wei.of(1)))
@ -332,6 +355,36 @@ public class MainnetTransactionValidatorTest {
ExperimentalEIPs.eip1559Enabled = false;
}
@Test
public void goQuorumCompatibilityModeRejectNonZeroGasPrice() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty(), true);
final Transaction transaction =
new TransactionTestFixture()
.gasPrice(Wei.ONE)
.chainId(Optional.empty())
.createTransaction(senderKeys);
assertThat(validator.validate(transaction, Optional.empty()).isValid()).isFalse();
assertThat(validator.validate(transaction, Optional.empty()).getInvalidReason())
.isEqualTo(GAS_PRICE_MUST_BE_ZERO);
}
@Test
public void goQuorumCompatibilityModeSuccessZeroGasPrice() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(gasCalculator, false, Optional.empty(), true);
final Transaction transaction =
new TransactionTestFixture()
.gasPrice(Wei.ZERO)
.chainId(Optional.empty())
.createTransaction(senderKeys);
when(gasCalculator.transactionIntrinsicGasCost(transaction)).thenReturn(Gas.of(50));
assertThat(validator.validate(transaction, Optional.empty()).isValid()).isTrue();
}
private Account accountWithNonce(final long nonce) {
return account(basicTransaction.getUpfrontCost(), nonce);
}

@ -98,7 +98,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
final EnvironmentInformation execEnv = spec.getExec();
final ProtocolSpec protocolSpec =
MainnetProtocolSpecs.frontierDefinition(OptionalInt.empty(), OptionalInt.empty())
MainnetProtocolSpecs.frontierDefinition(OptionalInt.empty(), OptionalInt.empty(), false)
.privacyParameters(PrivacyParameters.DEFAULT)
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(CHAIN_ID))
.badBlocksManager(new BadBlockManager())

@ -80,7 +80,12 @@ public class ReferenceTestProtocolSchedules {
private static ProtocolSchedule createSchedule(final GenesisConfigOptions options) {
return new ProtocolScheduleBuilder(
options, CHAIN_ID, Function.identity(), PrivacyParameters.DEFAULT, false)
options,
CHAIN_ID,
Function.identity(),
PrivacyParameters.DEFAULT,
false,
options.isQuorum())
.createProtocolSchedule();
}

@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verifyNoInteractions;
import org.junit.Test;
@ -46,7 +46,7 @@ public class SubscribersTest {
assertThat(subscribers.getSubscriberCount()).isEqualTo(1);
subscribers.forEach(Runnable::run);
verifyZeroInteractions(subscriber1);
verifyNoInteractions(subscriber1);
verify(subscriber2).run();
}

Loading…
Cancel
Save