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 { private BesuCommand configure() throws Exception {
checkPortClash(); checkPortClash();
checkGoQuorumCompatibilityConfig();
syncMode = syncMode =
Optional.ofNullable(syncMode) Optional.ofNullable(syncMode)
.orElse( .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 // If no chain id is found in the genesis as it's an optional, we use mainnet
// network id. // network id.
try { try {
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(genesisConfig());
builder.setNetworkId( builder.setNetworkId(
genesisConfigFile getGenesisConfigFile()
.getConfigOptions(genesisConfigOverrides) .getConfigOptions(genesisConfigOverrides)
.getChainId() .getChainId()
.orElse(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId())); .orElse(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId()));
@ -2218,6 +2218,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return builder.build(); return builder.build();
} }
private GenesisConfigFile getGenesisConfigFile() {
return GenesisConfigFile.fromConfig(genesisConfig());
}
private String genesisConfig() { private String genesisConfig() {
try { try {
return Resources.toString(genesisFile.toURI().toURL(), UTF_8); 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 @VisibleForTesting
Level getLogLevel() { Level getLogLevel() {
return logLevel; return logLevel;

@ -120,6 +120,8 @@ public class BesuCommandTest extends CommandTestAbstract {
.put("config", (new JsonObject()).put("chainId", GENESIS_CONFIG_TEST_CHAINID)); .put("config", (new JsonObject()).put("chainId", GENESIS_CONFIG_TEST_CHAINID));
private static final JsonObject GENESIS_INVALID_DATA = private static final JsonObject GENESIS_INVALID_DATA =
(new JsonObject()).put("config", new JsonObject()); (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 = private static final String ENCLAVE_PUBLIC_KEY_PATH =
BesuCommand.class.getResource("/orion_publickey.pub").getPath(); 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)"); "Enable the legacy Eth/64 fork id. (default: false)");
assertThat(commandErrorOutput.toString()).isEmpty(); 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, builder,
eip1559), eip1559),
privacyParameters, privacyParameters,
isMetadataEnabled) isMetadataEnabled,
config.isQuorum())
.createProtocolSchedule(); .createProtocolSchedule();
} }

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

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

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

@ -61,6 +61,7 @@ public enum JsonRpcError {
REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED(-32000, "ChainId not supported"), REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED(-32000, "ChainId not supported"),
TX_FEECAP_EXCEEDED(-32000, "Transaction fee cap exceeded"), TX_FEECAP_EXCEEDED(-32000, "Transaction fee cap exceeded"),
REVERT_ERROR(-32000, "Execution reverted"), REVERT_ERROR(-32000, "Execution reverted"),
GAS_PRICE_MUST_BE_ZERO(-3200, "gasPrice must be set to zero on a GoQuorum compatible network"),
// Miner failures // Miner failures
COINBASE_NOT_SET(-32010, "Coinbase not set. Unable to start mining without a coinbase"), 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, TransactionInvalidReason.TRANSACTION_REPLACEMENT_UNDERPRICED,
JsonRpcError.ETH_SEND_TX_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); 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( private void verifyErrorForInvalidTransaction(
final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) { final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) {
when(transactionPool.addLocalTransaction(any(Transaction.class))) 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 static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.config.GenesisConfigFile; 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.Address;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
@ -64,15 +65,17 @@ public class EthHashBlockCreatorTest {
@Test @Test
public void createMainnetBlock1() throws IOException { public void createMainnetBlock1() throws IOException {
final GenesisConfigOptions genesisConfigOptions = GenesisConfigFile.DEFAULT.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture = final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder() ExecutionContextTestFixture.builder()
.protocolSchedule( .protocolSchedule(
new ProtocolScheduleBuilder( new ProtocolScheduleBuilder(
GenesisConfigFile.DEFAULT.getConfigOptions(), genesisConfigOptions,
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
PrivacyParameters.DEFAULT, PrivacyParameters.DEFAULT,
false) false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
@ -120,17 +123,19 @@ public class EthHashBlockCreatorTest {
@Test @Test
public void createMainnetBlock1_fixedDifficulty1() { public void createMainnetBlock1_fixedDifficulty1() {
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture = final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder() ExecutionContextTestFixture.builder()
.protocolSchedule( .protocolSchedule(
new ProtocolScheduleBuilder( new ProtocolScheduleBuilder(
GenesisConfigFile.fromConfig( genesisConfigOptions,
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
PrivacyParameters.DEFAULT, PrivacyParameters.DEFAULT,
false) false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
@ -173,17 +178,19 @@ public class EthHashBlockCreatorTest {
@Test @Test
public void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { public void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() {
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture = final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder() ExecutionContextTestFixture.builder()
.protocolSchedule( .protocolSchedule(
new ProtocolScheduleBuilder( new ProtocolScheduleBuilder(
GenesisConfigFile.fromConfig( genesisConfigOptions,
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
PrivacyParameters.DEFAULT, PrivacyParameters.DEFAULT,
false) false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();
@ -242,17 +249,19 @@ public class EthHashBlockCreatorTest {
@Test @Test
public void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { public void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() {
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig("{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions();
final ExecutionContextTestFixture executionContextTestFixture = final ExecutionContextTestFixture executionContextTestFixture =
ExecutionContextTestFixture.builder() ExecutionContextTestFixture.builder()
.protocolSchedule( .protocolSchedule(
new ProtocolScheduleBuilder( new ProtocolScheduleBuilder(
GenesisConfigFile.fromConfig( genesisConfigOptions,
"{\"config\": {\"ethash\": {\"fixeddifficulty\":1}}}")
.getConfigOptions(),
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
PrivacyParameters.DEFAULT, PrivacyParameters.DEFAULT,
false) false,
genesisConfigOptions.isQuorum())
.createProtocolSchedule()) .createProtocolSchedule())
.build(); .build();

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

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

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

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

@ -48,18 +48,21 @@ public class MainnetTransactionValidator {
private Optional<TransactionFilter> transactionFilter = Optional.empty(); private Optional<TransactionFilter> transactionFilter = Optional.empty();
private final Optional<EIP1559> maybeEip1559; private final Optional<EIP1559> maybeEip1559;
private final AcceptedTransactionTypes acceptedTransactionTypes; private final AcceptedTransactionTypes acceptedTransactionTypes;
private final boolean goQuorumCompatibilityMode;
public MainnetTransactionValidator( public MainnetTransactionValidator(
final GasCalculator gasCalculator, final GasCalculator gasCalculator,
final boolean checkSignatureMalleability, final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId) { final Optional<BigInteger> chainId,
final boolean goQuorumCompatibilityMode) {
this( this(
gasCalculator, gasCalculator,
Optional.empty(), Optional.empty(),
checkSignatureMalleability, checkSignatureMalleability,
chainId, chainId,
Optional.empty(), Optional.empty(),
AcceptedTransactionTypes.FRONTIER_TRANSACTIONS); AcceptedTransactionTypes.FRONTIER_TRANSACTIONS,
goQuorumCompatibilityMode);
} }
public MainnetTransactionValidator( public MainnetTransactionValidator(
@ -68,13 +71,15 @@ public class MainnetTransactionValidator {
final boolean checkSignatureMalleability, final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId, final Optional<BigInteger> chainId,
final Optional<EIP1559> maybeEip1559, final Optional<EIP1559> maybeEip1559,
final AcceptedTransactionTypes acceptedTransactionTypes) { final AcceptedTransactionTypes acceptedTransactionTypes,
final boolean goQuorumCompatibilityMode) {
this.gasCalculator = gasCalculator; this.gasCalculator = gasCalculator;
this.transactionPriceCalculator = transactionPriceCalculator; this.transactionPriceCalculator = transactionPriceCalculator;
this.disallowSignatureMalleability = checkSignatureMalleability; this.disallowSignatureMalleability = checkSignatureMalleability;
this.chainId = chainId; this.chainId = chainId;
this.maybeEip1559 = maybeEip1559; this.maybeEip1559 = maybeEip1559;
this.acceptedTransactionTypes = acceptedTransactionTypes; this.acceptedTransactionTypes = acceptedTransactionTypes;
this.goQuorumCompatibilityMode = goQuorumCompatibilityMode;
} }
/** /**
@ -94,6 +99,12 @@ public class MainnetTransactionValidator {
return signatureResult; 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()) { if (ExperimentalEIPs.eip1559Enabled && maybeEip1559.isPresent()) {
final EIP1559 eip1559 = maybeEip1559.get(); final EIP1559 eip1559 = maybeEip1559.get();
if (!eip1559.isValidFormat(transaction, acceptedTransactionTypes)) { if (!eip1559.isValidFormat(transaction, acceptedTransactionTypes)) {

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

@ -42,5 +42,7 @@ public enum TransactionInvalidReason {
TX_FEECAP_EXCEEDED, TX_FEECAP_EXCEEDED,
PRIVATE_VALUE_NOT_ZERO, PRIVATE_VALUE_NOT_ZERO,
PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE, 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 ProtocolSchedule protocolSchedule;
private final ProtocolContext protocolContext; private final ProtocolContext protocolContext;
private static final GenesisConfigFile genesisConfigFile = GenesisConfigFile.mainnet();
private ExecutionContextTestFixture( private ExecutionContextTestFixture(
final ProtocolSchedule protocolSchedule, final KeyValueStorage keyValueStorage) { final ProtocolSchedule protocolSchedule, final KeyValueStorage keyValueStorage) {
final GenesisState genesisState = final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule);
this.genesis = genesisState.getBlock(); this.genesis = genesisState.getBlock();
this.keyValueStorage = keyValueStorage; this.keyValueStorage = keyValueStorage;
this.blockchain = this.blockchain =
@ -118,7 +118,8 @@ public class ExecutionContextTestFixture {
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
new PrivacyParameters(), new PrivacyParameters(),
false) false,
genesisConfigFile.getConfigOptions().isQuorum())
.createProtocolSchedule(); .createProtocolSchedule();
} }
if (keyValueStorage == null) { if (keyValueStorage == null) {

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

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

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

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

Loading…
Cancel
Save