From ee224b1f7787122f3be8af0e66cf0ecf69632a72 Mon Sep 17 00:00:00 2001 From: shemnon Date: Fri, 12 Jul 2019 08:51:52 -0600 Subject: [PATCH] [PAN-2829] Add opcode and precompiled support for versioning Different precompile sets for different account versions --- .../mainnet/MainnetMessageCallProcessor.java | 3 +- .../MainnetPrecompiledContractRegistries.java | 58 ++++++++++++++----- .../mainnet/PrecompileContractRegistry.java | 19 +++--- .../ethereum/mainnet/ProtocolSpecBuilder.java | 8 ++- .../tech/pegasys/pantheon/PrivacyTest.java | 3 +- 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetMessageCallProcessor.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetMessageCallProcessor.java index d1ad54594b..bddc43f408 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetMessageCallProcessor.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetMessageCallProcessor.java @@ -51,7 +51,8 @@ public void start(final MessageFrame frame) { transferValue(frame); // Check first if the message call is to a pre-compile contract - final PrecompiledContract precompile = precompiles.get(frame.getContractAddress()); + final PrecompiledContract precompile = + precompiles.get(frame.getContractAddress(), frame.getContractAccountVersion()); if (precompile != null) { executePrecompile(precompile, frame); } else { diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java index 5907adb28e..ffbbac2bfc 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetPrecompiledContractRegistries.java @@ -12,6 +12,7 @@ */ package tech.pegasys.pantheon.ethereum.mainnet; +import tech.pegasys.pantheon.ethereum.core.Account; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128AddPrecompiledContract; import tech.pegasys.pantheon.ethereum.mainnet.precompiles.AltBN128MulPrecompiledContract; @@ -30,45 +31,70 @@ public abstract class MainnetPrecompiledContractRegistries { private MainnetPrecompiledContractRegistries() {} private static void populateForFrontier( - final PrecompileContractRegistry registry, final GasCalculator gasCalculator) { - registry.put(Address.ECREC, new ECRECPrecompiledContract(gasCalculator)); - registry.put(Address.SHA256, new SHA256PrecompiledContract(gasCalculator)); - registry.put(Address.RIPEMD160, new RIPEMD160PrecompiledContract(gasCalculator)); - registry.put(Address.ID, new IDPrecompiledContract(gasCalculator)); + final PrecompileContractRegistry registry, + final GasCalculator gasCalculator, + final int accountVersion) { + registry.put(Address.ECREC, accountVersion, new ECRECPrecompiledContract(gasCalculator)); + registry.put(Address.SHA256, accountVersion, new SHA256PrecompiledContract(gasCalculator)); + registry.put( + Address.RIPEMD160, accountVersion, new RIPEMD160PrecompiledContract(gasCalculator)); + registry.put(Address.ID, accountVersion, new IDPrecompiledContract(gasCalculator)); } public static PrecompileContractRegistry frontier( final PrecompiledContractConfiguration precompiledContractConfiguration) { final PrecompileContractRegistry registry = new PrecompileContractRegistry(); - populateForFrontier(registry, precompiledContractConfiguration.getGasCalculator()); + populateForFrontier( + registry, precompiledContractConfiguration.getGasCalculator(), Account.DEFAULT_VERSION); return registry; } private static void populateForByzantium( - final PrecompileContractRegistry registry, final GasCalculator gasCalculator) { - populateForFrontier(registry, gasCalculator); + final PrecompileContractRegistry registry, + final GasCalculator gasCalculator, + final int accountVersion) { + populateForFrontier(registry, gasCalculator, accountVersion); + registry.put( + Address.MODEXP, + accountVersion, + new BigIntegerModularExponentiationPrecompiledContract(gasCalculator)); + registry.put( + Address.ALTBN128_ADD, accountVersion, new AltBN128AddPrecompiledContract(gasCalculator)); + registry.put( + Address.ALTBN128_MUL, accountVersion, new AltBN128MulPrecompiledContract(gasCalculator)); registry.put( - Address.MODEXP, new BigIntegerModularExponentiationPrecompiledContract(gasCalculator)); - registry.put(Address.ALTBN128_ADD, new AltBN128AddPrecompiledContract(gasCalculator)); - registry.put(Address.ALTBN128_MUL, new AltBN128MulPrecompiledContract(gasCalculator)); - registry.put(Address.ALTBN128_PAIRING, new AltBN128PairingPrecompiledContract(gasCalculator)); + Address.ALTBN128_PAIRING, + accountVersion, + new AltBN128PairingPrecompiledContract(gasCalculator)); } public static PrecompileContractRegistry byzantium( final PrecompiledContractConfiguration precompiledContractConfiguration) { final PrecompileContractRegistry registry = new PrecompileContractRegistry(); - populateForByzantium(registry, precompiledContractConfiguration.getGasCalculator()); + populateForByzantium( + registry, precompiledContractConfiguration.getGasCalculator(), Account.DEFAULT_VERSION); return registry; } - public static PrecompileContractRegistry appendPrivacy( - final PrecompileContractRegistry registry, + public static PrecompileContractRegistry istanbul( final PrecompiledContractConfiguration precompiledContractConfiguration) { - Address address = + final PrecompileContractRegistry registry = new PrecompileContractRegistry(); + populateForByzantium( + registry, precompiledContractConfiguration.getGasCalculator(), Account.DEFAULT_VERSION); + populateForByzantium(registry, precompiledContractConfiguration.getGasCalculator(), 1); + return registry; + } + + static PrecompileContractRegistry appendPrivacy( + final PrecompileContractRegistry registry, + final PrecompiledContractConfiguration precompiledContractConfiguration, + final int accountVersion) { + final Address address = Address.privacyPrecompiled( precompiledContractConfiguration.getPrivacyParameters().getPrivacyAddress()); registry.put( address, + accountVersion, new PrivacyPrecompiledContract( precompiledContractConfiguration.getGasCalculator(), precompiledContractConfiguration.getPrivacyParameters())); diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/PrecompileContractRegistry.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/PrecompileContractRegistry.java index 2c6f9dacf7..ef2665bd98 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/PrecompileContractRegistry.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/PrecompileContractRegistry.java @@ -14,23 +14,26 @@ import tech.pegasys.pantheon.ethereum.core.Address; -import java.util.HashMap; -import java.util.Map; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; /** Encapsulates a group of {@link PrecompiledContract}s used together. */ public class PrecompileContractRegistry { - private final Map precompiles; + private final Table precompiles; public PrecompileContractRegistry() { - this.precompiles = new HashMap<>(); + this.precompiles = HashBasedTable.create(16, 2); } - public PrecompiledContract get(final Address address) { - return precompiles.get(address); + public PrecompiledContract get(final Address address, final int contractAccountVersion) { + return precompiles.get(address, contractAccountVersion); } - public void put(final Address address, final PrecompiledContract precompile) { - precompiles.put(address, precompile); + public void put( + final Address address, + final int contractAccountVersion, + final PrecompiledContract precompile) { + precompiles.put(address, contractAccountVersion, precompile); } } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java index 7667332880..bd1e241765 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSpecBuilder.java @@ -15,6 +15,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import tech.pegasys.pantheon.ethereum.BlockValidator; +import tech.pegasys.pantheon.ethereum.core.Account; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.BlockHeaderFunctions; import tech.pegasys.pantheon.ethereum.core.BlockImporter; @@ -131,7 +132,9 @@ public ProtocolSpecBuilder precompileContractRegistryBuilder( precompileContractRegistryBuilder.apply(precompiledContractConfiguration); if (precompiledContractConfiguration.getPrivacyParameters().isEnabled()) { MainnetPrecompiledContractRegistries.appendPrivacy( - registry, precompiledContractConfiguration); + registry, precompiledContractConfiguration, Account.DEFAULT_VERSION); + MainnetPrecompiledContractRegistries.appendPrivacy( + registry, precompiledContractConfiguration, 1); } return registry; }; @@ -276,7 +279,8 @@ public ProtocolSpec build(final ProtocolSchedule protocolSchedule) { gasCalculator, transactionValidator, contractCreationProcessor, messageCallProcessor); Address address = Address.privacyPrecompiled(privacyParameters.getPrivacyAddress()); PrivacyPrecompiledContract privacyPrecompiledContract = - (PrivacyPrecompiledContract) precompileContractRegistry.get(address); + (PrivacyPrecompiledContract) + precompileContractRegistry.get(address, Account.DEFAULT_VERSION); privacyPrecompiledContract.setPrivateTransactionProcessor(privateTransactionProcessor); } diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java index e77275bed6..364e7abcdc 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java @@ -17,6 +17,7 @@ import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; +import tech.pegasys.pantheon.ethereum.core.Account; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider; import tech.pegasys.pantheon.ethereum.core.MiningParametersTestBuilder; @@ -72,7 +73,7 @@ public void privacyPrecompiled() throws IOException { .getProtocolSchedule() .getByBlockNumber(1) .getPrecompileContractRegistry() - .get(privacyContractAddress); + .get(privacyContractAddress, Account.DEFAULT_VERSION); assertThat(precompiledContract.getName()).isEqualTo("Privacy"); } }