mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-09 23:38:08 -05:00
[23.4] Remove GoQuorum privacy (#5303)
* removed separate decoding logic * run non-mainnet ATs to make sure * remove goQuorum flag from everywhere * remove GOQUORUM api group * remove GoQuorum enclave, privacy params, RPCs and other related config * removed Goquorum related error codes, rpcMethod codes, privateBloom * removed v from transaction * removed private GoQuorum storage provider --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
## 23.4-RC
|
||||
|
||||
### Breaking Changes
|
||||
- Removed IBFT1 feature [#5302](https://github.com/hyperledger/besu/pull/5302)
|
||||
- Remove IBFT 1.0 feature (deprecated in 23.1.0-beta) [#5302](https://github.com/hyperledger/besu/pull/5302)
|
||||
- Remove GoQuorum-compatible privacy feature (deprecated in 23.1.0-beta) [#5303](https://github.com/hyperledger/besu/pull/5303)
|
||||
|
||||
### Additions and Improvements
|
||||
- Update most dependencies to latest version [#5269](https://github.com/hyperledger/besu/pull/5269)
|
||||
|
||||
@@ -936,9 +936,7 @@ public class RunnerBuilder {
|
||||
|
||||
Optional<GraphQLHttpService> graphQLHttpService = Optional.empty();
|
||||
if (graphQLConfiguration.isEnabled()) {
|
||||
final GraphQLDataFetchers fetchers =
|
||||
new GraphQLDataFetchers(
|
||||
supportedCapabilities, privacyParameters.getGoQuorumPrivacyParameters());
|
||||
final GraphQLDataFetchers fetchers = new GraphQLDataFetchers(supportedCapabilities);
|
||||
final Map<GraphQLContextType, Object> graphQlContextMap = new ConcurrentHashMap<>();
|
||||
graphQlContextMap.putIfAbsent(GraphQLContextType.BLOCKCHAIN_QUERIES, blockchainQueries);
|
||||
graphQlContextMap.putIfAbsent(GraphQLContextType.PROTOCOL_SCHEDULE, protocolSchedule);
|
||||
|
||||
@@ -89,7 +89,6 @@ import org.hyperledger.besu.cli.util.VersionProvider;
|
||||
import org.hyperledger.besu.config.CheckpointConfigOptions;
|
||||
import org.hyperledger.besu.config.GenesisConfigFile;
|
||||
import org.hyperledger.besu.config.GenesisConfigOptions;
|
||||
import org.hyperledger.besu.config.GoQuorumOptions;
|
||||
import org.hyperledger.besu.config.MergeConfigOptions;
|
||||
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfiguration;
|
||||
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider;
|
||||
@@ -106,7 +105,6 @@ import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.enclave.EnclaveFactory;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.GasLimitCalculator;
|
||||
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
|
||||
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
|
||||
@@ -122,7 +120,6 @@ import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider;
|
||||
import org.hyperledger.besu.ethereum.api.tls.TlsClientAuthConfiguration;
|
||||
import org.hyperledger.besu.ethereum.api.tls.TlsConfiguration;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.SyncMode;
|
||||
@@ -141,15 +138,10 @@ import org.hyperledger.besu.ethereum.permissioning.PermissioningConfigurationBui
|
||||
import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration;
|
||||
import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DefaultWorldStateArchive;
|
||||
import org.hyperledger.besu.ethereum.worldstate.PrunerConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
|
||||
import org.hyperledger.besu.evm.precompile.AbstractAltBnPrecompiledContract;
|
||||
import org.hyperledger.besu.evm.precompile.BigIntegerModularExponentiationPrecompiledContract;
|
||||
import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract;
|
||||
@@ -213,7 +205,6 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Clock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -235,7 +226,6 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.io.Resources;
|
||||
import io.vertx.core.Vertx;
|
||||
import io.vertx.core.VertxOptions;
|
||||
@@ -2211,44 +2201,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
vertx.isNativeTransportEnabled() && enabled, actualPath, rpcIpcApis);
|
||||
}
|
||||
|
||||
private GoQuorumPrivacyParameters configureGoQuorumPrivacy(
|
||||
final KeyValueStorageProvider storageProvider) {
|
||||
return new GoQuorumPrivacyParameters(
|
||||
createGoQuorumEnclave(),
|
||||
readEnclaveKey(),
|
||||
storageProvider.createGoQuorumPrivateStorage(),
|
||||
createPrivateWorldStateArchive(storageProvider));
|
||||
}
|
||||
|
||||
private GoQuorumEnclave createGoQuorumEnclave() {
|
||||
final EnclaveFactory enclaveFactory = new EnclaveFactory(Vertx.vertx());
|
||||
if (privacyOptionGroup.privacyKeyStoreFile != null) {
|
||||
return enclaveFactory.createGoQuorumEnclave(
|
||||
privacyOptionGroup.privacyUrl,
|
||||
privacyOptionGroup.privacyKeyStoreFile,
|
||||
privacyOptionGroup.privacyKeyStorePasswordFile,
|
||||
privacyOptionGroup.privacyTlsKnownEnclaveFile);
|
||||
} else {
|
||||
return enclaveFactory.createGoQuorumEnclave(privacyOptionGroup.privacyUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private String readEnclaveKey() {
|
||||
final String key;
|
||||
try {
|
||||
key = Files.asCharSource(privacyOptionGroup.privacyPublicKeyFile, UTF_8).read();
|
||||
} catch (final Exception e) {
|
||||
throw new ParameterException(
|
||||
this.commandLine,
|
||||
"--privacy-public-key-file must be set if isQuorum is set in the genesis file.",
|
||||
e);
|
||||
}
|
||||
// throws exception if invalid base 64
|
||||
Base64.getDecoder().decode(key);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
private void ensureAllNodesAreInAllowlist(
|
||||
final Collection<EnodeURL> enodeAddresses,
|
||||
final LocalPermissioningConfiguration permissioningConfiguration) {
|
||||
@@ -2314,7 +2266,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
.nodeKey(new NodeKey(securityModule()))
|
||||
.metricsSystem(metricsSystem.get())
|
||||
.messagePermissioningProviders(permissioningService.getMessagePermissioningProviders())
|
||||
.privacyParameters(privacyParameters(storageProvider))
|
||||
.privacyParameters(privacyParameters())
|
||||
.pkiBlockCreationConfiguration(maybePkiBlockCreationConfiguration())
|
||||
.clock(Clock.systemUTC())
|
||||
.isRevertReasonEnabled(isRevertReasonEnabled)
|
||||
@@ -2807,7 +2759,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
|| permissionsOptionGroup.permissionsAccountsContractEnabled;
|
||||
}
|
||||
|
||||
private PrivacyParameters privacyParameters(final KeyValueStorageProvider storageProvider) {
|
||||
private PrivacyParameters privacyParameters() {
|
||||
|
||||
CommandLineUtils.checkOptionDependencies(
|
||||
logger,
|
||||
@@ -2836,7 +2788,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
}
|
||||
if (isGoQuorumCompatibilityMode) {
|
||||
throw new ParameterException(
|
||||
commandLine, String.format("%s %s", "GoQuorum mode", errorSuffix));
|
||||
commandLine, String.format("GoQuorum privacy is no longer supported in Besu"));
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(privacyOptionGroup.isPrivacyMultiTenancyEnabled)
|
||||
@@ -2898,20 +2850,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
privacyOptionGroup.privacyTlsKnownEnclaveFile);
|
||||
}
|
||||
privacyParametersBuilder.setEnclaveFactory(new EnclaveFactory(vertx));
|
||||
} else if (isGoQuorumCompatibilityMode) {
|
||||
privacyParametersBuilder.setGoQuorumPrivacyParameters(
|
||||
Optional.of(configureGoQuorumPrivacy(storageProvider)));
|
||||
}
|
||||
|
||||
if (Boolean.FALSE.equals(privacyOptionGroup.isPrivacyEnabled) && anyPrivacyApiEnabled()) {
|
||||
logger.warn("Privacy is disabled. Cannot use EEA/PRIV API methods when not using Privacy.");
|
||||
}
|
||||
|
||||
if (!isGoQuorumCompatibilityMode
|
||||
&& (jsonRPCHttpOptionGroup.rpcHttpApis.contains(RpcApis.GOQUORUM.name())
|
||||
|| jsonRPCWebsocketOptionGroup.rpcWsApis.contains(RpcApis.GOQUORUM.name()))) {
|
||||
logger.warn("Cannot use GOQUORUM API methods when not in GoQuorum mode.");
|
||||
}
|
||||
privacyParametersBuilder.setPrivacyService(privacyPluginService);
|
||||
final PrivacyParameters privacyParameters = privacyParametersBuilder.build();
|
||||
|
||||
@@ -2924,14 +2868,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
return privacyParameters;
|
||||
}
|
||||
|
||||
private WorldStateArchive createPrivateWorldStateArchive(final StorageProvider storageProvider) {
|
||||
final WorldStateStorage privateWorldStateStorage =
|
||||
storageProvider.createPrivateWorldStateStorage();
|
||||
final WorldStatePreimageStorage preimageStorage =
|
||||
storageProvider.createPrivateWorldStatePreimageStorage();
|
||||
return new DefaultWorldStateArchive(privateWorldStateStorage, preimageStorage);
|
||||
}
|
||||
|
||||
private boolean anyPrivacyApiEnabled() {
|
||||
return jsonRPCHttpOptionGroup.rpcHttpApis.contains(RpcApis.EEA.name())
|
||||
|| jsonRPCWebsocketOptionGroup.rpcWsApis.contains(RpcApis.EEA.name())
|
||||
@@ -2968,7 +2904,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
"No KeyValueStorageFactory found for key: " + name)))
|
||||
.withCommonConfiguration(pluginCommonConfiguration)
|
||||
.withMetricsSystem(getMetricsSystem())
|
||||
.isGoQuorumCompatibilityMode(isGoQuorumCompatibilityMode.booleanValue())
|
||||
.build();
|
||||
}
|
||||
return this.keyValueStorageProvider;
|
||||
@@ -3508,8 +3443,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
/** Enables Go Quorum Compatibility mode. Visible for testing. */
|
||||
@VisibleForTesting
|
||||
protected void enableGoQuorumCompatibilityMode() {
|
||||
// this static flag is read by the RLP decoder
|
||||
GoQuorumOptions.setGoQuorumCompatibilityMode(true);
|
||||
// this static flag is still used for GoQuorum permissioning compatibility
|
||||
isGoQuorumCompatibilityMode = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4545,13 +4545,7 @@ public class BesuCommandTest extends CommandTestAbstract {
|
||||
"--privacy-enabled", "--genesis-file", genesisFile.toString(), "--min-gas-price", "0");
|
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("GoQuorum mode cannot be enabled with privacy.");
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
verify(mockLogger, atLeast(1))
|
||||
.warn(
|
||||
DEPRECATION_WARNING_MSG,
|
||||
"isQuorum mode in genesis file (GoQuorum-compatible privacy mode)",
|
||||
"--privacy-enabled");
|
||||
.contains("GoQuorum privacy is no longer supported in Besu");
|
||||
}
|
||||
|
||||
@Rule public TemporaryFolder testFolder = new TemporaryFolder();
|
||||
@@ -5142,52 +5136,6 @@ public class BesuCommandTest extends CommandTestAbstract {
|
||||
"--min-gas-price must be set to zero if isQuorum mode is enabled in the genesis file.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quorumInteropEnabledSucceedsWithGasPriceSetToZero() throws IOException {
|
||||
final Path genesisFile =
|
||||
createFakeGenesisFile(VALID_GENESIS_QUORUM_INTEROP_ENABLED_WITH_CHAINID);
|
||||
parseCommand(
|
||||
"--genesis-file",
|
||||
genesisFile.toString(),
|
||||
"--min-gas-price",
|
||||
"0",
|
||||
"--privacy-public-key-file",
|
||||
ENCLAVE_PUBLIC_KEY_PATH);
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quorumInteropEnabledFailsIfEnclaveKeyFileDoesNotExist() throws IOException {
|
||||
final Path genesisFile =
|
||||
createFakeGenesisFile(VALID_GENESIS_QUORUM_INTEROP_ENABLED_WITH_CHAINID);
|
||||
parseCommand(
|
||||
"--genesis-file",
|
||||
genesisFile.toString(),
|
||||
"--min-gas-price",
|
||||
"0",
|
||||
"--privacy-public-key-file",
|
||||
"ThisFileDoesNotExist");
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("--privacy-public-key-file must be set if isQuorum is set in the genesis file.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quorumInteropEnabledFailsIfEnclaveKeyFileIsNotSet() throws IOException {
|
||||
final Path genesisFile =
|
||||
createFakeGenesisFile(VALID_GENESIS_QUORUM_INTEROP_ENABLED_WITH_CHAINID);
|
||||
parseCommand("--genesis-file", genesisFile.toString(), "--min-gas-price", "0");
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("--privacy-public-key-file must be set if isQuorum is set in the genesis file.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quorumInteropEnabledFailsWithMainnetDefaultNetwork() throws IOException {
|
||||
final Path genesisFile = createFakeGenesisFile(INVALID_GENESIS_QUORUM_INTEROP_ENABLED_MAINNET);
|
||||
parseCommand("--genesis-file", genesisFile.toString(), "--min-gas-price", "0");
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("isQuorum mode cannot be used on Mainnet.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quorumInteropEnabledFailsWithMainnetChainId() throws IOException {
|
||||
final Path genesisFile =
|
||||
|
||||
@@ -495,14 +495,6 @@ public abstract class CommandTestAbstract {
|
||||
return vertx;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableGoQuorumCompatibilityMode() {
|
||||
// We do *not* set the static GoQuorumOptions for test runs as
|
||||
// these are only allowed to be set once during the program
|
||||
// runtime.
|
||||
isGoQuorumCompatibilityMode = true;
|
||||
}
|
||||
|
||||
public CommandSpec getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.config;
|
||||
|
||||
/**
|
||||
* Flag to determine whether we are processing in GoQuorum mode. Note that this mode is incompatible
|
||||
* with MainNet.
|
||||
*/
|
||||
public class GoQuorumOptions {
|
||||
private static final boolean GOQUORUM_COMPATIBILITY_MODE_DEFAULT_VALUE = false;
|
||||
|
||||
private static Boolean goQuorumCompatibilityMode;
|
||||
|
||||
/**
|
||||
* Sets go quorum compatibility mode.
|
||||
*
|
||||
* @param goQuorumCompatibilityMode the go quorum compatibility mode
|
||||
*/
|
||||
public static void setGoQuorumCompatibilityMode(final boolean goQuorumCompatibilityMode) {
|
||||
if (GoQuorumOptions.goQuorumCompatibilityMode == null) {
|
||||
GoQuorumOptions.goQuorumCompatibilityMode = goQuorumCompatibilityMode;
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"goQuorumCompatibilityMode can not be changed after having been assigned");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets go quorum compatibility mode.
|
||||
*
|
||||
* @return the go quorum compatibility mode
|
||||
*/
|
||||
public static boolean getGoQuorumCompatibilityMode() {
|
||||
if (goQuorumCompatibilityMode == null) {
|
||||
// If the quorum mode has never been set, we default it
|
||||
// here. This allows running individual unit tests that
|
||||
// query the quorum mode without having to include a
|
||||
// setGoQuorumCompatibilityMode call in their setup
|
||||
// procedure. For production use, this case is not
|
||||
// triggered as we set the quorum mode very early during
|
||||
// startup.
|
||||
goQuorumCompatibilityMode = GOQUORUM_COMPATIBILITY_MODE_DEFAULT_VALUE;
|
||||
}
|
||||
return goQuorumCompatibilityMode;
|
||||
}
|
||||
}
|
||||
@@ -79,11 +79,9 @@ public class CliqueProtocolSchedule {
|
||||
epochManager,
|
||||
cliqueConfig.getBlockPeriodSeconds(),
|
||||
localNodeAddress,
|
||||
builder,
|
||||
privacyParameters.getGoQuorumPrivacyParameters().isPresent())),
|
||||
builder)),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
config.isQuorum(),
|
||||
evmConfiguration)
|
||||
.createProtocolSchedule();
|
||||
}
|
||||
@@ -110,8 +108,7 @@ public class CliqueProtocolSchedule {
|
||||
final EpochManager epochManager,
|
||||
final long secondsBetweenBlocks,
|
||||
final Address localNodeAddress,
|
||||
final ProtocolSpecBuilder specBuilder,
|
||||
final boolean goQuorumMode) {
|
||||
final ProtocolSpecBuilder specBuilder) {
|
||||
|
||||
return specBuilder
|
||||
.blockHeaderValidatorBuilder(
|
||||
@@ -121,7 +118,7 @@ public class CliqueProtocolSchedule {
|
||||
baseFeeMarket ->
|
||||
getBlockHeaderValidator(epochManager, secondsBetweenBlocks, baseFeeMarket))
|
||||
.blockBodyValidatorBuilder(MainnetBlockBodyValidator::new)
|
||||
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder(goQuorumMode))
|
||||
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder())
|
||||
.blockImporterBuilder(MainnetBlockImporter::new)
|
||||
.difficultyCalculator(new CliqueDifficultyCalculator(localNodeAddress))
|
||||
.blockReward(Wei.ZERO)
|
||||
|
||||
@@ -66,9 +66,7 @@ public abstract class BaseBftProtocolScheduleBuilder {
|
||||
forkSpec ->
|
||||
specMap.put(
|
||||
forkSpec.getBlock(),
|
||||
builder ->
|
||||
applyBftChanges(
|
||||
builder, forkSpec.getValue(), config.isQuorum(), bftExtraDataCodec)));
|
||||
builder -> applyBftChanges(builder, forkSpec.getValue(), bftExtraDataCodec)));
|
||||
|
||||
final ProtocolSpecAdapters specAdapters = new ProtocolSpecAdapters(specMap);
|
||||
|
||||
@@ -80,7 +78,6 @@ public abstract class BaseBftProtocolScheduleBuilder {
|
||||
specAdapters,
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
config.isQuorum(),
|
||||
evmConfiguration)
|
||||
.createProtocolSchedule();
|
||||
return new BftProtocolSchedule(mutableProtocolSchedule);
|
||||
@@ -99,7 +96,6 @@ public abstract class BaseBftProtocolScheduleBuilder {
|
||||
private ProtocolSpecBuilder applyBftChanges(
|
||||
final ProtocolSpecBuilder builder,
|
||||
final BftConfigOptions configOptions,
|
||||
final boolean goQuorumMode,
|
||||
final BftExtraDataCodec bftExtraDataCodec) {
|
||||
if (configOptions.getEpochLength() <= 0) {
|
||||
throw new IllegalArgumentException("Epoch length in config must be greater than zero");
|
||||
@@ -114,7 +110,7 @@ public abstract class BaseBftProtocolScheduleBuilder {
|
||||
.ommerHeaderValidatorBuilder(
|
||||
feeMarket -> createBlockHeaderRuleset(configOptions, feeMarket))
|
||||
.blockBodyValidatorBuilder(MainnetBlockBodyValidator::new)
|
||||
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder(goQuorumMode))
|
||||
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder())
|
||||
.blockImporterBuilder(MainnetBlockImporter::new)
|
||||
.difficultyCalculator((time, parent, protocolContext) -> BigInteger.ONE)
|
||||
.skipZeroBlockRewards(true)
|
||||
|
||||
@@ -149,7 +149,6 @@ public class CombinedProtocolScheduleFactoryTest {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
new PrivacyParameters(),
|
||||
false,
|
||||
false,
|
||||
EvmConfiguration.DEFAULT);
|
||||
|
||||
return protocolScheduleBuilder.createProtocolSchedule();
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.consensus.ibft;
|
||||
|
||||
import org.hyperledger.besu.consensus.common.BlockInterface;
|
||||
import org.hyperledger.besu.consensus.common.EpochManager;
|
||||
import org.hyperledger.besu.consensus.common.PoaContext;
|
||||
import org.hyperledger.besu.consensus.common.validator.ValidatorProvider;
|
||||
import org.hyperledger.besu.ethereum.ConsensusContext;
|
||||
|
||||
/** Holds the BFT specific mutable state. */
|
||||
public class IbftLegacyContext implements PoaContext {
|
||||
|
||||
private final ValidatorProvider validatorProvider;
|
||||
private final EpochManager epochManager;
|
||||
private final BlockInterface blockInterface;
|
||||
|
||||
/**
|
||||
* Instantiates a new Ibft legacy context.
|
||||
*
|
||||
* @param validatorProvider the validator provider
|
||||
* @param epochManager the epoch manager
|
||||
* @param blockInterface the block interface
|
||||
*/
|
||||
public IbftLegacyContext(
|
||||
final ValidatorProvider validatorProvider,
|
||||
final EpochManager epochManager,
|
||||
final BlockInterface blockInterface) {
|
||||
this.validatorProvider = validatorProvider;
|
||||
this.epochManager = epochManager;
|
||||
this.blockInterface = blockInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets validator provider.
|
||||
*
|
||||
* @return the validator provider
|
||||
*/
|
||||
public ValidatorProvider getValidatorProvider() {
|
||||
return validatorProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets epoch manager.
|
||||
*
|
||||
* @return the epoch manager
|
||||
*/
|
||||
public EpochManager getEpochManager() {
|
||||
return epochManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockInterface getBlockInterface() {
|
||||
return blockInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C extends ConsensusContext> C as(final Class<C> klass) {
|
||||
return klass.cast(this);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ package org.hyperledger.besu.consensus.merge;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockProcessor;
|
||||
@@ -24,7 +23,6 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/** The Merge block processor. */
|
||||
public class MergeBlockProcessor extends MainnetBlockProcessor {
|
||||
@@ -38,7 +36,6 @@ public class MergeBlockProcessor extends MainnetBlockProcessor {
|
||||
* @param blockReward the block reward
|
||||
* @param miningBeneficiaryCalculator the mining beneficiary calculator
|
||||
* @param skipZeroBlockRewards the skip zero block rewards
|
||||
* @param goQuorumPrivacyParameters the go quorum privacy parameters
|
||||
* @param protocolSchedule the header based protocol scheduler
|
||||
*/
|
||||
public MergeBlockProcessor(
|
||||
@@ -47,7 +44,6 @@ public class MergeBlockProcessor extends MainnetBlockProcessor {
|
||||
final Wei blockReward,
|
||||
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
|
||||
final boolean skipZeroBlockRewards,
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters,
|
||||
final HeaderBasedProtocolSchedule protocolSchedule) {
|
||||
super(
|
||||
transactionProcessor,
|
||||
@@ -55,7 +51,6 @@ public class MergeBlockProcessor extends MainnetBlockProcessor {
|
||||
blockReward,
|
||||
miningBeneficiaryCalculator,
|
||||
skipZeroBlockRewards,
|
||||
goQuorumPrivacyParameters,
|
||||
protocolSchedule);
|
||||
this.mergeContext = PostMergeContext.get();
|
||||
}
|
||||
|
||||
@@ -71,7 +71,6 @@ public class MergeProtocolSchedule {
|
||||
specBuilder, config.getChainId())),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
config.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule();
|
||||
}
|
||||
@@ -96,7 +95,6 @@ public class MergeProtocolSchedule {
|
||||
MergeProtocolSchedule::applyMergeSpecificModificationsForShanghai),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
config.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createTimestampSchedule();
|
||||
}
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.enclave;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse;
|
||||
import org.hyperledger.besu.enclave.types.SendResponse;
|
||||
import org.hyperledger.besu.enclave.types.StoreRawResponse;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
import io.vertx.core.Vertx;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
||||
public class GoQuorumEnclaveTest {
|
||||
|
||||
private static final byte[] PAYLOAD = Base64.getDecoder().decode("EAAAAAAA");
|
||||
private static final String MOCK_KEY = "iOCzoGo5kwtZU0J41Z9xnGXHN6ZNukIa9MspvHtu3Jk=";
|
||||
private static final String KEY =
|
||||
"tQEmN0d/xXJZs5OMgl8QVBIyYxu1XubAKehsSYbcOjbxai+QJQpEOs6ghrYAZizLtnM4EJdMyVeVrxO3cA9JJA==";
|
||||
private static GoQuorumEnclave enclave;
|
||||
|
||||
private RequestTransmitter vertxTransmitter;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
enclave = createGoQuorumEnclaveWithMockRequestTransmitter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upCheck() {
|
||||
when(vertxTransmitter.get(
|
||||
any(), any(), ArgumentMatchers.contains("/upcheck"), any(), anyBoolean()))
|
||||
.thenReturn("I'm up!");
|
||||
|
||||
assertThat(enclave.upCheck()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void receiveThrowsWhenPayloadDoesNotExist() {
|
||||
when(vertxTransmitter.get(
|
||||
any(), any(), ArgumentMatchers.contains("/transaction"), any(), anyBoolean()))
|
||||
.thenThrow(
|
||||
new EnclaveClientException(404, "Message with hash " + MOCK_KEY + " was not found"));
|
||||
|
||||
assertThatThrownBy(() -> enclave.receive(MOCK_KEY))
|
||||
.isInstanceOf(EnclaveClientException.class)
|
||||
.hasMessageContaining("Message with hash " + MOCK_KEY + " was not found");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendAndReceive() {
|
||||
when(vertxTransmitter.post(any(), any(), any(), any())).thenReturn(new SendResponse(KEY));
|
||||
when(vertxTransmitter.get(
|
||||
any(), any(), ArgumentMatchers.contains("/transaction"), any(), anyBoolean()))
|
||||
.thenReturn(new GoQuorumReceiveResponse(PAYLOAD, 0, null, null));
|
||||
|
||||
final List<String> publicKeys = Arrays.asList("/+UuD63zItL1EbjxkKUljMgG8Z1w0AJ8pNOR4iq2yQc=");
|
||||
|
||||
final SendResponse sr = enclave.send(PAYLOAD, publicKeys.get(0), publicKeys);
|
||||
assertThat(sr.getKey()).isEqualTo(KEY);
|
||||
|
||||
final GoQuorumReceiveResponse rr = enclave.receive(sr.getKey());
|
||||
assertThat(rr).isNotNull();
|
||||
assertThat(rr.getPayload()).isEqualTo(PAYLOAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendSignedTransaction() {
|
||||
when(vertxTransmitter.post(any(), any(), ArgumentMatchers.contains("/sendsignedtx"), any()))
|
||||
.thenReturn(new SendResponse(KEY));
|
||||
|
||||
final List<String> publicKeys = Arrays.asList("/+UuD63zItL1EbjxkKUljMgG8Z1w0AJ8pNOR4iq2yQc=");
|
||||
|
||||
final SendResponse sr = enclave.sendSignedTransaction(PAYLOAD, publicKeys);
|
||||
assertThat(sr.getKey()).isEqualTo(KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void storeRawTransaction() {
|
||||
when(vertxTransmitter.post(any(), any(), ArgumentMatchers.contains("/storeraw"), any()))
|
||||
.thenReturn(new StoreRawResponse(KEY));
|
||||
|
||||
final StoreRawResponse sr =
|
||||
enclave.storeRaw(
|
||||
"tQEmN0d/xXJZs5OMgl8QVBIyYxu1XubAKehsSYbcOjbxai+QJQpEOs6ghrYAZizLtnM4EJdMyVeVrxO3cA9JJA==");
|
||||
assertThat(sr.getKey()).isEqualTo(KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upcheckReturnsFalseIfNoResponseReceived() throws URISyntaxException {
|
||||
final Vertx vertx = Vertx.vertx();
|
||||
final EnclaveFactory factory = new EnclaveFactory(vertx);
|
||||
assertThat(factory.createGoQuorumEnclave(new URI("http://8.8.8.8:65535")).upCheck()).isFalse();
|
||||
}
|
||||
|
||||
private GoQuorumEnclave createGoQuorumEnclaveWithMockRequestTransmitter() {
|
||||
vertxTransmitter = mock(RequestTransmitter.class);
|
||||
|
||||
return new GoQuorumEnclave(vertxTransmitter);
|
||||
}
|
||||
}
|
||||
@@ -85,46 +85,6 @@ public class EnclaveFactory {
|
||||
return new Enclave(vertxTransmitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create GoQuorum enclave.
|
||||
*
|
||||
* @param enclaveUri the enclave uri
|
||||
* @return the GoQuorum enclave
|
||||
*/
|
||||
public GoQuorumEnclave createGoQuorumEnclave(final URI enclaveUri) {
|
||||
final HttpClientOptions clientOptions = createNonTlsClientOptions(enclaveUri);
|
||||
|
||||
final RequestTransmitter vertxTransmitter =
|
||||
new VertxRequestTransmitter(vertx.createHttpClient(clientOptions));
|
||||
|
||||
return new GoQuorumEnclave(vertxTransmitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create GoQuorum enclave.
|
||||
*
|
||||
* @param enclaveUri the enclave uri
|
||||
* @param privacyKeyStoreFile the privacy key store file
|
||||
* @param privacyKeyStorePasswordFile the privacy key store password file
|
||||
* @param privacyAllowlistFile the privacy allowlist file
|
||||
* @return the go quorum enclave
|
||||
*/
|
||||
public GoQuorumEnclave createGoQuorumEnclave(
|
||||
final URI enclaveUri,
|
||||
final Path privacyKeyStoreFile,
|
||||
final Path privacyKeyStorePasswordFile,
|
||||
final Path privacyAllowlistFile) {
|
||||
|
||||
final HttpClientOptions clientOptions =
|
||||
createTlsClientOptions(
|
||||
enclaveUri, privacyKeyStoreFile, privacyKeyStorePasswordFile, privacyAllowlistFile);
|
||||
|
||||
final RequestTransmitter vertxTransmitter =
|
||||
new VertxRequestTransmitter(vertx.createHttpClient(clientOptions));
|
||||
|
||||
return new GoQuorumEnclave(vertxTransmitter);
|
||||
}
|
||||
|
||||
private HttpClientOptions createNonTlsClientOptions(final URI enclaveUri) {
|
||||
|
||||
if (enclaveUri.getPort() == -1) {
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.enclave;
|
||||
|
||||
import org.hyperledger.besu.enclave.RequestTransmitter.ResponseBodyHandler;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumSendRequest;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumSendSignedRequest;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumStoreRawRequest;
|
||||
import org.hyperledger.besu.enclave.types.SendResponse;
|
||||
import org.hyperledger.besu.enclave.types.StoreRawResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/** The GoQuorum enclave. */
|
||||
public class GoQuorumEnclave {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private static final String JSON = "application/json";
|
||||
|
||||
private final RequestTransmitter requestTransmitter;
|
||||
|
||||
/**
|
||||
* Instantiates a new GoQuorum enclave.
|
||||
*
|
||||
* @param requestTransmitter the request transmitter
|
||||
*/
|
||||
public GoQuorumEnclave(final RequestTransmitter requestTransmitter) {
|
||||
this.requestTransmitter = requestTransmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Up check.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean upCheck() {
|
||||
try {
|
||||
final String upcheckResponse =
|
||||
requestTransmitter.get(null, null, "/upcheck", this::handleRawResponse, false);
|
||||
return upcheckResponse.equals("I'm up!");
|
||||
} catch (final Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send payload.
|
||||
*
|
||||
* @param payload the payload
|
||||
* @param privateFrom the private from
|
||||
* @param privateFor the private for
|
||||
* @return the send response
|
||||
*/
|
||||
public SendResponse send(
|
||||
final byte[] payload, final String privateFrom, final List<String> privateFor) {
|
||||
final GoQuorumSendRequest request = new GoQuorumSendRequest(payload, privateFrom, privateFor);
|
||||
return post(
|
||||
JSON,
|
||||
request,
|
||||
"/send",
|
||||
(statusCode, body) -> handleJsonResponse(statusCode, body, SendResponse.class, 201));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send signed transaction.
|
||||
*
|
||||
* @param txLookupId the tx lookup id
|
||||
* @param privateFor the private for
|
||||
* @return the send response
|
||||
*/
|
||||
public SendResponse sendSignedTransaction(
|
||||
final byte[] txLookupId, final List<String> privateFor) {
|
||||
final GoQuorumSendSignedRequest request = new GoQuorumSendSignedRequest(txLookupId, privateFor);
|
||||
return post(
|
||||
JSON,
|
||||
request,
|
||||
"/sendsignedtx",
|
||||
(statusCode, body) -> handleJsonResponse(statusCode, body, SendResponse.class, 201));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store raw payload.
|
||||
*
|
||||
* @param payload the payload
|
||||
* @return the store raw response
|
||||
*/
|
||||
public StoreRawResponse storeRaw(final String payload) {
|
||||
final GoQuorumStoreRawRequest request = new GoQuorumStoreRawRequest(payload);
|
||||
return post(
|
||||
JSON,
|
||||
request,
|
||||
"/storeraw",
|
||||
(statusCode, body) -> handleJsonResponse(statusCode, body, StoreRawResponse.class, 200));
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive GoQuorum response.
|
||||
*
|
||||
* @param payloadKey the payload key
|
||||
* @return the go quorum receive response
|
||||
*/
|
||||
public GoQuorumReceiveResponse receive(final String payloadKey) {
|
||||
return get(
|
||||
JSON,
|
||||
"/transaction/" + URLEncoder.encode(payloadKey, StandardCharsets.UTF_8),
|
||||
(statusCode, body) ->
|
||||
handleJsonResponse(statusCode, body, GoQuorumReceiveResponse.class, 200));
|
||||
}
|
||||
|
||||
private <T> T post(
|
||||
final String mediaType,
|
||||
final Object content,
|
||||
final String endpoint,
|
||||
final ResponseBodyHandler<T> responseBodyHandler) {
|
||||
final String bodyText;
|
||||
try {
|
||||
bodyText = objectMapper.writeValueAsString(content);
|
||||
} catch (final JsonProcessingException e) {
|
||||
throw new EnclaveClientException(400, "Unable to serialize request.");
|
||||
}
|
||||
return requestTransmitter.post(mediaType, bodyText, endpoint, responseBodyHandler);
|
||||
}
|
||||
|
||||
private <T> T get(
|
||||
final String mediaType,
|
||||
final String endpoint,
|
||||
final ResponseBodyHandler<T> responseBodyHandler) {
|
||||
final T t = requestTransmitter.get(mediaType, null, endpoint, responseBodyHandler, true);
|
||||
return t;
|
||||
}
|
||||
|
||||
private <T> T handleJsonResponse(
|
||||
final int statusCode,
|
||||
final byte[] body,
|
||||
final Class<T> responseType,
|
||||
final int expectedStatusCode) {
|
||||
|
||||
if (isSuccess(statusCode, expectedStatusCode)) {
|
||||
return parseResponse(statusCode, body, responseType);
|
||||
} else if (clientError(statusCode)) {
|
||||
final String utf8EncodedBody = new String(body, StandardCharsets.UTF_8);
|
||||
throw new EnclaveClientException(statusCode, utf8EncodedBody);
|
||||
} else {
|
||||
final String utf8EncodedBody = new String(body, StandardCharsets.UTF_8);
|
||||
throw new EnclaveServerException(statusCode, utf8EncodedBody);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T parseResponse(
|
||||
final int statusCode, final byte[] body, final Class<T> responseType) {
|
||||
try {
|
||||
return objectMapper.readValue(body, responseType);
|
||||
} catch (final IOException e) {
|
||||
final String utf8EncodedBody = new String(body, StandardCharsets.UTF_8);
|
||||
throw new EnclaveClientException(statusCode, utf8EncodedBody);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean clientError(final int statusCode) {
|
||||
return statusCode >= 400 && statusCode < 500;
|
||||
}
|
||||
|
||||
private boolean isSuccess(final int statusCode, final int expectedStatusCode) {
|
||||
return statusCode == expectedStatusCode;
|
||||
}
|
||||
|
||||
private String handleRawResponse(final int statusCode, final byte[] body) {
|
||||
final String bodyText = new String(body, StandardCharsets.UTF_8);
|
||||
if (isSuccess(statusCode, 200)) {
|
||||
return bodyText;
|
||||
}
|
||||
throw new EnclaveClientException(
|
||||
statusCode, String.format("Request failed with %d; body={%s}", statusCode, bodyText));
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.enclave.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/** The GoQuorum receive response. */
|
||||
public class GoQuorumReceiveResponse {
|
||||
|
||||
private final byte[] payload;
|
||||
private final int privacyFlag;
|
||||
private final String affectedContractTransactions[];
|
||||
private final String execHash;
|
||||
|
||||
/**
|
||||
* Instantiates a new GoQuorum receive response.
|
||||
*
|
||||
* @param payload the payload
|
||||
* @param privacyFlag the privacy flag
|
||||
* @param affectedContractTransactions the affected contract transactions
|
||||
* @param execHash the exec hash
|
||||
*/
|
||||
@JsonCreator
|
||||
public GoQuorumReceiveResponse(
|
||||
@JsonProperty(value = "payload") final byte[] payload,
|
||||
@JsonProperty(value = "privacyFlag") final int privacyFlag,
|
||||
@JsonProperty(value = "affectedContractTransactions")
|
||||
final String affectedContractTransactions[],
|
||||
@JsonProperty(value = "execHash") final String execHash) {
|
||||
this.payload = payload;
|
||||
this.privacyFlag = privacyFlag;
|
||||
this.affectedContractTransactions = affectedContractTransactions;
|
||||
this.execHash = execHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get payload.
|
||||
*
|
||||
* @return the byte [ ]
|
||||
*/
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets privacy flag.
|
||||
*
|
||||
* @return the privacy flag
|
||||
*/
|
||||
public int getPrivacyFlag() {
|
||||
return privacyFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get affected contract transactions.
|
||||
*
|
||||
* @return the string [ ]
|
||||
*/
|
||||
public String[] getAffectedContractTransactions() {
|
||||
return affectedContractTransactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets exec hash.
|
||||
*
|
||||
* @return the exec hash
|
||||
*/
|
||||
public String getExecHash() {
|
||||
return execHash;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.enclave.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
/** The GoQuorum send request. */
|
||||
@JsonPropertyOrder({"payload", "from", "to"})
|
||||
public class GoQuorumSendRequest {
|
||||
private final byte[] payload;
|
||||
private final String from;
|
||||
private final List<String> to;
|
||||
|
||||
/**
|
||||
* Instantiates a new Go quorum send request.
|
||||
*
|
||||
* @param payload the payload
|
||||
* @param from the from
|
||||
* @param to the to
|
||||
*/
|
||||
public GoQuorumSendRequest(
|
||||
@JsonProperty(value = "payload") final byte[] payload,
|
||||
@JsonProperty(value = "from") final String from,
|
||||
@JsonProperty(value = "to") final List<String> to) {
|
||||
this.payload = payload;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get payload byte [ ].
|
||||
*
|
||||
* @return the byte [ ]
|
||||
*/
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets from.
|
||||
*
|
||||
* @return the from
|
||||
*/
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets to.
|
||||
*
|
||||
* @return the to
|
||||
*/
|
||||
public List<String> getTo() {
|
||||
return to;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.enclave.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
/** The GoQuorum send signed request. */
|
||||
@JsonPropertyOrder({"hash", "to"})
|
||||
public class GoQuorumSendSignedRequest {
|
||||
private final byte[] hash;
|
||||
private final List<String> to;
|
||||
|
||||
/**
|
||||
* Instantiates a new GoQuorum send signed request.
|
||||
*
|
||||
* @param hash the hash
|
||||
* @param privateFor the private for
|
||||
*/
|
||||
public GoQuorumSendSignedRequest(
|
||||
@JsonProperty(value = "hash") final byte[] hash,
|
||||
@JsonProperty(value = "to") final List<String> privateFor) {
|
||||
this.hash = hash;
|
||||
this.to = privateFor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hash byte [ ].
|
||||
*
|
||||
* @return the byte [ ]
|
||||
*/
|
||||
public byte[] getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets to.
|
||||
*
|
||||
* @return the to
|
||||
*/
|
||||
public List<String> getTo() {
|
||||
return to;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.enclave.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/** The type Go quorum store raw request. */
|
||||
public class GoQuorumStoreRawRequest {
|
||||
private final String payload;
|
||||
|
||||
/**
|
||||
* Instantiates a new Go quorum store raw request.
|
||||
*
|
||||
* @param payload the payload
|
||||
*/
|
||||
public GoQuorumStoreRawRequest(@JsonProperty(value = "payload") final String payload) {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets payload.
|
||||
*
|
||||
* @return the payload
|
||||
*/
|
||||
public String getPayload() {
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.AccountAdapter;
|
||||
import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.EmptyAccountAdapter;
|
||||
import org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter.LogAdapter;
|
||||
@@ -33,7 +32,6 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.api.query.LogsQuery;
|
||||
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.LogWithMetadata;
|
||||
import org.hyperledger.besu.ethereum.core.Synchronizer;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
@@ -63,21 +61,10 @@ import graphql.GraphQLContext;
|
||||
import graphql.schema.DataFetcher;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GraphQLDataFetchers {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GraphQLDataFetchers.class);
|
||||
private final Integer highestEthVersion;
|
||||
private Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters = Optional.empty();
|
||||
|
||||
public GraphQLDataFetchers(
|
||||
final Set<Capability> supportedCapabilities,
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters) {
|
||||
this(supportedCapabilities);
|
||||
this.goQuorumPrivacyParameters = goQuorumPrivacyParameters;
|
||||
}
|
||||
|
||||
public GraphQLDataFetchers(final Set<Capability> supportedCapabilities) {
|
||||
final OptionalInt version =
|
||||
@@ -312,46 +299,6 @@ public class GraphQLDataFetchers {
|
||||
|
||||
private TransactionAdapter getTransactionAdapter(
|
||||
final TransactionWithMetadata transactionWithMetadata) {
|
||||
final Transaction transaction = transactionWithMetadata.getTransaction();
|
||||
final boolean isGoQuorumCompatbilityMode = goQuorumPrivacyParameters.isPresent();
|
||||
final boolean isGoQuorumPrivateTransaction =
|
||||
isGoQuorumCompatbilityMode
|
||||
&& transaction.isGoQuorumPrivateTransaction(isGoQuorumCompatbilityMode);
|
||||
return isGoQuorumPrivateTransaction
|
||||
? updatePrivatePayload(transaction)
|
||||
: new TransactionAdapter(transactionWithMetadata);
|
||||
}
|
||||
|
||||
private TransactionAdapter updatePrivatePayload(final Transaction transaction) {
|
||||
final GoQuorumEnclave enclave = goQuorumPrivacyParameters.get().enclave();
|
||||
Bytes enclavePayload;
|
||||
|
||||
try {
|
||||
// Retrieve the payload from the enclave
|
||||
enclavePayload =
|
||||
Bytes.wrap(enclave.receive(transaction.getPayload().toBase64String()).getPayload());
|
||||
} catch (final Exception ex) {
|
||||
LOG.debug("An error occurred while retrieving the GoQuorum transaction payload: ", ex);
|
||||
enclavePayload = Bytes.EMPTY;
|
||||
}
|
||||
|
||||
// Return a new transaction containing the retrieved payload
|
||||
return new TransactionAdapter(
|
||||
new TransactionWithMetadata(
|
||||
new Transaction(
|
||||
transaction.getNonce(),
|
||||
transaction.getGasPrice(),
|
||||
transaction.getMaxPriorityFeePerGas(),
|
||||
transaction.getMaxFeePerGas(),
|
||||
transaction.getMaxFeePerDataGas(),
|
||||
transaction.getGasLimit(),
|
||||
transaction.getTo(),
|
||||
transaction.getValue(),
|
||||
transaction.getSignature(),
|
||||
enclavePayload,
|
||||
transaction.getSender(),
|
||||
transaction.getChainId(),
|
||||
Optional.ofNullable(transaction.getV()),
|
||||
transaction.getVersionedHashes())));
|
||||
return new TransactionAdapter(transactionWithMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
|
||||
|
||||
import org.hyperledger.besu.config.GoQuorumOptions;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
@@ -209,20 +208,6 @@ public class TransactionAdapter extends AdapterBase {
|
||||
return results;
|
||||
}
|
||||
|
||||
public boolean getIsPrivate() {
|
||||
return transactionWithMetadata
|
||||
.getTransaction()
|
||||
.isGoQuorumPrivateTransaction(GoQuorumOptions.getGoQuorumCompatibilityMode());
|
||||
}
|
||||
|
||||
public Optional<Bytes> getPrivateInputData() {
|
||||
final Transaction transaction = transactionWithMetadata.getTransaction();
|
||||
if (transaction.isGoQuorumPrivateTransaction(GoQuorumOptions.getGoQuorumCompatibilityMode())) {
|
||||
return Optional.ofNullable(transaction.getPayload());
|
||||
}
|
||||
return Optional.of(Bytes.EMPTY);
|
||||
}
|
||||
|
||||
public List<AccessListEntryAdapter> getAccessList() {
|
||||
return transactionWithMetadata
|
||||
.getTransaction()
|
||||
|
||||
@@ -59,10 +59,6 @@ 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;
|
||||
case ETHER_VALUE_NOT_SUPPORTED:
|
||||
return JsonRpcError.ETHER_VALUE_NOT_SUPPORTED;
|
||||
case NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER:
|
||||
return JsonRpcError.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER;
|
||||
case LOWER_NONCE_INVALID_TRANSACTION_EXISTS:
|
||||
|
||||
@@ -32,7 +32,6 @@ public enum RpcApis {
|
||||
TXPOOL,
|
||||
TRACE,
|
||||
PLUGINS,
|
||||
GOQUORUM,
|
||||
CLIQUE,
|
||||
IBFT,
|
||||
ENGINE,
|
||||
|
||||
@@ -59,8 +59,6 @@ public enum RpcMethod {
|
||||
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1("engine_getPayloadBodiesByRangeV1"),
|
||||
ENGINE_EXCHANGE_CAPABILITIES("engine_exchangeCapabilities"),
|
||||
|
||||
GOQUORUM_ETH_GET_QUORUM_PAYLOAD("eth_getQuorumPayload"),
|
||||
GOQUORUM_STORE_RAW("goquorum_storeRaw"),
|
||||
PRIV_CALL("priv_call"),
|
||||
PRIV_GET_PRIVATE_TRANSACTION("priv_getPrivateTransaction"),
|
||||
PRIV_GET_TRANSACTION_COUNT("priv_getTransactionCount"),
|
||||
|
||||
@@ -14,39 +14,25 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStateUtil.getPrivateWorldStateAtBlock;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameterOrBlockHash;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
public class EthGetCode extends AbstractBlockParameterOrBlockHashMethod {
|
||||
final Optional<PrivacyParameters> privacyParameters;
|
||||
|
||||
public EthGetCode(
|
||||
final BlockchainQueries blockchainQueries,
|
||||
final Optional<PrivacyParameters> privacyParameters) {
|
||||
public EthGetCode(final BlockchainQueries blockchainQueries) {
|
||||
super(blockchainQueries);
|
||||
this.privacyParameters = privacyParameters;
|
||||
}
|
||||
|
||||
public EthGetCode(
|
||||
final Supplier<BlockchainQueries> blockchainQueries,
|
||||
final Optional<PrivacyParameters> privacyParameters) {
|
||||
public EthGetCode(final Supplier<BlockchainQueries> blockchainQueries) {
|
||||
super(blockchainQueries);
|
||||
this.privacyParameters = privacyParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,21 +49,6 @@ public class EthGetCode extends AbstractBlockParameterOrBlockHashMethod {
|
||||
@Override
|
||||
protected String resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) {
|
||||
final Address address = request.getRequiredParameter(0, Address.class);
|
||||
if (privacyParameters.isPresent()
|
||||
&& privacyParameters.get().getGoQuorumPrivacyParameters().isPresent()) {
|
||||
// get from private state if we can
|
||||
final Optional<BlockHeader> blockHeader =
|
||||
blockchainQueries.get().getBlockHeaderByHash(blockHash);
|
||||
if (blockHeader.isPresent()) {
|
||||
final MutableWorldState privateState =
|
||||
getPrivateWorldStateAtBlock(
|
||||
privacyParameters.get().getGoQuorumPrivacyParameters(), blockHeader.get());
|
||||
final Account privAccount = privateState.get(address);
|
||||
if (privAccount != null) {
|
||||
return privAccount.getCode().toHexString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return getBlockchainQueries().getCode(address, blockHash).map(Bytes::toString).orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.privacyUserId;
|
||||
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.util.InvalidConfigurationException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -29,9 +28,7 @@ public interface PrivacyIdProvider {
|
||||
String getPrivacyUserId(Optional<User> user);
|
||||
|
||||
static PrivacyIdProvider build(final PrivacyParameters privacyParameters) {
|
||||
if (privacyParameters.getGoQuorumPrivacyParameters().isPresent()) {
|
||||
return goQuorumPrivacyUserIdProvider(privacyParameters);
|
||||
} else if (privacyParameters.isMultiTenancyEnabled()) {
|
||||
if (privacyParameters.isMultiTenancyEnabled()) {
|
||||
return multiTenancyPrivacyUserIdProvider();
|
||||
}
|
||||
return defaultPrivacyUserIdProvider(privacyParameters);
|
||||
@@ -48,14 +45,4 @@ public interface PrivacyIdProvider {
|
||||
final PrivacyParameters privacyParameters) {
|
||||
return user -> privacyParameters.getPrivacyUserId();
|
||||
}
|
||||
|
||||
private static PrivacyIdProvider goQuorumPrivacyUserIdProvider(
|
||||
final PrivacyParameters privacyParameters) {
|
||||
return user ->
|
||||
privacyParameters
|
||||
.getGoQuorumPrivacyParameters()
|
||||
.orElseThrow(
|
||||
() -> new InvalidConfigurationException("GoQuorumPrivacyParameters not set"))
|
||||
.enclaveKey();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
|
||||
|
||||
import org.hyperledger.besu.enclave.EnclaveClientException;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoQuorumEthGetQuorumPayload implements JsonRpcMethod {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GoQuorumEthGetQuorumPayload.class);
|
||||
|
||||
private final GoQuorumEnclave enclave;
|
||||
|
||||
public GoQuorumEthGetQuorumPayload(final GoQuorumEnclave enclave) {
|
||||
this.enclave = enclave;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return RpcMethod.GOQUORUM_ETH_GET_QUORUM_PAYLOAD.getMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
|
||||
final String key = requestContext.getRequiredParameter(0, String.class);
|
||||
final Bytes bytes;
|
||||
try {
|
||||
bytes = Bytes.fromHexString(key);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
LOG.debug("Enclave key contains invalid hex character {}", key);
|
||||
return new JsonRpcErrorResponse(
|
||||
requestContext.getRequest().getId(), JsonRpcError.INVALID_PARAMS);
|
||||
}
|
||||
if (bytes.size() != 64) {
|
||||
LOG.debug("Enclave key expected length 64, but length is {}", bytes.size());
|
||||
return new JsonRpcErrorResponse(
|
||||
requestContext.getRequest().getId(), JsonRpcError.INVALID_PARAMS);
|
||||
}
|
||||
|
||||
try {
|
||||
final GoQuorumReceiveResponse receive = enclave.receive(bytes.toBase64String());
|
||||
return new JsonRpcSuccessResponse(
|
||||
requestContext.getRequest().getId(), Bytes.wrap(receive.getPayload()).toHexString());
|
||||
} catch (final EnclaveClientException ex) {
|
||||
if (ex.getStatusCode() == 404) {
|
||||
return new JsonRpcSuccessResponse(
|
||||
requestContext.getRequest().getId(), Bytes.EMPTY.toHexString());
|
||||
} else {
|
||||
LOG.debug("Error retrieving enclave payload: ", ex);
|
||||
return new JsonRpcErrorResponse(
|
||||
requestContext.getRequest().getId(), JsonRpcError.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter.convertEnclaveInvalidReason;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter.convertTransactionInvalidReason;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.DECODE_ERROR;
|
||||
|
||||
import org.hyperledger.besu.config.GoQuorumOptions;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.JsonRpcErrorResponseException;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.privacy.GoQuorumSendRawTxArgs;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPException;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoQuorumSendRawPrivateTransaction implements JsonRpcMethod {
|
||||
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(GoQuorumSendRawPrivateTransaction.class);
|
||||
final TransactionPool transactionPool;
|
||||
private final PrivacyIdProvider privacyIdProvider;
|
||||
private final GoQuorumEnclave enclave;
|
||||
private final boolean goQuorumCompatibilityMode;
|
||||
|
||||
public GoQuorumSendRawPrivateTransaction(
|
||||
final GoQuorumEnclave enclave,
|
||||
final TransactionPool transactionPool,
|
||||
final PrivacyIdProvider privacyIdProvider) {
|
||||
this(
|
||||
enclave,
|
||||
transactionPool,
|
||||
privacyIdProvider,
|
||||
GoQuorumOptions.getGoQuorumCompatibilityMode());
|
||||
}
|
||||
|
||||
public GoQuorumSendRawPrivateTransaction(
|
||||
final GoQuorumEnclave enclave,
|
||||
final TransactionPool transactionPool,
|
||||
final PrivacyIdProvider privacyIdProvider,
|
||||
final boolean goQuorumCompatibilityMode) {
|
||||
this.enclave = enclave;
|
||||
this.transactionPool = transactionPool;
|
||||
this.privacyIdProvider = privacyIdProvider;
|
||||
this.goQuorumCompatibilityMode = goQuorumCompatibilityMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return RpcMethod.ETH_SEND_RAW_PRIVATE_TRANSACTION.getMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
|
||||
final Object id = requestContext.getRequest().getId();
|
||||
final String rawPrivateTransaction = requestContext.getRequiredParameter(0, String.class);
|
||||
|
||||
final GoQuorumSendRawTxArgs rawTxArgs =
|
||||
requestContext.getRequiredParameter(1, GoQuorumSendRawTxArgs.class);
|
||||
|
||||
try {
|
||||
final Transaction transaction =
|
||||
TransactionDecoder.decodeForWire(
|
||||
RLP.input(Bytes.fromHexString(rawPrivateTransaction)), goQuorumCompatibilityMode);
|
||||
|
||||
checkAndHandlePrivateTransaction(transaction, rawTxArgs, requestContext);
|
||||
|
||||
return transactionPool
|
||||
.addLocalTransaction(transaction)
|
||||
.either(
|
||||
() -> new JsonRpcSuccessResponse(id, transaction.getHash().toString()),
|
||||
errorReason -> getJsonRpcErrorResponse(id, errorReason));
|
||||
|
||||
} catch (final JsonRpcErrorResponseException e) {
|
||||
return new JsonRpcErrorResponse(id, e.getJsonRpcError());
|
||||
} catch (final IllegalArgumentException | RLPException e) {
|
||||
LOG.error("Unable to decode private transaction for send", e);
|
||||
return new JsonRpcErrorResponse(id, DECODE_ERROR);
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Unexpected error", e);
|
||||
return new JsonRpcErrorResponse(id, convertEnclaveInvalidReason(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAndHandlePrivateTransaction(
|
||||
final Transaction transaction,
|
||||
final GoQuorumSendRawTxArgs rawTxArgs,
|
||||
final JsonRpcRequestContext requestContext) {
|
||||
// rawTxArgs cannot be null as the call to getRequiredParameter would have failed if it was not
|
||||
// available
|
||||
|
||||
if (rawTxArgs.getPrivateFor() == null) {
|
||||
LOG.error(JsonRpcError.GOQUORUM_NO_PRIVATE_FOR.getMessage());
|
||||
throw new JsonRpcErrorResponseException(JsonRpcError.GOQUORUM_NO_PRIVATE_FOR);
|
||||
}
|
||||
|
||||
if (rawTxArgs.getPrivacyFlag() != 0) {
|
||||
LOG.error(JsonRpcError.GOQUORUM_ONLY_STANDARD_MODE_SUPPORTED.getMessage());
|
||||
throw new JsonRpcErrorResponseException(JsonRpcError.GOQUORUM_ONLY_STANDARD_MODE_SUPPORTED);
|
||||
}
|
||||
|
||||
if (rawTxArgs.getPrivateFrom() != null) {
|
||||
final String privateFrom = rawTxArgs.getPrivateFrom();
|
||||
final String privacyUserId = privacyIdProvider.getPrivacyUserId(requestContext.getUser());
|
||||
if (!privateFrom.equals(privacyUserId)) {
|
||||
LOG.error(JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY.getMessage());
|
||||
throw new JsonRpcErrorResponseException(
|
||||
JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
if (!transaction.getV().equals(BigInteger.valueOf(37))
|
||||
&& !transaction.getV().equals(BigInteger.valueOf(38))) {
|
||||
LOG.error(JsonRpcError.GOQUORUM_V_VALUE.getMessage());
|
||||
throw new JsonRpcErrorResponseException(JsonRpcError.GOQUORUM_V_VALUE);
|
||||
}
|
||||
|
||||
final Bytes txId = transaction.getPayload();
|
||||
if (txId == null || txId.isEmpty()) {
|
||||
throw new JsonRpcErrorResponseException(JsonRpcError.GOQUORUM_LOOKUP_ID_NOT_AVAILABLE);
|
||||
}
|
||||
enclave.sendSignedTransaction(txId.toArray(), rawTxArgs.getPrivateFor());
|
||||
}
|
||||
|
||||
JsonRpcErrorResponse getJsonRpcErrorResponse(
|
||||
final Object id, final TransactionInvalidReason errorReason) {
|
||||
if (errorReason.equals(TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT)) {
|
||||
return new JsonRpcErrorResponse(id, JsonRpcError.PMT_FAILED_INTRINSIC_GAS_EXCEEDS_LIMIT);
|
||||
}
|
||||
return new JsonRpcErrorResponse(id, convertTransactionInvalidReason(errorReason));
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter.convertEnclaveInvalidReason;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.DECODE_ERROR;
|
||||
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.enclave.types.StoreRawResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPException;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoQuorumStoreRawPrivateTransaction implements JsonRpcMethod {
|
||||
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(GoQuorumStoreRawPrivateTransaction.class);
|
||||
private final GoQuorumEnclave enclave;
|
||||
|
||||
public GoQuorumStoreRawPrivateTransaction(final GoQuorumEnclave enclave) {
|
||||
this.enclave = enclave;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return RpcMethod.GOQUORUM_STORE_RAW.getMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
|
||||
final Object id = requestContext.getRequest().getId();
|
||||
final String payload = requestContext.getRequiredParameter(0, String.class);
|
||||
|
||||
try {
|
||||
LOG.debug("sending payload to GoQuorum enclave" + payload);
|
||||
final StoreRawResponse storeRawResponse =
|
||||
enclave.storeRaw(
|
||||
Base64.getEncoder().encodeToString(Bytes.fromHexString(payload).toArray()));
|
||||
final String enclaveLookupId = storeRawResponse.getKey();
|
||||
LOG.debug("retrieved lookupId from GoQuorum enclave " + enclaveLookupId);
|
||||
return new JsonRpcSuccessResponse(id, hexEncodeEnclaveKey(enclaveLookupId));
|
||||
} catch (final IllegalArgumentException | RLPException e) {
|
||||
LOG.error("Unable to decode private transaction for store", e);
|
||||
return new JsonRpcErrorResponse(id, DECODE_ERROR);
|
||||
} catch (final Exception e) {
|
||||
return new JsonRpcErrorResponse(id, convertEnclaveInvalidReason(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private String hexEncodeEnclaveKey(final String enclaveKey) {
|
||||
return Bytes.wrap(Base64.getDecoder().decode(enclaveKey)).toHexString();
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,6 @@ public enum JsonRpcError {
|
||||
REPLAY_PROTECTED_SIGNATURE_REQUIRED(-32000, "ChainId is required"),
|
||||
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"),
|
||||
TRANSACTION_NOT_FOUND(-32000, "Transaction not found"),
|
||||
MAX_PRIORITY_FEE_PER_GAS_EXCEEDS_MAX_FEE_PER_GAS(
|
||||
-32000, "Max priority fee per gas exceeds max fee per gas"),
|
||||
@@ -144,17 +143,8 @@ public enum JsonRpcError {
|
||||
CREATE_PRIVACY_GROUP_ERROR(-50100, "Error creating privacy group"),
|
||||
DECODE_ERROR(-50100, "Unable to decode the private signed raw transaction"),
|
||||
DELETE_PRIVACY_GROUP_ERROR(-50100, "Error deleting privacy group"),
|
||||
ETHER_VALUE_NOT_SUPPORTED(-50100, "ether value is not supported for private transactions"),
|
||||
FIND_PRIVACY_GROUP_ERROR(-50100, "Error finding privacy group"),
|
||||
FIND_FLEXIBLE_PRIVACY_GROUP_ERROR(-50100, "Error finding flexible privacy group"),
|
||||
GOQUORUM_NO_PRIVATE_FOR(
|
||||
-50100, "No privateFor specified in rawTxArgs for GoQuorum raw private transaction."),
|
||||
GOQUORUM_ONLY_STANDARD_MODE_SUPPORTED(
|
||||
-50100,
|
||||
"Invalid private transaction mode defined in rawTxArgs for GoQuorum raw private transaction."),
|
||||
GOQUORUM_LOOKUP_ID_NOT_AVAILABLE(
|
||||
-50100, "No lookup id specified in GoQuorum raw private transaction."),
|
||||
GOQUORUM_V_VALUE(-50100, "Signature v value not 37 or 38 for GoQuorum private transaction."),
|
||||
GET_PRIVATE_TRANSACTION_NONCE_ERROR(-50100, "Unable to determine nonce for account in group."),
|
||||
OFFCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST(-50100, "Offchain Privacy group does not exist."),
|
||||
FLEXIBLE_PRIVACY_GROUP_DOES_NOT_EXIST(-50100, "Flexible Privacy group does not exist."),
|
||||
|
||||
@@ -64,7 +64,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Synchronizer;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
@@ -86,7 +85,6 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
private final TransactionPool transactionPool;
|
||||
private final MiningCoordinator miningCoordinator;
|
||||
private final Set<Capability> supportedCapabilities;
|
||||
private final PrivacyParameters privacyParameters;
|
||||
private final Optional<Long> maxLogRange;
|
||||
|
||||
public EthJsonRpcMethods(
|
||||
@@ -97,7 +95,6 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
final TransactionPool transactionPool,
|
||||
final MiningCoordinator miningCoordinator,
|
||||
final Set<Capability> supportedCapabilities,
|
||||
final PrivacyParameters privacyParameters,
|
||||
final Optional<Long> maxLogRange) {
|
||||
this.blockchainQueries = blockchainQueries;
|
||||
this.synchronizer = synchronizer;
|
||||
@@ -106,7 +103,6 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
this.transactionPool = transactionPool;
|
||||
this.miningCoordinator = miningCoordinator;
|
||||
this.supportedCapabilities = supportedCapabilities;
|
||||
this.privacyParameters = privacyParameters;
|
||||
this.maxLogRange = maxLogRange;
|
||||
}
|
||||
|
||||
@@ -130,10 +126,9 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule,
|
||||
privacyParameters)),
|
||||
protocolSchedule)),
|
||||
new EthFeeHistory(protocolSchedule, blockchainQueries.getBlockchain()),
|
||||
new EthGetCode(blockchainQueries, Optional.of(privacyParameters)),
|
||||
new EthGetCode(blockchainQueries),
|
||||
new EthGetLogs(blockchainQueries, maxLogRange),
|
||||
new EthGetProof(blockchainQueries),
|
||||
new EthGetUncleCountByBlockHash(blockchainQueries),
|
||||
@@ -160,15 +155,13 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule,
|
||||
privacyParameters)),
|
||||
protocolSchedule)),
|
||||
new EthCreateAccessList(
|
||||
blockchainQueries,
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule,
|
||||
privacyParameters)),
|
||||
protocolSchedule)),
|
||||
new EthMining(miningCoordinator),
|
||||
new EthCoinbase(miningCoordinator),
|
||||
new EthProtocolVersion(supportedCapabilities),
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
|
||||
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.GoQuorumEthGetQuorumPayload;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.GoQuorumSendRawPrivateTransaction;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.GoQuorumStoreRawPrivateTransaction;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
|
||||
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GoQuorumJsonRpcPrivacyMethods extends PrivacyApiGroupJsonRpcMethods {
|
||||
|
||||
private final Optional<GoQuorumPrivacyParameters> goQuorumParameters;
|
||||
|
||||
public GoQuorumJsonRpcPrivacyMethods(
|
||||
final BlockchainQueries blockchainQueries,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final TransactionPool transactionPool,
|
||||
final PrivacyParameters privacyParameters) {
|
||||
super(blockchainQueries, protocolSchedule, transactionPool, privacyParameters);
|
||||
this.goQuorumParameters = privacyParameters.getGoQuorumPrivacyParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, JsonRpcMethod> create(
|
||||
final PrivacyController privacyController,
|
||||
final PrivacyIdProvider enclavePublicKeyProvider,
|
||||
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
|
||||
|
||||
if (goQuorumParameters.isPresent()) {
|
||||
final GoQuorumEnclave enclave = goQuorumParameters.get().enclave();
|
||||
return mapOf(
|
||||
new GoQuorumSendRawPrivateTransaction(
|
||||
enclave, getTransactionPool(), enclavePublicKeyProvider),
|
||||
new GoQuorumStoreRawPrivateTransaction(enclave),
|
||||
new GoQuorumEthGetQuorumPayload(enclave));
|
||||
} else {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getApiGroup() {
|
||||
return RpcApis.GOQUORUM.name();
|
||||
}
|
||||
}
|
||||
@@ -112,8 +112,6 @@ public class JsonRpcMethodsFactory {
|
||||
protocolContext,
|
||||
ethPeers,
|
||||
consensusEngineServer),
|
||||
new GoQuorumJsonRpcPrivacyMethods(
|
||||
blockchainQueries, protocolSchedule, transactionPool, privacyParameters),
|
||||
new EthJsonRpcMethods(
|
||||
blockchainQueries,
|
||||
synchronizer,
|
||||
@@ -122,7 +120,6 @@ public class JsonRpcMethodsFactory {
|
||||
transactionPool,
|
||||
miningCoordinator,
|
||||
supportedCapabilities,
|
||||
privacyParameters,
|
||||
maxLogRange),
|
||||
new NetJsonRpcMethods(
|
||||
p2pNetwork,
|
||||
@@ -141,7 +138,7 @@ public class JsonRpcMethodsFactory {
|
||||
new PrivxJsonRpcMethods(
|
||||
blockchainQueries, protocolSchedule, transactionPool, privacyParameters),
|
||||
new Web3JsonRpcMethods(clientVersion),
|
||||
new TraceJsonRpcMethods(blockchainQueries, protocolSchedule, privacyParameters),
|
||||
new TraceJsonRpcMethods(blockchainQueries, protocolSchedule),
|
||||
new TxPoolJsonRpcMethods(transactionPool),
|
||||
new PluginsJsonRpcMethods(namedPlugins));
|
||||
|
||||
|
||||
@@ -169,9 +169,7 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
|
||||
private JsonRpcMethod createPrivacyMethod(
|
||||
final PrivacyParameters privacyParameters, final JsonRpcMethod rpcMethod) {
|
||||
final String methodName = rpcMethod.getName();
|
||||
if (methodName.equals(RpcMethod.ETH_SEND_RAW_PRIVATE_TRANSACTION.getMethodName())
|
||||
|| methodName.equals(RpcMethod.GOQUORUM_STORE_RAW.getMethodName())
|
||||
|| methodName.equals(RpcMethod.GOQUORUM_ETH_GET_QUORUM_PAYLOAD.getMethodName())) {
|
||||
if (methodName.equals(RpcMethod.ETH_SEND_RAW_PRIVATE_TRANSACTION.getMethodName())) {
|
||||
return rpcMethod;
|
||||
} else if (privacyParameters.isEnabled() && privacyParameters.isMultiTenancyEnabled()) {
|
||||
return new MultiTenancyRpcMethodDecorator(rpcMethod);
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.TraceTransacti
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
|
||||
|
||||
@@ -37,15 +36,11 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
|
||||
private final BlockchainQueries blockchainQueries;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final PrivacyParameters privacyParameters;
|
||||
|
||||
TraceJsonRpcMethods(
|
||||
final BlockchainQueries blockchainQueries,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final PrivacyParameters privacyParameters) {
|
||||
final BlockchainQueries blockchainQueries, final ProtocolSchedule protocolSchedule) {
|
||||
this.blockchainQueries = blockchainQueries;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.privacyParameters = privacyParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,23 +65,20 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods {
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule,
|
||||
privacyParameters)),
|
||||
protocolSchedule)),
|
||||
new TraceCallMany(
|
||||
blockchainQueries,
|
||||
protocolSchedule,
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule,
|
||||
privacyParameters)),
|
||||
protocolSchedule)),
|
||||
new TraceRawTransaction(
|
||||
protocolSchedule,
|
||||
blockchainQueries,
|
||||
new TransactionSimulator(
|
||||
blockchainQueries.getBlockchain(),
|
||||
blockchainQueries.getWorldStateArchive(),
|
||||
protocolSchedule,
|
||||
privacyParameters)));
|
||||
protocolSchedule)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@ public class BlockchainQueries {
|
||||
// handles the case when fromBlockNumber is past chain head.
|
||||
.takeWhile(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.filter(header -> query.couldMatch(header.getLogsBloom(true)))
|
||||
.filter(header -> query.couldMatch(header.getLogsBloom()))
|
||||
.flatMap(header -> matchingLogs(header.getHash(), query, isQueryAlive).stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ public class TransactionLogBloomCacher {
|
||||
throw new InvalidCacheException();
|
||||
}
|
||||
writer.seek(offset);
|
||||
writer.write(ensureBloomBitsAreCorrectLength(blockHeader.getLogsBloom(true).toArray()));
|
||||
writer.write(ensureBloomBitsAreCorrectLength(blockHeader.getLogsBloom().toArray()));
|
||||
|
||||
// remove invalid logs when there was a reorg
|
||||
final long validCacheSize = offset + BLOOM_BITS_LENGTH;
|
||||
@@ -309,7 +309,7 @@ public class TransactionLogBloomCacher {
|
||||
|
||||
private void fillCacheFileWithBlock(final BlockHeader blockHeader, final OutputStream fos)
|
||||
throws IOException {
|
||||
fos.write(ensureBloomBitsAreCorrectLength(blockHeader.getLogsBloom(true).toArray()));
|
||||
fos.write(ensureBloomBitsAreCorrectLength(blockHeader.getLogsBloom().toArray()));
|
||||
}
|
||||
|
||||
private byte[] ensureBloomBitsAreCorrectLength(final byte[] logs) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.util;
|
||||
|
||||
import org.hyperledger.besu.config.GoQuorumOptions;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
|
||||
@@ -28,8 +27,7 @@ public class DomainObjectDecodeUtils {
|
||||
throws InvalidJsonRpcRequestException {
|
||||
try {
|
||||
Bytes txnBytes = Bytes.fromHexString(rawTransaction);
|
||||
final boolean isGoQuorumCompatibilityMode = GoQuorumOptions.getGoQuorumCompatibilityMode();
|
||||
return TransactionDecoder.decodeOpaqueBytes(txnBytes, isGoQuorumCompatibilityMode);
|
||||
return TransactionDecoder.decodeOpaqueBytes(txnBytes);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
throw new InvalidJsonRpcRequestException("Invalid raw transaction hex", e);
|
||||
} catch (final RLPException r) {
|
||||
|
||||
@@ -73,8 +73,7 @@ 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,12 +176,6 @@ 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)))
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.goquorum;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.enclave.EnclaveClientException;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.GoQuorumEthGetQuorumPayload;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings("DirectInvocationOnMock")
|
||||
public class GoQuorumEthGetQuorumPayloadTest {
|
||||
|
||||
@Mock GoQuorumEthGetQuorumPayload method;
|
||||
@Mock GoQuorumEnclave enclave;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
method = new GoQuorumEthGetQuorumPayload(enclave);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctRequest() {
|
||||
final String hexString = Bytes.wrap(new byte[64]).toHexString();
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {hexString}));
|
||||
|
||||
when(enclave.receive(any()))
|
||||
.thenReturn(new GoQuorumReceiveResponse(new byte[10], 0, null, null));
|
||||
|
||||
final JsonRpcResponse response = method.response(request);
|
||||
assertThat(response).isInstanceOf(JsonRpcSuccessResponse.class);
|
||||
assertThat(((JsonRpcSuccessResponse) response).getResult().toString())
|
||||
.isEqualTo("0x00000000000000000000");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestIsMissingParameter() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {}));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHasNullObjectParameter() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "eth_getQuorumPayload", null));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHasNullArrayParameter() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {null}));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHasShortHex() {
|
||||
final String hexString = Bytes.wrap(new byte[63]).toHexString();
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {hexString}));
|
||||
|
||||
final JsonRpcResponse response = method.response(request);
|
||||
assertThat(response).isInstanceOf(JsonRpcErrorResponse.class);
|
||||
assertThat(response.toString()).contains("INVALID_PARAMS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHasLongHex() {
|
||||
final String hexString = Bytes.wrap(new byte[65]).toHexString();
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {hexString}));
|
||||
|
||||
final JsonRpcResponse response = method.response(request);
|
||||
assertThat(response).isInstanceOf(JsonRpcErrorResponse.class);
|
||||
assertThat(response.toString()).contains("INVALID_PARAMS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestNonHexString() {
|
||||
final String hexString = Bytes.wrap(new byte[63]).toHexString() + "f";
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {hexString}));
|
||||
|
||||
final JsonRpcResponse response = method.response(request);
|
||||
assertThat(response).isInstanceOf(JsonRpcErrorResponse.class);
|
||||
assertThat(response.toString()).contains("INVALID_PARAMS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclave404ReturnsEmptyBytesString() {
|
||||
final String hexString = Bytes.wrap(new byte[64]).toHexString();
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_getQuorumPayload", new String[] {hexString}));
|
||||
|
||||
when(enclave.receive(any())).thenThrow(new EnclaveClientException(404, null));
|
||||
|
||||
final JsonRpcResponse response = method.response(request);
|
||||
assertThat(response).isInstanceOf(JsonRpcSuccessResponse.class);
|
||||
assertThat(((JsonRpcSuccessResponse) response).getResult())
|
||||
.isEqualTo(Bytes.EMPTY.toHexString());
|
||||
}
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.goquorum;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.GoQuorumSendRawPrivateTransaction;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
|
||||
import org.hyperledger.besu.ethereum.privacy.GoQuorumSendRawTxArgs;
|
||||
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.plugin.data.Restriction;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings("DirectInvocationOnMock")
|
||||
public class GoQuorumSendRawPrivateTransactionTest {
|
||||
|
||||
static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
|
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
|
||||
static final String INVALID_TRANSACTION_RLP = invalidGQPrivateTransactionRlp();
|
||||
|
||||
static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo=";
|
||||
final PrivacyIdProvider privacyIdProvider = (user) -> ENCLAVE_PUBLIC_KEY;
|
||||
|
||||
@Mock GoQuorumSendRawPrivateTransaction method;
|
||||
@Mock TransactionPool transactionPool;
|
||||
@Mock GoQuorumEnclave enclave;
|
||||
private static final String RAW_TRANSACTION_STRING = "someString";
|
||||
private static final String RAW_TRANSACTION = createValidTransactionRLP();
|
||||
private static final GoQuorumSendRawTxArgs GO_QUORUM_SEND_RAW_TX_ARGS =
|
||||
new GoQuorumSendRawTxArgs(
|
||||
ENCLAVE_PUBLIC_KEY, Collections.singletonList(ENCLAVE_PUBLIC_KEY), 0);
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
boolean goQuorumCompatibilityMode = true;
|
||||
method =
|
||||
new GoQuorumSendRawPrivateTransaction(
|
||||
enclave, transactionPool, privacyIdProvider, goQuorumCompatibilityMode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestIsMissingParameter() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "eth_sendRawPrivateTransaction", new String[] {}));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 0");
|
||||
|
||||
final JsonRpcRequestContext request2 =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest(
|
||||
"2.0", "eth_sendRawPrivateTransaction", new String[] {RAW_TRANSACTION_STRING}));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request2))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHasNullObjectParameter() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "eth_sendRawPrivateTransaction", null));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHasNullArrayParameter() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest("2.0", "\"eth_sendRawPrivateTransaction\"", new String[] {null}));
|
||||
|
||||
assertThatThrownBy(() -> method.response(request))
|
||||
.isInstanceOf(InvalidJsonRpcParameters.class)
|
||||
.hasMessage("Missing required json rpc parameter at index 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validTransactionIsSentToTransactionPool() {
|
||||
when(enclave.sendSignedTransaction(any(), any())).thenReturn(null);
|
||||
|
||||
when(transactionPool.addLocalTransaction(any(Transaction.class)))
|
||||
.thenReturn(ValidationResult.valid());
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest(
|
||||
"2.0",
|
||||
"\"eth_sendRawPrivateTransaction\"",
|
||||
new Object[] {RAW_TRANSACTION, GO_QUORUM_SEND_RAW_TX_ARGS}));
|
||||
|
||||
method.response(request);
|
||||
|
||||
verify(transactionPool).addLocalTransaction(any(Transaction.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidTransactionIsNotAddedToTransactionPool() {
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest(
|
||||
"2.0",
|
||||
"\"eth_sendRawPrivateTransaction\"",
|
||||
new Object[] {INVALID_TRANSACTION_RLP, GO_QUORUM_SEND_RAW_TX_ARGS}));
|
||||
|
||||
final JsonRpcResponse expectedResponse =
|
||||
new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.DECODE_ERROR);
|
||||
|
||||
final JsonRpcResponse actualResponse = method.response(request);
|
||||
|
||||
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
|
||||
verifyNoInteractions(transactionPool);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithNonceBelowAccountNonceIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.NONCE_TOO_LOW, JsonRpcError.NONCE_TOO_LOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithNonceAboveAccountNonceIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.NONCE_TOO_HIGH, JsonRpcError.NONCE_TOO_HIGH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithInvalidSignatureIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.INVALID_SIGNATURE, JsonRpcError.INVALID_TRANSACTION_SIGNATURE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithIntrinsicGasExceedingGasLimitIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT,
|
||||
JsonRpcError.PMT_FAILED_INTRINSIC_GAS_EXCEEDS_LIMIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithUpfrontGasExceedingAccountBalanceIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE,
|
||||
JsonRpcError.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithGasLimitExceedingBlockGasLimitIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT, JsonRpcError.EXCEEDS_BLOCK_GAS_LIMIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionWithNotWhitelistedSenderAccountIsRejected() {
|
||||
verifyErrorForInvalidTransaction(
|
||||
TransactionInvalidReason.TX_SENDER_NOT_AUTHORIZED, JsonRpcError.TX_SENDER_NOT_AUTHORIZED);
|
||||
}
|
||||
|
||||
private void verifyErrorForInvalidTransaction(
|
||||
final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) {
|
||||
|
||||
when(transactionPool.addLocalTransaction(any(Transaction.class)))
|
||||
.thenReturn(ValidationResult.invalid(transactionInvalidReason));
|
||||
final JsonRpcRequestContext request =
|
||||
new JsonRpcRequestContext(
|
||||
new JsonRpcRequest(
|
||||
"2.0",
|
||||
"\"eth_sendRawPrivateTransaction\"",
|
||||
new Object[] {RAW_TRANSACTION, GO_QUORUM_SEND_RAW_TX_ARGS}));
|
||||
|
||||
final JsonRpcResponse expectedResponse =
|
||||
new JsonRpcErrorResponse(request.getRequest().getId(), expectedError);
|
||||
|
||||
final JsonRpcResponse actualResponse = method.response(request);
|
||||
|
||||
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
|
||||
|
||||
verify(transactionPool).addLocalTransaction(any(Transaction.class));
|
||||
}
|
||||
|
||||
private static String invalidGQPrivateTransactionRlp() {
|
||||
final PrivateTransaction.Builder privateTransactionBuilder =
|
||||
PrivateTransaction.builder()
|
||||
.nonce(0)
|
||||
.gasPrice(Wei.of(1))
|
||||
.gasLimit(21000)
|
||||
.value(Wei.ZERO)
|
||||
.payload(Bytes.EMPTY)
|
||||
.to(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"))
|
||||
.chainId(BigInteger.ONE)
|
||||
.privateFrom(Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp="))
|
||||
.privateFor(
|
||||
List.of(
|
||||
Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp="),
|
||||
Bytes.fromBase64String("QTFhVnRNeExDVUhtQlZIWG9aenpCZ1BiVy93ajVheER=")))
|
||||
.restriction(Restriction.RESTRICTED);
|
||||
return rlpEncodeTransaction(privateTransactionBuilder);
|
||||
}
|
||||
|
||||
private static String rlpEncodeTransaction(
|
||||
final PrivateTransaction.Builder privateTransactionBuilder) {
|
||||
final KeyPair keyPair =
|
||||
SIGNATURE_ALGORITHM
|
||||
.get()
|
||||
.createKeyPair(
|
||||
SIGNATURE_ALGORITHM
|
||||
.get()
|
||||
.createPrivateKey(
|
||||
new BigInteger(
|
||||
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
|
||||
16)));
|
||||
|
||||
final PrivateTransaction privateTransaction = privateTransactionBuilder.signAndBuild(keyPair);
|
||||
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
|
||||
privateTransaction.writeTo(bvrlp);
|
||||
return bvrlp.encoded().toHexString();
|
||||
}
|
||||
|
||||
private static final String createValidTransactionRLP() {
|
||||
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
|
||||
final Transaction publicTransaction =
|
||||
new Transaction(
|
||||
0L,
|
||||
Wei.of(1),
|
||||
21000L,
|
||||
Optional.of(
|
||||
Address.wrap(Bytes.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"))),
|
||||
Wei.ZERO,
|
||||
SIGNATURE_ALGORITHM
|
||||
.get()
|
||||
.createSignature(
|
||||
new BigInteger(
|
||||
"32886959230931919120748662916110619501838190146643992583529828535682419954515"),
|
||||
new BigInteger(
|
||||
"14473701025599600909210599917245952381483216609124029382871721729679842002948"),
|
||||
Byte.parseByte("0")),
|
||||
Bytes.fromHexString("0x01"), // this is the enclave key for the private payload
|
||||
Address.wrap(
|
||||
Bytes.fromHexString(
|
||||
"0x8411b12666f68ef74cace3615c9d5a377729d03f")), // sender public address
|
||||
Optional.empty(),
|
||||
Optional.of(BigInteger.valueOf(37)),
|
||||
Optional.empty());
|
||||
publicTransaction.writeTo(bvrlp);
|
||||
return bvrlp.encoded().toHexString();
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -92,7 +91,6 @@ public class RewardTraceGeneratorTest {
|
||||
blockReward,
|
||||
BlockHeader::getCoinbase,
|
||||
true,
|
||||
Optional.empty(),
|
||||
protocolSchedule);
|
||||
when(protocolSpec.getBlockProcessor()).thenReturn(blockProcessor);
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.api.query;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.evm.log.Log;
|
||||
import org.hyperledger.besu.evm.log.LogsBloomFilter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GoQuorumPrivateTxBloomBlockchainQueriesTest {
|
||||
|
||||
@ClassRule public static TemporaryFolder cacheDir = new TemporaryFolder();
|
||||
|
||||
private static LogsQuery logsQuery;
|
||||
private Hash testHash;
|
||||
private static LogsBloomFilter testLogsBloomFilter;
|
||||
|
||||
@Mock MutableBlockchain blockchain;
|
||||
@Mock WorldStateArchive worldStateArchive;
|
||||
@Mock EthScheduler scheduler;
|
||||
private BlockchainQueries blockchainQueries;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupClass() {
|
||||
final Address testAddress = Address.fromHexString("0x123456");
|
||||
final Bytes testMessage = Bytes.fromHexString("0x9876");
|
||||
final Log testLog = new Log(testAddress, testMessage, List.of());
|
||||
testLogsBloomFilter = LogsBloomFilter.builder().insertLog(testLog).build();
|
||||
logsQuery = new LogsQuery(List.of(testAddress), List.of());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
final BlockHeader fakeHeader =
|
||||
new BlockHeader(
|
||||
Hash.EMPTY,
|
||||
Hash.EMPTY,
|
||||
Address.ZERO,
|
||||
Hash.EMPTY,
|
||||
Hash.EMPTY,
|
||||
Hash.EMPTY,
|
||||
LogsBloomFilter.empty(),
|
||||
Difficulty.ZERO,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Bytes.EMPTY,
|
||||
null,
|
||||
Hash.EMPTY,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new MainnetBlockHeaderFunctions(),
|
||||
Optional.of(testLogsBloomFilter));
|
||||
testHash = fakeHeader.getHash();
|
||||
final BlockBody fakeBody = new BlockBody(Collections.emptyList(), Collections.emptyList());
|
||||
when(blockchain.getBlockHeader(any())).thenReturn(Optional.of(fakeHeader));
|
||||
when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader));
|
||||
when(blockchain.getTxReceipts(any())).thenReturn(Optional.of(Collections.emptyList()));
|
||||
when(blockchain.getBlockBody(any())).thenReturn(Optional.of(fakeBody));
|
||||
blockchainQueries =
|
||||
new BlockchainQueries(
|
||||
blockchain,
|
||||
worldStateArchive,
|
||||
Optional.of(cacheDir.getRoot().toPath()),
|
||||
Optional.of(scheduler));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether block headers containing private blooms match. The resulting list of
|
||||
* LogWithMetadata would be empty, because the mocked blockchain does not return any receipts, but
|
||||
* we do check that the methods on the blockchain are actually called that would be called if the
|
||||
* block header matches the bloom filter.
|
||||
*/
|
||||
@Test
|
||||
public void testPrivateBloomsWork() {
|
||||
blockchainQueries.matchingLogs(0, 2, logsQuery, () -> true);
|
||||
|
||||
verify(blockchain, times(3)).getBlockHeader(anyLong());
|
||||
verify(blockchain, times(3)).getBlockHeader(testHash);
|
||||
verify(blockchain, times(3)).getTxReceipts(testHash);
|
||||
verify(blockchain, times(3)).getBlockBody(testHash);
|
||||
verify(blockchain, times(3)).blockIsOnCanonicalChain(testHash);
|
||||
|
||||
verifyNoMoreInteractions(blockchain);
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.api.query.cache;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher.BLOOM_BITS_LENGTH;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.api.query.LogsQuery;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.evm.log.Log;
|
||||
import org.hyperledger.besu.evm.log.LogsBloomFilter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings({"unused", "DirectInvocationOnMock"})
|
||||
public class GoQuorumPrivateTransactionLogBloomCacherTest {
|
||||
|
||||
private static final long NUMBER_3 = 3L;
|
||||
private static LogsQuery logsQuery;
|
||||
@Rule public TemporaryFolder cacheDir = new TemporaryFolder();
|
||||
|
||||
private Hash testBlockHeaderHash;
|
||||
private static LogsBloomFilter testLogsBloomFilter;
|
||||
|
||||
@Mock MutableBlockchain blockchain;
|
||||
@Mock EthScheduler scheduler;
|
||||
@Mock WorldStateArchive worldStateArchive;
|
||||
|
||||
private TransactionLogBloomCacher transactionLogBloomCacher;
|
||||
private BlockchainQueries blockchainQueries;
|
||||
private static Address testAddress;
|
||||
private static Bytes testMessage;
|
||||
private BlockHeader fakeHeader;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupClass() {
|
||||
testAddress = Address.fromHexString("0x123456");
|
||||
testMessage = Bytes.fromHexString("0x9876");
|
||||
final Log testLog = new Log(testAddress, testMessage, List.of());
|
||||
testLogsBloomFilter = LogsBloomFilter.builder().insertLog(testLog).build();
|
||||
logsQuery = new LogsQuery(List.of(testAddress), List.of());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "ReturnValueIgnored"})
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
fakeHeader = createBlock(NUMBER_3);
|
||||
|
||||
testBlockHeaderHash = fakeHeader.getHash();
|
||||
|
||||
transactionLogBloomCacher =
|
||||
new TransactionLogBloomCacher(blockchain, cacheDir.getRoot().toPath(), scheduler);
|
||||
|
||||
blockchainQueries =
|
||||
new BlockchainQueries(
|
||||
blockchain,
|
||||
worldStateArchive,
|
||||
Optional.of(cacheDir.getRoot().toPath()),
|
||||
Optional.of(scheduler));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUpdateCacheWhenBlockAdded() throws IOException {
|
||||
|
||||
final BlockBody fakeBody = new BlockBody(Collections.emptyList(), Collections.emptyList());
|
||||
when(blockchain.getBlockHeader(testBlockHeaderHash)).thenReturn(Optional.of(fakeHeader));
|
||||
when(blockchain.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(testBlockHeaderHash));
|
||||
when(blockchain.getTxReceipts(any())).thenReturn(Optional.of(Collections.emptyList()));
|
||||
when(blockchain.getBlockBody(any())).thenReturn(Optional.of(fakeBody));
|
||||
|
||||
final File logBloom = cacheDir.newFile("logBloom-0.cache");
|
||||
|
||||
createLogBloomCache(logBloom);
|
||||
|
||||
createBlock(3L);
|
||||
|
||||
assertThat(logBloom.length()).isEqualTo(BLOOM_BITS_LENGTH * 3);
|
||||
|
||||
when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader));
|
||||
transactionLogBloomCacher.cacheLogsBloomForBlockHeader(
|
||||
blockchain.getBlockHeader(NUMBER_3).get(), Optional.empty(), Optional.of(logBloom));
|
||||
|
||||
assertThat(logBloom.length()).isEqualTo(BLOOM_BITS_LENGTH * 4);
|
||||
assertThat(cacheDir.getRoot().list().length).isEqualTo(1);
|
||||
|
||||
blockchainQueries.matchingLogs(NUMBER_3, 3, logsQuery, () -> true);
|
||||
|
||||
verify(blockchain, times(1)).getBlockHashByNumber(NUMBER_3);
|
||||
verify(blockchain, times(1)).getBlockHeader(NUMBER_3);
|
||||
verify(blockchain, times(1)).getBlockHeader(testBlockHeaderHash);
|
||||
verify(blockchain, times(1)).getTxReceipts(testBlockHeaderHash);
|
||||
verify(blockchain, times(1)).getBlockBody(testBlockHeaderHash);
|
||||
verify(blockchain, times(1)).blockIsOnCanonicalChain(testBlockHeaderHash);
|
||||
|
||||
verifyNoMoreInteractions(blockchain);
|
||||
}
|
||||
|
||||
private void createLogBloomCache(final File logBloom) throws IOException {
|
||||
try (final RandomAccessFile randomAccessFile = new RandomAccessFile(logBloom, "rws")) {
|
||||
randomAccessFile.write(testLogsBloomFilter.toArray());
|
||||
randomAccessFile.write(testLogsBloomFilter.toArray());
|
||||
randomAccessFile.write(testLogsBloomFilter.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private BlockHeader createBlock(final long number) {
|
||||
final Log testLog = new Log(testAddress, testMessage, List.of());
|
||||
final BlockHeader fakeHeader =
|
||||
new BlockHeader(
|
||||
Hash.EMPTY,
|
||||
Hash.EMPTY,
|
||||
Address.ZERO,
|
||||
Hash.EMPTY,
|
||||
Hash.EMPTY,
|
||||
Hash.EMPTY,
|
||||
LogsBloomFilter.empty(),
|
||||
Difficulty.ZERO,
|
||||
number,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Bytes.EMPTY,
|
||||
null,
|
||||
Hash.EMPTY,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new MainnetBlockHeaderFunctions(),
|
||||
Optional.of(testLogsBloomFilter));
|
||||
return fakeHeader;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions.TransactionSelectionResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
@@ -34,13 +33,11 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
|
||||
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
|
||||
import org.hyperledger.besu.evm.account.EvmAccount;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
import org.hyperledger.besu.plugin.data.TransactionType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -50,7 +47,6 @@ import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -327,40 +323,18 @@ public class BlockTransactionSelector {
|
||||
final WorldUpdater worldStateUpdater = worldState.updater();
|
||||
final BlockHashLookup blockHashLookup =
|
||||
new CachingBlockHashLookup(processableBlockHeader, blockchain);
|
||||
final boolean isGoQuorumPrivateTransaction =
|
||||
transaction.isGoQuorumPrivateTransaction(
|
||||
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());
|
||||
|
||||
TransactionProcessingResult effectiveResult;
|
||||
|
||||
if (isGoQuorumPrivateTransaction) {
|
||||
final ValidationResult<TransactionInvalidReason> validationResult =
|
||||
validateTransaction(processableBlockHeader, transaction, worldStateUpdater);
|
||||
if (!validationResult.isValid()) {
|
||||
LOG.warn(
|
||||
"Invalid transaction: {}. Block {} Transaction {}",
|
||||
validationResult.getErrorMessage(),
|
||||
processableBlockHeader.getParentHash().toHexString(),
|
||||
transaction.getHash().toHexString());
|
||||
return transactionSelectionResultForInvalidResult(transaction, validationResult);
|
||||
} else {
|
||||
// valid GoQuorum private tx, we need to handcraft the receipt and increment the nonce
|
||||
effectiveResult = publicResultForWhenWeHaveAPrivateTransaction(transaction);
|
||||
worldStateUpdater.getOrCreate(transaction.getSender()).getMutable().incrementNonce();
|
||||
}
|
||||
} else {
|
||||
effectiveResult =
|
||||
transactionProcessor.processTransaction(
|
||||
blockchain,
|
||||
worldStateUpdater,
|
||||
processableBlockHeader,
|
||||
transaction,
|
||||
miningBeneficiary,
|
||||
blockHashLookup,
|
||||
false,
|
||||
TransactionValidationParams.mining(),
|
||||
dataGasPrice);
|
||||
}
|
||||
final TransactionProcessingResult effectiveResult =
|
||||
transactionProcessor.processTransaction(
|
||||
blockchain,
|
||||
worldStateUpdater,
|
||||
processableBlockHeader,
|
||||
transaction,
|
||||
miningBeneficiary,
|
||||
blockHashLookup,
|
||||
false,
|
||||
TransactionValidationParams.mining(),
|
||||
dataGasPrice);
|
||||
|
||||
if (!effectiveResult.isInvalid()) {
|
||||
worldStateUpdater.commit();
|
||||
@@ -445,42 +419,14 @@ public class BlockTransactionSelector {
|
||||
|| invalidReason.equals(TransactionInvalidReason.NONCE_TOO_HIGH);
|
||||
}
|
||||
|
||||
private ValidationResult<TransactionInvalidReason> validateTransaction(
|
||||
final ProcessableBlockHeader blockHeader,
|
||||
final Transaction transaction,
|
||||
final WorldUpdater publicWorldStateUpdater) {
|
||||
final TransactionValidationParams transactionValidationParams =
|
||||
TransactionValidationParams.processingBlock();
|
||||
final MainnetTransactionValidator transactionValidator =
|
||||
transactionProcessor.getTransactionValidator();
|
||||
ValidationResult<TransactionInvalidReason> validationResult =
|
||||
transactionValidator.validate(
|
||||
transaction, blockHeader.getBaseFee(), transactionValidationParams);
|
||||
if (!validationResult.isValid()) {
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
final Address senderAddress = transaction.getSender();
|
||||
|
||||
final EvmAccount sender = publicWorldStateUpdater.getOrCreate(senderAddress);
|
||||
validationResult =
|
||||
transactionValidator.validateForSender(transaction, sender, transactionValidationParams);
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
/*
|
||||
Responsible for updating the state maintained between transaction validation (i.e. receipts,
|
||||
cumulative gas, world state root hash.).
|
||||
*/
|
||||
private void updateTransactionResultTracking(
|
||||
final Transaction transaction, final TransactionProcessingResult result) {
|
||||
final boolean isGoQuorumPrivateTransaction =
|
||||
transaction.isGoQuorumPrivateTransaction(
|
||||
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());
|
||||
|
||||
final long gasUsedByTransaction =
|
||||
isGoQuorumPrivateTransaction ? 0 : transaction.getGasLimit() - result.getGasRemaining();
|
||||
final long gasUsedByTransaction = transaction.getGasLimit() - result.getGasRemaining();
|
||||
|
||||
final long cumulativeGasUsed =
|
||||
transactionSelectionResult.getCumulativeGasUsed() + gasUsedByTransaction;
|
||||
@@ -499,16 +445,6 @@ public class BlockTransactionSelector {
|
||||
return result.getInvalidReason().equals(TransactionInvalidReason.NONCE_TOO_HIGH);
|
||||
}
|
||||
|
||||
private TransactionProcessingResult publicResultForWhenWeHaveAPrivateTransaction(
|
||||
final Transaction transaction) {
|
||||
return TransactionProcessingResult.successful(
|
||||
Collections.emptyList(),
|
||||
0,
|
||||
transaction.getGasLimit(),
|
||||
Bytes.EMPTY,
|
||||
ValidationResult.valid());
|
||||
}
|
||||
|
||||
private boolean transactionTooLargeForBlock(final Transaction transaction) {
|
||||
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
|
||||
|
||||
|
||||
@@ -148,7 +148,6 @@ abstract class AbstractBlockCreatorTest {
|
||||
protocolSpecAdapters,
|
||||
PrivacyParameters.DEFAULT,
|
||||
false,
|
||||
genesisConfigOptions.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule())
|
||||
.build();
|
||||
|
||||
@@ -92,8 +92,6 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
public void setup() {
|
||||
worldState = InMemoryKeyValueStorageProvider.createInMemoryWorldState();
|
||||
pendingTransactions = createPendingTransactions();
|
||||
when(transactionProcessor.getTransactionValidator()).thenReturn(transactionValidator);
|
||||
when(transactionValidator.getGoQuorumCompatibilityMode()).thenReturn(true);
|
||||
}
|
||||
|
||||
protected abstract PendingTransactions createPendingTransactions();
|
||||
|
||||
@@ -80,7 +80,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
PrivacyParameters.DEFAULT,
|
||||
false,
|
||||
genesisConfigOptions.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule())
|
||||
.build();
|
||||
@@ -142,7 +141,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
PrivacyParameters.DEFAULT,
|
||||
false,
|
||||
genesisConfigOptions.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule())
|
||||
.build();
|
||||
@@ -194,7 +192,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
PrivacyParameters.DEFAULT,
|
||||
false,
|
||||
genesisConfigOptions.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule();
|
||||
final ExecutionContextTestFixture executionContextTestFixture =
|
||||
@@ -269,7 +266,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
PrivacyParameters.DEFAULT,
|
||||
false,
|
||||
genesisConfigOptions.isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule();
|
||||
final ExecutionContextTestFixture executionContextTestFixture =
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumBlockProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockBodyValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockProcessor;
|
||||
@@ -29,7 +28,6 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.plugin.services.exception.StorageException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -146,25 +144,6 @@ public class MainnetBlockValidator implements BlockValidator {
|
||||
handleAndLogImportFailure(block, result, shouldRecordBadBlock);
|
||||
return new BlockProcessingResult("failed to validate output of imported block");
|
||||
}
|
||||
if (result instanceof GoQuorumBlockProcessingResult) {
|
||||
var privateOutput = (GoQuorumBlockProcessingResult) result;
|
||||
if (!privateOutput.getPrivateReceipts().isEmpty()) {
|
||||
// replace the public receipts for marker transactions with the private receipts if we
|
||||
// are in goQuorumCompatibilityMode. That can be done now because we have validated the
|
||||
// block.
|
||||
final List<TransactionReceipt> privateTransactionReceipts =
|
||||
privateOutput.getPrivateReceipts();
|
||||
final ArrayList<TransactionReceipt> resultingList = new ArrayList<>(receipts.size());
|
||||
for (int i = 0; i < receipts.size(); i++) {
|
||||
if (privateTransactionReceipts.get(i) != null) {
|
||||
resultingList.add(privateTransactionReceipts.get(i));
|
||||
} else {
|
||||
resultingList.add(receipts.get(i));
|
||||
}
|
||||
}
|
||||
receipts = Collections.unmodifiableList(resultingList);
|
||||
}
|
||||
}
|
||||
|
||||
return new BlockProcessingResult(
|
||||
Optional.of(new BlockProcessingOutputs(worldState, receipts)));
|
||||
|
||||
@@ -42,8 +42,6 @@ public class BlockHeader extends SealableBlockHeader
|
||||
|
||||
private final Supplier<Hash> hash;
|
||||
|
||||
private Optional<LogsBloomFilter> privateLogsBloom;
|
||||
|
||||
private final Supplier<ParsedExtraData> parsedExtraData;
|
||||
|
||||
public BlockHeader(
|
||||
@@ -90,7 +88,6 @@ public class BlockHeader extends SealableBlockHeader
|
||||
this.nonce = nonce;
|
||||
this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this));
|
||||
this.parsedExtraData = Suppliers.memoize(() -> blockHeaderFunctions.parseExtraData(this));
|
||||
this.privateLogsBloom = privateLogsBloom;
|
||||
}
|
||||
|
||||
public BlockHeader(
|
||||
@@ -136,7 +133,6 @@ public class BlockHeader extends SealableBlockHeader
|
||||
this.nonce = nonce;
|
||||
this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this));
|
||||
this.parsedExtraData = Suppliers.memoize(() -> blockHeaderFunctions.parseExtraData(this));
|
||||
this.privateLogsBloom = Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,31 +183,6 @@ public class BlockHeader extends SealableBlockHeader
|
||||
return hash.get();
|
||||
}
|
||||
|
||||
public LogsBloomFilter getLogsBloom(final boolean addPrivateBloom) {
|
||||
if (addPrivateBloom && privateLogsBloom.isPresent()) {
|
||||
return LogsBloomFilter.builder()
|
||||
.insertFilter(logsBloom)
|
||||
.insertFilter(privateLogsBloom.get())
|
||||
.build();
|
||||
} else {
|
||||
return logsBloom;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPrivateLogsBloom(final LogsBloomFilter privateLogsBloom) {
|
||||
this.privateLogsBloom = Optional.ofNullable(privateLogsBloom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block's private logs bloom filter that might be available if we are in goQuorum
|
||||
* mode
|
||||
*
|
||||
* @return the private logs bloom filter
|
||||
*/
|
||||
public Optional<LogsBloomFilter> getPrivateLogsBloom() {
|
||||
return privateLogsBloom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an RLP representation.
|
||||
*
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core;
|
||||
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
|
||||
public class GoQuorumPrivacyParameters {
|
||||
|
||||
private final GoQuorumEnclave enclave;
|
||||
|
||||
private final String enclaveKey;
|
||||
|
||||
private final GoQuorumPrivateStorage goQuorumPrivateStorage;
|
||||
private final WorldStateArchive privateWorldStateArchive;
|
||||
|
||||
public GoQuorumPrivacyParameters(
|
||||
final GoQuorumEnclave enclave,
|
||||
final String enclaveKey,
|
||||
final GoQuorumPrivateStorage goQuorumPrivateStorage,
|
||||
final WorldStateArchive privateWorldStateArchive) {
|
||||
this.enclave = enclave;
|
||||
this.enclaveKey = enclaveKey;
|
||||
this.goQuorumPrivateStorage = goQuorumPrivateStorage;
|
||||
this.privateWorldStateArchive = privateWorldStateArchive;
|
||||
}
|
||||
|
||||
public GoQuorumEnclave enclave() {
|
||||
return enclave;
|
||||
}
|
||||
|
||||
public String enclaveKey() {
|
||||
return enclaveKey;
|
||||
}
|
||||
|
||||
public GoQuorumPrivateStorage privateStorage() {
|
||||
return goQuorumPrivateStorage;
|
||||
}
|
||||
|
||||
public WorldStateArchive worldStateArchive() {
|
||||
return privateWorldStateArchive;
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,6 @@ public class PrivacyParameters {
|
||||
private boolean privacyPluginEnabled;
|
||||
private PrivateStateRootResolver privateStateRootResolver;
|
||||
private PrivateWorldStateReader privateWorldStateReader;
|
||||
private Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters = Optional.empty();
|
||||
private PrivacyPluginService privacyPluginService;
|
||||
|
||||
public Address getPrivacyAddress() {
|
||||
@@ -202,16 +201,6 @@ public class PrivacyParameters {
|
||||
this.privateWorldStateReader = privateWorldStateReader;
|
||||
}
|
||||
|
||||
public Optional<GoQuorumPrivacyParameters> getGoQuorumPrivacyParameters() {
|
||||
return goQuorumPrivacyParameters;
|
||||
}
|
||||
|
||||
private void setGoQuorumPrivacyParameters(
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters) {
|
||||
this.goQuorumPrivacyParameters =
|
||||
goQuorumPrivacyParameters != null ? goQuorumPrivacyParameters : Optional.empty();
|
||||
}
|
||||
|
||||
private void setPrivacyService(final PrivacyPluginService privacyPluginService) {
|
||||
this.privacyPluginService = privacyPluginService;
|
||||
}
|
||||
@@ -272,7 +261,6 @@ public class PrivacyParameters {
|
||||
private Path privacyTlsKnownEnclaveFile;
|
||||
private boolean flexiblePrivacyGroupsEnabled;
|
||||
private boolean privacyPluginEnabled;
|
||||
private Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters;
|
||||
private PrivacyPluginService privacyPluginService;
|
||||
|
||||
public Builder setEnclaveUrl(final URI enclaveUrl) {
|
||||
@@ -330,12 +318,6 @@ public class PrivacyParameters {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setGoQuorumPrivacyParameters(
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters) {
|
||||
this.goQuorumPrivacyParameters = goQuorumPrivacyParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrivacyUserIdUsingFile(final File publicKeyFile) throws IOException {
|
||||
this.enclavePublicKeyFile = publicKeyFile;
|
||||
this.privacyUserId = Files.asCharSource(publicKeyFile, UTF_8).read();
|
||||
@@ -398,7 +380,6 @@ public class PrivacyParameters {
|
||||
config.setMultiTenancyEnabled(multiTenancyEnabled);
|
||||
config.setFlexiblePrivacyGroupsEnabled(flexiblePrivacyGroupsEnabled);
|
||||
config.setPrivacyPluginEnabled(privacyPluginEnabled);
|
||||
config.setGoQuorumPrivacyParameters(goQuorumPrivacyParameters);
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
import org.hyperledger.besu.ethereum.transaction.GoQuorumPrivateTransactionDetector;
|
||||
import org.hyperledger.besu.evm.AccessListEntry;
|
||||
import org.hyperledger.besu.plugin.data.TransactionType;
|
||||
|
||||
@@ -63,9 +62,6 @@ public class Transaction
|
||||
|
||||
public static final BigInteger REPLAY_PROTECTED_V_BASE = BigInteger.valueOf(35);
|
||||
|
||||
public static final BigInteger GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MIN = BigInteger.valueOf(37);
|
||||
public static final BigInteger GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MAX = BigInteger.valueOf(38);
|
||||
|
||||
// The v signature parameter starts at 36 because 1 is the first valid chainId so:
|
||||
// chainId > 1 implies that 2 * chainId + V_BASE > 36.
|
||||
public static final BigInteger REPLAY_PROTECTED_V_MIN = BigInteger.valueOf(36);
|
||||
@@ -95,8 +91,6 @@ public class Transaction
|
||||
|
||||
private final Optional<BigInteger> chainId;
|
||||
|
||||
private final Optional<BigInteger> v;
|
||||
|
||||
// Caches a "hash" of a portion of the transaction used for sender recovery.
|
||||
// Note that this hash does not include the transaction signature so it does not
|
||||
// fully identify the transaction (use the result of the {@code hash()} for that).
|
||||
@@ -145,9 +139,6 @@ public class Transaction
|
||||
* preload
|
||||
* @param sender the transaction sender
|
||||
* @param chainId the chain id to apply the transaction to
|
||||
* @param v the v value. This is only passed in directly for GoQuorum private transactions
|
||||
* (v=37|38). For all other transactions, the v value is derived from the signature. If v is
|
||||
* provided here, the chain id must be empty.
|
||||
* <p>The {@code to} will be an {@code Optional.empty()} for a contract creation transaction;
|
||||
* otherwise it should contain an address.
|
||||
* <p>The {@code chainId} must be greater than 0 to be applied to a specific chain; otherwise
|
||||
@@ -168,12 +159,7 @@ public class Transaction
|
||||
final Optional<List<AccessListEntry>> maybeAccessList,
|
||||
final Address sender,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Optional<BigInteger> v,
|
||||
final Optional<List<Hash>> versionedHashes) {
|
||||
if (v.isPresent() && chainId.isPresent()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("chainId '%s' and v '%s' cannot both be provided", chainId.get(), v.get()));
|
||||
}
|
||||
|
||||
if (transactionType.requiresChainId()) {
|
||||
checkArgument(
|
||||
@@ -218,7 +204,6 @@ public class Transaction
|
||||
this.maybeAccessList = maybeAccessList;
|
||||
this.sender = sender;
|
||||
this.chainId = chainId;
|
||||
this.v = v;
|
||||
this.versionedHashes = versionedHashes;
|
||||
|
||||
if (isUpfrontGasCostTooHigh()) {
|
||||
@@ -239,7 +224,6 @@ public class Transaction
|
||||
final Bytes payload,
|
||||
final Address sender,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Optional<BigInteger> v,
|
||||
final Optional<List<Hash>> versionedHashes) {
|
||||
this(
|
||||
TransactionType.FRONTIER,
|
||||
@@ -256,7 +240,6 @@ public class Transaction
|
||||
Optional.empty(),
|
||||
sender,
|
||||
chainId,
|
||||
v,
|
||||
versionedHashes);
|
||||
}
|
||||
|
||||
@@ -269,7 +252,6 @@ public class Transaction
|
||||
final SECPSignature signature,
|
||||
final Bytes payload,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Optional<BigInteger> v,
|
||||
final Optional<List<Hash>> versionedHashes) {
|
||||
this(
|
||||
TransactionType.FRONTIER,
|
||||
@@ -286,7 +268,6 @@ public class Transaction
|
||||
Optional.empty(),
|
||||
null,
|
||||
chainId,
|
||||
v,
|
||||
versionedHashes);
|
||||
}
|
||||
|
||||
@@ -331,54 +312,6 @@ public class Transaction
|
||||
payload,
|
||||
sender,
|
||||
chainId,
|
||||
Optional.empty(),
|
||||
versionedHashes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a transaction instance.
|
||||
*
|
||||
* @param nonce the nonce
|
||||
* @param gasPrice the gas price
|
||||
* @param gasLimit the gas limit
|
||||
* @param to the transaction recipient
|
||||
* @param value the value being transferred to the recipient
|
||||
* @param signature the signature
|
||||
* @param payload the payload
|
||||
* @param sender the transaction sender
|
||||
* @param chainId the chain id to apply the transaction to
|
||||
* @param v the v value (only passed in directly for GoQuorum private transactions)
|
||||
* <p>The {@code to} will be an {@code Optional.empty()} for a contract creation transaction;
|
||||
* otherwise it should contain an address.
|
||||
* <p>The {@code chainId} must be greater than 0 to be applied to a specific chain; otherwise
|
||||
* it will default to any chain.
|
||||
*/
|
||||
public Transaction(
|
||||
final long nonce,
|
||||
final Wei gasPrice,
|
||||
final long gasLimit,
|
||||
final Optional<Address> to,
|
||||
final Wei value,
|
||||
final SECPSignature signature,
|
||||
final Bytes payload,
|
||||
final Address sender,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Optional<BigInteger> v,
|
||||
final Optional<List<Hash>> versionedHashes) {
|
||||
this(
|
||||
nonce,
|
||||
Optional.of(gasPrice),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
gasLimit,
|
||||
to,
|
||||
value,
|
||||
signature,
|
||||
payload,
|
||||
sender,
|
||||
chainId,
|
||||
v,
|
||||
versionedHashes);
|
||||
}
|
||||
|
||||
@@ -638,9 +571,6 @@ public class Transaction
|
||||
|
||||
@Override
|
||||
public BigInteger getV() {
|
||||
if (this.v.isPresent()) {
|
||||
return this.v.get();
|
||||
}
|
||||
|
||||
final BigInteger recId = BigInteger.valueOf(signature.getRecId());
|
||||
|
||||
@@ -813,16 +743,7 @@ public class Transaction
|
||||
* @return true if GoQuorum private transaction, false otherwise
|
||||
*/
|
||||
public boolean isGoQuorumPrivateTransaction(final boolean goQuorumCompatibilityMode) {
|
||||
if (!goQuorumCompatibilityMode) {
|
||||
return false;
|
||||
}
|
||||
if (chainId.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
if (!v.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
return GoQuorumPrivateTransactionDetector.isGoQuorumPrivateTransactionV(v.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1073,8 +994,7 @@ public class Transaction
|
||||
value,
|
||||
payload,
|
||||
signature,
|
||||
chainId,
|
||||
v);
|
||||
chainId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1102,7 +1022,6 @@ public class Transaction
|
||||
sb.append("value=").append(getValue()).append(", ");
|
||||
sb.append("sig=").append(getSignature()).append(", ");
|
||||
if (chainId.isPresent()) sb.append("chainId=").append(getChainId().get()).append(", ");
|
||||
if (v.isPresent()) sb.append("v=").append(v.get()).append(", ");
|
||||
sb.append("payload=").append(getPayload());
|
||||
if (transactionType.equals(TransactionType.ACCESS_LIST)) {
|
||||
sb.append(", ").append("accessList=").append(maybeAccessList);
|
||||
@@ -1281,7 +1200,6 @@ public class Transaction
|
||||
accessList,
|
||||
sender,
|
||||
chainId,
|
||||
v,
|
||||
Optional.ofNullable(versionedHashes));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,12 @@
|
||||
package org.hyperledger.besu.ethereum.core.encoding;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MIN;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_BASE;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_MIN;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE_PLUS_1;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.TWO;
|
||||
|
||||
import org.hyperledger.besu.config.GoQuorumOptions;
|
||||
import org.hyperledger.besu.crypto.SECPSignature;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||
@@ -31,7 +29,6 @@ import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.transaction.GoQuorumPrivateTransactionDetector;
|
||||
import org.hyperledger.besu.evm.AccessListEntry;
|
||||
import org.hyperledger.besu.plugin.data.TransactionType;
|
||||
|
||||
@@ -61,13 +58,8 @@ public class TransactionDecoder {
|
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
|
||||
|
||||
public static Transaction decodeForWire(final RLPInput rlpInput) {
|
||||
return decodeForWire(rlpInput, GoQuorumOptions.getGoQuorumCompatibilityMode());
|
||||
}
|
||||
|
||||
public static Transaction decodeForWire(
|
||||
final RLPInput rlpInput, final boolean goQuorumCompatibilityMode) {
|
||||
if (rlpInput.nextIsList()) {
|
||||
return decodeFrontier(rlpInput, goQuorumCompatibilityMode);
|
||||
return decodeFrontier(rlpInput);
|
||||
} else {
|
||||
final Bytes typedTransactionBytes = rlpInput.readBytes();
|
||||
final TransactionType transactionType =
|
||||
@@ -77,16 +69,11 @@ public class TransactionDecoder {
|
||||
}
|
||||
|
||||
public static Transaction decodeOpaqueBytes(final Bytes input) {
|
||||
return decodeOpaqueBytes(input, GoQuorumOptions.getGoQuorumCompatibilityMode());
|
||||
}
|
||||
|
||||
public static Transaction decodeOpaqueBytes(
|
||||
final Bytes input, final boolean goQuorumCompatibilityMode) {
|
||||
final TransactionType transactionType;
|
||||
try {
|
||||
transactionType = TransactionType.of(input.get(0));
|
||||
} catch (final IllegalArgumentException __) {
|
||||
return decodeForWire(RLP.input(input), goQuorumCompatibilityMode);
|
||||
return decodeForWire(RLP.input(input));
|
||||
}
|
||||
return getDecoder(transactionType).decode(RLP.input(input.slice(1)));
|
||||
}
|
||||
@@ -98,7 +85,7 @@ public class TransactionDecoder {
|
||||
transactionType);
|
||||
}
|
||||
|
||||
static Transaction decodeFrontier(final RLPInput input, final boolean goQuorumCompatibilityMode) {
|
||||
static Transaction decodeFrontier(final RLPInput input) {
|
||||
input.enterList();
|
||||
final Transaction.Builder builder =
|
||||
Transaction.builder()
|
||||
@@ -113,11 +100,7 @@ public class TransactionDecoder {
|
||||
final BigInteger v = input.readBigIntegerScalar();
|
||||
final byte recId;
|
||||
Optional<BigInteger> chainId = Optional.empty();
|
||||
if (goQuorumCompatibilityMode
|
||||
&& GoQuorumPrivateTransactionDetector.isGoQuorumPrivateTransactionV(v)) {
|
||||
builder.v(v);
|
||||
recId = v.subtract(GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MIN).byteValueExact();
|
||||
} else if (v.equals(REPLAY_UNPROTECTED_V_BASE) || v.equals(REPLAY_UNPROTECTED_V_BASE_PLUS_1)) {
|
||||
if (v.equals(REPLAY_UNPROTECTED_V_BASE) || v.equals(REPLAY_UNPROTECTED_V_BASE_PLUS_1)) {
|
||||
recId = v.subtract(REPLAY_UNPROTECTED_V_BASE).byteValueExact();
|
||||
} else if (v.compareTo(REPLAY_PROTECTED_V_MIN) > 0) {
|
||||
chainId = Optional.of(v.subtract(REPLAY_PROTECTED_V_BASE).divide(TWO));
|
||||
|
||||
@@ -37,7 +37,6 @@ public class FixedDifficultyProtocolSchedule {
|
||||
builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config))),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
config.isQuorum(),
|
||||
evmConfiguration)
|
||||
.createProtocolSchedule();
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import org.hyperledger.besu.ethereum.BlockProcessingOutputs;
|
||||
import org.hyperledger.besu.ethereum.BlockProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GoQuorumBlockProcessingResult extends BlockProcessingResult {
|
||||
|
||||
public final Optional<BlockProcessingOutputs> privateYield;
|
||||
|
||||
public GoQuorumBlockProcessingResult(
|
||||
final BlockProcessingOutputs mainnetYield, final BlockProcessingOutputs privateYield) {
|
||||
super(Optional.of(mainnetYield));
|
||||
this.privateYield = Optional.ofNullable(privateYield);
|
||||
}
|
||||
|
||||
public List<TransactionReceipt> getPrivateReceipts() {
|
||||
if (privateYield.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return privateYield.get().getReceipts();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.enclave.EnclaveClientException;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.enclave.types.GoQuorumReceiveResponse;
|
||||
import org.hyperledger.besu.ethereum.BlockProcessingOutputs;
|
||||
import org.hyperledger.besu.ethereum.BlockProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
|
||||
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
|
||||
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
|
||||
import org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateWorldStateUpdater;
|
||||
import org.hyperledger.besu.evm.account.EvmAccount;
|
||||
import org.hyperledger.besu.evm.log.LogsBloomFilter;
|
||||
import org.hyperledger.besu.evm.tracing.OperationTracer;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoQuorumBlockProcessor extends MainnetBlockProcessor {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GoQuorumBlockProcessor.class);
|
||||
|
||||
private final GoQuorumEnclave goQuorumEnclave;
|
||||
private final GoQuorumPrivateStorage goQuorumPrivateStorage;
|
||||
|
||||
public GoQuorumBlockProcessor(
|
||||
final MainnetTransactionProcessor transactionProcessor,
|
||||
final TransactionReceiptFactory transactionReceiptFactory,
|
||||
final Wei blockReward,
|
||||
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
|
||||
final boolean skipZeroBlockRewards,
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters,
|
||||
final HeaderBasedProtocolSchedule protocolSchedule) {
|
||||
super(
|
||||
transactionProcessor,
|
||||
transactionReceiptFactory,
|
||||
blockReward,
|
||||
miningBeneficiaryCalculator,
|
||||
skipZeroBlockRewards,
|
||||
Optional.empty(),
|
||||
protocolSchedule);
|
||||
|
||||
this.goQuorumEnclave = goQuorumPrivacyParameters.orElseThrow().enclave();
|
||||
this.goQuorumPrivateStorage = goQuorumPrivacyParameters.orElseThrow().privateStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockProcessingResult processBlock(
|
||||
final Blockchain blockchain,
|
||||
final MutableWorldState publicWorldState,
|
||||
final MutableWorldState privateWorldState,
|
||||
final Block block) {
|
||||
final BlockHeader blockHeader = block.getHeader();
|
||||
final List<Transaction> transactions = block.getBody().getTransactions();
|
||||
final List<BlockHeader> ommers = block.getBody().getOmmers();
|
||||
|
||||
final List<TransactionReceipt> publicTxReceipts = new ArrayList<>();
|
||||
final List<TransactionReceipt> privateTxReceipts = new ArrayList<>();
|
||||
long currentGasUsed = 0;
|
||||
|
||||
final GoQuorumPrivateStorage.Updater privateStorageUpdater = goQuorumPrivateStorage.updater();
|
||||
|
||||
for (final Transaction transaction : transactions) {
|
||||
if (!hasAvailableBlockBudget(blockHeader, transaction, currentGasUsed)) {
|
||||
return new BlockProcessingResult(Optional.empty(), "insufficient gas");
|
||||
}
|
||||
|
||||
final WorldUpdater publicWorldStateUpdater = publicWorldState.updater();
|
||||
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(blockHeader, blockchain);
|
||||
final Address miningBeneficiary =
|
||||
miningBeneficiaryCalculator.calculateBeneficiary(blockHeader);
|
||||
|
||||
WorldUpdater effectiveWorldUpdater = null;
|
||||
Transaction effectiveTransaction;
|
||||
|
||||
final boolean isGoQuorumPrivateTransaction =
|
||||
transaction.isGoQuorumPrivateTransaction(
|
||||
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());
|
||||
|
||||
if (isGoQuorumPrivateTransaction) { // private transaction
|
||||
try {
|
||||
effectiveTransaction = retrievePrivateTransactionFromEnclave(transaction);
|
||||
|
||||
effectiveWorldUpdater =
|
||||
new GoQuorumMutablePrivateWorldStateUpdater(
|
||||
publicWorldStateUpdater, privateWorldState.updater());
|
||||
|
||||
} catch (final EnclaveClientException e) { // private transaction but not party to it
|
||||
// We do not have to execute anything, but we still need to validate the transaction
|
||||
effectiveTransaction = null;
|
||||
final ValidationResult<TransactionInvalidReason> validationResult =
|
||||
validateTransaction(blockHeader, transaction, publicWorldStateUpdater);
|
||||
if (!validationResult.isValid()) {
|
||||
return new BlockProcessingResult(Optional.empty(), e);
|
||||
}
|
||||
}
|
||||
} else { // public Transaction
|
||||
effectiveWorldUpdater = publicWorldState.updater();
|
||||
|
||||
effectiveTransaction = transaction;
|
||||
}
|
||||
|
||||
if (effectiveTransaction != null) { // public tx, or private tx that we are party to
|
||||
final TransactionProcessingResult result =
|
||||
transactionProcessor.processTransaction(
|
||||
blockchain,
|
||||
effectiveWorldUpdater,
|
||||
blockHeader,
|
||||
effectiveTransaction,
|
||||
miningBeneficiary,
|
||||
OperationTracer.NO_TRACING,
|
||||
blockHashLookup,
|
||||
true,
|
||||
TransactionValidationParams.processingBlock(),
|
||||
null,
|
||||
Wei.ZERO);
|
||||
|
||||
if (result.isInvalid()) {
|
||||
String errorMessage =
|
||||
MessageFormat.format(
|
||||
"Block processing error: transaction invalid '{}'. Block {} Transaction {}",
|
||||
result.getValidationResult().getErrorMessage(),
|
||||
blockHeader.getHash().toHexString(),
|
||||
transaction.getHash().toHexString());
|
||||
LOG.info(errorMessage);
|
||||
return new BlockProcessingResult(Optional.empty(), errorMessage);
|
||||
}
|
||||
|
||||
if (isGoQuorumPrivateTransaction) { // private transaction we are party to
|
||||
publicTxReceipts.add(
|
||||
transactionReceiptFactory.create(
|
||||
transaction.getType(),
|
||||
publicResultForWhenWeHaveAPrivateTransaction(transaction),
|
||||
publicWorldState,
|
||||
currentGasUsed));
|
||||
privateTxReceipts.add(
|
||||
transactionReceiptFactory.create(
|
||||
transaction.getType(), result, privateWorldState, currentGasUsed));
|
||||
publicWorldStateUpdater
|
||||
.getOrCreate(effectiveTransaction.getSender())
|
||||
.getMutable()
|
||||
.incrementNonce();
|
||||
effectiveWorldUpdater.commit();
|
||||
} else { // public transaction
|
||||
final long gasUsed = transaction.getGasLimit() - result.getGasRemaining();
|
||||
currentGasUsed += gasUsed;
|
||||
|
||||
publicTxReceipts.add(
|
||||
transactionReceiptFactory.create(
|
||||
transaction.getType(), result, publicWorldState, currentGasUsed));
|
||||
privateTxReceipts.add(null);
|
||||
effectiveWorldUpdater.commit();
|
||||
}
|
||||
} else { // private transaction we are not party to
|
||||
publicTxReceipts.add(
|
||||
transactionReceiptFactory.create(
|
||||
transaction.getType(),
|
||||
publicResultForWhenWeHaveAPrivateTransaction(transaction),
|
||||
publicWorldState,
|
||||
currentGasUsed));
|
||||
privateTxReceipts.add(null);
|
||||
publicWorldStateUpdater.getOrCreate(transaction.getSender()).getMutable().incrementNonce();
|
||||
}
|
||||
|
||||
publicWorldStateUpdater.commit();
|
||||
}
|
||||
|
||||
if (!rewardCoinbase(publicWorldState, blockHeader, ommers, skipZeroBlockRewards)) {
|
||||
// no need to log, rewardCoinbase logs the error.
|
||||
return new BlockProcessingResult(Optional.empty(), "ommer too old");
|
||||
}
|
||||
|
||||
// create the bloom for the private transactions in the block and store it
|
||||
final LogsBloomFilter.Builder privateBloomBuilder = LogsBloomFilter.builder();
|
||||
privateTxReceipts.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(pr -> privateBloomBuilder.insertFilter(pr.getBloomFilter()));
|
||||
blockHeader.setPrivateLogsBloom(privateBloomBuilder.build());
|
||||
|
||||
publicWorldState.persist(blockHeader);
|
||||
privateWorldState.persist(null);
|
||||
|
||||
privateStorageUpdater.putPrivateStateRootHashMapping(
|
||||
publicWorldState.rootHash(), privateWorldState.rootHash());
|
||||
privateStorageUpdater.commit();
|
||||
|
||||
BlockProcessingOutputs mainnetYield =
|
||||
new BlockProcessingOutputs(publicWorldState, publicTxReceipts);
|
||||
BlockProcessingOutputs privateYield =
|
||||
new BlockProcessingOutputs(privateWorldState, privateTxReceipts);
|
||||
return new GoQuorumBlockProcessingResult(mainnetYield, privateYield);
|
||||
}
|
||||
|
||||
private ValidationResult<TransactionInvalidReason> validateTransaction(
|
||||
final BlockHeader blockHeader,
|
||||
final Transaction transaction,
|
||||
final WorldUpdater publicWorldStateUpdater) {
|
||||
final MainnetTransactionValidator transactionValidator =
|
||||
transactionProcessor.getTransactionValidator();
|
||||
final TransactionValidationParams transactionValidationParams =
|
||||
TransactionValidationParams.processingBlock();
|
||||
ValidationResult<TransactionInvalidReason> validationResult =
|
||||
transactionValidator.validate(
|
||||
transaction, blockHeader.getBaseFee(), transactionValidationParams);
|
||||
if (!validationResult.isValid()) {
|
||||
LOG.warn(
|
||||
"Invalid transaction: {}. Block {} Transaction {}",
|
||||
validationResult.getErrorMessage(),
|
||||
blockHeader.getHash().toHexString(),
|
||||
transaction.getHash().toHexString());
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
final Address senderAddress = transaction.getSender();
|
||||
|
||||
final EvmAccount sender = publicWorldStateUpdater.getOrCreate(senderAddress);
|
||||
validationResult =
|
||||
transactionValidator.validateForSender(transaction, sender, transactionValidationParams);
|
||||
if (!validationResult.isValid()) {
|
||||
LOG.warn(
|
||||
"Invalid transaction: {}. Block {} Transaction {}",
|
||||
validationResult.getErrorMessage(),
|
||||
blockHeader.getHash().toHexString(),
|
||||
transaction.getHash().toHexString());
|
||||
return validationResult;
|
||||
}
|
||||
return ValidationResult.valid();
|
||||
}
|
||||
|
||||
private TransactionProcessingResult publicResultForWhenWeHaveAPrivateTransaction(
|
||||
final Transaction transaction) {
|
||||
return TransactionProcessingResult.successful(
|
||||
Collections.emptyList(),
|
||||
0,
|
||||
transaction.getGasLimit(),
|
||||
Bytes.EMPTY,
|
||||
ValidationResult.valid());
|
||||
}
|
||||
|
||||
private Transaction retrievePrivateTransactionFromEnclave(final Transaction transaction) {
|
||||
final GoQuorumReceiveResponse receive =
|
||||
goQuorumEnclave.receive(transaction.getPayload().toBase64String());
|
||||
|
||||
final Bytes privatePayload = Bytes.wrap(receive.getPayload());
|
||||
|
||||
return new Transaction(
|
||||
transaction.getNonce(),
|
||||
transaction.getGasPrice().get(),
|
||||
transaction.getGasLimit(),
|
||||
transaction.getTo(),
|
||||
transaction.getValue(),
|
||||
transaction.getSignature(),
|
||||
privatePayload,
|
||||
transaction
|
||||
.getSender(), // at this point we are checking the signature of the public transaction
|
||||
// and we are setting the sender for the private transaction, so the
|
||||
// signature of the private transaction will not (and should not) be
|
||||
// checked again.
|
||||
transaction.getChainId(),
|
||||
Optional.of(transaction.getV()),
|
||||
Optional.empty());
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStateUtil.getPrivateWorldState;
|
||||
|
||||
import org.hyperledger.besu.ethereum.BlockProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.MainnetBlockValidator;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockBodyValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.BlockProcessor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class GoQuorumBlockValidator extends MainnetBlockValidator {
|
||||
|
||||
private final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters;
|
||||
|
||||
public GoQuorumBlockValidator(
|
||||
final BlockHeaderValidator blockHeaderValidator,
|
||||
final BlockBodyValidator blockBodyValidator,
|
||||
final BlockProcessor blockProcessor,
|
||||
final BadBlockManager badBlockManager,
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters) {
|
||||
super(blockHeaderValidator, blockBodyValidator, blockProcessor, badBlockManager);
|
||||
|
||||
this.goQuorumPrivacyParameters = goQuorumPrivacyParameters;
|
||||
|
||||
if (!(blockProcessor instanceof GoQuorumBlockProcessor)) {
|
||||
throw new IllegalStateException(
|
||||
"GoQuorumBlockValidator requires an instance of GoQuorumBlockProcessor");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockProcessingResult processBlock(
|
||||
final ProtocolContext context, final MutableWorldState worldState, final Block block) {
|
||||
final MutableWorldState privateWorldState =
|
||||
getPrivateWorldState(goQuorumPrivacyParameters, worldState.rootHash(), block.getHash());
|
||||
|
||||
return ((GoQuorumBlockProcessor) blockProcessor)
|
||||
.processBlock(context.getBlockchain(), worldState, privateWorldState, block);
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
|
||||
public class GoQuorumPrivateKeyValueStorage implements GoQuorumPrivateStorage {
|
||||
|
||||
private static final Bytes PRIVATE_STATEROOT_SUFFIX = Bytes.of("PRIVSTATEROOT".getBytes(UTF_8));
|
||||
|
||||
private final KeyValueStorage keyValueStorage;
|
||||
|
||||
public GoQuorumPrivateKeyValueStorage(final KeyValueStorage keyValueStorage) {
|
||||
this.keyValueStorage = keyValueStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Hash> getPrivateStateRootHash(final Hash publicStateRootHash) {
|
||||
return get(publicStateRootHash, PRIVATE_STATEROOT_SUFFIX).map(Bytes32::wrap).map(Hash::wrap);
|
||||
}
|
||||
|
||||
private Optional<Bytes> get(final Bytes key, final Bytes keySuffix) {
|
||||
return keyValueStorage.get(Bytes.concatenate(key, keySuffix).toArrayUnsafe()).map(Bytes::wrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoQuorumPrivateStorage.Updater updater() {
|
||||
return new Updater(keyValueStorage.startTransaction());
|
||||
}
|
||||
|
||||
public static class Updater implements GoQuorumPrivateStorage.Updater {
|
||||
|
||||
private final KeyValueStorageTransaction transaction;
|
||||
|
||||
private Updater(final KeyValueStorageTransaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoQuorumPrivateStorage.Updater putPrivateStateRootHashMapping(
|
||||
final Hash publicStateRootHash, final Hash privateStateRootHash) {
|
||||
set(publicStateRootHash, PRIVATE_STATEROOT_SUFFIX, privateStateRootHash);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
transaction.rollback();
|
||||
}
|
||||
|
||||
private void set(final Bytes key, final Bytes keySuffix, final Bytes value) {
|
||||
transaction.put(Bytes.concatenate(key, keySuffix).toArrayUnsafe(), value.toArrayUnsafe());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GoQuorumPrivateStateUtil {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GoQuorumPrivateStateUtil.class);
|
||||
|
||||
public static MutableWorldState getPrivateWorldStateAtBlock(
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters,
|
||||
final BlockHeader header) {
|
||||
return getPrivateWorldState(goQuorumPrivacyParameters, header.getStateRoot(), header.getHash());
|
||||
}
|
||||
|
||||
public static MutableWorldState getPrivateWorldState(
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters,
|
||||
final Hash worldStateRootHash,
|
||||
final Hash publicBlockHash) {
|
||||
final GoQuorumPrivateStorage goQuorumPrivateStorage =
|
||||
goQuorumPrivacyParameters.orElseThrow().privateStorage();
|
||||
final WorldStateArchive goQuorumWorldStateArchive =
|
||||
goQuorumPrivacyParameters.orElseThrow().worldStateArchive();
|
||||
|
||||
final Hash privateStateRootHash =
|
||||
goQuorumPrivateStorage
|
||||
.getPrivateStateRootHash(worldStateRootHash)
|
||||
.orElse(Hash.EMPTY_TRIE_HASH);
|
||||
|
||||
final Optional<MutableWorldState> maybePrivateWorldState =
|
||||
goQuorumWorldStateArchive.getMutable(privateStateRootHash, publicBlockHash);
|
||||
if (maybePrivateWorldState.isEmpty()) {
|
||||
LOG.debug(
|
||||
"Private world state not available for public world state root hash {}, public block hash {}",
|
||||
worldStateRootHash,
|
||||
publicBlockHash);
|
||||
|
||||
/*
|
||||
This should never happen because privateStateRootResolver will either return a matching
|
||||
private world state root hash, or the hash for an empty world state (first private tx ever).
|
||||
*/
|
||||
throw new IllegalStateException(
|
||||
"Private world state not available for public world state root hash " + publicBlockHash);
|
||||
}
|
||||
return maybePrivateWorldState.get();
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface GoQuorumPrivateStorage {
|
||||
|
||||
Optional<Hash> getPrivateStateRootHash(final Hash publicStateRootHash);
|
||||
|
||||
Updater updater();
|
||||
|
||||
interface Updater {
|
||||
|
||||
Updater putPrivateStateRootHashMapping(
|
||||
final Hash publicStateRootHash, final Hash privateStateRootHash);
|
||||
|
||||
void commit();
|
||||
|
||||
void rollback();
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,6 @@ public abstract class AbstractProtocolScheduleBuilder {
|
||||
protected final PrivacyParameters privacyParameters;
|
||||
protected final boolean isRevertReasonEnabled;
|
||||
protected final BadBlockManager badBlockManager = new BadBlockManager();
|
||||
protected final boolean quorumCompatibilityMode;
|
||||
protected final EvmConfiguration evmConfiguration;
|
||||
|
||||
protected AbstractProtocolScheduleBuilder(
|
||||
@@ -47,13 +46,11 @@ public abstract class AbstractProtocolScheduleBuilder {
|
||||
final ProtocolSpecAdapters protocolSpecAdapters,
|
||||
final PrivacyParameters privacyParameters,
|
||||
final boolean isRevertReasonEnabled,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
this.config = config;
|
||||
this.protocolSpecAdapters = protocolSpecAdapters;
|
||||
this.privacyParameters = privacyParameters;
|
||||
this.isRevertReasonEnabled = isRevertReasonEnabled;
|
||||
this.quorumCompatibilityMode = quorumCompatibilityMode;
|
||||
this.evmConfiguration = evmConfiguration;
|
||||
}
|
||||
|
||||
@@ -66,7 +63,6 @@ public abstract class AbstractProtocolScheduleBuilder {
|
||||
config.getContractSizeLimit(),
|
||||
config.getEvmStackSize(),
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
config.getEcip1017EraRounds(),
|
||||
evmConfiguration);
|
||||
|
||||
|
||||
@@ -57,10 +57,9 @@ public class ClassicProtocolSpecs {
|
||||
public static ProtocolSpecBuilder classicRecoveryInitDefinition(
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return MainnetProtocolSpecs.homesteadDefinition(
|
||||
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode, evmConfiguration)
|
||||
contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.blockHeaderValidatorBuilder(
|
||||
feeMarket -> MainnetBlockHeaderValidator.createClassicValidator())
|
||||
.name("ClassicRecoveryInit");
|
||||
@@ -70,15 +69,13 @@ public class ClassicProtocolSpecs {
|
||||
final Optional<BigInteger> chainId,
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return MainnetProtocolSpecs.homesteadDefinition(
|
||||
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode, evmConfiguration)
|
||||
contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.gasCalculator(TangerineWhistleGasCalculator::new)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, gasLimitCalculator, true, chainId, quorumCompatibilityMode))
|
||||
new MainnetTransactionValidator(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
.name("ClassicTangerineWhistle");
|
||||
}
|
||||
|
||||
@@ -86,14 +83,9 @@ public class ClassicProtocolSpecs {
|
||||
final Optional<BigInteger> chainId,
|
||||
final OptionalInt ignoredConfigContractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return tangerineWhistleDefinition(
|
||||
chainId,
|
||||
OptionalInt.empty(),
|
||||
configStackSizeLimit,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, OptionalInt.empty(), configStackSizeLimit, evmConfiguration)
|
||||
.gasCalculator(DieHardGasCalculator::new)
|
||||
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_PAUSED)
|
||||
.name("DieHard");
|
||||
@@ -104,14 +96,8 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return dieHardDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
return dieHardDefinition(chainId, contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.blockReward(MAX_BLOCK_REWARD)
|
||||
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_DELAYED)
|
||||
.blockProcessorBuilder(
|
||||
@@ -120,7 +106,6 @@ public class ClassicProtocolSpecs {
|
||||
blockReward,
|
||||
miningBeneficiaryCalculator,
|
||||
skipZeroBlockRewards,
|
||||
goQuorumPrivacyParameters,
|
||||
protocolSchedule) ->
|
||||
new ClassicBlockProcessor(
|
||||
transactionProcessor,
|
||||
@@ -138,20 +123,13 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return gothamDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, contractSizeLimit, configStackSizeLimit, ecip1017EraRounds, evmConfiguration)
|
||||
.difficultyCalculator(ClassicDifficultyCalculators.DIFFICULTY_BOMB_REMOVED)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, gasLimitCalculator, true, chainId, quorumCompatibilityMode))
|
||||
new MainnetTransactionValidator(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
.name("DefuseDifficultyBomb");
|
||||
}
|
||||
|
||||
@@ -161,7 +139,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int contractSizeLimit =
|
||||
configContractSizeLimit.orElse(MainnetProtocolSpecs.SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
|
||||
@@ -171,7 +148,6 @@ public class ClassicProtocolSpecs {
|
||||
configContractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.evmBuilder(MainnetEVMs::byzantium)
|
||||
.evmConfiguration(evmConfiguration)
|
||||
@@ -216,7 +192,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return atlantisDefinition(
|
||||
chainId,
|
||||
@@ -224,7 +199,6 @@ public class ClassicProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.evmBuilder(MainnetEVMs::constantinople)
|
||||
.gasCalculator(PetersburgGasCalculator::new)
|
||||
@@ -239,7 +213,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return aghartaDefinition(
|
||||
chainId,
|
||||
@@ -247,7 +220,6 @@ public class ClassicProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.gasCalculator(IstanbulGasCalculator::new)
|
||||
.evmBuilder(
|
||||
@@ -264,7 +236,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return phoenixDefinition(
|
||||
chainId,
|
||||
@@ -272,7 +243,6 @@ public class ClassicProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.blockHeaderValidatorBuilder(
|
||||
feeMarket ->
|
||||
@@ -311,7 +281,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return thanosDefinition(
|
||||
chainId,
|
||||
@@ -319,7 +288,6 @@ public class ClassicProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.blockHeaderValidatorBuilder(
|
||||
feeMarket ->
|
||||
@@ -341,7 +309,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return thanosDefinition(
|
||||
chainId,
|
||||
@@ -349,7 +316,6 @@ public class ClassicProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.gasCalculator(BerlinGasCalculator::new)
|
||||
.transactionValidatorBuilder(
|
||||
@@ -359,8 +325,7 @@ public class ClassicProtocolSpecs {
|
||||
gasLimitCalculator,
|
||||
true,
|
||||
chainId,
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),
|
||||
quorumCompatibilityMode))
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST)))
|
||||
.transactionReceiptFactory(
|
||||
enableRevertReason
|
||||
? MainnetProtocolSpecs::berlinTransactionReceiptFactoryWithReasonEnabled
|
||||
@@ -374,7 +339,6 @@ public class ClassicProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int contractSizeLimit =
|
||||
configContractSizeLimit.orElse(MainnetProtocolSpecs.SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
|
||||
@@ -384,7 +348,6 @@ public class ClassicProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.gasCalculator(LondonGasCalculator::new)
|
||||
.contractCreationProcessorBuilder(
|
||||
|
||||
@@ -17,13 +17,11 @@ package org.hyperledger.besu.ethereum.mainnet;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -38,7 +36,6 @@ public class MainnetBlockProcessor extends AbstractBlockProcessor {
|
||||
final Wei blockReward,
|
||||
final MiningBeneficiaryCalculator miningBeneficiaryCalculator,
|
||||
final boolean skipZeroBlockRewards,
|
||||
final Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters,
|
||||
final HeaderBasedProtocolSchedule protocolSchedule) {
|
||||
super(
|
||||
transactionProcessor,
|
||||
|
||||
@@ -53,7 +53,6 @@ public class MainnetProtocolSchedule {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
config.isQuorum(),
|
||||
evmConfiguration)
|
||||
.createProtocolSchedule();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ public class MainnetProtocolSpecFactory {
|
||||
private final OptionalInt contractSizeLimit;
|
||||
private final OptionalInt evmStackSize;
|
||||
private final boolean isRevertReasonEnabled;
|
||||
private final boolean quorumCompatibilityMode;
|
||||
private final OptionalLong ecip1017EraRounds;
|
||||
private final EvmConfiguration evmConfiguration;
|
||||
|
||||
@@ -37,106 +36,74 @@ public class MainnetProtocolSpecFactory {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt evmStackSize,
|
||||
final boolean isRevertReasonEnabled,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final OptionalLong ecip1017EraRounds,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
this.chainId = chainId;
|
||||
this.contractSizeLimit = contractSizeLimit;
|
||||
this.evmStackSize = evmStackSize;
|
||||
this.isRevertReasonEnabled = isRevertReasonEnabled;
|
||||
this.quorumCompatibilityMode = quorumCompatibilityMode;
|
||||
this.ecip1017EraRounds = ecip1017EraRounds;
|
||||
this.evmConfiguration = evmConfiguration;
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder frontierDefinition() {
|
||||
return MainnetProtocolSpecs.frontierDefinition(
|
||||
contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder homesteadDefinition() {
|
||||
return MainnetProtocolSpecs.homesteadDefinition(
|
||||
contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder daoRecoveryInitDefinition() {
|
||||
return MainnetProtocolSpecs.daoRecoveryInitDefinition(
|
||||
contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder daoRecoveryTransitionDefinition() {
|
||||
return MainnetProtocolSpecs.daoRecoveryTransitionDefinition(
|
||||
contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder tangerineWhistleDefinition() {
|
||||
return MainnetProtocolSpecs.tangerineWhistleDefinition(
|
||||
contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder spuriousDragonDefinition() {
|
||||
return MainnetProtocolSpecs.spuriousDragonDefinition(
|
||||
chainId, contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder byzantiumDefinition() {
|
||||
return MainnetProtocolSpecs.byzantiumDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder constantinopleDefinition() {
|
||||
return MainnetProtocolSpecs.constantinopleDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder petersburgDefinition() {
|
||||
return MainnetProtocolSpecs.petersburgDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder istanbulDefinition() {
|
||||
return MainnetProtocolSpecs.istanbulDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder muirGlacierDefinition() {
|
||||
return MainnetProtocolSpecs.muirGlacierDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder berlinDefinition() {
|
||||
return MainnetProtocolSpecs.berlinDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, isRevertReasonEnabled, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder londonDefinition(final GenesisConfigOptions genesisConfigOptions) {
|
||||
@@ -146,7 +113,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -158,7 +124,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -170,7 +135,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -181,7 +145,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -192,7 +155,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -203,7 +165,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -225,7 +186,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -247,7 +207,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -256,27 +215,17 @@ public class MainnetProtocolSpecFactory {
|
||||
// Classic Protocol Specs
|
||||
public ProtocolSpecBuilder dieHardDefinition() {
|
||||
return ClassicProtocolSpecs.dieHardDefinition(
|
||||
chainId, contractSizeLimit, evmStackSize, quorumCompatibilityMode, evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder gothamDefinition() {
|
||||
return ClassicProtocolSpecs.gothamDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, ecip1017EraRounds, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder defuseDifficultyBombDefinition() {
|
||||
return ClassicProtocolSpecs.defuseDifficultyBombDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
evmStackSize,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
chainId, contractSizeLimit, evmStackSize, ecip1017EraRounds, evmConfiguration);
|
||||
}
|
||||
|
||||
public ProtocolSpecBuilder atlantisDefinition() {
|
||||
@@ -286,7 +235,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -297,7 +245,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -308,7 +255,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -319,7 +265,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -330,7 +275,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -341,7 +285,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -352,7 +295,6 @@ public class MainnetProtocolSpecFactory {
|
||||
evmStackSize,
|
||||
isRevertReasonEnabled,
|
||||
ecip1017EraRounds,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@ import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.core.Withdrawal;
|
||||
import org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumBlockProcessor;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumBlockValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder.BlockProcessorBuilder;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder.BlockValidatorBuilder;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
@@ -106,7 +103,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
public static ProtocolSpecBuilder frontierDefinition(
|
||||
final OptionalInt configContractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean goQuorumMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
|
||||
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
|
||||
@@ -127,7 +123,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, gasLimitCalculator, false, Optional.empty(), goQuorumMode))
|
||||
gasCalculator, gasLimitCalculator, false, Optional.empty()))
|
||||
.transactionProcessorBuilder(
|
||||
(gasCalculator,
|
||||
transactionValidator,
|
||||
@@ -163,8 +159,8 @@ public abstract class MainnetProtocolSpecs {
|
||||
.transactionReceiptFactory(MainnetProtocolSpecs::frontierTransactionReceiptFactory)
|
||||
.blockReward(FRONTIER_BLOCK_REWARD)
|
||||
.skipZeroBlockRewards(false)
|
||||
.blockProcessorBuilder(MainnetProtocolSpecs.blockProcessorBuilder(goQuorumMode))
|
||||
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder(goQuorumMode))
|
||||
.blockProcessorBuilder(MainnetBlockProcessor::new)
|
||||
.blockValidatorBuilder(MainnetProtocolSpecs.blockValidatorBuilder())
|
||||
.blockImporterBuilder(MainnetBlockImporter::new)
|
||||
.blockHeaderFunctions(new MainnetBlockHeaderFunctions())
|
||||
.miningBeneficiaryCalculator(BlockHeader::getCoinbase)
|
||||
@@ -187,39 +183,18 @@ public abstract class MainnetProtocolSpecs {
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockValidatorBuilder blockValidatorBuilder(final boolean goQuorumMode) {
|
||||
if (goQuorumMode) {
|
||||
return GoQuorumBlockValidator::new;
|
||||
} else {
|
||||
return (blockHeaderValidator,
|
||||
blockBodyValidator,
|
||||
blockProcessor,
|
||||
badBlockManager,
|
||||
goQuorumPrivacyParameters) ->
|
||||
new MainnetBlockValidator(
|
||||
blockHeaderValidator, blockBodyValidator, blockProcessor, badBlockManager);
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockProcessorBuilder blockProcessorBuilder(final boolean goQuorumMode) {
|
||||
if (goQuorumMode) {
|
||||
return GoQuorumBlockProcessor::new;
|
||||
} else {
|
||||
return MainnetBlockProcessor::new;
|
||||
}
|
||||
public static BlockValidatorBuilder blockValidatorBuilder() {
|
||||
return (blockHeaderValidator, blockBodyValidator, blockProcessor, badBlockManager) ->
|
||||
new MainnetBlockValidator(
|
||||
blockHeaderValidator, blockBodyValidator, blockProcessor, badBlockManager);
|
||||
}
|
||||
|
||||
public static ProtocolSpecBuilder homesteadDefinition(
|
||||
final OptionalInt configContractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
|
||||
return frontierDefinition(
|
||||
configContractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
return frontierDefinition(configContractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.gasCalculator(HomesteadGasCalculator::new)
|
||||
.evmBuilder(MainnetEVMs::homestead)
|
||||
.contractCreationProcessorBuilder(
|
||||
@@ -233,11 +208,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
true,
|
||||
Optional.empty(),
|
||||
quorumCompatibilityMode))
|
||||
gasCalculator, gasLimitCalculator, true, Optional.empty()))
|
||||
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
|
||||
.name("Homestead");
|
||||
}
|
||||
@@ -245,10 +216,8 @@ public abstract class MainnetProtocolSpecs {
|
||||
public static ProtocolSpecBuilder daoRecoveryInitDefinition(
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return homesteadDefinition(
|
||||
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode, evmConfiguration)
|
||||
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.blockHeaderValidatorBuilder(feeMarket -> MainnetBlockHeaderValidator.createDaoValidator())
|
||||
.blockProcessorBuilder(
|
||||
(transactionProcessor,
|
||||
@@ -256,7 +225,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
blockReward,
|
||||
miningBeneficiaryCalculator,
|
||||
skipZeroBlockRewards,
|
||||
goQuorumPrivacyParameters,
|
||||
protocolSchedule) ->
|
||||
new DaoBlockProcessor(
|
||||
new MainnetBlockProcessor(
|
||||
@@ -265,7 +233,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
blockReward,
|
||||
miningBeneficiaryCalculator,
|
||||
skipZeroBlockRewards,
|
||||
Optional.empty(),
|
||||
protocolSchedule)))
|
||||
.name("DaoRecoveryInit");
|
||||
}
|
||||
@@ -273,10 +240,8 @@ public abstract class MainnetProtocolSpecs {
|
||||
public static ProtocolSpecBuilder daoRecoveryTransitionDefinition(
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return daoRecoveryInitDefinition(
|
||||
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode, evmConfiguration)
|
||||
return daoRecoveryInitDefinition(contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.blockProcessorBuilder(MainnetBlockProcessor::new)
|
||||
.name("DaoRecoveryTransition");
|
||||
}
|
||||
@@ -284,10 +249,8 @@ public abstract class MainnetProtocolSpecs {
|
||||
public static ProtocolSpecBuilder tangerineWhistleDefinition(
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return homesteadDefinition(
|
||||
contractSizeLimit, configStackSizeLimit, quorumCompatibilityMode, evmConfiguration)
|
||||
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.gasCalculator(TangerineWhistleGasCalculator::new)
|
||||
.name("TangerineWhistle");
|
||||
}
|
||||
@@ -296,14 +259,12 @@ public abstract class MainnetProtocolSpecs {
|
||||
final Optional<BigInteger> chainId,
|
||||
final OptionalInt configContractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
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, quorumCompatibilityMode, evmConfiguration)
|
||||
return tangerineWhistleDefinition(OptionalInt.empty(), configStackSizeLimit, evmConfiguration)
|
||||
.gasCalculator(SpuriousDragonGasCalculator::new)
|
||||
.skipZeroBlockRewards(true)
|
||||
.messageCallProcessorBuilder(
|
||||
@@ -323,8 +284,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, gasLimitCalculator, true, chainId, quorumCompatibilityMode))
|
||||
new MainnetTransactionValidator(gasCalculator, gasLimitCalculator, true, chainId))
|
||||
.transactionProcessorBuilder(
|
||||
(gasCalculator,
|
||||
transactionValidator,
|
||||
@@ -348,15 +308,10 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
|
||||
return spuriousDragonDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, contractSizeLimit, configStackSizeLimit, evmConfiguration)
|
||||
.gasCalculator(ByzantiumGasCalculator::new)
|
||||
.evmBuilder(MainnetEVMs::byzantium)
|
||||
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
|
||||
@@ -387,15 +342,9 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return byzantiumDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, evmConfiguration)
|
||||
.difficultyCalculator(MainnetDifficultyCalculators.CONSTANTINOPLE)
|
||||
.gasCalculator(ConstantinopleGasCalculator::new)
|
||||
.evmBuilder(MainnetEVMs::constantinople)
|
||||
@@ -408,15 +357,9 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return constantinopleDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, evmConfiguration)
|
||||
.gasCalculator(PetersburgGasCalculator::new)
|
||||
.name("Petersburg");
|
||||
}
|
||||
@@ -426,7 +369,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configContractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int contractSizeLimit =
|
||||
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
|
||||
@@ -435,7 +377,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configContractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.gasCalculator(IstanbulGasCalculator::new)
|
||||
.evmBuilder(
|
||||
@@ -460,15 +401,9 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return istanbulDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, evmConfiguration)
|
||||
.difficultyCalculator(MainnetDifficultyCalculators.MUIR_GLACIER)
|
||||
.name("MuirGlacier");
|
||||
}
|
||||
@@ -478,15 +413,9 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt contractSizeLimit,
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return muirGlacierDefinition(
|
||||
chainId,
|
||||
contractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, evmConfiguration)
|
||||
.gasCalculator(BerlinGasCalculator::new)
|
||||
.transactionValidatorBuilder(
|
||||
(gasCalculator, gasLimitCalculator) ->
|
||||
@@ -495,8 +424,7 @@ public abstract class MainnetProtocolSpecs {
|
||||
gasLimitCalculator,
|
||||
true,
|
||||
chainId,
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST),
|
||||
quorumCompatibilityMode))
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST)))
|
||||
.transactionReceiptFactory(
|
||||
enableRevertReason
|
||||
? MainnetProtocolSpecs::berlinTransactionReceiptFactoryWithReasonEnabled
|
||||
@@ -510,7 +438,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final int contractSizeLimit =
|
||||
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
|
||||
@@ -526,7 +453,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configContractSizeLimit,
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.gasCalculator(LondonGasCalculator::new)
|
||||
.gasLimitCalculator(
|
||||
@@ -543,7 +469,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
TransactionType.FRONTIER,
|
||||
TransactionType.ACCESS_LIST,
|
||||
TransactionType.EIP1559),
|
||||
quorumCompatibilityMode,
|
||||
Integer.MAX_VALUE))
|
||||
.transactionProcessorBuilder(
|
||||
(gasCalculator,
|
||||
@@ -590,7 +515,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return londonDefinition(
|
||||
chainId,
|
||||
@@ -598,7 +522,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.difficultyCalculator(MainnetDifficultyCalculators.ARROW_GLACIER)
|
||||
.name("ArrowGlacier");
|
||||
@@ -610,7 +533,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return arrowGlacierDefinition(
|
||||
chainId,
|
||||
@@ -618,7 +540,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.difficultyCalculator(MainnetDifficultyCalculators.GRAY_GLACIER)
|
||||
.name("GrayGlacier");
|
||||
@@ -630,7 +551,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
|
||||
return grayGlacierDefinition(
|
||||
@@ -639,7 +559,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.evmBuilder(
|
||||
(gasCalculator, jdCacheConfig) ->
|
||||
@@ -657,7 +576,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
|
||||
// extra variables need to support flipping the warm coinbase flag.
|
||||
@@ -674,7 +592,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
// gas calculator has new code to support EIP-3860 limit and meter initcode
|
||||
.gasCalculator(ShanghaiGasCalculator::new)
|
||||
@@ -712,7 +629,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
TransactionType.FRONTIER,
|
||||
TransactionType.ACCESS_LIST,
|
||||
TransactionType.EIP1559),
|
||||
quorumCompatibilityMode,
|
||||
SHANGHAI_INIT_CODE_SIZE_LIMIT))
|
||||
.withdrawalsProcessor(new WithdrawalsProcessor())
|
||||
.withdrawalsValidator(new WithdrawalsValidator.AllowedWithdrawals())
|
||||
@@ -725,7 +641,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
|
||||
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
|
||||
@@ -746,7 +661,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.feeMarket(cancunFeeMarket)
|
||||
// gas calculator for EIP-4844 data gas
|
||||
@@ -799,7 +713,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
TransactionType.ACCESS_LIST,
|
||||
TransactionType.EIP1559,
|
||||
TransactionType.BLOB),
|
||||
quorumCompatibilityMode,
|
||||
SHANGHAI_INIT_CODE_SIZE_LIMIT))
|
||||
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::cancun)
|
||||
.name("Cancun");
|
||||
@@ -811,7 +724,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
|
||||
return cancunDefinition(
|
||||
@@ -820,7 +732,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.evmBuilder(
|
||||
(gasCalculator, jdCacheConfig) ->
|
||||
@@ -835,7 +746,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
final OptionalInt configStackSizeLimit,
|
||||
final boolean enableRevertReason,
|
||||
final GenesisConfigOptions genesisConfigOptions,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
|
||||
return futureEipsDefinition(
|
||||
@@ -844,7 +754,6 @@ public abstract class MainnetProtocolSpecs {
|
||||
configStackSizeLimit,
|
||||
enableRevertReason,
|
||||
genesisConfigOptions,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration)
|
||||
.evmBuilder(
|
||||
(gasCalculator, jdCacheConfig) ->
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
|
||||
import org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateWorldStateUpdater;
|
||||
import org.hyperledger.besu.evm.AccessListEntry;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.account.EvmAccount;
|
||||
@@ -446,33 +445,31 @@ public class MainnetTransactionProcessor {
|
||||
|
||||
final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas();
|
||||
|
||||
if (!worldState.getClass().equals(GoQuorumMutablePrivateWorldStateUpdater.class)) {
|
||||
// if this is not a private GoQuorum transaction we have to update the coinbase
|
||||
final var coinbase = worldState.getOrCreate(miningBeneficiary).getMutable();
|
||||
final long usedGas = transaction.getGasLimit() - refundedGas;
|
||||
final CoinbaseFeePriceCalculator coinbaseCalculator;
|
||||
if (blockHeader.getBaseFee().isPresent()) {
|
||||
final Wei baseFee = blockHeader.getBaseFee().get();
|
||||
if (transactionGasPrice.compareTo(baseFee) < 0) {
|
||||
return TransactionProcessingResult.failed(
|
||||
gasUsedByTransaction,
|
||||
refundedGas,
|
||||
ValidationResult.invalid(
|
||||
TransactionInvalidReason.TRANSACTION_PRICE_TOO_LOW,
|
||||
"transaction price must be greater than base fee"),
|
||||
Optional.empty());
|
||||
}
|
||||
coinbaseCalculator = coinbaseFeePriceCalculator;
|
||||
} else {
|
||||
coinbaseCalculator = CoinbaseFeePriceCalculator.frontier();
|
||||
// update the coinbase
|
||||
final var coinbase = worldState.getOrCreate(miningBeneficiary).getMutable();
|
||||
final long usedGas = transaction.getGasLimit() - refundedGas;
|
||||
final CoinbaseFeePriceCalculator coinbaseCalculator;
|
||||
if (blockHeader.getBaseFee().isPresent()) {
|
||||
final Wei baseFee = blockHeader.getBaseFee().get();
|
||||
if (transactionGasPrice.compareTo(baseFee) < 0) {
|
||||
return TransactionProcessingResult.failed(
|
||||
gasUsedByTransaction,
|
||||
refundedGas,
|
||||
ValidationResult.invalid(
|
||||
TransactionInvalidReason.TRANSACTION_PRICE_TOO_LOW,
|
||||
"transaction price must be greater than base fee"),
|
||||
Optional.empty());
|
||||
}
|
||||
|
||||
final Wei coinbaseWeiDelta =
|
||||
coinbaseCalculator.price(usedGas, transactionGasPrice, blockHeader.getBaseFee());
|
||||
|
||||
coinbase.incrementBalance(coinbaseWeiDelta);
|
||||
coinbaseCalculator = coinbaseFeePriceCalculator;
|
||||
} else {
|
||||
coinbaseCalculator = CoinbaseFeePriceCalculator.frontier();
|
||||
}
|
||||
|
||||
final Wei coinbaseWeiDelta =
|
||||
coinbaseCalculator.price(usedGas, transactionGasPrice, blockHeader.getBaseFee());
|
||||
|
||||
coinbase.incrementBalance(coinbaseWeiDelta);
|
||||
|
||||
initialFrame.getSelfDestructs().forEach(worldState::deleteAccount);
|
||||
|
||||
if (clearEmptyAccounts) {
|
||||
|
||||
@@ -51,7 +51,6 @@ public class MainnetTransactionValidator {
|
||||
|
||||
private Optional<TransactionFilter> transactionFilter = Optional.empty();
|
||||
private final Set<TransactionType> acceptedTransactionTypes;
|
||||
private final boolean goQuorumCompatibilityMode;
|
||||
|
||||
private final int maxInitcodeSize;
|
||||
|
||||
@@ -59,15 +58,13 @@ public class MainnetTransactionValidator {
|
||||
final GasCalculator gasCalculator,
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final boolean goQuorumCompatibilityMode) {
|
||||
final Optional<BigInteger> chainId) {
|
||||
this(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
Set.of(TransactionType.FRONTIER),
|
||||
goQuorumCompatibilityMode);
|
||||
Set.of(TransactionType.FRONTIER));
|
||||
}
|
||||
|
||||
public MainnetTransactionValidator(
|
||||
@@ -75,8 +72,7 @@ public class MainnetTransactionValidator {
|
||||
final GasLimitCalculator gasLimitCalculator,
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Set<TransactionType> acceptedTransactionTypes,
|
||||
final boolean quorumCompatibilityMode) {
|
||||
final Set<TransactionType> acceptedTransactionTypes) {
|
||||
this(
|
||||
gasCalculator,
|
||||
gasLimitCalculator,
|
||||
@@ -84,7 +80,6 @@ public class MainnetTransactionValidator {
|
||||
checkSignatureMalleability,
|
||||
chainId,
|
||||
acceptedTransactionTypes,
|
||||
quorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@@ -95,7 +90,6 @@ public class MainnetTransactionValidator {
|
||||
final boolean checkSignatureMalleability,
|
||||
final Optional<BigInteger> chainId,
|
||||
final Set<TransactionType> acceptedTransactionTypes,
|
||||
final boolean goQuorumCompatibilityMode,
|
||||
final int maxInitcodeSize) {
|
||||
this.gasCalculator = gasCalculator;
|
||||
this.gasLimitCalculator = gasLimitCalculator;
|
||||
@@ -103,7 +97,6 @@ public class MainnetTransactionValidator {
|
||||
this.disallowSignatureMalleability = checkSignatureMalleability;
|
||||
this.chainId = chainId;
|
||||
this.acceptedTransactionTypes = acceptedTransactionTypes;
|
||||
this.goQuorumCompatibilityMode = goQuorumCompatibilityMode;
|
||||
this.maxInitcodeSize = maxInitcodeSize;
|
||||
}
|
||||
|
||||
@@ -157,12 +150,6 @@ public class MainnetTransactionValidator {
|
||||
final Optional<Wei> maybeBaseFee,
|
||||
final TransactionValidationParams transactionValidationParams) {
|
||||
|
||||
if (goQuorumCompatibilityMode && transaction.hasCostParams()) {
|
||||
return ValidationResult.invalid(
|
||||
TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO,
|
||||
"gasPrice must be set to zero on a GoQuorum compatible network");
|
||||
}
|
||||
|
||||
if (maybeBaseFee.isPresent()) {
|
||||
final Wei price = feeMarket.getTransactionPriceCalculator().price(transaction, maybeBaseFee);
|
||||
if (!transactionValidationParams.isAllowMaxFeeGasBelowBaseFee()
|
||||
@@ -284,9 +271,7 @@ public class MainnetTransactionValidator {
|
||||
transaction.getChainId().get(), chainId.get()));
|
||||
}
|
||||
|
||||
if (!transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)
|
||||
&& chainId.isEmpty()
|
||||
&& transaction.getChainId().isPresent()) {
|
||||
if (chainId.isEmpty() && transaction.getChainId().isPresent()) {
|
||||
return ValidationResult.invalid(
|
||||
TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED,
|
||||
"replay protected signatures is not supported");
|
||||
@@ -356,8 +341,4 @@ public class MainnetTransactionValidator {
|
||||
ImmutableTransactionValidationParams.builder().isAllowFutureNonce(allowFutureNonce).build();
|
||||
return validateForSender(transaction, sender, validationParams);
|
||||
}
|
||||
|
||||
public boolean getGoQuorumCompatibilityMode() {
|
||||
return goQuorumCompatibilityMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public class ProtocolScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
final ProtocolSpecAdapters protocolSpecAdapters,
|
||||
final PrivacyParameters privacyParameters,
|
||||
final boolean isRevertReasonEnabled,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
this(
|
||||
config,
|
||||
@@ -44,7 +43,6 @@ public class ProtocolScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
protocolSpecAdapters,
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -53,7 +51,6 @@ public class ProtocolScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
final ProtocolSpecAdapters protocolSpecAdapters,
|
||||
final PrivacyParameters privacyParameters,
|
||||
final boolean isRevertReasonEnabled,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
this(
|
||||
config,
|
||||
@@ -61,7 +58,6 @@ public class ProtocolScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
protocolSpecAdapters,
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -71,15 +67,8 @@ public class ProtocolScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
final ProtocolSpecAdapters protocolSpecAdapters,
|
||||
final PrivacyParameters privacyParameters,
|
||||
final boolean isRevertReasonEnabled,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(
|
||||
config,
|
||||
protocolSpecAdapters,
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
super(config, protocolSpecAdapters, privacyParameters, isRevertReasonEnabled, evmConfiguration);
|
||||
this.defaultChainId = defaultChainId;
|
||||
}
|
||||
|
||||
@@ -225,10 +214,7 @@ public class ProtocolScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
protocolSchedule,
|
||||
classicBlockNumber,
|
||||
ClassicProtocolSpecs.classicRecoveryInitDefinition(
|
||||
config.getContractSizeLimit(),
|
||||
config.getEvmStackSize(),
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration),
|
||||
config.getContractSizeLimit(), config.getEvmStackSize(), evmConfiguration),
|
||||
Function.identity());
|
||||
protocolSchedule.putMilestone(classicBlockNumber + 1, originalProtocolSpec);
|
||||
});
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.hyperledger.besu.ethereum.GasLimitCalculator;
|
||||
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
import org.hyperledger.besu.ethereum.mainnet.precompiles.privacy.FlexiblePrivacyPrecompiledContract;
|
||||
@@ -346,11 +345,7 @@ public class ProtocolSpecBuilder {
|
||||
|
||||
final BlockValidator blockValidator =
|
||||
blockValidatorBuilder.apply(
|
||||
blockHeaderValidator,
|
||||
blockBodyValidator,
|
||||
blockProcessor,
|
||||
badBlockManager,
|
||||
privacyParameters.getGoQuorumPrivacyParameters());
|
||||
blockHeaderValidator, blockBodyValidator, blockProcessor, badBlockManager);
|
||||
final BlockImporter blockImporter = blockImporterBuilder.apply(blockValidator);
|
||||
return new ProtocolSpec(
|
||||
name,
|
||||
@@ -426,7 +421,6 @@ public class ProtocolSpecBuilder {
|
||||
blockReward,
|
||||
miningBeneficiaryCalculator,
|
||||
skipZeroBlockRewards,
|
||||
privacyParameters.getGoQuorumPrivacyParameters(),
|
||||
protocolSchedule);
|
||||
}
|
||||
|
||||
@@ -465,7 +459,6 @@ public class ProtocolSpecBuilder {
|
||||
Wei blockReward,
|
||||
MiningBeneficiaryCalculator miningBeneficiaryCalculator,
|
||||
boolean skipZeroBlockRewards,
|
||||
Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters,
|
||||
HeaderBasedProtocolSchedule protocolSchedule);
|
||||
}
|
||||
|
||||
@@ -474,8 +467,7 @@ public class ProtocolSpecBuilder {
|
||||
BlockHeaderValidator blockHeaderValidator,
|
||||
BlockBodyValidator blockBodyValidator,
|
||||
BlockProcessor blockProcessor,
|
||||
BadBlockManager badBlockManager,
|
||||
Optional<GoQuorumPrivacyParameters> goQuorumPrivacyParameters);
|
||||
BadBlockManager badBlockManager);
|
||||
}
|
||||
|
||||
public interface BlockImporterBuilder {
|
||||
|
||||
@@ -33,15 +33,8 @@ public class TimestampScheduleBuilder extends AbstractProtocolScheduleBuilder {
|
||||
final ProtocolSpecAdapters protocolSpecAdapters,
|
||||
final PrivacyParameters privacyParameters,
|
||||
final boolean isRevertReasonEnabled,
|
||||
final boolean quorumCompatibilityMode,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(
|
||||
config,
|
||||
protocolSpecAdapters,
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
super(config, protocolSpecAdapters, privacyParameters, isRevertReasonEnabled, evmConfiguration);
|
||||
this.defaultChainId = Optional.of(defaultChainId);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.privacy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class GoQuorumSendRawTxArgs {
|
||||
|
||||
private final String privateFrom;
|
||||
|
||||
private final List<String> privateFor;
|
||||
|
||||
private final int privacyFlag;
|
||||
|
||||
@JsonCreator
|
||||
public GoQuorumSendRawTxArgs(
|
||||
@JsonProperty("privateFrom") final String privateFrom,
|
||||
@JsonProperty("privateFor") final List<String> privateFor,
|
||||
@JsonProperty("privacyFlag") final int privacyFlag) {
|
||||
|
||||
this.privateFrom = privateFrom;
|
||||
this.privateFor = privateFor;
|
||||
this.privacyFlag = privacyFlag;
|
||||
}
|
||||
|
||||
public String getPrivateFrom() {
|
||||
return privateFrom;
|
||||
}
|
||||
|
||||
public List<String> getPrivateFor() {
|
||||
return privateFor;
|
||||
}
|
||||
|
||||
public int getPrivacyFlag() {
|
||||
return privacyFlag;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
package org.hyperledger.besu.ethereum.storage;
|
||||
|
||||
import org.hyperledger.besu.ethereum.chain.BlockchainStorage;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStorage;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
|
||||
@@ -38,12 +37,6 @@ public interface StorageProvider extends Closeable {
|
||||
|
||||
SnappableKeyValueStorage getSnappableStorageBySegmentIdentifier(SegmentIdentifier segment);
|
||||
|
||||
WorldStateStorage createPrivateWorldStateStorage();
|
||||
|
||||
WorldStatePreimageStorage createPrivateWorldStatePreimageStorage();
|
||||
|
||||
GoQuorumPrivateStorage createGoQuorumPrivateStorage();
|
||||
|
||||
boolean isWorldStateIterable();
|
||||
|
||||
boolean isWorldStateSnappable();
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.storage.keyvalue;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.evm.log.LogsBloomFilter;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
public class GoQuorumKeyValueStoragePrefixedKeyBlockchainStorage
|
||||
extends KeyValueStoragePrefixedKeyBlockchainStorage {
|
||||
|
||||
private static final Bytes BLOCK_HEADER_PRIVATE_BLOOM_PREFIX = Bytes.of(8);
|
||||
|
||||
public GoQuorumKeyValueStoragePrefixedKeyBlockchainStorage(
|
||||
final KeyValueStorage storage, final BlockHeaderFunctions blockHeaderFunctions) {
|
||||
super(storage, blockHeaderFunctions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlockHeader> getBlockHeader(final Hash blockHash) {
|
||||
final Optional<BlockHeader> blockHeaderOptional =
|
||||
get(BLOCK_HEADER_PREFIX, blockHash)
|
||||
.map(b -> BlockHeader.readFrom(RLP.input(b), blockHeaderFunctions));
|
||||
if (blockHeaderOptional.isPresent()) {
|
||||
final Optional<Bytes> privateBloomBytesOptional =
|
||||
get(BLOCK_HEADER_PRIVATE_BLOOM_PREFIX, blockHash);
|
||||
privateBloomBytesOptional.ifPresent(
|
||||
pBB -> blockHeaderOptional.get().setPrivateLogsBloom(new LogsBloomFilter(pBB)));
|
||||
}
|
||||
return blockHeaderOptional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Updater updater() {
|
||||
return new Updater(storage.startTransaction());
|
||||
}
|
||||
|
||||
public static class Updater extends KeyValueStoragePrefixedKeyBlockchainStorage.Updater {
|
||||
|
||||
private Updater(final KeyValueStorageTransaction transaction) {
|
||||
super(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBlockHeader(final Hash blockHash, final BlockHeader blockHeader) {
|
||||
set(BLOCK_HEADER_PREFIX, blockHash, RLP.encode(blockHeader::writeTo));
|
||||
blockHeader
|
||||
.getPrivateLogsBloom()
|
||||
.ifPresent(privateLoom -> set(BLOCK_HEADER_PRIVATE_BLOOM_PREFIX, blockHash, privateLoom));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.storage.keyvalue;
|
||||
|
||||
import org.hyperledger.besu.ethereum.chain.BlockchainStorage;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class GoQuorumKeyValueStorageProvider extends KeyValueStorageProvider {
|
||||
|
||||
public GoQuorumKeyValueStorageProvider(
|
||||
final Function<SegmentIdentifier, KeyValueStorage> storageCreator,
|
||||
final KeyValueStorage worldStatePreimageStorage,
|
||||
final boolean segmentIsolationSupported,
|
||||
final ObservableMetricsSystem metricsSystem) {
|
||||
super(storageCreator, worldStatePreimageStorage, segmentIsolationSupported, metricsSystem);
|
||||
}
|
||||
|
||||
public GoQuorumKeyValueStorageProvider(
|
||||
final Function<SegmentIdentifier, KeyValueStorage> storageCreator,
|
||||
final KeyValueStorage worldStatePreimageStorage,
|
||||
final KeyValueStorage privateWorldStatePreimageStorage,
|
||||
final boolean segmentIsolationSupported,
|
||||
final ObservableMetricsSystem metricsSystem) {
|
||||
super(
|
||||
storageCreator,
|
||||
worldStatePreimageStorage,
|
||||
privateWorldStatePreimageStorage,
|
||||
segmentIsolationSupported,
|
||||
SNAPSHOT_ISOLATION_UNSUPPORTED,
|
||||
metricsSystem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockchainStorage createBlockchainStorage(final ProtocolSchedule protocolSchedule) {
|
||||
return new GoQuorumKeyValueStoragePrefixedKeyBlockchainStorage(
|
||||
getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.BLOCKCHAIN),
|
||||
ScheduleBasedBlockHeaderFunctions.create(protocolSchedule));
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,9 @@ public enum KeyValueSegmentIdentifier implements SegmentIdentifier {
|
||||
ACCOUNT_STORAGE_STORAGE(new byte[] {8}, new int[] {2}),
|
||||
TRIE_BRANCH_STORAGE(new byte[] {9}, new int[] {2}),
|
||||
TRIE_LOG_STORAGE(new byte[] {10}, new int[] {2}),
|
||||
GOQUORUM_PRIVATE_WORLD_STATE(new byte[] {11}),
|
||||
GOQUORUM_PRIVATE_STORAGE(new byte[] {12}),
|
||||
// previously supported GoQuorum private states
|
||||
// GOQUORUM_PRIVATE_WORLD_STATE(new byte[] {11}),
|
||||
// GOQUORUM_PRIVATE_STORAGE(new byte[] {12}),
|
||||
BACKWARD_SYNC_HEADERS(new byte[] {13}),
|
||||
BACKWARD_SYNC_BLOCKS(new byte[] {14}),
|
||||
BACKWARD_SYNC_CHAIN(new byte[] {15}),
|
||||
|
||||
@@ -16,8 +16,6 @@ package org.hyperledger.besu.ethereum.storage.keyvalue;
|
||||
|
||||
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.chain.BlockchainStorage;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStorage;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
@@ -41,7 +39,6 @@ public class KeyValueStorageProvider implements StorageProvider {
|
||||
|
||||
protected final Function<SegmentIdentifier, KeyValueStorage> storageCreator;
|
||||
private final KeyValueStorage worldStatePreimageStorage;
|
||||
private final KeyValueStorage privateWorldStatePreimageStorage;
|
||||
private final boolean isWorldStateIterable;
|
||||
private final boolean isWorldStateSnappable;
|
||||
protected final Map<SegmentIdentifier, KeyValueStorage> storageInstances = new HashMap<>();
|
||||
@@ -54,7 +51,6 @@ public class KeyValueStorageProvider implements StorageProvider {
|
||||
final ObservableMetricsSystem metricsSystem) {
|
||||
this.storageCreator = storageCreator;
|
||||
this.worldStatePreimageStorage = worldStatePreimageStorage;
|
||||
this.privateWorldStatePreimageStorage = null;
|
||||
this.isWorldStateIterable = segmentIsolationSupported;
|
||||
this.isWorldStateSnappable = SNAPSHOT_ISOLATION_UNSUPPORTED;
|
||||
this.metricsSystem = metricsSystem;
|
||||
@@ -63,13 +59,11 @@ public class KeyValueStorageProvider implements StorageProvider {
|
||||
public KeyValueStorageProvider(
|
||||
final Function<SegmentIdentifier, KeyValueStorage> storageCreator,
|
||||
final KeyValueStorage worldStatePreimageStorage,
|
||||
final KeyValueStorage privateWorldStatePreimageStorage,
|
||||
final boolean segmentIsolationSupported,
|
||||
final boolean storageSnapshotIsolationSupported,
|
||||
final ObservableMetricsSystem metricsSystem) {
|
||||
this.storageCreator = storageCreator;
|
||||
this.worldStatePreimageStorage = worldStatePreimageStorage;
|
||||
this.privateWorldStatePreimageStorage = privateWorldStatePreimageStorage;
|
||||
this.isWorldStateIterable = segmentIsolationSupported;
|
||||
this.isWorldStateSnappable = storageSnapshotIsolationSupported;
|
||||
this.metricsSystem = metricsSystem;
|
||||
@@ -108,23 +102,6 @@ public class KeyValueStorageProvider implements StorageProvider {
|
||||
return (SnappableKeyValueStorage) getStorageBySegmentIdentifier(segment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldStateStorage createPrivateWorldStateStorage() {
|
||||
return new WorldStateKeyValueStorage(
|
||||
getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.GOQUORUM_PRIVATE_WORLD_STATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldStatePreimageStorage createPrivateWorldStatePreimageStorage() {
|
||||
return new WorldStatePreimageKeyValueStorage(privateWorldStatePreimageStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoQuorumPrivateStorage createGoQuorumPrivateStorage() {
|
||||
return new GoQuorumPrivateKeyValueStorage(
|
||||
getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.GOQUORUM_PRIVATE_STORAGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorldStateIterable() {
|
||||
return isWorldStateIterable;
|
||||
|
||||
@@ -30,7 +30,6 @@ public class KeyValueStorageProviderBuilder {
|
||||
private KeyValueStorageFactory storageFactory;
|
||||
private BesuConfiguration commonConfiguration;
|
||||
private MetricsSystem metricsSystem;
|
||||
private boolean isGoQuorumCompatibilityMode;
|
||||
|
||||
public KeyValueStorageProviderBuilder withStorageFactory(
|
||||
final KeyValueStorageFactory storageFactory) {
|
||||
@@ -49,12 +48,6 @@ public class KeyValueStorageProviderBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public KeyValueStorageProviderBuilder isGoQuorumCompatibilityMode(
|
||||
final boolean isGoQuorumCompatibilityMode) {
|
||||
this.isGoQuorumCompatibilityMode = isGoQuorumCompatibilityMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public KeyValueStorageProvider build() {
|
||||
checkNotNull(storageFactory, "Cannot build a storage provider without a storage factory.");
|
||||
checkNotNull(
|
||||
@@ -65,26 +58,13 @@ public class KeyValueStorageProviderBuilder {
|
||||
final KeyValueStorage worldStatePreImageStorage =
|
||||
new LimitedInMemoryKeyValueStorage(DEFAULT_WORLD_STATE_PRE_IMAGE_CACHE_SIZE);
|
||||
|
||||
final KeyValueStorage privateWorldStatePreImageStorage =
|
||||
new LimitedInMemoryKeyValueStorage(DEFAULT_WORLD_STATE_PRE_IMAGE_CACHE_SIZE);
|
||||
|
||||
// this tickles init needed for isSegmentIsolationSupported
|
||||
storageFactory.create(KeyValueSegmentIdentifier.BLOCKCHAIN, commonConfiguration, metricsSystem);
|
||||
if (isGoQuorumCompatibilityMode) {
|
||||
return new GoQuorumKeyValueStorageProvider(
|
||||
segment -> storageFactory.create(segment, commonConfiguration, metricsSystem),
|
||||
worldStatePreImageStorage,
|
||||
privateWorldStatePreImageStorage,
|
||||
storageFactory.isSegmentIsolationSupported(),
|
||||
(ObservableMetricsSystem) metricsSystem);
|
||||
} else {
|
||||
return new KeyValueStorageProvider(
|
||||
segment -> storageFactory.create(segment, commonConfiguration, metricsSystem),
|
||||
worldStatePreImageStorage,
|
||||
privateWorldStatePreImageStorage,
|
||||
storageFactory.isSegmentIsolationSupported(),
|
||||
storageFactory.isSnapshotIsolationSupported(),
|
||||
(ObservableMetricsSystem) metricsSystem);
|
||||
}
|
||||
return new KeyValueStorageProvider(
|
||||
segment -> storageFactory.create(segment, commonConfiguration, metricsSystem),
|
||||
worldStatePreImageStorage,
|
||||
storageFactory.isSegmentIsolationSupported(),
|
||||
storageFactory.isSnapshotIsolationSupported(),
|
||||
(ObservableMetricsSystem) metricsSystem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.transaction;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MAX;
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MIN;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class GoQuorumPrivateTransactionDetector {
|
||||
/**
|
||||
* Returns whether or not <i>v</i> indicates a GoQuorum private transaction.
|
||||
*
|
||||
* @param v the v value of a transaction
|
||||
* @return true if GoQuorum private transaction, false otherwise
|
||||
*/
|
||||
public static final boolean isGoQuorumPrivateTransactionV(final BigInteger v) {
|
||||
return ((v.compareTo(GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MAX) <= 0)
|
||||
&& (v.compareTo(GO_QUORUM_PRIVATE_TRANSACTION_V_VALUE_MIN)) >= 0);
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,6 @@
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.transaction;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStateUtil.getPrivateWorldStateAtBlock;
|
||||
|
||||
import org.hyperledger.besu.crypto.SECPSignature;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||
@@ -27,7 +25,6 @@ import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
@@ -36,7 +33,6 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
|
||||
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
|
||||
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.GoQuorumMutablePrivateAndPublicWorldStateUpdater;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.tracing.OperationTracer;
|
||||
@@ -77,7 +73,6 @@ public class TransactionSimulator {
|
||||
private final Blockchain blockchain;
|
||||
private final WorldStateArchive worldStateArchive;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
private final Optional<PrivacyParameters> maybePrivacyParameters;
|
||||
|
||||
public TransactionSimulator(
|
||||
final Blockchain blockchain,
|
||||
@@ -86,18 +81,6 @@ public class TransactionSimulator {
|
||||
this.blockchain = blockchain;
|
||||
this.worldStateArchive = worldStateArchive;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.maybePrivacyParameters = Optional.empty();
|
||||
}
|
||||
|
||||
public TransactionSimulator(
|
||||
final Blockchain blockchain,
|
||||
final WorldStateArchive worldStateArchive,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final PrivacyParameters privacyParameters) {
|
||||
this.blockchain = blockchain;
|
||||
this.worldStateArchive = worldStateArchive;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.maybePrivacyParameters = Optional.of(privacyParameters);
|
||||
}
|
||||
|
||||
public Optional<TransactionSimulatorResult> process(
|
||||
@@ -245,29 +228,6 @@ public class TransactionSimulator {
|
||||
operationTracer,
|
||||
dataGasPrice);
|
||||
|
||||
// If GoQuorum privacy enabled, and value = zero, get max gas possible for a PMT hash.
|
||||
// It is possible to have a data field that has a lower intrinsic value than the PMT hash.
|
||||
// This means a potential over-estimate of gas, but the tx, if sent with this gas, will not
|
||||
// fail.
|
||||
final boolean goQuorumCompatibilityMode =
|
||||
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode();
|
||||
|
||||
if (goQuorumCompatibilityMode && value.isZero()) {
|
||||
final long privateGasEstimateAndState =
|
||||
protocolSpec.getGasCalculator().getMaximumTransactionCost(64);
|
||||
if (privateGasEstimateAndState > result.getEstimateGasUsedByTransaction()) {
|
||||
// modify the result to have the larger estimate
|
||||
final TransactionProcessingResult resultPmt =
|
||||
TransactionProcessingResult.successful(
|
||||
result.getLogs(),
|
||||
privateGasEstimateAndState,
|
||||
result.getGasRemaining(),
|
||||
result.getOutput(),
|
||||
result.getValidationResult());
|
||||
return Optional.of(new TransactionSimulatorResult(transaction, resultPmt));
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.of(new TransactionSimulatorResult(transaction, result));
|
||||
}
|
||||
|
||||
@@ -325,20 +285,8 @@ public class TransactionSimulator {
|
||||
return Optional.ofNullable(transaction);
|
||||
}
|
||||
|
||||
// return combined private/public world state updater if GoQuorum mode, otherwise the public state
|
||||
public WorldUpdater getEffectiveWorldStateUpdater(
|
||||
final BlockHeader header, final MutableWorldState publicWorldState) {
|
||||
|
||||
if (maybePrivacyParameters.isPresent()
|
||||
&& maybePrivacyParameters.get().getGoQuorumPrivacyParameters().isPresent()) {
|
||||
|
||||
final MutableWorldState privateWorldState =
|
||||
getPrivateWorldStateAtBlock(
|
||||
maybePrivacyParameters.get().getGoQuorumPrivacyParameters(), header);
|
||||
return new GoQuorumMutablePrivateAndPublicWorldStateUpdater(
|
||||
publicWorldState.updater(), privateWorldState.updater());
|
||||
}
|
||||
|
||||
return publicWorldState.updater();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.worldstate;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.evm.account.EvmAccount;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
|
||||
// This class uses a public WorldUpdater and a private WorldUpdater to
|
||||
// provide a MutableWorldStateUpdater that can read and write from
|
||||
// BOTH the private world state and the public world state.
|
||||
//
|
||||
// Note that only writes to private states are committed to the
|
||||
// underlying storage (via
|
||||
// DefaultMutablePrivateWorldStateUpdater::commit) whereas public
|
||||
// state changes are discarded.
|
||||
//
|
||||
// World state obtained by this class must not be persisted: it allows
|
||||
// illegal write access from private to public contract data that
|
||||
// would result in world state divergence between nodes.
|
||||
public class GoQuorumMutablePrivateAndPublicWorldStateUpdater
|
||||
extends GoQuorumMutablePrivateWorldStateUpdater {
|
||||
|
||||
public GoQuorumMutablePrivateAndPublicWorldStateUpdater(
|
||||
final WorldUpdater publicWorldUpdater, final WorldUpdater privateWorldUpdater) {
|
||||
super(publicWorldUpdater, privateWorldUpdater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvmAccount getAccount(final Address address) {
|
||||
final EvmAccount privateAccount = privateWorldUpdater.getAccount(address);
|
||||
if (privateAccount != null && !privateAccount.isEmpty()) {
|
||||
return privateAccount;
|
||||
}
|
||||
final EvmAccount publicAccount = publicWorldUpdater.getAccount(address);
|
||||
if (publicAccount != null && !publicAccount.isEmpty()) {
|
||||
return publicAccount;
|
||||
}
|
||||
return privateAccount;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.worldstate;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.evm.account.EvmAccount;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
|
||||
// This class uses a public WorldUpdater and a private WorldUpdater to provide a
|
||||
// MutableWorldStateUpdater that can read and write from the private world state and can read from
|
||||
// the public world state, but cannot write to it.
|
||||
public class GoQuorumMutablePrivateWorldStateUpdater
|
||||
extends DefaultMutablePrivateWorldStateUpdater {
|
||||
|
||||
public GoQuorumMutablePrivateWorldStateUpdater(
|
||||
final WorldUpdater publicWorldUpdater, final WorldUpdater privateWorldUpdater) {
|
||||
super(publicWorldUpdater, privateWorldUpdater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvmAccount getOrCreateSenderAccount(final Address address) {
|
||||
return new UpdateTrackingAccount<>(publicWorldUpdater.getOrCreate(address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvmAccount getSenderAccount(final MessageFrame frame) {
|
||||
final Address senderAddress = frame.getSenderAddress();
|
||||
if (senderAddress.equals(frame.getOriginatorAddress())) {
|
||||
return new UpdateTrackingAccount<>(publicWorldUpdater.getOrCreate(senderAddress));
|
||||
} else {
|
||||
return getAccount(senderAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,6 @@ public class ExecutionContextTestFixture {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
new PrivacyParameters(),
|
||||
false,
|
||||
genesisConfigFile.getConfigOptions().isQuorum(),
|
||||
EvmConfiguration.DEFAULT)
|
||||
.createProtocolSchedule();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ public class InMemoryKeyValueStorageProvider extends KeyValueStorageProvider {
|
||||
super(
|
||||
segmentIdentifier -> new InMemoryKeyValueStorage(),
|
||||
new InMemoryKeyValueStorage(),
|
||||
new InMemoryKeyValueStorage(),
|
||||
SEGMENT_ISOLATION_SUPPORTED,
|
||||
SNAPSHOT_ISOLATION_UNSUPPORTED,
|
||||
new NoOpMetricsSystem());
|
||||
|
||||
@@ -72,7 +72,6 @@ public class BlockImportExceptionHandlingTest {
|
||||
Wei.ZERO,
|
||||
BlockHeader::getCoinbase,
|
||||
true,
|
||||
Optional.empty(),
|
||||
protocolSchedule);
|
||||
private final BlockHeaderValidator blockHeaderValidator = mock(BlockHeaderValidator.class);
|
||||
private final BlockBodyValidator blockBodyValidator = mock(BlockBodyValidator.class);
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TransactionGoQuorumTest {
|
||||
|
||||
private static final RLPInput ETHEREUM_PUBLIC_TX_RLP =
|
||||
toRLP(
|
||||
"0xf901fc8032830138808080b901ae60056013565b6101918061001d6000396000f35b3360008190555056006001600060e060020a6000350480630a874df61461003a57806341c0e1b514610058578063a02b161e14610066578063dbbdf0831461007757005b610045600435610149565b80600160a060020a031660005260206000f35b610060610161565b60006000f35b6100716004356100d4565b60006000f35b61008560043560243561008b565b60006000f35b600054600160a060020a031632600160a060020a031614156100ac576100b1565b6100d0565b8060018360005260205260406000208190555081600060005260206000a15b5050565b600054600160a060020a031633600160a060020a031614158015610118575033600160a060020a0316600182600052602052604060002054600160a060020a031614155b61012157610126565b610146565b600060018260005260205260406000208190555080600060005260206000a15b50565b60006001826000526020526040600020549050919050565b600054600160a060020a031633600160a060020a0316146101815761018f565b600054600160a060020a0316ff5b561ca0c5689ed1ad124753d54576dfb4b571465a41900a1dff4058d8adf16f752013d0a01221cbd70ec28c94a3b55ec771bcbc70778d6ee0b51ca7ea9514594c861b1884");
|
||||
private static final RLPInput GOQUORUM_PRIVATE_TX_RLP_V37 =
|
||||
toRLP(
|
||||
"0xf88d0b808347b7608080b840290a80a37d198ff06abe189b638ff53ac8a8dc51a0aff07609d2aa75342783ae493b3e3c6b564c0eebe49284b05a0726fb33087b9e0231d349ea0c7b5661c8c525a07144db7045a395e608cda6ab051c86cc4fb42e319960b82087f3b26f0cbc3c2da00223ac129b22aec7a6c2ace3c3ef39c5eaaa54070fd82d8ee2140b0e70b1dca9");
|
||||
private static final RLPInput GOQUORUM_PRIVATE_TX_RLP_V38 =
|
||||
toRLP(
|
||||
"0xf88d0b808347b7608080b840290a80a37d198ff06abe189b638ff53ac8a8dc51a0aff07609d2aa75342783ae493b3e3c6b564c0eebe49284b05a0726fb33087b9e0231d349ea0c7b5661c8c526a07144db7045a395e608cda6ab051c86cc4fb42e319960b82087f3b26f0cbc3c2da00223ac129b22aec7a6c2ace3c3ef39c5eaaa54070fd82d8ee2140b0e70b1dca9");
|
||||
|
||||
private static final boolean goQuorumCompatibilityMode = true;
|
||||
|
||||
@Test
|
||||
public void givenPublicTransaction_assertThatIsGoQuorumFlagIsFalse() {
|
||||
final Transaction transaction =
|
||||
TransactionDecoder.decodeForWire(ETHEREUM_PUBLIC_TX_RLP, goQuorumCompatibilityMode);
|
||||
|
||||
assertThat(transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)).isFalse();
|
||||
assertThat(transaction.hasCostParams()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGoQuorumTransactionV37_assertThatIsGoQuorumFlagIsTrue() {
|
||||
final Transaction transaction =
|
||||
TransactionDecoder.decodeForWire(GOQUORUM_PRIVATE_TX_RLP_V37, goQuorumCompatibilityMode);
|
||||
|
||||
assertThat(transaction.getV()).isEqualTo(37);
|
||||
assertThat(transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)).isTrue();
|
||||
assertThat(transaction.hasCostParams()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGoQuorumTransactionV38_assertThatIsGoQuorumFlagIsTrue() {
|
||||
final Transaction transaction =
|
||||
TransactionDecoder.decodeForWire(GOQUORUM_PRIVATE_TX_RLP_V38, goQuorumCompatibilityMode);
|
||||
|
||||
assertThat(transaction.getV()).isEqualTo(38);
|
||||
assertThat(transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)).isTrue();
|
||||
assertThat(transaction.hasCostParams()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTransactionWithChainId_assertThatIsGoQuorumFlagIsFalse() {
|
||||
final Transaction transaction =
|
||||
Transaction.builder().chainId(BigInteger.valueOf(0)).gasPrice(Wei.ZERO).build();
|
||||
assertThat(transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTransactionWithoutChainIdAndV37_assertThatIsGoQuorumFlagIsTrue() {
|
||||
final Transaction transaction =
|
||||
Transaction.builder().v(BigInteger.valueOf(37)).gasPrice(Wei.ZERO).build();
|
||||
assertThat(transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)).isTrue();
|
||||
}
|
||||
|
||||
private static RLPInput toRLP(final String bytes) {
|
||||
return RLP.input(Bytes.fromHexString(bytes));
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.hyperledger.besu.evm.account.Account.MAX_NONCE;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPException;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
@@ -40,24 +38,9 @@ class TransactionDecoderTest {
|
||||
"0xf901fc8032830138808080b901ae60056013565b6101918061001d6000396000f35b3360008190555056006001600060e060020a6000350480630a874df61461003a57806341c0e1b514610058578063a02b161e14610066578063dbbdf0831461007757005b610045600435610149565b80600160a060020a031660005260206000f35b610060610161565b60006000f35b6100716004356100d4565b60006000f35b61008560043560243561008b565b60006000f35b600054600160a060020a031632600160a060020a031614156100ac576100b1565b6100d0565b8060018360005260205260406000208190555081600060005260206000a15b5050565b600054600160a060020a031633600160a060020a031614158015610118575033600160a060020a0316600182600052602052604060002054600160a060020a031614155b61012157610126565b610146565b600060018260005260205260406000208190555080600060005260206000a15b50565b60006001826000526020526040600020549050919050565b600054600160a060020a031633600160a060020a0316146101815761018f565b600054600160a060020a0316ff5b561ca0c5689ed1ad124753d54576dfb4b571465a41900a1dff4058d8adf16f752013d0a01221cbd70ec28c94a3b55ec771bcbc70778d6ee0b51ca7ea9514594c861b1884";
|
||||
private static final String EIP1559_TX_RLP =
|
||||
"0xb8a902f8a686796f6c6f7632800285012a05f20082753094000000000000000000000000000000000000aaaa8080f838f794000000000000000000000000000000000000aaaae1a0000000000000000000000000000000000000000000000000000000000000000001a00c1d69648e348fe26155b45de45004f0e4195f6352d8f0935bc93e98a3e2a862a060064e5b9765c0ac74223b0cf49635c59ae0faf82044fd17bcc68a549ade6f95";
|
||||
private static final String GOQUORUM_PRIVATE_TX_RLP =
|
||||
"0xf88d0b808347b7608080b840290a80a37d198ff06abe189b638ff53ac8a8dc51a0aff07609d2aa75342783ae493b3e3c6b564c0eebe49284b05a0726fb33087b9e0231d349ea0c7b5661c8c526a07144db7045a395e608cda6ab051c86cc4fb42e319960b82087f3b26f0cbc3c2da00223ac129b22aec7a6c2ace3c3ef39c5eaaa54070fd82d8ee2140b0e70b1dca9";
|
||||
private static final String NONCE_64_BIT_MAX_MINUS_2_TX_RLP =
|
||||
"0xf86788fffffffffffffffe0182520894095e7baea6a6c7c4c2dfeb977efac326af552d8780801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804";
|
||||
|
||||
@Test
|
||||
void decodeGoQuorumPrivateTransactionRlp() {
|
||||
final boolean goQuorumCompatibilityMode = true;
|
||||
final RLPInput input = RLP.input(Bytes.fromHexString(GOQUORUM_PRIVATE_TX_RLP));
|
||||
|
||||
final Transaction transaction =
|
||||
TransactionDecoder.decodeForWire(input, goQuorumCompatibilityMode);
|
||||
assertThat(transaction).isNotNull();
|
||||
assertThat(transaction.getV()).isEqualTo(38);
|
||||
assertThat(transaction.getSender())
|
||||
.isEqualByComparingTo(Address.fromHexString("0xed9d02e382b34818e88b88a309c7fe71e65f419d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeFrontierNominalCase() {
|
||||
final Transaction transaction =
|
||||
@@ -81,11 +64,8 @@ class TransactionDecoderTest {
|
||||
void doesNotDecodeEIP1559WithLargeMaxFeePerGasOrLargeMaxPriorityFeePerGas() {
|
||||
final String txWithBigFees =
|
||||
"0x02f84e0101a1648a5f8b2dcad5ea5ba6b720ff069c1d87c21a4a6a5b3766b39e2c2792367bb066a1ffa5ffaf5b0560d3a9fb186c2ede2ae6751bc0b4fef9107cf36389630b6196a38805800180c0010203";
|
||||
final boolean goQuorumCompatibilityMode = false;
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
TransactionDecoder.decodeOpaqueBytes(
|
||||
Bytes.fromHexString(txWithBigFees), goQuorumCompatibilityMode))
|
||||
() -> TransactionDecoder.decodeOpaqueBytes(Bytes.fromHexString(txWithBigFees)))
|
||||
.isInstanceOf(RLPException.class);
|
||||
}
|
||||
|
||||
@@ -103,7 +83,6 @@ class TransactionDecoderTest {
|
||||
new Object[][] {
|
||||
{FRONTIER_TX_RLP, "FRONTIER_TX_RLP"},
|
||||
{EIP1559_TX_RLP, "EIP1559_TX_RLP"},
|
||||
{GOQUORUM_PRIVATE_TX_RLP, "GOQUORUM_PRIVATE_TX_RLP"},
|
||||
{NONCE_64_BIT_MAX_MINUS_2_TX_RLP, "NONCE_64_BIT_MAX_MINUS_2_TX_RLP"}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.goquorum;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.enclave.EnclaveServerException;
|
||||
import org.hyperledger.besu.enclave.GoQuorumEnclave;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.GoQuorumPrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
|
||||
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GoQuorumBlockProcessorTest {
|
||||
|
||||
@Mock private AbstractBlockProcessor.TransactionReceiptFactory transactionReceiptFactory;
|
||||
@Mock private GoQuorumEnclave goQuorumEnclave;
|
||||
@Mock private GoQuorumPrivateStorage goQuorumPrivateStorage;
|
||||
@Mock private MainnetTransactionProcessor transactionProcessor;
|
||||
@Mock private MainnetTransactionValidator transactionValidator;
|
||||
@Mock private HeaderBasedProtocolSchedule protocolSchedule;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
|
||||
private GoQuorumPrivacyParameters goQuorumPrivacyParameters;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
|
||||
goQuorumPrivacyParameters =
|
||||
new GoQuorumPrivacyParameters(goQuorumEnclave, "123", goQuorumPrivateStorage, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noAccountCreatedWhenBlockRewardIsZeroAndSkipped() {
|
||||
final Blockchain blockchain = new ReferenceTestBlockchain();
|
||||
final GoQuorumBlockProcessor blockProcessor =
|
||||
new GoQuorumBlockProcessor(
|
||||
transactionProcessor,
|
||||
transactionReceiptFactory,
|
||||
Wei.ZERO,
|
||||
BlockHeader::getCoinbase,
|
||||
true,
|
||||
Optional.of(goQuorumPrivacyParameters),
|
||||
protocolSchedule);
|
||||
|
||||
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
|
||||
final Hash initialHash = worldState.rootHash();
|
||||
|
||||
final BlockHeader emptyBlockHeader =
|
||||
new BlockHeaderTestFixture()
|
||||
.transactionsRoot(Hash.EMPTY_LIST_HASH)
|
||||
.ommersHash(Hash.EMPTY_LIST_HASH)
|
||||
.buildHeader();
|
||||
blockProcessor.processBlock(blockchain, worldState, emptyBlockHeader, emptyList(), emptyList());
|
||||
|
||||
// An empty block with 0 reward should not change the world state
|
||||
assertThat(worldState.rootHash()).isEqualTo(initialHash);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accountCreatedWhenBlockRewardIsZeroAndNotSkipped() {
|
||||
final Blockchain blockchain = new ReferenceTestBlockchain();
|
||||
final GoQuorumBlockProcessor blockProcessor =
|
||||
new GoQuorumBlockProcessor(
|
||||
transactionProcessor,
|
||||
transactionReceiptFactory,
|
||||
Wei.ZERO,
|
||||
BlockHeader::getCoinbase,
|
||||
false,
|
||||
Optional.of(goQuorumPrivacyParameters),
|
||||
protocolSchedule);
|
||||
|
||||
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
|
||||
final Hash initialHash = worldState.rootHash();
|
||||
|
||||
final BlockHeader emptyBlockHeader =
|
||||
new BlockHeaderTestFixture()
|
||||
.transactionsRoot(Hash.EMPTY_LIST_HASH)
|
||||
.ommersHash(Hash.EMPTY_LIST_HASH)
|
||||
.buildHeader();
|
||||
blockProcessor.processBlock(blockchain, worldState, emptyBlockHeader, emptyList(), emptyList());
|
||||
|
||||
// An empty block with 0 reward should change the world state prior to EIP158
|
||||
assertThat(worldState.rootHash()).isNotEqualTo(initialHash);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enclaveNotAvailable() {
|
||||
final Blockchain blockchain = new ReferenceTestBlockchain();
|
||||
final GoQuorumBlockProcessor blockProcessor =
|
||||
new GoQuorumBlockProcessor(
|
||||
transactionProcessor,
|
||||
transactionReceiptFactory,
|
||||
Wei.ZERO,
|
||||
BlockHeader::getCoinbase,
|
||||
false,
|
||||
Optional.of(goQuorumPrivacyParameters),
|
||||
protocolSchedule);
|
||||
|
||||
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
|
||||
|
||||
final Block block = mock(Block.class);
|
||||
final BlockHeader blockHeader = mock(BlockHeader.class);
|
||||
final BlockBody blockBody = mock(BlockBody.class);
|
||||
final Transaction transaction = mock(Transaction.class);
|
||||
when(transaction.getGasLimit()).thenReturn(1000L);
|
||||
when(transaction.isGoQuorumPrivateTransaction(true)).thenReturn(true);
|
||||
when(transaction.getPayload()).thenReturn(Bytes.wrap(new byte[] {(byte) 1}));
|
||||
when(block.getBody()).thenReturn(blockBody);
|
||||
when(blockBody.getTransactions()).thenReturn(Collections.singletonList(transaction));
|
||||
when(blockBody.getOmmers()).thenReturn(Collections.emptyList());
|
||||
when(blockHeader.getNumber()).thenReturn(20000L);
|
||||
when(blockHeader.getGasLimit()).thenReturn(20000L);
|
||||
when(block.getHeader()).thenReturn(blockHeader);
|
||||
when(goQuorumEnclave.receive(any())).thenThrow(new EnclaveServerException(1, "a"));
|
||||
when(transactionProcessor.getTransactionValidator()).thenReturn(transactionValidator);
|
||||
when(transactionValidator.getGoQuorumCompatibilityMode()).thenReturn(true);
|
||||
|
||||
assertThatThrownBy(() -> blockProcessor.processBlock(blockchain, worldState, worldState, block))
|
||||
.isExactlyInstanceOf(EnclaveServerException.class)
|
||||
.hasMessageContaining("a");
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,6 @@ public class DefaultTimestampScheduleTest {
|
||||
config = new StubGenesisConfigOptions();
|
||||
config.chainId(chainId);
|
||||
boolean isRevertReasonEnabled = false;
|
||||
boolean quorumCompatibilityMode = false;
|
||||
builder =
|
||||
new TimestampScheduleBuilder(
|
||||
config,
|
||||
@@ -60,7 +59,6 @@ public class DefaultTimestampScheduleTest {
|
||||
ProtocolSpecAdapters.create(FIRST_TIMESTAMP_FORK, modifier),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -82,7 +80,6 @@ public class DefaultTimestampScheduleTest {
|
||||
ProtocolSpecAdapters.create(2L, modifier),
|
||||
privacyParameters,
|
||||
false,
|
||||
false,
|
||||
evmConfiguration);
|
||||
final TimestampSchedule schedule = builder.createTimestampSchedule();
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
|
||||
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -63,7 +61,6 @@ public class MainnetBlockProcessorTest extends AbstractBlockProcessorTest {
|
||||
Wei.ZERO,
|
||||
BlockHeader::getCoinbase,
|
||||
true,
|
||||
Optional.empty(),
|
||||
protocolSchedule);
|
||||
|
||||
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
|
||||
@@ -90,7 +87,6 @@ public class MainnetBlockProcessorTest extends AbstractBlockProcessorTest {
|
||||
Wei.ZERO,
|
||||
BlockHeader::getCoinbase,
|
||||
false,
|
||||
Optional.empty(),
|
||||
protocolSchedule);
|
||||
|
||||
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
|
||||
|
||||
@@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.GAS_PRICE_BELOW_CURRENT_BASE_FEE;
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.GAS_PRICE_MUST_BE_ZERO;
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INVALID_TRANSACTION_FORMAT;
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.MAX_PRIORITY_FEE_PER_GAS_EXCEEDS_MAX_FEE_PER_GAS;
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE;
|
||||
@@ -73,17 +72,11 @@ public class MainnetTransactionValidatorTest {
|
||||
.chainId(Optional.of(BigInteger.ONE))
|
||||
.createTransaction(senderKeys);
|
||||
|
||||
private final boolean defaultGoQuorumCompatibilityMode = false;
|
||||
|
||||
@Test
|
||||
public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
.gasLimit(10)
|
||||
@@ -100,11 +93,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionWhenTransactionHasChainIdAndValidatorDoesNot() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
assertThat(validator.validate(basicTransaction, Optional.empty(), transactionValidationParams))
|
||||
.isEqualTo(
|
||||
ValidationResult.invalid(
|
||||
@@ -118,8 +107,7 @@ public class MainnetTransactionValidatorTest {
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.valueOf(2)),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
Optional.of(BigInteger.valueOf(2)));
|
||||
assertThat(validator.validate(basicTransaction, Optional.empty(), transactionValidationParams))
|
||||
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.WRONG_CHAIN_ID));
|
||||
}
|
||||
@@ -128,11 +116,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionWhenSenderAccountDoesNotExist() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
assertThat(validator.validateForSender(basicTransaction, null, false))
|
||||
.isEqualTo(ValidationResult.invalid(TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE));
|
||||
}
|
||||
@@ -141,11 +125,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionWhenTransactionNonceBelowAccountNonce() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Account account = accountWithNonce(basicTransaction.getNonce() + 1);
|
||||
assertThat(validator.validateForSender(basicTransaction, account, false))
|
||||
@@ -157,11 +137,7 @@ public class MainnetTransactionValidatorTest {
|
||||
shouldRejectTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsNotAllowed() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
|
||||
assertThat(validator.validateForSender(basicTransaction, account, false))
|
||||
@@ -173,11 +149,7 @@ public class MainnetTransactionValidatorTest {
|
||||
shouldAcceptTransactionWhenTransactionNonceAboveAccountNonceAndFutureNonceIsAllowed() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Account account = accountWithNonce(basicTransaction.getNonce() - 1);
|
||||
assertThat(validator.validateForSender(basicTransaction, account, true))
|
||||
@@ -188,11 +160,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionWhenNonceExceedsMaximumAllowedNonce() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture().nonce(11).createTransaction(senderKeys);
|
||||
@@ -206,11 +174,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void transactionWithNullSenderCanBeValidIfGasPriceAndValueIsZero() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.of(BigInteger.ONE));
|
||||
|
||||
final TransactionTestFixture builder = new TransactionTestFixture();
|
||||
final KeyPair senderKeyPair = SIGNATURE_ALGORITHM.get().generateKeyPair();
|
||||
@@ -225,11 +189,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionIfAccountIsNotEOA() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setTransactionFilter(transactionFilter(false));
|
||||
|
||||
Account invalidEOA =
|
||||
@@ -246,11 +206,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionIfAccountIsNotPermitted() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setTransactionFilter(transactionFilter(false));
|
||||
|
||||
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), true))
|
||||
@@ -261,11 +217,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldAcceptValidTransactionIfAccountIsPermitted() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setTransactionFilter(transactionFilter(true));
|
||||
|
||||
assertThat(validator.validateForSender(basicTransaction, accountWithNonce(0), true))
|
||||
@@ -276,11 +228,7 @@ public class MainnetTransactionValidatorTest {
|
||||
public void shouldRejectTransactionWithMaxFeeTimesGasLimitGreaterThanBalance() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setTransactionFilter(transactionFilter(true));
|
||||
|
||||
assertThat(
|
||||
@@ -314,7 +262,6 @@ public class MainnetTransactionValidatorTest {
|
||||
new TransactionType[] {
|
||||
TransactionType.FRONTIER, TransactionType.ACCESS_LIST, TransactionType.EIP1559
|
||||
}),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
validator.setTransactionFilter(transactionFilter(true));
|
||||
|
||||
@@ -354,11 +301,7 @@ public class MainnetTransactionValidatorTest {
|
||||
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setTransactionFilter(transactionFilter);
|
||||
|
||||
final TransactionValidationParams validationParams =
|
||||
@@ -376,11 +319,7 @@ public class MainnetTransactionValidatorTest {
|
||||
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator,
|
||||
GasLimitCalculator.constant(),
|
||||
false,
|
||||
Optional.empty(),
|
||||
defaultGoQuorumCompatibilityMode);
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
|
||||
validator.setTransactionFilter(transactionFilter);
|
||||
|
||||
final TransactionValidationParams validationParams =
|
||||
@@ -407,7 +346,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
final MainnetTransactionValidator eip1559Validator =
|
||||
@@ -418,7 +356,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
final Transaction transaction =
|
||||
@@ -452,7 +389,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
@@ -477,7 +413,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
@@ -501,7 +436,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
@@ -527,7 +461,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
Integer.MAX_VALUE);
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
@@ -554,7 +487,6 @@ public class MainnetTransactionValidatorTest {
|
||||
false,
|
||||
Optional.of(BigInteger.ONE),
|
||||
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
|
||||
defaultGoQuorumCompatibilityMode,
|
||||
0xc000);
|
||||
|
||||
var bigPayload =
|
||||
@@ -572,49 +504,6 @@ public class MainnetTransactionValidatorTest {
|
||||
.isEqualTo("Initcode size of 49153 exceeds maximum size of 49152");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void goQuorumCompatibilityModeRejectNonZeroGasPrice() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty(), true);
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
.gasPrice(Wei.ONE)
|
||||
.chainId(Optional.empty())
|
||||
.createTransaction(senderKeys);
|
||||
|
||||
assertThat(
|
||||
validator
|
||||
.validate(transaction, Optional.empty(), transactionValidationParams)
|
||||
.isValid())
|
||||
.isFalse();
|
||||
assertThat(
|
||||
validator
|
||||
.validate(transaction, Optional.empty(), transactionValidationParams)
|
||||
.getInvalidReason())
|
||||
.isEqualTo(GAS_PRICE_MUST_BE_ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void goQuorumCompatibilityModeSuccessZeroGasPrice() {
|
||||
final MainnetTransactionValidator validator =
|
||||
new MainnetTransactionValidator(
|
||||
gasCalculator, GasLimitCalculator.constant(), false, Optional.empty(), true);
|
||||
final Transaction transaction =
|
||||
new TransactionTestFixture()
|
||||
.gasPrice(Wei.ZERO)
|
||||
.chainId(Optional.empty())
|
||||
.createTransaction(senderKeys);
|
||||
|
||||
when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
|
||||
|
||||
assertThat(
|
||||
validator
|
||||
.validate(transaction, Optional.empty(), transactionValidationParams)
|
||||
.isValid())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
private Account accountWithNonce(final long nonce) {
|
||||
return account(basicTransaction.getUpfrontCost(0L), nonce);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ public class MutableProtocolScheduleTest {
|
||||
config = new StubGenesisConfigOptions();
|
||||
config.chainId(DEFAULT_CHAIN_ID);
|
||||
boolean isRevertReasonEnabled = false;
|
||||
boolean quorumCompatibilityMode = false;
|
||||
builder =
|
||||
new ProtocolScheduleBuilder(
|
||||
config,
|
||||
@@ -61,7 +60,6 @@ public class MutableProtocolScheduleTest {
|
||||
ProtocolSpecAdapters.create(FIRST_TIMESTAMP_FORK, modifier),
|
||||
new PrivacyParameters(),
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
EvmConfiguration.DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public class ProtocolScheduleBuilderTest {
|
||||
ProtocolSpecAdapters.create(0, Function.identity()),
|
||||
new PrivacyParameters(),
|
||||
false,
|
||||
false,
|
||||
EvmConfiguration.DEFAULT);
|
||||
}
|
||||
|
||||
@@ -166,7 +165,6 @@ public class ProtocolScheduleBuilderTest {
|
||||
ProtocolSpecAdapters.create(blockNumber, modifier),
|
||||
new PrivacyParameters(),
|
||||
false,
|
||||
false,
|
||||
EvmConfiguration.DEFAULT);
|
||||
|
||||
return new BlockNumberStreamingProtocolSchedule(
|
||||
|
||||
@@ -45,7 +45,6 @@ public class TimestampScheduleBuilderTest {
|
||||
config = new StubGenesisConfigOptions();
|
||||
config.chainId(chainId);
|
||||
boolean isRevertReasonEnabled = false;
|
||||
boolean quorumCompatibilityMode = false;
|
||||
builder =
|
||||
new TimestampScheduleBuilder(
|
||||
config,
|
||||
@@ -53,7 +52,6 @@ public class TimestampScheduleBuilderTest {
|
||||
ProtocolSpecAdapters.create(FIRST_TIMESTAMP_FORK, modifier),
|
||||
privacyParameters,
|
||||
isRevertReasonEnabled,
|
||||
quorumCompatibilityMode,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
|
||||
@@ -82,7 +81,6 @@ public class TransactionSimulatorTest {
|
||||
@Mock private ProtocolSchedule protocolSchedule;
|
||||
@Mock private ProtocolSpec protocolSpec;
|
||||
@Mock private MainnetTransactionProcessor transactionProcessor;
|
||||
@Mock private MainnetTransactionValidator transactionValidator;
|
||||
|
||||
private final BlockHeaderTestFixture blockHeaderTestFixture = new BlockHeaderTestFixture();
|
||||
|
||||
@@ -90,9 +88,6 @@ public class TransactionSimulatorTest {
|
||||
public void setUp() {
|
||||
this.transactionSimulator =
|
||||
new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule);
|
||||
|
||||
when(transactionProcessor.getTransactionValidator()).thenReturn(transactionValidator);
|
||||
when(transactionValidator.getGoQuorumCompatibilityMode()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package org.hyperledger.besu.ethereum.eth.transactions;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedStatus.ADDED;
|
||||
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedStatus.ALREADY_KNOWN;
|
||||
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_NOT_AVAILABLE;
|
||||
@@ -355,15 +354,6 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
private TransactionInvalidReason validatePrice(
|
||||
final Transaction transaction, final boolean isLocal, final FeeMarket feeMarket) {
|
||||
|
||||
// Check whether it's a GoQuorum transaction
|
||||
boolean goQuorumCompatibilityMode = getTransactionValidator().getGoQuorumCompatibilityMode();
|
||||
if (transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)) {
|
||||
final Optional<Wei> weiValue = ofNullable(transaction.getValue());
|
||||
if (weiValue.isPresent() && !weiValue.get().isZero()) {
|
||||
return TransactionInvalidReason.ETHER_VALUE_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLocal) {
|
||||
if (!configuration.getTxFeeCap().isZero()
|
||||
&& getMaxGasPrice(transaction).get().greaterThan(configuration.getTxFeeCap())) {
|
||||
|
||||
@@ -259,7 +259,6 @@ public class MessageWrapperTest {
|
||||
recIdAndChainId(Byte.decode(v)).getKey()),
|
||||
Bytes.fromHexString(data),
|
||||
recIdAndChainId(Byte.decode(v)).getValue(),
|
||||
Optional.empty(),
|
||||
Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -346,7 +345,6 @@ public abstract class AbstractTransactionPoolTest {
|
||||
transactionPool.addRemoteTransactions(singletonList(transaction));
|
||||
|
||||
assertTransactionNotPending(transaction);
|
||||
verify(transactionValidator).getGoQuorumCompatibilityMode();
|
||||
verifyNoMoreInteractions(transactionValidator);
|
||||
}
|
||||
|
||||
@@ -380,7 +378,6 @@ public abstract class AbstractTransactionPoolTest {
|
||||
.validateForSender(eq(transaction1), eq(null), any(TransactionValidationParams.class));
|
||||
verify(transactionValidator).validate(eq(transaction2), any(Optional.class), any());
|
||||
verify(transactionValidator).validateForSender(eq(transaction2), any(), any());
|
||||
verify(transactionValidator, atLeastOnce()).getGoQuorumCompatibilityMode();
|
||||
verifyNoMoreInteractions(transactionValidator);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user