[PAN-2829] - add hooks for validation (#1671)

EIP-1602 specifies a new validation step.  Add hooks for those to occur.
Move contract size checking into the validation hooks.

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Danno Ferrin 5 years ago committed by GitHub
parent 9a9b7e9dd6
commit ab6962b37f
  1. 4
      errorprone-checks/build.gradle
  2. 21
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ContractValidationRule.java
  3. 25
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetContractCreationProcessor.java
  4. 18
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java
  5. 48
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/contractvalidation/MaxCodeSizeRule.java

@ -42,6 +42,4 @@ dependencies {
epJavac 'com.google.errorprone:error_prone_check_api'
}
test {
testLogging { showStandardStreams = true }
}
test { testLogging { showStandardStreams = true } }

@ -0,0 +1,21 @@
/*
* Copyright 2019 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.mainnet;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
@FunctionalInterface
public interface ContractValidationRule {
boolean validate(MessageFrame frame);
}

@ -22,6 +22,7 @@ import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.ImmutableSet;
import org.apache.logging.log4j.LogManager;
@ -38,7 +39,7 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
private final long initialContractNonce;
private final int codeSizeLimit;
private final List<ContractValidationRule> contractValidationRules;
private final int accountVersion;
@ -46,14 +47,14 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
final GasCalculator gasCalculator,
final EVM evm,
final boolean requireCodeDepositToSucceed,
final int codeSizeLimit,
final List<ContractValidationRule> contractValidationRules,
final long initialContractNonce,
final Collection<Address> forceCommitAddresses,
final int accountVersion) {
super(evm, forceCommitAddresses);
this.gasCalculator = gasCalculator;
this.requireCodeDepositToSucceed = requireCodeDepositToSucceed;
this.codeSizeLimit = codeSizeLimit;
this.contractValidationRules = contractValidationRules;
this.initialContractNonce = initialContractNonce;
this.accountVersion = accountVersion;
}
@ -62,14 +63,14 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
final GasCalculator gasCalculator,
final EVM evm,
final boolean requireCodeDepositToSucceed,
final int codeSizeLimit,
final List<ContractValidationRule> contractValidationRules,
final long initialContractNonce,
final Collection<Address> forceCommitAddresses) {
this(
gasCalculator,
evm,
requireCodeDepositToSucceed,
codeSizeLimit,
contractValidationRules,
initialContractNonce,
forceCommitAddresses,
Account.DEFAULT_VERSION);
@ -79,13 +80,13 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
final GasCalculator gasCalculator,
final EVM evm,
final boolean requireCodeDepositToSucceed,
final int codeSizeLimit,
final List<ContractValidationRule> contractValidationRules,
final long initialContractNonce) {
this(
gasCalculator,
evm,
requireCodeDepositToSucceed,
codeSizeLimit,
contractValidationRules,
initialContractNonce,
ImmutableSet.of(),
Account.DEFAULT_VERSION);
@ -140,13 +141,7 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
frame.setState(MessageFrame.State.COMPLETED_SUCCESS);
}
} else {
if (contractCode.size() > codeSizeLimit) {
LOG.trace(
"Contract creation error: code size {} exceeds code size limit {}",
contractCode.size(),
codeSizeLimit);
frame.setState(MessageFrame.State.EXCEPTIONAL_HALT);
} else {
if (contractValidationRules.stream().allMatch(rule -> rule.validate(frame))) {
frame.decrementRemainingGas(depositFee);
// Finalize contract creation, setting the contract code.
@ -160,6 +155,8 @@ public class MainnetContractCreationProcessor extends AbstractMessageProcessor {
contractCode.size(),
frame.getRemainingGas());
frame.setState(MessageFrame.State.COMPLETED_SUCCESS);
} else {
frame.setState(MessageFrame.State.EXCEPTIONAL_HALT);
}
}
}

@ -25,11 +25,13 @@ import tech.pegasys.pantheon.ethereum.core.TransactionReceipt;
import tech.pegasys.pantheon.ethereum.core.Wei;
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 java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@ -76,7 +78,11 @@ public abstract class MainnetProtocolSpecs {
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator, evm, false, contractSizeLimit, 0))
gasCalculator,
evm,
false,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
0))
.transactionValidatorBuilder(
gasCalculator ->
new MainnetTransactionValidator(gasCalculator, false, Optional.empty()))
@ -128,7 +134,11 @@ public abstract class MainnetProtocolSpecs {
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator, evm, true, contractSizeLimit, 0))
gasCalculator,
evm,
true,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
0))
.transactionValidatorBuilder(
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, Optional.empty()))
.difficultyCalculator(MainnetDifficultyCalculators.HOMESTEAD)
@ -189,7 +199,7 @@ public abstract class MainnetProtocolSpecs {
gasCalculator,
evm,
true,
contractSizeLimit,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
1,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
.transactionValidatorBuilder(
@ -278,7 +288,7 @@ public abstract class MainnetProtocolSpecs {
gasCalculator,
evm,
true,
contractSizeLimit,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
1,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES,
1))

@ -0,0 +1,48 @@
/*
* Copyright 2019 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.mainnet.contractvalidation;
import tech.pegasys.pantheon.ethereum.mainnet.ContractValidationRule;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class MaxCodeSizeRule implements ContractValidationRule {
private static final Logger LOG = LogManager.getLogger();
private final int maxCodeSize;
private MaxCodeSizeRule(final int maxCodeSize) {
this.maxCodeSize = maxCodeSize;
}
@Override
public boolean validate(final MessageFrame frame) {
final int contractCodeSize = frame.getOutputData().size();
if (contractCodeSize <= maxCodeSize) {
return true;
} else {
LOG.trace(
"Contract creation error: code size {} exceeds code size limit {}",
contractCodeSize,
maxCodeSize);
return false;
}
}
public static ContractValidationRule of(final int maxCodeSize) {
return new MaxCodeSizeRule(maxCodeSize);
}
}
Loading…
Cancel
Save