PIE-1792: Added chainId validation to PrivateTransactionValidator (#1741)

* PIE-1792: Added chainId validation to PrivateTransactionValidator
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Lucas Saldanha 5 years ago committed by GitHub
parent 46eb7ef590
commit d215ff5acf
  1. 20
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java
  2. 4
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java
  3. 25
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java
  4. 7
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionHandler.java
  5. 5
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionProcessor.java
  6. 52
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionValidator.java
  7. 139
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/PrivateTransactionTestFixture.java
  8. 73
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionValidatorTest.java
  9. 2
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java
  10. 2
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcMethodsFactory.java

@ -29,6 +29,7 @@ import tech.pegasys.pantheon.ethereum.core.WorldState;
import tech.pegasys.pantheon.ethereum.core.WorldUpdater;
import tech.pegasys.pantheon.ethereum.mainnet.contractvalidation.MaxCodeSizeRule;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionProcessor;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import java.io.IOException;
import java.math.BigInteger;
@ -107,7 +108,8 @@ public abstract class MainnetProtocolSpecs {
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionValidator,
@ -115,7 +117,8 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
false,
stackSizeLimit,
Account.DEFAULT_VERSION))
Account.DEFAULT_VERSION,
new PrivateTransactionValidator(Optional.empty())))
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::create)
.ommerHeaderValidatorBuilder(MainnetBlockHeaderValidator::createOmmerValidator)
@ -223,11 +226,13 @@ public abstract class MainnetProtocolSpecs {
true,
stackSizeLimit,
Account.DEFAULT_VERSION))
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(chainId))
.privateTransactionProcessorBuilder(
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionValidator,
@ -235,7 +240,8 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
false,
stackSizeLimit,
Account.DEFAULT_VERSION))
Account.DEFAULT_VERSION,
privateTransactionValidator))
.name("SpuriousDragon");
}
@ -312,7 +318,8 @@ public abstract class MainnetProtocolSpecs {
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionValidator,
@ -320,7 +327,8 @@ public abstract class MainnetProtocolSpecs {
messageCallProcessor,
false,
stackSizeLimit,
ISTANBUL_ACCOUNT_VERSION))
ISTANBUL_ACCOUNT_VERSION,
privateTransactionValidator))
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
new MainnetContractCreationProcessor(

@ -14,6 +14,7 @@ package tech.pegasys.pantheon.ethereum.mainnet;
import tech.pegasys.pantheon.config.GenesisConfigOptions;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import java.math.BigInteger;
import java.util.Optional;
@ -24,6 +25,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ProtocolScheduleBuilder<C> {
private static final Logger LOG = LogManager.getLogger();
private final GenesisConfigOptions config;
private final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter;
@ -163,6 +165,8 @@ public class ProtocolScheduleBuilder<C> {
protocolSpecAdapter
.apply(definition)
.privacyParameters(privacyParameters)
.privateTransactionValidatorBuilder(
() -> new PrivateTransactionValidator(protocolSchedule.getChainId()))
.build(protocolSchedule)));
}

