diff --git a/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java index 84f1256961..fea46125d2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java @@ -52,6 +52,11 @@ public interface BlockchainConfig { */ BigInteger calcDifficulty(BlockHeader curBlock, BlockHeader parent); + /** + * Calculates difficulty adjustment to target mean block time + */ + BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent); + /** * Calculates transaction gas fee */ diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractConfig.java index 1d2399fbee..b6386d955f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractConfig.java @@ -100,8 +100,6 @@ public BigInteger calcDifficulty(BlockHeader curBlock, BlockHeader parent) { return difficulty; } - protected abstract BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent); - protected int getExplosion(BlockHeader curBlock, BlockHeader parent) { int periodCount = (int) (curBlock.getNumber() / getConstants().getEXP_DIFFICULTY_PERIOD()); return periodCount - 2; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ByzantiumConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ByzantiumConfig.java index 22151e4fe4..dd4151f174 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ByzantiumConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ByzantiumConfig.java @@ -1,9 +1,31 @@ package org.ethereum.config.blockchain; import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.Constants; +import org.ethereum.core.Block; +import org.ethereum.core.BlockHeader; +import org.ethereum.core.Repository; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigInteger; + +import static org.ethereum.util.BIUtil.max; /** - * Created by Anton Nashatyrev on 15.08.2017. + * EIPs included in the Hard Fork: + * + * + * @author Mikhail Kalinin + * @since 14.08.2017 */ public class ByzantiumConfig extends Eip160HFConfig { @@ -11,6 +33,35 @@ public ByzantiumConfig(BlockchainConfig parent) { super(parent); } + @Override + public BigInteger calcDifficulty(BlockHeader curBlock, BlockHeader parent) { + BigInteger pd = parent.getDifficultyBI(); + BigInteger quotient = pd.divide(getConstants().getDIFFICULTY_BOUND_DIVISOR()); + + BigInteger sign = getCalcDifficultyMultiplier(curBlock, parent); + + BigInteger fromParent = pd.add(quotient.multiply(sign)); + BigInteger difficulty = max(getConstants().getMINIMUM_DIFFICULTY(), fromParent); + + int explosion = getExplosion(curBlock, parent); + + if (explosion >= 0) { + difficulty = max(getConstants().getMINIMUM_DIFFICULTY(), difficulty.add(BigInteger.ONE.shiftLeft(explosion))); + } + + return difficulty; + } + + protected int getExplosion(BlockHeader curBlock, BlockHeader parent) { + int periodCount = (int) (curBlock.getNumber() / getConstants().getEXP_DIFFICULTY_PERIOD()); + return periodCount - 2; + } + + @Override + public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { + long unclesAdj = parent.hasUncles() ? 2 : 1; + return BigInteger.valueOf(Math.max(unclesAdj - (curBlock.getTimestamp() - parent.getTimestamp()) / 9, -99)); + @Override public boolean eip140() { return true; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ETCFork3M.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ETCFork3M.java index 82b8b834e1..77f4a18dd9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ETCFork3M.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/ETCFork3M.java @@ -66,7 +66,8 @@ public BigInteger calcDifficulty(BlockHeader curBlock, BlockHeader parent) { return difficulty; } - protected BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { + @Override + public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { return BigInteger.valueOf(Math.max(1 - (curBlock.getTimestamp() - parent.getTimestamp()) / 10, -99)); } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/Eip150HFConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/Eip150HFConfig.java index 64f7bc9874..1e541ba3c8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/Eip150HFConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/Eip150HFConfig.java @@ -87,6 +87,11 @@ public BigInteger calcDifficulty(BlockHeader curBlock, BlockHeader parent) { return this.parent.calcDifficulty(curBlock, parent); } + @Override + public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { + return this.parent.getCalcDifficultyMultiplier(curBlock, parent); + } + @Override public long getTransactionCost(Transaction tx) { return parent.getTransactionCost(tx); diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java index 45a63f3047..9bfd4648cf 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java @@ -52,7 +52,7 @@ public HomesteadConfig(Constants constants) { } @Override - protected BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { + public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { return BigInteger.valueOf(Math.max(1 - (curBlock.getTimestamp() - parent.getTimestamp()) / 10, -99)); } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/OlympicConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/OlympicConfig.java index fd3bb40f93..82f8d8eb97 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/OlympicConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/OlympicConfig.java @@ -37,7 +37,7 @@ public OlympicConfig(Constants constants) { } @Override - protected BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { + public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent) { return BigInteger.valueOf(curBlock.getTimestamp() >= parent.getTimestamp() + getConstants().getDURATION_LIMIT() ? -1 : 1); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockHeader.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockHeader.java index 125d016a7d..976393c17f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockHeader.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockHeader.java @@ -148,7 +148,7 @@ public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase, this.extraData = extraData; this.mixHash = mixHash; this.nonce = nonce; - this.stateRoot = HashUtil.EMPTY_TRIE_HASH; + this.stateRoot = EMPTY_TRIE_HASH; } public boolean isGenesis() { @@ -374,6 +374,10 @@ public BigInteger calcDifficulty(BlockchainNetConfig config, BlockHeader parent) calcDifficulty(this, parent); } + public boolean hasUncles() { + return !FastByteComparisons.equal(unclesHash, EMPTY_TRIE_HASH); + } + public String toString() { return toStringWithSuffix("\n"); } diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubJSONTestSuite.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubJSONTestSuite.java index 402d9086b3..4e544653cd 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubJSONTestSuite.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubJSONTestSuite.java @@ -19,6 +19,7 @@ import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.blockchain.*; +import org.ethereum.config.net.BaseNetConfig; import org.ethereum.jsontestsuite.suite.*; import org.ethereum.jsontestsuite.suite.runners.TransactionTestRunner; import org.json.simple.JSONObject; @@ -263,15 +264,37 @@ public enum Network { EIP150, EIP158, Byzantium, - Constantinople; + Constantinople, + + // Transition networks + FrontierToHomesteadAt5, + HomesteadToDaoAt5, + HomesteadToEIP150At5; public BlockchainNetConfig getConfig() { switch (this) { + case Frontier: return new FrontierConfig(); case Homestead: return new HomesteadConfig(); case EIP150: return new Eip150HFConfig(new DaoHFConfig()); case EIP158: return new Eip160HFConfig(new DaoHFConfig()); case Byzantium: return new ByzantiumConfig(new DaoHFConfig()); + + case FrontierToHomesteadAt5: return new BaseNetConfig() {{ + add(0, new FrontierConfig()); + add(5, new HomesteadConfig()); + }}; + + case HomesteadToDaoAt5: return new BaseNetConfig() {{ + add(0, new HomesteadConfig()); + add(5, new DaoHFConfig(new HomesteadConfig(), 5)); + }}; + + case HomesteadToEIP150At5: return new BaseNetConfig() {{ + add(0, new HomesteadConfig()); + add(5, new Eip150HFConfig(new HomesteadConfig())); + }}; + default: throw new IllegalArgumentException("Unknown network value: " + this.name()); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubTestNetTest.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubTestNetTest.java index 4bacd14558..412c2bf73b 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubTestNetTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubTestNetTest.java @@ -17,57 +17,47 @@ */ package org.ethereum.jsontestsuite; -import org.ethereum.config.SystemProperties; -import org.ethereum.config.blockchain.DaoHFConfig; -import org.ethereum.config.blockchain.Eip150HFConfig; -import org.ethereum.config.blockchain.FrontierConfig; -import org.ethereum.config.blockchain.HomesteadConfig; -import org.ethereum.config.net.BaseNetConfig; -import org.ethereum.config.net.MainNetConfig; -import org.ethereum.jsontestsuite.suite.JSONReader; -import org.json.simple.parser.ParseException; +import org.ethereum.jsontestsuite.suite.BlockchainTestSuite; import org.junit.*; import org.junit.runners.MethodSorters; import java.io.IOException; -import java.util.Collections; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class GitHubTestNetTest { - //SHACOMMIT of tested commit, ethereum/tests.git - public String shacommit = "9ed33d7440f13c09ce7f038f92abd02d23b26f0d"; + static String commitSHA = "85f6d7cc01b6bd04e071f5ba579fc675cfd2043b"; + static String treeSHA = "0af522c09e8a264f651f5a4715301381c14784d7"; // https://github.com/ethereum/tests/tree/develop/BlockchainTests/TransitionTests - @Before - public void setup() { - SystemProperties.getDefault().setGenesisInfo("frontier.json"); - SystemProperties.getDefault().setBlockchainConfig(new BaseNetConfig() {{ - add(0, new FrontierConfig()); - add(5, new HomesteadConfig()); - add(8, new DaoHFConfig(new HomesteadConfig(), 8)); - add(10, new Eip150HFConfig(new DaoHFConfig(new HomesteadConfig(), 8))); + static BlockchainTestSuite suite; - }}); + @BeforeClass + public static void setup() { + suite = new BlockchainTestSuite(treeSHA, commitSHA); } - @After - public void clean() { - SystemProperties.getDefault().setBlockchainConfig(MainNetConfig.INSTANCE); + @Test + @Ignore + // this method is mostly for hands-on convenient testing + // using this method turn off initializing of BlockchainTestSuite to avoid unnecessary GitHub API hits + public void bcTransitionSingle() throws IOException { + BlockchainTestSuite.runSingle( + "TransitionTests/bcHomesteadToDao/DaoTransactions.json", commitSHA); } @Test - public void bcEIP150Test() throws ParseException, IOException { - String json = JSONReader.loadJSONFromCommit("BlockchainTests/TestNetwork/bcEIP150Test.json", shacommit); - GitHubJSONTestSuite.runGitHubJsonBlockTest(json, Collections.EMPTY_SET); + public void bcFrontierToHomestead() throws IOException { + suite.runAll("TransitionTests/bcFrontierToHomestead", GitHubJSONTestSuite.Network.FrontierToHomesteadAt5); } + @Test - public void bcSimpleTransitionTest() throws ParseException, IOException { - String json = JSONReader.loadJSONFromCommit("BlockchainTests/TestNetwork/bcSimpleTransitionTest.json", shacommit); - GitHubJSONTestSuite.runGitHubJsonBlockTest(json, Collections.EMPTY_SET); + @Ignore // TODO fix it + public void bcHomesteadToDao() throws IOException { + suite.runAll("TransitionTests/bcHomesteadToDao", GitHubJSONTestSuite.Network.HomesteadToDaoAt5); } + @Test - public void bcTheDaoTest() throws ParseException, IOException { - String json = JSONReader.loadJSONFromCommit("BlockchainTests/TestNetwork/bcTheDaoTest.json", shacommit); - GitHubJSONTestSuite.runGitHubJsonBlockTest(json, Collections.EMPTY_SET); + public void bcHomesteadToEIP150() throws IOException { + suite.runAll("TransitionTests/bcHomesteadToEIP150", GitHubJSONTestSuite.Network.HomesteadToEIP150At5); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/BlockchainTestSuite.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/BlockchainTestSuite.java index b5f1cffbce..736e68816b 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/BlockchainTestSuite.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/BlockchainTestSuite.java @@ -33,6 +33,10 @@ public BlockchainTestSuite(String treeSHA, String commitSHA, GitHubJSONTestSuite this.networks = networks; } + public BlockchainTestSuite(String treeSHA, String commitSHA) { + this(treeSHA, commitSHA, GitHubJSONTestSuite.Network.values()); + } + private static void run(List checkFiles, String commitSHA, GitHubJSONTestSuite.Network[] networks) throws IOException { @@ -142,4 +146,9 @@ public static void runSingle(String testFile, String commitSHA, logger.info(" " + testFile); run(Collections.singletonList(testFile), commitSHA, new GitHubJSONTestSuite.Network[] { network }); } + + public static void runSingle(String testFile, String commitSHA) throws IOException { + logger.info(" " + testFile); + run(Collections.singletonList(testFile), commitSHA, GitHubJSONTestSuite.Network.values()); + } }