|
|
@ -12,9 +12,9 @@ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
package tech.pegasys.pantheon.ethereum.mainnet; |
|
|
|
package tech.pegasys.pantheon.ethereum.mainnet; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import tech.pegasys.pantheon.ethereum.core.Account; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.EVM; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.EVM; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.GasCalculator; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.GasCalculator; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.Operation; |
|
|
|
|
|
|
|
import tech.pegasys.pantheon.ethereum.vm.OperationRegistry; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.OperationRegistry; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.AddModOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.AddModOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.AddOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.AddOperation; |
|
|
@ -92,185 +92,173 @@ import tech.pegasys.pantheon.ethereum.vm.operations.SwapOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.TimestampOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.TimestampOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.XorOperation; |
|
|
|
import tech.pegasys.pantheon.ethereum.vm.operations.XorOperation; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
import java.util.function.Function; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.google.common.collect.ImmutableList; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Provides EVMs supporting the appropriate operations for mainnet hard forks. */ |
|
|
|
/** Provides EVMs supporting the appropriate operations for mainnet hard forks. */ |
|
|
|
public abstract class MainnetEvmRegistries { |
|
|
|
abstract class MainnetEvmRegistries { |
|
|
|
|
|
|
|
|
|
|
|
private interface OperationFactory extends Function<GasCalculator, Operation> {} |
|
|
|
static EVM frontier(final GasCalculator gasCalculator) { |
|
|
|
|
|
|
|
final OperationRegistry registry = new OperationRegistry(); |
|
|
|
|
|
|
|
|
|
|
|
private static final List<OperationFactory> FRONTIER_OPERATION_FACTORIES; |
|
|
|
registerFrontierOpcodes(registry, gasCalculator, Account.DEFAULT_VERSION); |
|
|
|
private static final List<OperationFactory> HOMESTEAD_OPERATION_FACTORIES; |
|
|
|
|
|
|
|
private static final List<OperationFactory> BYZANTIUM_OPERATION_FACTORIES; |
|
|
|
|
|
|
|
private static final List<OperationFactory> CONSTANTINOPLE_OPERATION_FACTORIES; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static { |
|
|
|
return new EVM(registry, new InvalidOperation(gasCalculator)); |
|
|
|
FRONTIER_OPERATION_FACTORIES = buildFrontierFactories(); |
|
|
|
|
|
|
|
HOMESTEAD_OPERATION_FACTORIES = buildHomesteadFactories(FRONTIER_OPERATION_FACTORIES); |
|
|
|
|
|
|
|
BYZANTIUM_OPERATION_FACTORIES = buildByzantiumFactories(HOMESTEAD_OPERATION_FACTORIES); |
|
|
|
|
|
|
|
CONSTANTINOPLE_OPERATION_FACTORIES = |
|
|
|
|
|
|
|
buildConstantinopleFactories(BYZANTIUM_OPERATION_FACTORIES); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static EVM createAndPopulate( |
|
|
|
static EVM homestead(final GasCalculator gasCalculator) { |
|
|
|
final List<OperationFactory> factories, final GasCalculator gasCalculator) { |
|
|
|
|
|
|
|
final OperationRegistry registry = new OperationRegistry(); |
|
|
|
final OperationRegistry registry = new OperationRegistry(); |
|
|
|
|
|
|
|
|
|
|
|
for (final OperationFactory factory : factories) { |
|
|
|
registerHomesteadOpcodes(registry, gasCalculator, Account.DEFAULT_VERSION); |
|
|
|
final Operation operation = factory.apply(gasCalculator); |
|
|
|
|
|
|
|
registry.put(operation.getOpcode(), operation); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new EVM(registry, new InvalidOperation(gasCalculator)); |
|
|
|
return new EVM(registry, new InvalidOperation(gasCalculator)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static EVM frontier(final GasCalculator gasCalculator) { |
|
|
|
static EVM byzantium(final GasCalculator gasCalculator) { |
|
|
|
return createAndPopulate(FRONTIER_OPERATION_FACTORIES, gasCalculator); |
|
|
|
final OperationRegistry registry = new OperationRegistry(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static EVM homestead(final GasCalculator gasCalculator) { |
|
|
|
registerByzantiumOpcodes(registry, gasCalculator, Account.DEFAULT_VERSION); |
|
|
|
return createAndPopulate(HOMESTEAD_OPERATION_FACTORIES, gasCalculator); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static EVM byzantium(final GasCalculator gasCalculator) { |
|
|
|
return new EVM(registry, new InvalidOperation(gasCalculator)); |
|
|
|
return createAndPopulate(BYZANTIUM_OPERATION_FACTORIES, gasCalculator); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static EVM constantinople(final GasCalculator gasCalculator) { |
|
|
|
static EVM constantinople(final GasCalculator gasCalculator) { |
|
|
|
return createAndPopulate(CONSTANTINOPLE_OPERATION_FACTORIES, gasCalculator); |
|
|
|
final OperationRegistry registry = new OperationRegistry(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
registerConstantinopleOpcodes(registry, gasCalculator, Account.DEFAULT_VERSION); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new EVM(registry, new InvalidOperation(gasCalculator)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static List<OperationFactory> buildFrontierFactories() { |
|
|
|
static EVM istanbul(final GasCalculator gasCalculator) { |
|
|
|
final ImmutableList.Builder<OperationFactory> builder = ImmutableList.builder(); |
|
|
|
final OperationRegistry registry = new OperationRegistry(2); |
|
|
|
|
|
|
|
|
|
|
|
builder.add(AddOperation::new); |
|
|
|
registerIstanbulOpcodes(registry, gasCalculator, Account.DEFAULT_VERSION); |
|
|
|
builder.add(AddOperation::new); |
|
|
|
|
|
|
|
builder.add(MulOperation::new); |
|
|
|
return new EVM(registry, new InvalidOperation(gasCalculator)); |
|
|
|
builder.add(SubOperation::new); |
|
|
|
} |
|
|
|
builder.add(DivOperation::new); |
|
|
|
|
|
|
|
builder.add(SDivOperation::new); |
|
|
|
private static void registerFrontierOpcodes( |
|
|
|
builder.add(ModOperation::new); |
|
|
|
final OperationRegistry registry, |
|
|
|
builder.add(SModOperation::new); |
|
|
|
final GasCalculator gasCalculator, |
|
|
|
builder.add(ExpOperation::new); |
|
|
|
final int accountVersion) { |
|
|
|
builder.add(AddModOperation::new); |
|
|
|
registry.put(new AddOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(MulModOperation::new); |
|
|
|
registry.put(new AddOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SignExtendOperation::new); |
|
|
|
registry.put(new MulOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(LtOperation::new); |
|
|
|
registry.put(new SubOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(GtOperation::new); |
|
|
|
registry.put(new DivOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SLtOperation::new); |
|
|
|
registry.put(new SDivOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SGtOperation::new); |
|
|
|
registry.put(new ModOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(EqOperation::new); |
|
|
|
registry.put(new SModOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(IsZeroOperation::new); |
|
|
|
registry.put(new ExpOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(AndOperation::new); |
|
|
|
registry.put(new AddModOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(OrOperation::new); |
|
|
|
registry.put(new MulModOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(XorOperation::new); |
|
|
|
registry.put(new SignExtendOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(NotOperation::new); |
|
|
|
registry.put(new LtOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ByteOperation::new); |
|
|
|
registry.put(new GtOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(Sha3Operation::new); |
|
|
|
registry.put(new SLtOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(AddressOperation::new); |
|
|
|
registry.put(new SGtOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(BalanceOperation::new); |
|
|
|
registry.put(new EqOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(OriginOperation::new); |
|
|
|
registry.put(new IsZeroOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallerOperation::new); |
|
|
|
registry.put(new AndOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallValueOperation::new); |
|
|
|
registry.put(new OrOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallDataLoadOperation::new); |
|
|
|
registry.put(new XorOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallDataSizeOperation::new); |
|
|
|
registry.put(new NotOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallDataCopyOperation::new); |
|
|
|
registry.put(new ByteOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CodeSizeOperation::new); |
|
|
|
registry.put(new Sha3Operation(gasCalculator), accountVersion); |
|
|
|
builder.add(CodeCopyOperation::new); |
|
|
|
registry.put(new AddressOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(GasPriceOperation::new); |
|
|
|
registry.put(new BalanceOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ExtCodeCopyOperation::new); |
|
|
|
registry.put(new OriginOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ExtCodeSizeOperation::new); |
|
|
|
registry.put(new CallerOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(BlockHashOperation::new); |
|
|
|
registry.put(new CallValueOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CoinbaseOperation::new); |
|
|
|
registry.put(new CallDataLoadOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(TimestampOperation::new); |
|
|
|
registry.put(new CallDataSizeOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(NumberOperation::new); |
|
|
|
registry.put(new CallDataCopyOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(DifficultyOperation::new); |
|
|
|
registry.put(new CodeSizeOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(GasLimitOperation::new); |
|
|
|
registry.put(new CodeCopyOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(PopOperation::new); |
|
|
|
registry.put(new GasPriceOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(MLoadOperation::new); |
|
|
|
registry.put(new ExtCodeCopyOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(MStoreOperation::new); |
|
|
|
registry.put(new ExtCodeSizeOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(MStore8Operation::new); |
|
|
|
registry.put(new BlockHashOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SLoadOperation::new); |
|
|
|
registry.put(new CoinbaseOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SStoreOperation::new); |
|
|
|
registry.put(new TimestampOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(JumpOperation::new); |
|
|
|
registry.put(new NumberOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(JumpiOperation::new); |
|
|
|
registry.put(new DifficultyOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(PCOperation::new); |
|
|
|
registry.put(new GasLimitOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(MSizeOperation::new); |
|
|
|
registry.put(new PopOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(GasOperation::new); |
|
|
|
registry.put(new MLoadOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(JumpDestOperation::new); |
|
|
|
registry.put(new MStoreOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ReturnOperation::new); |
|
|
|
registry.put(new MStore8Operation(gasCalculator), accountVersion); |
|
|
|
builder.add(InvalidOperation::new); |
|
|
|
registry.put(new SLoadOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(StopOperation::new); |
|
|
|
registry.put(new SStoreOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SelfDestructOperation::new); |
|
|
|
registry.put(new JumpOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CreateOperation::new); |
|
|
|
registry.put(new JumpiOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallOperation::new); |
|
|
|
registry.put(new PCOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(CallCodeOperation::new); |
|
|
|
registry.put(new MSizeOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new GasOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new JumpDestOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new ReturnOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new InvalidOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new StopOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new SelfDestructOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new CreateOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new CallOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
registry.put(new CallCodeOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
|
|
|
|
// Register the PUSH1, PUSH2, ..., PUSH32 operations.
|
|
|
|
// Register the PUSH1, PUSH2, ..., PUSH32 operations.
|
|
|
|
for (int i = 1; i <= 32; ++i) { |
|
|
|
for (int i = 1; i <= 32; ++i) { |
|
|
|
final int n = i; |
|
|
|
registry.put(new PushOperation(i, gasCalculator), accountVersion); |
|
|
|
builder.add(f -> new PushOperation(n, f)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Register the DUP1, DUP2, ..., DUP16 operations.
|
|
|
|
// Register the DUP1, DUP2, ..., DUP16 operations.
|
|
|
|
for (int i = 1; i <= 16; ++i) { |
|
|
|
for (int i = 1; i <= 16; ++i) { |
|
|
|
final int n = i; |
|
|
|
registry.put(new DupOperation(i, gasCalculator), accountVersion); |
|
|
|
builder.add(f -> new DupOperation(n, f)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Register the SWAP1, SWAP2, ..., SWAP16 operations.
|
|
|
|
// Register the SWAP1, SWAP2, ..., SWAP16 operations.
|
|
|
|
for (int i = 1; i <= 16; ++i) { |
|
|
|
for (int i = 1; i <= 16; ++i) { |
|
|
|
final int n = i; |
|
|
|
registry.put(new SwapOperation(i, gasCalculator), accountVersion); |
|
|
|
builder.add(f -> new SwapOperation(n, f)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Register the LOG0, LOG1, ..., LOG4 operations.
|
|
|
|
// Register the LOG0, LOG1, ..., LOG4 operations.
|
|
|
|
for (int i = 0; i < 5; ++i) { |
|
|
|
for (int i = 0; i < 5; ++i) { |
|
|
|
final int n = i; |
|
|
|
registry.put(new LogOperation(i, gasCalculator), accountVersion); |
|
|
|
builder.add(f -> new LogOperation(n, f)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return builder.build(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static List<OperationFactory> buildHomesteadFactories( |
|
|
|
private static void registerHomesteadOpcodes( |
|
|
|
final List<OperationFactory> factories) { |
|
|
|
final OperationRegistry registry, |
|
|
|
final ImmutableList.Builder<OperationFactory> builder = ImmutableList.builder(); |
|
|
|
final GasCalculator gasCalculator, |
|
|
|
|
|
|
|
final int accountVersion) { |
|
|
|
builder.addAll(factories); |
|
|
|
registerFrontierOpcodes(registry, gasCalculator, accountVersion); |
|
|
|
builder.add(DelegateCallOperation::new); |
|
|
|
registry.put(new DelegateCallOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
|
|
|
|
return builder.build(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static List<OperationFactory> buildByzantiumFactories( |
|
|
|
private static void registerByzantiumOpcodes( |
|
|
|
final List<OperationFactory> factories) { |
|
|
|
final OperationRegistry registry, |
|
|
|
final ImmutableList.Builder<OperationFactory> builder = ImmutableList.builder(); |
|
|
|
final GasCalculator gasCalculator, |
|
|
|
|
|
|
|
final int accountVersion) { |
|
|
|
builder.addAll(factories); |
|
|
|
registerHomesteadOpcodes(registry, gasCalculator, accountVersion); |
|
|
|
builder.add(ReturnDataCopyOperation::new); |
|
|
|
registry.put(new ReturnDataCopyOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ReturnDataSizeOperation::new); |
|
|
|
registry.put(new ReturnDataSizeOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(RevertOperation::new); |
|
|
|
registry.put(new RevertOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(StaticCallOperation::new); |
|
|
|
registry.put(new StaticCallOperation(gasCalculator), accountVersion); |
|
|
|
|
|
|
|
|
|
|
|
return builder.build(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static List<OperationFactory> buildConstantinopleFactories( |
|
|
|
private static void registerConstantinopleOpcodes( |
|
|
|
final List<OperationFactory> factories) { |
|
|
|
final OperationRegistry registry, |
|
|
|
|
|
|
|
final GasCalculator gasCalculator, |
|
|
|
final ImmutableList.Builder<OperationFactory> builder = ImmutableList.builder(); |
|
|
|
final int accountVersion) { |
|
|
|
|
|
|
|
registerByzantiumOpcodes(registry, gasCalculator, accountVersion); |
|
|
|
builder.addAll(factories); |
|
|
|
registry.put(new Create2Operation(gasCalculator), accountVersion); |
|
|
|
builder.add(Create2Operation::new); |
|
|
|
registry.put(new SarOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(SarOperation::new); |
|
|
|
registry.put(new ShlOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ShlOperation::new); |
|
|
|
registry.put(new ShrOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ShrOperation::new); |
|
|
|
registry.put(new ExtCodeHashOperation(gasCalculator), accountVersion); |
|
|
|
builder.add(ExtCodeHashOperation::new); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return builder.build(); |
|
|
|
private static void registerIstanbulOpcodes( |
|
|
|
|
|
|
|
final OperationRegistry registry, |
|
|
|
|
|
|
|
final GasCalculator gasCalculator, |
|
|
|
|
|
|
|
final int accountVersion) { |
|
|
|
|
|
|
|
registerConstantinopleOpcodes(registry, gasCalculator, accountVersion); |
|
|
|
|
|
|
|
registerConstantinopleOpcodes(registry, gasCalculator, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|