ETC Atlantis fork (#179)

This PR introduces code to support ECIP 1054: Atlantis EVM and Protocol Upgrades

Signed-off-by: edwardmack <ed@edwardmack.com>
pull/193/head
Edward Mack 5 years ago committed by Danno Ferrin
parent 925fb179d0
commit 9b9c373c88
  1. 12
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java
  2. 5
      config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java
  3. 1
      config/src/main/resources/classic.json
  4. 6
      config/src/test-support/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java
  5. 1
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicBlockProcessor.java
  6. 24
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicDifficultyCalculators.java
  7. 63
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java
  8. 31
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java

@ -113,6 +113,18 @@ public interface GenesisConfigOptions {
*/
OptionalLong getDefuseDifficultyBombBlockNumber();
/**
* Block number for Atlantis fork on Classic network Note, this fork happen after Defuse
* Difficulty Bomb fork and before Agharta fork ECIP-1054: Atlantis EVM and Protocol Upgrades
* Enable the outstanding Ethereum Foundation Spurious Dragon and Byzantium network protocol
* upgrades for the Ethereum Classic network.
*
* @see <a
* href="https://ecips.ethereumclassic.org/ECIPs/ecip-1054">https://ecips.ethereumclassic.org/ECIPs/ecip-1054</a>
* @return block number for Atlantis fork on Classic network
*/
OptionalLong getAtlantisBlockNumber();
Optional<BigInteger> getChainId();
OptionalInt getContractSizeLimit();

@ -220,6 +220,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return getOptionalLong("ecip1041block");
}
@Override
public OptionalLong getAtlantisBlockNumber() {
return getOptionalLong("atlantisblock");
}
@Override
public Optional<BigInteger> getChainId() {
return getOptionalBigInteger("chainid");

@ -7,6 +7,7 @@
"diehardBlock": 3000000,
"gothamBlock": 5000001,
"ecip1041Block": 5900000,
"atlantisBlock": 8772000,
"ethash": {
}

@ -37,6 +37,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
private OptionalLong diehardBlockNumber = OptionalLong.empty();
private OptionalLong gothamBlockNumber = OptionalLong.empty();
private OptionalLong defuseDifficultyBombBlockNumber = OptionalLong.empty();
private OptionalLong atlantisBlockNumber = OptionalLong.empty();
private Optional<BigInteger> chainId = Optional.empty();
private OptionalInt contractSizeLimit = OptionalInt.empty();
private OptionalInt stackSizeLimit = OptionalInt.empty();
@ -151,6 +152,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return defuseDifficultyBombBlockNumber;
}
@Override
public OptionalLong getAtlantisBlockNumber() {
return atlantisBlockNumber;
}
@Override
public OptionalInt getContractSizeLimit() {
return contractSizeLimit;

@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor.TransactionReceiptFactory;
import java.math.BigInteger;
import java.util.List;

@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.util.uint.UInt256;
import java.math.BigInteger;
@ -64,6 +65,29 @@ public abstract class ClassicDifficultyCalculators {
return difficulty;
};
public static DifficultyCalculator<Void> EIP100 =
(time, parent, protocolContext) -> {
final BigInteger parentDifficulty = difficulty(parent.getDifficulty());
final boolean hasOmmers = !parent.getOmmersHash().equals(Hash.EMPTY_LIST_HASH);
final BigInteger difficulty =
ensureMinimumDifficulty(
BigInteger.valueOf(byzantiumX(time, parent.getTimestamp(), hasOmmers))
.multiply(parentDifficulty.divide(DIFFICULTY_BOUND_DIVISOR))
.add(parentDifficulty));
return difficulty;
};
private static long byzantiumX(
final long blockTime, final long parentTime, final boolean hasOmmers) {
long x = (blockTime - parentTime) / 9L;
if (hasOmmers) {
x = 2 - x;
} else {
x = 1 - x;
}
return Math.max(x, -99L);
}
private static BigInteger adjustForDifficultyDelay(
final long periodCount, final BigInteger difficulty) {
return difficulty.add(BIGINT_2.pow(Ints.checkedCast(periodCount - DELAY - 2)));

@ -14,9 +14,15 @@
*/
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldState;
import org.hyperledger.besu.ethereum.mainnet.contractvalidation.MaxCodeSizeRule;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Optional;
import java.util.OptionalInt;
@ -83,4 +89,61 @@ public class ClassicProtocolSpecs {
gasCalculator -> new MainnetTransactionValidator(gasCalculator, true, chainId))
.name("DefuseDifficultyBomb");
}
public static ProtocolSpecBuilder<Void> atlantisDefinition(
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final int contractSizeLimit =
configContractSizeLimit.orElse(MainnetProtocolSpecs.SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
return gothamDefinition(chainId, configContractSizeLimit, configStackSizeLimit)
.evmBuilder(MainnetEvmRegistries::byzantium)
.gasCalculator(SpuriousDragonGasCalculator::new)
.skipZeroBlockRewards(true)
.messageCallProcessorBuilder(
(evm, precompileContractRegistry) ->
new MainnetMessageCallProcessor(evm, precompileContractRegistry))
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
.difficultyCalculator(ClassicDifficultyCalculators.EIP100)
.transactionReceiptFactory(
enableRevertReason
? ClassicProtocolSpecs::byzantiumTransactionReceiptFactoryWithReasonEnabled
: ClassicProtocolSpecs::byzantiumTransactionReceiptFactory)
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
new MainnetContractCreationProcessor(
gasCalculator,
evm,
true,
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
1))
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
true,
stackSizeLimit,
Account.DEFAULT_VERSION))
.name("Atlantis");
}
private static TransactionReceipt byzantiumTransactionReceiptFactory(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), Optional.empty());
}
private static TransactionReceipt byzantiumTransactionReceiptFactoryWithReasonEnabled(
final TransactionProcessor.Result result, final WorldState worldState, final long gasUsed) {
return new TransactionReceipt(
result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), result.getRevertReason());
}
}

