Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reduce use of global quorum config #2805

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ void setBannedNodeIds(final List<String> values) {
private Vertx vertx;
private EnodeDnsConfiguration enodeDnsConfiguration;
private KeyValueStorageProvider keyValueStorageProvider;
private Boolean isGoQuorumCompatibilityMode = false;
protected Boolean isGoQuorumCompatibilityMode = false;

public BesuCommand(
final Logger logger,
Expand Down Expand Up @@ -1208,9 +1208,7 @@ public void run() {
if (genesisFile != null) {
genesisConfigOptions = readGenesisConfigOptions();
if (genesisConfigOptions.isQuorum()) {
// this static flag is read by the RLP decoder
GoQuorumOptions.goQuorumCompatibilityMode = true;
isGoQuorumCompatibilityMode = true;
enableGoQuorumCompatibilityMode();
}
}

Expand Down Expand Up @@ -2762,4 +2760,10 @@ private Optional<String> getEcCurveFromGenesisFile() {
}
return genesisConfigOptions.getEcCurve();
}

protected void enableGoQuorumCompatibilityMode() {
// this static flag is read by the RLP decoder
GoQuorumOptions.setGoQuorumCompatibilityMode(true);
isGoQuorumCompatibilityMode = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,14 @@ protected Vertx createVertx(final VertxOptions vertxOptions) {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,30 @@
* with MainNet.
*/
public class GoQuorumOptions {
// To make it easier for tests to reset the value to default
public static final boolean GOQUORUM_COMPATIBILITY_MODE_DEFAULT_VALUE = false;
private static final boolean GOQUORUM_COMPATIBILITY_MODE_DEFAULT_VALUE = false;

public static boolean goQuorumCompatibilityMode = GOQUORUM_COMPATIBILITY_MODE_DEFAULT_VALUE;
private static Boolean goQuorumCompatibilityMode;

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");
}
}

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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ DataFetcher<Optional<TransactionAdapter>> getTransactionDataFetcher() {
private TransactionAdapter getTransactionAdapter(
final TransactionWithMetadata transactionWithMetadata) {
final Transaction transaction = transactionWithMetadata.getTransaction();
return goQuorumPrivacyParameters.isPresent() && transaction.isGoQuorumPrivateTransaction()
final boolean isGoQuorumCompatbilityMode = goQuorumPrivacyParameters.isPresent();
final boolean isGoQuorumPrivateTransaction =
isGoQuorumCompatbilityMode
&& transaction.isGoQuorumPrivateTransaction(isGoQuorumCompatbilityMode);
return isGoQuorumPrivateTransaction
? updatePrivatePayload(transaction)
: new TransactionAdapter(transactionWithMetadata);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
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;
Expand Down Expand Up @@ -187,12 +188,14 @@ public List<LogAdapter> getLogs(final DataFetchingEnvironment environment) {
}

public boolean getIsPrivate() {
return transactionWithMetadata.getTransaction().isGoQuorumPrivateTransaction();
return transactionWithMetadata
.getTransaction()
.isGoQuorumPrivateTransaction(GoQuorumOptions.getGoQuorumCompatibilityMode());
}

public Optional<Bytes> getPrivateInputData() {
final Transaction transaction = transactionWithMetadata.getTransaction();
if (transaction.isGoQuorumPrivateTransaction()) {
if (transaction.isGoQuorumPrivateTransaction(GoQuorumOptions.getGoQuorumCompatibilityMode())) {
return Optional.ofNullable(transaction.getPayload());
}
return Optional.of(Bytes.EMPTY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import static org.hyperledger.besu.ethereum.goquorum.GoQuorumPrivateStateUtil.getPrivateWorldStateAtBlock;

import org.hyperledger.besu.config.GoQuorumOptions;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
Expand Down Expand Up @@ -64,7 +63,8 @@ protected BlockParameterOrBlockHash blockParameterOrBlockHash(
@Override
protected String resultByBlockHash(final JsonRpcRequestContext request, final Hash blockHash) {
final Address address = request.getRequiredParameter(0, Address.class);
if (GoQuorumOptions.goQuorumCompatibilityMode && privacyParameters.isPresent()) {
if (privacyParameters.isPresent()
&& privacyParameters.get().getGoQuorumPrivacyParameters().isPresent()) {
// get from private state if we can
final Optional<BlockHeader> blockHeader =
blockchainQueries.get().getBlockHeaderByHash(blockHash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
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;
Expand All @@ -30,6 +31,7 @@
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;
Expand All @@ -47,14 +49,28 @@ public class GoQuorumSendRawPrivateTransaction implements JsonRpcMethod {
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
Expand All @@ -72,7 +88,8 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {

try {
final Transaction transaction =
Transaction.readFrom(RLP.input(Bytes.fromHexString(rawPrivateTransaction)));
TransactionDecoder.decodeForWire(
RLP.input(Bytes.fromHexString(rawPrivateTransaction)), goQuorumCompatibilityMode);

checkAndHandlePrivateTransaction(transaction, rawTxArgs, requestContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
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;
Expand All @@ -30,7 +31,8 @@ public static Transaction decodeRawTransaction(final String rawTransaction)
throws InvalidJsonRpcRequestException {
try {
Bytes txnBytes = Bytes.fromHexString(rawTransaction);
return TransactionDecoder.decodeOpaqueBytes(txnBytes);
final boolean isGoQuorumCompatibilityMode = GoQuorumOptions.getGoQuorumCompatibilityMode();
return TransactionDecoder.decodeOpaqueBytes(txnBytes, isGoQuorumCompatibilityMode);
} catch (final IllegalArgumentException | RLPException e) {
LOG.debug(e);
throw new InvalidJsonRpcRequestException("Invalid raw transaction hex", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.config.GoQuorumOptions;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
Expand Down Expand Up @@ -80,7 +79,10 @@ public class GoQuorumSendRawPrivateTransactionTest {

@Before
public void before() {
method = new GoQuorumSendRawPrivateTransaction(enclave, transactionPool, privacyIdProvider);
boolean goQuorumCompatibilityMode = true;
method =
new GoQuorumSendRawPrivateTransaction(
enclave, transactionPool, privacyIdProvider, goQuorumCompatibilityMode);
}

@Test
Expand Down Expand Up @@ -126,8 +128,6 @@ public void requestHasNullArrayParameter() {

@Test
public void validTransactionIsSentToTransactionPool() {
GoQuorumOptions.goQuorumCompatibilityMode = true;

when(enclave.sendSignedTransaction(any(), any())).thenReturn(null);

when(transactionPool.addLocalTransaction(any(Transaction.class)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,13 @@ private TransactionSelectionResult evaluateTransaction(final Transaction transac

final WorldUpdater worldStateUpdater = worldState.updater();
final BlockHashLookup blockHashLookup = new BlockHashLookup(processableBlockHeader, blockchain);
final boolean isGoQuorumPrivateTransaction =
transaction.isGoQuorumPrivateTransaction(
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());

TransactionProcessingResult effectiveResult;

if (transaction.isGoQuorumPrivateTransaction()) {
if (isGoQuorumPrivateTransaction) {
final ValidationResult<TransactionInvalidReason> validationResult =
validateTransaction(processableBlockHeader, transaction, worldStateUpdater);
if (!validationResult.isValid()) {
Expand Down Expand Up @@ -280,10 +283,12 @@ Responsible for updating the state maintained between transaction validation (i.
*/
private void updateTransactionResultTracking(
final Transaction transaction, final TransactionProcessingResult result) {
final boolean isGoQuorumPrivateTransaction =
transaction.isGoQuorumPrivateTransaction(
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());

final long gasUsedByTransaction =
transaction.isGoQuorumPrivateTransaction()
? 0
: transaction.getGasLimit() - result.getGasRemaining();
isGoQuorumPrivateTransaction ? 0 : transaction.getGasLimit() - result.getGasRemaining();

final long cumulativeGasUsed =
transactionSelectionResult.getCumulativeGasUsed() + gasUsedByTransaction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.hyperledger.besu.ethereum.eth.transactions.sorter.BaseFeePendingTransactionsSorter;
import org.hyperledger.besu.ethereum.eth.transactions.sorter.GasPricePendingTransactionsSorter;
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.ValidationResult;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
Expand All @@ -66,8 +67,13 @@
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
import org.assertj.core.api.Assertions;
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 BlockTransactionSelectorTest {

private static final KeyPair keyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
Expand All @@ -85,8 +91,14 @@ public class BlockTransactionSelectorTest {
TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
private final MutableWorldState worldState =
InMemoryKeyValueStorageProvider.createInMemoryWorldState();
private final MainnetTransactionProcessor transactionProcessor =
mock(MainnetTransactionProcessor.class);
@Mock private MainnetTransactionProcessor transactionProcessor;
@Mock private MainnetTransactionValidator transactionValidator;

@Before
public void setup() {
when(transactionProcessor.getTransactionValidator()).thenReturn(transactionValidator);
when(transactionValidator.getGoQuorumCompatibilityMode()).thenReturn(true);
}

private static BlockHeader mockBlockHeader() {
final BlockHeader blockHeader = mock(BlockHeader.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -661,9 +661,13 @@ public TransactionType getType() {
* A GoQuorum private transaction has its <i>v</i> value equal to 37 or 38, and does not contain a
* chainId.
*
* @param goQuorumCompatibilityMode true if GoQuorum compatbility mode is set
* @return true if GoQuorum private transaction, false otherwise
*/
public boolean isGoQuorumPrivateTransaction() {
public boolean isGoQuorumPrivateTransaction(final boolean goQuorumCompatibilityMode) {
if (!goQuorumCompatibilityMode) {
return false;
}
if (chainId.isPresent()) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand Down Expand Up @@ -61,8 +62,13 @@ interface Decoder {
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);
return decodeFrontier(rlpInput, goQuorumCompatibilityMode);
} else {
final Bytes typedTransactionBytes = rlpInput.readBytes();
final TransactionType transactionType =
Expand All @@ -71,12 +77,13 @@ public static Transaction decodeForWire(final RLPInput rlpInput) {
}
}

public static Transaction decodeOpaqueBytes(final Bytes input) {
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));
return decodeForWire(RLP.input(input), goQuorumCompatibilityMode);
}
return getDecoder(transactionType).decode(RLP.input(input.slice(1)));
}
Expand All @@ -88,7 +95,7 @@ private static Decoder getDecoder(final TransactionType transactionType) {
transactionType);
}

static Transaction decodeFrontier(final RLPInput input) {
static Transaction decodeFrontier(final RLPInput input, final boolean goQuorumCompatibilityMode) {
input.enterList();
final Transaction.Builder builder =
Transaction.builder()
Expand All @@ -103,7 +110,8 @@ static Transaction decodeFrontier(final RLPInput input) {
final BigInteger v = input.readBigIntegerScalar();
final byte recId;
Optional<BigInteger> chainId = Optional.empty();
if (GoQuorumPrivateTransactionDetector.isGoQuorumPrivateTransactionV(v)) {
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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ public Result processBlock(
WorldUpdater effectiveWorldUpdater = null;
Transaction effectiveTransaction;

final boolean isGoQuorumPrivateTransaction = transaction.isGoQuorumPrivateTransaction();
final boolean isGoQuorumPrivateTransaction =
transaction.isGoQuorumPrivateTransaction(
transactionProcessor.getTransactionValidator().getGoQuorumCompatibilityMode());

if (isGoQuorumPrivateTransaction) { // private transaction
try {
Expand Down
Loading