@ -24,6 +24,7 @@ import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockProcessor.TransactionReceiptFactory;
import tech.pegasys.pantheon.ethereum.mainnet.precompiles.privacy.PrivacyPrecompiledContract;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionProcessor;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import tech.pegasys.pantheon.ethereum.vm.EVM;
import tech.pegasys.pantheon.ethereum.vm.GasCalculator;
@ -56,6 +57,7 @@ public class ProtocolSpecBuilder<T> {
private MiningBeneficiaryCalculator miningBeneficiaryCalculator;
private PrivacyParameters privacyParameters;
private PrivateTransactionProcessorBuilder privateTransactionProcessorBuilder;
private PrivateTransactionValidatorBuilder privateTransactionValidatorBuilder;
public ProtocolSpecBuilder<T> gasCalculator(final Supplier<GasCalculator> gasCalculatorBuilder) {
this.gasCalculatorBuilder = gasCalculatorBuilder;
@ -160,6 +162,12 @@ public class ProtocolSpecBuilder<T> {
return this;
}
public ProtocolSpecBuilder<T> privateTransactionValidatorBuilder(
final PrivateTransactionValidatorBuilder privateTransactionValidatorBuilder) {
this.privateTransactionValidatorBuilder = privateTransactionValidatorBuilder;
return this;
}
public ProtocolSpecBuilder<T> blockProcessorBuilder(
final BlockProcessorBuilder blockProcessorBuilder) {
this.blockProcessorBuilder = blockProcessorBuilder;
@ -211,6 +219,7 @@ public class ProtocolSpecBuilder<T> {
.gasCalculator(gasCalculatorBuilder)
.evmBuilder(evmBuilder)
.transactionValidatorBuilder(transactionValidatorBuilder)
.privateTransactionValidatorBuilder(privateTransactionValidatorBuilder)
.contractCreationProcessorBuilder(contractCreationProcessorBuilder)
.privacyParameters(privacyParameters)
.precompileContractRegistryBuilder(precompileContractRegistryBuilder)
@ -236,6 +245,7 @@ public class ProtocolSpecBuilder<T> {
checkNotNull(gasCalculatorBuilder, "Missing gasCalculator");
checkNotNull(evmBuilder, "Missing operation registry");
checkNotNull(transactionValidatorBuilder, "Missing transaction validator");
checkNotNull(privateTransactionValidatorBuilder, "Missing private transaction validator");
checkNotNull(contractCreationProcessorBuilder, "Missing contract creation processor");
checkNotNull(precompileContractRegistryBuilder, "Missing precompile contract registry");
checkNotNull(messageCallProcessorBuilder, "Missing message call processor");
@ -274,9 +284,15 @@ public class ProtocolSpecBuilder<T> {
// Set private Tx Processor
if (privacyParameters.isEnabled()) {
final PrivateTransactionValidator privateTransactionValidator =
privateTransactionValidatorBuilder.apply();
final PrivateTransactionProcessor privateTransactionProcessor =
privateTransactionProcessorBuilder.apply(
gasCalculator, transactionValidator, contractCreationProcessor, messageCallProcessor);
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
privateTransactionValidator);
Address address = Address.privacyPrecompiled(privacyParameters.getPrivacyAddress());
PrivacyPrecompiledContract privacyPrecompiledContract =
(PrivacyPrecompiledContract)
@ -332,7 +348,12 @@ public class ProtocolSpecBuilder<T> {
GasCalculator gasCalculator,
TransactionValidator transactionValidator,
AbstractMessageProcessor contractCreationProcessor,
AbstractMessageProcessor messageCallProcessor);
AbstractMessageProcessor messageCallProcessor,
PrivateTransactionValidator privateTransactionValidator);
}
public interface PrivateTransactionValidatorBuilder {
PrivateTransactionValidator apply();
}
public interface BlockProcessorBuilder {

@ -31,7 +31,9 @@ import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
@ -50,7 +52,8 @@ public class PrivateTransactionHandler {
private final WorldStateArchive privateWorldStateArchive;
private final PrivateTransactionValidator privateTransactionValidator;
public PrivateTransactionHandler(final PrivacyParameters privacyParameters) {
public PrivateTransactionHandler(
final PrivacyParameters privacyParameters, final Optional<BigInteger> chainId) {
this(
new Enclave(privacyParameters.getEnclaveUri()),
Address.privacyPrecompiled(privacyParameters.getPrivacyAddress()),
@ -58,7 +61,7 @@ public class PrivateTransactionHandler {
privacyParameters.getEnclavePublicKey(),
privacyParameters.getPrivateStateStorage(),
privacyParameters.getPrivateWorldStateArchive(),
new PrivateTransactionValidator());
new PrivateTransactionValidator(chainId));
}
public PrivateTransactionHandler(

@ -163,15 +163,16 @@ public class PrivateTransactionProcessor {
final AbstractMessageProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final int maxStackSize,
final int createContractAccountVersion) {
final int createContractAccountVersion,
final PrivateTransactionValidator privateTransactionValidator) {
this.gasCalculator = gasCalculator;
this.transactionValidator = transactionValidator;
this.privateTransactionValidator = new PrivateTransactionValidator();
this.contractCreationProcessor = contractCreationProcessor;
this.messageCallProcessor = messageCallProcessor;
this.clearEmptyAccounts = clearEmptyAccounts;
this.maxStackSize = maxStackSize;
this.createContractAccountVersion = createContractAccountVersion;
this.privateTransactionValidator = privateTransactionValidator;
}
@SuppressWarnings("unused")

@ -13,20 +13,41 @@
package tech.pegasys.pantheon.ethereum.privacy;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.INCORRECT_PRIVATE_NONCE;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.INVALID_SIGNATURE;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.PRIVATE_NONCE_TOO_LOW;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.WRONG_CHAIN_ID;
import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason;
import tech.pegasys.pantheon.ethereum.mainnet.ValidationResult;
import java.math.BigInteger;
import java.util.Optional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
class PrivateTransactionValidator {
public class PrivateTransactionValidator {
private static final Logger LOG = LogManager.getLogger();
private final Optional<BigInteger> chainId;
public PrivateTransactionValidator(final Optional<BigInteger> chainId) {
this.chainId = chainId;
}
public ValidationResult<TransactionInvalidReason> validate(
final PrivateTransaction transaction, final Long accountNonce) {
LOG.debug("Validating private transaction {} signature ", transaction.hash());
ValidationResult<TransactionInvalidReason> signatureValidationResult =
validateTransactionSignature(transaction);
if (!signatureValidationResult.isValid()) {
return signatureValidationResult;
}
final long transactionNonce = transaction.getNonce();
LOG.debug("Validating actual nonce {} with expected nonce {}", transactionNonce, accountNonce);
@ -49,4 +70,33 @@ class PrivateTransactionValidator {
return ValidationResult.valid();
}
public ValidationResult<TransactionInvalidReason> validateTransactionSignature(
final PrivateTransaction transaction) {
if (chainId.isPresent()
&& (transaction.getChainId().isPresent() && !transaction.getChainId().equals(chainId))) {
return ValidationResult.invalid(
WRONG_CHAIN_ID,
String.format(
"transaction was meant for chain id %s and not this chain id %s",
transaction.getChainId().get(), chainId.get()));
}
if (!chainId.isPresent() && transaction.getChainId().isPresent()) {
return ValidationResult.invalid(
REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED,
"replay protected signatures is not supported");
}
// org.bouncycastle.math.ec.ECCurve.AbstractFp.decompressPoint throws an
// IllegalArgumentException for "Invalid point compression" for bad signatures.
try {
transaction.getSender();
} catch (final IllegalArgumentException e) {
return ValidationResult.invalid(
INVALID_SIGNATURE, "sender could not be extracted from transaction signature");
}
return ValidationResult.valid();
}
}

@ -0,0 +1,139 @@
/*
* Copyright 2018 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.
*/
package tech.pegasys.pantheon.ethereum.core;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.ethereum.privacy.Restriction;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
public class PrivateTransactionTestFixture {
private long nonce = 0;
private Wei gasPrice = Wei.of(5);
private long gasLimit = 5000;
private Optional<Address> to = Optional.empty();
private Address sender = Address.fromHexString(String.format("%020x", 1));
private Wei value = Wei.of(4);
private BytesValue payload = BytesValue.EMPTY;
private Optional<BigInteger> chainId = Optional.of(BigInteger.valueOf(2018));
private BytesValue privateFrom =
BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=");
private Optional<List<BytesValue>> privateFor =
Optional.of(
Lists.newArrayList(
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")));
private Optional<BytesValue> privacyGroupId = Optional.empty();
private Restriction restriction = Restriction.RESTRICTED;
public PrivateTransaction createTransaction(final KeyPair keys) {
final PrivateTransaction.Builder builder = PrivateTransaction.builder();
builder
.gasLimit(gasLimit)
.gasPrice(gasPrice)
.nonce(nonce)
.payload(payload)
.value(value)
.sender(sender)
.privateFrom(privateFrom)
.restriction(restriction);
to.ifPresent(builder::to);
chainId.ifPresent(builder::chainId);
if (privacyGroupId.isPresent()) {
this.privacyGroupId(privacyGroupId.get());
} else {
privateFor.ifPresent(builder::privateFor);
}
if (privacyGroupId.isEmpty() && privateFor.isEmpty()) {
throw new IllegalArgumentException(
"Private transaction needs a privacyGroupId or privateFor field");
}
return builder.signAndBuild(keys);
}
public PrivateTransactionTestFixture nonce(final long nonce) {
this.nonce = nonce;
return this;
}
public PrivateTransactionTestFixture gasPrice(final Wei gasPrice) {
this.gasPrice = gasPrice;
return this;
}
public PrivateTransactionTestFixture gasLimit(final long gasLimit) {
this.gasLimit = gasLimit;
return this;
}
public PrivateTransactionTestFixture to(final Optional<Address> to) {
this.to = to;
return this;
}
public PrivateTransactionTestFixture sender(final Address sender) {
this.sender = sender;
return this;
}
public PrivateTransactionTestFixture value(final Wei value) {
this.value = value;
return this;
}
public PrivateTransactionTestFixture payload(final BytesValue payload) {
this.payload = payload;
return this;
}
public PrivateTransactionTestFixture chainId(final Optional<BigInteger> chainId) {
this.chainId = chainId;
return this;
}
public PrivateTransactionTestFixture privateFrom(final BytesValue privateFrom) {
this.privateFrom = privateFrom;
return this;
}
public PrivateTransactionTestFixture privateFor(final List<BytesValue> privateFor) {
this.privateFor = Optional.of(privateFor);
return this;
}
public PrivateTransactionTestFixture privacyGroupId(final BytesValue privacyGroupId) {
this.privacyGroupId = Optional.of(privacyGroupId);
return this;
}
}

@ -13,27 +13,34 @@
package tech.pegasys.pantheon.ethereum.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.INCORRECT_PRIVATE_NONCE;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.INVALID_SIGNATURE;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.PRIVATE_NONCE_TOO_LOW;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.WRONG_CHAIN_ID;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.core.PrivateTransactionTestFixture;
import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason;
import tech.pegasys.pantheon.ethereum.mainnet.ValidationResult;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class PrivateTransactionValidatorTest {
private static final KeyPair senderKeys = KeyPair.generate();
private PrivateTransactionValidator validator;
@Before
public void before() {
validator = new PrivateTransactionValidator();
validator = new PrivateTransactionValidator(Optional.empty());
}
@Test
@ -60,17 +67,51 @@ public class PrivateTransactionValidatorTest {
assertThat(validationResult).isEqualTo(ValidationResult.valid());
}
private static PrivateTransaction privateTransactionWithNonce(final long nonce) {
return PrivateTransaction.builder()
.nonce(nonce)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57"))
.value(Wei.ZERO)
.payload(BytesValue.fromHexString("0x"))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(BigInteger.valueOf(2018))
.restriction(Restriction.RESTRICTED)
.build();
@Test
public void transactionWithInvalidChainIdShouldReturnWrongChainId() {
validator = new PrivateTransactionValidator(Optional.of(BigInteger.ONE));
ValidationResult<TransactionInvalidReason> validationResult =
validator.validate(privateTransactionWithChainId(999), 0L);
assertThat(validationResult).isEqualTo(ValidationResult.invalid(WRONG_CHAIN_ID));
}
@Test
public void
transactionWithoutChainIdWithValidatorUsingChainIdShouldReturnReplayProtectedSignaturesNotSupported() {
validator = new PrivateTransactionValidator(Optional.empty());
ValidationResult<TransactionInvalidReason> validationResult =
validator.validate(privateTransactionWithChainId(999), 0L);
assertThat(validationResult)
.isEqualTo(ValidationResult.invalid(REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED));
}
@Test
public void transactionWithInvalidSignatureShouldReturnInvalidSignature() {
PrivateTransaction transactionWithInvalidSignature = spy(privateTransactionWithNonce(1L));
when(transactionWithInvalidSignature.getSender()).thenThrow(new IllegalArgumentException());
ValidationResult<TransactionInvalidReason> validationResult =
validator.validate(transactionWithInvalidSignature, 1L);
assertThat(validationResult).isEqualTo(ValidationResult.invalid(INVALID_SIGNATURE));
}
private PrivateTransaction privateTransactionWithNonce(final long nonce) {
PrivateTransactionTestFixture privateTransactionTestFixture =
new PrivateTransactionTestFixture();
privateTransactionTestFixture.nonce(nonce);
privateTransactionTestFixture.chainId(Optional.empty());
return privateTransactionTestFixture.createTransaction(senderKeys);
}
private PrivateTransaction privateTransactionWithChainId(final int chainId) {
PrivateTransactionTestFixture privateTransactionTestFixture =
new PrivateTransactionTestFixture();
privateTransactionTestFixture.chainId(Optional.of(BigInteger.valueOf(chainId)));
return privateTransactionTestFixture.createTransaction(senderKeys);
}
}

@ -25,6 +25,7 @@ import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSpecs;
import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import tech.pegasys.pantheon.ethereum.vm.ehalt.ExceptionalHaltException;
import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState;
import tech.pegasys.pantheon.testutil.JsonTestParameters;
@ -122,6 +123,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
final ProtocolSpec<Void> protocolSpec =
MainnetProtocolSpecs.frontierDefinition(OptionalInt.empty(), OptionalInt.empty())
.privacyParameters(PrivacyParameters.DEFAULT)
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(CHAIN_ID))
.build(new MutableProtocolSchedule<>(CHAIN_ID));
final TestBlockchain blockchain = new TestBlockchain(execEnv.getBlockHeader().getNumber());

@ -323,7 +323,7 @@ public class JsonRpcMethodsFactory {
}
if (rpcApis.contains(RpcApis.EEA)) {
final PrivateTransactionHandler privateTransactionHandler =
new PrivateTransactionHandler(privacyParameters);
new PrivateTransactionHandler(privacyParameters, protocolSchedule.getChainId());
final Enclave enclave = new Enclave(privacyParameters.getEnclaveUri());
addMethods(
enabledMethods,

Loading…
Cancel
Save