From a0429043bd397dbdf6ffa0d6c4ae28e8dbcd5950 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 16:07:00 +0300 Subject: [PATCH 1/8] Fixed bug in ethereumj.conf.file param parsing --- .../src/main/java/org/ethereum/config/SystemProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java index 36464648e6..84d7d82eca 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -198,7 +198,7 @@ public SystemProperties(Config apiConfig, ClassLoader classLoader) { Config testUserConfig = ConfigFactory.parseResources("test-user.conf"); logger.info("Config (" + (testUserConfig.entrySet().size() > 0 ? " yes " : " no ") + "): test properties from resource 'test-user.conf'"); String file = System.getProperty("ethereumj.conf.file"); - Config cmdLineConfigFile = mergeConfigs(res, s -> ConfigFactory.parseFile(new File(s))); + Config cmdLineConfigFile = mergeConfigs(file, s -> ConfigFactory.parseFile(new File(s))); logger.info("Config (" + (cmdLineConfigFile.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.file file(s) '" + file + "'"); logger.info("Config (" + (apiConfig.entrySet().size() > 0 ? " yes " : " no ") + "): config passed via constructor"); config = apiConfig From 87a0eb36321859d6d47c9276869b522570fae191 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 16:31:00 +0300 Subject: [PATCH 2/8] Improve logging of network config --- .../java/org/ethereum/config/Initializer.java | 5 +-- .../ethereum/config/net/BaseNetConfig.java | 20 ++++++--- .../ethereum/config/net/JsonNetConfig.java | 44 +++++++++++++++++++ 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/config/Initializer.java b/ethereumj-core/src/main/java/org/ethereum/config/Initializer.java index dcb22ddfc6..fc78baf36a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/Initializer.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/Initializer.java @@ -64,16 +64,13 @@ private void initConfig(SystemProperties config) { // forcing loading blockchain config config.getBlockchainConfig(); + logger.info("Blockchain config {}", config.getBlockchainConfig().toString()); // forcing loading genesis to fail fast in case of error config.getGenesis(); // forcing reading private key or generating it in database directory config.nodeId(); - - if (logger.isDebugEnabled()) { - logger.debug("Blockchain config {}", config.getBlockchainConfig().toString()); - } } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/config/net/BaseNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/net/BaseNetConfig.java index ccceeae647..95beb88975 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/net/BaseNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/net/BaseNetConfig.java @@ -57,10 +57,20 @@ public Constants getCommonConstants() { @Override public String toString() { - return "BaseNetConfig{" + - "blockNumbers=" + Arrays.toString(Arrays.copyOfRange(blockNumbers, 0, count)) + - ", configs=" + Arrays.toString(Arrays.copyOfRange(configs, 0, count)) + - ", count=" + count + - '}'; + StringBuilder res = new StringBuilder() + .append("BaseNetConfig{") + .append("blockNumbers= "); + + for (int i = 0; i < count; ++i) { + res.append("#").append(blockNumbers[i]).append(" => "); + res.append(configs[i]); + if (i != count - 1) { + res.append(", "); + } + } + + res.append(" (total: ").append(count).append(")}"); + + return res.toString(); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/net/JsonNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/net/JsonNetConfig.java index 2f70fb4890..590902d795 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/net/JsonNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/net/JsonNetConfig.java @@ -21,6 +21,8 @@ import org.ethereum.config.BlockchainConfig; import org.ethereum.config.blockchain.*; import org.ethereum.core.genesis.GenesisConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; @@ -31,6 +33,8 @@ */ public class JsonNetConfig extends BaseNetConfig { + private static Logger logger = LoggerFactory.getLogger("general"); + final BlockchainConfig initialBlockConfig = new FrontierConfig(); /** @@ -46,11 +50,19 @@ public JsonNetConfig(GenesisConfig config) throws RuntimeException { final List> candidates = new ArrayList<>(); { + if (logger.isDebugEnabled()) + logger.debug("Rendering net config from genesis {} ...", config); + + Pair lastCandidate = Pair.of(0, initialBlockConfig); + if (logger.isDebugEnabled()) + logger.debug("Block #{} => Frontier", lastCandidate.getLeft()); candidates.add(lastCandidate); // homestead block assumed to be 0 by default lastCandidate = Pair.of(config.homesteadBlock == null ? 0 : config.homesteadBlock, new HomesteadConfig()); + if (logger.isDebugEnabled()) + logger.debug("Block #{} => Homestead", lastCandidate.getLeft()); candidates.add(lastCandidate); if (config.daoForkBlock != null) { @@ -58,27 +70,38 @@ public JsonNetConfig(GenesisConfig config) throws RuntimeException { new DaoHFConfig(lastCandidate.getRight(), config.daoForkBlock) : new DaoNoHFConfig(lastCandidate.getRight(), config.daoForkBlock); lastCandidate = Pair.of(config.daoForkBlock, daoConfig); + if (logger.isDebugEnabled()) + logger.debug("Block #{} => DaoForkSupport", lastCandidate.getLeft()); candidates.add(lastCandidate); } if (config.eip150Block != null) { lastCandidate = Pair.of(config.eip150Block, new Eip150HFConfig(lastCandidate.getRight())); + if (logger.isDebugEnabled()) + logger.debug("Block #{} => EIP150", lastCandidate.getLeft()); candidates.add(lastCandidate); } if (config.eip155Block != null || config.eip158Block != null) { int block; + StringBuilder logLine = new StringBuilder(); if (config.eip155Block != null) { if (config.eip158Block != null && !config.eip155Block.equals(config.eip158Block)) { throw new RuntimeException("Unable to build config with different blocks for EIP155 (" + config.eip155Block + ") and EIP158 (" + config.eip158Block + ")"); } block = config.eip155Block; + if (logger.isDebugEnabled()) + logLine.append("Block #").append(block).append(" => EIP155"); } else { block = config.eip158Block; + if (logger.isDebugEnabled()) + logLine.append("Block #").append(block).append(" => EIP158"); } if (config.chainId != null) { final int chainId = config.chainId; + if (logger.isDebugEnabled()) + logLine.append(", chainId: ").append(chainId); lastCandidate = Pair.of(block, new Eip160HFConfig(lastCandidate.getRight()) { @Override public Integer getChainId() { @@ -88,11 +111,19 @@ public Integer getChainId() { } else { lastCandidate = Pair.of(block, new Eip160HFConfig(lastCandidate.getRight())); } + if (logger.isDebugEnabled()) + logger.debug(logLine.toString()); candidates.add(lastCandidate); } + if (config.byzantiumBlock != null) { + StringBuilder logLine = new StringBuilder(); + if (logger.isDebugEnabled()) + logLine.append("Block #").append(config.byzantiumBlock).append(" => Byzantium"); if (config.chainId != null) { final int chainId = config.chainId; + if (logger.isDebugEnabled()) + logLine.append(", chainId: ").append(chainId); lastCandidate = Pair.of(config.byzantiumBlock, new ByzantiumConfig(lastCandidate.getRight()) { @Override public Integer getChainId() { @@ -102,11 +133,19 @@ public Integer getChainId() { } else { lastCandidate = Pair.of(config.byzantiumBlock, new ByzantiumConfig(lastCandidate.getRight())); } + if (logger.isDebugEnabled()) + logger.debug(logLine.toString()); candidates.add(lastCandidate); } + if (config.constantinopleBlock != null) { + StringBuilder logLine = new StringBuilder(); + if (logger.isDebugEnabled()) + logLine.append("Block #").append(config.constantinopleBlock).append(" => Constantinople"); if (config.chainId != null) { final int chainId = config.chainId; + if (logger.isDebugEnabled()) + logLine.append(", chainId: ").append(chainId); lastCandidate = Pair.of(config.constantinopleBlock, new ConstantinopleConfig(lastCandidate.getRight()) { @Override public Integer getChainId() { @@ -116,10 +155,15 @@ public Integer getChainId() { } else { lastCandidate = Pair.of(config.constantinopleBlock, new ConstantinopleConfig(lastCandidate.getRight())); } + if (logger.isDebugEnabled()) + logger.debug(logLine.toString()); candidates.add(lastCandidate); } } + if (logger.isDebugEnabled()) + logger.debug("Finished rendering net config from genesis {}", config); + { // add candidate per each block (take last in row for same block) Pair last = candidates.remove(0); From 9b0a46a4a14ebdd179cc136fdac2392f8b1e70e3 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 16:31:11 +0300 Subject: [PATCH 3/8] Fixed config to include Constantinople fork startup --- ethereumj-core/src/main/resources/genesis/ropsten.json | 1 + 1 file changed, 1 insertion(+) diff --git a/ethereumj-core/src/main/resources/genesis/ropsten.json b/ethereumj-core/src/main/resources/genesis/ropsten.json index 4cebf31c28..fc620a4650 100644 --- a/ethereumj-core/src/main/resources/genesis/ropsten.json +++ b/ethereumj-core/src/main/resources/genesis/ropsten.json @@ -3,6 +3,7 @@ "chainId": 3, "eip158Block": 10, "byzantiumBlock": 1700000, + "constantinopleBlock": 4230000, "headerValidators": [ {"number": 10, "hash": "0xb3074f936815a0425e674890d7db7b5e94f3a06dca5b22d291b55dcd02dde93e"}, From 9f14b0708f05f18cf4116e1466dffdb4e485a910 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 16:42:11 +0300 Subject: [PATCH 4/8] Verified that difficulty test is passed --- .../test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java index f5cc43007b..997bbca8c1 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java @@ -38,7 +38,7 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class GitHubBasicTest { - String commitSHA = "7f638829311dfc1d341c1db85d8a891f57fa4da7"; + String commitSHA = "95a309203890e6244c6d4353ca411671973c13b5"; @Test public void btCrypto() throws IOException { @@ -83,7 +83,6 @@ public void btDifficultyMainNetwork() throws IOException, ParseException { } @Test - @Ignore("Disable Ropsten until tests are updated with correct difficulty") public void btDifficultyRopsten() throws IOException, ParseException { runDifficultyTest(new RopstenNetConfig(), "BasicTests/difficultyRopsten.json", commitSHA); } From de80e111d862607080dc05cafc674749af587bcb Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 21:03:39 +0300 Subject: [PATCH 5/8] Fixed origRepository should not change on internal txs --- .../ethereum/core/TransactionExecutor.java | 5 ++-- .../java/org/ethereum/vm/program/Program.java | 6 ++--- .../vm/program/invoke/ProgramInvoke.java | 2 ++ .../program/invoke/ProgramInvokeFactory.java | 4 +-- .../invoke/ProgramInvokeFactoryImpl.java | 8 +++--- .../vm/program/invoke/ProgramInvokeImpl.java | 23 +++++++++++++---- .../program/invoke/ProgramInvokeMockImpl.java | 7 ++++++ .../jsontestsuite/GitHubStateTest.java | 25 +++++++++++++++++-- .../suite/TestProgramInvokeFactory.java | 12 +++++---- .../jsontestsuite/suite/TestRunner.java | 2 +- 10 files changed, 70 insertions(+), 24 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java index 3ef9070bbd..a23db7487e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java @@ -254,7 +254,7 @@ private void call() { result.spendGas(basicTxCost); } else { ProgramInvoke programInvoke = - programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, blockStore); + programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, track, blockStore); this.vm = new VM(config, vmHook); this.program = new Program(track.getCodeHash(targetAddress), code, programInvoke, tx, config, vmHook).withCommonConfig(commonConfig); @@ -289,7 +289,8 @@ private void create() { m_endGas = m_endGas.subtract(BigInteger.valueOf(basicTxCost)); result.spendGas(basicTxCost); } else { - ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, blockStore); + ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, currentBlock, + cacheTrack, track, blockStore); this.vm = new VM(config, vmHook); this.program = new Program(tx.getData(), programInvoke, tx, config, vmHook).withCommonConfig(commonConfig); diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/Program.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/Program.java index 492063c488..dc555267f2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/Program.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/Program.java @@ -140,7 +140,7 @@ public Program(byte[] codeHash, byte[] ops, ProgramInvoke programInvoke, Transac this.traceListener = new ProgramTraceListener(config.vmTrace()); this.memory = setupProgramListener(new Memory()); this.stack = setupProgramListener(new Stack()); - this.originalRepo = programInvoke.getRepository().clone(); + this.originalRepo = programInvoke.getOrigRepository(); this.storage = setupProgramListener(new Storage(programInvoke)); this.trace = new ProgramTrace(config, programInvoke); this.blockchainConfig = config.getBlockchainConfig().getConfigForBlock(programInvoke.getNumber().longValue()); @@ -523,7 +523,7 @@ private void createContractImpl(DataWord value, byte[] programCode, byte[] newAd InternalTransaction internalTx = addInternalTx(nonce, getGasLimit(), senderAddress, null, endowment, programCode, "create"); ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke( this, DataWord.of(newAddress), getOwnerAddress(), value, gasLimit, - newBalance, null, track, this.invoke.getBlockStore(), false, byTestingSuite()); + newBalance, null, track, this.invoke.getOrigRepository(), this.invoke.getBlockStore(), false, byTestingSuite()); ProgramResult result = ProgramResult.createEmpty(); @@ -659,7 +659,7 @@ public void callToAddress(MessageCall msg) { this, DataWord.of(contextAddress), msg.getType().callIsDelegate() ? getCallerAddress() : getOwnerAddress(), msg.getType().callIsDelegate() ? getCallValue() : msg.getEndowment(), - msg.getGas(), contextBalance, data, track, this.invoke.getBlockStore(), + msg.getGas(), contextBalance, data, track, this.invoke.getOrigRepository(), this.invoke.getBlockStore(), msg.getType().callIsStatic() || isStaticCall(), byTestingSuite()); VM vm = new VM(config, vmHook); diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvoke.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvoke.java index dd21d8ce26..cb8701b80d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvoke.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvoke.java @@ -69,6 +69,8 @@ public interface ProgramInvoke { Repository getRepository(); + Repository getOrigRepository(); + BlockStore getBlockStore(); boolean isStaticCall(); diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactory.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactory.java index b7a9b4c096..b992929d92 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactory.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactory.java @@ -33,12 +33,12 @@ public interface ProgramInvokeFactory { ProgramInvoke createProgramInvoke(Transaction tx, Block block, - Repository repository, BlockStore blockStore); + Repository repository, Repository origRepository, BlockStore blockStore); ProgramInvoke createProgramInvoke(Program program, DataWord toAddress, DataWord callerAddress, DataWord inValue, DataWord inGas, BigInteger balanceInt, byte[] dataIn, - Repository repository, BlockStore blockStore, + Repository repository, Repository origRepository, BlockStore blockStore, boolean staticCall, boolean byTestingSuite); diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactoryImpl.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactoryImpl.java index f1348e2bfc..0555d6a160 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactoryImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeFactoryImpl.java @@ -46,7 +46,7 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory { // Invocation by the wire tx @Override public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository, - BlockStore blockStore) { + Repository origRepository, BlockStore blockStore) { /*** ADDRESS op ***/ // YP: Get address of currently executing account. @@ -132,7 +132,7 @@ public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, data, lastHash, coinbase, timestamp, number, difficulty, gaslimit, - repository, blockStore); + repository, origRepository, blockStore); } /** @@ -142,7 +142,7 @@ public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository public ProgramInvoke createProgramInvoke(Program program, DataWord toAddress, DataWord callerAddress, DataWord inValue, DataWord inGas, BigInteger balanceInt, byte[] dataIn, - Repository repository, BlockStore blockStore, + Repository repository, Repository origRepository, BlockStore blockStore, boolean isStaticCall, boolean byTestingSuite) { DataWord address = toAddress; @@ -196,6 +196,6 @@ public ProgramInvoke createProgramInvoke(Program program, DataWord toAddress, Da return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, data, lastHash, coinbase, timestamp, number, difficulty, gasLimit, - repository, program.getCallDeep() + 1, blockStore, isStaticCall, byTestingSuite); + repository, origRepository, program.getCallDeep() + 1, blockStore, isStaticCall, byTestingSuite); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeImpl.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeImpl.java index 7451482c7d..4c56843f1f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeImpl.java @@ -51,6 +51,7 @@ public class ProgramInvokeImpl implements ProgramInvoke { private Map storage; private final Repository repository; + private final Repository origRepository; private boolean byTransaction = true; private boolean byTestingSuite = false; private int callDeep = 0; @@ -60,8 +61,8 @@ public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, Dat DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData, DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord difficulty, - DataWord gaslimit, Repository repository, int callDeep, BlockStore blockStore, - boolean isStaticCall, boolean byTestingSuite) { + DataWord gaslimit, Repository repository, Repository origRepository, int callDeep, + BlockStore blockStore, boolean isStaticCall, boolean byTestingSuite) { // Transaction env this.address = address; @@ -83,6 +84,7 @@ public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, Dat this.gaslimit = gaslimit; this.repository = repository; + this.origRepository = origRepository; this.byTransaction = false; this.callDeep = callDeep; this.blockStore = blockStore; @@ -94,9 +96,10 @@ public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] ba byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData, byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty, byte[] gaslimit, - Repository repository, BlockStore blockStore, boolean byTestingSuite) { + Repository repository, Repository origRepository, BlockStore blockStore, + boolean byTestingSuite) { this(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase, - timestamp, number, difficulty, gaslimit, repository, blockStore); + timestamp, number, difficulty, gaslimit, repository, origRepository, blockStore); this.byTestingSuite = byTestingSuite; } @@ -105,7 +108,7 @@ public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] ba byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData, byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty, byte[] gaslimit, - Repository repository, BlockStore blockStore) { + Repository repository, Repository origRepository, BlockStore blockStore) { // Transaction env this.address = DataWord.of(address); @@ -127,6 +130,7 @@ public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] ba this.gaslimit = DataWord.of(gaslimit); this.repository = repository; + this.origRepository = origRepository; this.blockStore = blockStore; } @@ -261,6 +265,13 @@ public Repository getRepository() { return repository; } + /** + * Repository at the start of top-level ttransaction execution + */ + public Repository getOrigRepository() { + return origRepository; + } + @Override public BlockStore getBlockStore() { return blockStore; @@ -309,6 +320,7 @@ public boolean equals(Object o) { if (origin != null ? !origin.equals(that.origin) : that.origin != null) return false; if (prevHash != null ? !prevHash.equals(that.prevHash) : that.prevHash != null) return false; if (repository != null ? !repository.equals(that.repository) : that.repository != null) return false; + if (origRepository != null ? !origRepository.equals(that.origRepository) : that.origRepository != null) return false; if (storage != null ? !storage.equals(that.storage) : that.storage != null) return false; if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false; @@ -334,6 +346,7 @@ public String toString() { ", gaslimit=" + gaslimit + ", storage=" + storage + ", repository=" + repository + + ", origRepository=" + origRepository + ", byTransaction=" + byTransaction + ", byTestingSuite=" + byTestingSuite + ", callDeep=" + callDeep + diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java index c1ccbe6b89..0ef6828709 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java @@ -37,6 +37,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke { private byte[] msgData; private Repository repository; + private Repository origRepository; private byte[] ownerAddress = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"); private final byte[] contractAddress = Hex.decode("471fd3ad3e9eeadeec4608b92d16ce6b500704cc"); @@ -61,6 +62,7 @@ public ProgramInvokeMockImpl() { + "6040016014525451606001601e52545160800160" + "28525460a052546016604860003960166000f260" + "00603f556103e75660005460005360200235")); + this.origRepository = this.repository.clone(); } public ProgramInvokeMockImpl(boolean defaults) { @@ -236,6 +238,11 @@ public Repository getRepository() { return this.repository; } + @Override + public Repository getOrigRepository() { + return this.repository; + } + @Override public BlockStore getBlockStore() { return new BlockStoreDummy(); diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubStateTest.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubStateTest.java index d1207ac438..6a4f4c7587 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubStateTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubStateTest.java @@ -339,9 +339,30 @@ public void stCreate2Test() throws IOException { "create2collisionStorage" // (nonce, balance 0, code empty, but some storage) ))); // TODO: Update all, this one passes with following settings: -// String commitSHA = "3f5febc901913ef698f1b09dda8705babd729e4a"; -// String treeSHA = "222ea3812849ed982ef0268ec41b609e5b13c412"; +// String commitSHA = "95a309203890e6244c6d4353ca411671973c13b5"; +// String treeSHA = "700fdc4aa7d74957a12fbda38785ecc7b846bcc0"; // targetNets += GitHubJSONTestSuite.Network.Constantinople } + + @Test + @Ignore("Update after all tests could pass latest develop") + public void stSstoreRefundBug() throws IOException { + final String commit = "9ff64743f0347952903287b9074803607e5855e8"; + + GeneralStateTestSuite.runSingle("stSStoreTest/SstoreCallToSelfSubRefundBelowZero.json", commit, + GitHubJSONTestSuite.Network.Constantinople); + + GeneralStateTestSuite.runSingle("stSStoreTest/sstore_0to0.json", commit, + GitHubJSONTestSuite.Network.Constantinople); + + GeneralStateTestSuite.runSingle("stSStoreTest/sstore_Xto0.json", commit, + GitHubJSONTestSuite.Network.Constantinople); + + GeneralStateTestSuite.runSingle("stSStoreTest/sstore_XtoX.json", commit, + GitHubJSONTestSuite.Network.Constantinople); + + GeneralStateTestSuite.runSingle("stSStoreTest/sstore_XtoY.json", commit, + GitHubJSONTestSuite.Network.Constantinople); + } } diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestProgramInvokeFactory.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestProgramInvokeFactory.java index f873a11819..6dcef76a3c 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestProgramInvokeFactory.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestProgramInvokeFactory.java @@ -44,21 +44,23 @@ public TestProgramInvokeFactory(Env env) { @Override - public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository, BlockStore blockStore) { - return generalInvoke(tx, repository, blockStore); + public ProgramInvoke createProgramInvoke(Transaction tx, Block block, + Repository repository, Repository origRepository, BlockStore blockStore) { + return generalInvoke(tx, repository, origRepository, blockStore); } @Override public ProgramInvoke createProgramInvoke(Program program, DataWord toAddress, DataWord callerAddress, DataWord inValue, DataWord inGas, BigInteger balanceInt, byte[] dataIn, - Repository repository, BlockStore blockStore, + Repository repository, Repository origRepository, BlockStore blockStore, boolean isStaticCall, boolean byTestingSuite) { return null; } - private ProgramInvoke generalInvoke(Transaction tx, Repository repository, BlockStore blockStore) { + private ProgramInvoke generalInvoke(Transaction tx, Repository repository, Repository origRepository, + BlockStore blockStore) { /*** ADDRESS op ***/ // YP: Get address of currently executing account. @@ -110,7 +112,7 @@ private ProgramInvoke generalInvoke(Transaction tx, Repository repository, Block return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, data, lastHash, coinbase, - timestamp, number, difficulty, gaslimit, repository, blockStore); + timestamp, number, difficulty, gaslimit, repository, origRepository, blockStore); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestRunner.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestRunner.java index a09db7b7f4..7e991db9ba 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestRunner.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/TestRunner.java @@ -223,7 +223,7 @@ public List runTestCase(TestCase testCase) { ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase, - timestamp, number, difficulty, gaslimit, repository, new BlockStoreDummy(), true); + timestamp, number, difficulty, gaslimit, repository, repository.clone(), new BlockStoreDummy(), true); /* 3. Create Program - exec.code */ /* 4. run VM */ From 93f2739c3fd953d43af9c9e4dbb3de4b84b6dfbb Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 21:10:13 +0300 Subject: [PATCH 6/8] Fixed netConfig toString test (updated fixtures) --- .../java/org/ethereum/config/net/BaseNetConfigTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/test/java/org/ethereum/config/net/BaseNetConfigTest.java b/ethereumj-core/src/test/java/org/ethereum/config/net/BaseNetConfigTest.java index 426da2d7cf..c17cdd2fca 100644 --- a/ethereumj-core/src/test/java/org/ethereum/config/net/BaseNetConfigTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/config/net/BaseNetConfigTest.java @@ -41,7 +41,7 @@ public void addedBlockShouldHaveIncrementedBlockNumber() throws Exception { @Test public void toStringShouldCaterForNulls() throws Exception { BaseNetConfig config = new BaseNetConfig(); - assertEquals("BaseNetConfig{blockNumbers=[], configs=[], count=0}", config.toString()); + assertEquals("BaseNetConfig{blockNumbers= (total: 0)}", config.toString()); BlockchainConfig blockchainConfig = new TestBlockchainConfig() { @Override @@ -50,10 +50,10 @@ public String toString() { } }; config.add(0, blockchainConfig); - assertEquals("BaseNetConfig{blockNumbers=[0], configs=[TestBlockchainConfig], count=1}", config.toString()); + assertEquals("BaseNetConfig{blockNumbers= #0 => TestBlockchainConfig (total: 1)}", config.toString()); config.add(1, blockchainConfig); - assertEquals("BaseNetConfig{blockNumbers=[0, 1], configs=[TestBlockchainConfig, TestBlockchainConfig], count=2}", config.toString()); + assertEquals("BaseNetConfig{blockNumbers= #0 => TestBlockchainConfig, #1 => TestBlockchainConfig (total: 2)}", config.toString()); } private static class TestBlockchainConfig extends AbstractConfig { From 9cb18e7d768446981373b3eccd82e812e877ff03 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 21:16:35 +0300 Subject: [PATCH 7/8] Put back Ropsten difficulty test to ignore, because cached tests repo is old --- .../test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java index 997bbca8c1..a747b80f68 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/GitHubBasicTest.java @@ -83,6 +83,7 @@ public void btDifficultyMainNetwork() throws IOException, ParseException { } @Test + @Ignore("Disable Ropsten until cached tests commit is updated to commitSHA") public void btDifficultyRopsten() throws IOException, ParseException { runDifficultyTest(new RopstenNetConfig(), "BasicTests/difficultyRopsten.json", commitSHA); } From 9ba7f37099e0a2653f340a013432b67ee5288a40 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 15 Oct 2018 23:34:24 +0300 Subject: [PATCH 8/8] Fix test fixture creating (pre executing storage) --- .../ethereum/vm/program/invoke/ProgramInvokeMockImpl.java | 6 +++++- .../src/test/java/org/ethereum/vm/VMMemoryOpTest.java | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java index 0ef6828709..1cc37b4f86 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/invoke/ProgramInvokeMockImpl.java @@ -240,7 +240,7 @@ public Repository getRepository() { @Override public Repository getOrigRepository() { - return this.repository; + return this.origRepository; } @Override @@ -252,6 +252,10 @@ public void setRepository(Repository repository) { this.repository = repository; } + public void setOrigRepository(Repository repository) { + this.origRepository = repository.clone(); + } + @Override public int getCallDeep() { return 0; diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/VMMemoryOpTest.java b/ethereumj-core/src/test/java/org/ethereum/vm/VMMemoryOpTest.java index 00ba721471..ea73e76f54 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/VMMemoryOpTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/VMMemoryOpTest.java @@ -1023,6 +1023,7 @@ private void setStorageToOne(VM vm) { while (!program.isStopped()) vm.step(program); invoke.getRepository().commit(); + invoke.setOrigRepository(invoke.getRepository()); } @Test // SSTORE EIP1283