@ -187,6 +187,14 @@ public class ProtocolScheduleBuilder<C> {
config.getDefuseDifficultyBombBlockNumber(),
ClassicProtocolSpecs.defuseDifficultyBombDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize()));
addProtocolSpec(
protocolSchedule,
config.getAtlantisBlockNumber(),
ClassicProtocolSpecs.atlantisDefinition(
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones());
return protocolSchedule;
@ -221,6 +229,14 @@ public class ProtocolScheduleBuilder<C> {
}
private void validateForkOrdering() {
if (config.getDaoForkBlock().isEmpty()) {
validateClassicForkOrdering();
} else {
validateEthereumForkOrdering();
}
}
private void validateEthereumForkOrdering() {
long lastForkBlock = 0;
lastForkBlock = validateForkOrder("Homestead", config.getHomesteadBlockNumber(), lastForkBlock);
lastForkBlock = validateForkOrder("DaoFork", config.getDaoForkBlock(), lastForkBlock);
@ -238,4 +254,19 @@ public class ProtocolScheduleBuilder<C> {
lastForkBlock = validateForkOrder("Istanbul", config.getIstanbulBlockNumber(), lastForkBlock);
assert (lastForkBlock >= 0);
}
private void validateClassicForkOrdering() {
long lastForkBlock = 0;
lastForkBlock = validateForkOrder("Homestead", config.getHomesteadBlockNumber(), lastForkBlock);
lastForkBlock =
validateForkOrder(
"ClassicTangerineWhistle", config.getEcip1015BlockNumber(), lastForkBlock);
lastForkBlock = validateForkOrder("DieHard", config.getDieHardBlockNumber(), lastForkBlock);
lastForkBlock = validateForkOrder("Gotham", config.getGothamBlockNumber(), lastForkBlock);
lastForkBlock =
validateForkOrder(
"DefuseDifficultyBomb", config.getDefuseDifficultyBombBlockNumber(), lastForkBlock);
lastForkBlock = validateForkOrder("Atlantis", config.getAtlantisBlockNumber(), lastForkBlock);
assert (lastForkBlock >= 0);
}
}

Loading…
Cancel
Save