diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f67ffa0ec..6e853c492e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Additions and Improvements +* Ethereum Classic Magneto Hard Fork [\#2315](https://github.com/hyperledger/besu/pull/2315) + ### Bug Fixes ### Early Access Features diff --git a/besu/src/test/java/org/hyperledger/besu/ForkIdsTest.java b/besu/src/test/java/org/hyperledger/besu/ForkIdsTest.java index 36b97846b6..d277373860 100644 --- a/besu/src/test/java/org/hyperledger/besu/ForkIdsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/ForkIdsTest.java @@ -113,8 +113,9 @@ public class ForkIdsTest { new ForkId(Bytes.ofUnsignedInt(0x175782aaL), 301243L), new ForkId(Bytes.ofUnsignedInt(0x604f6ee1L), 999983L), new ForkId(Bytes.ofUnsignedInt(0xf42f5539L), 2520000L), - new ForkId(Bytes.ofUnsignedInt(0x66b5c286L), 0L), - new ForkId(Bytes.ofUnsignedInt(0x66b5c286L), 0L)) + new ForkId(Bytes.ofUnsignedInt(0x66b5c286L), 3985893), + new ForkId(Bytes.ofUnsignedInt(0x92b323e0L), 0), + new ForkId(Bytes.ofUnsignedInt(0x92b323e0L), 0)) }, new Object[] { NetworkName.KOTTI, @@ -122,8 +123,9 @@ public class ForkIdsTest { new ForkId(Bytes.ofUnsignedInt(0x550152eL), 716617L), new ForkId(Bytes.ofUnsignedInt(0xa3270822L), 1705549L), new ForkId(Bytes.ofUnsignedInt(0x8f3698e0L), 2200013L), - new ForkId(Bytes.ofUnsignedInt(0x6f402821L), 0L), - new ForkId(Bytes.ofUnsignedInt(0x6f402821L), 0L)) + new ForkId(Bytes.ofUnsignedInt(0x6f402821L), 4368634), + new ForkId(Bytes.ofUnsignedInt(0xf03e54e7L), 0), + new ForkId(Bytes.ofUnsignedInt(0xf03e54e7L), 0)) }, new Object[] { NetworkName.CLASSIC, @@ -139,8 +141,9 @@ public class ForkIdsTest { new ForkId(Bytes.ofUnsignedInt(0x518b59c6L), 9573000L), new ForkId(Bytes.ofUnsignedInt(0x7ba22882L), 10500839L), new ForkId(Bytes.ofUnsignedInt(0x9007bfccL), 11700000L), - new ForkId(Bytes.ofUnsignedInt(0xdb63a1caL), 0L), - new ForkId(Bytes.ofUnsignedInt(0xdb63a1caL), 0L)) + new ForkId(Bytes.ofUnsignedInt(0xdb63a1caL), 13189133), + new ForkId(Bytes.ofUnsignedInt(0x0f6bf187L), 0), + new ForkId(Bytes.ofUnsignedInt(0x0f6bf187L), 0)) }); } diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index cf5fded7e7..f3caac982d 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -191,6 +191,15 @@ public interface GenesisConfigOptions { */ OptionalLong getThanosBlockNumber(); + /** + * Block number to activate Magneto on Classic networks. + * + * @return block number of Magneto fork on Classic networks + * @see https://github.com/ethereumclassic/ECIPs/issues/424 + */ + OptionalLong getMagnetoBlockNumber(); + /** * Block number to activate ECIP-1049 on Classic networks. Changes the hashing algorithm to * keccak-256. diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 27f95f14d1..ddccbfa7e7 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -317,6 +317,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { return getOptionalLong("thanosblock"); } + @Override + public OptionalLong getMagnetoBlockNumber() { + return getOptionalLong("magnetoblock"); + } + @Override public OptionalLong getEcip1049BlockNumber() { return getOptionalLong("ecip1049block"); @@ -405,6 +410,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l)); getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l)); getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l)); + getMagnetoBlockNumber().ifPresent(l -> builder.put("magnetoBlock", l)); getEcip1049BlockNumber().ifPresent(l -> builder.put("ecip1049Block", l)); getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l)); @@ -503,6 +509,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { getAghartaBlockNumber(), getPhoenixBlockNumber(), getThanosBlockNumber(), + getMagnetoBlockNumber(), getEcip1049BlockNumber()); // when adding forks add an entry to ${REPO_ROOT}/config/src/test/resources/all_forks.json diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 5495675bd1..5f138d2292 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -49,6 +49,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions { private OptionalLong aghartaBlockNumber = OptionalLong.empty(); private OptionalLong phoenixBlockNumber = OptionalLong.empty(); private OptionalLong thanosBlockNumber = OptionalLong.empty(); + private OptionalLong magnetoBlockNumber = OptionalLong.empty(); private OptionalLong ecip1049BlockNumber = OptionalLong.empty(); private Optional chainId = Optional.empty(); private OptionalInt contractSizeLimit = OptionalInt.empty(); @@ -231,6 +232,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions { return thanosBlockNumber; } + @Override + public OptionalLong getMagnetoBlockNumber() { + return magnetoBlockNumber; + } + @Override public OptionalLong getEcip1049BlockNumber() { return ecip1049BlockNumber; @@ -292,6 +298,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions { getAghartaBlockNumber().ifPresent(l -> builder.put("aghartaBlock", l)); getPhoenixBlockNumber().ifPresent(l -> builder.put("phoenixBlock", l)); getThanosBlockNumber().ifPresent(l -> builder.put("thanosBlock", l)); + getMagnetoBlockNumber().ifPresent(l -> builder.put("magnetoBlock", l)); getEcip1049BlockNumber().ifPresent(l -> builder.put("ecip1049Block", l)); getContractSizeLimit().ifPresent(l -> builder.put("contractSizeLimit", l)); @@ -446,6 +453,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions { return this; } + public StubGenesisConfigOptions magneto(final long blockNumber) { + magnetoBlockNumber = OptionalLong.of(blockNumber); + return this; + } + public StubGenesisConfigOptions ecip1049(final long blockNumber) { ecip1049BlockNumber = OptionalLong.of(blockNumber); return this; diff --git a/config/src/main/resources/classic.json b/config/src/main/resources/classic.json index f1132106ad..1063ef04d0 100644 --- a/config/src/main/resources/classic.json +++ b/config/src/main/resources/classic.json @@ -11,6 +11,7 @@ "aghartaBlock": 9573000, "phoenixBlock": 10500839, "thanosBlock": 11700000, + "magnetoBlock": 13189133, "ethash": { } diff --git a/config/src/main/resources/kotti.json b/config/src/main/resources/kotti.json index d809428702..2f1725b12a 100644 --- a/config/src/main/resources/kotti.json +++ b/config/src/main/resources/kotti.json @@ -5,6 +5,7 @@ "atlantisBlock": 716617, "aghartaBlock": 1705549, "phoenixBlock": 2200013, + "magnetoBlock": 4368634, "clique":{ "blockperiodseconds":15, "epochlength":30000 diff --git a/config/src/main/resources/mordor.json b/config/src/main/resources/mordor.json index fe0a1e64f1..15311cc5f6 100644 --- a/config/src/main/resources/mordor.json +++ b/config/src/main/resources/mordor.json @@ -6,6 +6,7 @@ "phoenixBlock": 999983, "ecip1017EraRounds": 2000000, "thanosBlock": 2520000, + "magnetoBlock": 3985893, "ethash": {} }, "nonce": "0x0000000000000000", diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java index 09d3c8ffc2..34338c600c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java @@ -369,7 +369,8 @@ public class AdminNodeInfoTest { .agharta(7) .phoenix(8) .thanos(9) - .ecip1049(10); + .magneto(10) + .ecip1049(11); final AdminNodeInfo methodClassic = new AdminNodeInfo( @@ -383,17 +384,19 @@ public class AdminNodeInfoTest { final JsonRpcRequestContext request = adminNodeInfo(); final Map expectedConfig = - Map.of( - "classicForkBlock", 1L, - "ecip1015Block", 2L, - "dieHardBlock", 3L, - "gothamBlock", 4L, - "ecip1041Block", 5L, - "atlantisBlock", 6L, - "aghartaBlock", 7L, - "phoenixBlock", 8L, - "thanosBlock", 9L, - "ecip1049Block", 10L); + new HashMap<>( + Map.of( + "classicForkBlock", 1L, + "ecip1015Block", 2L, + "dieHardBlock", 3L, + "gothamBlock", 4L, + "ecip1041Block", 5L, + "atlantisBlock", 6L, + "aghartaBlock", 7L, + "phoenixBlock", 8L, + "thanosBlock", 9L, + "magnetoBlock", 10L)); + expectedConfig.put("ecip1049Block", 11L); final JsonRpcResponse response = methodClassic.response(request); assertThat(response).isInstanceOf(JsonRpcSuccessResponse.class); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java index 512b5ccb1a..d69127ec4a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ClassicProtocolSpecs.java @@ -33,6 +33,7 @@ import java.util.Collections; import java.util.Optional; import java.util.OptionalInt; import java.util.OptionalLong; +import java.util.Set; public class ClassicProtocolSpecs { private static final Wei MAX_BLOCK_REWARD = Wei.fromEth(5); @@ -285,4 +286,34 @@ public class ClassicProtocolSpecs { .powHasher(powHasher(PowAlgorithm.KECCAK256)) .name("ecip1049"); } + + public static ProtocolSpecBuilder magnetoDefinition( + final Optional chainId, + final OptionalInt configContractSizeLimit, + final OptionalInt configStackSizeLimit, + final boolean enableRevertReason, + final OptionalLong ecip1017EraRounds, + final boolean quorumCompatibilityMode) { + return thanosDefinition( + chainId, + configContractSizeLimit, + configStackSizeLimit, + enableRevertReason, + ecip1017EraRounds, + quorumCompatibilityMode) + .gasCalculator(BerlinGasCalculator::new) + .transactionValidatorBuilder( + gasCalculator -> + new MainnetTransactionValidator( + gasCalculator, + true, + chainId, + Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST), + quorumCompatibilityMode)) + .transactionReceiptFactory( + enableRevertReason + ? MainnetProtocolSpecs::berlinTransactionReceiptFactoryWithReasonEnabled + : MainnetProtocolSpecs::berlinTransactionReceiptFactory) + .name("Magneto"); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java index 478cf6ffe9..733101493f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java @@ -183,6 +183,16 @@ public class MainnetProtocolSpecFactory { quorumCompatibilityMode); } + public ProtocolSpecBuilder magnetoDefinition() { + return ClassicProtocolSpecs.magnetoDefinition( + chainId, + contractSizeLimit, + evmStackSize, + isRevertReasonEnabled, + ecip1017EraRounds, + quorumCompatibilityMode); + } + public ProtocolSpecBuilder ecip1049Definition() { return ClassicProtocolSpecs.ecip1049Definition( chainId, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index 888681fd5a..0617903077 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -616,7 +616,7 @@ public abstract class MainnetProtocolSpecs { result.isSuccessful() ? 1 : 0, gasUsed, result.getLogs(), result.getRevertReason()); } - private static TransactionReceipt berlinTransactionReceiptFactory( + static TransactionReceipt berlinTransactionReceiptFactory( final TransactionType transactionType, final TransactionProcessingResult transactionProcessingResult, final WorldState worldState, @@ -629,7 +629,7 @@ public abstract class MainnetProtocolSpecs { Optional.empty()); } - private static TransactionReceipt berlinTransactionReceiptFactoryWithReasonEnabled( + static TransactionReceipt berlinTransactionReceiptFactoryWithReasonEnabled( final TransactionType transactionType, final TransactionProcessingResult transactionProcessingResult, final WorldState worldState, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java index f6927aab68..c117ff3090 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -234,6 +234,7 @@ public class ProtocolScheduleBuilder { create(config.getAghartaBlockNumber(), specFactory.aghartaDefinition()), create(config.getPhoenixBlockNumber(), specFactory.phoenixDefinition()), create(config.getThanosBlockNumber(), specFactory.thanosDefinition()), + create(config.getMagnetoBlockNumber(), specFactory.magnetoDefinition()), create(config.getEcip1049BlockNumber(), specFactory.ecip1049Definition())) .stream() .filter(Optional::isPresent) @@ -327,6 +328,7 @@ public class ProtocolScheduleBuilder { lastForkBlock = validateForkOrder("Agharta", config.getAghartaBlockNumber(), lastForkBlock); lastForkBlock = validateForkOrder("Phoenix", config.getPhoenixBlockNumber(), lastForkBlock); lastForkBlock = validateForkOrder("Thanos", config.getThanosBlockNumber(), lastForkBlock); + lastForkBlock = validateForkOrder("Magneto", config.getMagnetoBlockNumber(), lastForkBlock); assert (lastForkBlock >= 0); } }