From c34ea0fa88c39a5598d8d3b6b4083c977adf5c7b Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 22 Feb 2018 19:12:45 +0300 Subject: [PATCH 01/67] Casper init commit. Passive sync is ok, mining is ok, validator in debug. Refactoring needed. --- ethereumj-core/build.gradle | 6 + .../org/ethereum/config/CommonConfig.java | 61 +- .../org/ethereum/config/SystemProperties.java | 76 + .../config/blockchain/Eip150HFConfig.java | 2 +- .../config/net/CasperTestNetConfig.java | 80 + .../main/java/org/ethereum/core/Block.java | 1 + .../org/ethereum/core/BlockchainImpl.java | 72 +- .../org/ethereum/core/CallTransaction.java | 4 +- .../java/org/ethereum/core/PendingState.java | 11 + .../org/ethereum/core/PendingStateImpl.java | 51 +- .../java/org/ethereum/core/Repository.java | 2 + .../java/org/ethereum/core/Transaction.java | 4 +- .../ethereum/core/TransactionExecutor.java | 56 +- .../core/casper/CasperBlockchain.java | 445 +++ .../CasperHybridConsensusStrategy.java | 197 ++ .../core/consensus/ConsensusStrategy.java | 44 + .../core/consensus/PoWConsensusStrategy.java | 121 + .../core/genesis/CasperStateInit.java | 172 ++ .../core/genesis/CommonStateInit.java | 63 + .../org/ethereum/core/genesis/StateInit.java | 36 + .../main/java/org/ethereum/db/BlockStore.java | 5 + .../java/org/ethereum/db/BlockStoreDummy.java | 10 + .../org/ethereum/db/IndexedBlockStore.java | 9 + .../java/org/ethereum/db/RepositoryImpl.java | 5 + .../org/ethereum/db/RepositoryWrapper.java | 7 +- .../java/org/ethereum/facade/Ethereum.java | 37 + .../org/ethereum/facade/EthereumImpl.java | 56 +- .../org/ethereum/manager/BlockLoader.java | 19 +- .../manager/CasperValidatorService.java | 558 ++++ .../org/ethereum/manager/WorldManager.java | 39 +- .../java/org/ethereum/mine/BlockMiner.java | 9 +- .../org/ethereum/net/eth/handler/Eth62.java | 13 +- .../org/ethereum/net/eth/handler/Eth63.java | 6 +- .../org/ethereum/net/rlpx/FrameCodec.java | 31 +- .../org/ethereum/net/rlpx/MessageCodec.java | 6 +- .../java/org/ethereum/net/server/Channel.java | 2 +- .../ethereum/net/server/ChannelManager.java | 7 +- .../ethereum/net/submit/TransactionTask.java | 16 + .../java/org/ethereum/net/swarm/Util.java | 59 +- .../net/swarm/bzz/BzzStatusMessage.java | 4 +- .../org/ethereum/solidity/SolidityType.java | 75 +- .../org/ethereum/sync/FastSyncDownloader.java | 9 +- .../org/ethereum/sync/FastSyncManager.java | 14 +- .../java/org/ethereum/sync/SyncManager.java | 8 +- .../main/java/org/ethereum/sync/SyncPool.java | 5 +- .../src/main/java/org/ethereum/util/RLP.java | 39 + .../util/blockchain/StandaloneBlockchain.java | 29 +- .../java/org/ethereum/vm/program/Program.java | 19 +- .../java/org/ethereum/vm/program/Storage.java | 6 + ethereumj-core/src/main/resources/casper.conf | 95 + .../src/main/resources/casper/casper.abi | 545 ++++ .../src/main/resources/casper/casper.bin | 1 + .../src/main/resources/casper/casper.lll | 2666 +++++++++++++++++ .../src/main/resources/ethereumj.conf | 8 + .../src/main/resources/genesis/casper.json | 21 + ethereumj-core/src/main/resources/logback.xml | 1 + .../org/ethereum/core/ImportLightTest.java | 4 +- .../core/PendingStateLongRunTest.java | 3 +- .../core/casper/CasperStateInitTest.java | 200 ++ .../suite/IterableTestRepository.java | 6 + .../jsontestsuite/suite/TestRunner.java | 5 +- 61 files changed, 5951 insertions(+), 210 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java create mode 100644 ethereumj-core/src/main/resources/casper.conf create mode 100644 ethereumj-core/src/main/resources/casper/casper.abi create mode 100644 ethereumj-core/src/main/resources/casper/casper.bin create mode 100644 ethereumj-core/src/main/resources/casper/casper.lll create mode 100644 ethereumj-core/src/main/resources/genesis/casper.json create mode 100644 ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java diff --git a/ethereumj-core/build.gradle b/ethereumj-core/build.gradle index f2d0886d4b..8cf47ae148 100644 --- a/ethereumj-core/build.gradle +++ b/ethereumj-core/build.gradle @@ -63,6 +63,12 @@ task runTest (type: JavaExec) { jvmArgs = applicationDefaultJvmArgs + '-Dethereumj.conf.res=test.conf' } +task runCasper (type: JavaExec) { + main = mainClassName + classpath = sourceSets.main.runtimeClasspath + jvmArgs = applicationDefaultJvmArgs + '-Dethereumj.conf.res=casper.conf' +} + /** * This is TCK test command line option, * to run the test: diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index 46a3b1d77e..6b33a010ee 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -18,6 +18,9 @@ package org.ethereum.config; import org.ethereum.core.*; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.core.consensus.PoWConsensusStrategy; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.*; import org.ethereum.datasource.inmem.HashMapDB; @@ -31,13 +34,13 @@ import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.*; import org.springframework.transaction.annotation.EnableTransactionManagement; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import static java.util.Arrays.asList; @@ -51,6 +54,12 @@ public class CommonConfig { private static final Logger logger = LoggerFactory.getLogger("general"); private Set dbSources = new HashSet<>(); + private ConsensusStrategy consensusStrategy; + + + @Autowired + private ApplicationContext ctx; + private static CommonConfig defaultInstance; public static CommonConfig getDefault() { @@ -60,6 +69,11 @@ public static CommonConfig getDefault() { public Source precompileSource() { return null; } + + @Override + public ConsensusStrategy consensusStrategy() { + return new PoWConsensusStrategy(systemProperties()); + } }; } return defaultInstance; @@ -234,32 +248,6 @@ public DbFlushManager dbFlushManager() { return new DbFlushManager(systemProperties(), dbSources, blockchainDbCache()); } - @Bean - public BlockHeaderValidator headerValidator() { - - List rules = new ArrayList<>(asList( - new GasValueRule(), - new ExtraDataRule(systemProperties()), - new ProofOfWorkRule(), - new GasLimitRule(systemProperties()), - new BlockHashRule(systemProperties()) - )); - - return new BlockHeaderValidator(rules); - } - - @Bean - public ParentBlockHeaderValidator parentHeaderValidator() { - - List rules = new ArrayList<>(asList( - new ParentNumberRule(), - new DifficultyRule(systemProperties()), - new ParentGasLimitRule(systemProperties()) - )); - - return new ParentBlockHeaderValidator(rules); - } - @Bean @Lazy public PeerSource peerSource() { @@ -267,4 +255,21 @@ public PeerSource peerSource() { dbSources.add(dbSource); return new PeerSource(dbSource); } + + @Bean + public ConsensusStrategy consensusStrategy() { + if(consensusStrategy == null) { + switch (systemProperties().getConsensusStrategy()) { + case "pow": + consensusStrategy = new PoWConsensusStrategy(systemProperties(), ctx); + break; + case "casper-hybrid": + consensusStrategy = new CasperHybridConsensusStrategy(systemProperties(), ctx); + break; + default: + throw new RuntimeException("Consensus strategy is not set. Breaking."); + } + } + return consensusStrategy; + } } 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 9ace68a9ff..13c578e618 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -51,6 +51,7 @@ import java.net.Socket; import java.net.URL; import java.util.*; +import java.util.stream.Collectors; import static org.ethereum.crypto.HashUtil.sha3; @@ -154,6 +155,7 @@ static boolean isUseOnlySpringConfig() { private Genesis genesis; private Boolean vmTrace; private Boolean recordInternalTransactionsData; + private byte[] casperAddress = null; private final ClassLoader classLoader; @@ -342,6 +344,9 @@ public BlockchainNetConfig getBlockchainConfig() { case "testnet": blockchainConfig = new TestNetConfig(); break; + case "casper": + blockchainConfig = new CasperTestNetConfig(); + break; default: throw new RuntimeException("Unknown value for 'blockchain.config.name': '" + config.getString("blockchain.config.name") + "'"); } @@ -912,6 +917,77 @@ public Genesis getGenesis() { return genesis; } + @ValidateMe + public String getConsensusStrategy() { + return config.getString("consensus.strategy"); + } + + public byte[] getCasperAddress() { + return casperAddress; + } + + public void setCasperAddress(byte[] casperAddress) { + this.casperAddress = casperAddress; + } + + public int getCasperEpochLength() { + return config.getInt("consensus.casper.epochLength"); + } + + public byte[] getCasperValidatorPrivateKey() { + String key = config.getString("consensus.casper.validator.privateKey"); + if (key == null) return null; + return ByteUtil.hexStringToBytes(key); + } + + public long getCasperValidatorDeposit() { + return config.getLong("consensus.casper.validator.deposit"); + } + + public Boolean getCasperValidatorEnabled() { + return config.getBoolean("consensus.casper.validator.enabled"); + } + + // TODO: Implement me + // How to trigger this when I need it w/o restart? + public boolean getCasperValidatorShouldLogout() { + return false; + } + + + public String getCasperAbi() { + final String abiLocation = config.getString("consensus.casper.contractAbi"); + return readFile(abiLocation); + } + + public String getCasperBin() { + final String binLocation = config.getString("consensus.casper.contractBin"); + return readFile(binLocation); + } + + private static String readFile(final String location) { + try { + InputStream is = SystemProperties.class.getResourceAsStream(location); + + if (is != null) { + return readStream(is); + } else { + logger.error("File not found `{}`", location); + throw new RuntimeException(String.format("File not found `%s`", location)); + } + } catch (Exception ex) { + String errorMsg = String.format("Error while reading file from %s", location); + logger.error(errorMsg, ex); + throw new RuntimeException(errorMsg, ex); + } + } + + private static String readStream(InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + return buffer.lines().collect(Collectors.joining("\n")); + } + } + /** * Method used in StandaloneBlockchain. */ 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 63e4a17b82..2ce71310e0 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 @@ -45,7 +45,7 @@ public class Eip150HFConfig implements BlockchainConfig, BlockchainNetConfig { protected BlockchainConfig parent; - static class GasCostEip150HF extends GasCost { + public static class GasCostEip150HF extends GasCost { public int getBALANCE() { return 400; } public int getEXT_CODE_SIZE() { return 700; } public int getEXT_CODE_COPY() { return 700; } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java new file mode 100644 index 0000000000..cef3227490 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.config.net; + +import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.Constants; +import org.ethereum.config.ConstantsAdapter; +import org.ethereum.config.blockchain.ByzantiumConfig; +import org.ethereum.config.blockchain.Eip150HFConfig; +import org.ethereum.config.blockchain.FrontierConfig; +import org.ethereum.vm.GasCost; + +import java.math.BigInteger; + +public class CasperTestNetConfig extends BaseNetConfig { + public static final CasperTestNetConfig INSTANCE = new CasperTestNetConfig(); + + static class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { + public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork + } + + private static final GasCost NEW_GAS_COST = new CasperGasCost(); + + private class CasperConfig extends ByzantiumConfig { + private final Constants constants; + public CasperConfig(BlockchainConfig parent) { + + super(parent); + constants = new ConstantsAdapter(super.getConstants()) { + private final BigInteger BLOCK_REWARD = new BigInteger("1000000000000000000"); // 1 ETH + + private final BigInteger MINIMUM_DIFFICULTY = BigInteger.valueOf(8192); + + @Override + public BigInteger getBLOCK_REWARD() { + return BLOCK_REWARD; + } + + @Override + public BigInteger getMINIMUM_DIFFICULTY() { + return MINIMUM_DIFFICULTY; + } + }; + } + + @Override + public GasCost getGasCost() { + return NEW_GAS_COST; + } + + @Override + public boolean eip161() { + return false; + } + + @Override + public Constants getConstants() { + return constants; + } + } + + public CasperTestNetConfig() { + add(0, new CasperConfig(new FrontierConfig())); + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Block.java b/ethereumj-core/src/main/java/org/ethereum/core/Block.java index e2db0af99b..86cbe4e807 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Block.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Block.java @@ -386,6 +386,7 @@ public boolean isParentOf(Block block) { } public boolean isGenesis() { + parseRLP(); return this.header.isGenesis(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 3e44334565..822f10fa52 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -17,7 +17,6 @@ */ package org.ethereum.core; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; @@ -29,7 +28,6 @@ import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.manager.AdminInfo; -import org.ethereum.sync.SyncManager; import org.ethereum.util.*; import org.ethereum.validator.DependentBlockHeaderRule; import org.ethereum.validator.ParentBlockHeaderValidator; @@ -40,6 +38,7 @@ import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import java.io.BufferedWriter; @@ -55,9 +54,7 @@ import java.util.Map; import java.util.Set; import java.util.Stack; -import java.util.concurrent.*; -import static java.lang.Math.PI; import static java.lang.Math.max; import static java.lang.Runtime.getRuntime; import static java.math.BigInteger.ONE; @@ -66,7 +63,6 @@ import static org.ethereum.core.Denomination.SZABO; import static org.ethereum.core.ImportResult.*; import static org.ethereum.crypto.HashUtil.sha3; -import static org.ethereum.util.BIUtil.isMoreThan; /** * The Ethereum blockchain is in many ways similar to the Bitcoin blockchain, @@ -97,6 +93,7 @@ * @author Nick Savers * @since 20.05.2014 */ +@Lazy @Component public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchain { @@ -109,7 +106,6 @@ public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchai private static final int MAGIC_REWARD_OFFSET = 8; public static final byte[] EMPTY_LIST_HASH = sha3(RLP.encodeList(new byte[0])); - @Autowired @Qualifier("defaultRepository") private Repository repository; @Autowired @@ -123,28 +119,24 @@ public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchai private BigInteger totalDifficulty = ZERO; @Autowired - private EthereumListener listener; + protected EthereumListener listener; @Autowired ProgramInvokeFactory programInvokeFactory; @Autowired - private AdminInfo adminInfo; + protected AdminInfo adminInfo; - @Autowired private DependentBlockHeaderRule parentHeaderValidator; @Autowired private PendingState pendingState; @Autowired - EventDispatchThread eventDispatchThread; - - @Autowired - CommonConfig commonConfig = CommonConfig.getDefault(); + protected EventDispatchThread eventDispatchThread; @Autowired - SyncManager syncManager; + protected CommonConfig commonConfig = CommonConfig.getDefault(); @Autowired PruneManager pruneManager; @@ -155,7 +147,7 @@ public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchai @Autowired DbFlushManager dbFlushManager; - SystemProperties config = SystemProperties.getDefault(); + protected SystemProperties config = SystemProperties.getDefault(); private List altChains = new ArrayList<>(); private List garbage = new ArrayList<>(); @@ -163,7 +155,7 @@ public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchai long exitOn = Long.MAX_VALUE; public boolean byTest = false; - private boolean fork = false; + protected boolean fork = false; private byte[] minerCoinbase; private byte[] minerExtraData; @@ -211,13 +203,23 @@ public BlockchainImpl withEthereumListener(EthereumListener listener) { return this; } - public BlockchainImpl withSyncManager(SyncManager syncManager) { - this.syncManager = syncManager; + public BlockchainImpl withParentBlockHeaderValidator(ParentBlockHeaderValidator parentHeaderValidator) { + this.parentHeaderValidator = parentHeaderValidator; return this; } - public BlockchainImpl withParentBlockHeaderValidator(ParentBlockHeaderValidator parentHeaderValidator) { - this.parentHeaderValidator = parentHeaderValidator; + public BlockchainImpl withEventDispatchThread(EventDispatchThread eventDispatchThread) { + this.eventDispatchThread = eventDispatchThread; + return this; + } + + public BlockchainImpl withCommonConfig(CommonConfig commonConfig) { + this.commonConfig = commonConfig; + return this; + } + + public BlockchainImpl withBlockStore(BlockStore blockStore) { + this.blockStore = blockStore; return this; } @@ -340,7 +342,7 @@ public ProgramInvokeFactory getProgramInvokeFactory() { return programInvokeFactory; } - private State pushState(byte[] bestBlockHash) { + protected State pushState(byte[] bestBlockHash) { State push = stateStack.push(new State()); this.bestBlock = blockStore.getBlockByHash(bestBlockHash); totalDifficulty = blockStore.getTotalDifficultyForHash(bestBlockHash); @@ -348,7 +350,7 @@ private State pushState(byte[] bestBlockHash) { return push; } - private void popState() { + protected void popState() { State state = stateStack.pop(); this.repository = repository.getSnapshotTo(state.root); this.bestBlock = state.savedBest; @@ -411,6 +413,12 @@ public synchronized ImportResult tryToConnect(final Block block) { Hex.toHexString(block.getHash()).substring(0, 6), block.getNumber()); + if (blockExists(block)) return EXIST; // retry of well known block + + return tryToConnectImpl(block); + } + + protected boolean blockExists(final Block block) { if (blockStore.getMaxNumber() >= block.getNumber() && blockStore.isBlockExist(block.getHash())) { @@ -419,9 +427,12 @@ public synchronized ImportResult tryToConnect(final Block block) { Hex.toHexString(block.getHash()).substring(0, 6), block.getNumber()); - // retry of well known block - return EXIST; + return true; } + return false; + } + + protected ImportResult tryToConnectImpl(final Block block) { final ImportResult ret; @@ -708,7 +719,7 @@ public boolean isValid(BlockHeader header) { * likely next period. Conversely, if the period is too large, the difficulty, * and expected time to the next block, is reduced. */ - private boolean isValid(Repository repo, Block block) { + protected boolean isValid(Repository repo, Block block) { boolean isValid = true; @@ -850,7 +861,7 @@ private BlockSummary processBlock(Repository track, Block block) { } } - private BlockSummary applyBlock(Repository track, Block block) { + protected BlockSummary applyBlock(Repository track, Block block) { logger.debug("applyBlock: block: [{}] tx.list: [{}]", block.getNumber(), block.getTransactionsList().size()); @@ -929,7 +940,7 @@ private BlockSummary applyBlock(Repository track, Block block) { * * @param block object containing the header and uncles */ - private Map addReward(Repository track, Block block, List summaries) { + protected Map addReward(Repository track, Block block, List summaries) { Map rewards = new HashMap<>(); @@ -1046,7 +1057,7 @@ public void setTotalDifficulty(BigInteger totalDifficulty) { this.totalDifficulty = totalDifficulty; } - private void recordBlock(Block block) { + protected void recordBlock(Block block) { if (!config.recordBlocks()) return; @@ -1098,8 +1109,11 @@ public void updateBlockTotDifficulties(int startFrom) { } } + // FIXME: Magic + @Autowired @Qualifier("defaultRepository") public void setRepository(Repository repository) { this.repository = repository; + repository.setBlockchain(this); } public void setProgramInvokeFactory(ProgramInvokeFactory factory) { @@ -1285,7 +1299,7 @@ public List getListOfBodiesByHashes(List hashes) { return bodies; } - private class State { + protected class State { // Repository savedRepo = repository; byte[] root = repository.getRoot(); Block savedBest = bestBlock; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java b/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java index 6375f31a17..eae22f5ec7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java @@ -22,6 +22,7 @@ import static org.apache.commons.lang3.StringUtils.stripEnd; import static org.ethereum.crypto.HashUtil.sha3; import static org.ethereum.solidity.SolidityType.IntType; +import static org.ethereum.util.ByteUtil.hexStringToBytes; import static org.ethereum.util.ByteUtil.longToBytesNoLeadZeroes; import com.fasterxml.jackson.annotation.JsonGetter; @@ -38,7 +39,6 @@ import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; import org.ethereum.vm.LogInfo; -import org.spongycastle.util.encoders.Hex; /** * Creates a contract function call transaction. @@ -57,7 +57,7 @@ public static Transaction createRawTransaction(long nonce, long gasPrice, long g Transaction tx = new Transaction(longToBytesNoLeadZeroes(nonce), longToBytesNoLeadZeroes(gasPrice), longToBytesNoLeadZeroes(gasLimit), - toAddress == null ? null : Hex.decode(toAddress), + toAddress == null ? null : hexStringToBytes(toAddress), longToBytesNoLeadZeroes(value), data, null); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingState.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingState.java index 96297e5031..73e54c6025 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingState.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingState.java @@ -18,6 +18,7 @@ package org.ethereum.core; import java.util.List; +import java.util.function.Consumer; /** * @author Mikhail Kalinin @@ -43,6 +44,16 @@ public interface PendingState extends org.ethereum.facade.PendingState { */ void addPendingTransaction(Transaction tx); + /** + * Adds transaction to the list of pending state txs
+ * For the moment this list is populated with txs sent by our peer only
+ * Triggers an update of pending state + * + * @param tx transaction + * @param errorConsumer Fires if tx execution failed on current state in PendingState + */ + void addPendingTransaction(Transaction tx, Consumer errorConsumer); + /** * It should be called on each block imported as BEST
* Does several things: diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 10eb6989ff..40cbe9cb19 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -24,10 +24,10 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.TreeSet; +import java.util.function.Consumer; import org.apache.commons.collections4.map.LRUMap; import org.ethereum.config.CommonConfig; @@ -80,8 +80,7 @@ public TransactionSortedSet() { @Autowired private EthereumListener listener; - @Autowired - private BlockchainImpl blockchain; + private Blockchain blockchain; @Autowired private BlockStore blockStore; @@ -106,6 +105,10 @@ public TransactionSortedSet() { private Block best = null; @Autowired + public PendingStateImpl(final EthereumListener listener) { + this.listener = listener; + } + public PendingStateImpl(final EthereumListener listener, final BlockchainImpl blockchain) { this.listener = listener; this.blockchain = blockchain; @@ -115,12 +118,21 @@ public PendingStateImpl(final EthereumListener listener, final BlockchainImpl bl this.transactionStore = blockchain.getTransactionStore(); } + public void postConstruct() { + BlockchainImpl blockchain = (BlockchainImpl) commonConfig.consensusStrategy().getBlockchain(); + this.blockchain = blockchain; +// this.repository = blockchain.getRepository(); + this.blockStore = blockchain.getBlockStore(); + this.programInvokeFactory = blockchain.getProgramInvokeFactory(); + this.transactionStore = blockchain.getTransactionStore(); + } + public void init() { this.pendingState = getOrigRepository().startTracking(); } private Repository getOrigRepository() { - return blockchain.getRepositorySnapshot(); + return ((BlockchainImpl) blockchain).getRepositorySnapshot(); } @Override @@ -159,6 +171,29 @@ public void addPendingTransaction(Transaction tx) { addPendingTransactions(Collections.singletonList(tx)); } + @Override + public void addPendingTransaction(Transaction tx, Consumer errorConsumer) { + int unknownTx = 0; + List newPending = new ArrayList<>(); + if (addNewTxIfNotExist(tx)) { + unknownTx++; + TransactionReceipt receipt = addPendingTransactionImpl(tx); + if (receipt.isValid()) { + newPending.add(tx); + } else { + errorConsumer.accept(new Throwable("Tx execution simulation failed: " + receipt.getError())); + } + } + + logger.debug("Wire transaction list added: total: {}, new: {}, valid (added to pending): {} (current #of known txs: {})", + 1, unknownTx, newPending, receivedTxs.size()); + + if (!newPending.isEmpty()) { + listener.onPendingTransactionsReceived(newPending); + listener.onPendingStateChanged(PendingStateImpl.this); + } + } + @Override public synchronized List addPendingTransactions(List transactions) { int unknownTx = 0; @@ -166,7 +201,7 @@ public synchronized List addPendingTransactions(List t for (Transaction tx : transactions) { if (addNewTxIfNotExist(tx)) { unknownTx++; - if (addPendingTransactionImpl(tx)) { + if (addPendingTransactionImpl(tx).isValid()) { newPending.add(tx); } } @@ -214,9 +249,9 @@ private void fireTxUpdate(TransactionReceipt txReceipt, PendingTransactionState * Executes pending tx on the latest best block * Fires pending state update * @param tx Transaction - * @return True if transaction gets NEW_PENDING state, False if DROPPED + * @return execution receipt */ - private boolean addPendingTransactionImpl(final Transaction tx) { + private TransactionReceipt addPendingTransactionImpl(final Transaction tx) { TransactionReceipt newReceipt = new TransactionReceipt(); newReceipt.setTransaction(tx); @@ -235,7 +270,7 @@ private boolean addPendingTransactionImpl(final Transaction tx) { pendingTransactions.add(new PendingTransaction(tx, getBestBlock().getNumber())); fireTxUpdate(txReceipt, NEW_PENDING, getBestBlock()); } - return txReceipt.isValid(); + return txReceipt; } private TransactionReceipt createDroppedReceipt(Transaction tx, String error) { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Repository.java b/ethereumj-core/src/main/java/org/ethereum/core/Repository.java index 6ec1c16fa3..e434e57f64 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Repository.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Repository.java @@ -235,4 +235,6 @@ void loadAccount(byte[] addr, HashMap cacheAccou HashMap cacheDetails); Repository getSnapshotTo(byte[] root); + + void setBlockchain(Blockchain blockchain); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java index 1b55649174..5a5d9cb54e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java @@ -53,6 +53,7 @@ public class Transaction { private static final Logger logger = LoggerFactory.getLogger(Transaction.class); private static final BigInteger DEFAULT_GAS_PRICE = new BigInteger("10000000000000"); private static final BigInteger DEFAULT_BALANCE_GAS = new BigInteger("21000"); + public static final byte[] NULL_SENDER = Hex.decode("ffffffffffffffffffffffffffffffffffffffff"); public static final int HASH_LENGTH = 32; public static final int ADDRESS_LENGTH = 20; @@ -377,7 +378,8 @@ public synchronized byte[] getSender() { if (sendAddress == null && getSignature() != null) { sendAddress = ECKey.signatureToAddress(getRawHash(), getSignature()); } - return sendAddress; + // FIXME: Casper votes, we shouldn't do it this for Transaction itself + return sendAddress == null ? NULL_SENDER : sendAddress; } catch (SignatureException e) { logger.error(e.getMessage(), e); } 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 214dc9f2b3..eb02a8197d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java @@ -21,10 +21,12 @@ import org.ethereum.config.BlockchainConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ContractDetails; import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.manager.WorldManager; import org.ethereum.util.ByteArraySet; import org.ethereum.vm.*; import org.ethereum.vm.program.Program; @@ -36,6 +38,7 @@ import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; +import java.util.Arrays; import java.util.List; import static org.apache.commons.lang3.ArrayUtils.getLength; @@ -129,7 +132,7 @@ private void execError(String err) { * will be ready to run the transaction at the end * set readyToExecute = true */ - public void init() { + public void init() { // TODO: probably we need consensus-specific validation basicTxCost = tx.transactionCost(config.getBlockchainConfig(), currentBlock); if (localCall) { @@ -174,7 +177,7 @@ public void init() { return; } - if (!blockchainConfig.acceptTransactionSignature(tx)) { + if (!isCasperVote() && !blockchainConfig.acceptTransactionSignature(tx)) { execError("Transaction signature not accepted: " + tx.getSignature()); return; } @@ -186,7 +189,8 @@ public void execute() { if (!readyToExecute) return; - if (!localCall) { + // FIXME: Additional logic should be refactored to take place only for Casper + if (!localCall && !isCasperVote()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -385,6 +389,22 @@ private void rollback() { tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress()); } + // TODO: I shouldn't be here + private boolean isCasperVote() { + if (!(commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) + return false; + if (!Arrays.equals(tx.getSender(), Transaction.NULL_SENDER)) + return false; + if (config.getCasperAddress() == null) + return false; // Not yet initialized + if (!Arrays.equals(tx.getReceiveAddress(), config.getCasperAddress())) + return false; + + byte[] dataCopy = new byte[4]; + System.arraycopy(tx.getData(), 0, dataCopy, 0, 4); + return Arrays.equals(dataCopy, new byte[] {(byte) 0xe9, (byte) 0xdc, 0x06, 0x14}); + } + public TransactionExecutionSummary finalization() { if (!readyToExecute) return null; @@ -428,11 +448,6 @@ public TransactionExecutionSummary finalization() { track.addBalance(tx.getSender(), summary.getLeftover().add(summary.getRefund())); logger.info("Pay total refund to sender: [{}], refund val: [{}]", Hex.toHexString(tx.getSender()), summary.getRefund()); - // Transfer fees to miner - track.addBalance(coinbase, summary.getFee()); - touchedAccounts.add(coinbase); - logger.info("Pay fees to miner: [{}], feesEarned: [{}]", Hex.toHexString(coinbase), summary.getFee()); - if (result != null) { logs = result.getLogInfoList(); // Traverse list of suicides @@ -441,6 +456,17 @@ public TransactionExecutionSummary finalization() { } } + // TODO: We definitely need separate TransactionExecutor for Casper + if (getReceipt().isSuccessful() && isCasperVote()) { + track.addBalance(tx.getSender(), summary.getFee()); + logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); + } else { + // Transfer fees to miner + track.addBalance(coinbase, summary.getFee()); + touchedAccounts.add(coinbase); + logger.info("Pay fees to miner: [{}], feesEarned: [{}]", Hex.toHexString(coinbase), summary.getFee()); + } + if (blockchainConfig.eip161()) { for (byte[] acctAddr : touchedAccounts) { AccountState state = track.getAccountState(acctAddr); @@ -480,11 +506,15 @@ public TransactionExecutor setLocalCall(boolean localCall) { public TransactionReceipt getReceipt() { if (receipt == null) { receipt = new TransactionReceipt(); - long totalGasUsed = gasUsedInTheBlock + getGasUsed(); + long gasUsed = getGasUsed(); + if (isCasperVote() && execError == null) { // Successful Casper vote + gasUsed = 0; + } + long totalGasUsed = gasUsedInTheBlock + gasUsed; receipt.setCumulativeGas(totalGasUsed); receipt.setTransaction(tx); receipt.setLogInfoList(getVMLogs()); - receipt.setGasUsed(getGasUsed()); + receipt.setGasUsed(gasUsed); receipt.setExecutionResult(getResult().getHReturn()); receipt.setError(execError); // receipt.setPostTxState(track.getRoot()); // TODO later when RepositoryTrack.getRoot() is implemented @@ -501,7 +531,11 @@ public ProgramResult getResult() { } public long getGasUsed() { - return toBI(tx.getGasLimit()).subtract(m_endGas).longValue(); + long gasUsed = toBI(tx.getGasLimit()).subtract(m_endGas).longValue(); + if (result != null && execError == null && isCasperVote()) { + gasUsed = 0; + } + return gasUsed; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java new file mode 100644 index 0000000000..6ec8865bc4 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; + +import javafx.util.Pair; +import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Block; +import org.ethereum.core.BlockSummary; +import org.ethereum.core.BlockchainImpl; +import org.ethereum.core.Genesis; +import org.ethereum.core.ImportResult; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutionSummary; +import org.ethereum.core.TransactionExecutor; +import org.ethereum.core.TransactionReceipt; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.db.ByteArrayWrapper; +import org.ethereum.util.ByteUtil; +import org.ethereum.util.RLP; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.math.BigInteger.ONE; +import static org.ethereum.core.ImportResult.EXIST; +import static org.ethereum.core.ImportResult.IMPORTED_BEST; +import static org.ethereum.core.ImportResult.IMPORTED_NOT_BEST; +import static org.ethereum.core.ImportResult.INVALID_BLOCK; +import static org.ethereum.core.ImportResult.NO_PARENT; +import static org.ethereum.core.genesis.CasperStateInit.NULL_SENDER; +import static org.ethereum.manager.CasperValidatorService.DEFAULT_GASLIMIT; + + +@Lazy +@Component +public class CasperBlockchain extends BlockchainImpl { + + private static final Logger logger = LoggerFactory.getLogger("blockchain"); + private static final Logger stateLogger = LoggerFactory.getLogger("state"); + + private static final BigInteger PRETTY_BIG = BigInteger.valueOf(10).pow(40); + private static final BigInteger NON_REVERT_MIN_DEPOSIT = BigInteger.valueOf(10).pow(18); + + private CasperHybridConsensusStrategy strategy; + + public CasperBlockchain() { + throw new RuntimeException("Empty constructor not available"); + } + + @Autowired + public CasperBlockchain(SystemProperties config) { + super(config); + } + + private boolean switchRevertsFinalizedBlock(final Block block) { + if (block == null) return false; + Block oldHead = getBestBlock(); + Block newHead = block; + + // Assuming old head > new head and there are no finalized blocks between + while (oldHead.getNumber() > newHead.getNumber()) { + byte[] finalized = blockStore.loadMeta("finalized" + Hex.toHexString(oldHead.getHash())); + if (finalized != null) { + logger.warn("Attempt to revert failed: checkpoint {} is finalized", oldHead.getShortDescr()); + return true; + } + oldHead = getBlockByHash(oldHead.getParentHash()); + } + + // Assuming new head > old head and there could be connected in one chain + while (newHead.getNumber() > oldHead.getNumber()) { + newHead = getBlockByHash(newHead.getParentHash()); + if (newHead == null) { + logger.warn("Proposed head block {} is not connected with canonical chain", block.getShortDescr()); + return false; + } + } + + // As we are currently on one height we could be on one chain before any finalized block + while(!Arrays.areEqual(oldHead.getHash(), newHead.getHash())) { + byte[] finalized = blockStore.loadMeta("finalized" + Hex.toHexString(oldHead.getHash())); + if (finalized != null) { + logger.warn("Attempt to revert failed: checkpoint {} is finalized", oldHead.getShortDescr()); + return true; + } + oldHead = getBlockByHash(oldHead.getParentHash()); + newHead = getBlockByHash(newHead.getParentHash()); + if (newHead == null) { + logger.warn("Proposed head block {} is not connected with canonical chain", block.getShortDescr()); + return false; + } + } + return false; + } + + private BigInteger getScore(final Block block) { + Object[] res = strategy.constCallCasper(block, "get_last_justified_epoch"); + return ((BigInteger) res[0]).multiply(PRETTY_BIG).add(getPoWDifficulty(block)); + } + + @Override + public synchronized ImportResult tryToConnect(final Block block) { + + if (logger.isDebugEnabled()) + logger.debug("Try connect block hash: {}, number: {}", + Hex.toHexString(block.getHash()).substring(0, 6), + block.getNumber()); + + if (blockExists(block)) return EXIST; // retry of well known block + + // TODO: Remove try/catch, debug only + try { + return casperConnect(block); + } catch (Exception ex) { + throw ex; + } + } + + private synchronized ImportResult casperConnect(final Block block) { + final ImportResult ret; + final BlockSummary summary; + + if (blockStore.isBlockExist(block.getParentHash())) { + recordBlock(block); + Repository repo; + + Block parentBlock = getBlockByHash(block.getParentHash()); + Block bestBlock = getBestBlock(); + repo = getRepository().getSnapshotTo(parentBlock.getStateRoot()); + + // We already handle not matched block stateRoot and + // real root due to Casper background txs + State savedState = pushState(block.getParentHash()); + this.fork = true; + try { + summary = add(repo, block); + if (summary == null) { + return INVALID_BLOCK; + } + } catch (Throwable th) { + logger.error("Unexpected error: ", th); + return INVALID_BLOCK; + } finally { + this.fork = false; + } + + if (getScore(bestBlock).compareTo(getScore(block)) >= 0 || + switchRevertsFinalizedBlock(block)) { + logger.info("Skipping block {} which is not a descendant of current head checkpoint", block.getNumber()); + // Stay on previous branch + popState(); + ret = IMPORTED_NOT_BEST; + } else { + + // Main branch become this branch + // cause we proved that total difficulty + // is greater + blockStore.reBranch(block); + + // The main repository rebranch + setRepository(repo); + + dropState(); + + finalizeCheckpoint(block); + + ret = IMPORTED_BEST; + } + + listener.onBlock(summary); + listener.trace(String.format("Block chain size: [ %d ]", this.getSize())); + + if (ret == IMPORTED_BEST) { + eventDispatchThread.invokeLater(() -> getPendingState().processBest(block, summary.getReceipts())); + } + return ret; + } else { + return NO_PARENT; + } + } + + /** + * Finalizes Casper epoch checkpoint if needed + */ + private void finalizeCheckpoint(final Block block) { + Object[] res = strategy.constCallCasper(block, "get_last_finalized_epoch"); + long finalizedEpoch = ((BigInteger) res[0]).longValue(); + Object[] res2 = strategy.constCallCasper(block, "get_current_epoch"); + long currentEpoch = ((BigInteger) res2[0]).longValue(); + if (finalizedEpoch == currentEpoch - 1) { + // Actually one hash per epoch, just the getter for array + Object[] res3 = strategy.constCallCasper(block, "get_checkpoint_hashes", finalizedEpoch); + byte[] checkpointHash = (byte[]) res3[0]; + if (!Arrays.areEqual(checkpointHash, new byte[32])) { // new byte[32] == 00-filled + Block histBlock = getBlockByHash(checkpointHash); + Object[] res4 = strategy.constCallCasper(histBlock, "get_total_curdyn_deposits"); + BigInteger curDeposits = (BigInteger) res4[0]; + Object[] res5 = strategy.constCallCasper(histBlock, "get_total_prevdyn_deposits"); + BigInteger prevDeposits = (BigInteger) res5[0]; + if (curDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0 && + prevDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0) { + blockStore.saveMeta("finalized" + Hex.toHexString(checkpointHash), RLP.encodeByte((byte) 0x01)); // True + logger.info("Finalized checkpoint {} {}", finalizedEpoch, Hex.toHexString(checkpointHash)); + } else { + logger.info("Trivially finalized checkpoint {}", finalizedEpoch); + } + } + } + } + + @Override + protected BlockSummary applyBlock(Repository track, Block block) { + + logger.debug("applyBlock: block: [{}] tx.list: [{}]", block.getNumber(), block.getTransactionsList().size()); + + BlockchainConfig blockchainConfig = config.getBlockchainConfig().getConfigForBlock(block.getNumber()); + blockchainConfig.hardForkTransfers(block, track); + initCasper(track, block); + + long saveTime = System.nanoTime(); + int i = 1; + long totalGasUsed = 0; + List receipts = new ArrayList<>(); + List summaries = new ArrayList<>(); + + List txs = new ArrayList<>(block.getTransactionsList()); + + // Initialize the next epoch in the Casper contract + int epochLength = config.getCasperEpochLength(); + if(block.getNumber() % epochLength == 0 && block.getNumber() != 0) { + long startingEpoch = block.getNumber() / epochLength; + byte[] data = strategy.getCasper().getByName("initialize_epoch").encode(startingEpoch); + Transaction tx = new Transaction( + ByteUtil.bigIntegerToBytes(track.getNonce(NULL_SENDER.getAddress())), + new byte[0], + ByteUtil.longToBytes(DEFAULT_GASLIMIT), + strategy.getCasperAddress(), + new byte[0], + data + ); + tx.sign(NULL_SENDER); + txs.add(0, tx); + } + + for (Transaction tx : txs) { + stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); + + Repository txTrack = track.startTracking(); + TransactionExecutor executor = new TransactionExecutor(tx, block.getCoinbase(), + txTrack, blockStore, getProgramInvokeFactory(), block, listener, totalGasUsed) + .withCommonConfig(commonConfig); + + executor.init(); + executor.execute(); + executor.go(); + TransactionExecutionSummary summary = executor.finalization(); + + totalGasUsed += executor.getGasUsed(); + + txTrack.commit(); + final TransactionReceipt receipt = executor.getReceipt(); + + if (blockchainConfig.eip658()) { + receipt.setTxStatus(receipt.isSuccessful()); + } else { + receipt.setPostTxState(track.getRoot()); + } + + stateLogger.info("block: [{}] executed tx: [{}] \n state: [{}]", block.getNumber(), i, + Hex.toHexString(track.getRoot())); + + stateLogger.info("[{}] ", receipt.toString()); + + if (stateLogger.isInfoEnabled()) + stateLogger.info("tx[{}].receipt: [{}] ", i, Hex.toHexString(receipt.getEncoded())); + + // TODO +// if (block.getNumber() >= config.traceStartBlock()) +// repository.dumpState(block, totalGasUsed, i++, tx.getHash()); + + receipts.add(receipt); + if (summary != null) { + summaries.add(summary); + } + } + + Map rewards = addReward(track, block, summaries); + + stateLogger.info("applied reward for block: [{}] \n state: [{}]", + block.getNumber(), + Hex.toHexString(track.getRoot())); + + + // TODO +// if (block.getNumber() >= config.traceStartBlock()) +// repository.dumpState(block, totalGasUsed, 0, null); + + long totalTime = System.nanoTime() - saveTime; + adminInfo.addBlockExecTime(totalTime); + logger.debug("block: num: [{}] hash: [{}], executed after: [{}]nano", block.getNumber(), block.getShortHash(), totalTime); + + return new BlockSummary(block, rewards, receipts, summaries); + } + + private void initCasper(Repository track, Block block) { + // All changes should be applied only just after genesis, before 1st block state changes + if (block.getNumber() != 1) + return; + + + Pair> res = ((CasperStateInit) strategy.getInitState()).makeInitTxes(); + List txs = res.getValue(); + Genesis genesis = strategy.getInitState().getInitGenesis(); + byte[] casperAddress = config.getCasperAddress(); + + txs.forEach((tx) -> { + // We need money! + track.addBalance(NULL_SENDER.getAddress(), BigInteger.valueOf(15).pow(18)); + + Repository txTrack = track.startTracking(); + TransactionExecutor executor = new TransactionExecutor(tx, genesis.getCoinbase(), + txTrack, blockStore, getProgramInvokeFactory(), genesis, listener, 0) + .withCommonConfig(commonConfig); + + executor.init(); + executor.execute(); + executor.go(); + executor.finalization(); + + byte[] contractAddress = executor.getReceipt().getTransaction().getContractAddress(); + if (contractAddress != null) { + logger.info("Casper init: contract deployed at {}, tx: [{}]", Hex.toHexString(contractAddress), tx); + } + if (!executor.getReceipt().isSuccessful()) { + logger.error("Casper init failed on tx [{}], receipt [{}], breaking", tx, executor.getReceipt()); + throw new RuntimeException("Casper initialization transactions on 1st block failed"); + } + + txTrack.commit(); + BigInteger restBalance = track.getBalance(NULL_SENDER.getAddress()); + track.addBalance(NULL_SENDER.getAddress(), restBalance.negate()); + track.addBalance(casperAddress, track.getBalance(casperAddress).negate()); + track.addBalance(casperAddress, BigInteger.valueOf(10).pow(25)); + }); + } + + /** + * This mechanism enforces a homeostasis in terms of the time between blocks; + * a smaller period between the last two blocks results in an increase in the + * difficulty level and thus additional computation required, lengthening the + * likely next period. Conversely, if the period is too large, the difficulty, + * and expected time to the next block, is reduced. + */ + @Override + protected boolean isValid(Repository repo, Block block) { + + boolean isValid = true; + + if (!block.isGenesis()) { + isValid = isValid(block.getHeader()); + + // Sanity checks + String trieHash = Hex.toHexString(block.getTxTrieRoot()); + String trieListHash = Hex.toHexString(calcTxTrie(block.getTransactionsList())); + + + if (!trieHash.equals(trieListHash)) { + logger.warn("Block's given Trie Hash doesn't match: {} != {}", trieHash, trieListHash); + return false; + } + +// if (!validateUncles(block)) return false; + + List txs = block.getTransactionsList(); + if (!txs.isEmpty()) { +// Repository parentRepo = repository; +// if (!Arrays.equals(bestBlock.getHash(), block.getParentHash())) { +// parentRepo = repository.getSnapshotTo(getBlockByHash(block.getParentHash()).getStateRoot()); +// } + + Map curNonce = new HashMap<>(); + + for (Transaction tx : txs) { + byte[] txSender = tx.getSender(); + ByteArrayWrapper key = new ByteArrayWrapper(txSender); + BigInteger expectedNonce = curNonce.get(key); + if (expectedNonce == null) { + expectedNonce = repo.getNonce(txSender); + } + // We shouldn't track nonce for NULL_SENDER + if (!key.equals(new ByteArrayWrapper(Transaction.NULL_SENDER))) { + curNonce.put(key, expectedNonce.add(ONE)); + } else { + curNonce.put(key, expectedNonce); + } + BigInteger txNonce = new BigInteger(1, tx.getNonce()); + if (!expectedNonce.equals(txNonce)) { + logger.warn("Invalid transaction: Tx nonce {} != expected nonce {} (parent nonce: {}): {}", + txNonce, expectedNonce, repo.getNonce(txSender), tx); + return false; + } + } + } + } + + return isValid; + } + + private BigInteger getPoWDifficulty(final Block block) { + + return blockStore.getTotalDifficultyForHash(block.getHash()); + } + + public void setStrategy(CasperHybridConsensusStrategy strategy) { + this.strategy = strategy; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java new file mode 100644 index 0000000000..d91b4829c5 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.consensus; + +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; +import org.ethereum.core.CallTransaction; +import org.ethereum.core.Genesis; +import org.ethereum.core.Transaction; +import org.ethereum.core.casper.CasperBlockchain; +import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.core.genesis.StateInit; +import org.ethereum.facade.Ethereum; +import org.ethereum.facade.EthereumImpl; +import org.ethereum.manager.CasperValidatorService; +import org.ethereum.validator.BlockHashRule; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.DependentBlockHeaderRule; +import org.ethereum.validator.DifficultyRule; +import org.ethereum.validator.ExtraDataRule; +import org.ethereum.validator.GasLimitRule; +import org.ethereum.validator.GasValueRule; +import org.ethereum.validator.ParentBlockHeaderValidator; +import org.ethereum.validator.ParentGasLimitRule; +import org.ethereum.validator.ParentNumberRule; +import org.ethereum.validator.ProofOfWorkRule; +import org.ethereum.vm.program.ProgramResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; +import org.springframework.context.ApplicationContext; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; + +public class CasperHybridConsensusStrategy implements ConsensusStrategy { + + private static final Logger logger = LoggerFactory.getLogger("general"); + + private SystemProperties systemProperties; + + private BlockHeaderValidator blockHeaderValidator; + + private ParentBlockHeaderValidator parentBlockHeaderValidator; + + private CasperBlockchain blockchain; + + private CasperValidatorService casperValidatorService; + + private Ethereum ethereum; + + private ApplicationContext ctx; + + private StateInit stateInit; + + private CallTransaction.Contract casper = null; + + private String casperAddress; // FIXME: why should we have casper addresses in two places?. It's already in SystemProperties + + public CasperHybridConsensusStrategy(SystemProperties systemProperties, ApplicationContext ctx) { + this.systemProperties = systemProperties; + + List rules = new ArrayList<>(asList( + new GasValueRule(), + new ExtraDataRule(systemProperties), + new ProofOfWorkRule(), + new GasLimitRule(systemProperties), + new BlockHashRule(systemProperties) + )); + blockHeaderValidator = new BlockHeaderValidator(rules); + + + List parentRules = new ArrayList<>(asList( + new ParentNumberRule(), + new DifficultyRule(systemProperties), + new ParentGasLimitRule(systemProperties) + )); + parentBlockHeaderValidator = new ParentBlockHeaderValidator(parentRules); + + blockchain = ctx.getBean(CasperBlockchain.class); + blockchain.setStrategy(this); + ethereum = ctx.getBean(Ethereum.class); + this.ctx = ctx; + } + + @Override + public BlockHeaderValidator getHeaderValidator() { + return blockHeaderValidator; + } + + @Override + public ParentBlockHeaderValidator getParentHeaderValidator() { + return parentBlockHeaderValidator; + } + + @Override + public Blockchain getBlockchain() { + return blockchain; + } + + @Override + public void init() { + getCasperValidatorService(); + } + + @Override + public StateInit initState(Genesis genesis) { + if (stateInit != null) { + throw new RuntimeException("State is already initialized"); + } else { + this.stateInit = new CasperStateInit(genesis, blockchain.getRepository(), blockchain, ctx, systemProperties); + } + return stateInit; + } + + @Override + public StateInit getInitState() { + if (stateInit == null) { + throw new RuntimeException("State is not initialized"); + } + return stateInit; + } + + public CallTransaction.Contract getCasper() { + initCasper(); + return casper; + } + + private void initCasper() { + if (casper == null) { + casperAddress = Hex.toHexString(systemProperties.getCasperAddress()); + String casperAbi = systemProperties.getCasperAbi(); + casper = new CallTransaction.Contract(casperAbi); + } + } + + public Object[] constCallCasper(String func, Object... funcArgs) { + initCasper(); + ProgramResult r = ethereum.callConstantFunction(casperAddress, + casper.getByName(func), funcArgs); + return casper.getByName(func).decodeResult(r.getHReturn()); + } + + + public Object[] constCallCasper(Block block, String func, Object... funcArgs) { + initCasper(); + Transaction tx = CallTransaction.createCallTransaction(0, 0, 100000000000000L, + casperAddress, 0, casper.getByName(func), funcArgs); + ProgramResult r = ethereum.callConstantFunction(block, casperAddress, + casper.getByName(func), funcArgs); + return casper.getByName(func).decodeResult(r.getHReturn()); + } + + public byte[] getCasperAddress() { + return Hex.decode(casperAddress); + } + + public CasperValidatorService getCasperValidatorService() { + if (casperValidatorService == null && + systemProperties.getCasperValidatorEnabled() != null && systemProperties.getCasperValidatorEnabled()) { + logger.info("Casper validator is enabled, starting..."); + this.casperValidatorService = ctx.getBean(CasperValidatorService.class); + } + + return casperValidatorService; + } + + // FIXME: Magic + public void setBlockchain(CasperBlockchain blockchain) { + this.blockchain = blockchain; + blockchain.setParentHeaderValidator(parentBlockHeaderValidator); + blockchain.setStrategy(this); + } + + public void setEthereum(Ethereum ethereum) { + this.ethereum = ethereum; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java new file mode 100644 index 0000000000..ae8af02a8f --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.consensus; + +import org.ethereum.core.Blockchain; +import org.ethereum.core.Genesis; +import org.ethereum.core.genesis.StateInit; +import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.ParentBlockHeaderValidator; + +public interface ConsensusStrategy { + BlockHeaderValidator getHeaderValidator(); + + ParentBlockHeaderValidator getParentHeaderValidator(); + + Blockchain getBlockchain(); + + void init(); + + /** + * Creates state initializer + */ + StateInit initState(Genesis genesis); + + /** + * @return state initializer after state is initialized + */ + StateInit getInitState(); +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java new file mode 100644 index 0000000000..84ad167692 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.consensus; + +import org.ethereum.config.SystemProperties; +import org.ethereum.core.BlockchainImpl; +import org.ethereum.core.Genesis; +import org.ethereum.core.genesis.CommonStateInit; +import org.ethereum.core.genesis.StateInit; +import org.ethereum.validator.BlockHashRule; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.DependentBlockHeaderRule; +import org.ethereum.validator.DifficultyRule; +import org.ethereum.validator.ExtraDataRule; +import org.ethereum.validator.GasLimitRule; +import org.ethereum.validator.GasValueRule; +import org.ethereum.validator.ParentBlockHeaderValidator; +import org.ethereum.validator.ParentGasLimitRule; +import org.ethereum.validator.ParentNumberRule; +import org.ethereum.validator.ProofOfWorkRule; +import org.springframework.context.ApplicationContext; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; + +public class PoWConsensusStrategy implements ConsensusStrategy { + private SystemProperties systemProperties; + + private BlockHeaderValidator blockHeaderValidator; + private ParentBlockHeaderValidator parentBlockHeaderValidator; + private BlockchainImpl blockchain; + private StateInit stateInit; + + public PoWConsensusStrategy(SystemProperties systemProperties, ApplicationContext ctx) { + this(systemProperties); + blockchain = ctx.getBean(BlockchainImpl.class); + } + + public PoWConsensusStrategy(SystemProperties systemProperties) { + this.systemProperties = systemProperties; + + List rules = new ArrayList<>(asList( + new GasValueRule(), + new ExtraDataRule(systemProperties), + new ProofOfWorkRule(), + new GasLimitRule(systemProperties), + new BlockHashRule(systemProperties) + )); + blockHeaderValidator = new BlockHeaderValidator(rules); + + + List parentRules = new ArrayList<>(asList( + new ParentNumberRule(), + new DifficultyRule(systemProperties), + new ParentGasLimitRule(systemProperties) + )); + parentBlockHeaderValidator = new ParentBlockHeaderValidator(parentRules); + // TODO: Add default blockchainImpl when it's not provided + } + + @Override + public BlockHeaderValidator getHeaderValidator() { + return blockHeaderValidator; + } + + @Override + public ParentBlockHeaderValidator getParentHeaderValidator() { + return parentBlockHeaderValidator; + } + + @Override + public BlockchainImpl getBlockchain() { + return blockchain; + } + + @Override + public void init() { + + } + + @Override + public StateInit initState(Genesis genesis) { + if (stateInit != null) { + throw new RuntimeException("State is already initialized"); + } else { + this.stateInit = new CommonStateInit(genesis, blockchain.getRepository(), blockchain); + } + return stateInit; + } + + @Override + public StateInit getInitState() { + if (stateInit == null) { + throw new RuntimeException("State is not initialized"); + } + return stateInit; + } + + public void setBlockchain(BlockchainImpl blockchain) { + this.blockchain = blockchain; + blockchain.setParentHeaderValidator(parentBlockHeaderValidator); + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java new file mode 100644 index 0000000000..6015e1a8d5 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.genesis; + +import javafx.util.Pair; +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Blockchain; +import org.ethereum.core.Genesis; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.crypto.ECKey; +import org.ethereum.db.BlockStore; +import org.ethereum.util.ByteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; +import org.springframework.context.ApplicationContext; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +public class CasperStateInit implements StateInit { + private static final Logger logger = LoggerFactory.getLogger("general"); + private Genesis genesis; + private Repository repository; + private Blockchain blockchain; + private SystemProperties systemProperties; + private ApplicationContext ctx; + private Genesis initGenesis; + + public final static ECKey NULL_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + + public CasperStateInit(Genesis genesis, Repository repository, Blockchain blockchain, + ApplicationContext ctx, SystemProperties systemProperties) { + this.genesis = genesis; + this.repository = repository; + this.blockchain = blockchain; + this.systemProperties = systemProperties; + this.ctx = ctx; + init(); + } + + @Override + public void initDB() { + if (blockchain.getBlockByNumber(0) != null) { + return; // Already initialized + } + logger.info("DB is empty - initializing Casper Genesis"); + Genesis.populateRepository(repository, genesis); + + BlockStore blockStore = ((org.ethereum.facade.Blockchain)blockchain).getBlockStore(); + + + // Metropolis dummy + repository.saveCode(Hex.decode("0000000000000000000000000000000000000010"), Hex.decode("6000355460205260206020f3")); + repository.saveCode(Hex.decode("0000000000000000000000000000000000000020"), Hex.decode("6000355460205260206020f3")); + repository.commit(); + genesis.setStateRoot(repository.getRoot()); + + blockStore.saveBlock(genesis, genesis.getCumulativeDifficulty(), true); + blockchain.setBestBlock(genesis); + blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); + + logger.info("Genesis block loaded"); + } + + /** + * @return key: Casper contract address + * value: Casper state initialization transactions + */ + public Pair> makeInitTxes() { + final byte[] casperAddress = new byte[20]; + + // All contracts except Casper itself + final String VIPER_RLP_DECODER_TX = "0xf9035b808506fc23ac0083045f788080b903486103305660006109ac5260006109cc527f0100000000000000000000000000000000000000000000000000000000000000600035046109ec526000610a0c5260006109005260c06109ec51101515585760f86109ec51101561006e5760bf6109ec510336141558576001610a0c52610098565b60013560f76109ec51036020035260005160f66109ec510301361415585760f66109ec5103610a0c525b61022060016064818352015b36610a0c511015156100b557610291565b7f0100000000000000000000000000000000000000000000000000000000000000610a0c5135046109ec526109cc5160206109ac51026040015260016109ac51016109ac5260806109ec51101561013b5760016109cc5161044001526001610a0c516109cc5161046001376001610a0c5101610a0c5260216109cc51016109cc52610281565b60b86109ec5110156101d15760806109ec51036109cc51610440015260806109ec51036001610a0c51016109cc51610460013760816109ec5114156101ac5760807f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350410151558575b607f6109ec5103610a0c5101610a0c5260606109ec51036109cc51016109cc52610280565b60c06109ec51101561027d576001610a0c51013560b76109ec510360200352600051610a2c526038610a2c5110157f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350402155857610a2c516109cc516104400152610a2c5160b66109ec5103610a0c51016109cc516104600137610a2c5160b66109ec5103610a0c510101610a0c526020610a2c51016109cc51016109cc5261027f565bfe5b5b5b81516001018083528114156100a4575b5050601f6109ac511115155857602060206109ac5102016109005260206109005103610a0c5261022060016064818352015b6000610a0c5112156102d45761030a565b61090051610a0c516040015101610a0c51610900516104400301526020610a0c5103610a0c5281516001018083528114156102c3575b50506109cc516109005101610420526109cc5161090051016109005161044003f35b61000461033003610004600039610004610330036000f31b2d4f"; + final String SIG_HASHER_TX = "0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f"; + final String PURITY_CHECKER_TX = "0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f"; + + List txStrs = new ArrayList<>(); + txStrs.add(VIPER_RLP_DECODER_TX); + txStrs.add(SIG_HASHER_TX); + txStrs.add(PURITY_CHECKER_TX); + BigInteger nonce = repository.getNonce(NULL_SENDER.getAddress()); + List txs = new ArrayList<>(); + final long gasPriceFund = 25_000_000_000L; + for (int i = 0; i < txStrs.size(); ++i) { + Transaction deployTx = new Transaction(ByteUtil.hexStringToBytes(txStrs.get(i))); + BigInteger value = BigInteger.ZERO; + value = value.add(ByteUtil.bytesToBigInteger(deployTx.getValue())); + value = value.add( + ByteUtil.bytesToBigInteger(deployTx.getGasPrice()) + .multiply(ByteUtil.bytesToBigInteger(deployTx.getGasLimit())) + ); + Transaction fundTx = new Transaction( + ByteUtil.bigIntegerToBytes(nonce), + ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), + ByteUtil.longToBytesNoLeadZeroes(90_000), + deployTx.getSender(), + ByteUtil.bigIntegerToBytes(value), + new byte[0], + null + ); + fundTx.sign(NULL_SENDER); + txs.add(fundTx); + txs.add(deployTx); + nonce = nonce.add(BigInteger.ONE); + } + + // Casper! + // Currently there are hardcoded init args in bin, we should add it here instead + try { + String casperBinStr = systemProperties.getCasperBin(); + // Currently inited with following params: + // EPOCH_LENGTH=50, WITHDRAWAL_DELAY=5, BASE_INTEREST_FACTOR=0.1, BASE_PENALTY_FACTOR=0.0001 + // TODO: Use only contract BIN and merge with init encode + byte[] casperBin = ByteUtil.hexStringToBytes(casperBinStr); + Transaction tx = new Transaction( + ByteUtil.bigIntegerToBytes(nonce), + ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), + ByteUtil.longToBytesNoLeadZeroes(5_000_000), + new byte[0], + ByteUtil.longToBytesNoLeadZeroes(0), + casperBin, + null); + tx.sign(NULL_SENDER); + + // set casperAddress + System.arraycopy(tx.getContractAddress(), 0, casperAddress, 0, 20); + txs.add(tx); + } catch (Exception ex) { + throw new RuntimeException("Failed to generate Casper init transactions", ex); + } + + return new Pair<>(casperAddress, txs); + } + + private void init() { + Repository repo = repository.getSnapshotTo(null); + Genesis.populateRepository(repo, genesis); + + // Metropolis dummy + repo.saveCode(Hex.decode("0000000000000000000000000000000000000010"), Hex.decode("6000355460205260206020f3")); + repo.saveCode(Hex.decode("0000000000000000000000000000000000000020"), Hex.decode("6000355460205260206020f3")); + + this.initGenesis = genesis; + this.initGenesis.setStateRoot(repo.getRoot()); + + Pair> res = makeInitTxes(); + systemProperties.setCasperAddress(res.getKey()); + } + + @Override + public Genesis getInitGenesis() { + return initGenesis; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java new file mode 100644 index 0000000000..d39168b8ad --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.genesis; + +import org.ethereum.core.Blockchain; +import org.ethereum.core.Genesis; +import org.ethereum.core.Repository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CommonStateInit implements StateInit { + private static final Logger logger = LoggerFactory.getLogger("general"); + private Genesis genesis; + private Repository repository; + private Blockchain blockchain; + private Genesis initGenesis; + + public CommonStateInit(Genesis genesis, Repository repository, Blockchain blockchain) { + this.genesis = genesis; + this.repository = repository; + this.blockchain = blockchain; + init(); + } + + @Override + public void initDB() { + if (blockchain.getBlockByNumber(0) != null) { + return; // Already initialized + } + logger.info("DB is empty - adding Genesis"); + Genesis.populateRepository(repository, genesis); + repository.commit(); + ((org.ethereum.facade.Blockchain)blockchain).getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true); + blockchain.setBestBlock(genesis); + blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); + logger.info("Genesis block loaded"); + } + + + private void init() { + this.initGenesis = genesis; + } + + @Override + public Genesis getInitGenesis() { + return initGenesis; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java new file mode 100644 index 0000000000..e104d44136 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.genesis; + +import org.ethereum.core.Genesis; + +/** + * Creates initial state of blockchain + */ +public interface StateInit { + + /** + * Initializes DB with genesis etc. + */ + void initDB(); + + /** + * @return actual genesis + */ + Genesis getInitGenesis(); +} diff --git a/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java b/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java index e566cb0def..52fe138d07 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java @@ -64,6 +64,11 @@ public interface BlockStore { void reBranch(Block forkBlock); + // FIXME: Do something universal instead like BlockInfoV2 + void saveMeta(String name, byte[] value); + + byte[] loadMeta(String name); + void load(); void close(); diff --git a/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java b/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java index 8f0ac33c07..675e5341da 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java @@ -109,6 +109,16 @@ public void reBranch(Block forkBlock) { } + @Override + public void saveMeta(String name, byte[] value) { + + } + + @Override + public byte[] loadMeta(String name) { + return new byte[0]; + } + @Override public BigInteger getTotalDifficultyForHash(byte[] hash) { return null; diff --git a/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java b/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java index a42a71a4c5..a0c395da87 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java @@ -37,6 +37,7 @@ import java.util.List; import static java.math.BigInteger.ZERO; +import static org.ethereum.crypto.HashUtil.sha3; import static org.ethereum.crypto.HashUtil.shortHash; import static org.spongycastle.util.Arrays.areEqual; @@ -508,6 +509,14 @@ private static BlockInfo getBlockInfoForHash(List blocks, byte[] hash return null; } + public void saveMeta(String name, byte[] value) { + blocksDS.put(RLP.encode(sha3(name.getBytes())), value); + } + + public byte[] loadMeta(String name) { + return blocksDS.get(RLP.encode(sha3(name.getBytes()))); + } + @Override public synchronized void load() { } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java index 20e0f6d03a..645e0a7697 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java @@ -20,6 +20,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.AccountState; import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.*; @@ -426,4 +427,8 @@ public void loadAccount(byte[] addr, HashMap cac throw new RuntimeException("Not supported"); } + @Override + public void setBlockchain(Blockchain blockchain) { + // Not used in current implementation + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java index 86f05e638d..91d40e8016 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java @@ -19,10 +19,10 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; import org.ethereum.core.BlockchainImpl; import org.ethereum.core.Repository; import org.ethereum.vm.DataWord; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.Nullable; @@ -40,7 +40,6 @@ @Component public class RepositoryWrapper implements Repository { - @Autowired BlockchainImpl blockchain; public RepositoryWrapper() { @@ -215,4 +214,8 @@ public Set getStorageKeys(byte[] addr) { public Map getStorage(byte[] addr, @Nullable Collection keys) { return blockchain.getRepository().getStorage(addr, keys); } + + public void setBlockchain(Blockchain blockchain) { + this.blockchain = (BlockchainImpl) blockchain; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java b/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java index bed44abcfb..69015ba125 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java @@ -22,6 +22,7 @@ import org.ethereum.listener.EthereumListener; import org.ethereum.manager.AdminInfo; import org.ethereum.manager.BlockLoader; +import org.ethereum.manager.WorldManager; import org.ethereum.mine.BlockMiner; import org.ethereum.net.client.PeerClient; import org.ethereum.net.rlpx.Node; @@ -32,7 +33,9 @@ import java.math.BigInteger; import java.net.InetAddress; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; +import java.util.function.Consumer; /** * @author Roman Mandeleil @@ -92,8 +95,28 @@ Transaction createTransaction(BigInteger nonce, * @param transaction submit transaction to the net, return option to wait for net * return this transaction as approved */ + @Deprecated Future submitTransaction(Transaction transaction); + /** + * Submit transaction to the net, return option to wait for net + * @param transaction + * @return future of waiting for net + */ + CompletableFuture sendTransaction(Transaction transaction); + + /** + * Submit transaction to the net, return option to wait for net + * @param tx Transaction + * @param successConsumer Fires when tx is sent to the net + * @param errorConsumer Fires when tx is not sent to the net due to error + * @param simErrorConsumer Runs tx on pending state one time and fires error if it fails, + * so transaction execution is simulated on the current state. + * Also though one tx broadcast is guaranteed no matter whether it's correct or not, + * tx is not broadcasted to more peers if it's execution on pending state failed. + */ + void sendTransaction(Transaction tx, Consumer successConsumer, Consumer errorConsumer, + Consumer simErrorConsumer); /** * Executes the transaction based on the specified block but doesn't change the blockchain state @@ -146,6 +169,18 @@ ProgramResult callConstantFunction(String receiveAddress, CallTransaction.Functi ProgramResult callConstantFunction(String receiveAddress, ECKey senderPrivateKey, CallTransaction.Function function, Object... funcArgs); + /** + * Call a contract function locally on the state defined by input block + * without sending transaction to the network and without changing contract storage. + * @param block block replicates state for transaction execution, so it should be in local blockchain + * @param receiveAddress hex encoded contract address + * @param function contract function + * @param funcArgs function arguments + * @return function result. The return value can be fetched via {@link ProgramResult#getHReturn()} + * and decoded with {@link org.ethereum.core.CallTransaction.Function#decodeResult(byte[])}. + */ ProgramResult callConstantFunction(Block block, String receiveAddress, + CallTransaction.Function function, Object... funcArgs); + /** * Returns the Repository instance which always refers to the latest (best block) state * It is always better using {@link #getLastRepositorySnapshot()} to work on immutable @@ -217,4 +252,6 @@ ProgramResult callConstantFunction(String receiveAddress, ECKey senderPrivateKey Integer getChainIdForNextBlock(); void exitOn(long number); + + void setWorldManager(WorldManager worldManager); } diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index ad9191eb98..9d81d8af4a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -17,7 +17,6 @@ */ package org.ethereum.facade; -import org.apache.commons.lang3.ArrayUtils; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; @@ -56,8 +55,10 @@ import java.math.BigInteger; import java.net.InetAddress; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.function.Consumer; /** * @author Roman Mandeleil @@ -69,7 +70,6 @@ public class EthereumImpl implements Ethereum, SmartLifecycle { private static final Logger logger = LoggerFactory.getLogger("facade"); private static final Logger gLogger = LoggerFactory.getLogger("general"); - @Autowired WorldManager worldManager; @Autowired @@ -220,6 +220,37 @@ protected Transaction adapt(List adapteeResult) throws ExecutionExc }; } + @Override + public CompletableFuture sendTransaction(Transaction transaction) { + CompletableFuture future = new CompletableFuture<>(); + final TransactionTask transactionTask = new TransactionTask(transaction, channelManager, future); + + TransactionExecutor.instance.submitTransaction(transactionTask); + + pendingState.addPendingTransaction(transaction); + + return future; + } + + @Override + public void sendTransaction(Transaction tx, Consumer successConsumer, Consumer errorConsumer, + Consumer simErrorConsumer) { + CompletableFuture future = new CompletableFuture<>(); + final TransactionTask transactionTask = new TransactionTask(tx, channelManager, future); + + TransactionExecutor.instance.submitTransaction(transactionTask); + + pendingState.addPendingTransaction(tx, simErrorConsumer); + + future.whenComplete((transaction, throwable) -> { + if (throwable != null) { + errorConsumer.accept(throwable); + } else { + successConsumer.accept(transaction); + } + }); + } + @Override public TransactionReceipt callConstant(Transaction tx, Block block) { if (tx.getSignature() == null) { @@ -302,6 +333,15 @@ public ProgramResult callConstantFunction(String receiveAddress, return callConstantFunction(receiveAddress, ECKey.fromPrivate(new byte[32]), function, funcArgs); } + public ProgramResult callConstantFunction(Block block, String receiveAddress, + CallTransaction.Function function, Object... funcArgs) { + Transaction tx = CallTransaction.createCallTransaction(0, 0, 100000000000000L, + receiveAddress, 0, function, funcArgs); + tx.sign(ECKey.fromPrivate(new byte[32])); + + return callConstantImpl(tx, block).getResult(); + } + @Override public ProgramResult callConstantFunction(String receiveAddress, ECKey senderPrivateKey, CallTransaction.Function function, Object... funcArgs) { @@ -390,6 +430,18 @@ public void initSyncing() { worldManager.initSyncing(); } + @Override + public void setWorldManager(WorldManager worldManager) { + this.worldManager = worldManager; + } + + public void setCommonConfig(CommonConfig commonConfig) { + this.commonConfig = commonConfig; + } + + public void setProgramInvokeFactory(ProgramInvokeFactory programInvokeFactory) { + this.programInvokeFactory = programInvokeFactory; + } /** * For testing purposes and 'hackers' diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java index 555c795f21..240f403d07 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java @@ -20,6 +20,8 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.db.BlockStore; import org.ethereum.db.DbFlushManager; import org.ethereum.util.*; import org.ethereum.validator.BlockHeaderValidator; @@ -42,24 +44,31 @@ public class BlockLoader { private static final Logger logger = LoggerFactory.getLogger("blockqueue"); - @Autowired private BlockHeaderValidator headerValidator; @Autowired SystemProperties config; - @Autowired - private BlockchainImpl blockchain; + private Blockchain blockchain; + + private BlockStore blockStore; @Autowired DbFlushManager dbFlushManager; + @Autowired + public BlockLoader(ConsensusStrategy consensusStrategy) { + this.blockchain = consensusStrategy.getBlockchain(); + this.blockStore = ((org.ethereum.facade.Blockchain) blockchain).getBlockStore(); + this.headerValidator = consensusStrategy.getHeaderValidator(); + } + Scanner scanner = null; DateFormat df = new SimpleDateFormat("HH:mm:ss.SSSS"); private void blockWork(Block block) { - if (block.getNumber() >= blockchain.getBlockStore().getBestBlock().getNumber() || blockchain.getBlockStore().getBlockByHash(block.getHash()) == null) { + if (block.getNumber() >= blockStore.getBestBlock().getNumber() || blockStore.getBlockByHash(block.getHash()) == null) { if (block.getNumber() > 0 && !isValid(block.getHeader())) { throw new RuntimeException(); @@ -86,7 +95,7 @@ private void blockWork(Block block) { public void loadBlocks() { exec1 = new ExecutorPipeline(8, 1000, true, (Function) b -> { - if (b.getNumber() >= blockchain.getBlockStore().getBestBlock().getNumber()) { + if (b.getNumber() >= blockStore.getBestBlock().getNumber()) { for (Transaction tx : b.getTransactionsList()) { tx.getSender(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java new file mode 100644 index 0000000000..96a0d454b7 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java @@ -0,0 +1,558 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.manager; + +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Block; +import org.ethereum.core.BlockSummary; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.crypto.ECKey; +import org.ethereum.db.ByteArrayWrapper; +import org.ethereum.facade.Ethereum; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.sync.SyncManager; +import org.ethereum.util.ByteUtil; +import org.ethereum.util.RLP; +import org.ethereum.util.blockchain.EtherUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import static org.ethereum.crypto.HashUtil.sha3; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.LOGGED_OUT; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.UNINITIATED; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.VOTING; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_LOGIN; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_LOGOUT; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_VALCODE; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWABLE; +import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWN; + +@Component +@Lazy +public class CasperValidatorService { + private static final Logger logger = LoggerFactory.getLogger("casper.validator"); + + @Autowired + private SyncManager syncManager; + + @Autowired + private CasperHybridConsensusStrategy strategy; + + private Repository repository; + + private SystemProperties config; + + private Ethereum ethereum; + + private byte[] valContractAddress = null; + + private ECKey coinbase; + + private static final int LOGOUT_COOLDOWN = 60 * 1000; // In millis + + public static final long DEFAULT_GASLIMIT = 3_141_592; // Just copied it, don't ask! + + private Map votes = new HashMap<>(); + + private BigInteger depositSize; + + private long latestTargetEpoch = -1; + private long latestSourceEpoch = -1; + + private long lastLogoutBroadcast = -1; + + + private byte[] validationContractCode(byte[] address) { + // FIXME: It's better to have some contract here + // Originally LLL: + // ['seq', + // ['return', [0], + // ['lll', + // ['seq', + // ['calldatacopy', 0, 0, 128], + // ['call', 3000, 1, 0, 0, 128, 0, 32], + // ['mstore', 0, ['eq', ['mload', 0], ]], + // ['return', 0, 32] + // ], + // [0]] + // ] + // ] + String part1 = "61003d5660806000600037602060006080600060006001610bb8f15073"; + String part2 = "6000511460005260206000f35b61000461003d0361000460003961000461003d036000f3"; + return Hex.decode(part1 + Hex.toHexString(address) + part2); + } + + private byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { + byte[] sigHash = sha3(RLP.encodeList(validatorIndex, targetHash, targetEpoch, sourceEpoch)); + ECKey.ECDSASignature signature = sender.sign(sigHash); + return RLP.encodeList(validatorIndex, targetHash, targetEpoch, sourceEpoch, signature.v, signature.r, signature.s); + } + + private byte[] makeLogout(long validatorIndex, long epoch, ECKey sender) { + byte[] sigHash = sha3(RLP.encodeList(validatorIndex, epoch)); + ECKey.ECDSASignature signature = sender.sign(sigHash); + return RLP.encodeList(validatorIndex, epoch, signature.v, signature.r, signature.s); + } + + public enum ValidatorState { + UNINITIATED(1), // Check if logged in, and if not deploy a valcode contract + WAITING_FOR_VALCODE(2), // Wait for valcode contract to be included, then submit deposit + WAITING_FOR_LOGIN(3), // Wait for validator to login, then change state to `voting` + VOTING(4), // Vote on each new epoch + WAITING_FOR_LOGOUT(5), // + WAITING_FOR_WITHDRAWABLE(6), + WAITING_FOR_WITHDRAWN(7), + LOGGED_OUT(8); + + int i; + ValidatorState(int i) { + this.i = i; + } + + @Override + public String toString() { + return this.name(); + } + } + + private ValidatorState state = UNINITIATED; + + private Map> handlers = new HashMap<>(); + + @Autowired + public CasperValidatorService(Ethereum ethereum, SystemProperties config) { + this.ethereum = ethereum; + this.repository = (org.ethereum.core.Repository) ethereum.getRepository(); + this.config = config; + this.coinbase = ECKey.fromPrivate(config.getCasperValidatorPrivateKey()); + this.depositSize = EtherUtil.convert(config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); + + handlers.put(UNINITIATED, this::checkLoggedIn); + handlers.put(WAITING_FOR_VALCODE, this::checkValcode); + handlers.put(WAITING_FOR_LOGIN, this::checkLoggedIn); + handlers.put(VOTING, this::vote); + handlers.put(WAITING_FOR_LOGOUT, this::voteThenLogout); + handlers.put(WAITING_FOR_WITHDRAWABLE, this::checkWithdrawable); + handlers.put(WAITING_FOR_WITHDRAWN, this::checkWithdrawn); + handlers.put(LOGGED_OUT, this::checkLoggedIn); + // FIXME: Actually we should listen only to HEAD changes + ethereum.addListener(new EthereumListenerAdapter() { + @Override + public void onBlock(BlockSummary blockSummary) { + newBlockConsumer().accept(blockSummary.getBlock()); + } + }); + } + + private Consumer newBlockConsumer() { + return block -> { + if(!syncManager.isSyncDone()) return; + logCasperInfo(); + + handlers.get(state).accept(block); + }; + } + + /** + * Check if logged in, and if not deploy a valcode contract + */ + private void checkLoggedIn(Object o) { + Long validatorIndex = getValidatorIndex(); + // (1) Check if the validator has ever deposited funds + if (validatorIndex == 0 && depositSize.compareTo(BigInteger.ZERO) > 0) { + // The validator hasn't deposited funds but deposit flag is set, so deposit! + broadcastValcodeTx(); + setState(WAITING_FOR_VALCODE); + return; + } else if (validatorIndex == 0) { + // The validator hasn't deposited funds and we have no intention to, so return! + return; + } + initValContractAddress(); + this.depositSize = BigInteger.ZERO; // FIXME: Is it correct place for it? + + // (2) Check if the validator is logged in + long currentEpoch = getCurrentEpoch(); + if (!isLoggedIn(currentEpoch, validatorIndex)) { + // The validator isn't logged in, so return! + return; + } + if (config.getCasperValidatorShouldLogout()) { + setState(WAITING_FOR_LOGOUT); + } else{ + setState(VOTING); + } + } + + private void broadcastValcodeTx() { + Transaction tx = makeTx(null, null, validationContractCode(coinbase.getAddress()), null, null, null, null); + + ethereum.sendTransaction(tx, + transaction -> { + logger.info("Validation code contract creation tx sent, txHash: {}", ByteUtil.toHexString(tx.getHash())); + valContractAddress = transaction.getContractAddress(); // FIXME: it's not true until we didn't get tx exec in our state + }, + throwable -> logger.error("Validation code contract creation tx was not sent", throwable), + throwable -> logger.warn("Simulation of validation contract tx execution failed", throwable) + ); + } + + private Transaction makeTx(byte[] receiveAddress, BigInteger value, byte[] data, byte[] gasPrice, byte[] gasLimit, + BigInteger nonce, Boolean signed) { + if (nonce == null) { + nonce = repository.getNonce(coinbase.getAddress()); + } + if (gasPrice == null) { + gasPrice = ByteUtil.bigIntegerToBytes(BigInteger.valueOf(110).multiply(BigInteger.valueOf(10).pow(9))); + } + if (gasLimit == null) { + gasLimit = ByteUtil.longToBytes(DEFAULT_GASLIMIT); + } + if (value == null) { + value = BigInteger.ZERO; + } + if (data == null) { + data = new byte[0]; + } + if (signed == null) { + signed = Boolean.TRUE; + } + + Transaction tx = new Transaction( + ByteUtil.bigIntegerToBytes(nonce), + gasPrice, + gasLimit, + receiveAddress, + ByteUtil.bigIntegerToBytes(value), + data); + + if (signed) tx.sign(coinbase); + + return tx; + } + + + + private long getValidatorIndex() { + return constCallCasperForLong("get_validator_indexes", new ByteArrayWrapper(coinbase.getAddress())); + } + + private void initValContractAddress() { // Actually it's not used after deposit + if (valContractAddress != null) + return; + byte[] address = (byte[]) strategy.constCallCasper("get_validators__addr", getValidatorIndex())[0]; + if (!Arrays.equals(address, new byte[20])) { + logger.info("Valcode contract found at {}", address); + this.valContractAddress = address; + } + } + + /** + * Wait for valcode contract to be included, then submit deposit + */ + private void checkValcode(Object o) { + if (valContractAddress == null || repository.getCode(valContractAddress) == null) { + // Valcode still not deployed! or lost + return; + } + if (repository.getBalance(coinbase.getAddress()).compareTo(depositSize) < 0) { + logger.info("Cannot login as validator: Not enough ETH! Balance: {}, Deposit: {}", + repository.getBalance(coinbase.getAddress()), depositSize); + return; + } + broadcastDepositTx(); + setState(WAITING_FOR_LOGIN); + } + + + private void broadcastDepositTx() { + // Create deposit transaction + logger.info("Broadcasting deposit tx on value: {}", depositSize); // TODO: make me more readable than wei + Transaction depositTx = makeDepositTx(valContractAddress, coinbase.getAddress(), depositSize); + this.depositSize = BigInteger.ZERO; + ethereum.sendTransaction(depositTx, + tx -> logger.info("Deposit tx successfully submitted to the net, txHash {}", ByteUtil.toHexString(tx.getHash())), + throwable -> logger.error("Failed to send deposit tx", throwable), + throwable -> logger.warn("Simulation of deposit tx execution failed", throwable) + ); + logger.info("Broadcasting deposit tx {}", depositTx); + } + + private Transaction makeDepositTx(byte[] valContractAddress, byte[] coinbaseAddress, BigInteger deposit) { + byte[] functionCallBytes = strategy.getCasper().getByName("deposit").encode( + new ByteArrayWrapper(valContractAddress), + new ByteArrayWrapper(coinbaseAddress)); + Transaction tx = makeTx(strategy.getCasperAddress(), deposit, functionCallBytes, null, ByteUtil.longToBytes(1000000), + null, true); + return tx; + + } + + private Transaction makeVoteTx(byte[] voteData) { + byte[] functionCallBytes = strategy.getCasper().getByName("vote").encode(new ByteArrayWrapper(voteData)); + Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, ByteUtil.longToBytes(1000000), + null, true); + return tx; + + } + + private Transaction makeLogoutTx(byte[] logoutData) { + byte[] functionCallBytes = strategy.getCasper().getByName("logout").encode(new ByteArrayWrapper(logoutData)); + Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, null, + null, true); + return tx; + + } + + private Transaction makeWithdrawTx(long validatorIndex) { + byte[] functionCallBytes = strategy.getCasper().getByName("withdraw").encode(validatorIndex); + Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, null, + null, true); + return tx; + } + + private boolean isLoggedIn(long targetEpoch, long validatorIndex) { + long startDynasty = constCallCasperForLong("get_validators__start_dynasty", validatorIndex); + long endDynasty = constCallCasperForLong("get_validators__end_dynasty", validatorIndex); + long currentDynasty = constCallCasperForLong("get_dynasty_in_epoch", targetEpoch); + long pastDynasty = currentDynasty - 1; + boolean inCurrentDynasty = ((startDynasty <= currentDynasty) && + (currentDynasty < endDynasty)); + boolean inPrevDynasty = ((startDynasty <= pastDynasty) && + (pastDynasty < endDynasty)); + + return inCurrentDynasty || inPrevDynasty; + } + + private void setState(ValidatorState newState) { + logger.info("Changing validator state from {} to {}", state, newState); + this.state = newState; + } + + private byte[] getEpochBlockHash(long epoch) { + if (epoch == 0) { + return Hex.decode("0000000000000000000000000000000000000000000000000000000000000000"); + } + return strategy.getBlockchain().getBlockByNumber(epoch * config.getCasperEpochLength() - 1).getHash(); + } + + private void voteThenLogout(Object o) { + long epoch = getEpoch(); + long validatorIndex = getValidatorIndex(); + // Verify that we are not already logged out + if (!isLoggedIn(epoch, validatorIndex)) { + // If we logged out, start waiting for withdrawls + logger.info("Validator logged out!"); + setState(WAITING_FOR_WITHDRAWABLE); + return; + } + vote(null); + broadcastLogoutTx(); + setState(WAITING_FOR_LOGOUT); + } + + // FIXME: WHY there are 2 methods for the same thing??? + private long getEpoch() { + return strategy.getBlockchain().getBestBlock().getNumber() / config.getCasperEpochLength(); // floor division + } + + private long getCurrentEpoch() { // FIXME: WHY there are 2 methods for the same thing??? + return constCallCasperForLong("get_current_epoch"); + } + + private boolean vote(Object o) { + long epoch = getEpoch(); + + // NO DOUBLE VOTE: Don't vote if we have already + if (votes.containsKey(epoch)) { + return false; + } + + long validatorIndex = getValidatorIndex(); + + // Make sure we are logged in + if (!isLoggedIn(epoch, validatorIndex)) { + throw new RuntimeException("Cannot vote: Validator not logged in!"); + } + + // Don't start too early + if (strategy.getBlockchain().getBestBlock().getNumber() % config.getCasperEpochLength() <= config.getCasperEpochLength() / 4) { + return false; + } + + byte[] voteData = getRecommendedVoteData(validatorIndex); + votes.put(epoch, voteData); + // FIXME: I don't like that epoch could be not the same as in data + // FIXME: also synchronize required !!! + + // Send the vote! + Transaction voteTx = makeVoteTx(voteData); + ethereum.sendTransaction(voteTx, + tx -> logger.info("Vote sent!, txHash: {}", ByteUtil.toHexString(tx.getHash())), + throwable -> logger.error("Failed to sent vote", throwable), + throwable -> logger.warn("Simulation of vote tx exec failed", throwable) + ); + logger.info("Sending vote tx: {}", voteTx); + + return true; + } + + private void broadcastLogoutTx() { + if (lastLogoutBroadcast > (System.currentTimeMillis() - LOGOUT_COOLDOWN)) { + return; + } + + this.lastLogoutBroadcast = System.currentTimeMillis(); + long epoch = getEpoch(); + + // Generate the message + byte[] logoutData = makeLogout(getValidatorIndex(), epoch, coinbase); + Transaction logoutTx = makeLogoutTx(logoutData); + logger.info("Logout Tx broadcasted: {}", logoutTx); + ethereum.sendTransaction(logoutTx, + transaction -> logger.info("Successfully sent logout tx, txHash: {}", ByteUtil.toHexString(transaction.getHash())), + throwable -> logger.error("Failed to send logout", throwable), + throwable -> logger.warn("Simulation of logout tx exec failed", throwable) + ); + } + + private void checkWithdrawable(Object o) { + long validatorIndex = getValidatorIndex(); + if (validatorIndex == 0) { + logger.info("Validator is already deleted!"); + setState(LOGGED_OUT); + return; + } + long validatorEndDynasty = constCallCasperForLong("get_validators__end_dynasty", validatorIndex); + long endEpoch = constCallCasperForLong("get_dynasty_start_epoch", validatorEndDynasty + 1); + + // Check Casper to see if we can withdraw + long curEpoch = getCurrentEpoch(); + long withdrawalDelay = constCallCasperForLong("get_withdrawal_delay"); + if (curEpoch >= (endEpoch + withdrawalDelay)) { + // Make withdraw tx & broadcast + Transaction withdrawTx = makeWithdrawTx(validatorIndex); + ethereum.sendTransaction(withdrawTx, + transaction -> logger.info("Successfully sent withdraw tx, txHash {}", ByteUtil.toHexString(transaction.getHash())), + throwable -> logger.error("Failed to send withdraw", throwable), + throwable -> logger.warn("Simulation of withdraw tx exec failed", throwable) + ); + // Set the state to waiting for withdrawn + setState(WAITING_FOR_WITHDRAWN); + } + } + + private void checkWithdrawn(Object o) { + // Check that we have been withdrawn--validator index will now be zero + if (constCallCasperForLong("get_validator_indexes", new ByteArrayWrapper(coinbase.getAddress())) == 0) { + setState(LOGGED_OUT); + } + } + + private void logCasperInfo() { + long curEpoch = getCurrentEpoch(); + long expectedSourceEpoch = constCallCasperForLong("get_expected_source_epoch"); + BigInteger curDeposits = (BigInteger) strategy.constCallCasper("get_total_curdyn_deposits")[0]; + BigInteger prevDeposits = (BigInteger) strategy.constCallCasper("get_total_prevdyn_deposits")[0]; + BigDecimal curVotes = (BigDecimal) strategy.constCallCasper("get_votes__cur_dyn_votes", curEpoch, expectedSourceEpoch)[0]; + BigDecimal prevVotes = (BigDecimal) strategy.constCallCasper("get_votes__prev_dyn_votes", curEpoch, expectedSourceEpoch)[0]; + BigDecimal scaleFactor = (BigDecimal) strategy.constCallCasper("get_deposit_scale_factor", curEpoch)[0]; + BigDecimal curVotesScaled = curVotes.multiply(scaleFactor); + BigDecimal prevVotesScaled = prevVotes.multiply(scaleFactor); + BigDecimal curVotesPct = BigDecimal.ZERO; + BigDecimal prevVotesPct = BigDecimal.ZERO; + if (curDeposits.compareTo(BigInteger.ZERO) > 0 ) { + curVotesPct = curVotesScaled.multiply(BigDecimal.valueOf(100)).divide(new BigDecimal(curDeposits), MathContext.DECIMAL32); + } + if (prevDeposits.compareTo(BigInteger.ZERO) > 0 ) { + prevVotesPct = prevVotesScaled.multiply(BigDecimal.valueOf(100)).divide(new BigDecimal(prevDeposits), MathContext.DECIMAL32); + } + + long lastFinalizedEpoch = constCallCasperForLong("get_last_finalized_epoch"); + long lastJustifiedEpoch = constCallCasperForLong("get_last_justified_epoch"); + BigDecimal lastNonvoterRescale = (BigDecimal) strategy.constCallCasper("get_last_nonvoter_rescale")[0]; + BigDecimal lastVoterRescale = (BigDecimal) strategy.constCallCasper("get_last_voter_rescale")[0]; + String logStr = String.format( + "CASPER STATUS: epoch %d, %.3f / %.3f ETH (%.2f %%) voted from current dynasty, " + + "%.3f / %.3f ETH (%.2f %%) voted from previous dynasty, last finalized epoch %d justified %d " + + "expected source %d. Nonvoter deposits last rescaled %.5fx, voter deposits %.5fx", + curEpoch, + curVotesScaled.divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), + new BigDecimal(curDeposits).divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), + curVotesPct, + prevVotesScaled.divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), + new BigDecimal(prevDeposits).divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), + prevVotesPct, + lastFinalizedEpoch, + lastJustifiedEpoch, + expectedSourceEpoch, + lastNonvoterRescale, + lastVoterRescale); + logger.info(logStr); + } + + private byte[] getRecommendedVoteData(long validatorIndex) { + long curEpoch = getCurrentEpoch(); + if (curEpoch == 0) { + return null; + } + // NOTE: Using `epoch_blockhash` because currently calls to `blockhash` within contracts + // in the ephemeral state are off by one, so we can't use `get_recommended_target_hash()` :( + // target_hash = self.epoch_blockhash(current_epoch) + // ANSWER: Though, I'll try + + byte[] targetHash = (byte[]) strategy.constCallCasper("get_recommended_target_hash")[0]; + long sourceEpoch = constCallCasperForLong("get_recommended_source_epoch"); + + if (targetHash == null) { + return null; + } + + // Prevent NO_SURROUND slash + if (curEpoch < latestTargetEpoch || sourceEpoch < latestSourceEpoch) { + return null; + } + this.latestTargetEpoch = curEpoch; + this.latestSourceEpoch = sourceEpoch; + + return makeVote(validatorIndex, targetHash, curEpoch, sourceEpoch, coinbase); + } + + private long constCallCasperForLong(String func, Object... funcArgs) { + Object[] res = strategy.constCallCasper(func, funcArgs); + return ((BigInteger) res[0]).longValue(); + } + + public void setStrategy(CasperHybridConsensusStrategy strategy) { + this.strategy = strategy; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index c73d08eb1c..3b00ba1b9e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -17,11 +17,14 @@ */ package org.ethereum.manager; +import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; -import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.DbFlushManager; +import org.ethereum.facade.Ethereum; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; import org.ethereum.net.client.PeerClient; @@ -94,6 +97,8 @@ public class WorldManager { @Autowired private ApplicationContext ctx; + private Ethereum ethereum; + private SystemProperties config; private EthereumListener listener; @@ -106,19 +111,26 @@ public class WorldManager { @Autowired public WorldManager(final SystemProperties config, final Repository repository, - final EthereumListener listener, final Blockchain blockchain, + final EthereumListener listener, final ConsensusStrategy consensusStrategy, final BlockStore blockStore) { this.listener = listener; - this.blockchain = blockchain; + this.blockchain = consensusStrategy.getBlockchain(); this.repository = repository; + repository.setBlockchain(blockchain); this.blockStore = blockStore; this.config = config; - loadBlockchain(); } @PostConstruct private void init() { + ConsensusStrategy strategy = ctx.getBean(CommonConfig.class).consensusStrategy(); + loadBlockchain(strategy); + ethereum = ctx.getBean(Ethereum.class); + ethereum.setWorldManager(this); + channelManager.init(ethereum); + ((PendingStateImpl) pendingState).postConstruct(); syncManager.init(channelManager, pool); + strategy.init(); } public void addListener(EthereumListener listener) { @@ -167,33 +179,22 @@ public PendingState getPendingState() { return pendingState; } - public void loadBlockchain() { + public void loadBlockchain(ConsensusStrategy strategy) { if (!config.databaseReset() || config.databaseResetBlock() != 0) blockStore.load(); + StateInit stateInit = strategy.initState(Genesis.getInstance(config)); if (blockStore.getBestBlock() == null) { - logger.info("DB is empty - adding Genesis"); - - Genesis genesis = Genesis.getInstance(config); - Genesis.populateRepository(repository, genesis); - -// repository.commitBlock(genesis.getHeader()); - repository.commit(); - - blockStore.saveBlock(Genesis.getInstance(config), Genesis.getInstance(config).getCumulativeDifficulty(), true); - - blockchain.setBestBlock(Genesis.getInstance(config)); - blockchain.setTotalDifficulty(Genesis.getInstance(config).getCumulativeDifficulty()); + stateInit.initDB(); listener.onBlock(new BlockSummary(Genesis.getInstance(config), new HashMap(), new ArrayList(), new ArrayList())); // repository.dumpState(Genesis.getInstance(config), 0, 0, null); - logger.info("Genesis block loaded"); } else { if (!config.databaseReset() && - !Arrays.equals(blockchain.getBlockByNumber(0).getHash(), config.getGenesis().getHash())) { + !Arrays.equals(blockchain.getBlockByNumber(0).getHash(), stateInit.getInitGenesis().getHash())) { // fatal exit Utils.showErrorAndExit("*** DB is incorrect, 0 block in DB doesn't match genesis"); } diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index ed36f9fc12..ecc1c8833c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -22,6 +22,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; @@ -81,7 +82,6 @@ public class BlockMiner { private int UNCLE_LIST_LIMIT; private int UNCLE_GENERATION_LIMIT; - @Autowired public BlockMiner(final SystemProperties config, final CompositeEthereumListener listener, final Blockchain blockchain, final BlockStore blockStore, final PendingState pendingState) { @@ -117,6 +117,13 @@ public void onSyncDone(SyncState state) { } } + @Autowired + public BlockMiner(final SystemProperties config, final CompositeEthereumListener listener, + final ConsensusStrategy consensusStrategy, final BlockStore blockStore, + final PendingState pendingState) { + this(config, listener, consensusStrategy.getBlockchain(), blockStore, pendingState); + } + public void setFullMining(boolean fullMining) { this.fullMining = fullMining; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java index a726c23f56..54b0d91fdb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.net.eth.EthVersion; @@ -35,7 +36,6 @@ import org.ethereum.sync.PeerState; import org.ethereum.sync.SyncStatistics; import org.ethereum.util.ByteUtil; -import org.ethereum.util.Utils; import org.ethereum.validator.BlockHeaderRule; import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; @@ -85,6 +85,8 @@ public class Eth62 extends EthHandler { @Autowired protected NodeManager nodeManager; + private ConsensusStrategy strategy; + protected EthState ethState = EthState.INIT; protected PeerState peerState = IDLE; @@ -125,6 +127,11 @@ public Eth62() { } @Autowired + public Eth62(final SystemProperties config, final ConsensusStrategy consensusStrategy, + final BlockStore blockStore, final CompositeEthereumListener ethereumListener) { + this(version, config, consensusStrategy.getBlockchain(), blockStore, ethereumListener); + this.strategy = consensusStrategy; + } public Eth62(final SystemProperties config, final Blockchain blockchain, final BlockStore blockStore, final CompositeEthereumListener ethereumListener) { this(version, config, blockchain, blockStore, ethereumListener); @@ -196,7 +203,7 @@ public synchronized void sendStatus() { } StatusMessage msg = new StatusMessage(protocolVersion, networkId, - ByteUtil.bigIntegerToBytes(totalDifficulty), bestHash, config.getGenesis().getHash()); + ByteUtil.bigIntegerToBytes(totalDifficulty), bestHash, strategy.getInitState().getInitGenesis().getHash()); sendMessage(msg); ethState = EthState.STATUS_SENT; @@ -321,7 +328,7 @@ protected synchronized void processStatus(StatusMessage msg, ChannelHandlerConte try { - if (!Arrays.equals(msg.getGenesisHash(), config.getGenesis().getHash())) { + if (!Arrays.equals(msg.getGenesisHash(), strategy.getInitState().getInitGenesis().getHash())) { if (!peerDiscoveryMode) { loggerNet.debug("Removing EthHandler for {} due to protocol incompatibility", ctx.channel().remoteAddress()); } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java index 43385d003b..66dd6a14ee 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.StateSource; import org.ethereum.listener.CompositeEthereumListener; @@ -38,7 +39,6 @@ import org.ethereum.util.Value; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -71,9 +71,9 @@ public Eth63() { } @Autowired - public Eth63(final SystemProperties config, final Blockchain blockchain, BlockStore blockStore, + public Eth63(final SystemProperties config, final ConsensusStrategy consensusStrategy, BlockStore blockStore, final CompositeEthereumListener ethereumListener) { - super(version, config, blockchain, blockStore, ethereumListener); + super(version, config, consensusStrategy.getBlockchain(), blockStore, ethereumListener); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java index 022cc2c33d..1f65bd5591 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java @@ -33,7 +33,9 @@ import java.io.*; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.ethereum.util.RLP.decode2OneItem; @@ -51,6 +53,7 @@ public class FrameCodec { private int contextId = -1; private int totalFrameSize = -1; private int protocol; + private Map contextFrameIndex = new HashMap<>(); public FrameCodec(EncryptionHandshake.Secrets secrets) { this.mac = secrets.mac; @@ -163,7 +166,7 @@ public List readFrames(ByteBuf buf) throws IOException { } } - public List readFrames(DataInput inp) throws IOException { + public synchronized List readFrames(DataInput inp) throws IOException { if (!isHeadRead) { byte[] headBuffer = new byte[32]; try { @@ -189,6 +192,7 @@ public List readFrames(DataInput inp) throws IOException { contextId = Util.rlpDecodeInt(rlpList.get(1)); if (rlpList.size() > 2) { totalFrameSize = Util.rlpDecodeInt(rlpList.get(2)); + contextFrameIndex.put(contextId, totalFrameSize); } } @@ -208,10 +212,31 @@ public List readFrames(DataInput inp) throws IOException { ingressMac.update(buffer, 0, frameSize); dec.processBytes(buffer, 0, frameSize, buffer, 0); int pos = 0; - long type = RLP.decodeLong(buffer, pos); - pos = RLP.getNextElementIndex(buffer, pos); + long type = -1; + // According to frame specification only first frame comes with type and pos + if (totalFrameSize > 0 || contextFrameIndex.get(contextId) == null) { + type = RLP.decodeLong(buffer, pos); + pos = RLP.getNextElementIndex(buffer, pos); + } InputStream payload = new ByteArrayInputStream(buffer, pos, totalBodySize - pos); int size = totalBodySize - pos; + + // FIXME: 1 byte is lost in multi-frame, not sure, where is it + // this hack doesn't look normal + if (totalFrameSize > 0) { + size += pos; + } + + if (contextFrameIndex.get(contextId) != null) { + int curSize = contextFrameIndex.get(contextId); + curSize -= size; + if (curSize > 0) { + contextFrameIndex.put(contextId, curSize); + } else { + contextFrameIndex.remove(contextId); + } + } + byte[] macBuffer = new byte[ingressMac.getDigestSize()]; // Frame MAC diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java index 038879f7e8..75a0b40fcc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java @@ -93,7 +93,6 @@ private MessageCodec(final SystemProperties config) { @Override protected void decode(ChannelHandlerContext ctx, Frame frame, List out) throws Exception { - Frame completeFrame = null; if (frame.isChunked()) { if (!supportChunkedFrames && frame.totalFrameSize > 0) { throw new RuntimeException("Faming is not supported in this configuration."); @@ -157,15 +156,14 @@ private Message decodeMessage(ChannelHandlerContext ctx, List frames) thr Message msg; try { msg = createMessage((byte) frameType, payload); + if (loggerNet.isDebugEnabled()) + loggerNet.debug("From: {} Recv: {}", channel, msg.toString()); } catch (Exception ex) { loggerNet.debug("Incorrectly encoded message from: \t{}, dropping peer", channel); channel.disconnect(ReasonCode.BAD_PROTOCOL); return null; } - if (loggerNet.isDebugEnabled()) - loggerNet.debug("From: {} Recv: {}", channel, msg.toString()); - ethereumListener.onRecvMessage(channel, msg); channel.getNodeStatistics().rlpxInMessages.add(); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java b/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java index 10f8996f8c..89d444bc24 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java @@ -161,7 +161,7 @@ public void publicRLPxHandshakeFinished(ChannelHandlerContext ctx, FrameCodec fr logger.debug("publicRLPxHandshakeFinished with " + ctx.channel().remoteAddress()); - messageCodec.setSupportChunkedFrames(false); + messageCodec.setSupportChunkedFrames(true); FrameCodecHandler frameCodecHandler = new FrameCodecHandler(frameCodec, this); ctx.pipeline().addLast("medianFrameCodec", frameCodecHandler); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/server/ChannelManager.java b/ethereumj-core/src/main/java/org/ethereum/net/server/ChannelManager.java index dd079a3247..e01112ae84 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/server/ChannelManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/server/ChannelManager.java @@ -82,8 +82,7 @@ public class ChannelManager { @Autowired SyncPool syncPool; - @Autowired - private Ethereum ethereum; + private Ethereum ethereum; // FIXME: Ethereum -> World -> Channel @Autowired private PendingState pendingState; @@ -124,6 +123,10 @@ private ChannelManager(final SystemProperties config, final SyncManager syncMana this.txDistributeThread.start(); } + public void init(Ethereum ethereum) { + this.ethereum = ethereum; + } + public void connect(Node node) { if (logger.isTraceEnabled()) logger.trace( "Peer {}: initiate connection", diff --git a/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java b/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java index ce9863f51e..67d9b59f93 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/submit/TransactionTask.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import static java.lang.Thread.sleep; @@ -41,6 +42,7 @@ public class TransactionTask implements Callable> { private final List tx; private final ChannelManager channelManager; private final Channel receivedFrom; + private final CompletableFuture future; public TransactionTask(Transaction tx, ChannelManager channelManager) { this(Collections.singletonList(tx), channelManager); @@ -54,6 +56,14 @@ public TransactionTask(List tx, ChannelManager channelManager, Chan this.tx = tx; this.channelManager = channelManager; this.receivedFrom = receivedFrom; + this.future = null; + } + + public TransactionTask(Transaction tx, ChannelManager channelManager, CompletableFuture future) { + this.tx = Collections.singletonList(tx); + this.channelManager = channelManager; + this.future = future; + this.receivedFrom = null; } @Override @@ -62,10 +72,16 @@ public List call() throws Exception { try { logger.info("submit tx: {}", tx.toString()); channelManager.sendTransaction(tx, receivedFrom); + if (future != null) { + future.complete(tx.get(0)); + } return tx; } catch (Throwable th) { logger.warn("Exception caught: {}", th); + if (future != null) { + future.completeExceptionally(th); + } } return null; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/swarm/Util.java b/ethereumj-core/src/main/java/org/ethereum/net/swarm/Util.java index 895c241501..e996195b34 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/swarm/Util.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/swarm/Util.java @@ -1,20 +1,20 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ package org.ethereum.net.swarm; import org.ethereum.util.ByteUtil; @@ -124,11 +124,6 @@ public static byte[] uInt16ToBytes(int uInt16) { public static long curTime() { return TIMER.curTime();} - public static byte[] rlpEncodeLong(long n) { - // TODO for now leaving int cast - return RLP.encodeInt((int) n); - } - public static byte rlpDecodeByte(RLPElement elem) { return (byte) rlpDecodeInt(elem); } @@ -149,26 +144,6 @@ public static String rlpDecodeString(RLPElement elem) { return new String(b); } - public static byte[] rlpEncodeList(Object ... elems) { - byte[][] encodedElems = new byte[elems.length][]; - for (int i =0; i < elems.length; i++) { - if (elems[i] instanceof Byte) { - encodedElems[i] = RLP.encodeByte((Byte) elems[i]); - } else if (elems[i] instanceof Integer) { - encodedElems[i] = RLP.encodeInt((Integer) elems[i]); - } else if (elems[i] instanceof Long) { - encodedElems[i] = rlpEncodeLong((Long) elems[i]); - } else if (elems[i] instanceof String) { - encodedElems[i] = RLP.encodeString((String) elems[i]); - } else if (elems[i] instanceof byte[]) { - encodedElems[i] = ((byte[]) elems[i]); - } else { - throw new RuntimeException("Unsupported object: " + elems[i]); - } - } - return RLP.encodeList(encodedElems); - } - public static SectionReader stringToReader(String s) { return new ArrayReader(s.getBytes(StandardCharsets.UTF_8)); } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/swarm/bzz/BzzStatusMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/swarm/bzz/BzzStatusMessage.java index a70dfea809..abd99fc27a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/swarm/bzz/BzzStatusMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/swarm/bzz/BzzStatusMessage.java @@ -78,9 +78,9 @@ private void encode() { byte[][] capabilities = new byte[this.capabilities.size()][]; for (int i = 0; i < this.capabilities.size(); i++) { Capability capability = this.capabilities.get(i); - capabilities[i] = rlpEncodeList(capability.getName(),capability.getVersion()); + capabilities[i] = RLP.encodeList(capability.getName(),capability.getVersion()); } - this.encoded = rlpEncodeList(version, id, addr.encodeRlp(), networkId, rlpEncodeList(capabilities)); + this.encoded = RLP.encodeList(version, id, addr.encodeRlp(), networkId, RLP.encodeList(capabilities)); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/solidity/SolidityType.java b/ethereumj-core/src/main/java/org/ethereum/solidity/SolidityType.java index 87f3a9e914..c8f041b9b3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/solidity/SolidityType.java +++ b/ethereumj-core/src/main/java/org/ethereum/solidity/SolidityType.java @@ -19,12 +19,15 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; -import org.ethereum.vm.DataWord; import org.spongycastle.util.encoders.Hex; import java.lang.reflect.Array; +import java.math.BigDecimal; import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -63,6 +66,8 @@ public static SolidityType getType(String typeName) { if ("bytes".equals(typeName)) return new BytesType(); if ("function".equals(typeName)) return new FunctionType(); if (typeName.startsWith("bytes")) return new Bytes32Type(typeName); + // FIXME: actually we have 'fixedNM' in Solidity and 'decimal' in Vyper + if (typeName.startsWith("decimal")) return new DecimalType(typeName); throw new RuntimeException("Unknown type: " + typeName); } @@ -256,6 +261,8 @@ public byte[] encode(Object value) { byte[] bb; if (value instanceof byte[]) { bb = (byte[]) value; + } else if (value instanceof ByteArrayWrapper) { + bb = ((ByteArrayWrapper) value).getData(); } else if (value instanceof String) { bb = ((String) value).getBytes(); } else { @@ -387,6 +394,8 @@ public byte[] encode(Object value) { bigInt = (BigInteger) value; } else if (value instanceof Number) { bigInt = new BigInteger(value.toString()); + } else if (value instanceof ByteArrayWrapper) { + bigInt = ByteUtil.bytesToBigInteger(((ByteArrayWrapper) value).getData()); } else if (value instanceof byte[]) { bigInt = ByteUtil.bytesToBigInteger((byte[]) value); } else { @@ -411,6 +420,70 @@ public static byte[] encodeInt(BigInteger bigInt) { } } + public static class DecimalType extends SolidityType { + + // FIXME: what if it's not 10 digits after point + private static int DECIMAL_PLACES = 10; + + public DecimalType(String name) { + super(name); + } + + @Override + public String getCanonicalName() { + if (getName().equals("decimal")) return "decimal10"; + return super.getCanonicalName(); + } + + @Override + public byte[] encode(Object value) { + BigDecimal bigDecimal; + + if (value instanceof String) { + String s = ((String)value).toLowerCase().trim(); + int radix = 10; + if (s.startsWith("0x")) { + s = s.substring(2); + radix = 16; + } else if (s.contains("a") || s.contains("b") || s.contains("c") || + s.contains("d") || s.contains("e") || s.contains("f")) { + radix = 16; + } + + BigInteger bigInt = new BigInteger(s, radix); + bigDecimal = fromBigInt(bigInt, DECIMAL_PLACES); + } else if (value instanceof BigDecimal) { + bigDecimal = (BigDecimal) value; + } else if (value instanceof Number) { + bigDecimal = new BigDecimal(value.toString()); + } else if (value instanceof byte[]) { + BigInteger bigInt = ByteUtil.bytesToBigInteger((byte[]) value); + bigDecimal = fromBigInt(bigInt, DECIMAL_PLACES); + } else { + throw new RuntimeException("Invalid value for type '" + this + "': " + value + " (" + value.getClass() + ")"); + } + return encodeFixed(bigDecimal); + } + + private static BigDecimal fromBigInt(final BigInteger bigInt, final int decimalDigits) { + // FIXME: is it really rounding down?? cannot find Solidity/Vyper practice + return new BigDecimal(bigInt).divide(BigDecimal.valueOf(Math.pow(10, decimalDigits)), RoundingMode.DOWN); + } + + @Override + public Object decode(byte[] encoded, int offset) { + return decodeFixed(encoded, offset); + } + + public static BigDecimal decodeFixed(byte[] encoded, int offset) { + return fromBigInt(new BigInteger(Arrays.copyOfRange(encoded, offset, offset + 32)), DECIMAL_PLACES); + } + public static byte[] encodeFixed(BigDecimal bigDecimal) { + BigInteger bigInt = bigDecimal.multiply(BigDecimal.valueOf(Math.pow(10, DECIMAL_PLACES))).toBigInteger(); + return ByteUtil.bigIntegerToBytesSigned(bigInt, 32); + } + } + public static class BoolType extends IntType { public BoolType() { super("bool"); diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java index 0fbd122058..505c48e49b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java @@ -19,11 +19,8 @@ import org.ethereum.core.BlockHeaderWrapper; import org.ethereum.core.BlockWrapper; -import org.ethereum.core.Blockchain; -import org.ethereum.db.DbFlushManager; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.IndexedBlockStore; -import org.ethereum.util.ByteUtil; -import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -52,8 +49,8 @@ public class FastSyncDownloader extends BlockDownloader { long t; @Autowired - public FastSyncDownloader(BlockHeaderValidator headerValidator) { - super(headerValidator); + public FastSyncDownloader(ConsensusStrategy consensusStrategy) { + super(consensusStrategy.getHeaderValidator()); } public void startImporting(byte[] fromHash, int count) { diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java index be52869eed..5774f45f2c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java @@ -23,8 +23,8 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.HashUtil; -import org.ethereum.datasource.BloomFilter; import org.ethereum.datasource.DbSource; import org.ethereum.db.DbFlushManager; import org.ethereum.db.IndexedBlockStore; @@ -36,7 +36,6 @@ import org.ethereum.net.client.Capability; import org.ethereum.net.eth.handler.Eth63; import org.ethereum.net.message.ReasonCode; -import org.ethereum.net.rlpx.discover.NodeHandler; import org.ethereum.net.server.Channel; import org.ethereum.util.*; import org.slf4j.Logger; @@ -79,10 +78,11 @@ public class FastSyncManager { @Autowired private SystemProperties config; + private ConsensusStrategy consensusStrategy; + @Autowired private SyncPool pool; - @Autowired private BlockchainImpl blockchain; @Autowired @@ -140,6 +140,9 @@ private void waitDbQueueSizeBelow(int size) { void init() { + // FIXME: We could run fast sync on Casper too + blockchain = (BlockchainImpl) consensusStrategy.getBlockchain(); + dbWriterThread = new Thread(() -> { try { while (!Thread.currentThread().isInterrupted()) { @@ -826,4 +829,9 @@ public void close() { logger.warn("Problems closing FastSyncManager", e); } } + + @Autowired + public void setConsensusStrategy(ConsensusStrategy consensusStrategy) { + this.consensusStrategy = consensusStrategy; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java index 09a8f9aad2..209464f115 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java @@ -20,13 +20,13 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.core.Blockchain; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.facade.SyncStatus; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; import org.ethereum.net.server.Channel; import org.ethereum.net.server.ChannelManager; import org.ethereum.util.ExecutorPipeline; -import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -83,7 +83,6 @@ public void accept(BlockWrapper blockWrapper) { */ private BlockingQueue blockQueue = new LinkedBlockingQueue<>(); - @Autowired private Blockchain blockchain; @Autowired @@ -115,8 +114,9 @@ public SyncManager() { } @Autowired - public SyncManager(final SystemProperties config, BlockHeaderValidator validator) { - super(validator); + public SyncManager(final SystemProperties config, ConsensusStrategy consensusStrategy) { + super(consensusStrategy.getHeaderValidator()); + this.blockchain = consensusStrategy.getBlockchain(); this.config = config; blockBytesLimit = config.blockQueueSize(); setHeaderQueueLimit(config.headerQueueSize() / BlockHeader.MAX_HEADER_SIZE); diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java index c24641b444..7d093a7fc9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java @@ -19,6 +19,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.listener.EthereumListener; import org.ethereum.net.rlpx.Node; import org.ethereum.net.rlpx.discover.NodeHandler; @@ -83,9 +84,9 @@ public class SyncPool { private ScheduledExecutorService logExecutor = Executors.newSingleThreadScheduledExecutor(); @Autowired - public SyncPool(final SystemProperties config, final Blockchain blockchain) { + public SyncPool(final SystemProperties config, final ConsensusStrategy consensusStrategy) { this.config = config; - this.blockchain = blockchain; + this.blockchain = consensusStrategy.getBlockchain(); } public void init(final ChannelManager channelManager) { diff --git a/ethereumj-core/src/main/java/org/ethereum/util/RLP.java b/ethereumj-core/src/main/java/org/ethereum/util/RLP.java index 859530b85f..c1cf2b2aa4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/RLP.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/RLP.java @@ -934,6 +934,15 @@ else if ((singleInt & 0xFFFFFF) == singleInt) } } + public static byte[] encodeLong(long singleLong) { + if (singleLong <= Integer.MAX_VALUE) { + return encodeInt((int) singleLong); + } else { + // TODO: optimize me + return encodeBigInteger(BigInteger.valueOf(singleLong)); + } + } + public static byte[] encodeString(String srcString) { return encodeElement(srcString.getBytes()); } @@ -1123,6 +1132,36 @@ public static byte[] encodeSet(Set data) { return output; } + public static byte[] encodeList(Object... elements) { + + if (elements == null) { + return new byte[]{(byte) OFFSET_SHORT_LIST}; + } + + byte[][] encodedElems = new byte[elements.length][]; + for (int i =0; i < elements.length; i++) { + // TODO: consider using {@link: encode(Object)} + if (elements[i] instanceof Byte) { + encodedElems[i] = encodeByte((Byte) elements[i]); + } else if (elements[i] instanceof Short) { + encodedElems[i] = encodeShort((Short) elements[i]); + } else if (elements[i] instanceof Integer) { + encodedElems[i] = encodeInt((Integer) elements[i]); + } else if (elements[i] instanceof Long) { + encodedElems[i] = encodeLong((Long) elements[i]); + } else if (elements[i] instanceof BigInteger) { + encodedElems[i] = encodeBigInteger((BigInteger) elements[i]); + } else if (elements[i] instanceof String) { + encodedElems[i] = encodeString((String) elements[i]); + } else if (elements[i] instanceof byte[]) { + encodedElems[i] = ((byte[]) elements[i]); + } else { + throw new RuntimeException("Unsupported object: " + elements[i]); + } + } + return RLP.encodeList(encodedElems); + } + public static byte[] encodeList(byte[]... elements) { if (elements == null) { diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 3cd49ed270..2cbfba654b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -61,9 +61,9 @@ public class StandaloneBlockchain implements LocalBlockchain { Genesis genesis; byte[] coinbase; - BlockchainImpl blockchain; - PendingStateImpl pendingState; - CompositeEthereumListener listener; + protected BlockchainImpl blockchain; + protected PendingStateImpl pendingState; + protected CompositeEthereumListener listener; ECKey txSender; long gasPrice; long gasLimit; @@ -77,11 +77,11 @@ public class StandaloneBlockchain implements LocalBlockchain { long time = 0; long timeIncrement = 13; - private HashMapDB stateDS; - JournalSource pruningStateDS; - PruneManager pruneManager; + protected HashMapDB stateDS; + protected JournalSource pruningStateDS; + protected PruneManager pruneManager; - private BlockSummary lastSummary; + protected BlockSummary lastSummary; class PendingTx { ECKey sender; @@ -228,6 +228,10 @@ public PendingStateImpl getPendingState() { return pendingState; } + public CompositeEthereumListener getListener() { + return listener; + } + public void generatePendingTransactions() { pendingState.addPendingTransactions(new ArrayList<>(createTransactions(getBlockchain().getBestBlock()).values())); } @@ -237,6 +241,14 @@ public Block createBlock() { return createForkBlock(getBlockchain().getBestBlock()); } + public Block createBlock(byte[] minerCoinbase) { + byte[] curCoinbase = coinbase; + getBlockchain().setMinerCoinbase(minerCoinbase); + Block block = createForkBlock(getBlockchain().getBestBlock()); + getBlockchain().setMinerCoinbase(curCoinbase); + return block; + } + @Override public Block createForkBlock(Block parent) { try { @@ -486,8 +498,7 @@ private BlockchainImpl createBlockchain(Genesis genesis) { listener = new CompositeEthereumListener(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withEthereumListener(listener) - .withSyncManager(new SyncManager()); + .withEthereumListener(listener); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.setPruneManager(pruneManager); 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 5e8764c95a..7203d5a0a0 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 @@ -843,15 +843,18 @@ public void fullTrace() { ContractDetails contractDetails = getStorage(). getContractDetails(getOwnerAddress().getLast20Bytes()); StringBuilder storageData = new StringBuilder(); - if (contractDetails != null) { - List storageKeys = new ArrayList<>(contractDetails.getStorage().keySet()); - Collections.sort(storageKeys); - for (DataWord key : storageKeys) { - storageData.append(" ").append(key).append(" -> "). - append(contractDetails.getStorage().get(key)).append("\n"); + // FIXME: fails + try { + if (contractDetails != null) { + List storageKeys = new ArrayList<>(contractDetails.getStorage().keySet()); + Collections.sort(storageKeys); + for (DataWord key : storageKeys) { + storageData.append(" ").append(key).append(" -> "). + append(contractDetails.getStorage().get(key)).append("\n"); + } + if (storageData.length() > 0) storageData.insert(0, "\n"); } - if (storageData.length() > 0) storageData.insert(0, "\n"); - } + } catch (java.lang.Exception ex) {} StringBuilder memoryData = new StringBuilder(); StringBuilder oneLine = new StringBuilder(); diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java index bc007cca55..a2fe17be23 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java @@ -19,6 +19,7 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.ContractDetails; @@ -238,4 +239,9 @@ public Set getStorageKeys(byte[] addr) { public Map getStorage(byte[] addr, @Nullable Collection keys) { return repository.getStorage(addr, keys); } + + @Override + public void setBlockchain(Blockchain blockchain) { + // Not used in current implementation + } } diff --git a/ethereumj-core/src/main/resources/casper.conf b/ethereumj-core/src/main/resources/casper.conf new file mode 100644 index 0000000000..a34f7f4e82 --- /dev/null +++ b/ethereumj-core/src/main/resources/casper.conf @@ -0,0 +1,95 @@ +peer.discovery = { + enabled = false + + # List of the peers to start + # the search of the online peers + # values: [ip:port, ip:port, ip:port ...] + ip.list = [ +# "54.167.247.63:30303", +# "35.169.148.66:30303", +# "34.239.105.125:30303", +# "54.226.126.100:30303", +# "34.201.104.186:30303", +# "34.224.156.160:30303", +# "54.226.243.26:30303", +# "13.230.118.134:30303", +# "18.196.33.71:30303", +"34.201.104.186:30303" +#"127.0.0.1:30308" + ] +} + +peer.active = [ +# {url = "enode://d3260a710a752b926bb3328ebe29bfb568e4fb3b4c7ff59450738661113fb21f5efbdf42904c706a9f152275890840345a5bc990745919eeb2dfc2c481d778ee@54.167.247.63:30303"}, +# {url = "enode://a120401858c93f0be73ae7765930174689cad026df332f7e06a047ead917cee193e9210e899c3143cce55dd991493227ecea15de42aa05b9b730d2189e19b567@35.169.148.66:30303"}, +# {url = "enode://6f5210fab6b7530acd2a66da1c2568289bb065e6811673d5f24bf274491b037585da1ec854e172f8dcdf3e7c5dff4ef8a270c597bbc1928a43385586e1e9f431@34.239.105.125:30303"}, +# {url = "enode://8d4a6aec3e340f9e859fd72ced95d2a0b49766772ac914810f6888bc2be5f95acf241aa94de8cd47a92dec1e8f96d86f4c052cc020e7c8e5438f6f18211dfeb1@54.226.126.100:30303"}, +# {url = "enode://9e1b6f599f4aa29897c817dd4c68c11a60bb6388cf83d4606e82c6fc742363fb5b7e306c39f8887196f1c436274404503d50b7d023e99b53c8d97f197438c60b@34.201.104.186:30303"}, +# {url = "enode://8cae2ed1214f394ae36d8a737066572c2f45a01b13aca8cc9a42e4425c7d8f8a362674d1b34f9417840e584ddb00eccf7fe53af51f5d1a32c31aab74b6ed423e@34.224.156.160:30303"}, +# {url = "enode://e0e4620880078ba43a3c11bd19490f1cce6d7fdbf9e0fab7560b784409134405e0286881031016d8dad556ff89c8a729d5bcb87a7db91a2c047ad56bf19a3581@54.226.243.26:30303"}, +# {url = "enode://ca9df451335b0bd48f6196675303b7173f8c69e63ebce6b8fb063a8e9d58156e13932f21f496aca6fd0b2ac6b34cf1276a098d5e94aa244cb0126b5a05a1d958@13.230.118.134:30303"}, +# {url = "enode://58239d442b8167d59cdf22162778c94e2549ff5981c196dc4233b6ec3e860a698ad7bf4e11e8146b76ecedd6ff465f97b890ba89a9dee051c975ac7f322dbfd8@18.196.33.71:30303"} +{url="enode://9e1b6f599f4aa29897c817dd4c68c11a60bb6388cf83d4606e82c6fc742363fb5b7e306c39f8887196f1c436274404503d50b7d023e99b53c8d97f197438c60b@34.201.104.186:30303"} +#{url = "enode://7a2e5857abb1786cc0c4cd135ec406c81e64457a4eec59555b9b32d20188497122adcac6b59e47beadb583d6de4c29bfa7a465a3c01c2eaaf35ec3d31d04d4a7@127.0.0.1:30308"} +] + +# Network id +peer.networkId = 1307 +peer.listen.port = 30301 + +# the folder resources/genesis +# contains several versions of +# genesis configuration according +# to the network the peer will run on +genesis = casper.json + +database { + # place to save physical storage files + dir = database-casper +} + +#vm.structured { +#trace = true +#dir = vmtrace +#compressed = true +#initStorageLimit = 10000 +#} + +blockchain.config.name = "casper" + +consensus { + # Strategy for consensus + # Currently supported: + # "pow" - Proof of Work + # "casper-hybrid" - hybrid PoW + Casper PoS + strategy="casper-hybrid" + + # Casper specific settings, used only with Casper strategy + casper { + # Casper contract BIN (required) + contractBin = "/casper/casper.bin" + + # Casper contract ABI (required) + contractAbi = "/casper/casper.abi" + + # Casper epoch length (required) + epochLength = 50 + # Currently hardcoded and encoded in casper.bin + # withdrawalDelay = + # baseInterestFactor = + # basePenaltyFactor + + # Casper validator settings (required) + validator { + # Is Casper validator on (required) + enabled = true + # Validator coinbase (withdraw/deposit address) private key (optional) + # TODO: It should be something more secure + privateKey = "396ecd4115d4e20d4846060013823e1687b95960398f6f148f0fd64e70af13ac" + # Deposit in ethereum, 1500 is minimum (optional) + deposit = 2000 + } + } +} + +mine.start=false diff --git a/ethereumj-core/src/main/resources/casper/casper.abi b/ethereumj-core/src/main/resources/casper/casper.abi new file mode 100644 index 0000000000..7bf16fa1ad --- /dev/null +++ b/ethereumj-core/src/main/resources/casper/casper.abi @@ -0,0 +1,545 @@ +[{ + "name": "__init__", + "outputs": [], + "inputs": [{ + "type": "int128", + "name": "_epoch_length" + }, { + "type": "int128", + "name": "_withdrawal_delay" + }, { + "type": "address", + "name": "_owner" + }, { + "type": "address", + "name": "_sighasher" + }, { + "type": "address", + "name": "_purity_checker" + }, { + "type": "decimal10", + "name": "_base_interest_factor" + }, { + "type": "decimal10", + "name": "_base_penalty_factor" + }, { + "type": "int128", + "name": "_min_deposit_size" + }], + "constant": false, + "payable": false, + "type": "constructor" +}, { + "name": "get_main_hash_voted_frac", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_deposit_size", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "validator_index" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_total_curdyn_deposits", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_total_prevdyn_deposits", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_recommended_source_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_recommended_target_hash", + "outputs": [{ + "type": "bytes32", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "initialize_epoch", + "outputs": [], + "inputs": [{ + "type": "int128", + "name": "epoch" + }], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "deposit", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "validation_addr" + }, { + "type": "address", + "name": "withdrawal_addr" + }], + "constant": false, + "payable": true, + "type": "function" +}, { + "name": "logout", + "outputs": [], + "inputs": [{ + "type": "bytes", + "name": "logout_msg" + }], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "withdraw", + "outputs": [], + "inputs": [{ + "type": "int128", + "name": "validator_index" + }], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "vote", + "outputs": [], + "inputs": [{ + "type": "bytes", + "name": "vote_msg" + }], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "slash", + "outputs": [], + "inputs": [{ + "type": "bytes", + "name": "vote_msg_1" + }, { + "type": "bytes", + "name": "vote_msg_2" + }], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "owner_withdraw", + "outputs": [], + "inputs": [], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "change_owner", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "new_owner" + }], + "constant": false, + "payable": false, + "type": "function" +}, { + "name": "get_validators__deposit", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_validators__start_dynasty", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_validators__end_dynasty", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_validators__addr", + "outputs": [{ + "type": "address", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_validators__withdrawal_addr", + "outputs": [{ + "type": "address", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_checkpoint_hashes", + "outputs": [{ + "type": "bytes32", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_nextValidatorIndex", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_validator_indexes", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_dynasty", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_next_dynasty_wei_delta", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_second_next_dynasty_wei_delta", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_dynasty_start_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_dynasty_in_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_votes__cur_dyn_votes", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }, { + "type": "int128", + "name": "arg1" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_votes__prev_dyn_votes", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }, { + "type": "int128", + "name": "arg1" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_votes__vote_bitmap", + "outputs": [{ + "type": "uint256", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }, { + "type": "bytes32", + "name": "arg1" + }, { + "type": "int128", + "name": "arg2" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_votes__is_justified", + "outputs": [{ + "type": "bool", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_votes__is_finalized", + "outputs": [{ + "type": "bool", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_main_hash_justified", + "outputs": [{ + "type": "bool", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_deposit_scale_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_last_nonvoter_rescale", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_last_voter_rescale", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_epoch_length", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_withdrawal_delay", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_current_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_last_finalized_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_last_justified_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_expected_source_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_reward_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_base_interest_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}, { + "name": "get_base_penalty_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function" +}] \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/casper/casper.bin b/ethereumj-core/src/main/resources/casper/casper.bin new file mode 100644 index 0000000000..85bcdc5d0b --- /dev/null +++ b/ethereumj-core/src/main/resources/casper/casper.bin @@ -0,0 +1 @@ +0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05261010061377f6101403934156100a857600080fd5b606051602061377f60c03960c051806040519013585780919012156100cc57600080fd5b506060516020602061377f0160c03960c051806040519013585780919012156100f457600080fd5b506020604061377f0160c03960c051602051811061011157600080fd5b506020606061377f0160c03960c051602051811061012e57600080fd5b506020608061377f0160c03960c051602051811061014b57600080fd5b50606051602060e061377f0160c03960c0518060405190135857809190121561017357600080fd5b50610140516010556101605160115560016002556101805160165568056bc75e2d63100000600d60c052602060c020556000600455606051601054806101b857600080fd5b4305806040519013585780919012156101d057600080fd5b6012556101a0516018556101c051601955600060075560006008556101e051601b5561020051601c557f632a9a52ef120699847d16b5c0f45b7d5ff4404dd8054906681967edc6094fbf601d5561022051601e5561376756600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526394113f78600051141561017b5734156100ac57600080fd5b60a051601554601254600b60c052602060c0200160c052602060c02060c052602060c0200154600754806100df57600080fd5b806402540be400830205905090508060805190135857809190121561010357600080fd5b60a0516015546003601254600b60c052602060c0200160c052602060c0200160c052602060c02001546008548061013957600080fd5b806402540be400830205905090508060805190135857809190121561015d57600080fd5b8082131561016b578061016d565b815b9050905060005260206000f3005b63843b0890600051141561022f576020600461014037341561019c57600080fd5b606051600435806040519013585780919012156101b857600080fd5b506402540be40060a051601254600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c0200154818102811983838305141761020057600080fd5b6402540be40081059050905090508060805190135857809190121561022457600080fd5b0560005260206000f3005b633b812ec360005114156102a657341561024857600080fd5b6402540be40060a051601254600d60c052602060c0200154600754818102811983838305141761027757600080fd5b6402540be40081059050905090508060805190135857809190121561029b57600080fd5b0560005260206000f3005b63679dea62600051141561031d5734156102bf57600080fd5b6402540be40060a051601254600d60c052602060c020015460085481810281198383830514176102ee57600080fd5b6402540be40081059050905090508060805190135857809190121561031257600080fd5b0560005260206000f3005b63b2ae3f50600051141561034357341561033657600080fd5b60155460005260206000f3005b63cadbbfc160005114156103c057341561035c57600080fd5b6060516001606051601054601254028060405190135857809190121561038157600080fd5b038060405190135857809190121561039857600080fd5b61010043038112156103a957600080fd5b4381106103b557600080fd5b4060005260206000f3005b63de7f997560005114156103fc5734156103d957600080fd5b3033146103e557600080fd5b6000600854136000600754131660005260206000f3005b63d286bb82600051141561051657341561041557600080fd5b30331461042157600080fd5b601254610140526001606051600261014051038060405190135857809190121561044a57600080fd5b600b60c052602060c0200160c052602060c0200154156104d057600460605160018254018060405190135857809190121561048457600080fd5b815550600754600855600760a051600554825401806080519013585780919012156104ae57600080fd5b815550600654600555600060065561014051600454600960c052602060c02001555b60045461014051600a60c052602060c0200155600c541561050f57606051600161014051038060405190135857809190121561050b57600080fd5b6015555b6000600c55005b63fa650b2a600051141561056d57341561052f57600080fd5b30331461053b57600080fd5b6012546101405260605160135461014051038060405190135857809190121561056357600080fd5b60005260206000f3005b6370af50be600051141561077d57341561058657600080fd5b30331461059257600080fd5b60125461014052600260206101c0600463fa650b2a6101605261017c6000305af16105bc57600080fd5b6101c05113156101e0526101e051156020610260600463de7f99756102005261021c6000305af16105ec57600080fd5b6102605115171561060257600060005260206000f35b60a051601554606051600161014051038060405190135857809190121561062857600080fd5b600b60c052602060c0200160c052602060c02060c052602060c02001546007548061065257600080fd5b806402540be400830205905090508060805190135857809190121561067657600080fd5b6102805260a051601554600360605160016101405103806040519013585780919012156106a257600080fd5b600b60c052602060c0200160c052602060c0200160c052602060c0200154600854806106cd57600080fd5b806402540be40083020590509050806080519013585780919012156106f157600080fd5b6102a052610280516102a0518082131561070b578061070d565b815b905090506102c05260a051600260a051601a546102c051818102811983838305141761073857600080fd5b6402540be40081059050905090508060805190135857809190121561075c57600080fd5b058060805190135857809190121561077357600080fd5b60005260206000f3005b636526ed72600051141561086857341561079657600080fd5b3033146107a257600080fd5b601254610140526001600c556001600260605160016101405103806040519013585780919012156107d257600080fd5b600b60c052602060c0200160c052602060c020015560016001606051600161014051038060405190135857809190121561080b57600080fd5b600b60c052602060c0200160c052602060c0200155606051600161014051038060405190135857809190121561084057600080fd5b601455606051600161014051038060405190135857809190121561086357600080fd5b601355005b63d9d341b96000511415610a52576020600461014037341561088957600080fd5b30331461089557600080fd5b606051600435806040519013585780919012156108b157600080fd5b5060605160016402540be40060a051670de0b6b3a764000060a05160605160016101405103806040519013585780919012156108ec57600080fd5b600d60c052602060c02001546008546007548082121561090c578061090e565b815b90509050818102811983838305141761092657600080fd5b6402540be40081059050905090508060805190135857809190121561094a57600080fd5b058060805190135857809190121561096157600080fd5b05018060405190135857809190121561097957600080fd5b6101605260a0516404a817c80068056bc75e2d63100000610160510205806080519013585780919012156109ac57600080fd5b610180526101a060006014818352015b60a051600260a05160a05161018051806109d557600080fd5b68056bc75e2d63100000610160510205806080519013585780919012156109fb57600080fd5b610180510180608051901358578091901215610a1657600080fd5b0580608051901358578091901215610a2d57600080fd5b610180525b81516001018083528114156109bc575b50506101805160005260206000f3005b635dcffc176000511415610ddb5760206004610140373415610a7357600080fd5b60605160043580604051901358578091901215610a8f57600080fd5b5060605160105480610aa057600080fd5b430580604051901358578091901215610ab857600080fd5b6101605260605160016012540180604051901358578091901215610adb57600080fd5b61014051146101605161014051131516610af457600080fd5b6101405160125560a051601a5460a05160206101e060046370af50be6101805261019c6000305af1610b2557600080fd5b6101e0516402540be4000180608051901358578091901215610b4657600080fd5b0380608051901358578091901215610b5d57600080fd5b600e5560a05160a051601a546402540be4000180608051901358578091901215610b8657600080fd5b600e548181028119838383051417610b9d57600080fd5b6402540be400810590509050905080608051901358578091901215610bc157600080fd5b600f5560a051600e546060516001610140510380604051901358578091901215610bea57600080fd5b600d60c052602060c02001548181028119838383051417610c0a57600080fd5b6402540be400810590509050905080608051901358578091901215610c2e57600080fd5b61014051600d60c052602060c020015560206102c0600463de7f99756102605261027c6000305af1610c5f57600080fd5b6102c05115610d5e5760a051601b546020610360602463d9d341b96102e05261014051610300526102fc6000305af1610c9757600080fd5b6103605180610ca557600080fd5b806402540be4008302059050905080608051901358578091901215610cc957600080fd5b6103805260a05160a0516020610400600463fa650b2a6103a0526103bc6000305af1610cf457600080fd5b61040051601c548181028119838383051417610d0f57600080fd5b8090509050905080608051901358578091901215610d2c57600080fd5b610380510180608051901358578091901215610d4757600080fd5b601a556000601a5413610d5957600080fd5b610d84565b600060006004636526ed726102005261021c6000305af1610d7e57600080fd5b6000601a555b60006000600463d286bb826104205261043c6000305af1610da457600080fd5b60206104e0600463cadbbfc16104805261049c6000305af1610dc557600080fd5b6104e05161014051600160c052602060c0200155005b63f9609f0860005114156110915760406004610140376004356020518110610e0257600080fd5b506024356020518110610e1457600080fd5b5060605160105480610e2557600080fd5b430580604051901358578091901215610e3d57600080fd5b60125414610e4a57600080fd5b600060006004610180527fa1903eab000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101e001018260208501600060046012f1505080518201915050610140516020826101e0010152602081019050806101e0526101e09050805160200180610260828460006004600a8704601201f1610ed957600080fd5b505060206103006102605161028060006019546207a120f1610efa57600080fd5b60206102e0526102e0602060006020835103811315610f1857600080fd5b0460200260200181015190501415610f2f57600080fd5b61016051600360c052602060c020015415610f4957600080fd5b601e54341215610f5857600080fd5b600254600060c052602060c0200160c052602060c02061014051815560a051601254600d60c052602060c020015480610f9057600080fd5b68056bc75e2d6310000034020580608051901358578091901215610fb357600080fd5b60018201556c0c9f2c9cd04674edea40000000600282015560605160026004540180604051901358578091901215610fea57600080fd5b60038201556101605160048201555060025461016051600360c052602060c0200155600260605160018254018060405190135857809190121561102c57600080fd5b815550600660a05160a051601254600d60c052602060c02001548061105057600080fd5b68056bc75e2d631000003402058060805190135857809190121561107357600080fd5b8254018060805190135857809190121561108c57600080fd5b815550005b6342310c32600051141561148557602060046101403734156110b257600080fd5b610420600435600401610160376104006004356004013511156110d457600080fd5b606051601054806110e457600080fd5b4305806040519013585780919012156110fc57600080fd5b6012541461110957600080fd5b6101608051602001806105a0828460006004600a8704601201f161112c57600080fd5b50506020610a006105a0516105c0600060185462030d40f161114d57600080fd5b60206109e0526109e060206000602083510381131561116b57600080fd5b046020026020018101519050610a4052611000610160610560610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610aa0f150506080610a6051146111ba57600080fd5b610a6051610a60018060200151600082518060209013585780919012156111e057600080fd5b601f6101000a82048115176111f457600080fd5b606051816020036101000a83048060405190135857809190121561121757600080fd5b9050905090508152610a8051610a600180602001516000825180602090135857809190121561124557600080fd5b601f6101000a820481151761125957600080fd5b606051816020036101000a83048060405190135857809190121561127c57600080fd5b9050905090508160200152610aa051610a600180516020018083604001828460006004600a8704601201f16112b057600080fd5b5050506110005161148052611020516114a0526110408051602001806114c0828460006004600a8704601201f16112e657600080fd5b50506114a05160125412156112fa57600080fd5b60016000610a40516020826119000101526020810190506114c06104008060208461190001018260208501600060046078f150508051820191505080611900526119009050805160200180611d60828460006004600a8704601201f161135f57600080fd5b505060206121e0611d6051611d80600061148051600060c052602060c0200160c052602060c020546207a120f161139557600080fd5b60206121c0526121c06020600060208351038113156113b357600080fd5b046020026020018101519050146113c957600080fd5b606051600260045401806040519013585780919012156113e857600080fd5b600261148051600060c052602060c0200160c052602060c02001541361140d57600080fd5b6060516002600454018060405190135857809190121561142c57600080fd5b600261148051600060c052602060c0200160c052602060c0200155600660a051600161148051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561148057600080fd5b815550005b6301b7af1860005114156115af57602060046101403734156114a657600080fd5b3033146114b257600080fd5b606051600435806040519013585780919012156114ce57600080fd5b50606051600260045401806040519013585780919012156114ee57600080fd5b600261014051600060c052602060c0200160c052602060c0200154131561154c57600560a051600161014051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561154857600080fd5b8155505b6000600461014051600060c052602060c0200160c052602060c0200154600360c052602060c020015561014051600060c052602060c0200160c052602060c020600081556000600182015560006002820155600060038201556000600482015550005b63edea1480600051141561177657602060046101403734156115d057600080fd5b606051600435806040519013585780919012156115ec57600080fd5b506060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561162457600080fd5b600454121561163257600080fd5b6060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561166957600080fd5b600960c052602060c02001546101605260605160115461016051018060405190135857809190121561169a57600080fd5b60125412156116a857600080fd5b6402540be40060a05161016051600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c020015481810281198383830514176116f057600080fd5b6402540be40081059050905090508060805190135857809190121561171457600080fd5b0561018052600060006000600061018051600461014051600060c052602060c0200160c052602060c02001546000f161174c57600080fd5b6000600060246301b7af186101a052610140516101c0526101bc6000305af161177457600080fd5b005b63579f38b26000511415611a70576040600461014037341561179757600080fd5b3033146117a357600080fd5b606051600435806040519013585780919012156117bf57600080fd5b50606051602435806040519013585780919012156117dc57600080fd5b50600361014051600060c052602060c0200160c052602060c0200154600960c052602060c020015461018052600161014051600060c052602060c0200160c052602060c0200160a0516402540be40061016051028254018060805190135857809190121561184957600080fd5b815550600361014051600060c052602060c0200160c052602060c02001546101a052600261014051600060c052602060c0200160c052602060c02001546101c0526004546101e05260605160016101e05103806040519013585780919012156118b157600080fd5b610200526101c0516101e051126101e0516101a051131516156118fb57600760a0516402540be4006101605102825401806080519013585780919012156118f757600080fd5b8155505b6101c0516102005112610200516101a0511315161561194157600860a0516402540be40061016051028254018060805190135857809190121561193d57600080fd5b8155505b60605160016101c051038060405190135857809190121561196157600080fd5b6101e051141561199857600560a0516402540be40061016051028254038060805190135857809190121561199457600080fd5b8155505b60605160026101c05103806040519013585780919012156119b857600080fd5b6101e05114156119ef57600660a0516402540be4006101605102825403806080519013585780919012156119eb57600080fd5b8155505b60006000600060006402540be40060a051600860a051601254600d60c052602060c0200154610160518181028119838383051417611a2c57600080fd5b8090509050905080608051901358578091901215611a4957600080fd5b0580608051901358578091901215611a6057600080fd5b05416000f1611a6e57600080fd5b005b63e9dc061460005114156123ec5760206004610140373415611a9157600080fd5b61042060043560040161016037610400600435600401351115611ab357600080fd5b6101608051602001806105a0828460006004600a8704601201f1611ad657600080fd5b50506020610a006105a0516105c0600060185462030d40f1611af757600080fd5b60206109e0526109e0602060006020835103811315611b1557600080fd5b046020026020018101519050610a40526110c0610160610620610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610a605114611b6457600080fd5b610a6051610a6001806020015160008251806020901358578091901215611b8a57600080fd5b601f6101000a8204811517611b9e57600080fd5b606051816020036101000a830480604051901358578091901215611bc157600080fd5b90509050905081526020610a8051610a60015114611bde57600080fd5b610a8051610a8001518160200152610aa051610a6001806020015160008251806020901358578091901215611c1257600080fd5b601f6101000a8204811517611c2657600080fd5b606051816020036101000a830480604051901358578091901215611c4957600080fd5b9050905090508160400152610ac051610a6001806020015160008251806020901358578091901215611c7a57600080fd5b601f6101000a8204811517611c8e57600080fd5b606051816020036101000a830480604051901358578091901215611cb157600080fd5b9050905090508160600152610ae051610a600180516020018083608001828460006004600a8704601201f1611ce557600080fd5b5050506110c051611580526110e0516115a052611100516115c052611120516115e052611140805160200180611600828460006004600a8704601201f1611d2b57600080fd5b505060016000610a4051602082611a4001015260208101905061160061040080602084611a4001018260208501600060046078f150508051820191505080611a4052611a409050805160200180611ea0828460006004600a8704601201f1611d9257600080fd5b50506020612320611ea051611ec0600061158051600060c052602060c0200160c052602060c020546207a120f1611dc857600080fd5b602061230052612300602060006020835103811315611de657600080fd5b04602002602001810151905014611dfc57600080fd5b6001606051610100611580510780604051901358578091901215611e1f57600080fd5b600081131515611e37578060000360020a8204611e3e565b8060020a82025b90509050606051610100611580510580604051901358578091901215611e6357600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541615611e9f57600080fd5b60206123c0600463cadbbfc16123605261237c6000305af1611ec057600080fd5b6123c0516115a05114611ed257600080fd5b60026115e051600b60c052602060c0200160c052602060c0200154611ef657600080fd5b600361158051600060c052602060c0200160c052602060c02001546123e052600261158051600060c052602060c0200160c052602060c0200154612400526115c051600a60c052602060c0200154612420526060516001612420510380604051901358578091901215611f6857600080fd5b61244052612400516124205112612420516123e05113151661246052612400516124405112612440516123e05113151661248052612480516124605117611fae57600080fd5b6001606051610100611580510780604051901358578091901215611fd157600080fd5b600081131515611fe9578060000360020a8204611ff0565b8060020a82025b9050905060605161010061158051058060405190135857809190121561201557600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541760605161010061158051058060405190135857809190121561206857600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001556115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001546124a0526115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001546124c052612460511561215e576124a060a051600161158051600060c052602060c0200160c052602060c02001548251018060805190135857809190121561213157600080fd5b8152506124a0516115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001555b61248051156121d1576124c060a051600161158051600060c052602060c0200160c052602060c0200154825101806080519013585780919012156121a157600080fd5b8152506124c0516115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001555b6115e051601554146115c05160125414161561227c576402540be40060a051601a54600161158051600060c052602060c0200160c052602060c0200154818102811983838305141761222257600080fd5b6402540be40081059050905090508060805190135857809190121561224657600080fd5b056124e05260006000604463579f38b26125005261158051612520526124e0516125405261251c6000305af161227b57600080fd5b5b60026115c051600b60c052602060c0200160c052602060c02001541560a051600360a051600260085481810281198383830514176122b957600080fd5b80905090509050806080519013585780919012156122d657600080fd5b05806080519013585780919012156122ed57600080fd5b6124c051121560a051600360a0516002600754818102811983838305141761231457600080fd5b809050905090508060805190135857809190121561233157600080fd5b058060805190135857809190121561234857600080fd5b6124a05112151616156123dc57600160026115c051600b60c052602060c0200160c052602060c02001556115c0516014556012546115c051141561238c576001600c555b60605160016115e05101806040519013585780919012156123ac57600080fd5b6115c05114156123db57600160016115e051600b60c052602060c0200160c052602060c02001556115e0516013555b5b610160601d54815160208301a150005b63cc20f16b6000511415612c4d576040600461014037341561240d57600080fd5b6104206004356004016101803761040060043560040135111561242f57600080fd5b6104206024356004016105c03761040060243560040135111561245157600080fd5b610180805160200180610a00828460006004600a8704601201f161247457600080fd5b50506020610e60610a0051610a20600060185462030d40f161249557600080fd5b6020610e4052610e406020600060208351038113156124b357600080fd5b046020026020018101519050610ea052611520610180610620610ec08251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610ec0511461250257600080fd5b610ec051610ec00180602001516000825180602090135857809190121561252857600080fd5b601f6101000a820481151761253c57600080fd5b606051816020036101000a83048060405190135857809190121561255f57600080fd5b90509050905081526020610ee051610ec001511461257c57600080fd5b610ee051610ee001518160200152610f0051610ec0018060200151600082518060209013585780919012156125b057600080fd5b601f6101000a82048115176125c457600080fd5b606051816020036101000a8304806040519013585780919012156125e757600080fd5b9050905090508160400152610f2051610ec00180602001516000825180602090135857809190121561261857600080fd5b601f6101000a820481151761262c57600080fd5b606051816020036101000a83048060405190135857809190121561264f57600080fd5b9050905090508160600152610f4051610ec00180516020018083608001828460006004600a8704601201f161268357600080fd5b505050611520516119e05261156051611a005261158051611a20526115a0805160200180611a40828460006004600a8704601201f16126c157600080fd5b505060016000610ea051602082611e80010152602081019050611a4061040080602084611e8001018260208501600060046078f150508051820191505080611e8052611e8090508051602001806122e0828460006004600a8704601201f161272857600080fd5b505060206127606122e05161230060006119e051600060c052602060c0200160c052602060c020546207a120f161275e57600080fd5b60206127405261274060206000602083510381131561277c57600080fd5b0460200260200181015190501461279257600080fd5b6105c08051602001806127a0828460006004600a8704601201f16127b557600080fd5b50506020612c006127a0516127c0600060185462030d40f16127d657600080fd5b6020612be052612be06020600060208351038113156127f457600080fd5b046020026020018101519050612c40526115206105c0610620612c608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0612c60511461284357600080fd5b612c6051612c600180602001516000825180602090135857809190121561286957600080fd5b601f6101000a820481151761287d57600080fd5b606051816020036101000a8304806040519013585780919012156128a057600080fd5b90509050905081526020612c8051612c600151146128bd57600080fd5b612c8051612c8001518160200152612ca051612c60018060200151600082518060209013585780919012156128f157600080fd5b601f6101000a820481151761290557600080fd5b606051816020036101000a83048060405190135857809190121561292857600080fd5b9050905090508160400152612cc051612c600180602001516000825180602090135857809190121561295957600080fd5b601f6101000a820481151761296d57600080fd5b606051816020036101000a83048060405190135857809190121561299057600080fd5b9050905090508160600152612ce051612c600180516020018083608001828460006004600a8704601201f16129c457600080fd5b505050611520516132c052611560516132e05261158051613300526115a0805160200180613320828460006004600a8704601201f1612a0257600080fd5b505060016000612c40516020826137600101526020810190506133206104008060208461376001018260208501600060046078f150508051820191505080613760526137609050805160200180613bc0828460006004600a8704601201f1612a6957600080fd5b50506020614040613bc051613be060006132c051600060c052602060c0200160c052602060c020546207a120f1612a9f57600080fd5b602061402052614020602060006020835103811315612abd57600080fd5b04602002602001810151905014612ad357600080fd5b6132c0516119e05114612ae557600080fd5b612c4051610ea0511415612af857600080fd5b6000614080526132e051611a00511415612b1757600161408052612b4b565b611a20516133005112611a00516132e051131661330051611a2051126132e051611a005113161715612b4a576001614080525b5b61408051612b5857600080fd5b6020614120602463843b08906140a0526119e0516140c0526140bc6000305af1612b8157600080fd5b61412051614140526060516019614140510580604051901358578091901215612ba957600080fd5b61416052601760605160605160196060516018614140510280604051901358578091901215612bd757600080fd5b0580604051901358578091901215612bee57600080fd5b82540180604051901358578091901215612c0757600080fd5b8155506000600060246301b7af18614180526119e0516141a05261419c6000305af1612c3257600080fd5b600060006000600061416051336000f1612c4b57600080fd5b005b6334ef39f16000511415612c87573415612c6657600080fd5b60006000600060006017546016546000f1612c8057600080fd5b6000601755005b63253c8bd46000511415612cce5760206004610140373415612ca857600080fd5b6004356020518110612cb957600080fd5b50336016541415612ccc57610140516016555b005b63e395dc656000511415612d315760206004610140373415612cef57600080fd5b60605160043580604051901358578091901215612d0b57600080fd5b50600161014051600060c052602060c0200160c052602060c020015460005260206000f3005b6312b2a50a6000511415612d945760206004610140373415612d5257600080fd5b60605160043580604051901358578091901215612d6e57600080fd5b50600361014051600060c052602060c0200160c052602060c020015460005260206000f3005b63fc2d45406000511415612df75760206004610140373415612db557600080fd5b60605160043580604051901358578091901215612dd157600080fd5b50600261014051600060c052602060c0200160c052602060c020015460005260206000f3005b635302508f6000511415612e575760206004610140373415612e1857600080fd5b60605160043580604051901358578091901215612e3457600080fd5b5061014051600060c052602060c0200160c052602060c0205460005260206000f3005b637601d5636000511415612eba5760206004610140373415612e7857600080fd5b60605160043580604051901358578091901215612e9457600080fd5b50600461014051600060c052602060c0200160c052602060c020015460005260206000f3005b639abcf69c6000511415612f125760206004610140373415612edb57600080fd5b60605160043580604051901358578091901215612ef757600080fd5b5061014051600160c052602060c020015460005260206000f3005b63363258856000511415612f38573415612f2b57600080fd5b60025460005260206000f3005b63e46cec606000511415612f855760206004610140373415612f5957600080fd5b6004356020518110612f6a57600080fd5b5061014051600360c052602060c020015460005260206000f3005b63a0b286d66000511415612fab573415612f9e57600080fd5b60045460005260206000f3005b632c7e5aa26000511415612fd1573415612fc457600080fd5b60055460005260206000f3005b63a5fd35156000511415612ff7573415612fea57600080fd5b60065460005260206000f3005b62bc82df600051141561304e576020600461014037341561301757600080fd5b6060516004358060405190135857809190121561303357600080fd5b5061014051600960c052602060c020015460005260206000f3005b635320e5ba60005114156130a6576020600461014037341561306f57600080fd5b6060516004358060405190135857809190121561308b57600080fd5b5061014051600a60c052602060c020015460005260206000f3005b63f64927c3600051141561313057604060046101403734156130c757600080fd5b606051600435806040519013585780919012156130e357600080fd5b506060516024358060405190135857809190121561310057600080fd5b506101605161014051600b60c052602060c0200160c052602060c02060c052602060c020015460005260206000f3005b6348e821a960005114156131bd576040600461014037341561315157600080fd5b6060516004358060405190135857809190121561316d57600080fd5b506060516024358060405190135857809190121561318a57600080fd5b5061016051600361014051600b60c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b6356b861a1600051141561325757606060046101403734156131de57600080fd5b606051600435806040519013585780919012156131fa57600080fd5b506060516044358060405190135857809190121561321757600080fd5b506101805161016051600461014051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b63668d56fd60005114156132ba576020600461014037341561327857600080fd5b6060516004358060405190135857809190121561329457600080fd5b50600261014051600b60c052602060c0200160c052602060c020015460005260206000f3005b63625f375b600051141561331d57602060046101403734156132db57600080fd5b606051600435806040519013585780919012156132f757600080fd5b50600161014051600b60c052602060c0200160c052602060c020015460005260206000f3005b633f98cdef600051141561334357341561333657600080fd5b600c5460005260206000f3005b63a219390b600051141561339b576020600461014037341561336457600080fd5b6060516004358060405190135857809190121561338057600080fd5b5061014051600d60c052602060c020015460005260206000f3005b63ef5212dd60005114156133c15734156133b457600080fd5b600e5460005260206000f3005b636a5df9f460005114156133e75734156133da57600080fd5b600f5460005260206000f3005b6305fb1083600051141561340d57341561340057600080fd5b60105460005260206000f3005b63c3826907600051141561343357341561342657600080fd5b60115460005260206000f3005b63837a9bc7600051141561345957341561344c57600080fd5b60125460005260206000f3005b63634d0f77600051141561347f57341561347257600080fd5b60135460005260206000f3005b638370f33860005114156134a557341561349857600080fd5b60145460005260206000f3005b63ffb7619b60005114156134cb5734156134be57600080fd5b60155460005260206000f3005b63350d3fae60005114156134f15734156134e457600080fd5b601a5460005260206000f3005b63fba2b1b3600051141561351757341561350a57600080fd5b601b5460005260206000f3005b63199dfefa600051141561353d57341561353057600080fd5b601c5460005260206000f3005b5b61022961376703610229600039610229613767036000f30000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000500000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1000000000000000000000000dffd41e18f04ad8810c83b14fd1426a82e625a7d0000000000000000000000009f56d05661285a8fcc0dbdb3c8070ad024030af3000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000005150ae84a8cdf00000 \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/casper/casper.lll b/ethereumj-core/src/main/resources/casper/casper.lll new file mode 100644 index 0000000000..55f236919d --- /dev/null +++ b/ethereumj-core/src/main/resources/casper/casper.lll @@ -0,0 +1,2666 @@ +[seq, + [mstore, 28, [calldataload, 0]], + [mstore, 32, 1461501637330902918203684832716283019655932542976], + [mstore, 64, 170141183460469231731687303715884105727], + [mstore, 96, -170141183460469231731687303715884105728], + [mstore, 128, 1701411834604692317316873037158841057270000000000], + [mstore, 160, -1701411834604692317316873037158841057280000000000], + # Line 116 + [codecopy, 320, ~codelen, 256], + [assert, [iszero, callvalue]], + /* checking num input */ + [clamp, + [mload, 96], + [codeload, ~codelen], + [mload, 64]], + /* checking num input */ + [clamp, + [mload, 96], + [codeload, [add, ~codelen, 32]], + [mload, 64]], + /* checking address input */ + [uclamplt, + [codeload, [add, ~codelen, 64]], + [mload, 32]], + /* checking address input */ + [uclamplt, + [codeload, [add, ~codelen, 96]], + [mload, 32]], + /* checking address input */ + [uclamplt, + [codeload, [add, ~codelen, 128]], + [mload, 32]], + /* checking num input */ + [clamp, + [mload, 96], + [codeload, [add, ~codelen, 224]], + [mload, 64]], + # Line 126 + [sstore, 16 , [mload, 320 <_epoch_length>]], + # Line 128 + [sstore, 17 , [mload, 352 <_withdrawal_delay>]], + # Line 130 + [sstore, 2 , 1], + # Line 132 + [sstore, 22 , [mload, 384 <_owner>]], + # Line 134 + [sstore, [sha3_32, 13 ], 100000000000000000000], + # Line 136 + [sstore, 4 , 0], + # Line 138 + [sstore, + 18 , + [clamp, + [mload, 96], + [sdiv, number, [clamp_nonzero, [sload, 16 ]]], + [mload, 64]]], + # Line 140 + [sstore, 24 , [mload, 416 <_sighasher>]], + # Line 142 + [sstore, 25 , [mload, 448 <_purity_checker>]], + # Line 145 + [sstore, 7 , 0], + # Line 146 + [sstore, 8 , 0], + # Line 148 + [sstore, 27 , [mload, 480 <_base_interest_factor>]], + # Line 149 + [sstore, 28 , [mload, 512 <_base_penalty_factor>]], + # Line 150 + [sstore, + 29 , + 44854244691294150128543874285586038746497872340133682954055806415933027209151], + # Line 152 + [sstore, 30 , [mload, 544 <_min_deposit_size>]], + [return, + 0, + [lll, + [seq, + [mstore, 28, [calldataload, 0]], + [mstore, 32, 1461501637330902918203684832716283019655932542976], + [mstore, 64, 170141183460469231731687303715884105727], + [mstore, 96, -170141183460469231731687303715884105728], + [mstore, 128, 1701411834604692317316873037158841057270000000000], + [mstore, 160, -1701411834604692317316873037158841057280000000000], + # Line 155 + [if, + [eq, [mload, 0], 2484158328 ], + [seq, + [assert, [iszero, callvalue]], + # Line 158 + [mstore, + 0, + [with, + _l, + [clamp, + [mload, 160], + [with, + l, + [sload, + [add, + [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [sload, 18 ]]]], + [sload, 21 ]]], + [with, + r, + [clamp_nonzero, [sload, 7 ]], + [sdiv, [mul, l, 10000000000], r]]], + [mload, 128]], + [with, + _r, + [clamp, + [mload, 160], + [with, + l, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [sload, 18 ]]], + 3 ]], + [sload, 21 ]]], + [with, + r, + [clamp_nonzero, [sload, 8 ]], + [sdiv, [mul, l, 10000000000], r]]], + [mload, 128]], + [if, [sgt, _l, _r], _r, _l]]]], + [return, 0, 32], + # Line 155 + stop]], + # Line 161 + [if, + [eq, [mload, 0], 2218461328 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 164 + [mstore, + 0, + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, + [add, + [sha3_32, 13 ], + [sload, 18 ]]], + [with, + l, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 1 ]], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 10000000000]], + [return, 0, 32], + # Line 161 + stop]], + # Line 166 + [if, + [eq, [mload, 0], 998321859 ], + [seq, + [assert, [iszero, callvalue]], + # Line 169 + [mstore, + 0, + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, + [add, + [sha3_32, 13 ], + [sload, 18 ]]], + [with, + l, + [sload, 7 ], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 10000000000]], + [return, 0, 32], + # Line 166 + stop]], + # Line 171 + [if, + [eq, [mload, 0], 1738402402 ], + [seq, + [assert, [iszero, callvalue]], + # Line 174 + [mstore, + 0, + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, + [add, + [sha3_32, 13 ], + [sload, 18 ]]], + [with, + l, + [sload, 8 ], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 10000000000]], + [return, 0, 32], + # Line 171 + stop]], + # Line 177 + [if, + [eq, [mload, 0], 2997763920 ], + [seq, + [assert, [iszero, callvalue]], + # Line 180 + [mstore, 0, [sload, 21 ]], + [return, 0, 32], + # Line 177 + stop]], + # Line 182 + [if, + [eq, [mload, 0], 3403399105 ], + [seq, + [assert, [iszero, callvalue]], + # Line 185 + [mstore, + 0, + [blockhash, + [uclamplt, + [clampge, + [clamp, + [mload, 96], + [sub, + [clamp, + [mload, 96], + [mul, [sload, 18 ], [sload, 16 ]], + [mload, 64]], + 1], + [mload, 64]], + [sub, number, 256]], + number]]], + [return, 0, 32], + # Line 182 + stop]], + # Line 187 + [if, + [eq, [mload, 0], 3732904309 ], + [seq, + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + # Line 190 + [mstore, + 0, + [and, + [sgt, [sload, 7 ], 0], + [sgt, [sload, 8 ], 0]]], + [return, 0, 32], + # Line 187 + stop]], + # Line 196 + [if, + [eq, [mload, 0], 3532045186 ], + [seq, + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + # Line 198 + [mstore, 320 , [sload, 18 ]], + # Line 200 + [if, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, 11 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 2], [mload, 64]]]], + 1 ]], + # Line 201 + [seq, + [with, + _stloc, + 4 , + [sstore, _stloc, [clamp, [mload, 96], [add, [sload, _stloc], 1], [mload, 64]]]], + # Line 202 + [sstore, + 8 , + [sload, 7 ]], + # Line 203 + [with, + _stloc, + 7 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [add, [sload, _stloc], [sload, 5 ]], + [mload, 128]]]], + # Line 204 + [sstore, + 5 , + [sload, 6 ]], + # Line 205 + [sstore, 6 , 0], + # Line 206 + [sstore, + [add, [sha3_32, 9 ], [sload, 4 ]], + [mload, 320 ]]]], + # Line 207 + [sstore, + [add, [sha3_32, 10 ], [mload, 320 ]], + [sload, 4 ]], + # Line 208 + [if, + [sload, 12 ], + # Line 209 + [seq, + [sstore, + 21 , + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]]], + # Line 210 + [sstore, 12 , 0], + # Line 196 + stop]], + # Line 213 + [if, + [eq, [mload, 0], 4200925994 ], + [seq, + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + # Line 215 + [mstore, 320 , [sload, 18 ]], + # Line 216 + [mstore, + 0, + [clamp, + [mload, 96], + [sub, [mload, 320 ], [sload, 19 ]], + [mload, 64]]], + [return, 0, 32], + # Line 213 + stop]], + # Line 219 + [if, + [eq, [mload, 0], 1890537662 ], + [seq, + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + # Line 221 + [mstore, 320 , [sload, 18 ]], + # Line 222 + [mstore, + 480 , + [sle, + [mload, + /* Internal Call: get_esf */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 352, 4200925994], 380], 4, 448, 32]], + 448]], + 2]], + # Line 223 + [if, + [or, + [iszero, + [mload, + /* Internal Call: deposit_exists */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 512, 3732904309], 540], 4, 608, 32]], + 608]]], + [iszero, [mload, 480 ]]], + # Line 224 + [seq, [mstore, 0, 0], [return, 0, 32]]], + # Line 226 + [mstore, + 640 , + [clamp, + [mload, 160], + [with, + l, + [sload, + [add, + [sha3_32, + [sha3_32, + [add, + [sha3_32, 11 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]]], + [sload, 21 ]]], + [with, + r, + [clamp_nonzero, [sload, 7 ]], + [sdiv, [mul, l, 10000000000], r]]], + [mload, 128]]], + # Line 227 + [mstore, + 672 , + [clamp, + [mload, 160], + [with, + l, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, + [add, + [sha3_32, 11 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], + 3 ]], + [sload, 21 ]]], + [with, + r, + [clamp_nonzero, [sload, 8 ]], + [sdiv, [mul, l, 10000000000], r]]], + [mload, 128]]], + # Line 228 + [mstore, + 704 , + [with, + _l, + [mload, 640 ], + [with, _r, [mload, 672 ], [if, [sgt, _l, _r], _r, _l]]]], + # Line 229 + [mstore, + 0, + [clamp, + [mload, 160], + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, 26 ], + [with, + l, + [mload, 704 ], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 2], + [mload, 128]]], + [return, 0, 32], + # Line 219 + stop]], + # Line 231 + [if, + [eq, [mload, 0], 1697049970 ], + [seq, + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + # Line 233 + [mstore, 320 , [sload, 18 ]], + # Line 234 + [sstore, 12 , 1], + # Line 235 + [sstore, + [add, + [sha3_32, + [add, + [sha3_32, 11 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], + 2 ], + 1], + # Line 236 + [sstore, + [add, + [sha3_32, + [add, + [sha3_32, 11 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], + 1 ], + 1], + # Line 237 + [sstore, + 20 , + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]], + # Line 238 + [sstore, + 19 , + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]], + # Line 231 + stop]], + # Line 241 + [if, + [eq, [mload, 0], 2609002115 ], + [seq, + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + # Line 243 + [mstore, 320 , [sload, 18 ]], + # Line 244 + [mstore, + 352 , + [clamp, + [mload, 96], + [add, + [sdiv, + [clamp, + [mload, 160], + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, + [add, + [sha3_32, 13 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], + [with, + l, + [with, + _l, + [sload, 8 ], + [with, + _r, + [sload, 7 ], + [if, [slt, _l, _r], _r, _l]]], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 1000000000000000000], + [mload, 128]], + 10000000000], + 1], + [mload, 64]]], + # Line 246 + [mstore, + 384 , + [clamp, + [mload, 160], + [sdiv, + [mul, [mload, 352 ], 100000000000000000000], + 20000000000], + [mload, 128]]], + # Line 247 + [repeat, + 416, + 0, + 20, + [seq, + [mstore, + 384 , + [clamp, + [mload, 160], + [sdiv, + [clamp, + [mload, 160], + [add, + [mload, 384 ], + [clamp, + [mload, 160], + [sdiv, + [mul, [mload, 352 ], 100000000000000000000], + [clamp_nonzero, [mload, 384 ]]], + [mload, 128]]], + [mload, 128]], + 2], + [mload, 128]]]]], + # Line 249 + [mstore, 0, [mload, 384 ]], + [return, 0, 32], + # Line 241 + stop]], + # Line 254 + [if, + [eq, [mload, 0], 1573911575 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 257 + [mstore, + 352 , + [clamp, + [mload, 96], + [sdiv, number, [clamp_nonzero, [sload, 16 ]]], + [mload, 64]]], + # Line 258 + [assert, + [and, + [sle, [mload, 320 ], [mload, 352 ]], + [eq, + [mload, 320 ], + [clamp, [mload, 96], [add, [sload, 18 ], 1], [mload, 64]]]]], + # Line 261 + [sstore, 18 , [mload, 320 ]], + # Line 264 + [sstore, + 14 , + [clamp, + [mload, 160], + [sub, + [clamp, + [mload, 160], + [add, + 10000000000, + [mload, + /* Internal Call: get_collective_reward */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 384, 1890537662], 412], 4, 480, 32]], + 480]]], + [mload, 128]], + [sload, 26 ]], + [mload, 128]]], + # Line 265 + [sstore, + 15 , + [clamp, + [mload, 160], + [with, + r, + [clamp, + [mload, 160], + [add, 10000000000, [sload, 26 ]], + [mload, 128]], + [with, + l, + [sload, 14 ], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]]], + # Line 266 + [sstore, + [add, [sha3_32, 13 ], [mload, 320 ]], + [clamp, + [mload, 160], + [with, + r, + [sload, 14 ], + [with, + l, + [sload, + [add, + [sha3_32, 13 ], + [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]]], + # Line 268 + [if, + [mload, + /* Internal Call: deposit_exists */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 608, 3732904309], 636], 4, 704, 32]], + 704]], + # Line 270 + [seq, + [mstore, + 864 , + [clamp, + [mload, 160], + [with, + l, + [sload, 27 ], + [with, + r, + [clamp_nonzero, + [mload, + /* Internal Call: get_sqrt_of_total_deposits */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 736, 2609002115], 764], 4, 832, 32]], + 832]]], + [sdiv, [mul, l, 10000000000], r]]], + [mload, 128]]], + # Line 271 + [sstore, + 26 , + [clamp, + [mload, 160], + [add, + [mload, 864 ], + [clamp, + [mload, 160], + [with, + r, + [mload, + /* Internal Call: get_esf */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 896, 4200925994], 924], 4, 992, 32]], + 992]], + [with, + l, + [sload, 28 ], + [with, + ans, + [mul, l, r], + [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], + [mload, 128]]], + [mload, 128]]], + # Line 273 + [assert, [sgt, [sload, 26 ], 0]]], + # Line 275 + [seq, + /* Internal Call: insta_finalize */ [assert, [call, gas, address, 0, [seq, [mstore, 512, 1697049970], 540], 4, 0, 0]], + # Line 276 + [sstore, 26 , 0]]], + # Line 279 + /* Internal Call: increment_dynasty */ [assert, [call, gas, address, 0, [seq, [mstore, 1024, 3532045186], 1052], 4, 0, 0]], + # Line 282 + [sstore, + [add, [sha3_32, 1 ], [mload, 320 ]], + [mload, + /* Internal Call: get_recommended_target_hash */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 1120, 3403399105], 1148], 4, 1216, 32]], + 1216]]], + # Line 254 + stop]], + # Line 285 + [if, + [eq, [mload, 0], 4183858952 ], + [seq, + [calldatacopy, 320, 4, 64], + /* checking address input */ [uclamplt, [calldataload, 4], [mload, 32]], + /* checking address input */ [uclamplt, [calldataload, 36], [mload, 32]], + # Line 288 + [assert, + [eq, + [sload, 18 ], + [clamp, + [mload, 96], + [sdiv, number, [clamp_nonzero, [sload, 16 ]]], + [mload, 64]]]], + # Line 289 + [assert, + [ne, + /* extracting 32 bytes */ + [with, + _sub, + [seq, + [with, + _source, + /* concat */ + [with, + _poz, + 0, + [seq, + [with, + _arg, + [seq, + [mstore, 384, 4], + [mstore, + 416, + 73077227117658356969279410473650150870559631135483570926313946830681982107648], + 384], + [seq, + /* copy byte slice */ + [with, + _l, + 4, + [pop, [call, 18, 4, 0, [add, _arg, 32], _l, [add, [add, 480, _poz], 32], _l]]], + [set, _poz, [add, _poz, [mload, _arg]]]]], + [mstore, [add, [add, 480, _poz], 32], [mload, 320 ]], + [set, _poz, [add, _poz, 32]], + [mstore, 480, _poz], + 480]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 608, _sz]]]], + [assert, + [call, + 500000, + [sload, 25 ], + 0, + 640, + [mload, 608], + 768, + 32]], + [mstore, 736, 32], + 736], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], + 0]], + # Line 290 + [assert, [iszero, [sload, [add, [sha3_32, 3 ], [mload, 352 ]]]]], + # Line 291 + [assert, [sge, callvalue, [sload, 30 ]]], + # Line 292 + [with, + _L, + [sha3_32, [add, [sha3_32, 0 ], [sload, 2 ]]], + [seq, + [sstore, _L, [mload, 320 ]], + [sstore, + [add, _L, 1 ], + [clamp, + [mload, 160], + [sdiv, + [mul, callvalue, 100000000000000000000], + [clamp_nonzero, + [sload, + [add, + [sha3_32, 13 ], + [sload, 18 ]]]]], + [mload, 128]]], + [sstore, [add, _L, 2 ], 1000000000000000000000000000000], + [sstore, + [add, _L, 3 ], + [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]], + [sstore, [add, _L, 4 ], [mload, 352 ]]]], + # Line 299 + [sstore, + [add, [sha3_32, 3 ], [mload, 352 ]], + [sload, 2 ]], + # Line 300 + [with, + _stloc, + 2 , + [sstore, _stloc, [clamp, [mload, 96], [add, [sload, _stloc], 1], [mload, 64]]]], + # Line 301 + [with, + _stloc, + 6 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [add, + [sload, _stloc], + [clamp, + [mload, 160], + [sdiv, + [mul, callvalue, 100000000000000000000], + [clamp_nonzero, + [sload, + [add, + [sha3_32, 13 ], + [sload, 18 ]]]]], + [mload, 128]]], + [mload, 128]]]], + # Line 285 + stop]], + # Line 306 + [if, + [eq, [mload, 0], 1110510642 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + [calldatacopy, 352, [add, 4, [calldataload, 4]], 1056], + [assert, [le, [calldataload, [add, 4, [calldataload, 4]]], 1024]], + # Line 308 + [assert, + [eq, + [sload, 18 ], + [clamp, + [mload, 96], + [sdiv, number, [clamp_nonzero, [sload, 16 ]]], + [mload, 64]]]], + # Line 311 + [mstore, + 2624 , + [with, + _sub, + [seq, + [with, + _source, + 352 , + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 1440, _sz]]]], + [assert, [call, 200000, [sload, 24 ], 0, 1472, [mload, 1440], 2560, 32]], + [mstore, 2528, 32], + 2528], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], + # Line 313 + [with, + _L, + 4096 , + [seq, + [mstore, + _L, + [seq, + [with, + _sub, + 352 , + [pop, + [call, + 2720, + 611804413765252988754013619680738151377063423597 , + 0, + [add, _sub, 32], + [mload, _sub], + 2656, + 1376]]], + [assert, [eq, [mload, 2656], 128]], + /* bytearray to number, verify no leading zbytes */ + [with, + _sub, + /* getting and checking num */ [add, 2656, [mload, 2656]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], + [mstore, + [add, 32, _L], + [with, + _sub, + /* getting and checking num */ [add, 2656, [mload, 2688]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [with, + _source, + /* getting byte array */ [add, 2656, [mload, 2720]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 64, _L], _sz]]]]]], + # Line 314 + [mstore, 5248 , [mload, 4096 <0+values>]], + # Line 315 + [mstore, 5280 , [mload, 4128 <32+values>]], + # Line 316 + [with, + _source, + 4160 <64+values>, + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 5312 , _sz]]]], + # Line 317 + [assert, [sge, [sload, 18 ], [mload, 5280 ]]], + # Line 319 + [assert, + [eq, + /* extracting 32 bytes */ + [with, + _sub, + [seq, + [with, + _source, + /* concat */ + [with, + _poz, + 0, + [seq, + [mstore, [add, [add, 6400, _poz], 32], [mload, 2624 ]], + [set, _poz, [add, _poz, 32]], + [with, + _arg, + 5312 , + [seq, + /* copy byte slice */ + [with, + _l, + 1024, + [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 6400, _poz], 32], _l]]], + [set, _poz, [add, _poz, [mload, _arg]]]]], + [mstore, 6400, _poz], + 6400]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 7520, _sz]]]], + [assert, + [call, + 500000, + [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]]], + 0, + 7552, + [mload, 7520], + 8672, + 32]], + [mstore, 8640, 32], + 8640], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], + 1]], + # Line 321 + [assert, + [sgt, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]], + 2 ]], + [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]]], + # Line 323 + [sstore, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]], + 2 ], + [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]], + # Line 324 + [with, + _stloc, + 6 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [sub, + [sload, _stloc], + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]], + 1 ]]], + [mload, 128]]]], + # Line 306 + stop]], + # Line 327 + [if, + [eq, [mload, 0], 28815128 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 329 + [if, + [sgt, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 2 ]], + [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]], + # Line 330 + [seq, + [with, + _stloc, + 5 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [sub, + [sload, _stloc], + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 1 ]]], + [mload, 128]]]]]], + # Line 331 + [sstore, + [add, + [sha3_32, 3 ], + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 4 ]]], + 0], + # Line 332 + [with, + _L, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + [seq, + [sstore, _L, 0], + [sstore, [add, _L, 1 ], 0], + [sstore, [add, _L, 2 ], 0], + [sstore, [add, _L, 3 ], 0], + [sstore, [add, _L, 4 ], 0]]], + # Line 327 + stop]], + # Line 341 + [if, + [eq, [mload, 0], 3991540864 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 344 + [assert, + [sge, + [sload, 4 ], + [clamp, + [mload, 96], + [add, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 2 ]], + 1], + [mload, 64]]]], + # Line 345 + [mstore, + 352 , + [sload, + [add, + [sha3_32, 9 ], + [clamp, + [mload, 96], + [add, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 2 ]], + 1], + [mload, 64]]]]], + # Line 346 + [assert, + [sge, + [sload, 18 ], + [clamp, + [mload, 96], + [add, [mload, 352 ], [sload, 17 ]], + [mload, 64]]]], + # Line 348 + [mstore, + 384 , + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, [add, [sha3_32, 13 ], [mload, 352 ]]], + [with, + l, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 1 ]], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 10000000000]], + # Line 349 + [assert, + [call, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 4 ]], + [mload, 384 ], + 0, + 0, + 0, + 0]], + # Line 350 + /* Internal Call: delete_validator */ + [assert, + [call, + gas, + address, + 0, + [seq, + [mstore, 416, 28815128], + [mstore, 448, [mload, 320 ]], + 444], + 36, + 0, + 0]], + # Line 341 + stop]], + # Line 353 + [if, + [eq, [mload, 0], 1470052530 ], + [seq, + [calldatacopy, 320, 4, 64], + [assert, [iszero, callvalue]], + [assert, [eq, caller, address]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 36], [mload, 64]], + # Line 355 + [mstore, + 384 , + [sload, + [add, + [sha3_32, 9 ], + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 3 ]]]]], + # Line 356 + [with, + _stloc, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 1 ], + [sstore, + _stloc, + [clamp, + [mload, 160], + [add, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], + [mload, 128]]]], + # Line 357 + [mstore, + 416 , + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 3 ]]], + # Line 358 + [mstore, + 448 , + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 2 ]]], + # Line 359 + [mstore, 480 , [sload, 4 ]], + # Line 360 + [mstore, + 512 , + [clamp, [mload, 96], [sub, [mload, 480 ], 1], [mload, 64]]], + # Line 361 + [if, + [and, + [sle, [mload, 416 ], [mload, 480 ]], + [slt, [mload, 480 ], [mload, 448 ]]], + # Line 362 + [seq, + [with, + _stloc, + 7 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [add, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], + [mload, 128]]]]]], + # Line 363 + [if, + [and, + [sle, [mload, 416 ], [mload, 512 ]], + [slt, [mload, 512 ], [mload, 448 ]]], + # Line 364 + [seq, + [with, + _stloc, + 8 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [add, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], + [mload, 128]]]]]], + # Line 365 + [if, + [eq, + [mload, 480 ], + [clamp, [mload, 96], [sub, [mload, 448 ], 1], [mload, 64]]], + # Line 366 + [seq, + [with, + _stloc, + 5 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [sub, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], + [mload, 128]]]]]], + # Line 367 + [if, + [eq, + [mload, 480 ], + [clamp, [mload, 96], [sub, [mload, 448 ], 2], [mload, 64]]], + # Line 368 + [seq, + [with, + _stloc, + 6 , + [sstore, + _stloc, + [clamp, + [mload, 160], + [sub, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], + [mload, 128]]]]]], + # Line 369 + [assert, + [call, + 0, + coinbase, + [sdiv, + [clamp, + [mload, 160], + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, + [add, + [sha3_32, 13 ], + [sload, 18 ]]], + [with, + l, + [mload, 352 ], + [with, + ans, + [mul, l, r], + [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], + [mload, 128]], + 8], + [mload, 128]], + 10000000000], + 0, + 0, + 0, + 0]], + # Line 353 + stop]], + # Line 372 + [if, + [eq, [mload, 0], 3923510804 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + [calldatacopy, 352, [add, 4, [calldataload, 4]], 1056], + [assert, [le, [calldataload, [add, 4, [calldataload, 4]]], 1024]], + # Line 376 + [mstore, + 2624 , + [with, + _sub, + [seq, + [with, + _source, + 352 , + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 1440, _sz]]]], + [assert, [call, 200000, [sload, 24 ], 0, 1472, [mload, 1440], 2560, 32]], + [mstore, 2528, 32], + 2528], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], + # Line 378 + [with, + _L, + 4288 , + [seq, + [mstore, + _L, + [seq, + [with, + _sub, + 352 , + [pop, + [call, + 3520, + 611804413765252988754013619680738151377063423597 , + 0, + [add, _sub, 32], + [mload, _sub], + 2656, + 1568]]], + [assert, [eq, [mload, 2656], 192]], + /* bytearray to number, verify no leading zbytes */ + [with, + _sub, + /* getting and checking num */ [add, 2656, [mload, 2656]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], + [mstore, + [add, 32, _L], + [seq, + [assert, [eq, [mload, [add, 2656, [mload, 2688]]], 32]], + [mload, [add, 2688, [mload, 2688]]]]], + [mstore, + [add, 64, _L], + [with, + _sub, + /* getting and checking num */ [add, 2656, [mload, 2720]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [mstore, + [add, 96, _L], + [with, + _sub, + /* getting and checking num */ [add, 2656, [mload, 2752]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [with, + _source, + /* getting byte array */ [add, 2656, [mload, 2784]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 128, _L], _sz]]]]]], + # Line 379 + [mstore, 5504 , [mload, 4288 <0+values>]], + # Line 380 + [mstore, 5536 , [mload, 4320 <32+values>]], + # Line 381 + [mstore, 5568 , [mload, 4352 <64+values>]], + # Line 382 + [mstore, 5600 , [mload, 4384 <96+values>]], + # Line 383 + [with, + _source, + 4416 <128+values>, + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 5632 , _sz]]]], + # Line 385 + [assert, + [eq, + /* extracting 32 bytes */ + [with, + _sub, + [seq, + [with, + _source, + /* concat */ + [with, + _poz, + 0, + [seq, + [mstore, [add, [add, 6720, _poz], 32], [mload, 2624 ]], + [set, _poz, [add, _poz, 32]], + [with, + _arg, + 5632 , + [seq, + /* copy byte slice */ + [with, + _l, + 1024, + [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 6720, _poz], 32], _l]]], + [set, _poz, [add, _poz, [mload, _arg]]]]], + [mstore, 6720, _poz], + 6720]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 7840, _sz]]]], + [assert, + [call, + 500000, + [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]]], + 0, + 7872, + [mload, 7840], + 8992, + 32]], + [mstore, 8960, 32], + 8960], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], + 1]], + # Line 387 + [assert, + [iszero, + [and, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 4 ]], + [mload, 5536 ]]], + [clamp, [mload, 96], [sdiv, [mload, 5504 ], 256], [mload, 64]]]], + [with, + _v, + 1, + [with, + _s, + [clamp, [mload, 96], [smod, [mload, 5504 ], 256], [mload, 64]], + [if, [sle, _s, 0], [div, _v, [exp, 2, [sub, 0, _s]]], [mul, _v, [exp, 2, _s]]]]]]]], + # Line 390 + [assert, + [eq, + [mload, 5536 ], + [mload, + /* Internal Call: get_recommended_target_hash */ + [seq, + [assert, [call, gas, address, 0, [seq, [mstore, 9056, 3403399105], 9084], 4, 9152, 32]], + 9152]]]], + # Line 392 + [assert, + [sload, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5600 ]]], + 2 ]]], + # Line 396 + [mstore, + 9184 , + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], + 3 ]]], + # Line 398 + [mstore, + 9216 , + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], + 2 ]]], + # Line 400 + [mstore, + 9248 , + [sload, [add, [sha3_32, 10 ], [mload, 5568 ]]]], + # Line 401 + [mstore, + 9280 , + [clamp, [mload, 96], [sub, [mload, 9248 ], 1], [mload, 64]]], + # Line 402 + [mstore, + 9312 , + [and, + [sle, [mload, 9184 ], [mload, 9248 ]], + [slt, [mload, 9248 ], [mload, 9216 ]]]], + # Line 403 + [mstore, + 9344 , + [and, + [sle, [mload, 9184 ], [mload, 9280 ]], + [slt, [mload, 9280 ], [mload, 9216 ]]]], + # Line 404 + [assert, [or, [mload, 9312 ], [mload, 9344 ]]], + # Line 406 + [sstore, + [add, + [sha3_32, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 4 ]], + [mload, 5536 ]]], + [clamp, [mload, 96], [sdiv, [mload, 5504 ], 256], [mload, 64]]], + [or, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 4 ]], + [mload, 5536 ]]], + [clamp, [mload, 96], [sdiv, [mload, 5504 ], 256], [mload, 64]]]], + [with, + _v, + 1, + [with, + _s, + [clamp, [mload, 96], [smod, [mload, 5504 ], 256], [mload, 64]], + [if, [sle, _s, 0], [div, _v, [exp, 2, [sub, 0, _s]]], [mul, _v, [exp, 2, _s]]]]]]], + # Line 410 + [mstore, + 9376 , + [sload, + [add, + [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]]], + [mload, 5600 ]]]], + # Line 411 + [mstore, + 9408 , + [sload, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 3 ]], + [mload, 5600 ]]]], + # Line 412 + [if, + [mload, 9312 ], + # Line 413 + [seq, + [with, + _mloc, + 9376 , + [mstore, + _mloc, + [clamp, + [mload, 160], + [add, + [mload, _mloc], + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], + 1 ]]], + [mload, 128]]]], + # Line 414 + [sstore, + [add, + [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]]], + [mload, 5600 ]], + [mload, 9376 ]]]], + # Line 415 + [if, + [mload, 9344 ], + # Line 416 + [seq, + [with, + _mloc, + 9408 , + [mstore, + _mloc, + [clamp, + [mload, 160], + [add, + [mload, _mloc], + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], + 1 ]]], + [mload, 128]]]], + # Line 417 + [sstore, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 3 ]], + [mload, 5600 ]], + [mload, 9408 ]]]], + # Line 421 + [if, + [and, + [eq, [sload, 18 ], [mload, 5568 ]], + [eq, [sload, 21 ], [mload, 5600 ]]], + # Line 422 + [seq, + [mstore, + 9440 , + [sdiv, + [clamp, + [mload, 160], + [with, + r, + [sload, 26 ], + [with, + l, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], + 1 ]], + [with, + ans, + [mul, l, r], + [seq, + [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], + [sdiv, ans, 10000000000]]]]], + [mload, 128]], + 10000000000]], + # Line 423 + /* Internal Call: proc_reward */ + [assert, + [call, + gas, + address, + 0, + [seq, + [mstore, 9472, 1470052530], + [mstore, 9504, [mload, 5504 ]], + [mstore, 9536, [mload, 9440 ]], + 9500], + 68, + 0, + 0]]]], + # Line 426 + [if, + [and, + [and, + [sge, + [mload, 9376 ], + [clamp, + [mload, 160], + [sdiv, + [clamp, + [mload, 160], + [with, + r, + 2, + [with, + l, + [sload, 7 ], + [with, + ans, + [mul, l, r], + [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], + [mload, 128]], + 3], + [mload, 128]]], + [sge, + [mload, 9408 ], + [clamp, + [mload, 160], + [sdiv, + [clamp, + [mload, 160], + [with, + r, + 2, + [with, + l, + [sload, 8 ], + [with, + ans, + [mul, l, r], + [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], + [mload, 128]], + 3], + [mload, 128]]]], + [iszero, + [sload, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 2 ]]]], + # Line 429 + [seq, + [sstore, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], + 2 ], + 1], + # Line 430 + [sstore, 20 , [mload, 5568 ]], + # Line 431 + [if, + [eq, [mload, 5568 ], [sload, 18 ]], + # Line 432 + [seq, [sstore, 12 , 1]]], + # Line 435 + [if, + [eq, + [mload, 5568 ], + [clamp, [mload, 96], [add, [mload, 5600 ], 1], [mload, 64]]], + # Line 436 + [seq, + [sstore, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 5600 ]]], + 1 ], + 1], + # Line 437 + [sstore, 19 , [mload, 5600 ]]]]]], + # Line 438 + [with, + _arr, + 352 , + [log1, [add, _arr, 32], [mload, _arr], [sload, 29 ]]], + # Line 372 + stop]], + # Line 441 + [if, + [eq, [mload, 0], 3424711019 ], + [seq, + [calldatacopy, 320, 4, 64], + [assert, [iszero, callvalue]], + [calldatacopy, 384, [add, 4, [calldataload, 4]], 1056], + [assert, [le, [calldataload, [add, 4, [calldataload, 4]]], 1024]], + [calldatacopy, 1472, [add, 4, [calldataload, 36]], 1056], + [assert, [le, [calldataload, [add, 4, [calldataload, 36]]], 1024]], + # Line 444 + [mstore, + 3744 , + [with, + _sub, + [seq, + [with, + _source, + 384 , + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 2560, _sz]]]], + [assert, [call, 200000, [sload, 24 ], 0, 2592, [mload, 2560], 3680, 32]], + [mstore, 3648, 32], + 3648], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], + # Line 445 + [with, + _L, + 5408 , + [seq, + [mstore, + _L, + [seq, + [with, + _sub, + 384 , + [pop, + [call, + 3520, + 611804413765252988754013619680738151377063423597 , + 0, + [add, _sub, 32], + [mload, _sub], + 3776, + 1568]]], + [assert, [eq, [mload, 3776], 192]], + /* bytearray to number, verify no leading zbytes */ + [with, + _sub, + /* getting and checking num */ [add, 3776, [mload, 3776]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], + [mstore, + [add, 32, _L], + [seq, + [assert, [eq, [mload, [add, 3776, [mload, 3808]]], 32]], + [mload, [add, 3808, [mload, 3808]]]]], + [mstore, + [add, 64, _L], + [with, + _sub, + /* getting and checking num */ [add, 3776, [mload, 3840]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [mstore, + [add, 96, _L], + [with, + _sub, + /* getting and checking num */ [add, 3776, [mload, 3872]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [with, + _source, + /* getting byte array */ [add, 3776, [mload, 3904]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 128, _L], _sz]]]]]], + # Line 446 + [mstore, 6624 , [mload, 5408 <0+values>]], + # Line 447 + [mstore, 6656 , [mload, 5472 <64+values>]], + # Line 448 + [mstore, 6688 , [mload, 5504 <96+values>]], + # Line 449 + [with, + _source, + 5536 <128+values>, + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 6720 , _sz]]]], + # Line 451 + [assert, + [eq, + /* extracting 32 bytes */ + [with, + _sub, + [seq, + [with, + _source, + /* concat */ + [with, + _poz, + 0, + [seq, + [mstore, [add, [add, 7808, _poz], 32], [mload, 3744 ]], + [set, _poz, [add, _poz, 32]], + [with, + _arg, + 6720 , + [seq, + /* copy byte slice */ + [with, + _l, + 1024, + [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 7808, _poz], 32], _l]]], + [set, _poz, [add, _poz, [mload, _arg]]]]], + [mstore, 7808, _poz], + 7808]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 8928, _sz]]]], + [assert, + [call, + 500000, + [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 6624 ]]]], + 0, + 8960, + [mload, 8928], + 10080, + 32]], + [mstore, 10048, 32], + 10048], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], + 1]], + # Line 453 + [mstore, + 11328 , + [with, + _sub, + [seq, + [with, + _source, + 1472 , + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 10144, _sz]]]], + [assert, + [call, + 200000, + [sload, 24 ], + 0, + 10176, + [mload, 10144], + 11264, + 32]], + [mstore, 11232, 32], + 11232], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], + # Line 454 + [with, + _L, + 5408 , + [seq, + [mstore, + _L, + [seq, + [with, + _sub, + 1472 , + [pop, + [call, + 3520, + 611804413765252988754013619680738151377063423597 , + 0, + [add, _sub, 32], + [mload, _sub], + 11360, + 1568]]], + [assert, [eq, [mload, 11360], 192]], + /* bytearray to number, verify no leading zbytes */ + [with, + _sub, + /* getting and checking num */ [add, 11360, [mload, 11360]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], + [mstore, + [add, 32, _L], + [seq, + [assert, [eq, [mload, [add, 11360, [mload, 11392]]], 32]], + [mload, [add, 11392, [mload, 11392]]]]], + [mstore, + [add, 64, _L], + [with, + _sub, + /* getting and checking num */ [add, 11360, [mload, 11424]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [mstore, + [add, 96, _L], + [with, + _sub, + /* getting and checking num */ [add, 11360, [mload, 11456]], + [with, + _el1, + [mload, [add, 32, _sub]], + [with, + _len, + [clamp, 0, [mload, _sub], 32], + [seq, + [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], + [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], + [with, + _source, + /* getting byte array */ [add, 11360, [mload, 11488]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 128, _L], _sz]]]]]], + # Line 455 + [mstore, 12992 , [mload, 5408 <0+values>]], + # Line 456 + [mstore, 13024 , [mload, 5472 <64+values>]], + # Line 457 + [mstore, 13056 , [mload, 5504 <96+values>]], + # Line 458 + [with, + _source, + 5536 <128+values>, + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 13088 , _sz]]]], + # Line 460 + [assert, + [eq, + /* extracting 32 bytes */ + [with, + _sub, + [seq, + [with, + _source, + /* concat */ + [with, + _poz, + 0, + [seq, + [mstore, [add, [add, 14176, _poz], 32], [mload, 11328 ]], + [set, _poz, [add, _poz, 32]], + [with, + _arg, + 13088 , + [seq, + /* copy byte slice */ + [with, + _l, + 1024, + [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 14176, _poz], 32], _l]]], + [set, _poz, [add, _poz, [mload, _arg]]]]], + [mstore, 14176, _poz], + 14176]], + [with, + _sz, + [add, 32, [mload, _source]], + [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 15296, _sz]]]], + [assert, + [call, + 500000, + [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 12992 ]]]], + 0, + 15328, + [mload, 15296], + 16448, + 32]], + [mstore, 16416, 32], + 16416], + [mload, + [add, + _sub, + [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], + 1]], + # Line 462 + [assert, [eq, [mload, 6624 ], [mload, 12992 ]]], + # Line 464 + [assert, [ne, [mload, 3744 ], [mload, 11328 ]]], + # Line 466 + [mstore, 16512 , 0], + # Line 467 + [if, + [eq, [mload, 6656 ], [mload, 13024 ]], + # Line 469 + [seq, [mstore, 16512 , 1]], + # Line 470 + [seq, + [if, + [or, + [and, + [sgt, [mload, 6656 ], [mload, 13024 ]], + [slt, [mload, 6688 ], [mload, 13056 ]]], + [and, + [sgt, [mload, 13024 ], [mload, 6656 ]], + [slt, [mload, 13056 ], [mload, 6688 ]]]], + # Line 473 + [seq, [mstore, 16512 , 1]]]]], + # Line 474 + [assert, [mload, 16512 ]], + # Line 476 + [mstore, + 16704 , + [mload, + /* Internal Call: get_deposit_size */ + [seq, + [assert, + [call, + gas, + address, + 0, + [seq, + [mstore, 16544, 2218461328], + [mstore, 16576, [mload, 6624 ]], + 16572], + 36, + 16672, + 32]], + 16672]]], + # Line 477 + [mstore, + 16736 , + [clamp, + [mload, 96], + [sdiv, [mload, 16704 ], 25], + [mload, 64]]], + # Line 478 + [with, + _stloc, + 23 , + [sstore, + _stloc, + [clamp, + [mload, 96], + [add, + [sload, _stloc], + [clamp, + [mload, 96], + [sdiv, + [clamp, + [mload, 96], + [mul, [mload, 16704 ], 24], + [mload, 64]], + 25], + [mload, 64]]], + [mload, 64]]]], + # Line 479 + /* Internal Call: delete_validator */ + [assert, + [call, + gas, + address, + 0, + [seq, + [mstore, 16768, 28815128], + [mstore, 16800, [mload, 6624 ]], + 16796], + 36, + 0, + 0]], + # Line 480 + [assert, [call, 0, caller, [mload, 16736 ], 0, 0, 0, 0]], + # Line 441 + stop]], + # Line 483 + [if, + [eq, [mload, 0], 888093169 ], + [seq, + [assert, [iszero, callvalue]], + # Line 485 + [assert, + [call, + 0, + [sload, 22 ], + [sload, 23 ], + 0, + 0, + 0, + 0]], + # Line 486 + [sstore, 23 , 0], + # Line 483 + stop]], + # Line 489 + [if, + [eq, [mload, 0], 624724948 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking address input */ [uclamplt, [calldataload, 4], [mload, 32]], + # Line 491 + [if, + [eq, [sload, 22 ], caller], + # Line 492 + [seq, [sstore, 22 , [mload, 320 ]]]], + # Line 489 + stop]], + # Line 2 + [if, + [eq, [mload, 0], 3818249317 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 4 + [mstore, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 1 ]]], + [return, 0, 32], + # Line 2 + stop]], + [if, + [eq, [mload, 0], 313697546 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 4 + [mstore, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 3 ]]], + [return, 0, 32], + # Line 2 + stop]], + [if, + [eq, [mload, 0], 4230825280 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 4 + [mstore, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 2 ]]], + [return, 0, 32], + # Line 2 + stop]], + [if, + [eq, [mload, 0], 1392660623 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 4 + [mstore, + 0, + [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]]]], + [return, 0, 32], + # Line 2 + stop]], + [if, + [eq, [mload, 0], 1979831651 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 4 + [mstore, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], + 4 ]]], + [return, 0, 32], + # Line 2 + stop]], + # Line 17 + [if, + [eq, [mload, 0], 2596075164 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 19 + [mstore, + 0, + [sload, [add, [sha3_32, 1 ], [mload, 320 ]]]], + [return, 0, 32], + # Line 17 + stop]], + # Line 20 + [if, + [eq, [mload, 0], 909269125 ], + [seq, + [assert, [iszero, callvalue]], + # Line 22 + [mstore, 0, [sload, 2 ]], + [return, 0, 32], + # Line 20 + stop]], + # Line 23 + [if, + [eq, [mload, 0], 3832343648 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking address input */ [uclamplt, [calldataload, 4], [mload, 32]], + # Line 25 + [mstore, + 0, + [sload, [add, [sha3_32, 3 ], [mload, 320 ]]]], + [return, 0, 32], + # Line 23 + stop]], + # Line 26 + [if, + [eq, [mload, 0], 2696054486 ], + [seq, + [assert, [iszero, callvalue]], + # Line 28 + [mstore, 0, [sload, 4 ]], + [return, 0, 32], + # Line 26 + stop]], + # Line 29 + [if, + [eq, [mload, 0], 746478242 ], + [seq, + [assert, [iszero, callvalue]], + # Line 31 + [mstore, 0, [sload, 5 ]], + [return, 0, 32], + # Line 29 + stop]], + # Line 32 + [if, + [eq, [mload, 0], 2784834837 ], + [seq, + [assert, [iszero, callvalue]], + # Line 34 + [mstore, 0, [sload, 6 ]], + [return, 0, 32], + # Line 32 + stop]], + # Line 41 + [if, + [eq, [mload, 0], 12354271 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 43 + [mstore, + 0, + [sload, [add, [sha3_32, 9 ], [mload, 320 ]]]], + [return, 0, 32], + # Line 41 + stop]], + # Line 44 + [if, + [eq, [mload, 0], 1394664890 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 46 + [mstore, + 0, + [sload, [add, [sha3_32, 10 ], [mload, 320 ]]]], + [return, 0, 32], + # Line 44 + stop]], + # Line 47 + [if, + [eq, [mload, 0], 4131989443 ], + [seq, + [calldatacopy, 320, 4, 64], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 36], [mload, 64]], + # Line 49 + [mstore, + 0, + [sload, + [add, + [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]]], + [mload, 352 ]]]], + [return, 0, 32], + # Line 47 + stop]], + [if, + [eq, [mload, 0], 1223172521 ], + [seq, + [calldatacopy, 320, 4, 64], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 36], [mload, 64]], + # Line 49 + [mstore, + 0, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], + 3 ]], + [mload, 352 ]]]], + [return, 0, 32], + # Line 47 + stop]], + [if, + [eq, [mload, 0], 1454924193 ], + [seq, + [calldatacopy, 320, 4, 96], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 68], [mload, 64]], + # Line 49 + [mstore, + 0, + [sload, + [add, + [sha3_32, + [add, + [sha3_32, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], + 4 ]], + [mload, 352 ]]], + [mload, 384 ]]]], + [return, 0, 32], + # Line 47 + stop]], + [if, + [eq, [mload, 0], 1720538877 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 49 + [mstore, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], + 2 ]]], + [return, 0, 32], + # Line 47 + stop]], + [if, + [eq, [mload, 0], 1650407259 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 49 + [mstore, + 0, + [sload, + [add, + [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], + 1 ]]], + [return, 0, 32], + # Line 47 + stop]], + # Line 61 + [if, + [eq, [mload, 0], 1066978799 ], + [seq, + [assert, [iszero, callvalue]], + # Line 63 + [mstore, 0, [sload, 12 ]], + [return, 0, 32], + # Line 61 + stop]], + # Line 64 + [if, + [eq, [mload, 0], 2719561995 ], + [seq, + [calldatacopy, 320, 4, 32], + [assert, [iszero, callvalue]], + /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], + # Line 66 + [mstore, + 0, + [sload, [add, [sha3_32, 13 ], [mload, 320 ]]]], + [return, 0, 32], + # Line 64 + stop]], + # Line 68 + [if, + [eq, [mload, 0], 4015133405 ], + [seq, + [assert, [iszero, callvalue]], + # Line 70 + [mstore, 0, [sload, 14 ]], + [return, 0, 32], + # Line 68 + stop]], + # Line 69 + [if, + [eq, [mload, 0], 1784543732 ], + [seq, + [assert, [iszero, callvalue]], + # Line 71 + [mstore, 0, [sload, 15 ]], + [return, 0, 32], + # Line 69 + stop]], + # Line 72 + [if, + [eq, [mload, 0], 100339843 ], + [seq, + [assert, [iszero, callvalue]], + # Line 74 + [mstore, 0, [sload, 16 ]], + [return, 0, 32], + # Line 72 + stop]], + # Line 75 + [if, + [eq, [mload, 0], 3280103687 ], + [seq, + [assert, [iszero, callvalue]], + # Line 77 + [mstore, 0, [sload, 17 ]], + [return, 0, 32], + # Line 75 + stop]], + # Line 78 + [if, + [eq, [mload, 0], 2205850567 ], + [seq, + [assert, [iszero, callvalue]], + # Line 80 + [mstore, 0, [sload, 18 ]], + [return, 0, 32], + # Line 78 + stop]], + # Line 81 + [if, + [eq, [mload, 0], 1665994615 ], + [seq, + [assert, [iszero, callvalue]], + # Line 83 + [mstore, 0, [sload, 19 ]], + [return, 0, 32], + # Line 81 + stop]], + # Line 84 + [if, + [eq, [mload, 0], 2205217592 ], + [seq, + [assert, [iszero, callvalue]], + # Line 86 + [mstore, 0, [sload, 20 ]], + [return, 0, 32], + # Line 84 + stop]], + # Line 87 + [if, + [eq, [mload, 0], 4290208155 ], + [seq, + [assert, [iszero, callvalue]], + # Line 89 + [mstore, 0, [sload, 21 ]], + [return, 0, 32], + # Line 87 + stop]], + # Line 102 + [if, + [eq, [mload, 0], 890060718 ], + [seq, + [assert, [iszero, callvalue]], + # Line 104 + [mstore, 0, [sload, 26 ]], + [return, 0, 32], + # Line 102 + stop]], + # Line 105 + [if, + [eq, [mload, 0], 4221743539 ], + [seq, + [assert, [iszero, callvalue]], + # Line 107 + [mstore, 0, [sload, 27 ]], + [return, 0, 32], + # Line 105 + stop]], + # Line 108 + [if, + [eq, [mload, 0], 429784826 ], + [seq, + [assert, [iszero, callvalue]], + # Line 110 + [mstore, 0, [sload, 28 ]], + [return, 0, 32], + # Line 108 + stop]]], + 0]]] \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/ethereumj.conf b/ethereumj-core/src/main/resources/ethereumj.conf index b74ab03d87..5228b52d24 100644 --- a/ethereumj-core/src/main/resources/ethereumj.conf +++ b/ethereumj-core/src/main/resources/ethereumj.conf @@ -428,3 +428,11 @@ crypto { hash.alg256="ETH-KECCAK-256" hash.alg512="ETH-KECCAK-512" } + +consensus { + # Strategy for consensus + # Currently supported: + # "pow" - Proof of Work + # "casper-hybrid" - hybrid PoW + Casper PoS + strategy="pow" +} diff --git a/ethereumj-core/src/main/resources/genesis/casper.json b/ethereumj-core/src/main/resources/genesis/casper.json new file mode 100644 index 0000000000..f71df403d2 --- /dev/null +++ b/ethereumj-core/src/main/resources/genesis/casper.json @@ -0,0 +1,21 @@ +{ + "nonce": "0x0000000000000056", + "difficulty": "0x2000", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x5f5e100", + "alloc": { + "b42e5cafe87d951c5cf0022bfdab06fe56ba2ad2": { + "balance": "1001002003004005006007008" + }, + "0xf63a243fe6922320a53dfc4270f02b8af0d4921d": { + "balance": "1001002003004005006007008" + }, + "b96611e02f9eff3c8afc6226d4ebfa81a821547c": { + "balance": "5125001002003004005006" + } + } +} \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/logback.xml b/ethereumj-core/src/main/resources/logback.xml index 143011fa60..af224c7f12 100644 --- a/ethereumj-core/src/main/resources/logback.xml +++ b/ethereumj-core/src/main/resources/logback.xml @@ -70,6 +70,7 @@ + diff --git a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java index e9dba75d36..fe37c9222d 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java @@ -19,13 +19,11 @@ import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.core.genesis.GenesisLoader; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.inmem.HashMapDB; import org.ethereum.datasource.NoDeleteSource; -import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; import org.ethereum.db.RepositoryRoot; import org.ethereum.listener.EthereumListenerAdapter; @@ -898,7 +896,7 @@ public static BlockchainImpl createBlockchain(Genesis genesis) { EthereumListenerAdapter listener = new EthereumListenerAdapter(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); + .withParentBlockHeaderValidator(new CommonConfig().consensusStrategy().getParentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java index b50aadbda2..99dac8280d 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java @@ -20,7 +20,6 @@ import org.ethereum.config.CommonConfig; import org.ethereum.datasource.inmem.HashMapDB; import org.ethereum.db.RepositoryRoot; -import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.validator.DependentBlockHeaderRuleAdapter; @@ -126,7 +125,7 @@ private Blockchain createBlockchain(Genesis genesis) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); + .withParentBlockHeaderValidator(new CommonConfig().consensusStrategy().getParentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java new file mode 100644 index 0000000000..73782c291f --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; + +import org.ethereum.config.CommonConfig; +import org.ethereum.config.SystemProperties; +import org.ethereum.config.net.CasperTestNetConfig; +import org.ethereum.core.Block; +import org.ethereum.core.BlockSummary; +import org.ethereum.core.BlockchainImpl; +import org.ethereum.core.EventDispatchThread; +import org.ethereum.core.Genesis; +import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.datasource.CountingBytesSource; +import org.ethereum.datasource.JournalSource; +import org.ethereum.datasource.Source; +import org.ethereum.datasource.inmem.HashMapDB; +import org.ethereum.db.ByteArrayWrapper; +import org.ethereum.db.IndexedBlockStore; +import org.ethereum.db.PruneManager; +import org.ethereum.db.RepositoryRoot; +import org.ethereum.facade.Ethereum; +import org.ethereum.facade.EthereumImpl; +import org.ethereum.listener.CompositeEthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.manager.AdminInfo; +import org.ethereum.manager.WorldManager; +import org.ethereum.util.blockchain.StandaloneBlockchain; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.vm.program.ProgramPrecompile; +import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +import org.spongycastle.util.encoders.Hex; +import org.springframework.context.ApplicationContext; + +import static junit.framework.TestCase.assertEquals; + +@RunWith(MockitoJUnitRunner.class) +public class CasperStateInitTest { + @Mock + ApplicationContext context; + + private final SystemProperties systemProperties = SystemProperties.getDefault(); + + private CommonConfig commonConfig; + + private CasperBlockchain blockchain; + + private WorldManager worldManager; + + private EthereumImpl ethereum; + + private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); + + private CasperHybridConsensusStrategy strategy; + + private StandaloneBlockchain bc; + + @Before + public void init() { + // Just trust me! + // FIXME: Make it a little bit readable + systemProperties.setBlockchainConfig(new CasperTestNetConfig()); + systemProperties.setGenesisInfo("casper.json"); + systemProperties.overrideParams( + "consensus.casper.epochLength", "50", + "consensus.casper.contractBin", "/casper/casper.bin", + "consensus.casper.contractAbi", "/casper/casper.abi" + ); + MockitoAnnotations.initMocks(this); + this.commonConfig = new CommonConfig() { + @Override + public Source precompileSource() { + return null; + } + + @Override + public ConsensusStrategy consensusStrategy() { + if (strategy == null) { + strategy = new CasperHybridConsensusStrategy(systemProperties, context); + } + return strategy; + } + }; + + this.ethereum = new EthereumImpl(systemProperties, defaultListener); + ethereum.setCommonConfig(commonConfig); + Mockito.when(context.getBean(Ethereum.class)).thenReturn(ethereum); + this.worldManager = Mockito.mock(WorldManager.class); + + this.bc = new StandaloneBlockchain() { + @Override + public BlockchainImpl getBlockchain() { + if (blockchain == null) { + blockchain = createBlockchain(); + addEthereumListener(new EthereumListenerAdapter() { + @Override + public void onBlock(BlockSummary blockSummary) { + lastSummary = blockSummary; + } + }); + } + return blockchain; + } + + private BlockchainImpl createBlockchain() { + SystemProperties.getDefault().setBlockchainConfig(systemProperties.getBlockchainConfig()); + + IndexedBlockStore blockStore = new IndexedBlockStore(); + blockStore.init(new HashMapDB(), new HashMapDB()); + + stateDS = new HashMapDB<>(); + pruningStateDS = new JournalSource<>(new CountingBytesSource(stateDS)); + pruneManager = new PruneManager(blockStore, pruningStateDS, SystemProperties.getDefault().databasePruneDepth()); + + final RepositoryRoot repository = new RepositoryRoot(pruningStateDS); + + ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); + listener = defaultListener; + + BlockchainImpl blockchain = new CasperBlockchain(systemProperties).withEthereumListener(listener) + .withAdminInfo(new AdminInfo()) + .withEventDispatchThread(new EventDispatchThread()) + .withCommonConfig(commonConfig) + .withBlockStore(blockStore); + blockchain.setRepository(repository); + blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); + blockchain.setProgramInvokeFactory(programInvokeFactory); + blockchain.setPruneManager(pruneManager); + ((CasperBlockchain)blockchain).setStrategy(strategy); + + blockchain.byTest = true; + + pendingState = new PendingStateImpl(listener, blockchain); + + pendingState.setBlockchain(blockchain); + blockchain.setPendingState(pendingState); + return blockchain; + } + }.withNetConfig(systemProperties.getBlockchainConfig()); + + this.blockchain = (CasperBlockchain) bc.getBlockchain(); + Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); + Mockito.when(worldManager.getRepository()).thenReturn(bc.getBlockchain().getRepository()); + Mockito.when(worldManager.getBlockStore()).thenReturn(bc.getBlockchain().getBlockStore()); + ethereum.setWorldManager(worldManager); + ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); + commonConfig.consensusStrategy(); + } + + @Test + public void genesisPlusBlock() { + // Init with Genesis + final Genesis genesis = Genesis.getInstance(systemProperties); + CasperStateInit casperStateInit = (CasperStateInit) strategy.initState(genesis); + casperStateInit.initDB(); + + // Check after genesis + assertEquals(new ByteArrayWrapper(Hex.decode("f3f713c5ff3119287ae62861e3fd90d6afc94b57d06151007c409b86bf419d11")), + new ByteArrayWrapper(blockchain.getBestBlock().getStateRoot())); + assertEquals(new ByteArrayWrapper(Hex.decode("5d0dfcfbcb941825c7ed52c846dc2021e29374f6954c4eaf6f7352f63ec8cab4")), + new ByteArrayWrapper(blockchain.getBestBlock().getHash())); + + // Mine 1st block + Block block1 = bc.createBlock(Hex.decode("3535353535353535353535353535353535353535")); + + // Check after 1st block + assertEquals(new ByteArrayWrapper(Hex.decode("b1b5d87eeadab3ffc0e4045ee18fc63ccc06b8e9b7195af8f1a4450557c3818d")), + new ByteArrayWrapper(block1.getStateRoot())); + + assertEquals(new ByteArrayWrapper(Hex.decode("bd832b0cd3291c39ef67691858f35c71dfb3bf21")), + new ByteArrayWrapper(systemProperties.getCasperAddress())); + + // TODO: Mine to first epoch start to check all is ok + we could test votes etc + } +} diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java index 4683ab2358..b81596b112 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java @@ -19,6 +19,7 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.ContractDetails; @@ -409,4 +410,9 @@ public ContractDetails getSnapshotTo(byte[] hash) { return new IterableContractDetails(src.getSnapshotTo(hash)); } } + + @Override + public void setBlockchain(Blockchain blockchain) { + // Not used + } } 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 16367962c7..e35ecc7042 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 @@ -33,7 +33,6 @@ import org.ethereum.jsontestsuite.suite.validators.RepositoryValidator; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.DataWord; import org.ethereum.vm.LogInfo; import org.ethereum.vm.VM; @@ -100,14 +99,14 @@ public List runTestCase(BlockTestCase testCase) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(CommonConfig.getDefault().parentHeaderValidator()); + .withParentBlockHeaderValidator(CommonConfig.getDefault().consensusStrategy().getParentHeaderValidator()); blockchain.byTest = true; PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter(), blockchain); blockchain.setBestBlock(genesis); blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); - blockchain.setParentHeaderValidator(new CommonConfig().parentHeaderValidator()); + blockchain.setParentHeaderValidator(new CommonConfig().consensusStrategy().getParentHeaderValidator()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.setPendingState(pendingState); From ebe5fb0d266011feef6abc0d1dfe3eb0570c097f Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 23 Feb 2018 00:41:32 +0300 Subject: [PATCH 02/67] TransactionExecutor split to standard implementation and Casper version --- .../org/ethereum/core/BlockchainImpl.java | 2 +- .../core/CommonTransactionExecutor.java | 530 ++++++++++++++++ .../org/ethereum/core/PendingStateImpl.java | 2 +- .../ethereum/core/TransactionExecutor.java | 568 ++---------------- .../core/casper/CasperBlockchain.java | 4 +- .../casper/CasperTransactionExecutor.java | 116 ++++ .../CasperHybridConsensusStrategy.java | 21 + .../core/consensus/ConsensusStrategy.java | 14 + .../core/consensus/PoWConsensusStrategy.java | 23 + .../java/org/ethereum/facade/Ethereum.java | 3 + .../org/ethereum/facade/EthereumImpl.java | 12 +- .../util/blockchain/StandaloneBlockchain.java | 7 +- .../org/ethereum/core/TransactionTest.java | 4 +- .../suite/runners/StateTestRunner.java | 2 +- .../ethereum/longrun/SyncWithLoadTest.java | 4 +- 15 files changed, 781 insertions(+), 531 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 822f10fa52..0ba7f4e65b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -878,7 +878,7 @@ protected BlockSummary applyBlock(Repository track, Block block) { stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); Repository txTrack = track.startTracking(); - TransactionExecutor executor = new TransactionExecutor(tx, block.getCoinbase(), + TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor(tx, block.getCoinbase(), txTrack, blockStore, programInvokeFactory, block, listener, totalGasUsed) .withCommonConfig(commonConfig); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java new file mode 100644 index 0000000000..b4596d7799 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java @@ -0,0 +1,530 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core; + +import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.CommonConfig; +import org.ethereum.config.SystemProperties; +import org.ethereum.db.BlockStore; +import org.ethereum.db.ContractDetails; +import org.ethereum.listener.EthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.util.ByteArraySet; +import org.ethereum.vm.DataWord; +import org.ethereum.vm.LogInfo; +import org.ethereum.vm.PrecompiledContracts; +import org.ethereum.vm.VM; +import org.ethereum.vm.program.Program; +import org.ethereum.vm.program.ProgramResult; +import org.ethereum.vm.program.invoke.ProgramInvoke; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigInteger; + +import java.util.List; + +import static org.apache.commons.lang3.ArrayUtils.getLength; +import static org.apache.commons.lang3.ArrayUtils.isEmpty; +import static org.ethereum.util.BIUtil.isCovers; +import static org.ethereum.util.BIUtil.isNotEqual; +import static org.ethereum.util.BIUtil.toBI; +import static org.ethereum.util.BIUtil.transfer; +import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; +import static org.ethereum.util.ByteUtil.toHexString; +import static org.ethereum.vm.VMUtils.saveProgramTraceFile; +import static org.ethereum.vm.VMUtils.zipAndEncode; + +/** + * @author Roman Mandeleil + * @since 19.12.2014 + */ +public class CommonTransactionExecutor implements TransactionExecutor { + + protected static final Logger logger = LoggerFactory.getLogger("execute"); + private static final Logger stateLogger = LoggerFactory.getLogger("state"); + + protected SystemProperties config; + protected CommonConfig commonConfig; + BlockchainConfig blockchainConfig; + + protected Transaction tx; + protected Repository track; + private Repository cacheTrack; + private BlockStore blockStore; + private final long gasUsedInTheBlock; + protected boolean readyToExecute = false; + protected String execError; + + private ProgramInvokeFactory programInvokeFactory; + protected byte[] coinbase; + + private TransactionReceipt receipt; + private ProgramResult result = new ProgramResult(); + private Block currentBlock; + + private final EthereumListener listener; + + private VM vm; + private Program program; + + PrecompiledContracts.PrecompiledContract precompiledContract; + + BigInteger m_endGas = BigInteger.ZERO; + long basicTxCost = 0; + List logs = null; + + protected ByteArraySet touchedAccounts = new ByteArraySet(); + + protected boolean localCall = false; + + public CommonTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, + ProgramInvokeFactory programInvokeFactory, Block currentBlock) { + + this(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, new EthereumListenerAdapter(), 0); + } + + public CommonTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, + ProgramInvokeFactory programInvokeFactory, Block currentBlock, + EthereumListener listener, long gasUsedInTheBlock) { + + this.tx = tx; + this.coinbase = coinbase; + this.track = track; + this.cacheTrack = track.startTracking(); + this.blockStore = blockStore; + this.programInvokeFactory = programInvokeFactory; + this.currentBlock = currentBlock; + this.listener = listener; + this.gasUsedInTheBlock = gasUsedInTheBlock; + this.m_endGas = toBI(tx.getGasLimit()); + withCommonConfig(CommonConfig.getDefault()); + } + + @Override + public TransactionExecutor withCommonConfig(CommonConfig commonConfig) { + this.commonConfig = commonConfig; + this.config = commonConfig.systemProperties(); + this.blockchainConfig = config.getBlockchainConfig().getConfigForBlock(currentBlock.getNumber()); + return this; + } + + private void execError(String err) { + logger.warn(err); + execError = err; + } + + /** + * Do all the basic validation, if the executor + * will be ready to run the transaction at the end + * set readyToExecute = true + */ + @Override + public void init() { + basicTxCost = tx.transactionCost(config.getBlockchainConfig(), currentBlock); + + if (localCall) { + readyToExecute = true; + return; + } + + BigInteger txGasLimit = new BigInteger(1, tx.getGasLimit()); + BigInteger curBlockGasLimit = new BigInteger(1, currentBlock.getGasLimit()); + + boolean cumulativeGasReached = txGasLimit.add(BigInteger.valueOf(gasUsedInTheBlock)).compareTo(curBlockGasLimit) > 0; + if (cumulativeGasReached) { + + execError(String.format("Too much gas used in this block: Require: %s Got: %s", new BigInteger(1, currentBlock.getGasLimit()).longValue() - toBI(tx.getGasLimit()).longValue(), toBI(tx.getGasLimit()).longValue())); + + return; + } + + if (txGasLimit.compareTo(BigInteger.valueOf(basicTxCost)) < 0) { + + execError(String.format("Not enough gas for transaction execution: Require: %s Got: %s", basicTxCost, txGasLimit)); + + return; + } + + BigInteger reqNonce = track.getNonce(tx.getSender()); + BigInteger txNonce = toBI(tx.getNonce()); + if (isNotEqual(reqNonce, txNonce)) { + execError(String.format("Invalid nonce: required: %s , tx.nonce: %s", reqNonce, txNonce)); + + return; + } + + BigInteger txGasCost = toBI(tx.getGasPrice()).multiply(txGasLimit); + BigInteger totalCost = toBI(tx.getValue()).add(txGasCost); + BigInteger senderBalance = track.getBalance(tx.getSender()); + + if (!isCovers(senderBalance, totalCost)) { + + execError(String.format("Not enough cash: Require: %s, Sender cash: %s", totalCost, senderBalance)); + + return; + } + + if (!isSignatureValid()) { + execError("Transaction signature not accepted: " + tx.getSignature()); + return; + } + + readyToExecute = true; + } + + protected boolean isSignatureValid() { + return blockchainConfig.acceptTransactionSignature(tx); + } + + @Override + public void execute() { + + if (!readyToExecute) return; + + if (!localCall) { + track.increaseNonce(tx.getSender()); + + BigInteger txGasLimit = toBI(tx.getGasLimit()); + BigInteger txGasCost = toBI(tx.getGasPrice()).multiply(txGasLimit); + track.addBalance(tx.getSender(), txGasCost.negate()); + + if (logger.isInfoEnabled()) + logger.info("Paying: txGasCost: [{}], gasPrice: [{}], gasLimit: [{}]", txGasCost, toBI(tx.getGasPrice()), txGasLimit); + } + + if (tx.isContractCreation()) { + create(); + } else { + call(); + } + } + + protected void call() { + if (!readyToExecute) return; + + byte[] targetAddress = tx.getReceiveAddress(); + precompiledContract = PrecompiledContracts.getContractForAddress(new DataWord(targetAddress), blockchainConfig); + + if (precompiledContract != null) { + long requiredGas = precompiledContract.getGasForData(tx.getData()); + + BigInteger spendingGas = BigInteger.valueOf(requiredGas).add(BigInteger.valueOf(basicTxCost)); + + if (!localCall && m_endGas.compareTo(spendingGas) < 0) { + // no refund + // no endowment + execError("Out of Gas calling precompiled contract 0x" + Hex.toHexString(targetAddress) + + ", required: " + spendingGas + ", left: " + m_endGas); + m_endGas = BigInteger.ZERO; + return; + } else { + + m_endGas = m_endGas.subtract(spendingGas); + + // FIXME: save return for vm trace + Pair out = precompiledContract.execute(tx.getData()); + + if (!out.getLeft()) { + execError("Error executing precompiled contract 0x" + Hex.toHexString(targetAddress)); + m_endGas = BigInteger.ZERO; + return; + } + } + + } else { + + byte[] code = track.getCode(targetAddress); + if (isEmpty(code)) { + m_endGas = m_endGas.subtract(BigInteger.valueOf(basicTxCost)); + result.spendGas(basicTxCost); + } else { + ProgramInvoke programInvoke = + programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, blockStore); + + this.vm = new VM(config); + this.program = new Program(track.getCodeHash(targetAddress), code, programInvoke, tx, config).withCommonConfig(commonConfig); + } + } + + BigInteger endowment = toBI(tx.getValue()); + transfer(cacheTrack, tx.getSender(), targetAddress, endowment); + + touchedAccounts.add(targetAddress); + } + + protected void create() { + byte[] newContractAddress = tx.getContractAddress(); + + AccountState existingAddr = cacheTrack.getAccountState(newContractAddress); + if (existingAddr != null && existingAddr.isContractExist(blockchainConfig)) { + execError("Trying to create a contract with existing contract address: 0x" + Hex.toHexString(newContractAddress)); + m_endGas = BigInteger.ZERO; + return; + } + + //In case of hashing collisions (for TCK tests only), check for any balance before createAccount() + BigInteger oldBalance = track.getBalance(newContractAddress); + cacheTrack.createAccount(tx.getContractAddress()); + cacheTrack.addBalance(newContractAddress, oldBalance); + if (blockchainConfig.eip161()) { + cacheTrack.increaseNonce(newContractAddress); + } + + if (isEmpty(tx.getData())) { + m_endGas = m_endGas.subtract(BigInteger.valueOf(basicTxCost)); + result.spendGas(basicTxCost); + } else { + ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, blockStore); + + this.vm = new VM(config); + this.program = new Program(tx.getData(), programInvoke, tx, config).withCommonConfig(commonConfig); + + // reset storage if the contract with the same address already exists + // TCK test case only - normally this is near-impossible situation in the real network + // TODO make via Trie.clear() without keyset +// ContractDetails contractDetails = program.getStorage().getContractDetails(newContractAddress); +// for (DataWord key : contractDetails.getStorageKeys()) { +// program.storageSave(key, DataWord.ZERO); +// } + } + + BigInteger endowment = toBI(tx.getValue()); + transfer(cacheTrack, tx.getSender(), newContractAddress, endowment); + + touchedAccounts.add(newContractAddress); + } + + @Override + public void go() { + if (!readyToExecute) return; + + try { + + if (vm != null) { + + // Charge basic cost of the transaction + program.spendGas(tx.transactionCost(config.getBlockchainConfig(), currentBlock), "TRANSACTION COST"); + + if (config.playVM()) + vm.play(program); + + result = program.getResult(); + m_endGas = toBI(tx.getGasLimit()).subtract(toBI(program.getResult().getGasUsed())); + + if (tx.isContractCreation() && !result.isRevert()) { + int returnDataGasValue = getLength(program.getResult().getHReturn()) * + blockchainConfig.getGasCost().getCREATE_DATA(); + if (m_endGas.compareTo(BigInteger.valueOf(returnDataGasValue)) < 0) { + // Not enough gas to return contract code + if (!blockchainConfig.getConstants().createEmptyContractOnOOG()) { + program.setRuntimeFailure(Program.Exception.notEnoughSpendingGas("No gas to return just created contract", + returnDataGasValue, program)); + result = program.getResult(); + } + result.setHReturn(EMPTY_BYTE_ARRAY); + } else if (getLength(result.getHReturn()) > blockchainConfig.getConstants().getMAX_CONTRACT_SZIE()) { + // Contract size too large + program.setRuntimeFailure(Program.Exception.notEnoughSpendingGas("Contract size too large: " + getLength(result.getHReturn()), + returnDataGasValue, program)); + result = program.getResult(); + result.setHReturn(EMPTY_BYTE_ARRAY); + } else { + // Contract successfully created + m_endGas = m_endGas.subtract(BigInteger.valueOf(returnDataGasValue)); + cacheTrack.saveCode(tx.getContractAddress(), result.getHReturn()); + } + } + + String err = config.getBlockchainConfig().getConfigForBlock(currentBlock.getNumber()). + validateTransactionChanges(blockStore, currentBlock, tx, null); + if (err != null) { + program.setRuntimeFailure(new RuntimeException("Transaction changes validation failed: " + err)); + } + + + if (result.getException() != null || result.isRevert()) { + result.getDeleteAccounts().clear(); + result.getLogInfoList().clear(); + result.resetFutureRefund(); + rollback(); + + if (result.getException() != null) { + throw result.getException(); + } else { + execError("REVERT opcode executed"); + } + } else { + touchedAccounts.addAll(result.getTouchedAccounts()); + cacheTrack.commit(); + } + + } else { + cacheTrack.commit(); + } + + } catch (Throwable e) { + + // TODO: catch whatever they will throw on you !!! +// https://github.com/ethereum/cpp-ethereum/blob/develop/libethereum/Executive.cpp#L241 + rollback(); + m_endGas = BigInteger.ZERO; + execError(e.getMessage()); + } + } + + private void rollback() { + + cacheTrack.rollback(); + + // remove touched account + touchedAccounts.remove( + tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress()); + } + + @Override + public TransactionExecutionSummary finalization() { + if (!readyToExecute) return null; + + TransactionExecutionSummary.Builder summaryBuilder = TransactionExecutionSummary.builderFor(tx) + .gasLeftover(m_endGas) + .logs(result.getLogInfoList()) + .result(result.getHReturn()); + + if (result != null) { + // Accumulate refunds for suicides + result.addFutureRefund(result.getDeleteAccounts().size() * config.getBlockchainConfig(). + getConfigForBlock(currentBlock.getNumber()).getGasCost().getSUICIDE_REFUND()); + long gasRefund = Math.min(result.getFutureRefund(), getGasUsed() / 2); + byte[] addr = tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress(); + m_endGas = m_endGas.add(BigInteger.valueOf(gasRefund)); + + summaryBuilder + .gasUsed(toBI(result.getGasUsed())) + .gasRefund(toBI(gasRefund)) + .deletedAccounts(result.getDeleteAccounts()) + .internalTransactions(result.getInternalTransactions()); + + ContractDetails contractDetails = track.getContractDetails(addr); + if (contractDetails != null) { + // TODO +// summaryBuilder.storageDiff(track.getContractDetails(addr).getStorage()); +// +// if (program != null) { +// summaryBuilder.touchedStorage(contractDetails.getStorage(), program.getStorageDiff()); +// } + } + + if (result.getException() != null) { + summaryBuilder.markAsFailed(); + } + } + + TransactionExecutionSummary summary = summaryBuilder.build(); + + // Refund for gas leftover + track.addBalance(tx.getSender(), summary.getLeftover().add(summary.getRefund())); + logger.info("Pay total refund to sender: [{}], refund val: [{}]", Hex.toHexString(tx.getSender()), summary.getRefund()); + + payRewards(summary); + + if (result != null) { + logs = result.getLogInfoList(); + // Traverse list of suicides + for (DataWord address : result.getDeleteAccounts()) { + track.delete(address.getLast20Bytes()); + } + } + + if (blockchainConfig.eip161()) { + for (byte[] acctAddr : touchedAccounts) { + AccountState state = track.getAccountState(acctAddr); + if (state != null && state.isEmpty()) { + track.delete(acctAddr); + } + } + } + + + listener.onTransactionExecuted(summary); + + if (config.vmTrace() && program != null && result != null) { + String trace = program.getTrace() + .result(result.getHReturn()) + .error(result.getException()) + .toString(); + + + if (config.vmTraceCompressed()) { + trace = zipAndEncode(trace); + } + + String txHash = toHexString(tx.getHash()); + saveProgramTraceFile(config, txHash, trace); + listener.onVMTraceCreated(txHash, trace); + } + return summary; + } + + protected void payRewards(final TransactionExecutionSummary summary) { + // Transfer fees to miner + track.addBalance(coinbase, summary.getFee()); + touchedAccounts.add(coinbase); + logger.info("Pay fees to miner: [{}], feesEarned: [{}]", Hex.toHexString(coinbase), summary.getFee()); + } + + @Override + public TransactionExecutor setLocalCall(boolean localCall) { + this.localCall = localCall; + return this; + } + + @Override + public TransactionReceipt getReceipt() { + if (receipt == null) { + receipt = new TransactionReceipt(); + long totalGasUsed = gasUsedInTheBlock + getGasUsed(); + receipt.setCumulativeGas(totalGasUsed); + receipt.setTransaction(tx); + receipt.setLogInfoList(getVMLogs()); + receipt.setGasUsed(getGasUsed()); + receipt.setExecutionResult(getResult().getHReturn()); + receipt.setError(execError); +// receipt.setPostTxState(track.getRoot()); // TODO later when RepositoryTrack.getRoot() is implemented + } + return receipt; + } + + @Override + public List getVMLogs() { + return logs; + } + + @Override + public ProgramResult getResult() { + return result; + } + + @Override + public long getGasUsed() { + return toBI(tx.getGasLimit()).subtract(m_endGas).longValue(); + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 40cbe9cb19..6e084412df 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -442,7 +442,7 @@ private TransactionReceipt executeTx(Transaction tx) { Block best = getBestBlock(); - TransactionExecutor executor = new TransactionExecutor( + TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor( tx, best.getCoinbase(), getRepository(), blockStore, programInvokeFactory, createFakePendingBlock(), new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig); 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 eb02a8197d..3416d54db6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutor.java @@ -1,541 +1,75 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ package org.ethereum.core; -import org.apache.commons.lang3.tuple.Pair; -import org.ethereum.config.BlockchainConfig; import org.ethereum.config.CommonConfig; -import org.ethereum.config.SystemProperties; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; -import org.ethereum.db.BlockStore; -import org.ethereum.db.ContractDetails; -import org.ethereum.listener.EthereumListener; -import org.ethereum.listener.EthereumListenerAdapter; -import org.ethereum.manager.WorldManager; -import org.ethereum.util.ByteArraySet; -import org.ethereum.vm.*; -import org.ethereum.vm.program.Program; +import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.ProgramResult; -import org.ethereum.vm.program.invoke.ProgramInvoke; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.spongycastle.util.encoders.Hex; -import java.math.BigInteger; -import java.util.Arrays; import java.util.List; -import static org.apache.commons.lang3.ArrayUtils.getLength; -import static org.apache.commons.lang3.ArrayUtils.isEmpty; -import static org.ethereum.util.BIUtil.*; -import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; -import static org.ethereum.util.ByteUtil.toHexString; -import static org.ethereum.vm.VMUtils.saveProgramTraceFile; -import static org.ethereum.vm.VMUtils.zipAndEncode; - /** - * @author Roman Mandeleil - * @since 19.12.2014 + * Executes transaction using Ethereum VM + * Usual usage looks like this: + * 1. init() + * 2. execute() + * 3. go() + * 4. finalization() <- get Summary here + * After that all results of transaction execution + * could be obtained using all other methods */ -public class TransactionExecutor { - - private static final Logger logger = LoggerFactory.getLogger("execute"); - private static final Logger stateLogger = LoggerFactory.getLogger("state"); - - SystemProperties config; - CommonConfig commonConfig; - BlockchainConfig blockchainConfig; - - private Transaction tx; - private Repository track; - private Repository cacheTrack; - private BlockStore blockStore; - private final long gasUsedInTheBlock; - private boolean readyToExecute = false; - private String execError; - - private ProgramInvokeFactory programInvokeFactory; - private byte[] coinbase; - - private TransactionReceipt receipt; - private ProgramResult result = new ProgramResult(); - private Block currentBlock; - - private final EthereumListener listener; - - private VM vm; - private Program program; - - PrecompiledContracts.PrecompiledContract precompiledContract; - - BigInteger m_endGas = BigInteger.ZERO; - long basicTxCost = 0; - List logs = null; - - private ByteArraySet touchedAccounts = new ByteArraySet(); - - boolean localCall = false; - - public TransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, - ProgramInvokeFactory programInvokeFactory, Block currentBlock) { - - this(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, new EthereumListenerAdapter(), 0); - } - - public TransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, - ProgramInvokeFactory programInvokeFactory, Block currentBlock, - EthereumListener listener, long gasUsedInTheBlock) { - - this.tx = tx; - this.coinbase = coinbase; - this.track = track; - this.cacheTrack = track.startTracking(); - this.blockStore = blockStore; - this.programInvokeFactory = programInvokeFactory; - this.currentBlock = currentBlock; - this.listener = listener; - this.gasUsedInTheBlock = gasUsedInTheBlock; - this.m_endGas = toBI(tx.getGasLimit()); - withCommonConfig(CommonConfig.getDefault()); - } - - public TransactionExecutor withCommonConfig(CommonConfig commonConfig) { - this.commonConfig = commonConfig; - this.config = commonConfig.systemProperties(); - this.blockchainConfig = config.getBlockchainConfig().getConfigForBlock(currentBlock.getNumber()); - return this; - } - - private void execError(String err) { - logger.warn(err); - execError = err; - } +public interface TransactionExecutor { + TransactionExecutor withCommonConfig(CommonConfig commonConfig); /** * Do all the basic validation, if the executor * will be ready to run the transaction at the end * set readyToExecute = true */ - public void init() { // TODO: probably we need consensus-specific validation - basicTxCost = tx.transactionCost(config.getBlockchainConfig(), currentBlock); - - if (localCall) { - readyToExecute = true; - return; - } - - BigInteger txGasLimit = new BigInteger(1, tx.getGasLimit()); - BigInteger curBlockGasLimit = new BigInteger(1, currentBlock.getGasLimit()); - - boolean cumulativeGasReached = txGasLimit.add(BigInteger.valueOf(gasUsedInTheBlock)).compareTo(curBlockGasLimit) > 0; - if (cumulativeGasReached) { - - execError(String.format("Too much gas used in this block: Require: %s Got: %s", new BigInteger(1, currentBlock.getGasLimit()).longValue() - toBI(tx.getGasLimit()).longValue(), toBI(tx.getGasLimit()).longValue())); - - return; - } - - if (txGasLimit.compareTo(BigInteger.valueOf(basicTxCost)) < 0) { - - execError(String.format("Not enough gas for transaction execution: Require: %s Got: %s", basicTxCost, txGasLimit)); - - return; - } - - BigInteger reqNonce = track.getNonce(tx.getSender()); - BigInteger txNonce = toBI(tx.getNonce()); - if (isNotEqual(reqNonce, txNonce)) { - execError(String.format("Invalid nonce: required: %s , tx.nonce: %s", reqNonce, txNonce)); - - return; - } - - BigInteger txGasCost = toBI(tx.getGasPrice()).multiply(txGasLimit); - BigInteger totalCost = toBI(tx.getValue()).add(txGasCost); - BigInteger senderBalance = track.getBalance(tx.getSender()); - - if (!isCovers(senderBalance, totalCost)) { - - execError(String.format("Not enough cash: Require: %s, Sender cash: %s", totalCost, senderBalance)); - - return; - } - - if (!isCasperVote() && !blockchainConfig.acceptTransactionSignature(tx)) { - execError("Transaction signature not accepted: " + tx.getSignature()); - return; - } - - readyToExecute = true; - } - - public void execute() { - - if (!readyToExecute) return; - - // FIXME: Additional logic should be refactored to take place only for Casper - if (!localCall && !isCasperVote()) { - track.increaseNonce(tx.getSender()); - - BigInteger txGasLimit = toBI(tx.getGasLimit()); - BigInteger txGasCost = toBI(tx.getGasPrice()).multiply(txGasLimit); - track.addBalance(tx.getSender(), txGasCost.negate()); - - if (logger.isInfoEnabled()) - logger.info("Paying: txGasCost: [{}], gasPrice: [{}], gasLimit: [{}]", txGasCost, toBI(tx.getGasPrice()), txGasLimit); - } - - if (tx.isContractCreation()) { - create(); - } else { - call(); - } - } - - private void call() { - if (!readyToExecute) return; - - byte[] targetAddress = tx.getReceiveAddress(); - precompiledContract = PrecompiledContracts.getContractForAddress(new DataWord(targetAddress), blockchainConfig); - - if (precompiledContract != null) { - long requiredGas = precompiledContract.getGasForData(tx.getData()); - - BigInteger spendingGas = BigInteger.valueOf(requiredGas).add(BigInteger.valueOf(basicTxCost)); - - if (!localCall && m_endGas.compareTo(spendingGas) < 0) { - // no refund - // no endowment - execError("Out of Gas calling precompiled contract 0x" + Hex.toHexString(targetAddress) + - ", required: " + spendingGas + ", left: " + m_endGas); - m_endGas = BigInteger.ZERO; - return; - } else { - - m_endGas = m_endGas.subtract(spendingGas); - - // FIXME: save return for vm trace - Pair out = precompiledContract.execute(tx.getData()); - - if (!out.getLeft()) { - execError("Error executing precompiled contract 0x" + Hex.toHexString(targetAddress)); - m_endGas = BigInteger.ZERO; - return; - } - } - - } else { - - byte[] code = track.getCode(targetAddress); - if (isEmpty(code)) { - m_endGas = m_endGas.subtract(BigInteger.valueOf(basicTxCost)); - result.spendGas(basicTxCost); - } else { - ProgramInvoke programInvoke = - programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, blockStore); - - this.vm = new VM(config); - this.program = new Program(track.getCodeHash(targetAddress), code, programInvoke, tx, config).withCommonConfig(commonConfig); - } - } - - BigInteger endowment = toBI(tx.getValue()); - transfer(cacheTrack, tx.getSender(), targetAddress, endowment); - - touchedAccounts.add(targetAddress); - } - - private void create() { - byte[] newContractAddress = tx.getContractAddress(); - - AccountState existingAddr = cacheTrack.getAccountState(newContractAddress); - if (existingAddr != null && existingAddr.isContractExist(blockchainConfig)) { - execError("Trying to create a contract with existing contract address: 0x" + Hex.toHexString(newContractAddress)); - m_endGas = BigInteger.ZERO; - return; - } - - //In case of hashing collisions (for TCK tests only), check for any balance before createAccount() - BigInteger oldBalance = track.getBalance(newContractAddress); - cacheTrack.createAccount(tx.getContractAddress()); - cacheTrack.addBalance(newContractAddress, oldBalance); - if (blockchainConfig.eip161()) { - cacheTrack.increaseNonce(newContractAddress); - } + void init(); - if (isEmpty(tx.getData())) { - m_endGas = m_endGas.subtract(BigInteger.valueOf(basicTxCost)); - result.spendGas(basicTxCost); - } else { - ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, currentBlock, cacheTrack, blockStore); - - this.vm = new VM(config); - this.program = new Program(tx.getData(), programInvoke, tx, config).withCommonConfig(commonConfig); - - // reset storage if the contract with the same address already exists - // TCK test case only - normally this is near-impossible situation in the real network - // TODO make via Trie.clear() without keyset -// ContractDetails contractDetails = program.getStorage().getContractDetails(newContractAddress); -// for (DataWord key : contractDetails.getStorageKeys()) { -// program.storageSave(key, DataWord.ZERO); -// } - } - - BigInteger endowment = toBI(tx.getValue()); - transfer(cacheTrack, tx.getSender(), newContractAddress, endowment); - - touchedAccounts.add(newContractAddress); - } - - public void go() { - if (!readyToExecute) return; - - try { - - if (vm != null) { - - // Charge basic cost of the transaction - program.spendGas(tx.transactionCost(config.getBlockchainConfig(), currentBlock), "TRANSACTION COST"); - - if (config.playVM()) - vm.play(program); - - result = program.getResult(); - m_endGas = toBI(tx.getGasLimit()).subtract(toBI(program.getResult().getGasUsed())); - - if (tx.isContractCreation() && !result.isRevert()) { - int returnDataGasValue = getLength(program.getResult().getHReturn()) * - blockchainConfig.getGasCost().getCREATE_DATA(); - if (m_endGas.compareTo(BigInteger.valueOf(returnDataGasValue)) < 0) { - // Not enough gas to return contract code - if (!blockchainConfig.getConstants().createEmptyContractOnOOG()) { - program.setRuntimeFailure(Program.Exception.notEnoughSpendingGas("No gas to return just created contract", - returnDataGasValue, program)); - result = program.getResult(); - } - result.setHReturn(EMPTY_BYTE_ARRAY); - } else if (getLength(result.getHReturn()) > blockchainConfig.getConstants().getMAX_CONTRACT_SZIE()) { - // Contract size too large - program.setRuntimeFailure(Program.Exception.notEnoughSpendingGas("Contract size too large: " + getLength(result.getHReturn()), - returnDataGasValue, program)); - result = program.getResult(); - result.setHReturn(EMPTY_BYTE_ARRAY); - } else { - // Contract successfully created - m_endGas = m_endGas.subtract(BigInteger.valueOf(returnDataGasValue)); - cacheTrack.saveCode(tx.getContractAddress(), result.getHReturn()); - } - } - - String err = config.getBlockchainConfig().getConfigForBlock(currentBlock.getNumber()). - validateTransactionChanges(blockStore, currentBlock, tx, null); - if (err != null) { - program.setRuntimeFailure(new RuntimeException("Transaction changes validation failed: " + err)); - } - - - if (result.getException() != null || result.isRevert()) { - result.getDeleteAccounts().clear(); - result.getLogInfoList().clear(); - result.resetFutureRefund(); - rollback(); - - if (result.getException() != null) { - throw result.getException(); - } else { - execError("REVERT opcode executed"); - } - } else { - touchedAccounts.addAll(result.getTouchedAccounts()); - cacheTrack.commit(); - } - - } else { - cacheTrack.commit(); - } - - } catch (Throwable e) { - - // TODO: catch whatever they will throw on you !!! -// https://github.com/ethereum/cpp-ethereum/blob/develop/libethereum/Executive.cpp#L241 - rollback(); - m_endGas = BigInteger.ZERO; - execError(e.getMessage()); - } - } - - private void rollback() { - - cacheTrack.rollback(); - - // remove touched account - touchedAccounts.remove( - tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress()); - } - - // TODO: I shouldn't be here - private boolean isCasperVote() { - if (!(commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) - return false; - if (!Arrays.equals(tx.getSender(), Transaction.NULL_SENDER)) - return false; - if (config.getCasperAddress() == null) - return false; // Not yet initialized - if (!Arrays.equals(tx.getReceiveAddress(), config.getCasperAddress())) - return false; - - byte[] dataCopy = new byte[4]; - System.arraycopy(tx.getData(), 0, dataCopy, 0, 4); - return Arrays.equals(dataCopy, new byte[] {(byte) 0xe9, (byte) 0xdc, 0x06, 0x14}); - } - - public TransactionExecutionSummary finalization() { - if (!readyToExecute) return null; - - TransactionExecutionSummary.Builder summaryBuilder = TransactionExecutionSummary.builderFor(tx) - .gasLeftover(m_endGas) - .logs(result.getLogInfoList()) - .result(result.getHReturn()); - - if (result != null) { - // Accumulate refunds for suicides - result.addFutureRefund(result.getDeleteAccounts().size() * config.getBlockchainConfig(). - getConfigForBlock(currentBlock.getNumber()).getGasCost().getSUICIDE_REFUND()); - long gasRefund = Math.min(result.getFutureRefund(), getGasUsed() / 2); - byte[] addr = tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress(); - m_endGas = m_endGas.add(BigInteger.valueOf(gasRefund)); - - summaryBuilder - .gasUsed(toBI(result.getGasUsed())) - .gasRefund(toBI(gasRefund)) - .deletedAccounts(result.getDeleteAccounts()) - .internalTransactions(result.getInternalTransactions()); - - ContractDetails contractDetails = track.getContractDetails(addr); - if (contractDetails != null) { - // TODO -// summaryBuilder.storageDiff(track.getContractDetails(addr).getStorage()); -// -// if (program != null) { -// summaryBuilder.touchedStorage(contractDetails.getStorage(), program.getStorageDiff()); -// } - } - - if (result.getException() != null) { - summaryBuilder.markAsFailed(); - } - } - - TransactionExecutionSummary summary = summaryBuilder.build(); - - // Refund for gas leftover - track.addBalance(tx.getSender(), summary.getLeftover().add(summary.getRefund())); - logger.info("Pay total refund to sender: [{}], refund val: [{}]", Hex.toHexString(tx.getSender()), summary.getRefund()); - - if (result != null) { - logs = result.getLogInfoList(); - // Traverse list of suicides - for (DataWord address : result.getDeleteAccounts()) { - track.delete(address.getLast20Bytes()); - } - } - - // TODO: We definitely need separate TransactionExecutor for Casper - if (getReceipt().isSuccessful() && isCasperVote()) { - track.addBalance(tx.getSender(), summary.getFee()); - logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); - } else { - // Transfer fees to miner - track.addBalance(coinbase, summary.getFee()); - touchedAccounts.add(coinbase); - logger.info("Pay fees to miner: [{}], feesEarned: [{}]", Hex.toHexString(coinbase), summary.getFee()); - } - - if (blockchainConfig.eip161()) { - for (byte[] acctAddr : touchedAccounts) { - AccountState state = track.getAccountState(acctAddr); - if (state != null && state.isEmpty()) { - track.delete(acctAddr); - } - } - } - - - listener.onTransactionExecuted(summary); - - if (config.vmTrace() && program != null && result != null) { - String trace = program.getTrace() - .result(result.getHReturn()) - .error(result.getException()) - .toString(); - - - if (config.vmTraceCompressed()) { - trace = zipAndEncode(trace); - } - - String txHash = toHexString(tx.getHash()); - saveProgramTraceFile(config, txHash, trace); - listener.onVMTraceCreated(txHash, trace); - } - return summary; - } + /** + * Opening steps of transaction + * If transaction should create contract it creates, + * if it's calling existing it's loaded into VM + */ + void execute(); - public TransactionExecutor setLocalCall(boolean localCall) { - this.localCall = localCall; - return this; - } + /** + * Main execution of transaction + * If contract is involved program execution is done on this step + */ + void go(); + /** + * Called after execution is finished + * Pays rewards, do state modifications required by specs etc. + * Combines results from execution to Summary + */ + TransactionExecutionSummary finalization(); - public TransactionReceipt getReceipt() { - if (receipt == null) { - receipt = new TransactionReceipt(); - long gasUsed = getGasUsed(); - if (isCasperVote() && execError == null) { // Successful Casper vote - gasUsed = 0; - } - long totalGasUsed = gasUsedInTheBlock + gasUsed; - receipt.setCumulativeGas(totalGasUsed); - receipt.setTransaction(tx); - receipt.setLogInfoList(getVMLogs()); - receipt.setGasUsed(gasUsed); - receipt.setExecutionResult(getResult().getHReturn()); - receipt.setError(execError); -// receipt.setPostTxState(track.getRoot()); // TODO later when RepositoryTrack.getRoot() is implemented - } - return receipt; - } + /** + * Local execution does not spend gas on VM work + * Usually executor with localCall turned on is + * used for calling of constant methods + */ + TransactionExecutor setLocalCall(boolean localCall); - public List getVMLogs() { - return logs; - } + /** + * @return {@link TransactionReceipt} filled with data from execution result + */ + TransactionReceipt getReceipt(); - public ProgramResult getResult() { - return result; - } + /** + * @return list of {@link LogInfo}'s submitted during VM execution + */ + List getVMLogs(); - public long getGasUsed() { - long gasUsed = toBI(tx.getGasLimit()).subtract(m_endGas).longValue(); - if (result != null && execError == null && isCasperVote()) { - gasUsed = 0; - } - return gasUsed; - } + /** + * Result of program execution + */ + ProgramResult getResult(); + /** + * @return amount of gas used for tx execution + */ + long getGasUsed(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java index 6ec8865bc4..5c3f25f7b8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java @@ -274,7 +274,7 @@ protected BlockSummary applyBlock(Repository track, Block block) { stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); Repository txTrack = track.startTracking(); - TransactionExecutor executor = new TransactionExecutor(tx, block.getCoinbase(), + TransactionExecutor executor = strategy.createTransactionExecutor(tx, block.getCoinbase(), txTrack, blockStore, getProgramInvokeFactory(), block, listener, totalGasUsed) .withCommonConfig(commonConfig); @@ -346,7 +346,7 @@ private void initCasper(Repository track, Block block) { track.addBalance(NULL_SENDER.getAddress(), BigInteger.valueOf(15).pow(18)); Repository txTrack = track.startTracking(); - TransactionExecutor executor = new TransactionExecutor(tx, genesis.getCoinbase(), + TransactionExecutor executor = strategy.createTransactionExecutor(tx, genesis.getCoinbase(), txTrack, blockStore, getProgramInvokeFactory(), genesis, listener, 0) .withCommonConfig(commonConfig); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java new file mode 100644 index 0000000000..60d09e7edc --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; +import org.ethereum.core.Block; +import org.ethereum.core.CommonTransactionExecutor; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutionSummary; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.db.BlockStore; +import org.ethereum.listener.EthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigInteger; +import java.util.Arrays; +import static org.ethereum.util.BIUtil.toBI; + +public class CasperTransactionExecutor extends CommonTransactionExecutor { + + public CasperTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, + ProgramInvokeFactory programInvokeFactory, Block currentBlock) { + + super(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, new EthereumListenerAdapter(), 0); + } + + public CasperTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, + ProgramInvokeFactory programInvokeFactory, Block currentBlock, + EthereumListener listener, long gasUsedInTheBlock) { + + super(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, listener, gasUsedInTheBlock); + } + + @Override + protected boolean isSignatureValid() { + return isCasperVote() || super.isSignatureValid(); + } + + @Override + public void execute() { + + if (!readyToExecute) return; + + if (!localCall && !isCasperVote()) { + track.increaseNonce(tx.getSender()); + + BigInteger txGasLimit = toBI(tx.getGasLimit()); + BigInteger txGasCost = toBI(tx.getGasPrice()).multiply(txGasLimit); + track.addBalance(tx.getSender(), txGasCost.negate()); + + if (logger.isInfoEnabled()) + logger.info("Paying: txGasCost: [{}], gasPrice: [{}], gasLimit: [{}]", txGasCost, toBI(tx.getGasPrice()), txGasLimit); + } + + if (tx.isContractCreation()) { + create(); + } else { + call(); + } + } + + private boolean isCasperVote() { + if (!(commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) + return false; + if (!Arrays.equals(tx.getSender(), Transaction.NULL_SENDER)) + return false; + if (config.getCasperAddress() == null) + return false; // Not yet initialized + if (!Arrays.equals(tx.getReceiveAddress(), config.getCasperAddress())) + return false; + + byte[] dataCopy = new byte[4]; + System.arraycopy(tx.getData(), 0, dataCopy, 0, 4); + return Arrays.equals(dataCopy, new byte[] {(byte) 0xe9, (byte) 0xdc, 0x06, 0x14}); + } + + @Override + protected void payRewards(final TransactionExecutionSummary summary) { + if (execError == null && isCasperVote()) { + // Return money to sender for succesful Casper vote + track.addBalance(tx.getSender(), summary.getFee()); + logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); + } else { + // Transfer fees to miner + track.addBalance(coinbase, summary.getFee()); + touchedAccounts.add(coinbase); + logger.info("Pay fees to miner: [{}], feesEarned: [{}]", Hex.toHexString(coinbase), summary.getFee()); + } + } + + @Override + public long getGasUsed() { + long gasUsed = super.getGasUsed(); + // Successful Casper vote 0 cost + if (getResult() != null && execError == null && isCasperVote()) { + gasUsed = 0; + } + return gasUsed; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java index d91b4829c5..d3376f8429 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java @@ -22,12 +22,17 @@ import org.ethereum.core.Blockchain; import org.ethereum.core.CallTransaction; import org.ethereum.core.Genesis; +import org.ethereum.core.Repository; import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutor; import org.ethereum.core.casper.CasperBlockchain; +import org.ethereum.core.casper.CasperTransactionExecutor; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.core.genesis.StateInit; +import org.ethereum.db.BlockStore; import org.ethereum.facade.Ethereum; import org.ethereum.facade.EthereumImpl; +import org.ethereum.listener.EthereumListener; import org.ethereum.manager.CasperValidatorService; import org.ethereum.validator.BlockHashRule; import org.ethereum.validator.BlockHeaderRule; @@ -42,6 +47,7 @@ import org.ethereum.validator.ParentNumberRule; import org.ethereum.validator.ProofOfWorkRule; import org.ethereum.vm.program.ProgramResult; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -140,6 +146,21 @@ public StateInit getInitState() { return stateInit; } + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock) { + return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); + } + + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { + return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, + listener, gasUsedInTheBlock); + } + public CallTransaction.Contract getCasper() { initCasper(); return casper; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java index ae8af02a8f..02325ab647 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java @@ -17,11 +17,18 @@ */ package org.ethereum.core.consensus; +import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.Genesis; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutor; import org.ethereum.core.genesis.StateInit; +import org.ethereum.db.BlockStore; +import org.ethereum.listener.EthereumListener; import org.ethereum.validator.BlockHeaderValidator; import org.ethereum.validator.ParentBlockHeaderValidator; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; public interface ConsensusStrategy { BlockHeaderValidator getHeaderValidator(); @@ -41,4 +48,11 @@ public interface ConsensusStrategy { * @return state initializer after state is initialized */ StateInit getInitState(); + + TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, + ProgramInvokeFactory programInvokeFactory, Block currentBlock); + + TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, + ProgramInvokeFactory programInvokeFactory, Block currentBlock, + EthereumListener listener, long gasUsedInTheBlock); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java index 84ad167692..b5714f5eb2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java @@ -18,10 +18,17 @@ package org.ethereum.core.consensus; import org.ethereum.config.SystemProperties; +import org.ethereum.core.Block; import org.ethereum.core.BlockchainImpl; +import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Genesis; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutor; import org.ethereum.core.genesis.CommonStateInit; import org.ethereum.core.genesis.StateInit; +import org.ethereum.db.BlockStore; +import org.ethereum.listener.EthereumListener; import org.ethereum.validator.BlockHashRule; import org.ethereum.validator.BlockHeaderRule; import org.ethereum.validator.BlockHeaderValidator; @@ -34,6 +41,7 @@ import org.ethereum.validator.ParentGasLimitRule; import org.ethereum.validator.ParentNumberRule; import org.ethereum.validator.ProofOfWorkRule; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.springframework.context.ApplicationContext; import java.util.ArrayList; @@ -114,6 +122,21 @@ public StateInit getInitState() { return stateInit; } + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock) { + return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); + } + + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { + return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, + listener, gasUsedInTheBlock); + } + public void setBlockchain(BlockchainImpl blockchain) { this.blockchain = blockchain; blockchain.setParentHeaderValidator(parentBlockHeaderValidator); diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java b/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java index 69015ba125..83f5d0206c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java @@ -18,6 +18,7 @@ package org.ethereum.facade; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.listener.EthereumListener; import org.ethereum.manager.AdminInfo; @@ -55,6 +56,8 @@ public interface Ethereum { Blockchain getBlockchain(); + ConsensusStrategy getConsensusStrategy(); + void addListener(EthereumListener listener); PeerClient getDefaultPeer(); diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index 9d81d8af4a..c3f9fac350 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -23,6 +23,7 @@ import org.ethereum.core.*; import org.ethereum.core.PendingState; import org.ethereum.core.Repository; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; @@ -146,6 +147,11 @@ public org.ethereum.facade.Blockchain getBlockchain() { return (org.ethereum.facade.Blockchain) worldManager.getBlockchain(); } + @Override + public ConsensusStrategy getConsensusStrategy() { + return commonConfig.consensusStrategy(); + } + public ImportResult addNewMinedBlock(Block block) { ImportResult importResult = worldManager.getBlockchain().tryToConnect(block); if (importResult == ImportResult.IMPORTED_BEST) { @@ -278,7 +284,7 @@ public BlockSummary replayBlock(Block block) { for (Transaction tx : block.getTransactionsList()) { Repository txTrack = track.startTracking(); - org.ethereum.core.TransactionExecutor executor = new org.ethereum.core.TransactionExecutor( + org.ethereum.core.TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor( tx, block.getCoinbase(), txTrack, worldManager.getBlockStore(), programInvokeFactory, block, worldManager.getListener(), 0) .withCommonConfig(commonConfig); @@ -310,8 +316,8 @@ private org.ethereum.core.TransactionExecutor callConstantImpl(Transaction tx, B .startTracking(); try { - org.ethereum.core.TransactionExecutor executor = new org.ethereum.core.TransactionExecutor - (tx, block.getCoinbase(), repository, worldManager.getBlockStore(), + org.ethereum.core.TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor( + tx, block.getCoinbase(), repository, worldManager.getBlockStore(), programInvokeFactory, block, new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig) .setLocalCall(true); diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 2cbfba654b..29601c4379 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -18,9 +18,11 @@ package org.ethereum.util.blockchain; import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.core.*; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.GenesisLoader; import org.ethereum.crypto.ECKey; import org.ethereum.datasource.*; @@ -606,8 +608,9 @@ public Object[] callConstFunction(Block callBlock, String functionName, Object.. Repository repository = getBlockchain().getRepository().getSnapshotTo(callBlock.getStateRoot()).startTracking(); try { - org.ethereum.core.TransactionExecutor executor = new org.ethereum.core.TransactionExecutor - (tx, callBlock.getCoinbase(), repository, getBlockchain().getBlockStore(), + ConsensusStrategy strategy = CommonConfig.getDefault().consensusStrategy(); + org.ethereum.core.TransactionExecutor executor = strategy.createTransactionExecutor( + tx, callBlock.getCoinbase(), repository, getBlockchain().getBlockStore(), getBlockchain().getProgramInvokeFactory(), callBlock) .setLocalCall(true); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java b/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java index 79b89ebd28..958fdbd4e5 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/TransactionTest.java @@ -437,7 +437,7 @@ protected ProgramResult executeTransaction(Transaction tx) { Block bestBlock = block; - TransactionExecutor executor = new TransactionExecutor + TransactionExecutor executor = new CommonTransactionExecutor (txConst, bestBlock.getCoinbase(), track, new BlockStoreDummy(), invokeFactory, bestBlock) .setLocalCall(true); @@ -691,7 +691,7 @@ protected Transaction createTx(BlockchainImpl blockchain, ECKey sender, byte[] r public TransactionExecutor executeTransaction(BlockchainImpl blockchain, Transaction tx) { Repository track = blockchain.getRepository().startTracking(); - TransactionExecutor executor = new TransactionExecutor(tx, new byte[32], blockchain.getRepository(), + TransactionExecutor executor = new CommonTransactionExecutor(tx, new byte[32], blockchain.getRepository(), blockchain.getBlockStore(), blockchain.getProgramInvokeFactory(), blockchain.getBestBlock()); executor.init(); diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/runners/StateTestRunner.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/runners/StateTestRunner.java index a49e2c5e6d..fd75702af1 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/runners/StateTestRunner.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/runners/StateTestRunner.java @@ -71,7 +71,7 @@ protected ProgramResult executeTransaction(Transaction tx) { Repository track = repository.startTracking(); TransactionExecutor executor = - new TransactionExecutor(transaction, env.getCurrentCoinbase(), track, new BlockStoreDummy(), + new CommonTransactionExecutor(transaction, env.getCurrentCoinbase(), track, new BlockStoreDummy(), invokeFactory, blockchain.getBestBlock()); try{ diff --git a/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java b/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java index f37a607b48..cd32555004 100644 --- a/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java @@ -207,8 +207,8 @@ public void onPendingTransactionsReceived(List transactions) { .getSnapshotTo(block.getStateRoot()) .startTracking(); try { - TransactionExecutor executor = new TransactionExecutor - (tx, block.getCoinbase(), repository, ethereum.getBlockchain().getBlockStore(), + TransactionExecutor executor = ethereum.getConsensusStrategy().createTransactionExecutor( + tx, block.getCoinbase(), repository, ethereum.getBlockchain().getBlockStore(), programInvokeFactory, block, new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig) .setLocalCall(true); From d736638a7b0ac707c063deb673bc6d445a99fb50 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 23 Feb 2018 15:40:51 +0300 Subject: [PATCH 03/67] Fixing Spring circular references --- .../core/consensus/CasperHybridConsensusStrategy.java | 1 - .../src/main/java/org/ethereum/manager/WorldManager.java | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java index d3376f8429..4450bb4fca 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java @@ -104,7 +104,6 @@ public CasperHybridConsensusStrategy(SystemProperties systemProperties, Applicat blockchain = ctx.getBean(CasperBlockchain.class); blockchain.setStrategy(this); - ethereum = ctx.getBean(Ethereum.class); this.ctx = ctx; } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index 3b00ba1b9e..efbbc630ea 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -20,6 +20,7 @@ import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; @@ -124,9 +125,13 @@ public WorldManager(final SystemProperties config, final Repository repository, @PostConstruct private void init() { ConsensusStrategy strategy = ctx.getBean(CommonConfig.class).consensusStrategy(); - loadBlockchain(strategy); ethereum = ctx.getBean(Ethereum.class); ethereum.setWorldManager(this); + // FIXME: Bad Spring fix + if (strategy instanceof CasperHybridConsensusStrategy) { + ((CasperHybridConsensusStrategy) strategy).setEthereum(ethereum); + } + loadBlockchain(strategy); channelManager.init(ethereum); ((PendingStateImpl) pendingState).postConstruct(); syncManager.init(channelManager, pool); From 3f1b724bf300d48161dde880ee175aa72784ba8f Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 23 Feb 2018 18:55:17 +0300 Subject: [PATCH 04/67] Fixing miner rejects casper votes --- .../java/org/ethereum/core/PendingStateImpl.java | 8 ++++++++ .../core/casper/CasperTransactionExecutor.java | 15 ++++++++++----- .../main/java/org/ethereum/mine/BlockMiner.java | 9 +++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 6e084412df..e1b3a51da3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -32,6 +32,8 @@ import org.apache.commons.collections4.map.LRUMap; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; +import org.ethereum.core.casper.CasperTransactionExecutor; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.TransactionStore; @@ -288,6 +290,12 @@ private String validate(Transaction tx) { return String.format("Invalid transaction: %s", e.getMessage()); } + // FIXME: Shouldn't be there + if ((commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) { + if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { + return null; // Doesn't require more checks + } + } if (config.getMineMinGasPrice().compareTo(ByteUtil.bytesToBigInteger(tx.getGasPrice())) > 0) { return "Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(tx.getGasPrice()); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java index 60d09e7edc..a29d1979b5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java @@ -16,6 +16,7 @@ * along with the ethereumJ library. If not, see . */ package org.ethereum.core.casper; +import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Repository; @@ -78,15 +79,19 @@ public void execute() { private boolean isCasperVote() { if (!(commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) return false; - if (!Arrays.equals(tx.getSender(), Transaction.NULL_SENDER)) + return isCasperVote(tx, config.getCasperAddress()); + } + + public static boolean isCasperVote(Transaction transaction, byte[] casperAddress) { + if (!Arrays.equals(transaction.getSender(), Transaction.NULL_SENDER)) + return false; + if (casperAddress == null) return false; - if (config.getCasperAddress() == null) - return false; // Not yet initialized - if (!Arrays.equals(tx.getReceiveAddress(), config.getCasperAddress())) + if (!Arrays.equals(transaction.getReceiveAddress(), casperAddress)) return false; byte[] dataCopy = new byte[4]; - System.arraycopy(tx.getData(), 0, dataCopy, 0, 4); + System.arraycopy(transaction.getData(), 0, dataCopy, 0, 4); return Arrays.equals(dataCopy, new byte[] {(byte) 0xe9, (byte) 0xdc, 0x06, 0x14}); } diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index ecc1c8833c..0defef0afe 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -22,6 +22,8 @@ import org.apache.commons.collections4.CollectionUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; +import org.ethereum.core.casper.CasperTransactionExecutor; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; @@ -193,6 +195,13 @@ private void onPendingStateChanged() { } protected boolean isAcceptableTx(Transaction tx) { + // FIXME: Shouldn't be there + if ((ethereum.getConsensusStrategy() instanceof CasperHybridConsensusStrategy)) { + if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { + return true; + } + } + return minGasPrice.compareTo(new BigInteger(1, tx.getGasPrice())) <= 0; } From 726f4f79bdaddc609413674c1a0436d9411f4d33 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 23 Feb 2018 22:00:54 +0300 Subject: [PATCH 05/67] Fixed Ethereum Harmony build dependency failing --- .../src/main/java/org/ethereum/manager/WorldManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index efbbc630ea..a0e5ee5c5b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -17,7 +17,6 @@ */ package org.ethereum.manager; -import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.core.consensus.CasperHybridConsensusStrategy; @@ -98,6 +97,8 @@ public class WorldManager { @Autowired private ApplicationContext ctx; + private ConsensusStrategy strategy; + private Ethereum ethereum; private SystemProperties config; @@ -115,6 +116,7 @@ public WorldManager(final SystemProperties config, final Repository repository, final EthereumListener listener, final ConsensusStrategy consensusStrategy, final BlockStore blockStore) { this.listener = listener; + this.strategy = consensusStrategy; this.blockchain = consensusStrategy.getBlockchain(); this.repository = repository; repository.setBlockchain(blockchain); @@ -124,7 +126,6 @@ public WorldManager(final SystemProperties config, final Repository repository, @PostConstruct private void init() { - ConsensusStrategy strategy = ctx.getBean(CommonConfig.class).consensusStrategy(); ethereum = ctx.getBean(Ethereum.class); ethereum.setWorldManager(this); // FIXME: Bad Spring fix From e2e3fd62a52e1fd7d8044f9c49b25960b65feea7 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 26 Feb 2018 20:46:02 +0300 Subject: [PATCH 06/67] Init Casper with passed params instead of hexcode --- .../core/genesis/CasperStateInit.java | 42 ++++++++++++++++--- .../src/main/resources/casper/casper.bin | 2 +- .../core/casper/CasperStateInitTest.java | 5 +-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java index 6015e1a8d5..4f88106719 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java @@ -18,8 +18,10 @@ package org.ethereum.core.genesis; import javafx.util.Pair; +import org.apache.commons.lang3.ArrayUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; +import org.ethereum.core.CallTransaction; import org.ethereum.core.Genesis; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; @@ -35,13 +37,27 @@ import java.util.ArrayList; import java.util.List; +import static org.ethereum.crypto.HashUtil.sha3; + public class CasperStateInit implements StateInit { + private static final Logger logger = LoggerFactory.getLogger("general"); + + public static final int WITHDRAWAL_DELAY = 5; + public static final double BASE_INTEREST_FACTOR = 0.1; + public static final double BASE_PENALTY_FACTOR = 0.0001; + public static final int MIN_DEPOSIT_ETH = 1500; + private Genesis genesis; + private Repository repository; + private Blockchain blockchain; + private SystemProperties systemProperties; + private ApplicationContext ctx; + private Genesis initGenesis; public final static ECKey NULL_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); @@ -122,21 +138,37 @@ public Pair> makeInitTxes() { nonce = nonce.add(BigInteger.ONE); } + // 0 - fund, 1 - rlp, 2 - fund, 3 - sig hasher, 4 - fund, 5 - purity checker + byte[] sigHasherContract = txs.get(3).getContractAddress(); + byte[] purityCheckerContract = txs.get(5).getContractAddress(); + // Casper! - // Currently there are hardcoded init args in bin, we should add it here instead try { + // Sources: + // https://github.com/ethereum/casper/blob/9106ad647857e6a545f55d7f6193bdc03bb9f5cd/casper/contracts/simple_casper.v.py String casperBinStr = systemProperties.getCasperBin(); - // Currently inited with following params: - // EPOCH_LENGTH=50, WITHDRAWAL_DELAY=5, BASE_INTEREST_FACTOR=0.1, BASE_PENALTY_FACTOR=0.0001 - // TODO: Use only contract BIN and merge with init encode byte[] casperBin = ByteUtil.hexStringToBytes(casperBinStr); + + CallTransaction.Contract contract = new CallTransaction.Contract(systemProperties.getCasperAbi()); + + byte[] casperInit = contract.getConstructor().encodeArguments( + systemProperties.getCasperEpochLength(), // Epoch length + WITHDRAWAL_DELAY, // Withdrawal delay + ECKey.fromPrivate(sha3("0".getBytes())).getAddress(), // Owner + sigHasherContract, // Signature hasher contract + purityCheckerContract, // Purity checker contract + BASE_INTEREST_FACTOR, // Base interest factor + BASE_PENALTY_FACTOR, // Base penalty factor + BigInteger.valueOf(MIN_DEPOSIT_ETH).multiply(BigInteger.TEN.pow(18)) // Minimum validator deposit in wei + ); + Transaction tx = new Transaction( ByteUtil.bigIntegerToBytes(nonce), ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), ByteUtil.longToBytesNoLeadZeroes(5_000_000), new byte[0], ByteUtil.longToBytesNoLeadZeroes(0), - casperBin, + ArrayUtils.addAll(casperBin, casperInit), // Merge contract and constructor args null); tx.sign(NULL_SENDER); diff --git a/ethereumj-core/src/main/resources/casper/casper.bin b/ethereumj-core/src/main/resources/casper/casper.bin index 85bcdc5d0b..52cb435173 100644 --- a/ethereumj-core/src/main/resources/casper/casper.bin +++ b/ethereumj-core/src/main/resources/casper/casper.bin @@ -1 +1 @@ -0x600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05261010061377f6101403934156100a857600080fd5b606051602061377f60c03960c051806040519013585780919012156100cc57600080fd5b506060516020602061377f0160c03960c051806040519013585780919012156100f457600080fd5b506020604061377f0160c03960c051602051811061011157600080fd5b506020606061377f0160c03960c051602051811061012e57600080fd5b506020608061377f0160c03960c051602051811061014b57600080fd5b50606051602060e061377f0160c03960c0518060405190135857809190121561017357600080fd5b50610140516010556101605160115560016002556101805160165568056bc75e2d63100000600d60c052602060c020556000600455606051601054806101b857600080fd5b4305806040519013585780919012156101d057600080fd5b6012556101a0516018556101c051601955600060075560006008556101e051601b5561020051601c557f632a9a52ef120699847d16b5c0f45b7d5ff4404dd8054906681967edc6094fbf601d5561022051601e5561376756600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526394113f78600051141561017b5734156100ac57600080fd5b60a051601554601254600b60c052602060c0200160c052602060c02060c052602060c0200154600754806100df57600080fd5b806402540be400830205905090508060805190135857809190121561010357600080fd5b60a0516015546003601254600b60c052602060c0200160c052602060c0200160c052602060c02001546008548061013957600080fd5b806402540be400830205905090508060805190135857809190121561015d57600080fd5b8082131561016b578061016d565b815b9050905060005260206000f3005b63843b0890600051141561022f576020600461014037341561019c57600080fd5b606051600435806040519013585780919012156101b857600080fd5b506402540be40060a051601254600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c0200154818102811983838305141761020057600080fd5b6402540be40081059050905090508060805190135857809190121561022457600080fd5b0560005260206000f3005b633b812ec360005114156102a657341561024857600080fd5b6402540be40060a051601254600d60c052602060c0200154600754818102811983838305141761027757600080fd5b6402540be40081059050905090508060805190135857809190121561029b57600080fd5b0560005260206000f3005b63679dea62600051141561031d5734156102bf57600080fd5b6402540be40060a051601254600d60c052602060c020015460085481810281198383830514176102ee57600080fd5b6402540be40081059050905090508060805190135857809190121561031257600080fd5b0560005260206000f3005b63b2ae3f50600051141561034357341561033657600080fd5b60155460005260206000f3005b63cadbbfc160005114156103c057341561035c57600080fd5b6060516001606051601054601254028060405190135857809190121561038157600080fd5b038060405190135857809190121561039857600080fd5b61010043038112156103a957600080fd5b4381106103b557600080fd5b4060005260206000f3005b63de7f997560005114156103fc5734156103d957600080fd5b3033146103e557600080fd5b6000600854136000600754131660005260206000f3005b63d286bb82600051141561051657341561041557600080fd5b30331461042157600080fd5b601254610140526001606051600261014051038060405190135857809190121561044a57600080fd5b600b60c052602060c0200160c052602060c0200154156104d057600460605160018254018060405190135857809190121561048457600080fd5b815550600754600855600760a051600554825401806080519013585780919012156104ae57600080fd5b815550600654600555600060065561014051600454600960c052602060c02001555b60045461014051600a60c052602060c0200155600c541561050f57606051600161014051038060405190135857809190121561050b57600080fd5b6015555b6000600c55005b63fa650b2a600051141561056d57341561052f57600080fd5b30331461053b57600080fd5b6012546101405260605160135461014051038060405190135857809190121561056357600080fd5b60005260206000f3005b6370af50be600051141561077d57341561058657600080fd5b30331461059257600080fd5b60125461014052600260206101c0600463fa650b2a6101605261017c6000305af16105bc57600080fd5b6101c05113156101e0526101e051156020610260600463de7f99756102005261021c6000305af16105ec57600080fd5b6102605115171561060257600060005260206000f35b60a051601554606051600161014051038060405190135857809190121561062857600080fd5b600b60c052602060c0200160c052602060c02060c052602060c02001546007548061065257600080fd5b806402540be400830205905090508060805190135857809190121561067657600080fd5b6102805260a051601554600360605160016101405103806040519013585780919012156106a257600080fd5b600b60c052602060c0200160c052602060c0200160c052602060c0200154600854806106cd57600080fd5b806402540be40083020590509050806080519013585780919012156106f157600080fd5b6102a052610280516102a0518082131561070b578061070d565b815b905090506102c05260a051600260a051601a546102c051818102811983838305141761073857600080fd5b6402540be40081059050905090508060805190135857809190121561075c57600080fd5b058060805190135857809190121561077357600080fd5b60005260206000f3005b636526ed72600051141561086857341561079657600080fd5b3033146107a257600080fd5b601254610140526001600c556001600260605160016101405103806040519013585780919012156107d257600080fd5b600b60c052602060c0200160c052602060c020015560016001606051600161014051038060405190135857809190121561080b57600080fd5b600b60c052602060c0200160c052602060c0200155606051600161014051038060405190135857809190121561084057600080fd5b601455606051600161014051038060405190135857809190121561086357600080fd5b601355005b63d9d341b96000511415610a52576020600461014037341561088957600080fd5b30331461089557600080fd5b606051600435806040519013585780919012156108b157600080fd5b5060605160016402540be40060a051670de0b6b3a764000060a05160605160016101405103806040519013585780919012156108ec57600080fd5b600d60c052602060c02001546008546007548082121561090c578061090e565b815b90509050818102811983838305141761092657600080fd5b6402540be40081059050905090508060805190135857809190121561094a57600080fd5b058060805190135857809190121561096157600080fd5b05018060405190135857809190121561097957600080fd5b6101605260a0516404a817c80068056bc75e2d63100000610160510205806080519013585780919012156109ac57600080fd5b610180526101a060006014818352015b60a051600260a05160a05161018051806109d557600080fd5b68056bc75e2d63100000610160510205806080519013585780919012156109fb57600080fd5b610180510180608051901358578091901215610a1657600080fd5b0580608051901358578091901215610a2d57600080fd5b610180525b81516001018083528114156109bc575b50506101805160005260206000f3005b635dcffc176000511415610ddb5760206004610140373415610a7357600080fd5b60605160043580604051901358578091901215610a8f57600080fd5b5060605160105480610aa057600080fd5b430580604051901358578091901215610ab857600080fd5b6101605260605160016012540180604051901358578091901215610adb57600080fd5b61014051146101605161014051131516610af457600080fd5b6101405160125560a051601a5460a05160206101e060046370af50be6101805261019c6000305af1610b2557600080fd5b6101e0516402540be4000180608051901358578091901215610b4657600080fd5b0380608051901358578091901215610b5d57600080fd5b600e5560a05160a051601a546402540be4000180608051901358578091901215610b8657600080fd5b600e548181028119838383051417610b9d57600080fd5b6402540be400810590509050905080608051901358578091901215610bc157600080fd5b600f5560a051600e546060516001610140510380604051901358578091901215610bea57600080fd5b600d60c052602060c02001548181028119838383051417610c0a57600080fd5b6402540be400810590509050905080608051901358578091901215610c2e57600080fd5b61014051600d60c052602060c020015560206102c0600463de7f99756102605261027c6000305af1610c5f57600080fd5b6102c05115610d5e5760a051601b546020610360602463d9d341b96102e05261014051610300526102fc6000305af1610c9757600080fd5b6103605180610ca557600080fd5b806402540be4008302059050905080608051901358578091901215610cc957600080fd5b6103805260a05160a0516020610400600463fa650b2a6103a0526103bc6000305af1610cf457600080fd5b61040051601c548181028119838383051417610d0f57600080fd5b8090509050905080608051901358578091901215610d2c57600080fd5b610380510180608051901358578091901215610d4757600080fd5b601a556000601a5413610d5957600080fd5b610d84565b600060006004636526ed726102005261021c6000305af1610d7e57600080fd5b6000601a555b60006000600463d286bb826104205261043c6000305af1610da457600080fd5b60206104e0600463cadbbfc16104805261049c6000305af1610dc557600080fd5b6104e05161014051600160c052602060c0200155005b63f9609f0860005114156110915760406004610140376004356020518110610e0257600080fd5b506024356020518110610e1457600080fd5b5060605160105480610e2557600080fd5b430580604051901358578091901215610e3d57600080fd5b60125414610e4a57600080fd5b600060006004610180527fa1903eab000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101e001018260208501600060046012f1505080518201915050610140516020826101e0010152602081019050806101e0526101e09050805160200180610260828460006004600a8704601201f1610ed957600080fd5b505060206103006102605161028060006019546207a120f1610efa57600080fd5b60206102e0526102e0602060006020835103811315610f1857600080fd5b0460200260200181015190501415610f2f57600080fd5b61016051600360c052602060c020015415610f4957600080fd5b601e54341215610f5857600080fd5b600254600060c052602060c0200160c052602060c02061014051815560a051601254600d60c052602060c020015480610f9057600080fd5b68056bc75e2d6310000034020580608051901358578091901215610fb357600080fd5b60018201556c0c9f2c9cd04674edea40000000600282015560605160026004540180604051901358578091901215610fea57600080fd5b60038201556101605160048201555060025461016051600360c052602060c0200155600260605160018254018060405190135857809190121561102c57600080fd5b815550600660a05160a051601254600d60c052602060c02001548061105057600080fd5b68056bc75e2d631000003402058060805190135857809190121561107357600080fd5b8254018060805190135857809190121561108c57600080fd5b815550005b6342310c32600051141561148557602060046101403734156110b257600080fd5b610420600435600401610160376104006004356004013511156110d457600080fd5b606051601054806110e457600080fd5b4305806040519013585780919012156110fc57600080fd5b6012541461110957600080fd5b6101608051602001806105a0828460006004600a8704601201f161112c57600080fd5b50506020610a006105a0516105c0600060185462030d40f161114d57600080fd5b60206109e0526109e060206000602083510381131561116b57600080fd5b046020026020018101519050610a4052611000610160610560610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610aa0f150506080610a6051146111ba57600080fd5b610a6051610a60018060200151600082518060209013585780919012156111e057600080fd5b601f6101000a82048115176111f457600080fd5b606051816020036101000a83048060405190135857809190121561121757600080fd5b9050905090508152610a8051610a600180602001516000825180602090135857809190121561124557600080fd5b601f6101000a820481151761125957600080fd5b606051816020036101000a83048060405190135857809190121561127c57600080fd5b9050905090508160200152610aa051610a600180516020018083604001828460006004600a8704601201f16112b057600080fd5b5050506110005161148052611020516114a0526110408051602001806114c0828460006004600a8704601201f16112e657600080fd5b50506114a05160125412156112fa57600080fd5b60016000610a40516020826119000101526020810190506114c06104008060208461190001018260208501600060046078f150508051820191505080611900526119009050805160200180611d60828460006004600a8704601201f161135f57600080fd5b505060206121e0611d6051611d80600061148051600060c052602060c0200160c052602060c020546207a120f161139557600080fd5b60206121c0526121c06020600060208351038113156113b357600080fd5b046020026020018101519050146113c957600080fd5b606051600260045401806040519013585780919012156113e857600080fd5b600261148051600060c052602060c0200160c052602060c02001541361140d57600080fd5b6060516002600454018060405190135857809190121561142c57600080fd5b600261148051600060c052602060c0200160c052602060c0200155600660a051600161148051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561148057600080fd5b815550005b6301b7af1860005114156115af57602060046101403734156114a657600080fd5b3033146114b257600080fd5b606051600435806040519013585780919012156114ce57600080fd5b50606051600260045401806040519013585780919012156114ee57600080fd5b600261014051600060c052602060c0200160c052602060c0200154131561154c57600560a051600161014051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561154857600080fd5b8155505b6000600461014051600060c052602060c0200160c052602060c0200154600360c052602060c020015561014051600060c052602060c0200160c052602060c020600081556000600182015560006002820155600060038201556000600482015550005b63edea1480600051141561177657602060046101403734156115d057600080fd5b606051600435806040519013585780919012156115ec57600080fd5b506060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561162457600080fd5b600454121561163257600080fd5b6060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561166957600080fd5b600960c052602060c02001546101605260605160115461016051018060405190135857809190121561169a57600080fd5b60125412156116a857600080fd5b6402540be40060a05161016051600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c020015481810281198383830514176116f057600080fd5b6402540be40081059050905090508060805190135857809190121561171457600080fd5b0561018052600060006000600061018051600461014051600060c052602060c0200160c052602060c02001546000f161174c57600080fd5b6000600060246301b7af186101a052610140516101c0526101bc6000305af161177457600080fd5b005b63579f38b26000511415611a70576040600461014037341561179757600080fd5b3033146117a357600080fd5b606051600435806040519013585780919012156117bf57600080fd5b50606051602435806040519013585780919012156117dc57600080fd5b50600361014051600060c052602060c0200160c052602060c0200154600960c052602060c020015461018052600161014051600060c052602060c0200160c052602060c0200160a0516402540be40061016051028254018060805190135857809190121561184957600080fd5b815550600361014051600060c052602060c0200160c052602060c02001546101a052600261014051600060c052602060c0200160c052602060c02001546101c0526004546101e05260605160016101e05103806040519013585780919012156118b157600080fd5b610200526101c0516101e051126101e0516101a051131516156118fb57600760a0516402540be4006101605102825401806080519013585780919012156118f757600080fd5b8155505b6101c0516102005112610200516101a0511315161561194157600860a0516402540be40061016051028254018060805190135857809190121561193d57600080fd5b8155505b60605160016101c051038060405190135857809190121561196157600080fd5b6101e051141561199857600560a0516402540be40061016051028254038060805190135857809190121561199457600080fd5b8155505b60605160026101c05103806040519013585780919012156119b857600080fd5b6101e05114156119ef57600660a0516402540be4006101605102825403806080519013585780919012156119eb57600080fd5b8155505b60006000600060006402540be40060a051600860a051601254600d60c052602060c0200154610160518181028119838383051417611a2c57600080fd5b8090509050905080608051901358578091901215611a4957600080fd5b0580608051901358578091901215611a6057600080fd5b05416000f1611a6e57600080fd5b005b63e9dc061460005114156123ec5760206004610140373415611a9157600080fd5b61042060043560040161016037610400600435600401351115611ab357600080fd5b6101608051602001806105a0828460006004600a8704601201f1611ad657600080fd5b50506020610a006105a0516105c0600060185462030d40f1611af757600080fd5b60206109e0526109e0602060006020835103811315611b1557600080fd5b046020026020018101519050610a40526110c0610160610620610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610a605114611b6457600080fd5b610a6051610a6001806020015160008251806020901358578091901215611b8a57600080fd5b601f6101000a8204811517611b9e57600080fd5b606051816020036101000a830480604051901358578091901215611bc157600080fd5b90509050905081526020610a8051610a60015114611bde57600080fd5b610a8051610a8001518160200152610aa051610a6001806020015160008251806020901358578091901215611c1257600080fd5b601f6101000a8204811517611c2657600080fd5b606051816020036101000a830480604051901358578091901215611c4957600080fd5b9050905090508160400152610ac051610a6001806020015160008251806020901358578091901215611c7a57600080fd5b601f6101000a8204811517611c8e57600080fd5b606051816020036101000a830480604051901358578091901215611cb157600080fd5b9050905090508160600152610ae051610a600180516020018083608001828460006004600a8704601201f1611ce557600080fd5b5050506110c051611580526110e0516115a052611100516115c052611120516115e052611140805160200180611600828460006004600a8704601201f1611d2b57600080fd5b505060016000610a4051602082611a4001015260208101905061160061040080602084611a4001018260208501600060046078f150508051820191505080611a4052611a409050805160200180611ea0828460006004600a8704601201f1611d9257600080fd5b50506020612320611ea051611ec0600061158051600060c052602060c0200160c052602060c020546207a120f1611dc857600080fd5b602061230052612300602060006020835103811315611de657600080fd5b04602002602001810151905014611dfc57600080fd5b6001606051610100611580510780604051901358578091901215611e1f57600080fd5b600081131515611e37578060000360020a8204611e3e565b8060020a82025b90509050606051610100611580510580604051901358578091901215611e6357600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541615611e9f57600080fd5b60206123c0600463cadbbfc16123605261237c6000305af1611ec057600080fd5b6123c0516115a05114611ed257600080fd5b60026115e051600b60c052602060c0200160c052602060c0200154611ef657600080fd5b600361158051600060c052602060c0200160c052602060c02001546123e052600261158051600060c052602060c0200160c052602060c0200154612400526115c051600a60c052602060c0200154612420526060516001612420510380604051901358578091901215611f6857600080fd5b61244052612400516124205112612420516123e05113151661246052612400516124405112612440516123e05113151661248052612480516124605117611fae57600080fd5b6001606051610100611580510780604051901358578091901215611fd157600080fd5b600081131515611fe9578060000360020a8204611ff0565b8060020a82025b9050905060605161010061158051058060405190135857809190121561201557600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541760605161010061158051058060405190135857809190121561206857600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001556115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001546124a0526115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001546124c052612460511561215e576124a060a051600161158051600060c052602060c0200160c052602060c02001548251018060805190135857809190121561213157600080fd5b8152506124a0516115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001555b61248051156121d1576124c060a051600161158051600060c052602060c0200160c052602060c0200154825101806080519013585780919012156121a157600080fd5b8152506124c0516115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001555b6115e051601554146115c05160125414161561227c576402540be40060a051601a54600161158051600060c052602060c0200160c052602060c0200154818102811983838305141761222257600080fd5b6402540be40081059050905090508060805190135857809190121561224657600080fd5b056124e05260006000604463579f38b26125005261158051612520526124e0516125405261251c6000305af161227b57600080fd5b5b60026115c051600b60c052602060c0200160c052602060c02001541560a051600360a051600260085481810281198383830514176122b957600080fd5b80905090509050806080519013585780919012156122d657600080fd5b05806080519013585780919012156122ed57600080fd5b6124c051121560a051600360a0516002600754818102811983838305141761231457600080fd5b809050905090508060805190135857809190121561233157600080fd5b058060805190135857809190121561234857600080fd5b6124a05112151616156123dc57600160026115c051600b60c052602060c0200160c052602060c02001556115c0516014556012546115c051141561238c576001600c555b60605160016115e05101806040519013585780919012156123ac57600080fd5b6115c05114156123db57600160016115e051600b60c052602060c0200160c052602060c02001556115e0516013555b5b610160601d54815160208301a150005b63cc20f16b6000511415612c4d576040600461014037341561240d57600080fd5b6104206004356004016101803761040060043560040135111561242f57600080fd5b6104206024356004016105c03761040060243560040135111561245157600080fd5b610180805160200180610a00828460006004600a8704601201f161247457600080fd5b50506020610e60610a0051610a20600060185462030d40f161249557600080fd5b6020610e4052610e406020600060208351038113156124b357600080fd5b046020026020018101519050610ea052611520610180610620610ec08251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610ec0511461250257600080fd5b610ec051610ec00180602001516000825180602090135857809190121561252857600080fd5b601f6101000a820481151761253c57600080fd5b606051816020036101000a83048060405190135857809190121561255f57600080fd5b90509050905081526020610ee051610ec001511461257c57600080fd5b610ee051610ee001518160200152610f0051610ec0018060200151600082518060209013585780919012156125b057600080fd5b601f6101000a82048115176125c457600080fd5b606051816020036101000a8304806040519013585780919012156125e757600080fd5b9050905090508160400152610f2051610ec00180602001516000825180602090135857809190121561261857600080fd5b601f6101000a820481151761262c57600080fd5b606051816020036101000a83048060405190135857809190121561264f57600080fd5b9050905090508160600152610f4051610ec00180516020018083608001828460006004600a8704601201f161268357600080fd5b505050611520516119e05261156051611a005261158051611a20526115a0805160200180611a40828460006004600a8704601201f16126c157600080fd5b505060016000610ea051602082611e80010152602081019050611a4061040080602084611e8001018260208501600060046078f150508051820191505080611e8052611e8090508051602001806122e0828460006004600a8704601201f161272857600080fd5b505060206127606122e05161230060006119e051600060c052602060c0200160c052602060c020546207a120f161275e57600080fd5b60206127405261274060206000602083510381131561277c57600080fd5b0460200260200181015190501461279257600080fd5b6105c08051602001806127a0828460006004600a8704601201f16127b557600080fd5b50506020612c006127a0516127c0600060185462030d40f16127d657600080fd5b6020612be052612be06020600060208351038113156127f457600080fd5b046020026020018101519050612c40526115206105c0610620612c608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0612c60511461284357600080fd5b612c6051612c600180602001516000825180602090135857809190121561286957600080fd5b601f6101000a820481151761287d57600080fd5b606051816020036101000a8304806040519013585780919012156128a057600080fd5b90509050905081526020612c8051612c600151146128bd57600080fd5b612c8051612c8001518160200152612ca051612c60018060200151600082518060209013585780919012156128f157600080fd5b601f6101000a820481151761290557600080fd5b606051816020036101000a83048060405190135857809190121561292857600080fd5b9050905090508160400152612cc051612c600180602001516000825180602090135857809190121561295957600080fd5b601f6101000a820481151761296d57600080fd5b606051816020036101000a83048060405190135857809190121561299057600080fd5b9050905090508160600152612ce051612c600180516020018083608001828460006004600a8704601201f16129c457600080fd5b505050611520516132c052611560516132e05261158051613300526115a0805160200180613320828460006004600a8704601201f1612a0257600080fd5b505060016000612c40516020826137600101526020810190506133206104008060208461376001018260208501600060046078f150508051820191505080613760526137609050805160200180613bc0828460006004600a8704601201f1612a6957600080fd5b50506020614040613bc051613be060006132c051600060c052602060c0200160c052602060c020546207a120f1612a9f57600080fd5b602061402052614020602060006020835103811315612abd57600080fd5b04602002602001810151905014612ad357600080fd5b6132c0516119e05114612ae557600080fd5b612c4051610ea0511415612af857600080fd5b6000614080526132e051611a00511415612b1757600161408052612b4b565b611a20516133005112611a00516132e051131661330051611a2051126132e051611a005113161715612b4a576001614080525b5b61408051612b5857600080fd5b6020614120602463843b08906140a0526119e0516140c0526140bc6000305af1612b8157600080fd5b61412051614140526060516019614140510580604051901358578091901215612ba957600080fd5b61416052601760605160605160196060516018614140510280604051901358578091901215612bd757600080fd5b0580604051901358578091901215612bee57600080fd5b82540180604051901358578091901215612c0757600080fd5b8155506000600060246301b7af18614180526119e0516141a05261419c6000305af1612c3257600080fd5b600060006000600061416051336000f1612c4b57600080fd5b005b6334ef39f16000511415612c87573415612c6657600080fd5b60006000600060006017546016546000f1612c8057600080fd5b6000601755005b63253c8bd46000511415612cce5760206004610140373415612ca857600080fd5b6004356020518110612cb957600080fd5b50336016541415612ccc57610140516016555b005b63e395dc656000511415612d315760206004610140373415612cef57600080fd5b60605160043580604051901358578091901215612d0b57600080fd5b50600161014051600060c052602060c0200160c052602060c020015460005260206000f3005b6312b2a50a6000511415612d945760206004610140373415612d5257600080fd5b60605160043580604051901358578091901215612d6e57600080fd5b50600361014051600060c052602060c0200160c052602060c020015460005260206000f3005b63fc2d45406000511415612df75760206004610140373415612db557600080fd5b60605160043580604051901358578091901215612dd157600080fd5b50600261014051600060c052602060c0200160c052602060c020015460005260206000f3005b635302508f6000511415612e575760206004610140373415612e1857600080fd5b60605160043580604051901358578091901215612e3457600080fd5b5061014051600060c052602060c0200160c052602060c0205460005260206000f3005b637601d5636000511415612eba5760206004610140373415612e7857600080fd5b60605160043580604051901358578091901215612e9457600080fd5b50600461014051600060c052602060c0200160c052602060c020015460005260206000f3005b639abcf69c6000511415612f125760206004610140373415612edb57600080fd5b60605160043580604051901358578091901215612ef757600080fd5b5061014051600160c052602060c020015460005260206000f3005b63363258856000511415612f38573415612f2b57600080fd5b60025460005260206000f3005b63e46cec606000511415612f855760206004610140373415612f5957600080fd5b6004356020518110612f6a57600080fd5b5061014051600360c052602060c020015460005260206000f3005b63a0b286d66000511415612fab573415612f9e57600080fd5b60045460005260206000f3005b632c7e5aa26000511415612fd1573415612fc457600080fd5b60055460005260206000f3005b63a5fd35156000511415612ff7573415612fea57600080fd5b60065460005260206000f3005b62bc82df600051141561304e576020600461014037341561301757600080fd5b6060516004358060405190135857809190121561303357600080fd5b5061014051600960c052602060c020015460005260206000f3005b635320e5ba60005114156130a6576020600461014037341561306f57600080fd5b6060516004358060405190135857809190121561308b57600080fd5b5061014051600a60c052602060c020015460005260206000f3005b63f64927c3600051141561313057604060046101403734156130c757600080fd5b606051600435806040519013585780919012156130e357600080fd5b506060516024358060405190135857809190121561310057600080fd5b506101605161014051600b60c052602060c0200160c052602060c02060c052602060c020015460005260206000f3005b6348e821a960005114156131bd576040600461014037341561315157600080fd5b6060516004358060405190135857809190121561316d57600080fd5b506060516024358060405190135857809190121561318a57600080fd5b5061016051600361014051600b60c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b6356b861a1600051141561325757606060046101403734156131de57600080fd5b606051600435806040519013585780919012156131fa57600080fd5b506060516044358060405190135857809190121561321757600080fd5b506101805161016051600461014051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b63668d56fd60005114156132ba576020600461014037341561327857600080fd5b6060516004358060405190135857809190121561329457600080fd5b50600261014051600b60c052602060c0200160c052602060c020015460005260206000f3005b63625f375b600051141561331d57602060046101403734156132db57600080fd5b606051600435806040519013585780919012156132f757600080fd5b50600161014051600b60c052602060c0200160c052602060c020015460005260206000f3005b633f98cdef600051141561334357341561333657600080fd5b600c5460005260206000f3005b63a219390b600051141561339b576020600461014037341561336457600080fd5b6060516004358060405190135857809190121561338057600080fd5b5061014051600d60c052602060c020015460005260206000f3005b63ef5212dd60005114156133c15734156133b457600080fd5b600e5460005260206000f3005b636a5df9f460005114156133e75734156133da57600080fd5b600f5460005260206000f3005b6305fb1083600051141561340d57341561340057600080fd5b60105460005260206000f3005b63c3826907600051141561343357341561342657600080fd5b60115460005260206000f3005b63837a9bc7600051141561345957341561344c57600080fd5b60125460005260206000f3005b63634d0f77600051141561347f57341561347257600080fd5b60135460005260206000f3005b638370f33860005114156134a557341561349857600080fd5b60145460005260206000f3005b63ffb7619b60005114156134cb5734156134be57600080fd5b60155460005260206000f3005b63350d3fae60005114156134f15734156134e457600080fd5b601a5460005260206000f3005b63fba2b1b3600051141561351757341561350a57600080fd5b601b5460005260206000f3005b63199dfefa600051141561353d57341561353057600080fd5b601c5460005260206000f3005b5b61022961376703610229600039610229613767036000f30000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000500000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1000000000000000000000000dffd41e18f04ad8810c83b14fd1426a82e625a7d0000000000000000000000009f56d05661285a8fcc0dbdb3c8070ad024030af3000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000005150ae84a8cdf00000 \ No newline at end of file +600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05261010061377f6101403934156100a857600080fd5b606051602061377f60c03960c051806040519013585780919012156100cc57600080fd5b506060516020602061377f0160c03960c051806040519013585780919012156100f457600080fd5b506020604061377f0160c03960c051602051811061011157600080fd5b506020606061377f0160c03960c051602051811061012e57600080fd5b506020608061377f0160c03960c051602051811061014b57600080fd5b50606051602060e061377f0160c03960c0518060405190135857809190121561017357600080fd5b50610140516010556101605160115560016002556101805160165568056bc75e2d63100000600d60c052602060c020556000600455606051601054806101b857600080fd5b4305806040519013585780919012156101d057600080fd5b6012556101a0516018556101c051601955600060075560006008556101e051601b5561020051601c557f632a9a52ef120699847d16b5c0f45b7d5ff4404dd8054906681967edc6094fbf601d5561022051601e5561376756600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526394113f78600051141561017b5734156100ac57600080fd5b60a051601554601254600b60c052602060c0200160c052602060c02060c052602060c0200154600754806100df57600080fd5b806402540be400830205905090508060805190135857809190121561010357600080fd5b60a0516015546003601254600b60c052602060c0200160c052602060c0200160c052602060c02001546008548061013957600080fd5b806402540be400830205905090508060805190135857809190121561015d57600080fd5b8082131561016b578061016d565b815b9050905060005260206000f3005b63843b0890600051141561022f576020600461014037341561019c57600080fd5b606051600435806040519013585780919012156101b857600080fd5b506402540be40060a051601254600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c0200154818102811983838305141761020057600080fd5b6402540be40081059050905090508060805190135857809190121561022457600080fd5b0560005260206000f3005b633b812ec360005114156102a657341561024857600080fd5b6402540be40060a051601254600d60c052602060c0200154600754818102811983838305141761027757600080fd5b6402540be40081059050905090508060805190135857809190121561029b57600080fd5b0560005260206000f3005b63679dea62600051141561031d5734156102bf57600080fd5b6402540be40060a051601254600d60c052602060c020015460085481810281198383830514176102ee57600080fd5b6402540be40081059050905090508060805190135857809190121561031257600080fd5b0560005260206000f3005b63b2ae3f50600051141561034357341561033657600080fd5b60155460005260206000f3005b63cadbbfc160005114156103c057341561035c57600080fd5b6060516001606051601054601254028060405190135857809190121561038157600080fd5b038060405190135857809190121561039857600080fd5b61010043038112156103a957600080fd5b4381106103b557600080fd5b4060005260206000f3005b63de7f997560005114156103fc5734156103d957600080fd5b3033146103e557600080fd5b6000600854136000600754131660005260206000f3005b63d286bb82600051141561051657341561041557600080fd5b30331461042157600080fd5b601254610140526001606051600261014051038060405190135857809190121561044a57600080fd5b600b60c052602060c0200160c052602060c0200154156104d057600460605160018254018060405190135857809190121561048457600080fd5b815550600754600855600760a051600554825401806080519013585780919012156104ae57600080fd5b815550600654600555600060065561014051600454600960c052602060c02001555b60045461014051600a60c052602060c0200155600c541561050f57606051600161014051038060405190135857809190121561050b57600080fd5b6015555b6000600c55005b63fa650b2a600051141561056d57341561052f57600080fd5b30331461053b57600080fd5b6012546101405260605160135461014051038060405190135857809190121561056357600080fd5b60005260206000f3005b6370af50be600051141561077d57341561058657600080fd5b30331461059257600080fd5b60125461014052600260206101c0600463fa650b2a6101605261017c6000305af16105bc57600080fd5b6101c05113156101e0526101e051156020610260600463de7f99756102005261021c6000305af16105ec57600080fd5b6102605115171561060257600060005260206000f35b60a051601554606051600161014051038060405190135857809190121561062857600080fd5b600b60c052602060c0200160c052602060c02060c052602060c02001546007548061065257600080fd5b806402540be400830205905090508060805190135857809190121561067657600080fd5b6102805260a051601554600360605160016101405103806040519013585780919012156106a257600080fd5b600b60c052602060c0200160c052602060c0200160c052602060c0200154600854806106cd57600080fd5b806402540be40083020590509050806080519013585780919012156106f157600080fd5b6102a052610280516102a0518082131561070b578061070d565b815b905090506102c05260a051600260a051601a546102c051818102811983838305141761073857600080fd5b6402540be40081059050905090508060805190135857809190121561075c57600080fd5b058060805190135857809190121561077357600080fd5b60005260206000f3005b636526ed72600051141561086857341561079657600080fd5b3033146107a257600080fd5b601254610140526001600c556001600260605160016101405103806040519013585780919012156107d257600080fd5b600b60c052602060c0200160c052602060c020015560016001606051600161014051038060405190135857809190121561080b57600080fd5b600b60c052602060c0200160c052602060c0200155606051600161014051038060405190135857809190121561084057600080fd5b601455606051600161014051038060405190135857809190121561086357600080fd5b601355005b63d9d341b96000511415610a52576020600461014037341561088957600080fd5b30331461089557600080fd5b606051600435806040519013585780919012156108b157600080fd5b5060605160016402540be40060a051670de0b6b3a764000060a05160605160016101405103806040519013585780919012156108ec57600080fd5b600d60c052602060c02001546008546007548082121561090c578061090e565b815b90509050818102811983838305141761092657600080fd5b6402540be40081059050905090508060805190135857809190121561094a57600080fd5b058060805190135857809190121561096157600080fd5b05018060405190135857809190121561097957600080fd5b6101605260a0516404a817c80068056bc75e2d63100000610160510205806080519013585780919012156109ac57600080fd5b610180526101a060006014818352015b60a051600260a05160a05161018051806109d557600080fd5b68056bc75e2d63100000610160510205806080519013585780919012156109fb57600080fd5b610180510180608051901358578091901215610a1657600080fd5b0580608051901358578091901215610a2d57600080fd5b610180525b81516001018083528114156109bc575b50506101805160005260206000f3005b635dcffc176000511415610ddb5760206004610140373415610a7357600080fd5b60605160043580604051901358578091901215610a8f57600080fd5b5060605160105480610aa057600080fd5b430580604051901358578091901215610ab857600080fd5b6101605260605160016012540180604051901358578091901215610adb57600080fd5b61014051146101605161014051131516610af457600080fd5b6101405160125560a051601a5460a05160206101e060046370af50be6101805261019c6000305af1610b2557600080fd5b6101e0516402540be4000180608051901358578091901215610b4657600080fd5b0380608051901358578091901215610b5d57600080fd5b600e5560a05160a051601a546402540be4000180608051901358578091901215610b8657600080fd5b600e548181028119838383051417610b9d57600080fd5b6402540be400810590509050905080608051901358578091901215610bc157600080fd5b600f5560a051600e546060516001610140510380604051901358578091901215610bea57600080fd5b600d60c052602060c02001548181028119838383051417610c0a57600080fd5b6402540be400810590509050905080608051901358578091901215610c2e57600080fd5b61014051600d60c052602060c020015560206102c0600463de7f99756102605261027c6000305af1610c5f57600080fd5b6102c05115610d5e5760a051601b546020610360602463d9d341b96102e05261014051610300526102fc6000305af1610c9757600080fd5b6103605180610ca557600080fd5b806402540be4008302059050905080608051901358578091901215610cc957600080fd5b6103805260a05160a0516020610400600463fa650b2a6103a0526103bc6000305af1610cf457600080fd5b61040051601c548181028119838383051417610d0f57600080fd5b8090509050905080608051901358578091901215610d2c57600080fd5b610380510180608051901358578091901215610d4757600080fd5b601a556000601a5413610d5957600080fd5b610d84565b600060006004636526ed726102005261021c6000305af1610d7e57600080fd5b6000601a555b60006000600463d286bb826104205261043c6000305af1610da457600080fd5b60206104e0600463cadbbfc16104805261049c6000305af1610dc557600080fd5b6104e05161014051600160c052602060c0200155005b63f9609f0860005114156110915760406004610140376004356020518110610e0257600080fd5b506024356020518110610e1457600080fd5b5060605160105480610e2557600080fd5b430580604051901358578091901215610e3d57600080fd5b60125414610e4a57600080fd5b600060006004610180527fa1903eab000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101e001018260208501600060046012f1505080518201915050610140516020826101e0010152602081019050806101e0526101e09050805160200180610260828460006004600a8704601201f1610ed957600080fd5b505060206103006102605161028060006019546207a120f1610efa57600080fd5b60206102e0526102e0602060006020835103811315610f1857600080fd5b0460200260200181015190501415610f2f57600080fd5b61016051600360c052602060c020015415610f4957600080fd5b601e54341215610f5857600080fd5b600254600060c052602060c0200160c052602060c02061014051815560a051601254600d60c052602060c020015480610f9057600080fd5b68056bc75e2d6310000034020580608051901358578091901215610fb357600080fd5b60018201556c0c9f2c9cd04674edea40000000600282015560605160026004540180604051901358578091901215610fea57600080fd5b60038201556101605160048201555060025461016051600360c052602060c0200155600260605160018254018060405190135857809190121561102c57600080fd5b815550600660a05160a051601254600d60c052602060c02001548061105057600080fd5b68056bc75e2d631000003402058060805190135857809190121561107357600080fd5b8254018060805190135857809190121561108c57600080fd5b815550005b6342310c32600051141561148557602060046101403734156110b257600080fd5b610420600435600401610160376104006004356004013511156110d457600080fd5b606051601054806110e457600080fd5b4305806040519013585780919012156110fc57600080fd5b6012541461110957600080fd5b6101608051602001806105a0828460006004600a8704601201f161112c57600080fd5b50506020610a006105a0516105c0600060185462030d40f161114d57600080fd5b60206109e0526109e060206000602083510381131561116b57600080fd5b046020026020018101519050610a4052611000610160610560610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610aa0f150506080610a6051146111ba57600080fd5b610a6051610a60018060200151600082518060209013585780919012156111e057600080fd5b601f6101000a82048115176111f457600080fd5b606051816020036101000a83048060405190135857809190121561121757600080fd5b9050905090508152610a8051610a600180602001516000825180602090135857809190121561124557600080fd5b601f6101000a820481151761125957600080fd5b606051816020036101000a83048060405190135857809190121561127c57600080fd5b9050905090508160200152610aa051610a600180516020018083604001828460006004600a8704601201f16112b057600080fd5b5050506110005161148052611020516114a0526110408051602001806114c0828460006004600a8704601201f16112e657600080fd5b50506114a05160125412156112fa57600080fd5b60016000610a40516020826119000101526020810190506114c06104008060208461190001018260208501600060046078f150508051820191505080611900526119009050805160200180611d60828460006004600a8704601201f161135f57600080fd5b505060206121e0611d6051611d80600061148051600060c052602060c0200160c052602060c020546207a120f161139557600080fd5b60206121c0526121c06020600060208351038113156113b357600080fd5b046020026020018101519050146113c957600080fd5b606051600260045401806040519013585780919012156113e857600080fd5b600261148051600060c052602060c0200160c052602060c02001541361140d57600080fd5b6060516002600454018060405190135857809190121561142c57600080fd5b600261148051600060c052602060c0200160c052602060c0200155600660a051600161148051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561148057600080fd5b815550005b6301b7af1860005114156115af57602060046101403734156114a657600080fd5b3033146114b257600080fd5b606051600435806040519013585780919012156114ce57600080fd5b50606051600260045401806040519013585780919012156114ee57600080fd5b600261014051600060c052602060c0200160c052602060c0200154131561154c57600560a051600161014051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561154857600080fd5b8155505b6000600461014051600060c052602060c0200160c052602060c0200154600360c052602060c020015561014051600060c052602060c0200160c052602060c020600081556000600182015560006002820155600060038201556000600482015550005b63edea1480600051141561177657602060046101403734156115d057600080fd5b606051600435806040519013585780919012156115ec57600080fd5b506060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561162457600080fd5b600454121561163257600080fd5b6060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561166957600080fd5b600960c052602060c02001546101605260605160115461016051018060405190135857809190121561169a57600080fd5b60125412156116a857600080fd5b6402540be40060a05161016051600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c020015481810281198383830514176116f057600080fd5b6402540be40081059050905090508060805190135857809190121561171457600080fd5b0561018052600060006000600061018051600461014051600060c052602060c0200160c052602060c02001546000f161174c57600080fd5b6000600060246301b7af186101a052610140516101c0526101bc6000305af161177457600080fd5b005b63579f38b26000511415611a70576040600461014037341561179757600080fd5b3033146117a357600080fd5b606051600435806040519013585780919012156117bf57600080fd5b50606051602435806040519013585780919012156117dc57600080fd5b50600361014051600060c052602060c0200160c052602060c0200154600960c052602060c020015461018052600161014051600060c052602060c0200160c052602060c0200160a0516402540be40061016051028254018060805190135857809190121561184957600080fd5b815550600361014051600060c052602060c0200160c052602060c02001546101a052600261014051600060c052602060c0200160c052602060c02001546101c0526004546101e05260605160016101e05103806040519013585780919012156118b157600080fd5b610200526101c0516101e051126101e0516101a051131516156118fb57600760a0516402540be4006101605102825401806080519013585780919012156118f757600080fd5b8155505b6101c0516102005112610200516101a0511315161561194157600860a0516402540be40061016051028254018060805190135857809190121561193d57600080fd5b8155505b60605160016101c051038060405190135857809190121561196157600080fd5b6101e051141561199857600560a0516402540be40061016051028254038060805190135857809190121561199457600080fd5b8155505b60605160026101c05103806040519013585780919012156119b857600080fd5b6101e05114156119ef57600660a0516402540be4006101605102825403806080519013585780919012156119eb57600080fd5b8155505b60006000600060006402540be40060a051600860a051601254600d60c052602060c0200154610160518181028119838383051417611a2c57600080fd5b8090509050905080608051901358578091901215611a4957600080fd5b0580608051901358578091901215611a6057600080fd5b05416000f1611a6e57600080fd5b005b63e9dc061460005114156123ec5760206004610140373415611a9157600080fd5b61042060043560040161016037610400600435600401351115611ab357600080fd5b6101608051602001806105a0828460006004600a8704601201f1611ad657600080fd5b50506020610a006105a0516105c0600060185462030d40f1611af757600080fd5b60206109e0526109e0602060006020835103811315611b1557600080fd5b046020026020018101519050610a40526110c0610160610620610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610a605114611b6457600080fd5b610a6051610a6001806020015160008251806020901358578091901215611b8a57600080fd5b601f6101000a8204811517611b9e57600080fd5b606051816020036101000a830480604051901358578091901215611bc157600080fd5b90509050905081526020610a8051610a60015114611bde57600080fd5b610a8051610a8001518160200152610aa051610a6001806020015160008251806020901358578091901215611c1257600080fd5b601f6101000a8204811517611c2657600080fd5b606051816020036101000a830480604051901358578091901215611c4957600080fd5b9050905090508160400152610ac051610a6001806020015160008251806020901358578091901215611c7a57600080fd5b601f6101000a8204811517611c8e57600080fd5b606051816020036101000a830480604051901358578091901215611cb157600080fd5b9050905090508160600152610ae051610a600180516020018083608001828460006004600a8704601201f1611ce557600080fd5b5050506110c051611580526110e0516115a052611100516115c052611120516115e052611140805160200180611600828460006004600a8704601201f1611d2b57600080fd5b505060016000610a4051602082611a4001015260208101905061160061040080602084611a4001018260208501600060046078f150508051820191505080611a4052611a409050805160200180611ea0828460006004600a8704601201f1611d9257600080fd5b50506020612320611ea051611ec0600061158051600060c052602060c0200160c052602060c020546207a120f1611dc857600080fd5b602061230052612300602060006020835103811315611de657600080fd5b04602002602001810151905014611dfc57600080fd5b6001606051610100611580510780604051901358578091901215611e1f57600080fd5b600081131515611e37578060000360020a8204611e3e565b8060020a82025b90509050606051610100611580510580604051901358578091901215611e6357600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541615611e9f57600080fd5b60206123c0600463cadbbfc16123605261237c6000305af1611ec057600080fd5b6123c0516115a05114611ed257600080fd5b60026115e051600b60c052602060c0200160c052602060c0200154611ef657600080fd5b600361158051600060c052602060c0200160c052602060c02001546123e052600261158051600060c052602060c0200160c052602060c0200154612400526115c051600a60c052602060c0200154612420526060516001612420510380604051901358578091901215611f6857600080fd5b61244052612400516124205112612420516123e05113151661246052612400516124405112612440516123e05113151661248052612480516124605117611fae57600080fd5b6001606051610100611580510780604051901358578091901215611fd157600080fd5b600081131515611fe9578060000360020a8204611ff0565b8060020a82025b9050905060605161010061158051058060405190135857809190121561201557600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541760605161010061158051058060405190135857809190121561206857600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001556115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001546124a0526115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001546124c052612460511561215e576124a060a051600161158051600060c052602060c0200160c052602060c02001548251018060805190135857809190121561213157600080fd5b8152506124a0516115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001555b61248051156121d1576124c060a051600161158051600060c052602060c0200160c052602060c0200154825101806080519013585780919012156121a157600080fd5b8152506124c0516115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001555b6115e051601554146115c05160125414161561227c576402540be40060a051601a54600161158051600060c052602060c0200160c052602060c0200154818102811983838305141761222257600080fd5b6402540be40081059050905090508060805190135857809190121561224657600080fd5b056124e05260006000604463579f38b26125005261158051612520526124e0516125405261251c6000305af161227b57600080fd5b5b60026115c051600b60c052602060c0200160c052602060c02001541560a051600360a051600260085481810281198383830514176122b957600080fd5b80905090509050806080519013585780919012156122d657600080fd5b05806080519013585780919012156122ed57600080fd5b6124c051121560a051600360a0516002600754818102811983838305141761231457600080fd5b809050905090508060805190135857809190121561233157600080fd5b058060805190135857809190121561234857600080fd5b6124a05112151616156123dc57600160026115c051600b60c052602060c0200160c052602060c02001556115c0516014556012546115c051141561238c576001600c555b60605160016115e05101806040519013585780919012156123ac57600080fd5b6115c05114156123db57600160016115e051600b60c052602060c0200160c052602060c02001556115e0516013555b5b610160601d54815160208301a150005b63cc20f16b6000511415612c4d576040600461014037341561240d57600080fd5b6104206004356004016101803761040060043560040135111561242f57600080fd5b6104206024356004016105c03761040060243560040135111561245157600080fd5b610180805160200180610a00828460006004600a8704601201f161247457600080fd5b50506020610e60610a0051610a20600060185462030d40f161249557600080fd5b6020610e4052610e406020600060208351038113156124b357600080fd5b046020026020018101519050610ea052611520610180610620610ec08251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610ec0511461250257600080fd5b610ec051610ec00180602001516000825180602090135857809190121561252857600080fd5b601f6101000a820481151761253c57600080fd5b606051816020036101000a83048060405190135857809190121561255f57600080fd5b90509050905081526020610ee051610ec001511461257c57600080fd5b610ee051610ee001518160200152610f0051610ec0018060200151600082518060209013585780919012156125b057600080fd5b601f6101000a82048115176125c457600080fd5b606051816020036101000a8304806040519013585780919012156125e757600080fd5b9050905090508160400152610f2051610ec00180602001516000825180602090135857809190121561261857600080fd5b601f6101000a820481151761262c57600080fd5b606051816020036101000a83048060405190135857809190121561264f57600080fd5b9050905090508160600152610f4051610ec00180516020018083608001828460006004600a8704601201f161268357600080fd5b505050611520516119e05261156051611a005261158051611a20526115a0805160200180611a40828460006004600a8704601201f16126c157600080fd5b505060016000610ea051602082611e80010152602081019050611a4061040080602084611e8001018260208501600060046078f150508051820191505080611e8052611e8090508051602001806122e0828460006004600a8704601201f161272857600080fd5b505060206127606122e05161230060006119e051600060c052602060c0200160c052602060c020546207a120f161275e57600080fd5b60206127405261274060206000602083510381131561277c57600080fd5b0460200260200181015190501461279257600080fd5b6105c08051602001806127a0828460006004600a8704601201f16127b557600080fd5b50506020612c006127a0516127c0600060185462030d40f16127d657600080fd5b6020612be052612be06020600060208351038113156127f457600080fd5b046020026020018101519050612c40526115206105c0610620612c608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0612c60511461284357600080fd5b612c6051612c600180602001516000825180602090135857809190121561286957600080fd5b601f6101000a820481151761287d57600080fd5b606051816020036101000a8304806040519013585780919012156128a057600080fd5b90509050905081526020612c8051612c600151146128bd57600080fd5b612c8051612c8001518160200152612ca051612c60018060200151600082518060209013585780919012156128f157600080fd5b601f6101000a820481151761290557600080fd5b606051816020036101000a83048060405190135857809190121561292857600080fd5b9050905090508160400152612cc051612c600180602001516000825180602090135857809190121561295957600080fd5b601f6101000a820481151761296d57600080fd5b606051816020036101000a83048060405190135857809190121561299057600080fd5b9050905090508160600152612ce051612c600180516020018083608001828460006004600a8704601201f16129c457600080fd5b505050611520516132c052611560516132e05261158051613300526115a0805160200180613320828460006004600a8704601201f1612a0257600080fd5b505060016000612c40516020826137600101526020810190506133206104008060208461376001018260208501600060046078f150508051820191505080613760526137609050805160200180613bc0828460006004600a8704601201f1612a6957600080fd5b50506020614040613bc051613be060006132c051600060c052602060c0200160c052602060c020546207a120f1612a9f57600080fd5b602061402052614020602060006020835103811315612abd57600080fd5b04602002602001810151905014612ad357600080fd5b6132c0516119e05114612ae557600080fd5b612c4051610ea0511415612af857600080fd5b6000614080526132e051611a00511415612b1757600161408052612b4b565b611a20516133005112611a00516132e051131661330051611a2051126132e051611a005113161715612b4a576001614080525b5b61408051612b5857600080fd5b6020614120602463843b08906140a0526119e0516140c0526140bc6000305af1612b8157600080fd5b61412051614140526060516019614140510580604051901358578091901215612ba957600080fd5b61416052601760605160605160196060516018614140510280604051901358578091901215612bd757600080fd5b0580604051901358578091901215612bee57600080fd5b82540180604051901358578091901215612c0757600080fd5b8155506000600060246301b7af18614180526119e0516141a05261419c6000305af1612c3257600080fd5b600060006000600061416051336000f1612c4b57600080fd5b005b6334ef39f16000511415612c87573415612c6657600080fd5b60006000600060006017546016546000f1612c8057600080fd5b6000601755005b63253c8bd46000511415612cce5760206004610140373415612ca857600080fd5b6004356020518110612cb957600080fd5b50336016541415612ccc57610140516016555b005b63e395dc656000511415612d315760206004610140373415612cef57600080fd5b60605160043580604051901358578091901215612d0b57600080fd5b50600161014051600060c052602060c0200160c052602060c020015460005260206000f3005b6312b2a50a6000511415612d945760206004610140373415612d5257600080fd5b60605160043580604051901358578091901215612d6e57600080fd5b50600361014051600060c052602060c0200160c052602060c020015460005260206000f3005b63fc2d45406000511415612df75760206004610140373415612db557600080fd5b60605160043580604051901358578091901215612dd157600080fd5b50600261014051600060c052602060c0200160c052602060c020015460005260206000f3005b635302508f6000511415612e575760206004610140373415612e1857600080fd5b60605160043580604051901358578091901215612e3457600080fd5b5061014051600060c052602060c0200160c052602060c0205460005260206000f3005b637601d5636000511415612eba5760206004610140373415612e7857600080fd5b60605160043580604051901358578091901215612e9457600080fd5b50600461014051600060c052602060c0200160c052602060c020015460005260206000f3005b639abcf69c6000511415612f125760206004610140373415612edb57600080fd5b60605160043580604051901358578091901215612ef757600080fd5b5061014051600160c052602060c020015460005260206000f3005b63363258856000511415612f38573415612f2b57600080fd5b60025460005260206000f3005b63e46cec606000511415612f855760206004610140373415612f5957600080fd5b6004356020518110612f6a57600080fd5b5061014051600360c052602060c020015460005260206000f3005b63a0b286d66000511415612fab573415612f9e57600080fd5b60045460005260206000f3005b632c7e5aa26000511415612fd1573415612fc457600080fd5b60055460005260206000f3005b63a5fd35156000511415612ff7573415612fea57600080fd5b60065460005260206000f3005b62bc82df600051141561304e576020600461014037341561301757600080fd5b6060516004358060405190135857809190121561303357600080fd5b5061014051600960c052602060c020015460005260206000f3005b635320e5ba60005114156130a6576020600461014037341561306f57600080fd5b6060516004358060405190135857809190121561308b57600080fd5b5061014051600a60c052602060c020015460005260206000f3005b63f64927c3600051141561313057604060046101403734156130c757600080fd5b606051600435806040519013585780919012156130e357600080fd5b506060516024358060405190135857809190121561310057600080fd5b506101605161014051600b60c052602060c0200160c052602060c02060c052602060c020015460005260206000f3005b6348e821a960005114156131bd576040600461014037341561315157600080fd5b6060516004358060405190135857809190121561316d57600080fd5b506060516024358060405190135857809190121561318a57600080fd5b5061016051600361014051600b60c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b6356b861a1600051141561325757606060046101403734156131de57600080fd5b606051600435806040519013585780919012156131fa57600080fd5b506060516044358060405190135857809190121561321757600080fd5b506101805161016051600461014051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b63668d56fd60005114156132ba576020600461014037341561327857600080fd5b6060516004358060405190135857809190121561329457600080fd5b50600261014051600b60c052602060c0200160c052602060c020015460005260206000f3005b63625f375b600051141561331d57602060046101403734156132db57600080fd5b606051600435806040519013585780919012156132f757600080fd5b50600161014051600b60c052602060c0200160c052602060c020015460005260206000f3005b633f98cdef600051141561334357341561333657600080fd5b600c5460005260206000f3005b63a219390b600051141561339b576020600461014037341561336457600080fd5b6060516004358060405190135857809190121561338057600080fd5b5061014051600d60c052602060c020015460005260206000f3005b63ef5212dd60005114156133c15734156133b457600080fd5b600e5460005260206000f3005b636a5df9f460005114156133e75734156133da57600080fd5b600f5460005260206000f3005b6305fb1083600051141561340d57341561340057600080fd5b60105460005260206000f3005b63c3826907600051141561343357341561342657600080fd5b60115460005260206000f3005b63837a9bc7600051141561345957341561344c57600080fd5b60125460005260206000f3005b63634d0f77600051141561347f57341561347257600080fd5b60135460005260206000f3005b638370f33860005114156134a557341561349857600080fd5b60145460005260206000f3005b63ffb7619b60005114156134cb5734156134be57600080fd5b60155460005260206000f3005b63350d3fae60005114156134f15734156134e457600080fd5b601a5460005260206000f3005b63fba2b1b3600051141561351757341561350a57600080fd5b601b5460005260206000f3005b63199dfefa600051141561353d57341561353057600080fd5b601c5460005260206000f3005b5b61022961376703610229600039610229613767036000f3 \ No newline at end of file diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index 73782c291f..fb573e4ded 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -81,7 +81,7 @@ public class CasperStateInitTest { private StandaloneBlockchain bc; @Before - public void init() { + public void setup() { // Just trust me! // FIXME: Make it a little bit readable systemProperties.setBlockchainConfig(new CasperTestNetConfig()); @@ -109,7 +109,6 @@ public ConsensusStrategy consensusStrategy() { this.ethereum = new EthereumImpl(systemProperties, defaultListener); ethereum.setCommonConfig(commonConfig); - Mockito.when(context.getBean(Ethereum.class)).thenReturn(ethereum); this.worldManager = Mockito.mock(WorldManager.class); this.bc = new StandaloneBlockchain() { @@ -169,7 +168,7 @@ private BlockchainImpl createBlockchain() { Mockito.when(worldManager.getBlockStore()).thenReturn(bc.getBlockchain().getBlockStore()); ethereum.setWorldManager(worldManager); ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); - commonConfig.consensusStrategy(); + ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); } @Test From 71dde8d730b5e64c90981b9cda37133738ca56e4 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 27 Feb 2018 23:54:07 +0300 Subject: [PATCH 07/67] Added Casper Epoch test + minor fixes --- .../manager/CasperValidatorService.java | 8 +- .../util/blockchain/StandaloneBlockchain.java | 4 +- ethereumj-core/src/main/resources/casper.conf | 40 ++-- .../org/ethereum/core/casper/CasperBase.java | 172 ++++++++++++++++++ .../core/casper/CasperEpochSwitchTest.java | 143 +++++++++++++++ .../core/casper/CasperStateInitTest.java | 150 +-------------- 6 files changed, 346 insertions(+), 171 deletions(-) create mode 100644 ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java create mode 100644 ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java index 96a0d454b7..63bfbb0567 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java @@ -506,11 +506,11 @@ private void logCasperInfo() { "%.3f / %.3f ETH (%.2f %%) voted from previous dynasty, last finalized epoch %d justified %d " + "expected source %d. Nonvoter deposits last rescaled %.5fx, voter deposits %.5fx", curEpoch, - curVotesScaled.divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), - new BigDecimal(curDeposits).divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), + curVotesScaled.divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), + new BigDecimal(curDeposits).divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), curVotesPct, - prevVotesScaled.divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), - new BigDecimal(prevDeposits).divide(BigDecimal.valueOf(10).pow(18), MathContext.DECIMAL32), + prevVotesScaled.divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), + new BigDecimal(prevDeposits).divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), prevVotesPct, lastFinalizedEpoch, lastJustifiedEpoch, diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 29601c4379..4d58047e6f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -273,7 +273,9 @@ public Block createForkBlock(Block parent) { } List pendingTxes = new ArrayList<>(txes.keySet()); - for (int i = 0; i < lastSummary.getReceipts().size(); i++) { + // FIXME: Not sure it's correct for non-casper cases + // The issue is that Casper has background txs. It's not included in txs but it affects receipts + for (int i = 0; i < pendingTxes.size(); i++) { pendingTxes.get(i).txResult.receipt = lastSummary.getReceipts().get(i); pendingTxes.get(i).txResult.executionSummary = getTxSummary(lastSummary, i); } diff --git a/ethereumj-core/src/main/resources/casper.conf b/ethereumj-core/src/main/resources/casper.conf index a34f7f4e82..feba7924f7 100644 --- a/ethereumj-core/src/main/resources/casper.conf +++ b/ethereumj-core/src/main/resources/casper.conf @@ -5,31 +5,31 @@ peer.discovery = { # the search of the online peers # values: [ip:port, ip:port, ip:port ...] ip.list = [ -# "54.167.247.63:30303", -# "35.169.148.66:30303", -# "34.239.105.125:30303", -# "54.226.126.100:30303", -# "34.201.104.186:30303", -# "34.224.156.160:30303", -# "54.226.243.26:30303", -# "13.230.118.134:30303", -# "18.196.33.71:30303", -"34.201.104.186:30303" + "54.167.247.63:30303", + "35.169.148.66:30303", + "34.239.105.125:30303", + "54.226.126.100:30303", + "34.201.104.186:30303", + "34.224.156.160:30303", + "54.226.243.26:30303", + "13.230.118.134:30303", + "18.196.33.71:30303", + "34.201.104.186:30303" #"127.0.0.1:30308" ] } peer.active = [ -# {url = "enode://d3260a710a752b926bb3328ebe29bfb568e4fb3b4c7ff59450738661113fb21f5efbdf42904c706a9f152275890840345a5bc990745919eeb2dfc2c481d778ee@54.167.247.63:30303"}, -# {url = "enode://a120401858c93f0be73ae7765930174689cad026df332f7e06a047ead917cee193e9210e899c3143cce55dd991493227ecea15de42aa05b9b730d2189e19b567@35.169.148.66:30303"}, -# {url = "enode://6f5210fab6b7530acd2a66da1c2568289bb065e6811673d5f24bf274491b037585da1ec854e172f8dcdf3e7c5dff4ef8a270c597bbc1928a43385586e1e9f431@34.239.105.125:30303"}, -# {url = "enode://8d4a6aec3e340f9e859fd72ced95d2a0b49766772ac914810f6888bc2be5f95acf241aa94de8cd47a92dec1e8f96d86f4c052cc020e7c8e5438f6f18211dfeb1@54.226.126.100:30303"}, -# {url = "enode://9e1b6f599f4aa29897c817dd4c68c11a60bb6388cf83d4606e82c6fc742363fb5b7e306c39f8887196f1c436274404503d50b7d023e99b53c8d97f197438c60b@34.201.104.186:30303"}, -# {url = "enode://8cae2ed1214f394ae36d8a737066572c2f45a01b13aca8cc9a42e4425c7d8f8a362674d1b34f9417840e584ddb00eccf7fe53af51f5d1a32c31aab74b6ed423e@34.224.156.160:30303"}, -# {url = "enode://e0e4620880078ba43a3c11bd19490f1cce6d7fdbf9e0fab7560b784409134405e0286881031016d8dad556ff89c8a729d5bcb87a7db91a2c047ad56bf19a3581@54.226.243.26:30303"}, -# {url = "enode://ca9df451335b0bd48f6196675303b7173f8c69e63ebce6b8fb063a8e9d58156e13932f21f496aca6fd0b2ac6b34cf1276a098d5e94aa244cb0126b5a05a1d958@13.230.118.134:30303"}, -# {url = "enode://58239d442b8167d59cdf22162778c94e2549ff5981c196dc4233b6ec3e860a698ad7bf4e11e8146b76ecedd6ff465f97b890ba89a9dee051c975ac7f322dbfd8@18.196.33.71:30303"} -{url="enode://9e1b6f599f4aa29897c817dd4c68c11a60bb6388cf83d4606e82c6fc742363fb5b7e306c39f8887196f1c436274404503d50b7d023e99b53c8d97f197438c60b@34.201.104.186:30303"} + {url = "enode://d3260a710a752b926bb3328ebe29bfb568e4fb3b4c7ff59450738661113fb21f5efbdf42904c706a9f152275890840345a5bc990745919eeb2dfc2c481d778ee@54.167.247.63:30303"}, + {url = "enode://a120401858c93f0be73ae7765930174689cad026df332f7e06a047ead917cee193e9210e899c3143cce55dd991493227ecea15de42aa05b9b730d2189e19b567@35.169.148.66:30303"}, + {url = "enode://6f5210fab6b7530acd2a66da1c2568289bb065e6811673d5f24bf274491b037585da1ec854e172f8dcdf3e7c5dff4ef8a270c597bbc1928a43385586e1e9f431@34.239.105.125:30303"}, + {url = "enode://8d4a6aec3e340f9e859fd72ced95d2a0b49766772ac914810f6888bc2be5f95acf241aa94de8cd47a92dec1e8f96d86f4c052cc020e7c8e5438f6f18211dfeb1@54.226.126.100:30303"}, + {url = "enode://9e1b6f599f4aa29897c817dd4c68c11a60bb6388cf83d4606e82c6fc742363fb5b7e306c39f8887196f1c436274404503d50b7d023e99b53c8d97f197438c60b@34.201.104.186:30303"}, + {url = "enode://8cae2ed1214f394ae36d8a737066572c2f45a01b13aca8cc9a42e4425c7d8f8a362674d1b34f9417840e584ddb00eccf7fe53af51f5d1a32c31aab74b6ed423e@34.224.156.160:30303"}, + {url = "enode://e0e4620880078ba43a3c11bd19490f1cce6d7fdbf9e0fab7560b784409134405e0286881031016d8dad556ff89c8a729d5bcb87a7db91a2c047ad56bf19a3581@54.226.243.26:30303"}, + {url = "enode://ca9df451335b0bd48f6196675303b7173f8c69e63ebce6b8fb063a8e9d58156e13932f21f496aca6fd0b2ac6b34cf1276a098d5e94aa244cb0126b5a05a1d958@13.230.118.134:30303"}, + {url = "enode://58239d442b8167d59cdf22162778c94e2549ff5981c196dc4233b6ec3e860a698ad7bf4e11e8146b76ecedd6ff465f97b890ba89a9dee051c975ac7f322dbfd8@18.196.33.71:30303"}, + {url="enode://9e1b6f599f4aa29897c817dd4c68c11a60bb6388cf83d4606e82c6fc742363fb5b7e306c39f8887196f1c436274404503d50b7d023e99b53c8d97f197438c60b@34.201.104.186:30303"} #{url = "enode://7a2e5857abb1786cc0c4cd135ec406c81e64457a4eec59555b9b32d20188497122adcac6b59e47beadb583d6de4c29bfa7a465a3c01c2eaaf35ec3d31d04d4a7@127.0.0.1:30308"} ] diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java new file mode 100644 index 0000000000..8af696a632 --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; + +import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.config.CommonConfig; +import org.ethereum.config.SystemProperties; +import org.ethereum.config.net.CasperTestNetConfig; +import org.ethereum.core.BlockSummary; +import org.ethereum.core.BlockchainImpl; +import org.ethereum.core.EventDispatchThread; +import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.datasource.CountingBytesSource; +import org.ethereum.datasource.JournalSource; +import org.ethereum.datasource.Source; +import org.ethereum.datasource.inmem.HashMapDB; +import org.ethereum.db.IndexedBlockStore; +import org.ethereum.db.PruneManager; +import org.ethereum.db.RepositoryRoot; +import org.ethereum.db.TransactionStore; +import org.ethereum.facade.EthereumImpl; +import org.ethereum.listener.CompositeEthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.manager.AdminInfo; +import org.ethereum.manager.WorldManager; +import org.ethereum.util.blockchain.StandaloneBlockchain; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.vm.program.ProgramPrecompile; +import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.context.ApplicationContext; + +@RunWith(MockitoJUnitRunner.class) +public class CasperBase { + @Mock + ApplicationContext context; + + final SystemProperties systemProperties = SystemProperties.getDefault(); + + private CommonConfig commonConfig; + + CasperBlockchain blockchain; + + private WorldManager worldManager; + + private EthereumImpl ethereum; + + private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); + + CasperHybridConsensusStrategy strategy; + + StandaloneBlockchain bc; + + @Before + public void setup() { + // Just trust me! + // FIXME: Make it a little bit readable + systemProperties.setBlockchainConfig(config()); + systemProperties.setGenesisInfo("casper.json"); + systemProperties.overrideParams( + "consensus.casper.epochLength", "50", + "consensus.casper.contractBin", "/casper/casper.bin", + "consensus.casper.contractAbi", "/casper/casper.abi" + ); + MockitoAnnotations.initMocks(this); + this.commonConfig = new CommonConfig() { + @Override + public Source precompileSource() { + return null; + } + + @Override + public ConsensusStrategy consensusStrategy() { + if (strategy == null) { + strategy = new CasperHybridConsensusStrategy(systemProperties, context); + } + return strategy; + } + }; + + this.ethereum = new EthereumImpl(systemProperties, defaultListener); + ethereum.setCommonConfig(commonConfig); + this.worldManager = Mockito.mock(WorldManager.class); + + this.bc = new StandaloneBlockchain() { + @Override + public BlockchainImpl getBlockchain() { + if (blockchain == null) { + blockchain = createBlockchain(); + addEthereumListener(new EthereumListenerAdapter() { + @Override + public void onBlock(BlockSummary blockSummary) { + lastSummary = blockSummary; + } + }); + } + return blockchain; + } + + private BlockchainImpl createBlockchain() { + SystemProperties.getDefault().setBlockchainConfig(systemProperties.getBlockchainConfig()); + + IndexedBlockStore blockStore = new IndexedBlockStore(); + blockStore.init(new HashMapDB(), new HashMapDB()); + + stateDS = new HashMapDB<>(); + pruningStateDS = new JournalSource<>(new CountingBytesSource(stateDS)); + pruneManager = new PruneManager(blockStore, pruningStateDS, SystemProperties.getDefault().databasePruneDepth()); + + final RepositoryRoot repository = new RepositoryRoot(pruningStateDS); + + ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); + listener = defaultListener; + + BlockchainImpl blockchain = new CasperBlockchain(systemProperties).withEthereumListener(listener) + .withAdminInfo(new AdminInfo()) + .withEventDispatchThread(new EventDispatchThread()) + .withTransactionStore(new TransactionStore(new HashMapDB())) + .withCommonConfig(commonConfig) + .withBlockStore(blockStore); + blockchain.setRepository(repository); + blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); + blockchain.setProgramInvokeFactory(programInvokeFactory); + blockchain.setPruneManager(pruneManager); + ((CasperBlockchain)blockchain).setStrategy(strategy); + + blockchain.byTest = true; + + pendingState = new PendingStateImpl(listener, blockchain); + + pendingState.setBlockchain(blockchain); + blockchain.setPendingState(pendingState); + return blockchain; + } + }.withNetConfig(systemProperties.getBlockchainConfig()); + + this.blockchain = (CasperBlockchain) bc.getBlockchain(); + Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); + Mockito.when(worldManager.getBlockchain()).thenReturn(blockchain); + Mockito.when(worldManager.getRepository()).thenReturn(bc.getBlockchain().getRepository()); + Mockito.when(worldManager.getBlockStore()).thenReturn(bc.getBlockchain().getBlockStore()); + ethereum.setWorldManager(worldManager); + ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); + ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); + } + + BlockchainNetConfig config() { + return new CasperTestNetConfig(); + } +} diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java new file mode 100644 index 0000000000..4a9616294a --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; + +import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.config.Constants; +import org.ethereum.config.ConstantsAdapter; +import org.ethereum.config.blockchain.ByzantiumConfig; +import org.ethereum.config.blockchain.Eip150HFConfig; +import org.ethereum.config.blockchain.FrontierConfig; +import org.ethereum.config.net.BaseNetConfig; +import org.ethereum.core.Block; +import org.ethereum.core.Genesis; +import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.util.ByteUtil; +import org.ethereum.vm.GasCost; +import org.junit.Test; + +import java.math.BigInteger; + +import static junit.framework.TestCase.assertEquals; + +public class CasperEpochSwitchTest extends CasperBase { + + class CasperEasyConfig extends BaseNetConfig { + class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { + public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork + } + + private final GasCost NEW_GAS_COST = new CasperEasyConfig.CasperGasCost(); + + private class CasperConfig extends ByzantiumConfig { + private final Constants constants; + CasperConfig(BlockchainConfig parent) { + + super(parent); + constants = new ConstantsAdapter(super.getConstants()) { + private final BigInteger BLOCK_REWARD = new BigInteger("1000000000000000000"); // 1 ETH + + private final BigInteger MINIMUM_DIFFICULTY = BigInteger.ONE; + + @Override + public BigInteger getBLOCK_REWARD() { + return BLOCK_REWARD; + } + + @Override + public BigInteger getMINIMUM_DIFFICULTY() { + return MINIMUM_DIFFICULTY; + } + }; + } + + @Override + public GasCost getGasCost() { + return NEW_GAS_COST; + } + + @Override + public boolean eip161() { + return false; + } + + @Override + public Constants getConstants() { + return constants; + } + } + + public CasperEasyConfig() { + add(0, new CasperConfig(new FrontierConfig())); + } + } + + @Override + BlockchainNetConfig config() { + return new CasperEasyConfig(); + } + + @Test + public void epochStartTest() { + // Init with Genesis + final Genesis genesis = Genesis.getInstance(systemProperties); + final Genesis modifiedGenesis = new Genesis( + genesis.getParentHash(), + genesis.getUnclesHash(), + genesis.getCoinbase(), + genesis.getLogBloom(), + ByteUtil.longToBytes(1), + genesis.getNumber(), + ByteUtil.byteArrayToLong(genesis.getGasLimit()), + genesis.getGasUsed(), + genesis.getTimestamp(), + genesis.getExtraData(), + genesis.getMixHash(), + genesis.getNonce() + ); + modifiedGenesis.setPremine(genesis.getPremine()); + CasperStateInit casperStateInit = (CasperStateInit) strategy.initState(modifiedGenesis); + casperStateInit.initDB(); + + BigInteger zeroEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + assertEquals(0, zeroEpoch.longValue()); + for (int i = 0; i < 50; ++i) { + Block block = bc.createBlock(); + } + + BigInteger firstEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + assertEquals(1, firstEpoch.longValue()); + + for (int i = 0; i < 50; ++i) { + Block block = bc.createBlock(); + } + + // Epochs switches and they are finalized and justified because there no deposits yet [insta_finalize] + BigInteger secondEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + assertEquals(2, secondEpoch.longValue()); + + BigInteger lastFinalized = (BigInteger) strategy.constCallCasper("get_last_finalized_epoch")[0]; + assertEquals(1, lastFinalized.longValue()); + + BigInteger lastJustified = (BigInteger) strategy.constCallCasper("get_last_justified_epoch")[0]; + assertEquals(1, lastJustified.longValue()); + } + + // TODO: test validator deposit votes etc +} diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index fb573e4ded..6a4a708bf1 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -17,160 +17,20 @@ */ package org.ethereum.core.casper; -import org.ethereum.config.CommonConfig; -import org.ethereum.config.SystemProperties; -import org.ethereum.config.net.CasperTestNetConfig; import org.ethereum.core.Block; -import org.ethereum.core.BlockSummary; -import org.ethereum.core.BlockchainImpl; -import org.ethereum.core.EventDispatchThread; import org.ethereum.core.Genesis; -import org.ethereum.core.PendingStateImpl; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.CasperStateInit; -import org.ethereum.datasource.CountingBytesSource; -import org.ethereum.datasource.JournalSource; -import org.ethereum.datasource.Source; -import org.ethereum.datasource.inmem.HashMapDB; import org.ethereum.db.ByteArrayWrapper; -import org.ethereum.db.IndexedBlockStore; -import org.ethereum.db.PruneManager; -import org.ethereum.db.RepositoryRoot; -import org.ethereum.facade.Ethereum; -import org.ethereum.facade.EthereumImpl; -import org.ethereum.listener.CompositeEthereumListener; -import org.ethereum.listener.EthereumListenerAdapter; -import org.ethereum.manager.AdminInfo; -import org.ethereum.manager.WorldManager; -import org.ethereum.util.blockchain.StandaloneBlockchain; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; -import org.ethereum.vm.program.ProgramPrecompile; -import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.junit.MockitoJUnitRunner; import org.spongycastle.util.encoders.Hex; -import org.springframework.context.ApplicationContext; import static junit.framework.TestCase.assertEquals; -@RunWith(MockitoJUnitRunner.class) -public class CasperStateInitTest { - @Mock - ApplicationContext context; - - private final SystemProperties systemProperties = SystemProperties.getDefault(); - - private CommonConfig commonConfig; - - private CasperBlockchain blockchain; - - private WorldManager worldManager; - - private EthereumImpl ethereum; - - private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); - - private CasperHybridConsensusStrategy strategy; - - private StandaloneBlockchain bc; - - @Before - public void setup() { - // Just trust me! - // FIXME: Make it a little bit readable - systemProperties.setBlockchainConfig(new CasperTestNetConfig()); - systemProperties.setGenesisInfo("casper.json"); - systemProperties.overrideParams( - "consensus.casper.epochLength", "50", - "consensus.casper.contractBin", "/casper/casper.bin", - "consensus.casper.contractAbi", "/casper/casper.abi" - ); - MockitoAnnotations.initMocks(this); - this.commonConfig = new CommonConfig() { - @Override - public Source precompileSource() { - return null; - } - - @Override - public ConsensusStrategy consensusStrategy() { - if (strategy == null) { - strategy = new CasperHybridConsensusStrategy(systemProperties, context); - } - return strategy; - } - }; - - this.ethereum = new EthereumImpl(systemProperties, defaultListener); - ethereum.setCommonConfig(commonConfig); - this.worldManager = Mockito.mock(WorldManager.class); - - this.bc = new StandaloneBlockchain() { - @Override - public BlockchainImpl getBlockchain() { - if (blockchain == null) { - blockchain = createBlockchain(); - addEthereumListener(new EthereumListenerAdapter() { - @Override - public void onBlock(BlockSummary blockSummary) { - lastSummary = blockSummary; - } - }); - } - return blockchain; - } - - private BlockchainImpl createBlockchain() { - SystemProperties.getDefault().setBlockchainConfig(systemProperties.getBlockchainConfig()); - - IndexedBlockStore blockStore = new IndexedBlockStore(); - blockStore.init(new HashMapDB(), new HashMapDB()); - - stateDS = new HashMapDB<>(); - pruningStateDS = new JournalSource<>(new CountingBytesSource(stateDS)); - pruneManager = new PruneManager(blockStore, pruningStateDS, SystemProperties.getDefault().databasePruneDepth()); - - final RepositoryRoot repository = new RepositoryRoot(pruningStateDS); - - ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); - listener = defaultListener; - - BlockchainImpl blockchain = new CasperBlockchain(systemProperties).withEthereumListener(listener) - .withAdminInfo(new AdminInfo()) - .withEventDispatchThread(new EventDispatchThread()) - .withCommonConfig(commonConfig) - .withBlockStore(blockStore); - blockchain.setRepository(repository); - blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); - blockchain.setProgramInvokeFactory(programInvokeFactory); - blockchain.setPruneManager(pruneManager); - ((CasperBlockchain)blockchain).setStrategy(strategy); - - blockchain.byTest = true; - - pendingState = new PendingStateImpl(listener, blockchain); - - pendingState.setBlockchain(blockchain); - blockchain.setPendingState(pendingState); - return blockchain; - } - }.withNetConfig(systemProperties.getBlockchainConfig()); - - this.blockchain = (CasperBlockchain) bc.getBlockchain(); - Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); - Mockito.when(worldManager.getRepository()).thenReturn(bc.getBlockchain().getRepository()); - Mockito.when(worldManager.getBlockStore()).thenReturn(bc.getBlockchain().getBlockStore()); - ethereum.setWorldManager(worldManager); - ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); - ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); - } +public class CasperStateInitTest extends CasperBase { + /** + * Used same values like in Casper Test Network based on Pyethereum + */ @Test public void genesisPlusBlock() { // Init with Genesis @@ -193,7 +53,5 @@ public void genesisPlusBlock() { assertEquals(new ByteArrayWrapper(Hex.decode("bd832b0cd3291c39ef67691858f35c71dfb3bf21")), new ByteArrayWrapper(systemProperties.getCasperAddress())); - - // TODO: Mine to first epoch start to check all is ok + we could test votes etc } } From a50d2808af93198f130f66ad29dcde4a58460662 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 28 Feb 2018 15:16:16 +0300 Subject: [PATCH 08/67] Quick fix casper votes are dropped --- .../org/ethereum/core/PendingStateImpl.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index e1b3a51da3..3de9475e44 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -34,6 +34,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.casper.CasperTransactionExecutor; import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.TransactionStore; @@ -180,7 +181,7 @@ public void addPendingTransaction(Transaction tx, Consumer errorConsu if (addNewTxIfNotExist(tx)) { unknownTx++; TransactionReceipt receipt = addPendingTransactionImpl(tx); - if (receipt.isValid()) { + if (receiptIsValid(receipt)) { newPending.add(tx); } else { errorConsumer.accept(new Throwable("Tx execution simulation failed: " + receipt.getError())); @@ -203,7 +204,7 @@ public synchronized List addPendingTransactions(List t for (Transaction tx : transactions) { if (addNewTxIfNotExist(tx)) { unknownTx++; - if (addPendingTransactionImpl(tx).isValid()) { + if (receiptIsValid(addPendingTransactionImpl(tx))) { newPending.add(tx); } } @@ -220,6 +221,22 @@ public synchronized List addPendingTransactions(List t return newPending; } + // TODO: Refactor me!!! Casper only + private boolean receiptIsValid(TransactionReceipt receipt) { + ConsensusStrategy strategy = commonConfig.consensusStrategy(); + if (strategy instanceof CasperHybridConsensusStrategy && + CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), config.getCasperAddress())) { + // Gas not used, it's ok if it was successful vote, so let's check it + if (!receipt.isValid()) { + return receipt.isSuccessful(); + } else { + return true; // Receipt is valid already + } + } else { + return receipt.isValid(); + } + } + public synchronized void trackTransaction(Transaction tx) { List infos = transactionStore.get(tx.getHash()); if (!infos.isEmpty()) { @@ -266,7 +283,7 @@ private TransactionReceipt addPendingTransactionImpl(final Transaction tx) { txReceipt = executeTx(tx); } - if (!txReceipt.isValid()) { + if (!receiptIsValid(txReceipt)) { fireTxUpdate(txReceipt, DROPPED, getBestBlock()); } else { pendingTransactions.add(new PendingTransaction(tx, getBestBlock().getNumber())); From 6b0f381cdcf03a8893ae42c5f3da953d263b0cf6 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 28 Feb 2018 21:15:19 +0300 Subject: [PATCH 09/67] Fixed sync not done after miner start --- .../org/ethereum/core/PendingStateImpl.java | 1 + .../org/ethereum/manager/WorldManager.java | 28 +++++++++++++++++++ .../java/org/ethereum/sync/SyncManager.java | 12 ++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 3de9475e44..3eff23b2fa 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -228,6 +228,7 @@ private boolean receiptIsValid(TransactionReceipt receipt) { CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), config.getCasperAddress())) { // Gas not used, it's ok if it was successful vote, so let's check it if (!receipt.isValid()) { + logger.debug("Casper vote validity checking {}, success={} ", receipt, receipt.isSuccessful()); return receipt.isSuccessful(); } else { return true; // Receipt is valid already diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index a0e5ee5c5b..3116d76cac 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -27,6 +27,7 @@ import org.ethereum.facade.Ethereum; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; +import org.ethereum.mine.MinerListener; import org.ethereum.net.client.PeerClient; import org.ethereum.net.rlpx.discover.UDPListener; import org.ethereum.sync.FastSyncManager; @@ -137,6 +138,33 @@ private void init() { ((PendingStateImpl) pendingState).postConstruct(); syncManager.init(channelManager, pool); strategy.init(); + + ethereum.getBlockMiner().addListener(new MinerListener() { + @Override + public void miningStarted() { + syncManager.makeSyncDone(); + } + + @Override + public void miningStopped() { + + } + + @Override + public void blockMiningStarted(Block block) { + + } + + @Override + public void blockMined(Block block) { + + } + + @Override + public void blockMiningCanceled(Block block) { + + } + }); } public void addListener(EthereumListener listener) { diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java index 209464f115..9f8dd8f976 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java @@ -264,9 +264,7 @@ private void produceQueue() { wrapper.getBlock().getTransactionsList().size(), ts); if (wrapper.isNewBlock() && !syncDone) { - syncDone = true; - channelManager.onSyncDone(true); - compositeEthereumListener.onSyncDone(syncDoneType); + makeSyncDone(); } } @@ -301,6 +299,14 @@ private void produceQueue() { } } + public synchronized void makeSyncDone() { + if(!syncDone) { + syncDone = true; + channelManager.onSyncDone(true); + compositeEthereumListener.onSyncDone(syncDoneType); + } + } + /** * Adds NEW block to the queue * From 4369d4f6ff2041ed7a40218e3bd67bc8495bd1ff Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 1 Mar 2018 23:45:34 +0300 Subject: [PATCH 10/67] Added simple casper validator test, fixed voting in casper validator service --- .../core/CommonTransactionExecutor.java | 2 +- .../org/ethereum/core/PendingStateImpl.java | 4 + .../casper/CasperTransactionExecutor.java | 27 +++ .../org/ethereum/facade/EthereumImpl.java | 8 + .../manager/CasperValidatorService.java | 41 ++-- .../src/main/java/org/ethereum/util/RLP.java | 8 + .../util/blockchain/StandaloneBlockchain.java | 15 +- .../org/ethereum/core/casper/CasperBase.java | 25 ++- .../core/casper/CasperEpochSwitchTest.java | 3 +- .../core/casper/CasperValidatorTest.java | 183 ++++++++++++++++++ 10 files changed, 294 insertions(+), 22 deletions(-) create mode 100644 ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java diff --git a/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java index b4596d7799..864b0d03f1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/CommonTransactionExecutor.java @@ -127,7 +127,7 @@ public TransactionExecutor withCommonConfig(CommonConfig commonConfig) { return this; } - private void execError(String err) { + protected void execError(String err) { logger.warn(err); execError = err; } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 3eff23b2fa..e3fa897f68 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -506,4 +506,8 @@ private Block createFakePendingBlock() { public void setBlockchain(BlockchainImpl blockchain) { this.blockchain = blockchain; } + + public void setCommonConfig(CommonConfig commonConfig) { + this.commonConfig = commonConfig; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java index a29d1979b5..c886ba8e71 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java @@ -48,6 +48,33 @@ public CasperTransactionExecutor(Transaction tx, byte[] coinbase, Repository tra super(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, listener, gasUsedInTheBlock); } + @Override + public void init() { + super.init(); + // Already failed on common validation + if (execError != null) { + return; + } + + // More validations for Casper + + // EIP 208 + if (Arrays.equals(tx.getSender(), Transaction.NULL_SENDER) && toBI(tx.getNonce()).compareTo(BigInteger.ZERO) > 0) { + execError(String.format("Null sender transaction should use 0 nonce, %s instead", toBI(tx.getNonce()))); + + return; + } + + // EIP 208 + if (Arrays.equals(tx.getSender(), Transaction.NULL_SENDER) && + (toBI(tx.getValue()).compareTo(BigInteger.ZERO) > 0 || toBI(tx.getGasPrice()).compareTo(BigInteger.ZERO) > 0)) { + execError(String.format("Null sender transaction should have 0 value (actual %s), " + + "and 0 gasprice (actual: %s)", toBI(tx.getValue()), toBI(tx.getGasPrice()))); + + return; + } + } + @Override protected boolean isSignatureValid() { return isCasperVote() || super.isSignatureValid(); diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index c3f9fac350..0432214ac9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -449,6 +449,14 @@ public void setProgramInvokeFactory(ProgramInvokeFactory programInvokeFactory) { this.programInvokeFactory = programInvokeFactory; } + public void setPendingState(PendingState pendingState) { + this.pendingState = pendingState; + } + + public void setChannelManager(ChannelManager channelManager) { + this.channelManager = channelManager; + } + /** * For testing purposes and 'hackers' */ diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java index 63bfbb0567..c3bb34a2b1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java @@ -17,6 +17,7 @@ */ package org.ethereum.manager; +import org.apache.commons.lang3.ArrayUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; @@ -33,6 +34,7 @@ import org.ethereum.util.blockchain.EtherUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.spongycastle.util.BigIntegers; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -112,15 +114,27 @@ private byte[] validationContractCode(byte[] address) { } private byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { - byte[] sigHash = sha3(RLP.encodeList(validatorIndex, targetHash, targetEpoch, sourceEpoch)); + byte[] sigHash = sha3(RLP.encodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch)); ECKey.ECDSASignature signature = sender.sign(sigHash); - return RLP.encodeList(validatorIndex, targetHash, targetEpoch, sourceEpoch, signature.v, signature.r, signature.s); + byte[] v, r, s; // encoding as 32-byte ints + v = BigIntegers.asUnsignedByteArray(32, BigInteger.valueOf(signature.v)); // FIXME: If we'll have chainId it would fail + r = BigIntegers.asUnsignedByteArray(32, signature.r); + s = BigIntegers.asUnsignedByteArray(32, signature.s); + byte[] vr = ArrayUtils.addAll(v, r); + byte[] vrs = ArrayUtils.addAll(vr, s); + return RLP.encodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch, new ByteArrayWrapper(vrs)); } private byte[] makeLogout(long validatorIndex, long epoch, ECKey sender) { byte[] sigHash = sha3(RLP.encodeList(validatorIndex, epoch)); ECKey.ECDSASignature signature = sender.sign(sigHash); - return RLP.encodeList(validatorIndex, epoch, signature.v, signature.r, signature.s); + byte[] v, r, s; // encoding as 32-byte ints + v = BigIntegers.asUnsignedByteArray(32, BigInteger.valueOf(signature.v)); // FIXME: If we'll have chainId it would fail + r = BigIntegers.asUnsignedByteArray(32, signature.r); + s = BigIntegers.asUnsignedByteArray(32, signature.s); + byte[] vr = ArrayUtils.addAll(v, r); + byte[] vrs = ArrayUtils.addAll(vr, s); + return RLP.encodeList(validatorIndex, epoch, new ByteArrayWrapper(vrs)); } public enum ValidatorState { @@ -231,9 +245,6 @@ private Transaction makeTx(byte[] receiveAddress, BigInteger value, byte[] data, if (nonce == null) { nonce = repository.getNonce(coinbase.getAddress()); } - if (gasPrice == null) { - gasPrice = ByteUtil.bigIntegerToBytes(BigInteger.valueOf(110).multiply(BigInteger.valueOf(10).pow(9))); - } if (gasLimit == null) { gasLimit = ByteUtil.longToBytes(DEFAULT_GASLIMIT); } @@ -246,6 +257,9 @@ private Transaction makeTx(byte[] receiveAddress, BigInteger value, byte[] data, if (signed == null) { signed = Boolean.TRUE; } + if (gasPrice == null && signed) { + gasPrice = ByteUtil.bigIntegerToBytes(BigInteger.valueOf(110).multiply(BigInteger.TEN.pow(9))); + } Transaction tx = new Transaction( ByteUtil.bigIntegerToBytes(nonce), @@ -280,7 +294,8 @@ private void initValContractAddress() { // Actually it's not used after deposit * Wait for valcode contract to be included, then submit deposit */ private void checkValcode(Object o) { - if (valContractAddress == null || repository.getCode(valContractAddress) == null) { + if (valContractAddress == null || repository.getCode(valContractAddress) == null || + repository.getCode(valContractAddress).length == 0) { // Valcode still not deployed! or lost return; } @@ -311,16 +326,16 @@ private Transaction makeDepositTx(byte[] valContractAddress, byte[] coinbaseAddr byte[] functionCallBytes = strategy.getCasper().getByName("deposit").encode( new ByteArrayWrapper(valContractAddress), new ByteArrayWrapper(coinbaseAddress)); - Transaction tx = makeTx(strategy.getCasperAddress(), deposit, functionCallBytes, null, ByteUtil.longToBytes(1000000), + Transaction tx = makeTx(strategy.getCasperAddress(), deposit, functionCallBytes, null, ByteUtil.longToBytes(1_000_000), null, true); return tx; } private Transaction makeVoteTx(byte[] voteData) { - byte[] functionCallBytes = strategy.getCasper().getByName("vote").encode(new ByteArrayWrapper(voteData)); - Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, ByteUtil.longToBytes(1000000), - null, true); + byte[] functionCallBytes = strategy.getCasper().getByName("vote").encode(voteData); + Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, ByteUtil.longToBytes(1_000_000), + BigInteger.ZERO, false); return tx; } @@ -555,4 +570,8 @@ private long constCallCasperForLong(String func, Object... funcArgs) { public void setStrategy(CasperHybridConsensusStrategy strategy) { this.strategy = strategy; } + + public void setSyncManager(SyncManager syncManager) { + this.syncManager = syncManager; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/RLP.java b/ethereumj-core/src/main/java/org/ethereum/util/RLP.java index c1cf2b2aa4..a70958dbad 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/RLP.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/RLP.java @@ -1132,6 +1132,12 @@ public static byte[] encodeSet(Set data) { return output; } + /** + * Expects byte[] objects are already RLP-encoded while everything else is not + * @param elements Any elements, supports Byte, Short, Integer, Long, + * BigInteger, String, byte[], ByteArrayWrapper + * @return RLP list byte encoded + */ public static byte[] encodeList(Object... elements) { if (elements == null) { @@ -1153,6 +1159,8 @@ public static byte[] encodeList(Object... elements) { encodedElems[i] = encodeBigInteger((BigInteger) elements[i]); } else if (elements[i] instanceof String) { encodedElems[i] = encodeString((String) elements[i]); + } else if (elements[i] instanceof ByteArrayWrapper) { + encodedElems[i] = encodeElement(((ByteArrayWrapper) elements[i]).getData()); } else if (elements[i] instanceof byte[]) { encodedElems[i] = ((byte[]) elements[i]); } else { diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 4d58047e6f..55ad7f15d1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -208,7 +208,13 @@ private Map createTransactions(Block parent) { BigInteger bcNonce = repoSnapshot.getNonce(tx.sender.getAddress()); nonce = bcNonce.longValue(); } - nonces.put(senderW, nonce + 1); + // FIXME: Casper only + // Increase nonce only for non-casper txs + Long newNonce = nonce; + if (!Arrays.equals(tx.sender.getAddress(), Transaction.NULL_SENDER)) { + ++newNonce; + } + nonces.put(senderW, newNonce); byte[] toAddress = tx.targetContract != null ? tx.targetContract.getAddress() : tx.toAddress; @@ -276,11 +282,12 @@ public Block createForkBlock(Block parent) { // FIXME: Not sure it's correct for non-casper cases // The issue is that Casper has background txs. It's not included in txs but it affects receipts for (int i = 0; i < pendingTxes.size(); i++) { - pendingTxes.get(i).txResult.receipt = lastSummary.getReceipts().get(i); - pendingTxes.get(i).txResult.executionSummary = getTxSummary(lastSummary, i); + final PendingTx currentTx = pendingTxes.get(i); + currentTx.txResult.receipt = lastSummary.getReceipts().get(i); + currentTx.txResult.executionSummary = getTxSummary(lastSummary, i); + submittedTxes.removeIf(tx -> Arrays.equals(tx.customTx.getHash(), currentTx.customTx.getHash())); } - submittedTxes.clear(); return b; } catch (InterruptedException|ExecutionException e) { throw new RuntimeException(e); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 8af696a632..1b8762beab 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -34,12 +34,15 @@ import org.ethereum.db.IndexedBlockStore; import org.ethereum.db.PruneManager; import org.ethereum.db.RepositoryRoot; +import org.ethereum.db.RepositoryWrapper; import org.ethereum.db.TransactionStore; import org.ethereum.facade.EthereumImpl; import org.ethereum.listener.CompositeEthereumListener; +import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.manager.AdminInfo; import org.ethereum.manager.WorldManager; +import org.ethereum.net.server.ChannelManager; import org.ethereum.util.blockchain.StandaloneBlockchain; import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.program.ProgramPrecompile; @@ -50,8 +53,12 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; import org.springframework.context.ApplicationContext; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; + @RunWith(MockitoJUnitRunner.class) public class CasperBase { @Mock @@ -63,9 +70,9 @@ public class CasperBase { CasperBlockchain blockchain; - private WorldManager worldManager; + WorldManager worldManager; - private EthereumImpl ethereum; + EthereumImpl ethereum; private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); @@ -149,6 +156,7 @@ private BlockchainImpl createBlockchain() { blockchain.byTest = true; pendingState = new PendingStateImpl(listener, blockchain); + pendingState.setCommonConfig(commonConfig); pendingState.setBlockchain(blockchain); blockchain.setPendingState(pendingState); @@ -159,10 +167,19 @@ private BlockchainImpl createBlockchain() { this.blockchain = (CasperBlockchain) bc.getBlockchain(); Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); Mockito.when(worldManager.getBlockchain()).thenReturn(blockchain); - Mockito.when(worldManager.getRepository()).thenReturn(bc.getBlockchain().getRepository()); - Mockito.when(worldManager.getBlockStore()).thenReturn(bc.getBlockchain().getBlockStore()); + Mockito.when(worldManager.getBlockStore()).thenReturn(blockchain.getBlockStore()); + RepositoryWrapper wrapper = new RepositoryWrapper(); + wrapper.setBlockchain(bc.getBlockchain()); + Mockito.when(worldManager.getRepository()).thenReturn(wrapper); + doAnswer((Answer) invocation -> { + Object arg0 = invocation.getArgument(0); + defaultListener.addListener((EthereumListener) arg0); + return null; + }).when(worldManager).addListener(any(EthereumListener.class)); ethereum.setWorldManager(worldManager); ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); + ethereum.setPendingState(blockchain.getPendingState()); + ethereum.setChannelManager(Mockito.mock(ChannelManager.class)); ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index 4a9616294a..9ab36d2ef7 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -117,6 +117,7 @@ public void epochStartTest() { BigInteger zeroEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); + for (int i = 0; i < 50; ++i) { Block block = bc.createBlock(); } @@ -138,6 +139,4 @@ public void epochStartTest() { BigInteger lastJustified = (BigInteger) strategy.constCallCasper("get_last_justified_epoch")[0]; assertEquals(1, lastJustified.longValue()); } - - // TODO: test validator deposit votes etc } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java new file mode 100644 index 0000000000..f8b47da0ad --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; + +import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.config.Constants; +import org.ethereum.config.ConstantsAdapter; +import org.ethereum.config.blockchain.ByzantiumConfig; +import org.ethereum.config.blockchain.Eip150HFConfig; +import org.ethereum.config.blockchain.FrontierConfig; +import org.ethereum.config.net.BaseNetConfig; +import org.ethereum.core.AccountState; +import org.ethereum.core.Block; +import org.ethereum.core.Genesis; +import org.ethereum.core.TransactionReceipt; +import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.crypto.ECKey; +import org.ethereum.db.ByteArrayWrapper; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.manager.CasperValidatorService; +import org.ethereum.sync.SyncManager; +import org.ethereum.util.ByteUtil; +import org.ethereum.util.blockchain.EtherUtil; +import org.ethereum.vm.GasCost; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; + +@Ignore +public class CasperValidatorTest extends CasperBase { + + class CasperEasyConfig extends BaseNetConfig { + class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { + public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork + } + + private final GasCost NEW_GAS_COST = new CasperEasyConfig.CasperGasCost(); + + private class CasperConfig extends ByzantiumConfig { + private final Constants constants; + CasperConfig(BlockchainConfig parent) { + + super(parent); + constants = new ConstantsAdapter(super.getConstants()) { + private final BigInteger BLOCK_REWARD = new BigInteger("1000000000000000000"); // 1 ETH + + private final BigInteger MINIMUM_DIFFICULTY = BigInteger.ONE; + + @Override + public BigInteger getBLOCK_REWARD() { + return BLOCK_REWARD; + } + + @Override + public BigInteger getMINIMUM_DIFFICULTY() { + return MINIMUM_DIFFICULTY; + } + }; + } + + @Override + public GasCost getGasCost() { + return NEW_GAS_COST; + } + + @Override + public boolean eip161() { + return false; + } + + @Override + public Constants getConstants() { + return constants; + } + } + + public CasperEasyConfig() { + add(0, new CasperConfig(new FrontierConfig())); + } + } + + @Override + BlockchainNetConfig config() { + return new CasperEasyConfig(); + } + + @Test + public void validatorTest() { + // Init with Genesis + final Genesis genesis = Genesis.getInstance(systemProperties); + final ECKey coinbase = new ECKey(); + final Genesis modifiedGenesis = new Genesis( + genesis.getParentHash(), + genesis.getUnclesHash(), + genesis.getCoinbase(), + genesis.getLogBloom(), + ByteUtil.longToBytes(1), + genesis.getNumber(), + ByteUtil.byteArrayToLong(genesis.getGasLimit()), + genesis.getGasUsed(), + genesis.getTimestamp(), + genesis.getExtraData(), + genesis.getMixHash(), + genesis.getNonce() + ); + + // We need money + Genesis.PremineAccount coinbaseAcc = new Genesis.PremineAccount(); + coinbaseAcc.accountState = new AccountState(BigInteger.ZERO, EtherUtil.convert(2500, EtherUtil.Unit.ETHER)); + genesis.getPremine().put(new ByteArrayWrapper(coinbase.getAddress()), coinbaseAcc); + modifiedGenesis.setPremine(genesis.getPremine()); + + CasperStateInit casperStateInit = (CasperStateInit) strategy.initState(modifiedGenesis); + casperStateInit.initDB(); + + BigInteger zeroEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + assertEquals(0, zeroEpoch.longValue()); + + systemProperties.overrideParams( + "consensus.casper.validator.enabled", "true", + "consensus.casper.validator.privateKey", Hex.toHexString(coinbase.getPrivKeyBytes()), + "consensus.casper.validator.deposit", "2000" + ); + + + bc.createBlock(); + + CasperValidatorService service = new CasperValidatorService(ethereum, systemProperties); + service.setStrategy(strategy); + SyncManager syncManager = Mockito.mock(SyncManager.class); + Mockito.when(syncManager.isSyncDone()).thenReturn(true); + service.setSyncManager(syncManager); + + ethereum.addListener(new EthereumListenerAdapter(){ + @Override + public void onPendingTransactionUpdate(TransactionReceipt txReceipt, PendingTransactionState state, Block block) { + if (state.equals(PendingTransactionState.NEW_PENDING)) { + bc.submitTransaction(txReceipt.getTransaction()); + } + } + }); + + for (int i = 0; i < 10; ++i) { + Block block = bc.createBlock(); + } + // Deposit is scaled, so it's neither in wei nor in ETH. Should be 2000 ETH + // TODO: Convert to ETH or wei + BigDecimal curDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", 1)[0]; + assertTrue(curDeposit.compareTo(new BigDecimal("200000000000")) == 0); + for (int i = 0; i < 500; ++i) { + Block block = bc.createBlock(); + } + // We've earned some money on top of our deposit as premium for our votes, which finalized epochs!! + BigDecimal increasedDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", 1)[0]; + assertTrue(increasedDeposit.compareTo(new BigDecimal("200000000000")) > 0); + + // TODO: add more checking with listeners etc. + // TODO: add more validators and logout + } +} From a556ecc27b3f0d96088652cbdd5cdc2a00feb0ab Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 2 Mar 2018 00:00:29 +0300 Subject: [PATCH 11/67] Added logging of my validator stats --- .../org/ethereum/manager/CasperValidatorService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java index c3bb34a2b1..7db898578e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java @@ -533,6 +533,17 @@ private void logCasperInfo() { lastNonvoterRescale, lastVoterRescale); logger.info(logStr); + + long valIndex = getValidatorIndex(); + BigDecimal myDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", valIndex)[0]; + BigDecimal myDepositScaled = myDeposit.multiply(scaleFactor); + String myStr = String.format( + "MY VALIDATOR STATUS: epoch %d, index #%d, deposit: %.3f ETH", + curEpoch, + valIndex, + myDepositScaled.divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32) + ); + logger.info(myStr); } private byte[] getRecommendedVoteData(long validatorIndex) { From 492468ec210180870360e14981986cf2fddc00a8 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 2 Mar 2018 18:51:09 +0300 Subject: [PATCH 12/67] Added validator logout test --- .../manager/CasperValidatorService.java | 29 ++++++++++++------- .../org/ethereum/core/casper/CasperBase.java | 12 ++++++++ .../core/casper/CasperStateInitTest.java | 2 ++ .../core/casper/CasperValidatorTest.java | 26 +++++++++-------- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java index 7db898578e..097cbee077 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java @@ -160,7 +160,7 @@ public String toString() { private ValidatorState state = UNINITIATED; - private Map> handlers = new HashMap<>(); + private Map handlers = new HashMap<>(); @Autowired public CasperValidatorService(Ethereum ethereum, SystemProperties config) { @@ -192,14 +192,22 @@ private Consumer newBlockConsumer() { if(!syncManager.isSyncDone()) return; logCasperInfo(); - handlers.get(state).accept(block); + handlers.get(state).run(); }; } + public void reLogin() { + if (!state.equals(LOGGED_OUT)) { + throw new RuntimeException(String.format("Validator is not logged, out, cannot relogin. " + + "Current state: %s", state)); + } + this.depositSize = EtherUtil.convert(config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); + } + /** * Check if logged in, and if not deploy a valcode contract */ - private void checkLoggedIn(Object o) { + private void checkLoggedIn() { Long validatorIndex = getValidatorIndex(); // (1) Check if the validator has ever deposited funds if (validatorIndex == 0 && depositSize.compareTo(BigInteger.ZERO) > 0) { @@ -293,7 +301,7 @@ private void initValContractAddress() { // Actually it's not used after deposit /** * Wait for valcode contract to be included, then submit deposit */ - private void checkValcode(Object o) { + private void checkValcode() { if (valContractAddress == null || repository.getCode(valContractAddress) == null || repository.getCode(valContractAddress).length == 0) { // Valcode still not deployed! or lost @@ -368,6 +376,7 @@ private boolean isLoggedIn(long targetEpoch, long validatorIndex) { return inCurrentDynasty || inPrevDynasty; } + // TODO: integrate with composite ethereum listener private void setState(ValidatorState newState) { logger.info("Changing validator state from {} to {}", state, newState); this.state = newState; @@ -380,17 +389,17 @@ private byte[] getEpochBlockHash(long epoch) { return strategy.getBlockchain().getBlockByNumber(epoch * config.getCasperEpochLength() - 1).getHash(); } - private void voteThenLogout(Object o) { + public void voteThenLogout() { long epoch = getEpoch(); long validatorIndex = getValidatorIndex(); // Verify that we are not already logged out if (!isLoggedIn(epoch, validatorIndex)) { - // If we logged out, start waiting for withdrawls + // If we logged out, start waiting for withdrawal logger.info("Validator logged out!"); setState(WAITING_FOR_WITHDRAWABLE); return; } - vote(null); + vote(); broadcastLogoutTx(); setState(WAITING_FOR_LOGOUT); } @@ -404,7 +413,7 @@ private long getCurrentEpoch() { // FIXME: WHY there are 2 methods for the same return constCallCasperForLong("get_current_epoch"); } - private boolean vote(Object o) { + private boolean vote() { long epoch = getEpoch(); // NO DOUBLE VOTE: Don't vote if we have already @@ -460,7 +469,7 @@ private void broadcastLogoutTx() { ); } - private void checkWithdrawable(Object o) { + private void checkWithdrawable() { long validatorIndex = getValidatorIndex(); if (validatorIndex == 0) { logger.info("Validator is already deleted!"); @@ -486,7 +495,7 @@ private void checkWithdrawable(Object o) { } } - private void checkWithdrawn(Object o) { + private void checkWithdrawn() { // Check that we have been withdrawn--validator index will now be zero if (constCallCasperForLong("get_validator_indexes", new ByteArrayWrapper(coinbase.getAddress())) == 0) { setState(LOGGED_OUT); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 1b8762beab..4b15fc2ed0 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -21,10 +21,12 @@ import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.config.net.CasperTestNetConfig; +import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; import org.ethereum.core.BlockchainImpl; import org.ethereum.core.EventDispatchThread; import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.TransactionReceipt; import org.ethereum.core.consensus.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.datasource.CountingBytesSource; @@ -181,6 +183,16 @@ private BlockchainImpl createBlockchain() { ethereum.setPendingState(blockchain.getPendingState()); ethereum.setChannelManager(Mockito.mock(ChannelManager.class)); ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); + + // Push pending txs in StandaloneBlockchain + ethereum.addListener(new EthereumListenerAdapter(){ + @Override + public void onPendingTransactionUpdate(TransactionReceipt txReceipt, PendingTransactionState state, Block block) { + if (state.equals(PendingTransactionState.NEW_PENDING)) { + bc.submitTransaction(txReceipt.getTransaction()); + } + } + }); } BlockchainNetConfig config() { diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index 6a4a708bf1..703a81a0d2 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -21,11 +21,13 @@ import org.ethereum.core.Genesis; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.db.ByteArrayWrapper; +import org.junit.Ignore; import org.junit.Test; import org.spongycastle.util.encoders.Hex; import static junit.framework.TestCase.assertEquals; +@Ignore // Takes too long to run usually public class CasperStateInitTest extends CasperBase { /** diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index f8b47da0ad..0e56236065 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -49,7 +49,7 @@ import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; -@Ignore +@Ignore // Takes too long to run usually public class CasperValidatorTest extends CasperBase { class CasperEasyConfig extends BaseNetConfig { @@ -154,15 +154,6 @@ public void validatorTest() { Mockito.when(syncManager.isSyncDone()).thenReturn(true); service.setSyncManager(syncManager); - ethereum.addListener(new EthereumListenerAdapter(){ - @Override - public void onPendingTransactionUpdate(TransactionReceipt txReceipt, PendingTransactionState state, Block block) { - if (state.equals(PendingTransactionState.NEW_PENDING)) { - bc.submitTransaction(txReceipt.getTransaction()); - } - } - }); - for (int i = 0; i < 10; ++i) { Block block = bc.createBlock(); } @@ -170,14 +161,25 @@ public void onPendingTransactionUpdate(TransactionReceipt txReceipt, PendingTran // TODO: Convert to ETH or wei BigDecimal curDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", 1)[0]; assertTrue(curDeposit.compareTo(new BigDecimal("200000000000")) == 0); - for (int i = 0; i < 500; ++i) { + for (int i = 0; i < 300; ++i) { Block block = bc.createBlock(); } // We've earned some money on top of our deposit as premium for our votes, which finalized epochs!! BigDecimal increasedDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", 1)[0]; assertTrue(increasedDeposit.compareTo(new BigDecimal("200000000000")) > 0); + // We've left less than 500 ETH + assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(EtherUtil.convert(500, EtherUtil.Unit.ETHER)) < 0); + // Let's logout + service.voteThenLogout(); + // Withdrawal delay is 5 epochs + 1 vote epoch + overhead + for (int i = 0; i < 400; ++i) { + Block block = bc.createBlock(); + } + // We should have more than 2500 ETH in the end + assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(EtherUtil.convert(2500, EtherUtil.Unit.ETHER)) > 0); + // TODO: add more checking with listeners etc. - // TODO: add more validators and logout + // TODO: add more validators } } From 4818249d812cbc6fb9fa50d11589544399fcdc0a Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 2 Mar 2018 19:51:34 +0300 Subject: [PATCH 13/67] Fixed processed txs removal --- .../java/org/ethereum/util/blockchain/StandaloneBlockchain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 55ad7f15d1..665c7af39a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -285,7 +285,7 @@ public Block createForkBlock(Block parent) { final PendingTx currentTx = pendingTxes.get(i); currentTx.txResult.receipt = lastSummary.getReceipts().get(i); currentTx.txResult.executionSummary = getTxSummary(lastSummary, i); - submittedTxes.removeIf(tx -> Arrays.equals(tx.customTx.getHash(), currentTx.customTx.getHash())); + submittedTxes.removeIf(tx -> tx == currentTx); // same object } return b; From 5287b22fc4b223703c51e8601a4e3e42e5131901 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 2 Mar 2018 19:51:59 +0300 Subject: [PATCH 14/67] Fixed basis test was started, but shouldn't --- .../src/test/java/org/ethereum/core/casper/CasperBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 4b15fc2ed0..ecdd983bf8 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -62,7 +62,7 @@ import static org.mockito.Mockito.doAnswer; @RunWith(MockitoJUnitRunner.class) -public class CasperBase { +public abstract class CasperBase { @Mock ApplicationContext context; From b47e24ca97668bdbe7576401c8dec71691b0fad1 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 2 Mar 2018 19:58:42 +0300 Subject: [PATCH 15/67] Refactored null sender txs signing --- .../manager/CasperValidatorService.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java index 097cbee077..38b5e78e1a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java @@ -115,26 +115,26 @@ private byte[] validationContractCode(byte[] address) { private byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { byte[] sigHash = sha3(RLP.encodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch)); - ECKey.ECDSASignature signature = sender.sign(sigHash); - byte[] v, r, s; // encoding as 32-byte ints - v = BigIntegers.asUnsignedByteArray(32, BigInteger.valueOf(signature.v)); // FIXME: If we'll have chainId it would fail - r = BigIntegers.asUnsignedByteArray(32, signature.r); - s = BigIntegers.asUnsignedByteArray(32, signature.s); - byte[] vr = ArrayUtils.addAll(v, r); - byte[] vrs = ArrayUtils.addAll(vr, s); + byte[] vrs = make3IntSignature(sigHash, sender); return RLP.encodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch, new ByteArrayWrapper(vrs)); } private byte[] makeLogout(long validatorIndex, long epoch, ECKey sender) { byte[] sigHash = sha3(RLP.encodeList(validatorIndex, epoch)); - ECKey.ECDSASignature signature = sender.sign(sigHash); + byte[] vrs = make3IntSignature(sigHash, sender); + return RLP.encodeList(validatorIndex, epoch, new ByteArrayWrapper(vrs)); + } + + private byte[] make3IntSignature(byte[] data, ECKey signer) { + ECKey.ECDSASignature signature = signer.sign(data); byte[] v, r, s; // encoding as 32-byte ints v = BigIntegers.asUnsignedByteArray(32, BigInteger.valueOf(signature.v)); // FIXME: If we'll have chainId it would fail r = BigIntegers.asUnsignedByteArray(32, signature.r); s = BigIntegers.asUnsignedByteArray(32, signature.s); byte[] vr = ArrayUtils.addAll(v, r); byte[] vrs = ArrayUtils.addAll(vr, s); - return RLP.encodeList(validatorIndex, epoch, new ByteArrayWrapper(vrs)); + + return vrs; } public enum ValidatorState { From 068152af8765df67b3ec1d4ba4b5130c63e6a48b Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 2 Mar 2018 21:30:56 +0300 Subject: [PATCH 16/67] Started to detaching Casper in separate package: Config moved --- ethereumj-core/build.gradle | 2 +- .../main/java/org/ethereum/casper/Start.java | 62 +++++++++++++ .../casper/config/CasperBeanConfig.java | 34 +++++++ .../ethereum/casper/config/CasperConfig.java | 89 +++++++++++++++++++ .../org/ethereum/config/CommonConfig.java | 27 +----- .../org/ethereum/config/DefaultConfig.java | 7 ++ .../org/ethereum/core/BlockchainImpl.java | 2 + 7 files changed, 197 insertions(+), 26 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/Start.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java diff --git a/ethereumj-core/build.gradle b/ethereumj-core/build.gradle index 8cf47ae148..ed5d7cbae9 100644 --- a/ethereumj-core/build.gradle +++ b/ethereumj-core/build.gradle @@ -64,7 +64,7 @@ task runTest (type: JavaExec) { } task runCasper (type: JavaExec) { - main = mainClassName + main = 'org.ethereum.casper.Start' classpath = sourceSets.main.runtimeClasspath jvmArgs = applicationDefaultJvmArgs + '-Dethereumj.conf.res=casper.conf' } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/Start.java b/ethereumj-core/src/main/java/org/ethereum/casper/Start.java new file mode 100644 index 0000000000..445658391a --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/Start.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper; + +import org.apache.commons.lang3.StringUtils; +import org.ethereum.casper.config.CasperConfig; +import org.ethereum.cli.CLIInterface; +import org.ethereum.config.SystemProperties; +import org.ethereum.facade.Ethereum; +import org.ethereum.facade.EthereumFactory; +import org.ethereum.mine.Ethash; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URISyntaxException; + +public class Start { + + private static final Logger logger = LoggerFactory.getLogger("general"); + + public static void main(String args[]) throws IOException, URISyntaxException { + logger.info("EthereumJ Casper edition"); + CLIInterface.call(args); + + final SystemProperties config = SystemProperties.getDefault(); + final boolean actionBlocksLoader = !config.blocksLoader().equals(""); + final boolean actionGenerateDag = !StringUtils.isEmpty(System.getProperty("ethash.blockNumber")); + + if (actionBlocksLoader || actionGenerateDag) { + config.setSyncEnabled(false); + config.setDiscoveryEnabled(false); + } + + if (actionGenerateDag) { + new Ethash(config, Long.parseLong(System.getProperty("ethash.blockNumber"))).getFullDataset(); + // DAG file has been created, lets exit + System.exit(0); + } else { + Ethereum ethereum = EthereumFactory.createEthereum(new Class[] {CasperConfig.class}); + + if (actionBlocksLoader) { + ethereum.getBlockLoader().loadBlocks(); + } + } + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java new file mode 100644 index 0000000000..88d1848278 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.config; + +import org.ethereum.config.CommonConfig; +import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +public class CasperBeanConfig extends CommonConfig { + + @Override + public ConsensusStrategy consensusStrategy() { + return new CasperHybridConsensusStrategy(systemProperties(), ctx); + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java new file mode 100644 index 0000000000..7d47e2a704 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.config; + +import org.ethereum.config.CommonConfig; +import org.ethereum.config.DefaultConfig; +import org.ethereum.config.NoAutoscan; +import org.ethereum.config.SystemProperties; +import org.ethereum.datasource.Source; +import org.ethereum.db.BlockStore; +import org.ethereum.db.IndexedBlockStore; +import org.ethereum.db.PruneManager; +import org.ethereum.db.TransactionStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.Import; + +@Configuration +@ComponentScan( + basePackages = "org.ethereum", + excludeFilters = {@ComponentScan.Filter(NoAutoscan.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {CommonConfig.class, DefaultConfig.class})}, + includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {CasperBeanConfig.class})} +) +@Import(CasperBeanConfig.class) +public class CasperConfig { + private static Logger logger = LoggerFactory.getLogger("general"); + + @Autowired + ApplicationContext appCtx; + + @Autowired + CasperBeanConfig beanConfig; + + @Autowired + SystemProperties config; + + public CasperConfig() { + Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception", e)); + } + + @Bean + public BlockStore blockStore(){ + beanConfig.fastSyncCleanUp(); + IndexedBlockStore indexedBlockStore = new IndexedBlockStore(); + Source block = beanConfig.cachedDbSource("block"); + Source index = beanConfig.cachedDbSource("index"); + indexedBlockStore.init(index, block); + + return indexedBlockStore; + } + + @Bean + public TransactionStore transactionStore() { + beanConfig.fastSyncCleanUp(); + return new TransactionStore(beanConfig.cachedDbSource("transactions")); + } + + @Bean + public PruneManager pruneManager() { + if (config.databasePruneDepth() >= 0) { + return new PruneManager((IndexedBlockStore) blockStore(), beanConfig.stateSource().getJournalSource(), + config.databasePruneDepth()); + } else { + return new PruneManager(null, null, -1); // dummy + } + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index 6b33a010ee..2bcd3e49f3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -18,7 +18,6 @@ package org.ethereum.config; import org.ethereum.core.*; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.consensus.PoWConsensusStrategy; import org.ethereum.crypto.HashUtil; @@ -28,10 +27,8 @@ import org.ethereum.db.*; import org.ethereum.listener.EthereumListener; import org.ethereum.sync.FastSyncManager; -import org.ethereum.validator.*; import org.ethereum.vm.DataWord; import org.ethereum.vm.program.ProgramPrecompile; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -43,22 +40,14 @@ import java.util.HashSet; import java.util.Set; -import static java.util.Arrays.asList; - @Configuration @EnableTransactionManagement -@ComponentScan( - basePackages = "org.ethereum", - excludeFilters = @ComponentScan.Filter(NoAutoscan.class)) public class CommonConfig { private static final Logger logger = LoggerFactory.getLogger("general"); private Set dbSources = new HashSet<>(); - private ConsensusStrategy consensusStrategy; - - @Autowired - private ApplicationContext ctx; + protected ApplicationContext ctx; private static CommonConfig defaultInstance; @@ -258,18 +247,6 @@ public PeerSource peerSource() { @Bean public ConsensusStrategy consensusStrategy() { - if(consensusStrategy == null) { - switch (systemProperties().getConsensusStrategy()) { - case "pow": - consensusStrategy = new PoWConsensusStrategy(systemProperties(), ctx); - break; - case "casper-hybrid": - consensusStrategy = new CasperHybridConsensusStrategy(systemProperties(), ctx); - break; - default: - throw new RuntimeException("Consensus strategy is not set. Breaking."); - } - } - return consensusStrategy; + return new PoWConsensusStrategy(systemProperties(), ctx); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/DefaultConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/DefaultConfig.java index 0f94a10d95..fa06550e5c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/DefaultConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/DefaultConfig.java @@ -27,7 +27,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Import; /** @@ -36,6 +38,11 @@ * Created on: 27/01/2015 01:05 */ @Configuration +@ComponentScan( + basePackages = "org.ethereum", + excludeFilters = {@ComponentScan.Filter(NoAutoscan.class), + @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org\\.ethereum\\.casper\\..*")} +) @Import(CommonConfig.class) public class DefaultConfig { private static Logger logger = LoggerFactory.getLogger("general"); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 0ba7f4e65b..918751b3ae 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -39,6 +39,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import java.io.BufferedWriter; @@ -94,6 +95,7 @@ * @since 20.05.2014 */ @Lazy +@Primary @Component public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchain { From 3a88e8bea15d680938eeeab9078a2897702671a2 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Sat, 3 Mar 2018 01:18:56 +0300 Subject: [PATCH 17/67] Moved Blockchain and validators out of consensus strategy --- .../CasperHybridConsensusStrategy.java | 78 +++---------------- .../casper/config/CasperBeanConfig.java | 11 ++- .../service}/CasperValidatorService.java | 38 +++++---- .../org/ethereum/config/CommonConfig.java | 47 +++++++++++ .../org/ethereum/core/BlockchainImpl.java | 7 +- .../org/ethereum/core/PendingStateImpl.java | 27 ++----- .../core/casper/CasperBlockchain.java | 15 ++-- .../casper/CasperTransactionExecutor.java | 3 +- .../core/consensus/ConsensusStrategy.java | 9 --- .../core/consensus/PoWConsensusStrategy.java | 61 ++------------- .../org/ethereum/manager/BlockLoader.java | 19 ++--- .../org/ethereum/manager/WorldManager.java | 7 +- .../java/org/ethereum/mine/BlockMiner.java | 11 +-- .../org/ethereum/net/eth/handler/Eth62.java | 6 +- .../org/ethereum/net/eth/handler/Eth63.java | 5 +- .../org/ethereum/sync/FastSyncDownloader.java | 6 +- .../org/ethereum/sync/FastSyncManager.java | 12 +-- .../java/org/ethereum/sync/SyncManager.java | 8 +- .../main/java/org/ethereum/sync/SyncPool.java | 5 +- .../util/blockchain/StandaloneBlockchain.java | 2 +- .../org/ethereum/core/ImportLightTest.java | 4 +- .../core/PendingStateLongRunTest.java | 4 +- .../org/ethereum/core/casper/CasperBase.java | 4 +- .../core/casper/CasperValidatorTest.java | 4 +- .../jsontestsuite/suite/TestRunner.java | 7 +- 25 files changed, 147 insertions(+), 253 deletions(-) rename ethereumj-core/src/main/java/org/ethereum/{core/consensus => casper}/CasperHybridConsensusStrategy.java (72%) rename ethereumj-core/src/main/java/org/ethereum/{manager => casper/service}/CasperValidatorService.java (94%) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/casper/CasperHybridConsensusStrategy.java similarity index 72% rename from ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java rename to ethereumj-core/src/main/java/org/ethereum/casper/CasperHybridConsensusStrategy.java index 4450bb4fca..9e4506bcfe 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/CasperHybridConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/CasperHybridConsensusStrategy.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.core.consensus; +package org.ethereum.casper; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; @@ -27,47 +27,27 @@ import org.ethereum.core.TransactionExecutor; import org.ethereum.core.casper.CasperBlockchain; import org.ethereum.core.casper.CasperTransactionExecutor; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; import org.ethereum.facade.Ethereum; -import org.ethereum.facade.EthereumImpl; import org.ethereum.listener.EthereumListener; -import org.ethereum.manager.CasperValidatorService; -import org.ethereum.validator.BlockHashRule; -import org.ethereum.validator.BlockHeaderRule; -import org.ethereum.validator.BlockHeaderValidator; -import org.ethereum.validator.DependentBlockHeaderRule; -import org.ethereum.validator.DifficultyRule; -import org.ethereum.validator.ExtraDataRule; -import org.ethereum.validator.GasLimitRule; -import org.ethereum.validator.GasValueRule; -import org.ethereum.validator.ParentBlockHeaderValidator; -import org.ethereum.validator.ParentGasLimitRule; -import org.ethereum.validator.ParentNumberRule; -import org.ethereum.validator.ProofOfWorkRule; +import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.vm.program.ProgramResult; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import java.util.ArrayList; -import java.util.List; - -import static java.util.Arrays.asList; - public class CasperHybridConsensusStrategy implements ConsensusStrategy { private static final Logger logger = LoggerFactory.getLogger("general"); private SystemProperties systemProperties; - private BlockHeaderValidator blockHeaderValidator; - - private ParentBlockHeaderValidator parentBlockHeaderValidator; - private CasperBlockchain blockchain; private CasperValidatorService casperValidatorService; @@ -82,46 +62,14 @@ public class CasperHybridConsensusStrategy implements ConsensusStrategy { private String casperAddress; // FIXME: why should we have casper addresses in two places?. It's already in SystemProperties + public CasperHybridConsensusStrategy() { + } + public CasperHybridConsensusStrategy(SystemProperties systemProperties, ApplicationContext ctx) { this.systemProperties = systemProperties; - - List rules = new ArrayList<>(asList( - new GasValueRule(), - new ExtraDataRule(systemProperties), - new ProofOfWorkRule(), - new GasLimitRule(systemProperties), - new BlockHashRule(systemProperties) - )); - blockHeaderValidator = new BlockHeaderValidator(rules); - - - List parentRules = new ArrayList<>(asList( - new ParentNumberRule(), - new DifficultyRule(systemProperties), - new ParentGasLimitRule(systemProperties) - )); - parentBlockHeaderValidator = new ParentBlockHeaderValidator(parentRules); - - blockchain = ctx.getBean(CasperBlockchain.class); - blockchain.setStrategy(this); this.ctx = ctx; } - @Override - public BlockHeaderValidator getHeaderValidator() { - return blockHeaderValidator; - } - - @Override - public ParentBlockHeaderValidator getParentHeaderValidator() { - return parentBlockHeaderValidator; - } - - @Override - public Blockchain getBlockchain() { - return blockchain; - } - @Override public void init() { getCasperValidatorService(); @@ -204,14 +152,12 @@ public CasperValidatorService getCasperValidatorService() { return casperValidatorService; } - // FIXME: Magic - public void setBlockchain(CasperBlockchain blockchain) { - this.blockchain = blockchain; - blockchain.setParentHeaderValidator(parentBlockHeaderValidator); - blockchain.setStrategy(this); - } - public void setEthereum(Ethereum ethereum) { this.ethereum = ethereum; } + + @Autowired + public void setBlockchain(Blockchain blockchain) { + this.blockchain = (CasperBlockchain) blockchain; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index 88d1848278..ec7e16a3ee 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -18,8 +18,11 @@ package org.ethereum.casper.config; import org.ethereum.config.CommonConfig; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.core.Blockchain; +import org.ethereum.core.casper.CasperBlockchain; +import org.ethereum.casper.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -31,4 +34,10 @@ public class CasperBeanConfig extends CommonConfig { public ConsensusStrategy consensusStrategy() { return new CasperHybridConsensusStrategy(systemProperties(), ctx); } + + @Override + @Bean + public Blockchain blockchain() { + return new CasperBlockchain(systemProperties()); + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java rename to ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 38b5e78e1a..22dc250506 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -15,15 +15,17 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.manager; +package org.ethereum.casper.service; import org.apache.commons.lang3.ArrayUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; +import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.facade.Ethereum; @@ -37,6 +39,7 @@ import org.spongycastle.util.BigIntegers; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -49,14 +52,14 @@ import java.util.function.Consumer; import static org.ethereum.crypto.HashUtil.sha3; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.LOGGED_OUT; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.UNINITIATED; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.VOTING; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_LOGIN; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_LOGOUT; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_VALCODE; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWABLE; -import static org.ethereum.manager.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWN; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.LOGGED_OUT; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.UNINITIATED; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.VOTING; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.WAITING_FOR_LOGIN; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.WAITING_FOR_LOGOUT; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.WAITING_FOR_VALCODE; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWABLE; +import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWN; @Component @Lazy @@ -66,9 +69,11 @@ public class CasperValidatorService { @Autowired private SyncManager syncManager; - @Autowired private CasperHybridConsensusStrategy strategy; + @Autowired + Blockchain blockchain; + private Repository repository; private SystemProperties config; @@ -386,7 +391,7 @@ private byte[] getEpochBlockHash(long epoch) { if (epoch == 0) { return Hex.decode("0000000000000000000000000000000000000000000000000000000000000000"); } - return strategy.getBlockchain().getBlockByNumber(epoch * config.getCasperEpochLength() - 1).getHash(); + return blockchain.getBlockByNumber(epoch * config.getCasperEpochLength() - 1).getHash(); } public void voteThenLogout() { @@ -406,7 +411,7 @@ public void voteThenLogout() { // FIXME: WHY there are 2 methods for the same thing??? private long getEpoch() { - return strategy.getBlockchain().getBestBlock().getNumber() / config.getCasperEpochLength(); // floor division + return blockchain.getBestBlock().getNumber() / config.getCasperEpochLength(); // floor division } private long getCurrentEpoch() { // FIXME: WHY there are 2 methods for the same thing??? @@ -429,7 +434,7 @@ private boolean vote() { } // Don't start too early - if (strategy.getBlockchain().getBestBlock().getNumber() % config.getCasperEpochLength() <= config.getCasperEpochLength() / 4) { + if (blockchain.getBestBlock().getNumber() % config.getCasperEpochLength() <= config.getCasperEpochLength() / 4) { return false; } @@ -594,4 +599,9 @@ public void setStrategy(CasperHybridConsensusStrategy strategy) { public void setSyncManager(SyncManager syncManager) { this.syncManager = syncManager; } + + @Autowired + public void setStrategy(ConsensusStrategy strategy) { + this.strategy = (CasperHybridConsensusStrategy) strategy; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index 2bcd3e49f3..c957c59943 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -27,6 +27,18 @@ import org.ethereum.db.*; import org.ethereum.listener.EthereumListener; import org.ethereum.sync.FastSyncManager; +import org.ethereum.validator.BlockHashRule; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.DependentBlockHeaderRule; +import org.ethereum.validator.DifficultyRule; +import org.ethereum.validator.ExtraDataRule; +import org.ethereum.validator.GasLimitRule; +import org.ethereum.validator.GasValueRule; +import org.ethereum.validator.ParentBlockHeaderValidator; +import org.ethereum.validator.ParentGasLimitRule; +import org.ethereum.validator.ParentNumberRule; +import org.ethereum.validator.ProofOfWorkRule; import org.ethereum.vm.DataWord; import org.ethereum.vm.program.ProgramPrecompile; import org.slf4j.Logger; @@ -37,9 +49,13 @@ import org.springframework.context.annotation.*; import org.springframework.transaction.annotation.EnableTransactionManagement; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; +import static java.util.Arrays.asList; + @Configuration @EnableTransactionManagement public class CommonConfig { @@ -237,6 +253,32 @@ public DbFlushManager dbFlushManager() { return new DbFlushManager(systemProperties(), dbSources, blockchainDbCache()); } + @Bean + public BlockHeaderValidator headerValidator() { + + List rules = new ArrayList<>(asList( + new GasValueRule(), + new ExtraDataRule(systemProperties()), + new ProofOfWorkRule(), + new GasLimitRule(systemProperties()), + new BlockHashRule(systemProperties()) + )); + + return new BlockHeaderValidator(rules); + } + + @Bean + public ParentBlockHeaderValidator parentHeaderValidator() { + + List rules = new ArrayList<>(asList( + new ParentNumberRule(), + new DifficultyRule(systemProperties()), + new ParentGasLimitRule(systemProperties()) + )); + + return new ParentBlockHeaderValidator(rules); + } + @Bean @Lazy public PeerSource peerSource() { @@ -245,6 +287,11 @@ public PeerSource peerSource() { return new PeerSource(dbSource); } + @Bean + public Blockchain blockchain() { + return new BlockchainImpl(systemProperties()); + } + @Bean public ConsensusStrategy consensusStrategy() { return new PoWConsensusStrategy(systemProperties(), ctx); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 918751b3ae..feea547f5c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -38,9 +38,6 @@ import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; import java.io.BufferedWriter; import java.io.File; @@ -94,9 +91,6 @@ * @author Nick Savers * @since 20.05.2014 */ -@Lazy -@Primary -@Component public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchain { @@ -129,6 +123,7 @@ public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchai @Autowired protected AdminInfo adminInfo; + @Autowired private DependentBlockHeaderRule parentHeaderValidator; @Autowired diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index e3fa897f68..791028e1c9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -33,7 +33,7 @@ import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.casper.CasperTransactionExecutor; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; @@ -83,15 +83,13 @@ public TransactionSortedSet() { @Autowired private EthereumListener listener; + @Autowired private Blockchain blockchain; - @Autowired private BlockStore blockStore; - @Autowired private TransactionStore transactionStore; - @Autowired private ProgramInvokeFactory programInvokeFactory; // private Repository repository; @@ -110,24 +108,7 @@ public TransactionSortedSet() { @Autowired public PendingStateImpl(final EthereumListener listener) { this.listener = listener; - } - - public PendingStateImpl(final EthereumListener listener, final BlockchainImpl blockchain) { - this.listener = listener; - this.blockchain = blockchain; -// this.repository = blockchain.getRepository(); - this.blockStore = blockchain.getBlockStore(); - this.programInvokeFactory = blockchain.getProgramInvokeFactory(); - this.transactionStore = blockchain.getTransactionStore(); - } - - public void postConstruct() { - BlockchainImpl blockchain = (BlockchainImpl) commonConfig.consensusStrategy().getBlockchain(); - this.blockchain = blockchain; // this.repository = blockchain.getRepository(); - this.blockStore = blockchain.getBlockStore(); - this.programInvokeFactory = blockchain.getProgramInvokeFactory(); - this.transactionStore = blockchain.getTransactionStore(); } public void init() { @@ -503,8 +484,12 @@ private Block createFakePendingBlock() { return block; } + @Autowired public void setBlockchain(BlockchainImpl blockchain) { this.blockchain = blockchain; + this.blockStore = blockchain.getBlockStore(); + this.programInvokeFactory = blockchain.getProgramInvokeFactory(); + this.transactionStore = blockchain.getTransactionStore(); } public void setCommonConfig(CommonConfig commonConfig) { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java index 5c3f25f7b8..c268e5d655 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java @@ -30,7 +30,8 @@ import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutor; import org.ethereum.core.TransactionReceipt; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; @@ -40,8 +41,6 @@ import org.spongycastle.util.Arrays; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; import java.math.BigInteger; import java.util.ArrayList; @@ -56,11 +55,8 @@ import static org.ethereum.core.ImportResult.INVALID_BLOCK; import static org.ethereum.core.ImportResult.NO_PARENT; import static org.ethereum.core.genesis.CasperStateInit.NULL_SENDER; -import static org.ethereum.manager.CasperValidatorService.DEFAULT_GASLIMIT; +import static org.ethereum.casper.service.CasperValidatorService.DEFAULT_GASLIMIT; - -@Lazy -@Component public class CasperBlockchain extends BlockchainImpl { private static final Logger logger = LoggerFactory.getLogger("blockchain"); @@ -439,7 +435,8 @@ private BigInteger getPoWDifficulty(final Block block) { return blockStore.getTotalDifficultyForHash(block.getHash()); } - public void setStrategy(CasperHybridConsensusStrategy strategy) { - this.strategy = strategy; + @Autowired + public void setStrategy(ConsensusStrategy strategy) { + this.strategy = (CasperHybridConsensusStrategy) strategy; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java index c886ba8e71..72036418c5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java @@ -16,13 +16,12 @@ * along with the ethereumJ library. If not, see . */ package org.ethereum.core.casper; -import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutionSummary; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java index 02325ab647..a31359144c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java @@ -18,7 +18,6 @@ package org.ethereum.core.consensus; import org.ethereum.core.Block; -import org.ethereum.core.Blockchain; import org.ethereum.core.Genesis; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; @@ -26,17 +25,9 @@ import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; import org.ethereum.listener.EthereumListener; -import org.ethereum.validator.BlockHeaderValidator; -import org.ethereum.validator.ParentBlockHeaderValidator; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; public interface ConsensusStrategy { - BlockHeaderValidator getHeaderValidator(); - - ParentBlockHeaderValidator getParentHeaderValidator(); - - Blockchain getBlockchain(); - void init(); /** diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java index b5714f5eb2..72ba6908fd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java @@ -29,76 +29,30 @@ import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; import org.ethereum.listener.EthereumListener; -import org.ethereum.validator.BlockHashRule; -import org.ethereum.validator.BlockHeaderRule; -import org.ethereum.validator.BlockHeaderValidator; -import org.ethereum.validator.DependentBlockHeaderRule; -import org.ethereum.validator.DifficultyRule; -import org.ethereum.validator.ExtraDataRule; -import org.ethereum.validator.GasLimitRule; -import org.ethereum.validator.GasValueRule; -import org.ethereum.validator.ParentBlockHeaderValidator; -import org.ethereum.validator.ParentGasLimitRule; -import org.ethereum.validator.ParentNumberRule; -import org.ethereum.validator.ProofOfWorkRule; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import java.util.ArrayList; -import java.util.List; - -import static java.util.Arrays.asList; - public class PoWConsensusStrategy implements ConsensusStrategy { private SystemProperties systemProperties; - private BlockHeaderValidator blockHeaderValidator; - private ParentBlockHeaderValidator parentBlockHeaderValidator; + @Autowired private BlockchainImpl blockchain; private StateInit stateInit; + public PoWConsensusStrategy() { + } + public PoWConsensusStrategy(SystemProperties systemProperties, ApplicationContext ctx) { this(systemProperties); - blockchain = ctx.getBean(BlockchainImpl.class); } public PoWConsensusStrategy(SystemProperties systemProperties) { this.systemProperties = systemProperties; - List rules = new ArrayList<>(asList( - new GasValueRule(), - new ExtraDataRule(systemProperties), - new ProofOfWorkRule(), - new GasLimitRule(systemProperties), - new BlockHashRule(systemProperties) - )); - blockHeaderValidator = new BlockHeaderValidator(rules); - - - List parentRules = new ArrayList<>(asList( - new ParentNumberRule(), - new DifficultyRule(systemProperties), - new ParentGasLimitRule(systemProperties) - )); - parentBlockHeaderValidator = new ParentBlockHeaderValidator(parentRules); // TODO: Add default blockchainImpl when it's not provided } - @Override - public BlockHeaderValidator getHeaderValidator() { - return blockHeaderValidator; - } - - @Override - public ParentBlockHeaderValidator getParentHeaderValidator() { - return parentBlockHeaderValidator; - } - - @Override - public BlockchainImpl getBlockchain() { - return blockchain; - } - @Override public void init() { @@ -136,9 +90,4 @@ public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coin return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, listener, gasUsedInTheBlock); } - - public void setBlockchain(BlockchainImpl blockchain) { - this.blockchain = blockchain; - blockchain.setParentHeaderValidator(parentBlockHeaderValidator); - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java index 240f403d07..555c795f21 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java @@ -20,8 +20,6 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; -import org.ethereum.db.BlockStore; import org.ethereum.db.DbFlushManager; import org.ethereum.util.*; import org.ethereum.validator.BlockHeaderValidator; @@ -44,31 +42,24 @@ public class BlockLoader { private static final Logger logger = LoggerFactory.getLogger("blockqueue"); + @Autowired private BlockHeaderValidator headerValidator; @Autowired SystemProperties config; - private Blockchain blockchain; - - private BlockStore blockStore; - @Autowired - DbFlushManager dbFlushManager; + private BlockchainImpl blockchain; @Autowired - public BlockLoader(ConsensusStrategy consensusStrategy) { - this.blockchain = consensusStrategy.getBlockchain(); - this.blockStore = ((org.ethereum.facade.Blockchain) blockchain).getBlockStore(); - this.headerValidator = consensusStrategy.getHeaderValidator(); - } + DbFlushManager dbFlushManager; Scanner scanner = null; DateFormat df = new SimpleDateFormat("HH:mm:ss.SSSS"); private void blockWork(Block block) { - if (block.getNumber() >= blockStore.getBestBlock().getNumber() || blockStore.getBlockByHash(block.getHash()) == null) { + if (block.getNumber() >= blockchain.getBlockStore().getBestBlock().getNumber() || blockchain.getBlockStore().getBlockByHash(block.getHash()) == null) { if (block.getNumber() > 0 && !isValid(block.getHeader())) { throw new RuntimeException(); @@ -95,7 +86,7 @@ private void blockWork(Block block) { public void loadBlocks() { exec1 = new ExecutorPipeline(8, 1000, true, (Function) b -> { - if (b.getNumber() >= blockStore.getBestBlock().getNumber()) { + if (b.getNumber() >= blockchain.getBlockStore().getBestBlock().getNumber()) { for (Transaction tx : b.getTransactionsList()) { tx.getSender(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index 3116d76cac..38608b0114 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -19,7 +19,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; @@ -115,10 +115,10 @@ public class WorldManager { @Autowired public WorldManager(final SystemProperties config, final Repository repository, final EthereumListener listener, final ConsensusStrategy consensusStrategy, - final BlockStore blockStore) { + final Blockchain blockchain, final BlockStore blockStore) { this.listener = listener; this.strategy = consensusStrategy; - this.blockchain = consensusStrategy.getBlockchain(); + this.blockchain = blockchain; this.repository = repository; repository.setBlockchain(blockchain); this.blockStore = blockStore; @@ -135,7 +135,6 @@ private void init() { } loadBlockchain(strategy); channelManager.init(ethereum); - ((PendingStateImpl) pendingState).postConstruct(); syncManager.init(channelManager, pool); strategy.init(); diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index 0defef0afe..56e65a31ba 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -23,8 +23,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.core.casper.CasperTransactionExecutor; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; @@ -84,6 +83,7 @@ public class BlockMiner { private int UNCLE_LIST_LIMIT; private int UNCLE_GENERATION_LIMIT; + @Autowired public BlockMiner(final SystemProperties config, final CompositeEthereumListener listener, final Blockchain blockchain, final BlockStore blockStore, final PendingState pendingState) { @@ -119,13 +119,6 @@ public void onSyncDone(SyncState state) { } } - @Autowired - public BlockMiner(final SystemProperties config, final CompositeEthereumListener listener, - final ConsensusStrategy consensusStrategy, final BlockStore blockStore, - final PendingState pendingState) { - this(config, listener, consensusStrategy.getBlockchain(), blockStore, pendingState); - } - public void setFullMining(boolean fullMining) { this.fullMining = fullMining; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java index 54b0d91fdb..8727d58fea 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java @@ -85,6 +85,7 @@ public class Eth62 extends EthHandler { @Autowired protected NodeManager nodeManager; + @Autowired private ConsensusStrategy strategy; protected EthState ethState = EthState.INIT; @@ -127,11 +128,6 @@ public Eth62() { } @Autowired - public Eth62(final SystemProperties config, final ConsensusStrategy consensusStrategy, - final BlockStore blockStore, final CompositeEthereumListener ethereumListener) { - this(version, config, consensusStrategy.getBlockchain(), blockStore, ethereumListener); - this.strategy = consensusStrategy; - } public Eth62(final SystemProperties config, final Blockchain blockchain, final BlockStore blockStore, final CompositeEthereumListener ethereumListener) { this(version, config, blockchain, blockStore, ethereumListener); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java index 66dd6a14ee..39f0a780d6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java @@ -23,7 +23,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.StateSource; import org.ethereum.listener.CompositeEthereumListener; @@ -71,9 +70,9 @@ public Eth63() { } @Autowired - public Eth63(final SystemProperties config, final ConsensusStrategy consensusStrategy, BlockStore blockStore, + public Eth63(final SystemProperties config, final Blockchain blockchain, BlockStore blockStore, final CompositeEthereumListener ethereumListener) { - super(version, config, consensusStrategy.getBlockchain(), blockStore, ethereumListener); + super(version, config, blockchain, blockStore, ethereumListener); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java index 505c48e49b..45fcb10eb0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java @@ -19,8 +19,8 @@ import org.ethereum.core.BlockHeaderWrapper; import org.ethereum.core.BlockWrapper; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.IndexedBlockStore; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,8 +49,8 @@ public class FastSyncDownloader extends BlockDownloader { long t; @Autowired - public FastSyncDownloader(ConsensusStrategy consensusStrategy) { - super(consensusStrategy.getHeaderValidator()); + public FastSyncDownloader(BlockHeaderValidator headerValidator) { + super(headerValidator); } public void startImporting(byte[] fromHash, int count) { diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java index 5774f45f2c..bcb0982b80 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncManager.java @@ -23,7 +23,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.DbSource; import org.ethereum.db.DbFlushManager; @@ -78,11 +77,10 @@ public class FastSyncManager { @Autowired private SystemProperties config; - private ConsensusStrategy consensusStrategy; - @Autowired private SyncPool pool; + @Autowired private BlockchainImpl blockchain; @Autowired @@ -140,9 +138,6 @@ private void waitDbQueueSizeBelow(int size) { void init() { - // FIXME: We could run fast sync on Casper too - blockchain = (BlockchainImpl) consensusStrategy.getBlockchain(); - dbWriterThread = new Thread(() -> { try { while (!Thread.currentThread().isInterrupted()) { @@ -829,9 +824,4 @@ public void close() { logger.warn("Problems closing FastSyncManager", e); } } - - @Autowired - public void setConsensusStrategy(ConsensusStrategy consensusStrategy) { - this.consensusStrategy = consensusStrategy; - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java index 9f8dd8f976..2bed9b2837 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java @@ -20,13 +20,13 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.core.Blockchain; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.facade.SyncStatus; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; import org.ethereum.net.server.Channel; import org.ethereum.net.server.ChannelManager; import org.ethereum.util.ExecutorPipeline; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -83,6 +83,7 @@ public void accept(BlockWrapper blockWrapper) { */ private BlockingQueue blockQueue = new LinkedBlockingQueue<>(); + @Autowired private Blockchain blockchain; @Autowired @@ -114,9 +115,8 @@ public SyncManager() { } @Autowired - public SyncManager(final SystemProperties config, ConsensusStrategy consensusStrategy) { - super(consensusStrategy.getHeaderValidator()); - this.blockchain = consensusStrategy.getBlockchain(); + public SyncManager(final SystemProperties config, BlockHeaderValidator validator) { + super(validator); this.config = config; blockBytesLimit = config.blockQueueSize(); setHeaderQueueLimit(config.headerQueueSize() / BlockHeader.MAX_HEADER_SIZE); diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java index 7d093a7fc9..c24641b444 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncPool.java @@ -19,7 +19,6 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.listener.EthereumListener; import org.ethereum.net.rlpx.Node; import org.ethereum.net.rlpx.discover.NodeHandler; @@ -84,9 +83,9 @@ public class SyncPool { private ScheduledExecutorService logExecutor = Executors.newSingleThreadScheduledExecutor(); @Autowired - public SyncPool(final SystemProperties config, final ConsensusStrategy consensusStrategy) { + public SyncPool(final SystemProperties config, final Blockchain blockchain) { this.config = config; - this.blockchain = consensusStrategy.getBlockchain(); + this.blockchain = blockchain; } public void init(final ChannelManager channelManager) { diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 665c7af39a..059f8412bd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -516,7 +516,7 @@ private BlockchainImpl createBlockchain(Genesis genesis) { blockchain.byTest = true; - pendingState = new PendingStateImpl(listener, blockchain); + pendingState = new PendingStateImpl(listener); pendingState.setBlockchain(blockchain); blockchain.setPendingState(pendingState); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java index fe37c9222d..b75e55c040 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java @@ -896,13 +896,13 @@ public static BlockchainImpl createBlockchain(Genesis genesis) { EthereumListenerAdapter listener = new EthereumListenerAdapter(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(new CommonConfig().consensusStrategy().getParentHeaderValidator()); + .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.byTest = true; - PendingStateImpl pendingState = new PendingStateImpl(listener, blockchain); + PendingStateImpl pendingState = new PendingStateImpl(listener); pendingState.setBlockchain(blockchain); blockchain.setPendingState(pendingState); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java index 99dac8280d..ccb81b577f 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java @@ -125,13 +125,13 @@ private Blockchain createBlockchain(Genesis genesis) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(new CommonConfig().consensusStrategy().getParentHeaderValidator()); + .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.byTest = true; - PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter(), blockchain); + PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter()); pendingState.setBlockchain(blockchain); blockchain.setPendingState(pendingState); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index ecdd983bf8..213dcff434 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -27,7 +27,7 @@ import org.ethereum.core.EventDispatchThread; import org.ethereum.core.PendingStateImpl; import org.ethereum.core.TransactionReceipt; -import org.ethereum.core.consensus.CasperHybridConsensusStrategy; +import org.ethereum.casper.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.datasource.CountingBytesSource; import org.ethereum.datasource.JournalSource; @@ -157,7 +157,7 @@ private BlockchainImpl createBlockchain() { blockchain.byTest = true; - pendingState = new PendingStateImpl(listener, blockchain); + pendingState = new PendingStateImpl(listener); pendingState.setCommonConfig(commonConfig); pendingState.setBlockchain(blockchain); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 0e56236065..4a09beaafa 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -28,12 +28,10 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; import org.ethereum.core.Genesis; -import org.ethereum.core.TransactionReceipt; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.crypto.ECKey; import org.ethereum.db.ByteArrayWrapper; -import org.ethereum.listener.EthereumListenerAdapter; -import org.ethereum.manager.CasperValidatorService; +import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.sync.SyncManager; import org.ethereum.util.ByteUtil; import org.ethereum.util.blockchain.EtherUtil; 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 e35ecc7042..9fdf981fd5 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 @@ -33,6 +33,7 @@ import org.ethereum.jsontestsuite.suite.validators.RepositoryValidator; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.DataWord; import org.ethereum.vm.LogInfo; import org.ethereum.vm.VM; @@ -99,14 +100,14 @@ public List runTestCase(BlockTestCase testCase) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(CommonConfig.getDefault().consensusStrategy().getParentHeaderValidator()); + .withParentBlockHeaderValidator(CommonConfig.getDefault().parentHeaderValidator()); blockchain.byTest = true; - PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter(), blockchain); + PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter()); blockchain.setBestBlock(genesis); blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); - blockchain.setParentHeaderValidator(new CommonConfig().consensusStrategy().getParentHeaderValidator()); + blockchain.setParentHeaderValidator(new CommonConfig().parentHeaderValidator()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.setPendingState(pendingState); From 11fa1a7150906c9ced7fc5cc36a3c4c5d7d20f65 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 01:39:41 +0300 Subject: [PATCH 18/67] Fixed frame encoding for chunked frames --- .../src/main/java/org/ethereum/net/rlpx/FrameCodec.java | 5 ++++- .../src/main/java/org/ethereum/net/rlpx/MessageCodec.java | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java index 1f65bd5591..0904dd9a08 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java @@ -114,7 +114,10 @@ public void writeFrame(Frame frame, ByteBuf buf) throws IOException { public void writeFrame(Frame frame, OutputStream out) throws IOException { byte[] headBuffer = new byte[32]; - byte[] ptype = RLP.encodeInt((int) frame.type); // FIXME encodeLong + byte[] ptype = new byte[0]; + if (frame.type != -1) { // Type is actual only for 1st frame + ptype = RLP.encodeLong(frame.type); + } int totalSize = frame.size + ptype.length; headBuffer[0] = (byte)(totalSize >> 16); headBuffer[1] = (byte)(totalSize >> 8); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java index 75a0b40fcc..ccd485afce 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java @@ -199,14 +199,18 @@ private List splitMessageToFrames(Message msg) { int newPos = min(curPos + maxFramePayloadSize, bytes.length); byte[] frameBytes = curPos == 0 && newPos == bytes.length ? bytes : Arrays.copyOfRange(bytes, curPos, newPos); - ret.add(new Frame(code, frameBytes)); + if (curPos == 0) { // 1st frame needs type + ret.add(new Frame(code, frameBytes)); + } else { // Next frames don't need type + ret.add(new Frame(-1, frameBytes)); + } curPos = newPos; } if (ret.size() > 1) { // frame has been split int contextId = contextIdCounter.getAndIncrement(); - ret.get(0).totalFrameSize = bytes.length; + ret.get(0).totalFrameSize = bytes.length + 1; // type is 1 byte loggerWire.debug("Message (size " + bytes.length + ") split to " + ret.size() + " frames. Context-id: " + contextId); for (Frame frame : ret) { frame.contextId = contextId; From dbdbc28a3451bfadfe238ce17ef8e8dc73578e25 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 02:11:26 +0300 Subject: [PATCH 19/67] Fxied type size counting --- .../src/main/java/org/ethereum/net/rlpx/MessageCodec.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java index ccd485afce..8c464386c2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/MessageCodec.java @@ -34,6 +34,7 @@ import org.ethereum.net.server.Channel; import org.ethereum.net.shh.ShhMessageCodes; import org.ethereum.net.swarm.bzz.BzzMessageCodes; +import org.ethereum.util.RLP; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -210,7 +211,7 @@ private List splitMessageToFrames(Message msg) { if (ret.size() > 1) { // frame has been split int contextId = contextIdCounter.getAndIncrement(); - ret.get(0).totalFrameSize = bytes.length + 1; // type is 1 byte + ret.get(0).totalFrameSize = bytes.length + RLP.encodeLong(code).length; // type is part of the body loggerWire.debug("Message (size " + bytes.length + ") split to " + ret.size() + " frames. Context-id: " + contextId); for (Frame frame : ret) { frame.contextId = contextId; From a87b98f44e3481395416cc6cdc922b78273c7343 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 02:25:14 +0300 Subject: [PATCH 20/67] Fixed dirty read coded size adjust --- .../main/java/org/ethereum/net/rlpx/FrameCodec.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java index 0904dd9a08..2c2a6ab5bd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java @@ -224,15 +224,13 @@ public synchronized List readFrames(DataInput inp) throws IOException { InputStream payload = new ByteArrayInputStream(buffer, pos, totalBodySize - pos); int size = totalBodySize - pos; - // FIXME: 1 byte is lost in multi-frame, not sure, where is it - // this hack doesn't look normal - if (totalFrameSize > 0) { - size += pos; - } - if (contextFrameIndex.get(contextId) != null) { int curSize = contextFrameIndex.get(contextId); curSize -= size; + if (type != -1) { // Type is part of body too, so we should deduct it too + curSize -= RLP.encodeLong(type).length; + } + if (curSize > 0) { contextFrameIndex.put(contextId, curSize); } else { From 26f5c6e80c6b5357fbe937a944bddbef58f49476 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 17:11:10 +0300 Subject: [PATCH 21/67] Fixed incorrect Transactions creation (with lead zeros) --- .../ethereum/casper/service/CasperValidatorService.java | 8 +++++--- .../java/org/ethereum/core/casper/CasperBlockchain.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 22dc250506..88ca21bc39 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -259,7 +259,7 @@ private Transaction makeTx(byte[] receiveAddress, BigInteger value, byte[] data, nonce = repository.getNonce(coinbase.getAddress()); } if (gasLimit == null) { - gasLimit = ByteUtil.longToBytes(DEFAULT_GASLIMIT); + gasLimit = ByteUtil.longToBytesNoLeadZeroes(DEFAULT_GASLIMIT); } if (value == null) { value = BigInteger.ZERO; @@ -339,7 +339,8 @@ private Transaction makeDepositTx(byte[] valContractAddress, byte[] coinbaseAddr byte[] functionCallBytes = strategy.getCasper().getByName("deposit").encode( new ByteArrayWrapper(valContractAddress), new ByteArrayWrapper(coinbaseAddress)); - Transaction tx = makeTx(strategy.getCasperAddress(), deposit, functionCallBytes, null, ByteUtil.longToBytes(1_000_000), + Transaction tx = makeTx(strategy.getCasperAddress(), deposit, functionCallBytes, null, + ByteUtil.longToBytesNoLeadZeroes(1_000_000), null, true); return tx; @@ -347,7 +348,8 @@ private Transaction makeDepositTx(byte[] valContractAddress, byte[] coinbaseAddr private Transaction makeVoteTx(byte[] voteData) { byte[] functionCallBytes = strategy.getCasper().getByName("vote").encode(voteData); - Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, ByteUtil.longToBytes(1_000_000), + Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, + ByteUtil.longToBytesNoLeadZeroes(1_000_000), BigInteger.ZERO, false); return tx; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java index c268e5d655..3f537d80ea 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java @@ -257,7 +257,7 @@ protected BlockSummary applyBlock(Repository track, Block block) { Transaction tx = new Transaction( ByteUtil.bigIntegerToBytes(track.getNonce(NULL_SENDER.getAddress())), new byte[0], - ByteUtil.longToBytes(DEFAULT_GASLIMIT), + ByteUtil.longToBytesNoLeadZeroes(DEFAULT_GASLIMIT), strategy.getCasperAddress(), new byte[0], data From 770b377c7d6f3288aeb81431f583acb56a742e2f Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 17:31:31 +0300 Subject: [PATCH 22/67] Fixed wrong place of chunked frame size adjust --- .../src/main/java/org/ethereum/net/rlpx/FrameCodec.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java index 2c2a6ab5bd..43a585c8fe 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/rlpx/FrameCodec.java @@ -225,11 +225,11 @@ public synchronized List readFrames(DataInput inp) throws IOException { int size = totalBodySize - pos; if (contextFrameIndex.get(contextId) != null) { - int curSize = contextFrameIndex.get(contextId); - curSize -= size; if (type != -1) { // Type is part of body too, so we should deduct it too - curSize -= RLP.encodeLong(type).length; + size += RLP.encodeLong(type).length; } + int curSize = contextFrameIndex.get(contextId); + curSize -= size; if (curSize > 0) { contextFrameIndex.put(contextId, curSize); From 23e894cb7c20d1d98ae6107ce600da10111b358a Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 19:42:37 +0300 Subject: [PATCH 23/67] Fixed tests --- .../casper/service/CasperValidatorService.java | 14 +++++++------- .../java/org/ethereum/net/eth/handler/Eth62.java | 10 +++------- .../java/org/ethereum/core/casper/CasperBase.java | 7 +++++-- .../ethereum/core/casper/CasperValidatorTest.java | 1 + 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 88ca21bc39..8ab7593179 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -66,13 +66,11 @@ public class CasperValidatorService { private static final Logger logger = LoggerFactory.getLogger("casper.validator"); - @Autowired private SyncManager syncManager; private CasperHybridConsensusStrategy strategy; - @Autowired - Blockchain blockchain; + private Blockchain blockchain; private Repository repository; @@ -594,10 +592,7 @@ private long constCallCasperForLong(String func, Object... funcArgs) { return ((BigInteger) res[0]).longValue(); } - public void setStrategy(CasperHybridConsensusStrategy strategy) { - this.strategy = strategy; - } - + @Autowired public void setSyncManager(SyncManager syncManager) { this.syncManager = syncManager; } @@ -606,4 +601,9 @@ public void setSyncManager(SyncManager syncManager) { public void setStrategy(ConsensusStrategy strategy) { this.strategy = (CasperHybridConsensusStrategy) strategy; } + + @Autowired + public void setBlockchain(Blockchain blockchain) { + this.blockchain = blockchain; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java index 8727d58fea..59b67003d8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java @@ -23,7 +23,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.net.eth.EthVersion; @@ -85,9 +84,6 @@ public class Eth62 extends EthHandler { @Autowired protected NodeManager nodeManager; - @Autowired - private ConsensusStrategy strategy; - protected EthState ethState = EthState.INIT; protected PeerState peerState = IDLE; @@ -198,8 +194,8 @@ public synchronized void sendStatus() { totalDifficulty = blockchain.getTotalDifficulty(); } - StatusMessage msg = new StatusMessage(protocolVersion, networkId, - ByteUtil.bigIntegerToBytes(totalDifficulty), bestHash, strategy.getInitState().getInitGenesis().getHash()); + StatusMessage msg = new StatusMessage(protocolVersion, networkId, // Casper genesis from config is not final + ByteUtil.bigIntegerToBytes(totalDifficulty), bestHash, blockstore.getBlockHashByNumber(0)); sendMessage(msg); ethState = EthState.STATUS_SENT; @@ -324,7 +320,7 @@ protected synchronized void processStatus(StatusMessage msg, ChannelHandlerConte try { - if (!Arrays.equals(msg.getGenesisHash(), strategy.getInitState().getInitGenesis().getHash())) { + if (!Arrays.equals(msg.getGenesisHash(), blockstore.getBlockHashByNumber(0))) { // Casper genesis from config is not final if (!peerDiscoveryMode) { loggerNet.debug("Removing EthHandler for {} due to protocol incompatibility", ctx.channel().remoteAddress()); } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 213dcff434..4c218d2ac9 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -61,12 +61,13 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; -@RunWith(MockitoJUnitRunner.class) +// We have all mocks here and not all of them are used in every test, so strict stubs should be turned off +@RunWith(MockitoJUnitRunner.Silent.class) public abstract class CasperBase { @Mock ApplicationContext context; - final SystemProperties systemProperties = SystemProperties.getDefault(); + final SystemProperties systemProperties = new SystemProperties(); private CommonConfig commonConfig; @@ -183,6 +184,8 @@ private BlockchainImpl createBlockchain() { ethereum.setPendingState(blockchain.getPendingState()); ethereum.setChannelManager(Mockito.mock(ChannelManager.class)); ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); + strategy.setBlockchain(blockchain); + blockchain.setStrategy(strategy); // Push pending txs in StandaloneBlockchain ethereum.addListener(new EthereumListenerAdapter(){ diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 4a09beaafa..46ea16a1b7 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -148,6 +148,7 @@ public void validatorTest() { CasperValidatorService service = new CasperValidatorService(ethereum, systemProperties); service.setStrategy(strategy); + service.setBlockchain(blockchain); SyncManager syncManager = Mockito.mock(SyncManager.class); Mockito.when(syncManager.isSyncDone()).thenReturn(true); service.setSyncManager(syncManager); From d5c265013823d6082f878f104c5ccdccc609f061 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 22:03:31 +0300 Subject: [PATCH 24/67] Add publishing to jfrog --- build.gradle | 3 ++- ethereumj-core/build.gradle | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index fccac1ce29..d60180d732 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,8 @@ subprojects { group = 'org.ethereum' - version = config.versionNumber + ("master" == gitCurBranch() ? "-RELEASE" : "-SNAPSHOT") + version = config.versionNumber + ("master" == gitCurBranch() ? "-RELEASE" : + "research/casper" == gitCurBranch() ? "-CASPER" : "-SNAPSHOT") println("Building version: " + version + " (from branch " + gitCurBranch() + ")") diff --git a/ethereumj-core/build.gradle b/ethereumj-core/build.gradle index ed5d7cbae9..a1d7186ff9 100644 --- a/ethereumj-core/build.gradle +++ b/ethereumj-core/build.gradle @@ -220,10 +220,11 @@ artifactory { artifactoryPublish.onlyIf { (branchName != null) && (!pullRequest || pullRequest == 'false') && - project.version.endsWith('-SNAPSHOT') && + (project.version.endsWith('-SNAPSHOT') || project.version.endsWith('-CASPER')) && (branchName.startsWith('master') || branchName.startsWith('develop') || - branchName.startsWith('stage')) + branchName.startsWith('stage') || + branchName.startsWith('research/casper')) } bintray { @@ -243,7 +244,7 @@ bintray { bintrayUpload.onlyIf { // comment 'false' and uncomment the next line to publish next release - (!pullRequest || pullRequest == 'false') && !project.version.endsWith('-SNAPSHOT') + (!pullRequest || pullRequest == 'false') && !project.version.endsWith('-SNAPSHOT') && !project.version.endsWith('-CASPER') // false } From f932df1e0b9bbd7673f0a9233e5b9fddc4bb6576 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 6 Mar 2018 23:58:01 +0300 Subject: [PATCH 25/67] Trying another naming for publishing --- build.gradle | 2 +- ethereumj-core/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index d60180d732..997188df6f 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ subprojects { group = 'org.ethereum' version = config.versionNumber + ("master" == gitCurBranch() ? "-RELEASE" : - "research/casper" == gitCurBranch() ? "-CASPER" : "-SNAPSHOT") + "research/casper" == gitCurBranch() ? "-casper-SNAPSHOT" : "-SNAPSHOT") println("Building version: " + version + " (from branch " + gitCurBranch() + ")") diff --git a/ethereumj-core/build.gradle b/ethereumj-core/build.gradle index a1d7186ff9..835f608e4d 100644 --- a/ethereumj-core/build.gradle +++ b/ethereumj-core/build.gradle @@ -220,7 +220,7 @@ artifactory { artifactoryPublish.onlyIf { (branchName != null) && (!pullRequest || pullRequest == 'false') && - (project.version.endsWith('-SNAPSHOT') || project.version.endsWith('-CASPER')) && + project.version.endsWith('-SNAPSHOT') && (branchName.startsWith('master') || branchName.startsWith('develop') || branchName.startsWith('stage') || @@ -244,7 +244,7 @@ bintray { bintrayUpload.onlyIf { // comment 'false' and uncomment the next line to publish next release - (!pullRequest || pullRequest == 'false') && !project.version.endsWith('-SNAPSHOT') && !project.version.endsWith('-CASPER') + (!pullRequest || pullRequest == 'false') && !project.version.endsWith('-SNAPSHOT') // false } From beccdb9247e5687f9a8443ab002696fb807138b6 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 7 Mar 2018 19:20:50 +0300 Subject: [PATCH 26/67] TransactionExecutor creation moved to CommonConfig. CasperBlockchain and CasperTransactionExecutor moved to casper package. --- .../casper/config/CasperBeanConfig.java | 37 ++++++++++++- .../core}/CasperBlockchain.java | 13 +++-- .../CasperHybridConsensusStrategy.java | 24 +------- .../core}/CasperTransactionExecutor.java | 4 +- .../service/CasperValidatorService.java | 3 +- .../org/ethereum/config/CommonConfig.java | 23 ++++++++ .../org/ethereum/core/BlockchainImpl.java | 3 +- .../org/ethereum/core/PendingStateImpl.java | 7 ++- .../core/TransactionExecutorFactory.java | 36 ++++++++++++ .../core/consensus/ConsensusStrategy.java | 14 ----- .../core/consensus/PoWConsensusStrategy.java | 23 -------- .../org/ethereum/facade/EthereumImpl.java | 6 +- .../org/ethereum/manager/WorldManager.java | 2 +- .../java/org/ethereum/mine/BlockMiner.java | 4 +- .../util/blockchain/StandaloneBlockchain.java | 4 +- .../org/ethereum/core/casper/CasperBase.java | 55 ++++++++++--------- .../ethereum/longrun/SyncWithLoadTest.java | 7 ++- 17 files changed, 156 insertions(+), 109 deletions(-) rename ethereumj-core/src/main/java/org/ethereum/{core/casper => casper/core}/CasperBlockchain.java (96%) rename ethereumj-core/src/main/java/org/ethereum/casper/{ => core}/CasperHybridConsensusStrategy.java (78%) rename ethereumj-core/src/main/java/org/ethereum/{core/casper => casper/core}/CasperTransactionExecutor.java (98%) create mode 100644 ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index ec7e16a3ee..8828bbe26b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -18,10 +18,19 @@ package org.ethereum.casper.config; import org.ethereum.config.CommonConfig; +import org.ethereum.core.Block; import org.ethereum.core.Blockchain; -import org.ethereum.core.casper.CasperBlockchain; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.core.Repository; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutor; +import org.ethereum.core.TransactionExecutorFactory; +import org.ethereum.casper.core.CasperBlockchain; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperTransactionExecutor; import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.db.BlockStore; +import org.ethereum.listener.EthereumListener; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -40,4 +49,28 @@ public ConsensusStrategy consensusStrategy() { public Blockchain blockchain() { return new CasperBlockchain(systemProperties()); } + + @Override + @Bean + public TransactionExecutorFactory transactionExecutorFactory() { + return new CasperTransactionExecutorFactory(); + } + + class CasperTransactionExecutorFactory implements TransactionExecutorFactory { + + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock) { + return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); + } + + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { + return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, + listener, gasUsedInTheBlock); + } + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java similarity index 96% rename from ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java rename to ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 3f537d80ea..5af6d45f3b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.core.casper; +package org.ethereum.casper.core; import javafx.util.Pair; import org.ethereum.config.BlockchainConfig; @@ -29,8 +29,9 @@ import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutor; +import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.db.ByteArrayWrapper; @@ -270,7 +271,8 @@ protected BlockSummary applyBlock(Repository track, Block block) { stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); Repository txTrack = track.startTracking(); - TransactionExecutor executor = strategy.createTransactionExecutor(tx, block.getCoinbase(), + TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); + TransactionExecutor executor = txFactory.createTransactionExecutor(tx, block.getCoinbase(), txTrack, blockStore, getProgramInvokeFactory(), block, listener, totalGasUsed) .withCommonConfig(commonConfig); @@ -342,8 +344,9 @@ private void initCasper(Repository track, Block block) { track.addBalance(NULL_SENDER.getAddress(), BigInteger.valueOf(15).pow(18)); Repository txTrack = track.startTracking(); - TransactionExecutor executor = strategy.createTransactionExecutor(tx, genesis.getCoinbase(), - txTrack, blockStore, getProgramInvokeFactory(), genesis, listener, 0) + TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); + TransactionExecutor executor = txFactory.createTransactionExecutor(tx, + genesis.getCoinbase(), txTrack, blockStore, getProgramInvokeFactory(), genesis, listener, 0) .withCommonConfig(commonConfig); executor.init(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/CasperHybridConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java similarity index 78% rename from ethereumj-core/src/main/java/org/ethereum/casper/CasperHybridConsensusStrategy.java rename to ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java index 9e4506bcfe..3f4fd3c05b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/CasperHybridConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java @@ -15,27 +15,20 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.casper; +package org.ethereum.casper.core; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.CallTransaction; import org.ethereum.core.Genesis; -import org.ethereum.core.Repository; import org.ethereum.core.Transaction; -import org.ethereum.core.TransactionExecutor; -import org.ethereum.core.casper.CasperBlockchain; -import org.ethereum.core.casper.CasperTransactionExecutor; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.core.genesis.StateInit; -import org.ethereum.db.BlockStore; import org.ethereum.facade.Ethereum; -import org.ethereum.listener.EthereumListener; import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.vm.program.ProgramResult; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -93,21 +86,6 @@ public StateInit getInitState() { return stateInit; } - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock) { - return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); - } - - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { - return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, - listener, gasUsedInTheBlock); - } - public CallTransaction.Contract getCasper() { initCasper(); return casper; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java similarity index 98% rename from ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java rename to ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 72036418c5..42d193ac78 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/casper/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -15,13 +15,13 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.core.casper; +package org.ethereum.casper.core; import org.ethereum.core.Block; import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutionSummary; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 8ab7593179..57684a5f16 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -24,7 +24,7 @@ import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.db.ByteArrayWrapper; @@ -39,7 +39,6 @@ import org.spongycastle.util.BigIntegers; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index c957c59943..06a9237955 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -41,6 +41,7 @@ import org.ethereum.validator.ProofOfWorkRule; import org.ethereum.vm.DataWord; import org.ethereum.vm.program.ProgramPrecompile; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -296,4 +297,26 @@ public Blockchain blockchain() { public ConsensusStrategy consensusStrategy() { return new PoWConsensusStrategy(systemProperties(), ctx); } + + @Bean + public TransactionExecutorFactory transactionExecutorFactory() { + return new CommonTransactionExecutorFactory(); + } + + class CommonTransactionExecutorFactory implements TransactionExecutorFactory { + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock) { + return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); + } + + @Override + public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { + return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, + listener, gasUsedInTheBlock); + } + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index feea547f5c..ac6fed6af9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -875,7 +875,8 @@ protected BlockSummary applyBlock(Repository track, Block block) { stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); Repository txTrack = track.startTracking(); - TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor(tx, block.getCoinbase(), + TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); + TransactionExecutor executor = txFactory.createTransactionExecutor(tx, block.getCoinbase(), txTrack, blockStore, programInvokeFactory, block, listener, totalGasUsed) .withCommonConfig(commonConfig); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 791028e1c9..676f9a0a30 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -32,8 +32,8 @@ import org.apache.commons.collections4.map.LRUMap; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.core.casper.CasperTransactionExecutor; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperTransactionExecutor; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; @@ -449,7 +449,8 @@ private TransactionReceipt executeTx(Transaction tx) { Block best = getBestBlock(); - TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor( + TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); + TransactionExecutor executor = txFactory.createTransactionExecutor( tx, best.getCoinbase(), getRepository(), blockStore, programInvokeFactory, createFakePendingBlock(), new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java new file mode 100644 index 0000000000..5d13df7c02 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core; + +import org.ethereum.db.BlockStore; +import org.ethereum.listener.EthereumListener; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; + +/** + * Creates custom {@link TransactionExecutor} tailored for current environment + */ +public interface TransactionExecutorFactory { + + TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock); + + TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, + BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, + Block currentBlock, EthereumListener listener, long gasUsedInTheBlock); +} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java index a31359144c..787b18f220 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java @@ -17,15 +17,8 @@ */ package org.ethereum.core.consensus; -import org.ethereum.core.Block; import org.ethereum.core.Genesis; -import org.ethereum.core.Repository; -import org.ethereum.core.Transaction; -import org.ethereum.core.TransactionExecutor; import org.ethereum.core.genesis.StateInit; -import org.ethereum.db.BlockStore; -import org.ethereum.listener.EthereumListener; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; public interface ConsensusStrategy { void init(); @@ -39,11 +32,4 @@ public interface ConsensusStrategy { * @return state initializer after state is initialized */ StateInit getInitState(); - - TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, - ProgramInvokeFactory programInvokeFactory, Block currentBlock); - - TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, BlockStore blockStore, - ProgramInvokeFactory programInvokeFactory, Block currentBlock, - EthereumListener listener, long gasUsedInTheBlock); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java index 72ba6908fd..df9d993dd4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java @@ -18,18 +18,10 @@ package org.ethereum.core.consensus; import org.ethereum.config.SystemProperties; -import org.ethereum.core.Block; import org.ethereum.core.BlockchainImpl; -import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Genesis; -import org.ethereum.core.Repository; -import org.ethereum.core.Transaction; -import org.ethereum.core.TransactionExecutor; import org.ethereum.core.genesis.CommonStateInit; import org.ethereum.core.genesis.StateInit; -import org.ethereum.db.BlockStore; -import org.ethereum.listener.EthereumListener; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -75,19 +67,4 @@ public StateInit getInitState() { } return stateInit; } - - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock) { - return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); - } - - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { - return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, - listener, gasUsedInTheBlock); - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index 0432214ac9..82748dacdc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -284,7 +284,8 @@ public BlockSummary replayBlock(Block block) { for (Transaction tx : block.getTransactionsList()) { Repository txTrack = track.startTracking(); - org.ethereum.core.TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor( + TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); + org.ethereum.core.TransactionExecutor executor = txFactory.createTransactionExecutor( tx, block.getCoinbase(), txTrack, worldManager.getBlockStore(), programInvokeFactory, block, worldManager.getListener(), 0) .withCommonConfig(commonConfig); @@ -316,7 +317,8 @@ private org.ethereum.core.TransactionExecutor callConstantImpl(Transaction tx, B .startTracking(); try { - org.ethereum.core.TransactionExecutor executor = commonConfig.consensusStrategy().createTransactionExecutor( + TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); + org.ethereum.core.TransactionExecutor executor = txFactory.createTransactionExecutor( tx, block.getCoinbase(), repository, worldManager.getBlockStore(), programInvokeFactory, block, new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index 38608b0114..99a98fa464 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -19,7 +19,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index 56e65a31ba..de3de8c5aa 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -22,8 +22,8 @@ import org.apache.commons.collections4.CollectionUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.casper.CasperTransactionExecutor; -import org.ethereum.casper.CasperHybridConsensusStrategy; +import org.ethereum.casper.core.CasperTransactionExecutor; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index 059f8412bd..b0e2aa0f47 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -617,8 +617,8 @@ public Object[] callConstFunction(Block callBlock, String functionName, Object.. Repository repository = getBlockchain().getRepository().getSnapshotTo(callBlock.getStateRoot()).startTracking(); try { - ConsensusStrategy strategy = CommonConfig.getDefault().consensusStrategy(); - org.ethereum.core.TransactionExecutor executor = strategy.createTransactionExecutor( + TransactionExecutorFactory transactionExecutorFactory = CommonConfig.getDefault().transactionExecutorFactory(); + org.ethereum.core.TransactionExecutor executor = transactionExecutorFactory.createTransactionExecutor( tx, callBlock.getCoinbase(), repository, getBlockchain().getBlockStore(), getBlockchain().getProgramInvokeFactory(), callBlock) .setLocalCall(true); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 4c218d2ac9..6db5444fe9 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -17,6 +17,8 @@ */ package org.ethereum.core.casper; +import org.ethereum.casper.config.CasperBeanConfig; +import org.ethereum.casper.core.CasperBlockchain; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; @@ -26,9 +28,9 @@ import org.ethereum.core.BlockchainImpl; import org.ethereum.core.EventDispatchThread; import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; -import org.ethereum.casper.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.datasource.CountingBytesSource; import org.ethereum.datasource.JournalSource; import org.ethereum.datasource.Source; @@ -51,12 +53,16 @@ import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.Before; import org.junit.runner.RunWith; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.context.ApplicationContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; @@ -67,51 +73,49 @@ public abstract class CasperBase { @Mock ApplicationContext context; - final SystemProperties systemProperties = new SystemProperties(); + @InjectMocks + private CommonConfig commonConfig = new CasperBeanConfig() { + @Override + public Source precompileSource() { + return null; + } + }; + + final SystemProperties systemProperties = commonConfig.systemProperties(); - private CommonConfig commonConfig; + @Spy + private TransactionExecutorFactory transactionExecutorFactory = commonConfig.transactionExecutorFactory(); CasperBlockchain blockchain; WorldManager worldManager; - EthereumImpl ethereum; - private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); + @InjectMocks + EthereumImpl ethereum = new EthereumImpl(systemProperties, defaultListener); + CasperHybridConsensusStrategy strategy; StandaloneBlockchain bc; @Before - public void setup() { + public void setup() throws Exception { // Just trust me! // FIXME: Make it a little bit readable + systemProperties.setBlockchainConfig(config()); - systemProperties.setGenesisInfo("casper.json"); + Resource casperGenesis = new ClassPathResource("/genesis/casper.json"); + systemProperties.useGenesis(casperGenesis.getInputStream()); systemProperties.overrideParams( "consensus.casper.epochLength", "50", "consensus.casper.contractBin", "/casper/casper.bin", "consensus.casper.contractAbi", "/casper/casper.abi" ); - MockitoAnnotations.initMocks(this); - this.commonConfig = new CommonConfig() { - @Override - public Source precompileSource() { - return null; - } - @Override - public ConsensusStrategy consensusStrategy() { - if (strategy == null) { - strategy = new CasperHybridConsensusStrategy(systemProperties, context); - } - return strategy; - } - }; + MockitoAnnotations.initMocks(this); - this.ethereum = new EthereumImpl(systemProperties, defaultListener); - ethereum.setCommonConfig(commonConfig); + this.ethereum.setCommonConfig(commonConfig); this.worldManager = Mockito.mock(WorldManager.class); this.bc = new StandaloneBlockchain() { @@ -183,7 +187,8 @@ private BlockchainImpl createBlockchain() { ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); ethereum.setPendingState(blockchain.getPendingState()); ethereum.setChannelManager(Mockito.mock(ChannelManager.class)); - ((CasperHybridConsensusStrategy) commonConfig.consensusStrategy()).setEthereum(ethereum); + this.strategy = (CasperHybridConsensusStrategy) commonConfig.consensusStrategy(); + strategy.setEthereum(ethereum); strategy.setBlockchain(blockchain); blockchain.setStrategy(strategy); diff --git a/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java b/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java index cd32555004..d642e56fbf 100644 --- a/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java @@ -27,9 +27,9 @@ import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutor; +import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; import org.ethereum.db.ContractDetails; -import org.ethereum.db.RepositoryImpl; import org.ethereum.facade.Ethereum; import org.ethereum.facade.EthereumFactory; import org.ethereum.listener.EthereumListener; @@ -161,6 +161,9 @@ static class RegularNode extends BasicNode { @Autowired SyncManager syncManager; + @Autowired + TransactionExecutorFactory transactionExecutorFactory; + /** * The main EthereumJ callback. */ @@ -207,7 +210,7 @@ public void onPendingTransactionsReceived(List transactions) { .getSnapshotTo(block.getStateRoot()) .startTracking(); try { - TransactionExecutor executor = ethereum.getConsensusStrategy().createTransactionExecutor( + TransactionExecutor executor = transactionExecutorFactory.createTransactionExecutor( tx, block.getCoinbase(), repository, ethereum.getBlockchain().getBlockStore(), programInvokeFactory, block, new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig) From abc8906c7998ce41a04b358a19132e94ece3c7c1 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 7 Mar 2018 20:20:41 +0300 Subject: [PATCH 27/67] Net config moved to casper package --- .../ethereum/{ => casper}/config/net/CasperTestNetConfig.java | 3 ++- .../src/main/java/org/ethereum/config/SystemProperties.java | 1 + .../src/test/java/org/ethereum/core/casper/CasperBase.java | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) rename ethereumj-core/src/main/java/org/ethereum/{ => casper}/config/net/CasperTestNetConfig.java (96%) diff --git a/ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java similarity index 96% rename from ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java rename to ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java index cef3227490..178bb6d905 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/net/CasperTestNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.config.net; +package org.ethereum.casper.config.net; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.Constants; @@ -23,6 +23,7 @@ import org.ethereum.config.blockchain.ByzantiumConfig; import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; +import org.ethereum.config.net.BaseNetConfig; import org.ethereum.vm.GasCost; import java.math.BigInteger; 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 13c578e618..71a86349f0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -22,6 +22,7 @@ import com.typesafe.config.ConfigObject; import com.typesafe.config.ConfigRenderOptions; import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.casper.config.net.CasperTestNetConfig; import org.ethereum.config.blockchain.OlympicConfig; import org.ethereum.config.net.*; import org.ethereum.core.Genesis; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 6db5444fe9..4957fb9453 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -22,7 +22,7 @@ import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.config.net.CasperTestNetConfig; +import org.ethereum.casper.config.net.CasperTestNetConfig; import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; import org.ethereum.core.BlockchainImpl; From 6d23835b0c7fa26c5dc0d940c9f22f53b1114e8b Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 7 Mar 2018 20:29:02 +0300 Subject: [PATCH 28/67] Moved switching to short sync on manual miner start to Harmony --- .../org/ethereum/manager/WorldManager.java | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index 99a98fa464..f86c952f82 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -137,33 +137,6 @@ private void init() { channelManager.init(ethereum); syncManager.init(channelManager, pool); strategy.init(); - - ethereum.getBlockMiner().addListener(new MinerListener() { - @Override - public void miningStarted() { - syncManager.makeSyncDone(); - } - - @Override - public void miningStopped() { - - } - - @Override - public void blockMiningStarted(Block block) { - - } - - @Override - public void blockMined(Block block) { - - } - - @Override - public void blockMiningCanceled(Block block) { - - } - }); } public void addListener(EthereumListener listener) { From 5c8634d8a58922a00f6fb790ace90a8a0ded2293 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 8 Mar 2018 19:21:06 +0300 Subject: [PATCH 29/67] Completely removed ConsensusStrategy abstraction --- .../casper/config/CasperBeanConfig.java | 33 +++- .../casper/core/CasperBlockchain.java | 39 ++--- .../ethereum/casper/core/CasperFacade.java | 91 +++++++++++ .../core/CasperHybridConsensusStrategy.java | 141 ------------------ .../casper/core/CasperPendingStateImpl.java | 62 ++++++++ .../core/CasperTransactionExecutor.java | 3 - .../casper/manager/CasperWorldManager.java | 49 ++++++ .../casper/mine/CasperBlockMiner.java | 42 ++++++ .../service/CasperValidatorService.java | 82 +++++----- .../org/ethereum/config/CommonConfig.java | 33 ++-- .../org/ethereum/config/SystemProperties.java | 5 - .../org/ethereum/core/PendingStateImpl.java | 33 +--- .../core/consensus/ConsensusStrategy.java | 35 ----- .../core/consensus/PoWConsensusStrategy.java | 70 --------- .../core/genesis/CasperStateInit.java | 6 +- .../java/org/ethereum/facade/Ethereum.java | 3 - .../org/ethereum/facade/EthereumImpl.java | 6 - .../org/ethereum/manager/WorldManager.java | 42 +++--- .../java/org/ethereum/mine/BlockMiner.java | 16 +- .../util/blockchain/StandaloneBlockchain.java | 1 - .../org/ethereum/core/casper/CasperBase.java | 32 ++-- .../core/casper/CasperEpochSwitchTest.java | 15 +- .../core/casper/CasperStateInitTest.java | 4 +- .../core/casper/CasperValidatorTest.java | 13 +- .../org/ethereum/mine/ExternalMinerTest.java | 2 +- 25 files changed, 421 insertions(+), 437 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index 8828bbe26b..d60f7bf23d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -17,19 +17,24 @@ */ package org.ethereum.casper.config; +import org.ethereum.casper.core.CasperPendingStateImpl; +import org.ethereum.casper.manager.CasperWorldManager; +import org.ethereum.casper.mine.CasperBlockMiner; import org.ethereum.config.CommonConfig; import org.ethereum.core.Block; import org.ethereum.core.Blockchain; +import org.ethereum.core.PendingState; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutor; import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.casper.core.CasperBlockchain; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.casper.core.CasperTransactionExecutor; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; +import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; +import org.ethereum.manager.WorldManager; +import org.ethereum.mine.BlockMiner; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -39,11 +44,6 @@ @EnableTransactionManagement public class CasperBeanConfig extends CommonConfig { - @Override - public ConsensusStrategy consensusStrategy() { - return new CasperHybridConsensusStrategy(systemProperties(), ctx); - } - @Override @Bean public Blockchain blockchain() { @@ -73,4 +73,23 @@ public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coin listener, gasUsedInTheBlock); } } + + @Bean + @Override + public WorldManager worldManager() { + return new CasperWorldManager(systemProperties(), repository(), blockchain()); + } + + @Bean + @Override + public PendingState pendingState() { + return new CasperPendingStateImpl(ethereumListener); + } + + @Bean + @Override + public BlockMiner blockMiner() { + return new CasperBlockMiner(systemProperties(), (CompositeEthereumListener) ethereumListener, + blockchain(), pendingState()); + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 5af6d45f3b..175fff0939 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -17,13 +17,11 @@ */ package org.ethereum.casper.core; -import javafx.util.Pair; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; import org.ethereum.core.BlockchainImpl; -import org.ethereum.core.Genesis; import org.ethereum.core.ImportResult; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; @@ -31,9 +29,6 @@ import org.ethereum.core.TransactionExecutor; import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; -import org.ethereum.core.genesis.CasperStateInit; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; @@ -60,14 +55,15 @@ public class CasperBlockchain extends BlockchainImpl { + @Autowired + private CasperFacade casper; + private static final Logger logger = LoggerFactory.getLogger("blockchain"); private static final Logger stateLogger = LoggerFactory.getLogger("state"); private static final BigInteger PRETTY_BIG = BigInteger.valueOf(10).pow(40); private static final BigInteger NON_REVERT_MIN_DEPOSIT = BigInteger.valueOf(10).pow(18); - private CasperHybridConsensusStrategy strategy; - public CasperBlockchain() { throw new RuntimeException("Empty constructor not available"); } @@ -119,7 +115,7 @@ private boolean switchRevertsFinalizedBlock(final Block block) { } private BigInteger getScore(final Block block) { - Object[] res = strategy.constCallCasper(block, "get_last_justified_epoch"); + Object[] res = casper.constCall(block, "get_last_justified_epoch"); return ((BigInteger) res[0]).multiply(PRETTY_BIG).add(getPoWDifficulty(block)); } @@ -208,19 +204,19 @@ private synchronized ImportResult casperConnect(final Block block) { * Finalizes Casper epoch checkpoint if needed */ private void finalizeCheckpoint(final Block block) { - Object[] res = strategy.constCallCasper(block, "get_last_finalized_epoch"); + Object[] res = casper.constCall(block, "get_last_finalized_epoch"); long finalizedEpoch = ((BigInteger) res[0]).longValue(); - Object[] res2 = strategy.constCallCasper(block, "get_current_epoch"); + Object[] res2 = casper.constCall(block, "get_current_epoch"); long currentEpoch = ((BigInteger) res2[0]).longValue(); if (finalizedEpoch == currentEpoch - 1) { // Actually one hash per epoch, just the getter for array - Object[] res3 = strategy.constCallCasper(block, "get_checkpoint_hashes", finalizedEpoch); + Object[] res3 = casper.constCall(block, "get_checkpoint_hashes", finalizedEpoch); byte[] checkpointHash = (byte[]) res3[0]; if (!Arrays.areEqual(checkpointHash, new byte[32])) { // new byte[32] == 00-filled Block histBlock = getBlockByHash(checkpointHash); - Object[] res4 = strategy.constCallCasper(histBlock, "get_total_curdyn_deposits"); + Object[] res4 = casper.constCall(histBlock, "get_total_curdyn_deposits"); BigInteger curDeposits = (BigInteger) res4[0]; - Object[] res5 = strategy.constCallCasper(histBlock, "get_total_prevdyn_deposits"); + Object[] res5 = casper.constCall(histBlock, "get_total_prevdyn_deposits"); BigInteger prevDeposits = (BigInteger) res5[0]; if (curDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0 && prevDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0) { @@ -254,12 +250,12 @@ protected BlockSummary applyBlock(Repository track, Block block) { int epochLength = config.getCasperEpochLength(); if(block.getNumber() % epochLength == 0 && block.getNumber() != 0) { long startingEpoch = block.getNumber() / epochLength; - byte[] data = strategy.getCasper().getByName("initialize_epoch").encode(startingEpoch); + byte[] data = casper.getContract().getByName("initialize_epoch").encode(startingEpoch); Transaction tx = new Transaction( ByteUtil.bigIntegerToBytes(track.getNonce(NULL_SENDER.getAddress())), new byte[0], ByteUtil.longToBytesNoLeadZeroes(DEFAULT_GASLIMIT), - strategy.getCasperAddress(), + casper.getAddress(), new byte[0], data ); @@ -333,11 +329,9 @@ private void initCasper(Repository track, Block block) { if (block.getNumber() != 1) return; - - Pair> res = ((CasperStateInit) strategy.getInitState()).makeInitTxes(); - List txs = res.getValue(); - Genesis genesis = strategy.getInitState().getInitGenesis(); + List txs = casper.getInitTxs(); byte[] casperAddress = config.getCasperAddress(); + byte[] coinbase = blockStore.getChainBlockByNumber(0).getCoinbase(); txs.forEach((tx) -> { // We need money! @@ -346,7 +340,7 @@ private void initCasper(Repository track, Block block) { Repository txTrack = track.startTracking(); TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); TransactionExecutor executor = txFactory.createTransactionExecutor(tx, - genesis.getCoinbase(), txTrack, blockStore, getProgramInvokeFactory(), genesis, listener, 0) + coinbase, txTrack, blockStore, getProgramInvokeFactory(), block, listener, 0) .withCommonConfig(commonConfig); executor.init(); @@ -438,8 +432,7 @@ private BigInteger getPoWDifficulty(final Block block) { return blockStore.getTotalDifficultyForHash(block.getHash()); } - @Autowired - public void setStrategy(ConsensusStrategy strategy) { - this.strategy = (CasperHybridConsensusStrategy) strategy; + public void setCasper(CasperFacade casper) { + this.casper = casper; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java new file mode 100644 index 0000000000..68d5be256e --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.core; + +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Block; +import org.ethereum.core.CallTransaction; +import org.ethereum.core.Transaction; +import org.ethereum.facade.Ethereum; +import org.ethereum.vm.program.ProgramResult; +import org.spongycastle.util.encoders.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class CasperFacade { + + @Autowired + private SystemProperties systemProperties; + + private Ethereum ethereum; + + private CallTransaction.Contract casper = null; + + private String contractAddress; // FIXME: why should we have casper addresses in two places?. It's already in SystemProperties + + private List initTxs; + + public CallTransaction.Contract getContract() { + init(); + return casper; + } + + private void init() { + if (casper == null) { + contractAddress = Hex.toHexString(systemProperties.getCasperAddress()); + String casperAbi = systemProperties.getCasperAbi(); + casper = new CallTransaction.Contract(casperAbi); + } + } + + public Object[] constCall(String func, Object... funcArgs) { + init(); + ProgramResult r = ethereum.callConstantFunction(contractAddress, + casper.getByName(func), funcArgs); + return casper.getByName(func).decodeResult(r.getHReturn()); + } + + + public Object[] constCall(Block block, String func, Object... funcArgs) { + init(); + Transaction tx = CallTransaction.createCallTransaction(0, 0, 100000000000000L, + contractAddress, 0, casper.getByName(func), funcArgs); + ProgramResult r = ethereum.callConstantFunction(block, contractAddress, + casper.getByName(func), funcArgs); + return casper.getByName(func).decodeResult(r.getHReturn()); + } + + public byte[] getAddress() { + return Hex.decode(contractAddress); + } + + public List getInitTxs() { + return initTxs; + } + + public void setInitTxs(List initTxs) { + this.initTxs = initTxs; + } + + public void setEthereum(Ethereum ethereum) { + this.ethereum = ethereum; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java deleted file mode 100644 index 3f4fd3c05b..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperHybridConsensusStrategy.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.casper.core; - -import org.ethereum.config.SystemProperties; -import org.ethereum.core.Block; -import org.ethereum.core.Blockchain; -import org.ethereum.core.CallTransaction; -import org.ethereum.core.Genesis; -import org.ethereum.core.Transaction; -import org.ethereum.core.consensus.ConsensusStrategy; -import org.ethereum.core.genesis.CasperStateInit; -import org.ethereum.core.genesis.StateInit; -import org.ethereum.facade.Ethereum; -import org.ethereum.casper.service.CasperValidatorService; -import org.ethereum.vm.program.ProgramResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.spongycastle.util.encoders.Hex; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; - -public class CasperHybridConsensusStrategy implements ConsensusStrategy { - - private static final Logger logger = LoggerFactory.getLogger("general"); - - private SystemProperties systemProperties; - - private CasperBlockchain blockchain; - - private CasperValidatorService casperValidatorService; - - private Ethereum ethereum; - - private ApplicationContext ctx; - - private StateInit stateInit; - - private CallTransaction.Contract casper = null; - - private String casperAddress; // FIXME: why should we have casper addresses in two places?. It's already in SystemProperties - - public CasperHybridConsensusStrategy() { - } - - public CasperHybridConsensusStrategy(SystemProperties systemProperties, ApplicationContext ctx) { - this.systemProperties = systemProperties; - this.ctx = ctx; - } - - @Override - public void init() { - getCasperValidatorService(); - } - - @Override - public StateInit initState(Genesis genesis) { - if (stateInit != null) { - throw new RuntimeException("State is already initialized"); - } else { - this.stateInit = new CasperStateInit(genesis, blockchain.getRepository(), blockchain, ctx, systemProperties); - } - return stateInit; - } - - @Override - public StateInit getInitState() { - if (stateInit == null) { - throw new RuntimeException("State is not initialized"); - } - return stateInit; - } - - public CallTransaction.Contract getCasper() { - initCasper(); - return casper; - } - - private void initCasper() { - if (casper == null) { - casperAddress = Hex.toHexString(systemProperties.getCasperAddress()); - String casperAbi = systemProperties.getCasperAbi(); - casper = new CallTransaction.Contract(casperAbi); - } - } - - public Object[] constCallCasper(String func, Object... funcArgs) { - initCasper(); - ProgramResult r = ethereum.callConstantFunction(casperAddress, - casper.getByName(func), funcArgs); - return casper.getByName(func).decodeResult(r.getHReturn()); - } - - - public Object[] constCallCasper(Block block, String func, Object... funcArgs) { - initCasper(); - Transaction tx = CallTransaction.createCallTransaction(0, 0, 100000000000000L, - casperAddress, 0, casper.getByName(func), funcArgs); - ProgramResult r = ethereum.callConstantFunction(block, casperAddress, - casper.getByName(func), funcArgs); - return casper.getByName(func).decodeResult(r.getHReturn()); - } - - public byte[] getCasperAddress() { - return Hex.decode(casperAddress); - } - - public CasperValidatorService getCasperValidatorService() { - if (casperValidatorService == null && - systemProperties.getCasperValidatorEnabled() != null && systemProperties.getCasperValidatorEnabled()) { - logger.info("Casper validator is enabled, starting..."); - this.casperValidatorService = ctx.getBean(CasperValidatorService.class); - } - - return casperValidatorService; - } - - public void setEthereum(Ethereum ethereum) { - this.ethereum = ethereum; - } - - @Autowired - public void setBlockchain(Blockchain blockchain) { - this.blockchain = (CasperBlockchain) blockchain; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java new file mode 100644 index 0000000000..b0dad1beb5 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.core; + +import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionReceipt; +import org.ethereum.listener.EthereumListener; +import org.ethereum.util.ByteUtil; + +public class CasperPendingStateImpl extends PendingStateImpl { + + public CasperPendingStateImpl(EthereumListener listener) { + super(listener); + } + + @Override + protected boolean receiptIsValid(TransactionReceipt receipt) { + boolean isValid = super.receiptIsValid(receipt); + if (isValid) { + return true; + } else if (CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), config.getCasperAddress())) { + return receipt.isSuccessful(); + } + + return false; + } + + @Override + protected String validate(Transaction tx) { + try { + tx.verify(); + } catch (Exception e) { + return String.format("Invalid transaction: %s", e.getMessage()); + } + + if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { + return null; // Doesn't require more checks + } + + if (config.getMineMinGasPrice().compareTo(ByteUtil.bytesToBigInteger(tx.getGasPrice())) > 0) { + return "Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(tx.getGasPrice()); + } + + return null; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 42d193ac78..f41f785af3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -21,7 +21,6 @@ import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutionSummary; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.listener.EthereumListener; import org.ethereum.listener.EthereumListenerAdapter; @@ -103,8 +102,6 @@ public void execute() { } private boolean isCasperVote() { - if (!(commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) - return false; return isCasperVote(tx, config.getCasperAddress()); } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java new file mode 100644 index 0000000000..0624efb634 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java @@ -0,0 +1,49 @@ +package org.ethereum.casper.manager; + +import org.ethereum.casper.core.CasperFacade; +import org.ethereum.casper.service.CasperValidatorService; +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Blockchain; +import org.ethereum.core.Genesis; +import org.ethereum.core.Repository; +import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.core.genesis.StateInit; +import org.ethereum.manager.WorldManager; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.PostConstruct; + +public class CasperWorldManager extends WorldManager { + + @Autowired + private CasperValidatorService casperValidatorService; + + @Autowired + private CasperFacade casper; + + private CasperStateInit stateInit; + + public CasperWorldManager(SystemProperties config, Repository repository, Blockchain blockchain) { + super(config, repository, blockchain); + } + + @PostConstruct + @Override + protected void init() { + super.init(); + casper.setEthereum(ethereum); + if (Boolean.TRUE.equals(config.getCasperValidatorEnabled())) { + casperValidatorService.start(); + } + } + + @Override + protected StateInit createStateInit(Genesis genesis) { + if (stateInit == null) { + this.stateInit = new CasperStateInit(genesis, (Repository) getRepository(), blockchain, config); + // FIXME: Looks like not a good side job + casper.setInitTxs(stateInit.makeInitTxes().getValue()); + } + return stateInit; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java new file mode 100644 index 0000000000..d2cc467390 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.mine; + +import org.ethereum.casper.core.CasperTransactionExecutor; +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Blockchain; +import org.ethereum.core.PendingState; +import org.ethereum.core.Transaction; +import org.ethereum.listener.CompositeEthereumListener; +import org.ethereum.mine.BlockMiner; + +public class CasperBlockMiner extends BlockMiner { + + public CasperBlockMiner(SystemProperties config, CompositeEthereumListener listener, + Blockchain blockchain, PendingState pendingState) { + super(config, listener, blockchain, pendingState); + } + + @Override + protected boolean isAcceptableTx(Transaction tx) { + if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { + return true; + } + return super.isAcceptableTx(tx); + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 57684a5f16..be794f2afd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -18,14 +18,13 @@ package org.ethereum.casper.service; import org.apache.commons.lang3.ArrayUtils; +import org.ethereum.casper.core.CasperFacade; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.facade.Ethereum; @@ -39,7 +38,6 @@ import org.spongycastle.util.BigIntegers; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import java.math.BigDecimal; @@ -61,13 +59,12 @@ import static org.ethereum.casper.service.CasperValidatorService.ValidatorState.WAITING_FOR_WITHDRAWN; @Component -@Lazy public class CasperValidatorService { private static final Logger logger = LoggerFactory.getLogger("casper.validator"); private SyncManager syncManager; - private CasperHybridConsensusStrategy strategy; + private CasperFacade casper; private Blockchain blockchain; @@ -89,6 +86,8 @@ public class CasperValidatorService { private BigInteger depositSize; + private boolean started = false; + private long latestTargetEpoch = -1; private long latestSourceEpoch = -1; @@ -167,7 +166,6 @@ public String toString() { @Autowired public CasperValidatorService(Ethereum ethereum, SystemProperties config) { this.ethereum = ethereum; - this.repository = (org.ethereum.core.Repository) ethereum.getRepository(); this.config = config; this.coinbase = ECKey.fromPrivate(config.getCasperValidatorPrivateKey()); this.depositSize = EtherUtil.convert(config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); @@ -180,13 +178,20 @@ public CasperValidatorService(Ethereum ethereum, SystemProperties config) { handlers.put(WAITING_FOR_WITHDRAWABLE, this::checkWithdrawable); handlers.put(WAITING_FOR_WITHDRAWN, this::checkWithdrawn); handlers.put(LOGGED_OUT, this::checkLoggedIn); - // FIXME: Actually we should listen only to HEAD changes - ethereum.addListener(new EthereumListenerAdapter() { - @Override - public void onBlock(BlockSummary blockSummary) { - newBlockConsumer().accept(blockSummary.getBlock()); - } - }); + + } + + public synchronized void start() { + if (!started) { + // FIXME: Actually we should listen only to HEAD changes + ethereum.addListener(new EthereumListenerAdapter() { + @Override + public void onBlock(BlockSummary blockSummary) { + newBlockConsumer().accept(blockSummary.getBlock()); + } + }); + this.started = true; + } } private Consumer newBlockConsumer() { @@ -293,7 +298,7 @@ private long getValidatorIndex() { private void initValContractAddress() { // Actually it's not used after deposit if (valContractAddress != null) return; - byte[] address = (byte[]) strategy.constCallCasper("get_validators__addr", getValidatorIndex())[0]; + byte[] address = (byte[]) casper.constCall("get_validators__addr", getValidatorIndex())[0]; if (!Arrays.equals(address, new byte[20])) { logger.info("Valcode contract found at {}", address); this.valContractAddress = address; @@ -333,10 +338,10 @@ private void broadcastDepositTx() { } private Transaction makeDepositTx(byte[] valContractAddress, byte[] coinbaseAddress, BigInteger deposit) { - byte[] functionCallBytes = strategy.getCasper().getByName("deposit").encode( + byte[] functionCallBytes = casper.getContract().getByName("deposit").encode( new ByteArrayWrapper(valContractAddress), new ByteArrayWrapper(coinbaseAddress)); - Transaction tx = makeTx(strategy.getCasperAddress(), deposit, functionCallBytes, null, + Transaction tx = makeTx(casper.getAddress(), deposit, functionCallBytes, null, ByteUtil.longToBytesNoLeadZeroes(1_000_000), null, true); return tx; @@ -344,8 +349,8 @@ private Transaction makeDepositTx(byte[] valContractAddress, byte[] coinbaseAddr } private Transaction makeVoteTx(byte[] voteData) { - byte[] functionCallBytes = strategy.getCasper().getByName("vote").encode(voteData); - Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, + byte[] functionCallBytes = casper.getContract().getByName("vote").encode(voteData); + Transaction tx = makeTx(casper.getAddress(), null, functionCallBytes, null, ByteUtil.longToBytesNoLeadZeroes(1_000_000), BigInteger.ZERO, false); return tx; @@ -353,16 +358,16 @@ private Transaction makeVoteTx(byte[] voteData) { } private Transaction makeLogoutTx(byte[] logoutData) { - byte[] functionCallBytes = strategy.getCasper().getByName("logout").encode(new ByteArrayWrapper(logoutData)); - Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, null, + byte[] functionCallBytes = casper.getContract().getByName("logout").encode(new ByteArrayWrapper(logoutData)); + Transaction tx = makeTx(casper.getAddress(), null, functionCallBytes, null, null, null, true); return tx; } private Transaction makeWithdrawTx(long validatorIndex) { - byte[] functionCallBytes = strategy.getCasper().getByName("withdraw").encode(validatorIndex); - Transaction tx = makeTx(strategy.getCasperAddress(), null, functionCallBytes, null, null, + byte[] functionCallBytes = casper.getContract().getByName("withdraw").encode(validatorIndex); + Transaction tx = makeTx(casper.getAddress(), null, functionCallBytes, null, null, null, true); return tx; } @@ -509,11 +514,11 @@ private void checkWithdrawn() { private void logCasperInfo() { long curEpoch = getCurrentEpoch(); long expectedSourceEpoch = constCallCasperForLong("get_expected_source_epoch"); - BigInteger curDeposits = (BigInteger) strategy.constCallCasper("get_total_curdyn_deposits")[0]; - BigInteger prevDeposits = (BigInteger) strategy.constCallCasper("get_total_prevdyn_deposits")[0]; - BigDecimal curVotes = (BigDecimal) strategy.constCallCasper("get_votes__cur_dyn_votes", curEpoch, expectedSourceEpoch)[0]; - BigDecimal prevVotes = (BigDecimal) strategy.constCallCasper("get_votes__prev_dyn_votes", curEpoch, expectedSourceEpoch)[0]; - BigDecimal scaleFactor = (BigDecimal) strategy.constCallCasper("get_deposit_scale_factor", curEpoch)[0]; + BigInteger curDeposits = (BigInteger) casper.constCall("get_total_curdyn_deposits")[0]; + BigInteger prevDeposits = (BigInteger) casper.constCall("get_total_prevdyn_deposits")[0]; + BigDecimal curVotes = (BigDecimal) casper.constCall("get_votes__cur_dyn_votes", curEpoch, expectedSourceEpoch)[0]; + BigDecimal prevVotes = (BigDecimal) casper.constCall("get_votes__prev_dyn_votes", curEpoch, expectedSourceEpoch)[0]; + BigDecimal scaleFactor = (BigDecimal) casper.constCall("get_deposit_scale_factor", curEpoch)[0]; BigDecimal curVotesScaled = curVotes.multiply(scaleFactor); BigDecimal prevVotesScaled = prevVotes.multiply(scaleFactor); BigDecimal curVotesPct = BigDecimal.ZERO; @@ -527,8 +532,8 @@ private void logCasperInfo() { long lastFinalizedEpoch = constCallCasperForLong("get_last_finalized_epoch"); long lastJustifiedEpoch = constCallCasperForLong("get_last_justified_epoch"); - BigDecimal lastNonvoterRescale = (BigDecimal) strategy.constCallCasper("get_last_nonvoter_rescale")[0]; - BigDecimal lastVoterRescale = (BigDecimal) strategy.constCallCasper("get_last_voter_rescale")[0]; + BigDecimal lastNonvoterRescale = (BigDecimal) casper.constCall("get_last_nonvoter_rescale")[0]; + BigDecimal lastVoterRescale = (BigDecimal) casper.constCall("get_last_voter_rescale")[0]; String logStr = String.format( "CASPER STATUS: epoch %d, %.3f / %.3f ETH (%.2f %%) voted from current dynasty, " + "%.3f / %.3f ETH (%.2f %%) voted from previous dynasty, last finalized epoch %d justified %d " + @@ -548,7 +553,7 @@ private void logCasperInfo() { logger.info(logStr); long valIndex = getValidatorIndex(); - BigDecimal myDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", valIndex)[0]; + BigDecimal myDeposit = (BigDecimal) casper.constCall("get_validators__deposit", valIndex)[0]; BigDecimal myDepositScaled = myDeposit.multiply(scaleFactor); String myStr = String.format( "MY VALIDATOR STATUS: epoch %d, index #%d, deposit: %.3f ETH", @@ -569,7 +574,7 @@ private byte[] getRecommendedVoteData(long validatorIndex) { // target_hash = self.epoch_blockhash(current_epoch) // ANSWER: Though, I'll try - byte[] targetHash = (byte[]) strategy.constCallCasper("get_recommended_target_hash")[0]; + byte[] targetHash = (byte[]) casper.constCall("get_recommended_target_hash")[0]; long sourceEpoch = constCallCasperForLong("get_recommended_source_epoch"); if (targetHash == null) { @@ -587,7 +592,7 @@ private byte[] getRecommendedVoteData(long validatorIndex) { } private long constCallCasperForLong(String func, Object... funcArgs) { - Object[] res = strategy.constCallCasper(func, funcArgs); + Object[] res = casper.constCall(func, funcArgs); return ((BigInteger) res[0]).longValue(); } @@ -597,12 +602,17 @@ public void setSyncManager(SyncManager syncManager) { } @Autowired - public void setStrategy(ConsensusStrategy strategy) { - this.strategy = (CasperHybridConsensusStrategy) strategy; + public void setBlockchain(Blockchain blockchain) { + this.blockchain = blockchain; + } + + @Autowired + public void setCasper(CasperFacade casper) { + this.casper = casper; } @Autowired - public void setBlockchain(Blockchain blockchain) { - this.blockchain = blockchain; + public void setRepository(Repository repository) { + this.repository = repository; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index 06a9237955..538b5f5152 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -18,14 +18,15 @@ package org.ethereum.config; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; -import org.ethereum.core.consensus.PoWConsensusStrategy; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.*; import org.ethereum.datasource.inmem.HashMapDB; import org.ethereum.datasource.leveldb.LevelDbDataSource; import org.ethereum.db.*; +import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; +import org.ethereum.manager.WorldManager; +import org.ethereum.mine.BlockMiner; import org.ethereum.sync.FastSyncManager; import org.ethereum.validator.BlockHashRule; import org.ethereum.validator.BlockHeaderRule; @@ -66,6 +67,9 @@ public class CommonConfig { @Autowired protected ApplicationContext ctx; + @Autowired + protected EthereumListener ethereumListener; + private static CommonConfig defaultInstance; public static CommonConfig getDefault() { @@ -75,11 +79,6 @@ public static CommonConfig getDefault() { public Source precompileSource() { return null; } - - @Override - public ConsensusStrategy consensusStrategy() { - return new PoWConsensusStrategy(systemProperties()); - } }; } return defaultInstance; @@ -293,11 +292,6 @@ public Blockchain blockchain() { return new BlockchainImpl(systemProperties()); } - @Bean - public ConsensusStrategy consensusStrategy() { - return new PoWConsensusStrategy(systemProperties(), ctx); - } - @Bean public TransactionExecutorFactory transactionExecutorFactory() { return new CommonTransactionExecutorFactory(); @@ -319,4 +313,19 @@ public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coin listener, gasUsedInTheBlock); } } + + @Bean + public WorldManager worldManager() { + return new WorldManager(systemProperties(), repository(), blockchain()); + } + + @Bean + public PendingState pendingState() { + return new PendingStateImpl(ethereumListener); + } + + @Bean + public BlockMiner blockMiner() { + return new BlockMiner(systemProperties(), (CompositeEthereumListener) ethereumListener, blockchain(), pendingState()); + } } 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 71a86349f0..c27e9a1ad4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -918,11 +918,6 @@ public Genesis getGenesis() { return genesis; } - @ValidateMe - public String getConsensusStrategy() { - return config.getString("consensus.strategy"); - } - public byte[] getCasperAddress() { return casperAddress; } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 676f9a0a30..9363df46b5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -32,9 +32,6 @@ import org.apache.commons.collections4.map.LRUMap; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.casper.core.CasperTransactionExecutor; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.TransactionStore; @@ -48,7 +45,6 @@ import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; /** * Keeps logic providing pending state management @@ -56,7 +52,6 @@ * @author Mikhail Kalinin * @since 28.09.2015 */ -@Component public class PendingStateImpl implements PendingState { public static class TransactionSortedSet extends TreeSet { @@ -75,12 +70,11 @@ public TransactionSortedSet() { private static final Logger logger = LoggerFactory.getLogger("pending"); @Autowired - private SystemProperties config = SystemProperties.getDefault(); + protected SystemProperties config = SystemProperties.getDefault(); @Autowired CommonConfig commonConfig = CommonConfig.getDefault(); - @Autowired private EthereumListener listener; @Autowired @@ -202,21 +196,8 @@ public synchronized List addPendingTransactions(List t return newPending; } - // TODO: Refactor me!!! Casper only - private boolean receiptIsValid(TransactionReceipt receipt) { - ConsensusStrategy strategy = commonConfig.consensusStrategy(); - if (strategy instanceof CasperHybridConsensusStrategy && - CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), config.getCasperAddress())) { - // Gas not used, it's ok if it was successful vote, so let's check it - if (!receipt.isValid()) { - logger.debug("Casper vote validity checking {}, success={} ", receipt, receipt.isSuccessful()); - return receipt.isSuccessful(); - } else { - return true; // Receipt is valid already - } - } else { - return receipt.isValid(); - } + protected boolean receiptIsValid(TransactionReceipt receipt) { + return receipt.isValid(); } public synchronized void trackTransaction(Transaction tx) { @@ -282,19 +263,13 @@ private TransactionReceipt createDroppedReceipt(Transaction tx, String error) { } // validations which are not performed within executeTx - private String validate(Transaction tx) { + protected String validate(Transaction tx) { try { tx.verify(); } catch (Exception e) { return String.format("Invalid transaction: %s", e.getMessage()); } - // FIXME: Shouldn't be there - if ((commonConfig.consensusStrategy() instanceof CasperHybridConsensusStrategy)) { - if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { - return null; // Doesn't require more checks - } - } if (config.getMineMinGasPrice().compareTo(ByteUtil.bytesToBigInteger(tx.getGasPrice())) > 0) { return "Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(tx.getGasPrice()); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java deleted file mode 100644 index 787b18f220..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/ConsensusStrategy.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.core.consensus; - -import org.ethereum.core.Genesis; -import org.ethereum.core.genesis.StateInit; - -public interface ConsensusStrategy { - void init(); - - /** - * Creates state initializer - */ - StateInit initState(Genesis genesis); - - /** - * @return state initializer after state is initialized - */ - StateInit getInitState(); -} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java b/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java deleted file mode 100644 index df9d993dd4..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/core/consensus/PoWConsensusStrategy.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.core.consensus; - -import org.ethereum.config.SystemProperties; -import org.ethereum.core.BlockchainImpl; -import org.ethereum.core.Genesis; -import org.ethereum.core.genesis.CommonStateInit; -import org.ethereum.core.genesis.StateInit; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; - -public class PoWConsensusStrategy implements ConsensusStrategy { - private SystemProperties systemProperties; - - @Autowired - private BlockchainImpl blockchain; - private StateInit stateInit; - - public PoWConsensusStrategy() { - } - - public PoWConsensusStrategy(SystemProperties systemProperties, ApplicationContext ctx) { - this(systemProperties); - } - - public PoWConsensusStrategy(SystemProperties systemProperties) { - this.systemProperties = systemProperties; - - // TODO: Add default blockchainImpl when it's not provided - } - - @Override - public void init() { - - } - - @Override - public StateInit initState(Genesis genesis) { - if (stateInit != null) { - throw new RuntimeException("State is already initialized"); - } else { - this.stateInit = new CommonStateInit(genesis, blockchain.getRepository(), blockchain); - } - return stateInit; - } - - @Override - public StateInit getInitState() { - if (stateInit == null) { - throw new RuntimeException("State is not initialized"); - } - return stateInit; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java index 4f88106719..b8f3ac7b42 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java @@ -31,7 +31,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; -import org.springframework.context.ApplicationContext; import java.math.BigInteger; import java.util.ArrayList; @@ -56,19 +55,16 @@ public class CasperStateInit implements StateInit { private SystemProperties systemProperties; - private ApplicationContext ctx; - private Genesis initGenesis; public final static ECKey NULL_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); public CasperStateInit(Genesis genesis, Repository repository, Blockchain blockchain, - ApplicationContext ctx, SystemProperties systemProperties) { + SystemProperties systemProperties) { this.genesis = genesis; this.repository = repository; this.blockchain = blockchain; this.systemProperties = systemProperties; - this.ctx = ctx; init(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java b/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java index 83f5d0206c..69015ba125 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/Ethereum.java @@ -18,7 +18,6 @@ package org.ethereum.facade; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.listener.EthereumListener; import org.ethereum.manager.AdminInfo; @@ -56,8 +55,6 @@ public interface Ethereum { Blockchain getBlockchain(); - ConsensusStrategy getConsensusStrategy(); - void addListener(EthereumListener listener); PeerClient getDefaultPeer(); diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index 82748dacdc..e40eb93517 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -23,7 +23,6 @@ import org.ethereum.core.*; import org.ethereum.core.PendingState; import org.ethereum.core.Repository; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.crypto.ECKey; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; @@ -147,11 +146,6 @@ public org.ethereum.facade.Blockchain getBlockchain() { return (org.ethereum.facade.Blockchain) worldManager.getBlockchain(); } - @Override - public ConsensusStrategy getConsensusStrategy() { - return commonConfig.consensusStrategy(); - } - public ImportResult addNewMinedBlock(Block block) { ImportResult importResult = worldManager.getBlockchain().tryToConnect(block); if (importResult == ImportResult.IMPORTED_BEST) { diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index f86c952f82..bdc0a6c473 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -19,15 +19,13 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; -import org.ethereum.core.consensus.ConsensusStrategy; +import org.ethereum.core.genesis.CommonStateInit; import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; import org.ethereum.db.DbFlushManager; import org.ethereum.facade.Ethereum; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListener; -import org.ethereum.mine.MinerListener; import org.ethereum.net.client.PeerClient; import org.ethereum.net.rlpx.discover.UDPListener; import org.ethereum.sync.FastSyncManager; @@ -57,7 +55,6 @@ * @author Roman Mandeleil * @since 01.06.2014 */ -@Component public class WorldManager { private static final Logger logger = LoggerFactory.getLogger("general"); @@ -96,47 +93,38 @@ public class WorldManager { private DbFlushManager dbFlushManager; @Autowired - private ApplicationContext ctx; + protected ApplicationContext ctx; - private ConsensusStrategy strategy; + protected Ethereum ethereum; - private Ethereum ethereum; - - private SystemProperties config; + protected SystemProperties config; + @Autowired private EthereumListener listener; - private Blockchain blockchain; + protected Blockchain blockchain; private Repository repository; + @Autowired private BlockStore blockStore; @Autowired public WorldManager(final SystemProperties config, final Repository repository, - final EthereumListener listener, final ConsensusStrategy consensusStrategy, - final Blockchain blockchain, final BlockStore blockStore) { - this.listener = listener; - this.strategy = consensusStrategy; + final Blockchain blockchain) { this.blockchain = blockchain; this.repository = repository; repository.setBlockchain(blockchain); - this.blockStore = blockStore; this.config = config; } @PostConstruct - private void init() { - ethereum = ctx.getBean(Ethereum.class); + protected void init() { + this.ethereum = ctx.getBean(Ethereum.class); ethereum.setWorldManager(this); - // FIXME: Bad Spring fix - if (strategy instanceof CasperHybridConsensusStrategy) { - ((CasperHybridConsensusStrategy) strategy).setEthereum(ethereum); - } - loadBlockchain(strategy); + loadBlockchain(); channelManager.init(ethereum); syncManager.init(channelManager, pool); - strategy.init(); } public void addListener(EthereumListener listener) { @@ -185,12 +173,16 @@ public PendingState getPendingState() { return pendingState; } - public void loadBlockchain(ConsensusStrategy strategy) { + protected StateInit createStateInit(Genesis genesis) { + return new CommonStateInit(genesis, repository, blockchain); + } + + public void loadBlockchain() { if (!config.databaseReset() || config.databaseResetBlock() != 0) blockStore.load(); - StateInit stateInit = strategy.initState(Genesis.getInstance(config)); + StateInit stateInit = createStateInit(Genesis.getInstance(config)); if (blockStore.getBestBlock() == null) { stateInit.initDB(); diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index de3de8c5aa..7e98004942 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -23,7 +23,6 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.casper.core.CasperTransactionExecutor; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; @@ -48,7 +47,6 @@ * * Created by Anton Nashatyrev on 10.12.2015. */ -@Component public class BlockMiner { private static final Logger logger = LoggerFactory.getLogger("mine"); @@ -65,7 +63,7 @@ public class BlockMiner { private CompositeEthereumListener listener; - private SystemProperties config; + protected SystemProperties config; private List listeners = new CopyOnWriteArrayList<>(); @@ -85,12 +83,11 @@ public class BlockMiner { @Autowired public BlockMiner(final SystemProperties config, final CompositeEthereumListener listener, - final Blockchain blockchain, final BlockStore blockStore, - final PendingState pendingState) { + final Blockchain blockchain, final PendingState pendingState) { this.listener = listener; this.config = config; this.blockchain = blockchain; - this.blockStore = blockStore; + this.blockStore = ((BlockchainImpl) blockchain).getBlockStore(); this.pendingState = pendingState; UNCLE_LIST_LIMIT = config.getBlockchainConfig().getCommonConstants().getUNCLE_LIST_LIMIT(); UNCLE_GENERATION_LIMIT = config.getBlockchainConfig().getCommonConstants().getUNCLE_GENERATION_LIMIT(); @@ -188,13 +185,6 @@ private void onPendingStateChanged() { } protected boolean isAcceptableTx(Transaction tx) { - // FIXME: Shouldn't be there - if ((ethereum.getConsensusStrategy() instanceof CasperHybridConsensusStrategy)) { - if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { - return true; - } - } - return minGasPrice.compareTo(new BigInteger(1, tx.getGasPrice())) <= 0; } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index b0e2aa0f47..ca1b76a081 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -22,7 +22,6 @@ import org.ethereum.config.SystemProperties; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.core.*; -import org.ethereum.core.consensus.ConsensusStrategy; import org.ethereum.core.genesis.GenesisLoader; import org.ethereum.crypto.ECKey; import org.ethereum.datasource.*; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 4957fb9453..c58a02a0c9 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -19,6 +19,8 @@ import org.ethereum.casper.config.CasperBeanConfig; import org.ethereum.casper.core.CasperBlockchain; +import org.ethereum.casper.core.CasperFacade; +import org.ethereum.casper.core.CasperPendingStateImpl; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; @@ -27,10 +29,9 @@ import org.ethereum.core.BlockSummary; import org.ethereum.core.BlockchainImpl; import org.ethereum.core.EventDispatchThread; -import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.Repository; import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; -import org.ethereum.casper.core.CasperHybridConsensusStrategy; import org.ethereum.datasource.CountingBytesSource; import org.ethereum.datasource.JournalSource; import org.ethereum.datasource.Source; @@ -73,15 +74,22 @@ public abstract class CasperBase { @Mock ApplicationContext context; + @Spy + final SystemProperties systemProperties = new SystemProperties(); + @InjectMocks private CommonConfig commonConfig = new CasperBeanConfig() { @Override public Source precompileSource() { return null; } + + @Override + public SystemProperties systemProperties() { + return systemProperties; + } }; - final SystemProperties systemProperties = commonConfig.systemProperties(); @Spy private TransactionExecutorFactory transactionExecutorFactory = commonConfig.transactionExecutorFactory(); @@ -95,10 +103,16 @@ public Source precompileSource() { @InjectMocks EthereumImpl ethereum = new EthereumImpl(systemProperties, defaultListener); - CasperHybridConsensusStrategy strategy; + @InjectMocks + CasperFacade casper = new CasperFacade(); + + @InjectMocks + CasperPendingStateImpl casperPendingState = new CasperPendingStateImpl(defaultListener); StandaloneBlockchain bc; + Repository repository; + @Before public void setup() throws Exception { // Just trust me! @@ -158,11 +172,10 @@ private BlockchainImpl createBlockchain() { blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.setPruneManager(pruneManager); - ((CasperBlockchain)blockchain).setStrategy(strategy); blockchain.byTest = true; - pendingState = new PendingStateImpl(listener); + pendingState = casperPendingState; pendingState.setCommonConfig(commonConfig); pendingState.setBlockchain(blockchain); @@ -172,11 +185,14 @@ private BlockchainImpl createBlockchain() { }.withNetConfig(systemProperties.getBlockchainConfig()); this.blockchain = (CasperBlockchain) bc.getBlockchain(); + casper.setEthereum(ethereum); + blockchain.setCasper(casper); Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); Mockito.when(worldManager.getBlockchain()).thenReturn(blockchain); Mockito.when(worldManager.getBlockStore()).thenReturn(blockchain.getBlockStore()); RepositoryWrapper wrapper = new RepositoryWrapper(); wrapper.setBlockchain(bc.getBlockchain()); + this.repository = wrapper; Mockito.when(worldManager.getRepository()).thenReturn(wrapper); doAnswer((Answer) invocation -> { Object arg0 = invocation.getArgument(0); @@ -187,10 +203,6 @@ private BlockchainImpl createBlockchain() { ethereum.setProgramInvokeFactory(new ProgramInvokeFactoryImpl()); ethereum.setPendingState(blockchain.getPendingState()); ethereum.setChannelManager(Mockito.mock(ChannelManager.class)); - this.strategy = (CasperHybridConsensusStrategy) commonConfig.consensusStrategy(); - strategy.setEthereum(ethereum); - strategy.setBlockchain(blockchain); - blockchain.setStrategy(strategy); // Push pending txs in StandaloneBlockchain ethereum.addListener(new EthereumListenerAdapter(){ diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index 9ab36d2ef7..4474d5e29e 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -112,17 +112,20 @@ public void epochStartTest() { genesis.getNonce() ); modifiedGenesis.setPremine(genesis.getPremine()); - CasperStateInit casperStateInit = (CasperStateInit) strategy.initState(modifiedGenesis); + + CasperStateInit casperStateInit = new CasperStateInit(modifiedGenesis, repository, blockchain, systemProperties); casperStateInit.initDB(); - BigInteger zeroEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + casper.setInitTxs(casperStateInit.makeInitTxes().getValue()); + + BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); for (int i = 0; i < 50; ++i) { Block block = bc.createBlock(); } - BigInteger firstEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + BigInteger firstEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(1, firstEpoch.longValue()); for (int i = 0; i < 50; ++i) { @@ -130,13 +133,13 @@ public void epochStartTest() { } // Epochs switches and they are finalized and justified because there no deposits yet [insta_finalize] - BigInteger secondEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + BigInteger secondEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(2, secondEpoch.longValue()); - BigInteger lastFinalized = (BigInteger) strategy.constCallCasper("get_last_finalized_epoch")[0]; + BigInteger lastFinalized = (BigInteger) casper.constCall("get_last_finalized_epoch")[0]; assertEquals(1, lastFinalized.longValue()); - BigInteger lastJustified = (BigInteger) strategy.constCallCasper("get_last_justified_epoch")[0]; + BigInteger lastJustified = (BigInteger) casper.constCall("get_last_justified_epoch")[0]; assertEquals(1, lastJustified.longValue()); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index 703a81a0d2..25c85d46e2 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -37,8 +37,10 @@ public class CasperStateInitTest extends CasperBase { public void genesisPlusBlock() { // Init with Genesis final Genesis genesis = Genesis.getInstance(systemProperties); - CasperStateInit casperStateInit = (CasperStateInit) strategy.initState(genesis); + + CasperStateInit casperStateInit = new CasperStateInit(genesis, repository, blockchain, systemProperties); casperStateInit.initDB(); + casper.setInitTxs(casperStateInit.makeInitTxes().getValue()); // Check after genesis assertEquals(new ByteArrayWrapper(Hex.decode("f3f713c5ff3119287ae62861e3fd90d6afc94b57d06151007c409b86bf419d11")), diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 46ea16a1b7..47be5caa68 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -131,10 +131,12 @@ public void validatorTest() { genesis.getPremine().put(new ByteArrayWrapper(coinbase.getAddress()), coinbaseAcc); modifiedGenesis.setPremine(genesis.getPremine()); - CasperStateInit casperStateInit = (CasperStateInit) strategy.initState(modifiedGenesis); + CasperStateInit casperStateInit = new CasperStateInit(modifiedGenesis, repository, blockchain, systemProperties); casperStateInit.initDB(); - BigInteger zeroEpoch = (BigInteger) strategy.constCallCasper("get_current_epoch")[0]; + casper.setInitTxs(casperStateInit.makeInitTxes().getValue()); + + BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); systemProperties.overrideParams( @@ -147,24 +149,25 @@ public void validatorTest() { bc.createBlock(); CasperValidatorService service = new CasperValidatorService(ethereum, systemProperties); - service.setStrategy(strategy); service.setBlockchain(blockchain); SyncManager syncManager = Mockito.mock(SyncManager.class); Mockito.when(syncManager.isSyncDone()).thenReturn(true); service.setSyncManager(syncManager); + service.setCasper(casper); + service.start(); for (int i = 0; i < 10; ++i) { Block block = bc.createBlock(); } // Deposit is scaled, so it's neither in wei nor in ETH. Should be 2000 ETH // TODO: Convert to ETH or wei - BigDecimal curDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", 1)[0]; + BigDecimal curDeposit = (BigDecimal) casper.constCall("get_validators__deposit", 1)[0]; assertTrue(curDeposit.compareTo(new BigDecimal("200000000000")) == 0); for (int i = 0; i < 300; ++i) { Block block = bc.createBlock(); } // We've earned some money on top of our deposit as premium for our votes, which finalized epochs!! - BigDecimal increasedDeposit = (BigDecimal) strategy.constCallCasper("get_validators__deposit", 1)[0]; + BigDecimal increasedDeposit = (BigDecimal) casper.constCall("get_validators__deposit", 1)[0]; assertTrue(increasedDeposit.compareTo(new BigDecimal("200000000000")) > 0); // We've left less than 500 ETH diff --git a/ethereumj-core/src/test/java/org/ethereum/mine/ExternalMinerTest.java b/ethereumj-core/src/test/java/org/ethereum/mine/ExternalMinerTest.java index bb4efc3923..160eca492c 100644 --- a/ethereumj-core/src/test/java/org/ethereum/mine/ExternalMinerTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/mine/ExternalMinerTest.java @@ -66,7 +66,7 @@ public class ExternalMinerTest { @InjectMocks @Resource private BlockMiner blockMiner = new BlockMiner(SystemProperties.getDefault(), listener, bc.getBlockchain(), - bc.getBlockchain().getBlockStore(), bc.getPendingState());; + bc.getPendingState());; @Before public void setup() { From 920747f44d3d99376ffb0663bca1d1954d351459 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 8 Mar 2018 21:55:18 +0300 Subject: [PATCH 30/67] More cleanup to enclose casper in separate package --- .../casper/config/CasperBeanConfig.java | 7 ++ .../casper/config/CasperProperties.java | 91 +++++++++++++++++++ .../config/net/CasperTestNetConfig.java | 11 +++ .../casper/core/CasperBlockchain.java | 17 ++-- .../ethereum/casper/core/CasperFacade.java | 9 +- .../casper/core/CasperPendingStateImpl.java | 5 +- .../core/CasperTransactionExecutor.java | 3 +- .../core/genesis/CasperStateInit.java | 26 +++--- .../casper/manager/CasperWorldManager.java | 5 +- .../casper/mine/CasperBlockMiner.java | 3 +- .../service/CasperValidatorService.java | 24 +++-- .../org/ethereum/config/CommonConfig.java | 2 +- .../org/ethereum/config/SystemProperties.java | 74 +-------------- .../org/ethereum/core/BlockchainImpl.java | 4 +- .../java/org/ethereum/core/Repository.java | 2 - .../java/org/ethereum/db/RepositoryImpl.java | 5 - .../java/org/ethereum/db/RepositoryRoot.java | 4 +- .../org/ethereum/db/RepositoryWrapper.java | 2 + .../org/ethereum/manager/WorldManager.java | 1 - .../net/swarm/bzz/BzzStatusMessage.java | 4 +- .../src/main/java/org/ethereum/util/RLP.java | 5 +- .../java/org/ethereum/vm/program/Storage.java | 6 -- ethereumj-core/src/main/resources/casper.conf | 45 +++------ .../org/ethereum/core/casper/CasperBase.java | 8 +- .../core/casper/CasperEpochSwitchTest.java | 2 +- .../core/casper/CasperStateInitTest.java | 2 +- .../core/casper/CasperValidatorTest.java | 8 +- .../suite/IterableTestRepository.java | 5 - 28 files changed, 199 insertions(+), 181 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java rename ethereumj-core/src/main/java/org/ethereum/{ => casper}/core/genesis/CasperStateInit.java (93%) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index d60f7bf23d..40e7d91b0e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -21,6 +21,7 @@ import org.ethereum.casper.manager.CasperWorldManager; import org.ethereum.casper.mine.CasperBlockMiner; import org.ethereum.config.CommonConfig; +import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.PendingState; @@ -92,4 +93,10 @@ public BlockMiner blockMiner() { return new CasperBlockMiner(systemProperties(), (CompositeEthereumListener) ethereumListener, blockchain(), pendingState()); } + + @Bean + @Override + public SystemProperties systemProperties() { + return CasperProperties.getDefault(); + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java new file mode 100644 index 0000000000..0101bd5bc8 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java @@ -0,0 +1,91 @@ +package org.ethereum.casper.config; + +import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.casper.config.net.CasperTestNetConfig; +import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.config.SystemProperties; +import org.ethereum.core.genesis.GenesisConfig; +import org.ethereum.util.ByteUtil; +import org.ethereum.validator.BlockCustomHashRule; +import org.ethereum.validator.BlockHeaderValidator; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.stream.Collectors; + +import static org.ethereum.casper.config.net.CasperTestNetConfig.EPOCH_LENGTH; + +public class CasperProperties extends SystemProperties { + + private static CasperProperties CONFIG; + + private byte[] casperAddress = null; + + public static SystemProperties getDefault() { + if (CONFIG == null) { + CONFIG = new CasperProperties(); + } + return CONFIG; + } + + public byte[] getCasperAddress() { + return casperAddress; + } + + public void setCasperAddress(byte[] casperAddress) { + this.casperAddress = casperAddress; + } + + public int getCasperEpochLength() { + return EPOCH_LENGTH; + } + + public byte[] getCasperValidatorPrivateKey() { + String key = config.getString("casper.validator.privateKey"); + if (key == null) return null; + return ByteUtil.hexStringToBytes(key); + } + + public long getCasperValidatorDeposit() { + return config.getLong("casper.validator.deposit"); + } + + public Boolean getCasperValidatorEnabled() { + return config.getBoolean("casper.validator.enabled"); + } + + public String getCasperAbi() { + final String abiLocation = config.getString("casper.contractAbi"); + return readFile(abiLocation); + } + + public String getCasperBin() { + final String binLocation = config.getString("casper.contractBin"); + return readFile(binLocation); + } + + private static String readFile(final String location) { + try { + InputStream is = SystemProperties.class.getResourceAsStream(location); + + if (is != null) { + return readStream(is); + } else { + logger.error("File not found `{}`", location); + throw new RuntimeException(String.format("File not found `%s`", location)); + } + } catch (Exception ex) { + String errorMsg = String.format("Error while reading file from %s", location); + logger.error(errorMsg, ex); + throw new RuntimeException(errorMsg, ex); + } + } + + private static String readStream(InputStream input) throws IOException { + try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { + return buffer.lines().collect(Collectors.joining("\n")); + } + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java index 178bb6d905..f9224dc4b0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java @@ -24,11 +24,22 @@ import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; +import org.ethereum.crypto.ECKey; import org.ethereum.vm.GasCost; +import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; public class CasperTestNetConfig extends BaseNetConfig { + + public static final int EPOCH_LENGTH = 50; + public static final int WITHDRAWAL_DELAY = 5; + public static final double BASE_INTEREST_FACTOR = 0.1; + public static final double BASE_PENALTY_FACTOR = 0.0001; + public static final int MIN_DEPOSIT_ETH = 1500; + + public final static ECKey NULL_SIGN_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + public static final CasperTestNetConfig INSTANCE = new CasperTestNetConfig(); static class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 175fff0939..cbe54a9c69 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -17,6 +17,7 @@ */ package org.ethereum.casper.core; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; @@ -45,12 +46,12 @@ import java.util.Map; import static java.math.BigInteger.ONE; +import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; import static org.ethereum.core.ImportResult.EXIST; import static org.ethereum.core.ImportResult.IMPORTED_BEST; import static org.ethereum.core.ImportResult.IMPORTED_NOT_BEST; import static org.ethereum.core.ImportResult.INVALID_BLOCK; import static org.ethereum.core.ImportResult.NO_PARENT; -import static org.ethereum.core.genesis.CasperStateInit.NULL_SENDER; import static org.ethereum.casper.service.CasperValidatorService.DEFAULT_GASLIMIT; public class CasperBlockchain extends BlockchainImpl { @@ -247,19 +248,19 @@ protected BlockSummary applyBlock(Repository track, Block block) { List txs = new ArrayList<>(block.getTransactionsList()); // Initialize the next epoch in the Casper contract - int epochLength = config.getCasperEpochLength(); + int epochLength = ((CasperProperties) config).getCasperEpochLength(); if(block.getNumber() % epochLength == 0 && block.getNumber() != 0) { long startingEpoch = block.getNumber() / epochLength; byte[] data = casper.getContract().getByName("initialize_epoch").encode(startingEpoch); Transaction tx = new Transaction( - ByteUtil.bigIntegerToBytes(track.getNonce(NULL_SENDER.getAddress())), + ByteUtil.bigIntegerToBytes(track.getNonce(NULL_SIGN_SENDER.getAddress())), new byte[0], ByteUtil.longToBytesNoLeadZeroes(DEFAULT_GASLIMIT), casper.getAddress(), new byte[0], data ); - tx.sign(NULL_SENDER); + tx.sign(NULL_SIGN_SENDER); txs.add(0, tx); } @@ -330,12 +331,12 @@ private void initCasper(Repository track, Block block) { return; List txs = casper.getInitTxs(); - byte[] casperAddress = config.getCasperAddress(); + byte[] casperAddress = ((CasperProperties) config).getCasperAddress(); byte[] coinbase = blockStore.getChainBlockByNumber(0).getCoinbase(); txs.forEach((tx) -> { // We need money! - track.addBalance(NULL_SENDER.getAddress(), BigInteger.valueOf(15).pow(18)); + track.addBalance(NULL_SIGN_SENDER.getAddress(), BigInteger.valueOf(15).pow(18)); Repository txTrack = track.startTracking(); TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); @@ -358,8 +359,8 @@ coinbase, txTrack, blockStore, getProgramInvokeFactory(), block, listener, 0) } txTrack.commit(); - BigInteger restBalance = track.getBalance(NULL_SENDER.getAddress()); - track.addBalance(NULL_SENDER.getAddress(), restBalance.negate()); + BigInteger restBalance = track.getBalance(NULL_SIGN_SENDER.getAddress()); + track.addBalance(NULL_SIGN_SENDER.getAddress(), restBalance.negate()); track.addBalance(casperAddress, track.getBalance(casperAddress).negate()); track.addBalance(casperAddress, BigInteger.valueOf(10).pow(25)); }); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 68d5be256e..850b9498fc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -17,6 +17,7 @@ */ package org.ethereum.casper.core; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CallTransaction; @@ -32,8 +33,7 @@ @Component public class CasperFacade { - @Autowired - private SystemProperties systemProperties; + private CasperProperties systemProperties; private Ethereum ethereum; @@ -88,4 +88,9 @@ public void setInitTxs(List initTxs) { public void setEthereum(Ethereum ethereum) { this.ethereum = ethereum; } + + @Autowired + public void setSystemProperties(SystemProperties systemProperties) { + this.systemProperties = (CasperProperties) systemProperties; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java index b0dad1beb5..74da6fd53e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java @@ -17,6 +17,7 @@ */ package org.ethereum.casper.core; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.core.PendingStateImpl; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionReceipt; @@ -34,7 +35,7 @@ protected boolean receiptIsValid(TransactionReceipt receipt) { boolean isValid = super.receiptIsValid(receipt); if (isValid) { return true; - } else if (CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), config.getCasperAddress())) { + } else if (CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), ((CasperProperties) config).getCasperAddress())) { return receipt.isSuccessful(); } @@ -49,7 +50,7 @@ protected String validate(Transaction tx) { return String.format("Invalid transaction: %s", e.getMessage()); } - if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { + if (CasperTransactionExecutor.isCasperVote(tx, ((CasperProperties) config).getCasperAddress())) { return null; // Doesn't require more checks } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index f41f785af3..46eb9d8cb8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -16,6 +16,7 @@ * along with the ethereumJ library. If not, see . */ package org.ethereum.casper.core; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.core.Block; import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Repository; @@ -102,7 +103,7 @@ public void execute() { } private boolean isCasperVote() { - return isCasperVote(tx, config.getCasperAddress()); + return isCasperVote(tx, ((CasperProperties) config).getCasperAddress()); } public static boolean isCasperVote(Transaction transaction, byte[] casperAddress) { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java similarity index 93% rename from ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java rename to ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java index b8f3ac7b42..14699039fb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CasperStateInit.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java @@ -15,16 +15,18 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.core.genesis; +package org.ethereum.casper.core.genesis; import javafx.util.Pair; import org.apache.commons.lang3.ArrayUtils; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; import org.ethereum.core.CallTransaction; import org.ethereum.core.Genesis; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; +import org.ethereum.core.genesis.StateInit; import org.ethereum.crypto.ECKey; import org.ethereum.db.BlockStore; import org.ethereum.util.ByteUtil; @@ -36,35 +38,33 @@ import java.util.ArrayList; import java.util.List; +import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_INTEREST_FACTOR; +import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_PENALTY_FACTOR; +import static org.ethereum.casper.config.net.CasperTestNetConfig.MIN_DEPOSIT_ETH; +import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; +import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; import static org.ethereum.crypto.HashUtil.sha3; public class CasperStateInit implements StateInit { private static final Logger logger = LoggerFactory.getLogger("general"); - public static final int WITHDRAWAL_DELAY = 5; - public static final double BASE_INTEREST_FACTOR = 0.1; - public static final double BASE_PENALTY_FACTOR = 0.0001; - public static final int MIN_DEPOSIT_ETH = 1500; - private Genesis genesis; private Repository repository; private Blockchain blockchain; - private SystemProperties systemProperties; + private CasperProperties systemProperties; private Genesis initGenesis; - public final static ECKey NULL_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); - public CasperStateInit(Genesis genesis, Repository repository, Blockchain blockchain, SystemProperties systemProperties) { this.genesis = genesis; this.repository = repository; this.blockchain = blockchain; - this.systemProperties = systemProperties; + this.systemProperties = (CasperProperties) systemProperties; init(); } @@ -108,7 +108,7 @@ public Pair> makeInitTxes() { txStrs.add(VIPER_RLP_DECODER_TX); txStrs.add(SIG_HASHER_TX); txStrs.add(PURITY_CHECKER_TX); - BigInteger nonce = repository.getNonce(NULL_SENDER.getAddress()); + BigInteger nonce = repository.getNonce(NULL_SIGN_SENDER.getAddress()); List txs = new ArrayList<>(); final long gasPriceFund = 25_000_000_000L; for (int i = 0; i < txStrs.size(); ++i) { @@ -128,7 +128,7 @@ public Pair> makeInitTxes() { new byte[0], null ); - fundTx.sign(NULL_SENDER); + fundTx.sign(NULL_SIGN_SENDER); txs.add(fundTx); txs.add(deployTx); nonce = nonce.add(BigInteger.ONE); @@ -166,7 +166,7 @@ public Pair> makeInitTxes() { ByteUtil.longToBytesNoLeadZeroes(0), ArrayUtils.addAll(casperBin, casperInit), // Merge contract and constructor args null); - tx.sign(NULL_SENDER); + tx.sign(NULL_SIGN_SENDER); // set casperAddress System.arraycopy(tx.getContractAddress(), 0, casperAddress, 0, 20); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java index 0624efb634..8cb7e12372 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java @@ -1,12 +1,13 @@ package org.ethereum.casper.manager; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperFacade; import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; import org.ethereum.core.Genesis; import org.ethereum.core.Repository; -import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.casper.core.genesis.CasperStateInit; import org.ethereum.core.genesis.StateInit; import org.ethereum.manager.WorldManager; import org.springframework.beans.factory.annotation.Autowired; @@ -32,7 +33,7 @@ public CasperWorldManager(SystemProperties config, Repository repository, Blockc protected void init() { super.init(); casper.setEthereum(ethereum); - if (Boolean.TRUE.equals(config.getCasperValidatorEnabled())) { + if (Boolean.TRUE.equals(((CasperProperties) config).getCasperValidatorEnabled())) { casperValidatorService.start(); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java index d2cc467390..cb60818811 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java @@ -17,6 +17,7 @@ */ package org.ethereum.casper.mine; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperTransactionExecutor; import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; @@ -34,7 +35,7 @@ public CasperBlockMiner(SystemProperties config, CompositeEthereumListener liste @Override protected boolean isAcceptableTx(Transaction tx) { - if (CasperTransactionExecutor.isCasperVote(tx, config.getCasperAddress())) { + if (CasperTransactionExecutor.isCasperVote(tx, ((CasperProperties) config).getCasperAddress())) { return true; } return super.isAcceptableTx(tx); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index be794f2afd..f90b4f2894 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -18,6 +18,7 @@ package org.ethereum.casper.service; import org.apache.commons.lang3.ArrayUtils; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperFacade; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; @@ -70,7 +71,7 @@ public class CasperValidatorService { private Repository repository; - private SystemProperties config; + private CasperProperties config; private Ethereum ethereum; @@ -115,15 +116,15 @@ private byte[] validationContractCode(byte[] address) { } private byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { - byte[] sigHash = sha3(RLP.encodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch)); + byte[] sigHash = sha3(RLP.smartEncodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch)); byte[] vrs = make3IntSignature(sigHash, sender); - return RLP.encodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch, new ByteArrayWrapper(vrs)); + return RLP.smartEncodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch, new ByteArrayWrapper(vrs)); } private byte[] makeLogout(long validatorIndex, long epoch, ECKey sender) { - byte[] sigHash = sha3(RLP.encodeList(validatorIndex, epoch)); + byte[] sigHash = sha3(RLP.smartEncodeList(validatorIndex, epoch)); byte[] vrs = make3IntSignature(sigHash, sender); - return RLP.encodeList(validatorIndex, epoch, new ByteArrayWrapper(vrs)); + return RLP.smartEncodeList(validatorIndex, epoch, new ByteArrayWrapper(vrs)); } private byte[] make3IntSignature(byte[] data, ECKey signer) { @@ -166,9 +167,9 @@ public String toString() { @Autowired public CasperValidatorService(Ethereum ethereum, SystemProperties config) { this.ethereum = ethereum; - this.config = config; - this.coinbase = ECKey.fromPrivate(config.getCasperValidatorPrivateKey()); - this.depositSize = EtherUtil.convert(config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); + this.config = (CasperProperties) config; + this.coinbase = ECKey.fromPrivate(this.config.getCasperValidatorPrivateKey()); + this.depositSize = EtherUtil.convert(this.config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); handlers.put(UNINITIATED, this::checkLoggedIn); handlers.put(WAITING_FOR_VALCODE, this::checkValcode); @@ -235,11 +236,8 @@ private void checkLoggedIn() { // The validator isn't logged in, so return! return; } - if (config.getCasperValidatorShouldLogout()) { - setState(WAITING_FOR_LOGOUT); - } else{ - setState(VOTING); - } + + setState(VOTING); } private void broadcastValcodeTx() { diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index 538b5f5152..c70b4be9a4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -86,7 +86,7 @@ public Source precompileSource() { @Bean public SystemProperties systemProperties() { - return SystemProperties.getSpringDefault(); + return SystemProperties.getDefault(); } @Bean 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 c27e9a1ad4..40d3a76681 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -52,7 +52,6 @@ import java.net.Socket; import java.net.URL; import java.util.*; -import java.util.stream.Collectors; import static org.ethereum.crypto.HashUtil.sha3; @@ -72,7 +71,7 @@ * @since 22.05.2014 */ public class SystemProperties { - private static Logger logger = LoggerFactory.getLogger("general"); + protected static Logger logger = LoggerFactory.getLogger("general"); public final static String PROPERTY_DB_DIR = "database.dir"; public final static String PROPERTY_LISTEN_PORT = "peer.listen.port"; @@ -134,7 +133,7 @@ static boolean isUseOnlySpringConfig() { private @interface ValidateMe {}; - private Config config; + protected Config config; // mutable options for tests private String databaseDir = null; @@ -152,11 +151,10 @@ static boolean isUseOnlySpringConfig() { private Boolean discoveryEnabled = null; private GenesisJson genesisJson; - private BlockchainNetConfig blockchainConfig; + protected BlockchainNetConfig blockchainConfig; private Genesis genesis; private Boolean vmTrace; private Boolean recordInternalTransactionsData; - private byte[] casperAddress = null; private final ClassLoader classLoader; @@ -918,72 +916,6 @@ public Genesis getGenesis() { return genesis; } - public byte[] getCasperAddress() { - return casperAddress; - } - - public void setCasperAddress(byte[] casperAddress) { - this.casperAddress = casperAddress; - } - - public int getCasperEpochLength() { - return config.getInt("consensus.casper.epochLength"); - } - - public byte[] getCasperValidatorPrivateKey() { - String key = config.getString("consensus.casper.validator.privateKey"); - if (key == null) return null; - return ByteUtil.hexStringToBytes(key); - } - - public long getCasperValidatorDeposit() { - return config.getLong("consensus.casper.validator.deposit"); - } - - public Boolean getCasperValidatorEnabled() { - return config.getBoolean("consensus.casper.validator.enabled"); - } - - // TODO: Implement me - // How to trigger this when I need it w/o restart? - public boolean getCasperValidatorShouldLogout() { - return false; - } - - - public String getCasperAbi() { - final String abiLocation = config.getString("consensus.casper.contractAbi"); - return readFile(abiLocation); - } - - public String getCasperBin() { - final String binLocation = config.getString("consensus.casper.contractBin"); - return readFile(binLocation); - } - - private static String readFile(final String location) { - try { - InputStream is = SystemProperties.class.getResourceAsStream(location); - - if (is != null) { - return readStream(is); - } else { - logger.error("File not found `{}`", location); - throw new RuntimeException(String.format("File not found `%s`", location)); - } - } catch (Exception ex) { - String errorMsg = String.format("Error while reading file from %s", location); - logger.error(errorMsg, ex); - throw new RuntimeException(errorMsg, ex); - } - } - - private static String readStream(InputStream input) throws IOException { - try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) { - return buffer.lines().collect(Collectors.joining("\n")); - } - } - /** * Method used in StandaloneBlockchain. */ diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index ac6fed6af9..0c0febc5eb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -102,6 +102,7 @@ public class BlockchainImpl implements Blockchain, org.ethereum.facade.Blockchai private static final int MAGIC_REWARD_OFFSET = 8; public static final byte[] EMPTY_LIST_HASH = sha3(RLP.encodeList(new byte[0])); + @Autowired @Qualifier("defaultRepository") private Repository repository; @Autowired @@ -1107,11 +1108,8 @@ public void updateBlockTotDifficulties(int startFrom) { } } - // FIXME: Magic - @Autowired @Qualifier("defaultRepository") public void setRepository(Repository repository) { this.repository = repository; - repository.setBlockchain(this); } public void setProgramInvokeFactory(ProgramInvokeFactory factory) { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Repository.java b/ethereumj-core/src/main/java/org/ethereum/core/Repository.java index e434e57f64..6ec1c16fa3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Repository.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Repository.java @@ -235,6 +235,4 @@ void loadAccount(byte[] addr, HashMap cacheAccou HashMap cacheDetails); Repository getSnapshotTo(byte[] root); - - void setBlockchain(Blockchain blockchain); } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java index 645e0a7697..20e0f6d03a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java @@ -20,7 +20,6 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.AccountState; import org.ethereum.core.Block; -import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.crypto.HashUtil; import org.ethereum.datasource.*; @@ -427,8 +426,4 @@ public void loadAccount(byte[] addr, HashMap cac throw new RuntimeException("Not supported"); } - @Override - public void setBlockchain(Blockchain blockchain) { - // Not used in current implementation - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java index 8eb09d07fe..1faf2d482e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java @@ -129,7 +129,9 @@ public synchronized void flush() { @Override public Repository getSnapshotTo(byte[] root) { - return new RepositoryRoot(stateDS, root); + RepositoryRoot repo = new RepositoryRoot(stateDS, root); + repo.config = this.config; + return repo; } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java index 91d40e8016..2eb21853e9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryWrapper.java @@ -23,6 +23,7 @@ import org.ethereum.core.BlockchainImpl; import org.ethereum.core.Repository; import org.ethereum.vm.DataWord; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.Nullable; @@ -215,6 +216,7 @@ public Map getStorage(byte[] addr, @Nullable Collection data) { } /** - * Expects byte[] objects are already RLP-encoded while everything else is not + * NOTE: Expects byte[] objects are already RLP-encoded while everything else is not + * * @param elements Any elements, supports Byte, Short, Integer, Long, * BigInteger, String, byte[], ByteArrayWrapper * @return RLP list byte encoded */ - public static byte[] encodeList(Object... elements) { + public static byte[] smartEncodeList(Object... elements) { if (elements == null) { return new byte[]{(byte) OFFSET_SHORT_LIST}; diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java b/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java index a2fe17be23..bc007cca55 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/program/Storage.java @@ -19,7 +19,6 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; -import org.ethereum.core.Blockchain; import org.ethereum.core.Repository; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.ContractDetails; @@ -239,9 +238,4 @@ public Set getStorageKeys(byte[] addr) { public Map getStorage(byte[] addr, @Nullable Collection keys) { return repository.getStorage(addr, keys); } - - @Override - public void setBlockchain(Blockchain blockchain) { - // Not used in current implementation - } } diff --git a/ethereumj-core/src/main/resources/casper.conf b/ethereumj-core/src/main/resources/casper.conf index feba7924f7..429b652067 100644 --- a/ethereumj-core/src/main/resources/casper.conf +++ b/ethereumj-core/src/main/resources/casper.conf @@ -57,38 +57,23 @@ database { blockchain.config.name = "casper" -consensus { - # Strategy for consensus - # Currently supported: - # "pow" - Proof of Work - # "casper-hybrid" - hybrid PoW + Casper PoS - strategy="casper-hybrid" +# Casper specific settings, used only with Casper strategy +casper { + # Casper contract BIN (required) + contractBin = "/casper/casper.bin" - # Casper specific settings, used only with Casper strategy - casper { - # Casper contract BIN (required) - contractBin = "/casper/casper.bin" + # Casper contract ABI (required) + contractAbi = "/casper/casper.abi" - # Casper contract ABI (required) - contractAbi = "/casper/casper.abi" - - # Casper epoch length (required) - epochLength = 50 - # Currently hardcoded and encoded in casper.bin - # withdrawalDelay = - # baseInterestFactor = - # basePenaltyFactor - - # Casper validator settings (required) - validator { - # Is Casper validator on (required) - enabled = true - # Validator coinbase (withdraw/deposit address) private key (optional) - # TODO: It should be something more secure - privateKey = "396ecd4115d4e20d4846060013823e1687b95960398f6f148f0fd64e70af13ac" - # Deposit in ethereum, 1500 is minimum (optional) - deposit = 2000 - } + # Casper validator settings (required) + validator { + # Is Casper validator on (required) + enabled = false + # Validator coinbase (withdraw/deposit address) private key (optional) + # TODO: It should be something more secure + privateKey = "396ecd4115d4e20d4846060013823e1687b95960398f6f148f0fd64e70af13ac" + # Deposit in ethereum, 1500 is minimum (optional) + deposit = 2000 } } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index c58a02a0c9..9e2da44477 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -18,6 +18,7 @@ package org.ethereum.core.casper; import org.ethereum.casper.config.CasperBeanConfig; +import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperBlockchain; import org.ethereum.casper.core.CasperFacade; import org.ethereum.casper.core.CasperPendingStateImpl; @@ -75,7 +76,7 @@ public abstract class CasperBase { ApplicationContext context; @Spy - final SystemProperties systemProperties = new SystemProperties(); + final CasperProperties systemProperties = new CasperProperties(); @InjectMocks private CommonConfig commonConfig = new CasperBeanConfig() { @@ -122,9 +123,8 @@ public void setup() throws Exception { Resource casperGenesis = new ClassPathResource("/genesis/casper.json"); systemProperties.useGenesis(casperGenesis.getInputStream()); systemProperties.overrideParams( - "consensus.casper.epochLength", "50", - "consensus.casper.contractBin", "/casper/casper.bin", - "consensus.casper.contractAbi", "/casper/casper.abi" + "casper.contractBin", "/casper/casper.bin", + "casper.contractAbi", "/casper/casper.abi" ); MockitoAnnotations.initMocks(this); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index 4474d5e29e..e1a91df395 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -27,7 +27,7 @@ import org.ethereum.config.net.BaseNetConfig; import org.ethereum.core.Block; import org.ethereum.core.Genesis; -import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.casper.core.genesis.CasperStateInit; import org.ethereum.util.ByteUtil; import org.ethereum.vm.GasCost; import org.junit.Test; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index 25c85d46e2..addc094841 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -19,7 +19,7 @@ import org.ethereum.core.Block; import org.ethereum.core.Genesis; -import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.casper.core.genesis.CasperStateInit; import org.ethereum.db.ByteArrayWrapper; import org.junit.Ignore; import org.junit.Test; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 47be5caa68..eafc5a5ece 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -28,7 +28,7 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; import org.ethereum.core.Genesis; -import org.ethereum.core.genesis.CasperStateInit; +import org.ethereum.casper.core.genesis.CasperStateInit; import org.ethereum.crypto.ECKey; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.casper.service.CasperValidatorService; @@ -140,9 +140,9 @@ public void validatorTest() { assertEquals(0, zeroEpoch.longValue()); systemProperties.overrideParams( - "consensus.casper.validator.enabled", "true", - "consensus.casper.validator.privateKey", Hex.toHexString(coinbase.getPrivKeyBytes()), - "consensus.casper.validator.deposit", "2000" + "casper.validator.enabled", "true", + "casper.validator.privateKey", Hex.toHexString(coinbase.getPrivKeyBytes()), + "casper.validator.deposit", "2000" ); diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java index b81596b112..c5c8fe7d5a 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/IterableTestRepository.java @@ -410,9 +410,4 @@ public ContractDetails getSnapshotTo(byte[] hash) { return new IterableContractDetails(src.getSnapshotTo(hash)); } } - - @Override - public void setBlockchain(Blockchain blockchain) { - // Not used - } } From 0fb3a638123ac6c5e464b44042c1abfee1a84655 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 8 Mar 2018 22:07:26 +0300 Subject: [PATCH 31/67] Temp patch for p2pv4 framing compatibility with p2pv5 snappy --- .../src/main/java/org/ethereum/net/server/Channel.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java b/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java index 89d444bc24..969c2cf52a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java @@ -161,14 +161,16 @@ public void publicRLPxHandshakeFinished(ChannelHandlerContext ctx, FrameCodec fr logger.debug("publicRLPxHandshakeFinished with " + ctx.channel().remoteAddress()); - messageCodec.setSupportChunkedFrames(true); - FrameCodecHandler frameCodecHandler = new FrameCodecHandler(frameCodec, this); ctx.pipeline().addLast("medianFrameCodec", frameCodecHandler); if (SnappyCodec.isSupported(Math.min(config.defaultP2PVersion(), helloRemote.getP2PVersion()))) { ctx.pipeline().addLast("snappyCodec", new SnappyCodec(this)); logger.debug("{}: use snappy compression", ctx.channel()); + } else { + // FIXME: Actually frames are not used by every P2Pv4 client + // only Pyethereum is known + messageCodec.setSupportChunkedFrames(true); } ctx.pipeline().addLast("messageCodec", messageCodec); From dbc1dcf33c71050e03e02d7a73577141fe9f1457 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 9 Mar 2018 19:01:45 +0300 Subject: [PATCH 32/67] Validator start logging added --- .../org/ethereum/casper/service/CasperValidatorService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index f90b4f2894..44d836477d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -184,6 +184,7 @@ public CasperValidatorService(Ethereum ethereum, SystemProperties config) { public synchronized void start() { if (!started) { + logger.info("Starting casper validator with coinbase 0x{}", Hex.toHexString(coinbase.getAddress())); // FIXME: Actually we should listen only to HEAD changes ethereum.addListener(new EthereumListenerAdapter() { @Override @@ -192,6 +193,8 @@ public void onBlock(BlockSummary blockSummary) { } }); this.started = true; + } else { + logger.warn("Attempting to start casper validator but it's already started"); } } @@ -205,6 +208,7 @@ private Consumer newBlockConsumer() { } public void reLogin() { + logger.info("Attempting to relogin casper validator with coinbase 0x{}", Hex.toHexString(coinbase.getAddress())); if (!state.equals(LOGGED_OUT)) { throw new RuntimeException(String.format("Validator is not logged, out, cannot relogin. " + "Current state: %s", state)); From 97dba273c05e4957348a5920a9c32ea206fda3dc Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Fri, 9 Mar 2018 21:17:55 +0300 Subject: [PATCH 33/67] Fixed: casper votes should come after regular txs in mined block + validator of txs in block added --- .../casper/core/CasperBlockchain.java | 11 +++++++ .../casper/mine/CasperBlockMiner.java | 29 +++++++++++++++++++ .../java/org/ethereum/mine/BlockMiner.java | 4 +-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index cbe54a9c69..e53a99406d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -402,6 +402,7 @@ protected boolean isValid(Repository repo, Block block) { Map curNonce = new HashMap<>(); + boolean votesStarted = false; for (Transaction tx : txs) { byte[] txSender = tx.getSender(); ByteArrayWrapper key = new ByteArrayWrapper(txSender); @@ -421,6 +422,16 @@ protected boolean isValid(Repository repo, Block block) { txNonce, expectedNonce, repo.getNonce(txSender), tx); return false; } + + // Casper votes txs should come after regular txs + if (votesStarted && !CasperTransactionExecutor.isCasperVote(tx, casper.getAddress())) { + logger.warn("Invalid transaction: all transactions should be before casper votes: {}", tx); + return false; + } + + if (!votesStarted && CasperTransactionExecutor.isCasperVote(tx, casper.getAddress())) { + votesStarted = true; + } } } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java index cb60818811..5d4b4f9dde 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java @@ -18,15 +18,23 @@ package org.ethereum.casper.mine; import org.ethereum.casper.config.CasperProperties; +import org.ethereum.casper.core.CasperFacade; import org.ethereum.casper.core.CasperTransactionExecutor; import org.ethereum.config.SystemProperties; +import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.PendingState; +import org.ethereum.core.PendingStateImpl; import org.ethereum.core.Transaction; import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.mine.BlockMiner; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; public class CasperBlockMiner extends BlockMiner { + @Autowired + CasperFacade casper; public CasperBlockMiner(SystemProperties config, CompositeEthereumListener listener, Blockchain blockchain, PendingState pendingState) { @@ -40,4 +48,25 @@ protected boolean isAcceptableTx(Transaction tx) { } return super.isAcceptableTx(tx); } + + @Override + protected Block getNewBlockForMining() { + Block bestBlockchain = blockchain.getBestBlock(); + Block bestPendingState = ((PendingStateImpl) pendingState).getBestBlock(); + + logger.debug("getNewBlockForMining best blocks: PendingState: " + bestPendingState.getShortDescr() + + ", Blockchain: " + bestBlockchain.getShortDescr()); + + // Casper txs should come after regular + List pendingTxs = getAllPendingTransactions(); + pendingTxs.sort((tx1, tx2) -> { + boolean tx1isVote = CasperTransactionExecutor.isCasperVote(tx1, casper.getAddress()); + boolean tx2isVote = CasperTransactionExecutor.isCasperVote(tx2, casper.getAddress()); + return Boolean.compare(tx1isVote, tx2isVote); + }); + + Block newMiningBlock = blockchain.createNewBlock(bestPendingState, pendingTxs, + getUncles(bestPendingState)); + return newMiningBlock; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index 7e98004942..2c1061d036 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -48,11 +48,11 @@ * Created by Anton Nashatyrev on 10.12.2015. */ public class BlockMiner { - private static final Logger logger = LoggerFactory.getLogger("mine"); + protected static final Logger logger = LoggerFactory.getLogger("mine"); private static ExecutorService executor = Executors.newSingleThreadExecutor(); - private Blockchain blockchain; + protected Blockchain blockchain; private BlockStore blockStore; From b83b9cb0f7cf512ff09572044212caae12d08696 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Sat, 10 Mar 2018 22:15:45 +0300 Subject: [PATCH 34/67] Fixing ethereumj w. ethereumj p2p --- .../src/main/java/org/ethereum/net/server/Channel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java b/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java index 969c2cf52a..bdd305900f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/server/Channel.java @@ -166,6 +166,7 @@ public void publicRLPxHandshakeFinished(ChannelHandlerContext ctx, FrameCodec fr if (SnappyCodec.isSupported(Math.min(config.defaultP2PVersion(), helloRemote.getP2PVersion()))) { ctx.pipeline().addLast("snappyCodec", new SnappyCodec(this)); + messageCodec.setSupportChunkedFrames(false); logger.debug("{}: use snappy compression", ctx.channel()); } else { // FIXME: Actually frames are not used by every P2Pv4 client From 281c60c5c9ae7a4e7865d4e70cd903d3d5af49d6 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Sun, 11 Mar 2018 23:29:03 +0300 Subject: [PATCH 35/67] Moved dummy contracts to Casper genesis --- .../casper/core/genesis/CasperStateInit.java | 13 ++----------- .../org/ethereum/core/genesis/CommonStateInit.java | 1 + .../java/org/ethereum/net/eth/handler/Eth62.java | 6 +++--- .../src/main/resources/genesis/casper.json | 6 ++++++ 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java index 14699039fb..91573ddbbc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java @@ -73,19 +73,10 @@ public void initDB() { if (blockchain.getBlockByNumber(0) != null) { return; // Already initialized } - logger.info("DB is empty - initializing Casper Genesis"); + logger.info("DB is empty - adding Genesis"); Genesis.populateRepository(repository, genesis); - - BlockStore blockStore = ((org.ethereum.facade.Blockchain)blockchain).getBlockStore(); - - - // Metropolis dummy - repository.saveCode(Hex.decode("0000000000000000000000000000000000000010"), Hex.decode("6000355460205260206020f3")); - repository.saveCode(Hex.decode("0000000000000000000000000000000000000020"), Hex.decode("6000355460205260206020f3")); repository.commit(); - genesis.setStateRoot(repository.getRoot()); - - blockStore.saveBlock(genesis, genesis.getCumulativeDifficulty(), true); + ((org.ethereum.facade.Blockchain)blockchain).getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true); blockchain.setBestBlock(genesis); blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java index d39168b8ad..3260c637fb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java @@ -48,6 +48,7 @@ public void initDB() { ((org.ethereum.facade.Blockchain)blockchain).getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true); blockchain.setBestBlock(genesis); blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); + logger.info("Genesis block loaded"); } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java index 59b67003d8..2733bb121e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java @@ -194,8 +194,8 @@ public synchronized void sendStatus() { totalDifficulty = blockchain.getTotalDifficulty(); } - StatusMessage msg = new StatusMessage(protocolVersion, networkId, // Casper genesis from config is not final - ByteUtil.bigIntegerToBytes(totalDifficulty), bestHash, blockstore.getBlockHashByNumber(0)); + StatusMessage msg = new StatusMessage(protocolVersion, networkId, + ByteUtil.bigIntegerToBytes(totalDifficulty), bestHash, config.getGenesis().getHash()); sendMessage(msg); ethState = EthState.STATUS_SENT; @@ -320,7 +320,7 @@ protected synchronized void processStatus(StatusMessage msg, ChannelHandlerConte try { - if (!Arrays.equals(msg.getGenesisHash(), blockstore.getBlockHashByNumber(0))) { // Casper genesis from config is not final + if (!Arrays.equals(msg.getGenesisHash(), config.getGenesis().getHash())) { if (!peerDiscoveryMode) { loggerNet.debug("Removing EthHandler for {} due to protocol incompatibility", ctx.channel().remoteAddress()); } diff --git a/ethereumj-core/src/main/resources/genesis/casper.json b/ethereumj-core/src/main/resources/genesis/casper.json index f71df403d2..2b0cab4dbe 100644 --- a/ethereumj-core/src/main/resources/genesis/casper.json +++ b/ethereumj-core/src/main/resources/genesis/casper.json @@ -16,6 +16,12 @@ }, "b96611e02f9eff3c8afc6226d4ebfa81a821547c": { "balance": "5125001002003004005006" + }, + "0000000000000000000000000000000000000010": { + "code": "6000355460205260206020f3" + }, + "0000000000000000000000000000000000000020": { + "code": "6000355460205260206020f3" } } } \ No newline at end of file From ce4bdf8a6a4b5b2af44cc1f905893dcb8bc856ec Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Sun, 11 Mar 2018 23:33:09 +0300 Subject: [PATCH 36/67] Cleanup of default config --- ethereumj-core/src/main/resources/ethereumj.conf | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/ethereumj-core/src/main/resources/ethereumj.conf b/ethereumj-core/src/main/resources/ethereumj.conf index 5228b52d24..25fd7d4352 100644 --- a/ethereumj-core/src/main/resources/ethereumj.conf +++ b/ethereumj-core/src/main/resources/ethereumj.conf @@ -314,7 +314,7 @@ mine { # minimal timeout between mined blocks minBlockTimeoutMsec = 0 - # start mining with specific nonce (might be usefult for testing) + # start mining with specific nonce (might be useful for testing) # null for random start nonce startNonce = null } @@ -428,11 +428,3 @@ crypto { hash.alg256="ETH-KECCAK-256" hash.alg512="ETH-KECCAK-512" } - -consensus { - # Strategy for consensus - # Currently supported: - # "pow" - Proof of Work - # "casper-hybrid" - hybrid PoW + Casper PoS - strategy="pow" -} From f101e4b6e5728b3b72f6d3f55842f851c8cef483 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Sun, 11 Mar 2018 23:39:45 +0300 Subject: [PATCH 37/67] Correct constructor for creating RepositoryRoot without autowiring added --- .../main/java/org/ethereum/db/RepositoryRoot.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java index 1faf2d482e..1d4dc63ac3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/RepositoryRoot.java @@ -17,6 +17,7 @@ */ package org.ethereum.db; +import org.ethereum.config.SystemProperties; import org.ethereum.core.AccountState; import org.ethereum.core.Repository; import org.ethereum.datasource.*; @@ -106,6 +107,15 @@ public RepositoryRoot(final Source stateDS, byte[] root) { init(accountStateCache, codeCache, storageCache); } + /** + * Same as {@link #RepositoryRoot(Source, byte[])} but more correct + * when autowiring is not active as you get default SystemProperties otherwise + */ + public RepositoryRoot(final Source stateDS, byte[] root, final SystemProperties props) { + this(stateDS, root); + this.config = props; + } + @Override public synchronized void commit() { super.commit(); @@ -129,9 +139,7 @@ public synchronized void flush() { @Override public Repository getSnapshotTo(byte[] root) { - RepositoryRoot repo = new RepositoryRoot(stateDS, root); - repo.config = this.config; - return repo; + return new RepositoryRoot(stateDS, root, config); } @Override From dc652a34dc9e767ebc125cac589485c4dbb257da Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Sun, 11 Mar 2018 23:43:14 +0300 Subject: [PATCH 38/67] Logic of casper validator start moved to casper validator --- .../java/org/ethereum/casper/manager/CasperWorldManager.java | 5 +---- .../org/ethereum/casper/service/CasperValidatorService.java | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java index 8cb7e12372..9755924ac3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java @@ -1,6 +1,5 @@ package org.ethereum.casper.manager; -import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperFacade; import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.config.SystemProperties; @@ -33,9 +32,7 @@ public CasperWorldManager(SystemProperties config, Repository repository, Blockc protected void init() { super.init(); casper.setEthereum(ethereum); - if (Boolean.TRUE.equals(((CasperProperties) config).getCasperValidatorEnabled())) { - casperValidatorService.start(); - } + casperValidatorService.init(); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 44d836477d..17c052c57a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -179,7 +179,12 @@ public CasperValidatorService(Ethereum ethereum, SystemProperties config) { handlers.put(WAITING_FOR_WITHDRAWABLE, this::checkWithdrawable); handlers.put(WAITING_FOR_WITHDRAWN, this::checkWithdrawn); handlers.put(LOGGED_OUT, this::checkLoggedIn); + } + public void init() { + if (Boolean.TRUE.equals(config.getCasperValidatorEnabled())) { + start(); + } } public synchronized void start() { From c06a3b5357a8c725af9b4ebbaec3f425cfcf5289 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 12 Mar 2018 01:38:43 +0300 Subject: [PATCH 39/67] Casper vote checking moved to CasperFacade --- .../casper/core/CasperBlockchain.java | 4 ++-- .../ethereum/casper/core/CasperFacade.java | 22 ++++++++++++++++++- .../casper/core/CasperPendingStateImpl.java | 4 ++-- .../core/CasperTransactionExecutor.java | 15 +------------ .../casper/mine/CasperBlockMiner.java | 8 +++---- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index e53a99406d..3ba776814d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -424,12 +424,12 @@ protected boolean isValid(Repository repo, Block block) { } // Casper votes txs should come after regular txs - if (votesStarted && !CasperTransactionExecutor.isCasperVote(tx, casper.getAddress())) { + if (votesStarted && !casper.isVote(tx)) { logger.warn("Invalid transaction: all transactions should be before casper votes: {}", tx); return false; } - if (!votesStarted && CasperTransactionExecutor.isCasperVote(tx, casper.getAddress())) { + if (!votesStarted && casper.isVote(tx)) { votesStarted = true; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 850b9498fc..da46bfc2b6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -23,16 +23,20 @@ import org.ethereum.core.CallTransaction; import org.ethereum.core.Transaction; import org.ethereum.facade.Ethereum; +import org.ethereum.util.FastByteComparisons; import org.ethereum.vm.program.ProgramResult; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Arrays; import java.util.List; @Component public class CasperFacade { + private static final byte[] CASPER_VOTE_DATA_HEAD = Hex.decode("e9dc0614"); + private CasperProperties systemProperties; private Ethereum ethereum; @@ -73,8 +77,24 @@ public Object[] constCall(Block block, String func, Object... funcArgs) { return casper.getByName(func).decodeResult(r.getHReturn()); } + public boolean isVote(Transaction transaction) { + return isVote(transaction, getAddress()); + } + + public static boolean isVote(Transaction transaction, byte[] casperAddress) { + if (!Arrays.equals(transaction.getSender(), Transaction.NULL_SENDER)) + return false; + if (casperAddress == null) + return false; + if (!Arrays.equals(transaction.getReceiveAddress(), casperAddress)) + return false; + + return FastByteComparisons.compareTo(transaction.getData(), 0, CASPER_VOTE_DATA_HEAD.length, + CASPER_VOTE_DATA_HEAD, 0, CASPER_VOTE_DATA_HEAD.length) == 0; + } + public byte[] getAddress() { - return Hex.decode(contractAddress); + return systemProperties.getCasperAddress(); } public List getInitTxs() { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java index 74da6fd53e..99220e5eb2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java @@ -35,7 +35,7 @@ protected boolean receiptIsValid(TransactionReceipt receipt) { boolean isValid = super.receiptIsValid(receipt); if (isValid) { return true; - } else if (CasperTransactionExecutor.isCasperVote(receipt.getTransaction(), ((CasperProperties) config).getCasperAddress())) { + } else if (CasperFacade.isVote(receipt.getTransaction(), ((CasperProperties) config).getCasperAddress())) { return receipt.isSuccessful(); } @@ -50,7 +50,7 @@ protected String validate(Transaction tx) { return String.format("Invalid transaction: %s", e.getMessage()); } - if (CasperTransactionExecutor.isCasperVote(tx, ((CasperProperties) config).getCasperAddress())) { + if (CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress())) { return null; // Doesn't require more checks } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 46eb9d8cb8..7e88e57604 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -103,20 +103,7 @@ public void execute() { } private boolean isCasperVote() { - return isCasperVote(tx, ((CasperProperties) config).getCasperAddress()); - } - - public static boolean isCasperVote(Transaction transaction, byte[] casperAddress) { - if (!Arrays.equals(transaction.getSender(), Transaction.NULL_SENDER)) - return false; - if (casperAddress == null) - return false; - if (!Arrays.equals(transaction.getReceiveAddress(), casperAddress)) - return false; - - byte[] dataCopy = new byte[4]; - System.arraycopy(transaction.getData(), 0, dataCopy, 0, 4); - return Arrays.equals(dataCopy, new byte[] {(byte) 0xe9, (byte) 0xdc, 0x06, 0x14}); + return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java index 5d4b4f9dde..b59eb1d250 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java @@ -17,9 +17,7 @@ */ package org.ethereum.casper.mine; -import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperFacade; -import org.ethereum.casper.core.CasperTransactionExecutor; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.Blockchain; @@ -43,7 +41,7 @@ public CasperBlockMiner(SystemProperties config, CompositeEthereumListener liste @Override protected boolean isAcceptableTx(Transaction tx) { - if (CasperTransactionExecutor.isCasperVote(tx, ((CasperProperties) config).getCasperAddress())) { + if (casper.isVote(tx)) { return true; } return super.isAcceptableTx(tx); @@ -60,8 +58,8 @@ protected Block getNewBlockForMining() { // Casper txs should come after regular List pendingTxs = getAllPendingTransactions(); pendingTxs.sort((tx1, tx2) -> { - boolean tx1isVote = CasperTransactionExecutor.isCasperVote(tx1, casper.getAddress()); - boolean tx2isVote = CasperTransactionExecutor.isCasperVote(tx2, casper.getAddress()); + boolean tx1isVote = casper.isVote(tx1); + boolean tx2isVote = casper.isVote(tx2); return Boolean.compare(tx1isVote, tx2isVote); }); From 313223bebf4442c8c7796e11bc7d99d98944bab2 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 12 Mar 2018 19:01:36 +0300 Subject: [PATCH 40/67] Fixed block was not always thrown away with new block mined when minimum block time was applied --- .../java/org/ethereum/mine/BlockMiner.java | 11 +- .../org/ethereum/mine/CancelMiningTest.java | 161 ++++++++++++++++++ 2 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 ethereumj-core/src/test/java/org/ethereum/mine/CancelMiningTest.java diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index 2c1061d036..eda816bf8b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -272,7 +272,7 @@ protected void restartMining() { try { // wow, block mined! final Block minedBlock = task.get().block; - blockMined(minedBlock); + blockMined(minedBlock, task); } catch (InterruptedException | CancellationException e) { // OK, we've been cancelled, just exit } catch (Exception e) { @@ -293,7 +293,7 @@ private Block cloneBlock(Block block) { return new Block(block.getEncoded()); } - protected void blockMined(Block newBlock) throws InterruptedException { + protected void blockMined(Block newBlock, ListenableFuture task) throws InterruptedException { long t = System.currentTimeMillis(); if (t - lastBlockMinedTime < minBlockTimeout) { long sleepTime = minBlockTimeout - (t - lastBlockMinedTime); @@ -302,6 +302,13 @@ protected void blockMined(Block newBlock) throws InterruptedException { Thread.sleep(sleepTime); } + synchronized (BlockMiner.class) { + if (!currentMiningTasks.contains(task)) { // Task is removed from current tasks so it's cancelled + logger.debug("Discarding block [{}] because mining task was already cancelled", newBlock.getShortDescr()); + return; + } + } + fireBlockMined(newBlock); logger.info("Wow, block mined !!!: {}", newBlock.toString()); diff --git a/ethereumj-core/src/test/java/org/ethereum/mine/CancelMiningTest.java b/ethereumj-core/src/test/java/org/ethereum/mine/CancelMiningTest.java new file mode 100644 index 0000000000..29bcda0a6a --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/mine/CancelMiningTest.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.mine; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; +import org.ethereum.config.SystemProperties; +import org.ethereum.config.blockchain.FrontierConfig; +import org.ethereum.core.Block; +import org.ethereum.core.BlockHeader; +import org.ethereum.core.Blockchain; +import org.ethereum.core.ImportResult; +import org.ethereum.core.Transaction; +import org.ethereum.crypto.ECKey; +import org.ethereum.facade.EthereumImpl; +import org.ethereum.util.ByteUtil; +import org.ethereum.util.blockchain.StandaloneBlockchain; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import javax.annotation.Resource; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.util.Collections.EMPTY_LIST; +import static junit.framework.TestCase.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; + + +/** + * Testing following case: + * Time limit for block is set + * When block is mined and time limit is not over, new tx is pushed in pending state, + * so the new block is mined and old one should be cancelled + */ +@Ignore +public class CancelMiningTest { + + private static final long MIN_BLOCK_TIME = 1000; + + static { + SystemProperties.getDefault().setBlockchainConfig(new FrontierConfig(new FrontierConfig.FrontierConstants() { + @Override + public BigInteger getMINIMUM_DIFFICULTY() { + return BigInteger.ONE; + } + })); + SystemProperties.getDefault().overrideParams("mine.minBlockTimeoutMsec", String.valueOf(MIN_BLOCK_TIME)); + } + + + private StandaloneBlockchain bc = new StandaloneBlockchain().withAutoblock(false); + + private AtomicInteger blocksImported = new AtomicInteger(0); + + private Map> miningFutures = new HashMap<>(); + + @Mock + private EthereumImpl ethereum; + + Blockchain blockchain = bc.getBlockchain(); // Just to init blockchain in StandaloneBlockchain + + @InjectMocks + @Resource + private BlockMiner blockMiner = new BlockMiner(SystemProperties.getDefault(), bc.getListener(), blockchain, + bc.getPendingState());; + + @Before + public void setup() { + + // Initialize mocks created above + MockitoAnnotations.initMocks(this); + + when(ethereum.addNewMinedBlock(any(Block.class))).thenAnswer(new Answer() { + @Override + public ImportResult answer(InvocationOnMock invocation) throws Throwable { + Block block = (Block) invocation.getArguments()[0]; + blocksImported.incrementAndGet(); + return bc.getBlockchain().tryToConnect(block); + } + }); + } + + @Test + public void onlyOneBlockShouldBeMined() throws Exception { + + blockMiner.setExternalMiner(new MinerIfc() { + @Override + public ListenableFuture mine(Block block) { + final SettableFuture futureBlock = SettableFuture.create(); + miningFutures.put(miningFutures.keySet().size() + 1, futureBlock); + return futureBlock; + } + + @Override + public boolean validate(BlockHeader blockHeader) { + return true; + } + }); + + Block block = bc.createBlock(); + assertEquals(1, block.getNumber()); + + + // Dummy to set last block time in Block miner + Block b = bc.getBlockchain().createNewBlock(bc.getBlockchain().getBestBlock(), EMPTY_LIST, EMPTY_LIST); + Ethash.getForBlock(SystemProperties.getDefault(), b.getNumber()).mineLight(b).get(); + // Run it in blocking way to finish + miningFutures.get(miningFutures.size()).set(new MinerIfc.MiningResult(ByteUtil.byteArrayToLong(b.getNonce()), b.getMixHash(), b)); + + for (int i = 0; i < 50; ++i) { + // This block we will cancel with tx + Block b2 = bc.getBlockchain().createNewBlock(bc.getBlockchain().getBestBlock(), EMPTY_LIST, EMPTY_LIST); + Ethash.getForBlock(SystemProperties.getDefault(), b2.getNumber()).mineLight(b2).get(); + // Run it non-blocking to fire new tx until task is finished + Executors.newSingleThreadExecutor().submit(() -> { + miningFutures.get(miningFutures.size()).set(new MinerIfc.MiningResult(ByteUtil.byteArrayToLong(b2.getNonce()), b2.getMixHash(), b2)); + }); + + ECKey alice = new ECKey(); + Transaction tx = bc.createTransaction(i, alice.getAddress(), 1000000, new byte[0]); + bc.getPendingState().addPendingTransaction(tx); + + Block b3 = bc.getBlockchain().createNewBlock(bc.getBlockchain().getBestBlock(), new ArrayList() {{ + add(tx); + }}, EMPTY_LIST); + + miningFutures.get(miningFutures.size()).set(new MinerIfc.MiningResult(ByteUtil.byteArrayToLong(b3.getNonce()), b3.getMixHash(), b3)); + + assertEquals(i + 3, bc.getBlockchain().getBestBlock().getNumber()); // + bc.createBlock() + assertEquals(i + 2, blocksImported.get()); // bc.createBlock() is not counted + assertEquals(1, bc.getBlockchain().getBestBlock().getTransactionsList().size()); + } + } +} From 16e4515a05a38cddcb1c340ad283493e932b3a21 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 12 Mar 2018 21:52:55 +0300 Subject: [PATCH 41/67] Removed state init abstraction --- .../ethereum/casper/core/CasperFacade.java | 119 ++++++++++- .../casper/core/genesis/CasperStateInit.java | 191 ------------------ .../casper/manager/CasperWorldManager.java | 14 -- .../core/genesis/CommonStateInit.java | 64 ------ .../org/ethereum/core/genesis/StateInit.java | 36 ---- .../org/ethereum/manager/WorldManager.java | 24 ++- .../org/ethereum/core/casper/CasperBase.java | 39 +++- .../core/casper/CasperEpochSwitchTest.java | 33 +-- .../core/casper/CasperStateInitTest.java | 7 +- .../core/casper/CasperValidatorTest.java | 53 ++--- .../test/resources/genesis/casper-test.json | 30 +++ 11 files changed, 211 insertions(+), 399 deletions(-) delete mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java create mode 100644 ethereumj-core/src/test/resources/genesis/casper-test.json diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index da46bfc2b6..49e4e6f719 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -17,21 +17,34 @@ */ package org.ethereum.casper.core; +import javafx.util.Pair; +import org.apache.commons.lang3.ArrayUtils; import org.ethereum.casper.config.CasperProperties; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CallTransaction; import org.ethereum.core.Transaction; +import org.ethereum.crypto.ECKey; import org.ethereum.facade.Ethereum; +import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; import org.ethereum.vm.program.ProgramResult; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.math.BigInteger; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_INTEREST_FACTOR; +import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_PENALTY_FACTOR; +import static org.ethereum.casper.config.net.CasperTestNetConfig.MIN_DEPOSIT_ETH; +import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; +import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; +import static org.ethereum.crypto.HashUtil.sha3; + @Component public class CasperFacade { @@ -53,11 +66,17 @@ public CallTransaction.Contract getContract() { } private void init() { - if (casper == null) { - contractAddress = Hex.toHexString(systemProperties.getCasperAddress()); - String casperAbi = systemProperties.getCasperAbi(); - casper = new CallTransaction.Contract(casperAbi); + if (casper != null) { + return; } + + Pair> res = makeInitTxes(); + byte[] casperAddress = res.getKey(); + this.initTxs = res.getValue(); + systemProperties.setCasperAddress(casperAddress); + this.contractAddress = Hex.toHexString(casperAddress); + String casperAbi = systemProperties.getCasperAbi(); + this.casper = new CallTransaction.Contract(casperAbi); } public Object[] constCall(String func, Object... funcArgs) { @@ -94,17 +113,15 @@ public static boolean isVote(Transaction transaction, byte[] casperAddress) { } public byte[] getAddress() { + init(); return systemProperties.getCasperAddress(); } public List getInitTxs() { + init(); return initTxs; } - public void setInitTxs(List initTxs) { - this.initTxs = initTxs; - } - public void setEthereum(Ethereum ethereum) { this.ethereum = ethereum; } @@ -113,4 +130,90 @@ public void setEthereum(Ethereum ethereum) { public void setSystemProperties(SystemProperties systemProperties) { this.systemProperties = (CasperProperties) systemProperties; } + + /** + * @return key: Casper contract address + * value: Casper state initialization transactions + */ + private Pair> makeInitTxes() { + final byte[] casperAddress = new byte[20]; + + // All contracts except Casper itself + final String VIPER_RLP_DECODER_TX = "0xf9035b808506fc23ac0083045f788080b903486103305660006109ac5260006109cc527f0100000000000000000000000000000000000000000000000000000000000000600035046109ec526000610a0c5260006109005260c06109ec51101515585760f86109ec51101561006e5760bf6109ec510336141558576001610a0c52610098565b60013560f76109ec51036020035260005160f66109ec510301361415585760f66109ec5103610a0c525b61022060016064818352015b36610a0c511015156100b557610291565b7f0100000000000000000000000000000000000000000000000000000000000000610a0c5135046109ec526109cc5160206109ac51026040015260016109ac51016109ac5260806109ec51101561013b5760016109cc5161044001526001610a0c516109cc5161046001376001610a0c5101610a0c5260216109cc51016109cc52610281565b60b86109ec5110156101d15760806109ec51036109cc51610440015260806109ec51036001610a0c51016109cc51610460013760816109ec5114156101ac5760807f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350410151558575b607f6109ec5103610a0c5101610a0c5260606109ec51036109cc51016109cc52610280565b60c06109ec51101561027d576001610a0c51013560b76109ec510360200352600051610a2c526038610a2c5110157f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350402155857610a2c516109cc516104400152610a2c5160b66109ec5103610a0c51016109cc516104600137610a2c5160b66109ec5103610a0c510101610a0c526020610a2c51016109cc51016109cc5261027f565bfe5b5b5b81516001018083528114156100a4575b5050601f6109ac511115155857602060206109ac5102016109005260206109005103610a0c5261022060016064818352015b6000610a0c5112156102d45761030a565b61090051610a0c516040015101610a0c51610900516104400301526020610a0c5103610a0c5281516001018083528114156102c3575b50506109cc516109005101610420526109cc5161090051016109005161044003f35b61000461033003610004600039610004610330036000f31b2d4f"; + final String SIG_HASHER_TX = "0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f"; + final String PURITY_CHECKER_TX = "0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f"; + + List txStrs = new ArrayList<>(); + txStrs.add(VIPER_RLP_DECODER_TX); + txStrs.add(SIG_HASHER_TX); + txStrs.add(PURITY_CHECKER_TX); + BigInteger nonce = ethereum.getRepository().getNonce(NULL_SIGN_SENDER.getAddress()); + List txs = new ArrayList<>(); + final long gasPriceFund = 25_000_000_000L; + for (int i = 0; i < txStrs.size(); ++i) { + Transaction deployTx = new Transaction(ByteUtil.hexStringToBytes(txStrs.get(i))); + BigInteger value = BigInteger.ZERO; + value = value.add(ByteUtil.bytesToBigInteger(deployTx.getValue())); + value = value.add( + ByteUtil.bytesToBigInteger(deployTx.getGasPrice()) + .multiply(ByteUtil.bytesToBigInteger(deployTx.getGasLimit())) + ); + Transaction fundTx = new Transaction( + ByteUtil.bigIntegerToBytes(nonce), + ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), + ByteUtil.longToBytesNoLeadZeroes(90_000), + deployTx.getSender(), + ByteUtil.bigIntegerToBytes(value), + new byte[0], + null + ); + fundTx.sign(NULL_SIGN_SENDER); + txs.add(fundTx); + txs.add(deployTx); + nonce = nonce.add(BigInteger.ONE); + } + + // 0 - fund, 1 - rlp, 2 - fund, 3 - sig hasher, 4 - fund, 5 - purity checker + byte[] sigHasherContract = txs.get(3).getContractAddress(); + byte[] purityCheckerContract = txs.get(5).getContractAddress(); + + // Casper! + try { + // Sources: + // https://github.com/ethereum/casper/blob/9106ad647857e6a545f55d7f6193bdc03bb9f5cd/casper/contracts/simple_casper.v.py + String casperBinStr = systemProperties.getCasperBin(); + byte[] casperBin = ByteUtil.hexStringToBytes(casperBinStr); + + CallTransaction.Contract contract = new CallTransaction.Contract(systemProperties.getCasperAbi()); + + byte[] casperInit = contract.getConstructor().encodeArguments( + systemProperties.getCasperEpochLength(), // Epoch length + WITHDRAWAL_DELAY, // Withdrawal delay + ECKey.fromPrivate(sha3("0".getBytes())).getAddress(), // Owner + sigHasherContract, // Signature hasher contract + purityCheckerContract, // Purity checker contract + BASE_INTEREST_FACTOR, // Base interest factor + BASE_PENALTY_FACTOR, // Base penalty factor + BigInteger.valueOf(MIN_DEPOSIT_ETH).multiply(BigInteger.TEN.pow(18)) // Minimum validator deposit in wei + ); + + Transaction tx = new Transaction( + ByteUtil.bigIntegerToBytes(nonce), + ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), + ByteUtil.longToBytesNoLeadZeroes(5_000_000), + new byte[0], + ByteUtil.longToBytesNoLeadZeroes(0), + ArrayUtils.addAll(casperBin, casperInit), // Merge contract and constructor args + null); + tx.sign(NULL_SIGN_SENDER); + + // set casperAddress + System.arraycopy(tx.getContractAddress(), 0, casperAddress, 0, 20); + txs.add(tx); + } catch (Exception ex) { + throw new RuntimeException("Failed to generate Casper init transactions", ex); + } + + return new Pair<>(casperAddress, txs); + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java deleted file mode 100644 index 91573ddbbc..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/genesis/CasperStateInit.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.casper.core.genesis; - -import javafx.util.Pair; -import org.apache.commons.lang3.ArrayUtils; -import org.ethereum.casper.config.CasperProperties; -import org.ethereum.config.SystemProperties; -import org.ethereum.core.Blockchain; -import org.ethereum.core.CallTransaction; -import org.ethereum.core.Genesis; -import org.ethereum.core.Repository; -import org.ethereum.core.Transaction; -import org.ethereum.core.genesis.StateInit; -import org.ethereum.crypto.ECKey; -import org.ethereum.db.BlockStore; -import org.ethereum.util.ByteUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.spongycastle.util.encoders.Hex; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_INTEREST_FACTOR; -import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_PENALTY_FACTOR; -import static org.ethereum.casper.config.net.CasperTestNetConfig.MIN_DEPOSIT_ETH; -import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; -import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; -import static org.ethereum.crypto.HashUtil.sha3; - -public class CasperStateInit implements StateInit { - - private static final Logger logger = LoggerFactory.getLogger("general"); - - private Genesis genesis; - - private Repository repository; - - private Blockchain blockchain; - - private CasperProperties systemProperties; - - private Genesis initGenesis; - - public CasperStateInit(Genesis genesis, Repository repository, Blockchain blockchain, - SystemProperties systemProperties) { - this.genesis = genesis; - this.repository = repository; - this.blockchain = blockchain; - this.systemProperties = (CasperProperties) systemProperties; - init(); - } - - @Override - public void initDB() { - if (blockchain.getBlockByNumber(0) != null) { - return; // Already initialized - } - logger.info("DB is empty - adding Genesis"); - Genesis.populateRepository(repository, genesis); - repository.commit(); - ((org.ethereum.facade.Blockchain)blockchain).getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true); - blockchain.setBestBlock(genesis); - blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); - - logger.info("Genesis block loaded"); - } - - /** - * @return key: Casper contract address - * value: Casper state initialization transactions - */ - public Pair> makeInitTxes() { - final byte[] casperAddress = new byte[20]; - - // All contracts except Casper itself - final String VIPER_RLP_DECODER_TX = "0xf9035b808506fc23ac0083045f788080b903486103305660006109ac5260006109cc527f0100000000000000000000000000000000000000000000000000000000000000600035046109ec526000610a0c5260006109005260c06109ec51101515585760f86109ec51101561006e5760bf6109ec510336141558576001610a0c52610098565b60013560f76109ec51036020035260005160f66109ec510301361415585760f66109ec5103610a0c525b61022060016064818352015b36610a0c511015156100b557610291565b7f0100000000000000000000000000000000000000000000000000000000000000610a0c5135046109ec526109cc5160206109ac51026040015260016109ac51016109ac5260806109ec51101561013b5760016109cc5161044001526001610a0c516109cc5161046001376001610a0c5101610a0c5260216109cc51016109cc52610281565b60b86109ec5110156101d15760806109ec51036109cc51610440015260806109ec51036001610a0c51016109cc51610460013760816109ec5114156101ac5760807f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350410151558575b607f6109ec5103610a0c5101610a0c5260606109ec51036109cc51016109cc52610280565b60c06109ec51101561027d576001610a0c51013560b76109ec510360200352600051610a2c526038610a2c5110157f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350402155857610a2c516109cc516104400152610a2c5160b66109ec5103610a0c51016109cc516104600137610a2c5160b66109ec5103610a0c510101610a0c526020610a2c51016109cc51016109cc5261027f565bfe5b5b5b81516001018083528114156100a4575b5050601f6109ac511115155857602060206109ac5102016109005260206109005103610a0c5261022060016064818352015b6000610a0c5112156102d45761030a565b61090051610a0c516040015101610a0c51610900516104400301526020610a0c5103610a0c5281516001018083528114156102c3575b50506109cc516109005101610420526109cc5161090051016109005161044003f35b61000461033003610004600039610004610330036000f31b2d4f"; - final String SIG_HASHER_TX = "0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f"; - final String PURITY_CHECKER_TX = "0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f"; - - List txStrs = new ArrayList<>(); - txStrs.add(VIPER_RLP_DECODER_TX); - txStrs.add(SIG_HASHER_TX); - txStrs.add(PURITY_CHECKER_TX); - BigInteger nonce = repository.getNonce(NULL_SIGN_SENDER.getAddress()); - List txs = new ArrayList<>(); - final long gasPriceFund = 25_000_000_000L; - for (int i = 0; i < txStrs.size(); ++i) { - Transaction deployTx = new Transaction(ByteUtil.hexStringToBytes(txStrs.get(i))); - BigInteger value = BigInteger.ZERO; - value = value.add(ByteUtil.bytesToBigInteger(deployTx.getValue())); - value = value.add( - ByteUtil.bytesToBigInteger(deployTx.getGasPrice()) - .multiply(ByteUtil.bytesToBigInteger(deployTx.getGasLimit())) - ); - Transaction fundTx = new Transaction( - ByteUtil.bigIntegerToBytes(nonce), - ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), - ByteUtil.longToBytesNoLeadZeroes(90_000), - deployTx.getSender(), - ByteUtil.bigIntegerToBytes(value), - new byte[0], - null - ); - fundTx.sign(NULL_SIGN_SENDER); - txs.add(fundTx); - txs.add(deployTx); - nonce = nonce.add(BigInteger.ONE); - } - - // 0 - fund, 1 - rlp, 2 - fund, 3 - sig hasher, 4 - fund, 5 - purity checker - byte[] sigHasherContract = txs.get(3).getContractAddress(); - byte[] purityCheckerContract = txs.get(5).getContractAddress(); - - // Casper! - try { - // Sources: - // https://github.com/ethereum/casper/blob/9106ad647857e6a545f55d7f6193bdc03bb9f5cd/casper/contracts/simple_casper.v.py - String casperBinStr = systemProperties.getCasperBin(); - byte[] casperBin = ByteUtil.hexStringToBytes(casperBinStr); - - CallTransaction.Contract contract = new CallTransaction.Contract(systemProperties.getCasperAbi()); - - byte[] casperInit = contract.getConstructor().encodeArguments( - systemProperties.getCasperEpochLength(), // Epoch length - WITHDRAWAL_DELAY, // Withdrawal delay - ECKey.fromPrivate(sha3("0".getBytes())).getAddress(), // Owner - sigHasherContract, // Signature hasher contract - purityCheckerContract, // Purity checker contract - BASE_INTEREST_FACTOR, // Base interest factor - BASE_PENALTY_FACTOR, // Base penalty factor - BigInteger.valueOf(MIN_DEPOSIT_ETH).multiply(BigInteger.TEN.pow(18)) // Minimum validator deposit in wei - ); - - Transaction tx = new Transaction( - ByteUtil.bigIntegerToBytes(nonce), - ByteUtil.longToBytesNoLeadZeroes(gasPriceFund), - ByteUtil.longToBytesNoLeadZeroes(5_000_000), - new byte[0], - ByteUtil.longToBytesNoLeadZeroes(0), - ArrayUtils.addAll(casperBin, casperInit), // Merge contract and constructor args - null); - tx.sign(NULL_SIGN_SENDER); - - // set casperAddress - System.arraycopy(tx.getContractAddress(), 0, casperAddress, 0, 20); - txs.add(tx); - } catch (Exception ex) { - throw new RuntimeException("Failed to generate Casper init transactions", ex); - } - - return new Pair<>(casperAddress, txs); - } - - private void init() { - Repository repo = repository.getSnapshotTo(null); - Genesis.populateRepository(repo, genesis); - - // Metropolis dummy - repo.saveCode(Hex.decode("0000000000000000000000000000000000000010"), Hex.decode("6000355460205260206020f3")); - repo.saveCode(Hex.decode("0000000000000000000000000000000000000020"), Hex.decode("6000355460205260206020f3")); - - this.initGenesis = genesis; - this.initGenesis.setStateRoot(repo.getRoot()); - - Pair> res = makeInitTxes(); - systemProperties.setCasperAddress(res.getKey()); - } - - @Override - public Genesis getInitGenesis() { - return initGenesis; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java index 9755924ac3..4c75e1c245 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/manager/CasperWorldManager.java @@ -4,10 +4,7 @@ import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.config.SystemProperties; import org.ethereum.core.Blockchain; -import org.ethereum.core.Genesis; import org.ethereum.core.Repository; -import org.ethereum.casper.core.genesis.CasperStateInit; -import org.ethereum.core.genesis.StateInit; import org.ethereum.manager.WorldManager; import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +18,6 @@ public class CasperWorldManager extends WorldManager { @Autowired private CasperFacade casper; - private CasperStateInit stateInit; public CasperWorldManager(SystemProperties config, Repository repository, Blockchain blockchain) { super(config, repository, blockchain); @@ -34,14 +30,4 @@ protected void init() { casper.setEthereum(ethereum); casperValidatorService.init(); } - - @Override - protected StateInit createStateInit(Genesis genesis) { - if (stateInit == null) { - this.stateInit = new CasperStateInit(genesis, (Repository) getRepository(), blockchain, config); - // FIXME: Looks like not a good side job - casper.setInitTxs(stateInit.makeInitTxes().getValue()); - } - return stateInit; - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java deleted file mode 100644 index 3260c637fb..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/core/genesis/CommonStateInit.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.core.genesis; - -import org.ethereum.core.Blockchain; -import org.ethereum.core.Genesis; -import org.ethereum.core.Repository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CommonStateInit implements StateInit { - private static final Logger logger = LoggerFactory.getLogger("general"); - private Genesis genesis; - private Repository repository; - private Blockchain blockchain; - private Genesis initGenesis; - - public CommonStateInit(Genesis genesis, Repository repository, Blockchain blockchain) { - this.genesis = genesis; - this.repository = repository; - this.blockchain = blockchain; - init(); - } - - @Override - public void initDB() { - if (blockchain.getBlockByNumber(0) != null) { - return; // Already initialized - } - logger.info("DB is empty - adding Genesis"); - Genesis.populateRepository(repository, genesis); - repository.commit(); - ((org.ethereum.facade.Blockchain)blockchain).getBlockStore().saveBlock(genesis, genesis.getCumulativeDifficulty(), true); - blockchain.setBestBlock(genesis); - blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); - - logger.info("Genesis block loaded"); - } - - - private void init() { - this.initGenesis = genesis; - } - - @Override - public Genesis getInitGenesis() { - return initGenesis; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java b/ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java deleted file mode 100644 index e104d44136..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/core/genesis/StateInit.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.core.genesis; - -import org.ethereum.core.Genesis; - -/** - * Creates initial state of blockchain - */ -public interface StateInit { - - /** - * Initializes DB with genesis etc. - */ - void initDB(); - - /** - * @return actual genesis - */ - Genesis getInitGenesis(); -} diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index af3df3c98e..5575e4ccf4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -19,8 +19,6 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.core.genesis.CommonStateInit; -import org.ethereum.core.genesis.StateInit; import org.ethereum.db.BlockStore; import org.ethereum.db.DbFlushManager; import org.ethereum.facade.Ethereum; @@ -39,7 +37,6 @@ import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.math.BigInteger; @@ -172,26 +169,33 @@ public PendingState getPendingState() { return pendingState; } - protected StateInit createStateInit(Genesis genesis) { - return new CommonStateInit(genesis, repository, blockchain); - } - public void loadBlockchain() { if (!config.databaseReset() || config.databaseResetBlock() != 0) blockStore.load(); - StateInit stateInit = createStateInit(Genesis.getInstance(config)); if (blockStore.getBestBlock() == null) { + logger.info("DB is empty - adding Genesis"); + + Genesis genesis = Genesis.getInstance(config); + Genesis.populateRepository(repository, genesis); + +// repository.commitBlock(genesis.getHeader()); + repository.commit(); + + blockStore.saveBlock(Genesis.getInstance(config), Genesis.getInstance(config).getCumulativeDifficulty(), true); + + blockchain.setBestBlock(Genesis.getInstance(config)); + blockchain.setTotalDifficulty(Genesis.getInstance(config).getCumulativeDifficulty()); - stateInit.initDB(); listener.onBlock(new BlockSummary(Genesis.getInstance(config), new HashMap(), new ArrayList(), new ArrayList())); // repository.dumpState(Genesis.getInstance(config), 0, 0, null); + logger.info("Genesis block loaded"); } else { if (!config.databaseReset() && - !Arrays.equals(blockchain.getBlockByNumber(0).getHash(), stateInit.getInitGenesis().getHash())) { + !Arrays.equals(blockchain.getBlockByNumber(0).getHash(), config.getGenesis().getHash())) { // fatal exit Utils.showErrorAndExit("*** DB is incorrect, 0 block in DB doesn't match genesis"); } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 9e2da44477..e43781f29d 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -30,7 +30,9 @@ import org.ethereum.core.BlockSummary; import org.ethereum.core.BlockchainImpl; import org.ethereum.core.EventDispatchThread; +import org.ethereum.core.Genesis; import org.ethereum.core.Repository; +import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; import org.ethereum.datasource.CountingBytesSource; @@ -66,8 +68,13 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; // We have all mocks here and not all of them are used in every test, so strict stubs should be turned off @RunWith(MockitoJUnitRunner.Silent.class) @@ -97,8 +104,6 @@ public SystemProperties systemProperties() { CasperBlockchain blockchain; - WorldManager worldManager; - private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); @InjectMocks @@ -107,12 +112,14 @@ public SystemProperties systemProperties() { @InjectMocks CasperFacade casper = new CasperFacade(); + Repository repository = new RepositoryWrapper(); + @InjectMocks CasperPendingStateImpl casperPendingState = new CasperPendingStateImpl(defaultListener); StandaloneBlockchain bc; - Repository repository; + WorldManager worldManager; @Before public void setup() throws Exception { @@ -190,10 +197,8 @@ private BlockchainImpl createBlockchain() { Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); Mockito.when(worldManager.getBlockchain()).thenReturn(blockchain); Mockito.when(worldManager.getBlockStore()).thenReturn(blockchain.getBlockStore()); - RepositoryWrapper wrapper = new RepositoryWrapper(); - wrapper.setBlockchain(bc.getBlockchain()); - this.repository = wrapper; - Mockito.when(worldManager.getRepository()).thenReturn(wrapper); + ((RepositoryWrapper) repository).setBlockchain(bc.getBlockchain()); + Mockito.when(worldManager.getRepository()).thenReturn(repository); doAnswer((Answer) invocation -> { Object arg0 = invocation.getArgument(0); defaultListener.addListener((EthereumListener) arg0); @@ -215,6 +220,26 @@ public void onPendingTransactionUpdate(TransactionReceipt txReceipt, PendingTran }); } + /** + * Same logic as in WorldManager.loadBlockchain + */ + protected void loadBlockchain() { + + Genesis genesis = Genesis.getInstance(systemProperties); + Genesis.populateRepository(repository, genesis); + +// repository.commitBlock(genesis.getHeader()); + repository.commit(); + + blockchain.getBlockStore().saveBlock(Genesis.getInstance(systemProperties), Genesis.getInstance(systemProperties).getCumulativeDifficulty(), true); + + blockchain.setBestBlock(Genesis.getInstance(systemProperties)); + blockchain.setTotalDifficulty(Genesis.getInstance(systemProperties).getCumulativeDifficulty()); + + defaultListener.onBlock(new BlockSummary(Genesis.getInstance(systemProperties), new HashMap(), new ArrayList(), new ArrayList())); +// repository.dumpState(Genesis.getInstance(config), 0, 0, null); + } + BlockchainNetConfig config() { return new CasperTestNetConfig(); } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index e1a91df395..9c5332725e 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -26,11 +26,10 @@ import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; import org.ethereum.core.Block; -import org.ethereum.core.Genesis; -import org.ethereum.casper.core.genesis.CasperStateInit; -import org.ethereum.util.ByteUtil; import org.ethereum.vm.GasCost; import org.junit.Test; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import java.math.BigInteger; @@ -94,29 +93,11 @@ BlockchainNetConfig config() { } @Test - public void epochStartTest() { - // Init with Genesis - final Genesis genesis = Genesis.getInstance(systemProperties); - final Genesis modifiedGenesis = new Genesis( - genesis.getParentHash(), - genesis.getUnclesHash(), - genesis.getCoinbase(), - genesis.getLogBloom(), - ByteUtil.longToBytes(1), - genesis.getNumber(), - ByteUtil.byteArrayToLong(genesis.getGasLimit()), - genesis.getGasUsed(), - genesis.getTimestamp(), - genesis.getExtraData(), - genesis.getMixHash(), - genesis.getNonce() - ); - modifiedGenesis.setPremine(genesis.getPremine()); - - CasperStateInit casperStateInit = new CasperStateInit(modifiedGenesis, repository, blockchain, systemProperties); - casperStateInit.initDB(); - - casper.setInitTxs(casperStateInit.makeInitTxes().getValue()); + public void epochStartTest() throws Exception { + // Init with light Genesis + Resource casperGenesis = new ClassPathResource("/genesis/casper-test.json"); + systemProperties.useGenesis(casperGenesis.getInputStream()); + loadBlockchain(); BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index addc094841..ec02a8aecd 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -19,7 +19,6 @@ import org.ethereum.core.Block; import org.ethereum.core.Genesis; -import org.ethereum.casper.core.genesis.CasperStateInit; import org.ethereum.db.ByteArrayWrapper; import org.junit.Ignore; import org.junit.Test; @@ -36,11 +35,7 @@ public class CasperStateInitTest extends CasperBase { @Test public void genesisPlusBlock() { // Init with Genesis - final Genesis genesis = Genesis.getInstance(systemProperties); - - CasperStateInit casperStateInit = new CasperStateInit(genesis, repository, blockchain, systemProperties); - casperStateInit.initDB(); - casper.setInitTxs(casperStateInit.makeInitTxes().getValue()); + loadBlockchain(); // Check after genesis assertEquals(new ByteArrayWrapper(Hex.decode("f3f713c5ff3119287ae62861e3fd90d6afc94b57d06151007c409b86bf419d11")), diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index eafc5a5ece..730f68b389 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -25,27 +25,25 @@ import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; -import org.ethereum.core.AccountState; import org.ethereum.core.Block; -import org.ethereum.core.Genesis; -import org.ethereum.casper.core.genesis.CasperStateInit; import org.ethereum.crypto.ECKey; -import org.ethereum.db.ByteArrayWrapper; import org.ethereum.casper.service.CasperValidatorService; import org.ethereum.sync.SyncManager; -import org.ethereum.util.ByteUtil; import org.ethereum.util.blockchain.EtherUtil; import org.ethereum.vm.GasCost; import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import org.spongycastle.util.encoders.Hex; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import java.math.BigDecimal; import java.math.BigInteger; import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; +import static org.ethereum.crypto.HashUtil.sha3; @Ignore // Takes too long to run usually public class CasperValidatorTest extends CasperBase { @@ -106,35 +104,13 @@ BlockchainNetConfig config() { } @Test - public void validatorTest() { - // Init with Genesis - final Genesis genesis = Genesis.getInstance(systemProperties); - final ECKey coinbase = new ECKey(); - final Genesis modifiedGenesis = new Genesis( - genesis.getParentHash(), - genesis.getUnclesHash(), - genesis.getCoinbase(), - genesis.getLogBloom(), - ByteUtil.longToBytes(1), - genesis.getNumber(), - ByteUtil.byteArrayToLong(genesis.getGasLimit()), - genesis.getGasUsed(), - genesis.getTimestamp(), - genesis.getExtraData(), - genesis.getMixHash(), - genesis.getNonce() - ); - - // We need money - Genesis.PremineAccount coinbaseAcc = new Genesis.PremineAccount(); - coinbaseAcc.accountState = new AccountState(BigInteger.ZERO, EtherUtil.convert(2500, EtherUtil.Unit.ETHER)); - genesis.getPremine().put(new ByteArrayWrapper(coinbase.getAddress()), coinbaseAcc); - modifiedGenesis.setPremine(genesis.getPremine()); + public void validatorTest() throws Exception { + // Init with light Genesis + Resource casperGenesis = new ClassPathResource("/genesis/casper-test.json"); + systemProperties.useGenesis(casperGenesis.getInputStream()); + loadBlockchain(); - CasperStateInit casperStateInit = new CasperStateInit(modifiedGenesis, repository, blockchain, systemProperties); - casperStateInit.initDB(); - - casper.setInitTxs(casperStateInit.makeInitTxes().getValue()); + final ECKey coinbase = ECKey.fromPrivate(sha3("cow".getBytes())); // Premined in light genesis BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); @@ -154,8 +130,11 @@ public void validatorTest() { Mockito.when(syncManager.isSyncDone()).thenReturn(true); service.setSyncManager(syncManager); service.setCasper(casper); + service.setRepository(repository); service.start(); + BigInteger initialBalance = ethereum.getRepository().getBalance(coinbase.getAddress()); + for (int i = 0; i < 10; ++i) { Block block = bc.createBlock(); } @@ -170,16 +149,16 @@ public void validatorTest() { BigDecimal increasedDeposit = (BigDecimal) casper.constCall("get_validators__deposit", 1)[0]; assertTrue(increasedDeposit.compareTo(new BigDecimal("200000000000")) > 0); - // We've left less than 500 ETH - assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(EtherUtil.convert(500, EtherUtil.Unit.ETHER)) < 0); + // We've left less than (initial - 2000 ETH) + assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(initialBalance.subtract(EtherUtil.convert(2000, EtherUtil.Unit.ETHER))) < 0); // Let's logout service.voteThenLogout(); // Withdrawal delay is 5 epochs + 1 vote epoch + overhead for (int i = 0; i < 400; ++i) { Block block = bc.createBlock(); } - // We should have more than 2500 ETH in the end - assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(EtherUtil.convert(2500, EtherUtil.Unit.ETHER)) > 0); + // We should have more than initialBalance in the end + assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(initialBalance) > 0); // TODO: add more checking with listeners etc. // TODO: add more validators diff --git a/ethereumj-core/src/test/resources/genesis/casper-test.json b/ethereumj-core/src/test/resources/genesis/casper-test.json new file mode 100644 index 0000000000..ac92304bbe --- /dev/null +++ b/ethereumj-core/src/test/resources/genesis/casper-test.json @@ -0,0 +1,30 @@ +{ + "nonce": "0x0000000000000056", + "difficulty": "0x01", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x5f5e100", + "alloc": { + "cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { + "balance": "1001002003004005006007008" + }, + "b42e5cafe87d951c5cf0022bfdab06fe56ba2ad2": { + "balance": "1001002003004005006007008" + }, + "0xf63a243fe6922320a53dfc4270f02b8af0d4921d": { + "balance": "1001002003004005006007008" + }, + "b96611e02f9eff3c8afc6226d4ebfa81a821547c": { + "balance": "5125001002003004005006" + }, + "0000000000000000000000000000000000000010": { + "code": "6000355460205260206020f3" + }, + "0000000000000000000000000000000000000020": { + "code": "6000355460205260206020f3" + } + } +} \ No newline at end of file From 2b1db0f0b6f8c6935782fb0890b8f860f29e90e7 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 13 Mar 2018 01:51:50 +0300 Subject: [PATCH 42/67] Added validators for transaction and transaction receipt in PendingState --- .../casper/config/CasperBeanConfig.java | 8 --- .../casper/config/CasperProperties.java | 6 -- .../casper/core/CasperBlockchain.java | 39 ++++++++++++ .../casper/core/CasperPendingStateImpl.java | 63 ------------------- .../org/ethereum/config/BlockchainConfig.java | 2 +- .../org/ethereum/config/CommonConfig.java | 53 ++++++++++++---- .../org/ethereum/config/SystemProperties.java | 4 +- .../config/blockchain/AbstractConfig.java | 2 +- .../config/blockchain/AbstractDaoConfig.java | 9 +-- .../config/blockchain/Eip150HFConfig.java | 2 +- .../config/blockchain/RopstenConfig.java | 8 +-- .../org/ethereum/core/BlockchainImpl.java | 4 +- .../org/ethereum/core/PendingStateImpl.java | 29 +++++++-- .../org/ethereum/manager/BlockLoader.java | 2 +- .../org/ethereum/net/eth/handler/Eth62.java | 4 +- .../ethereum/sync/BlockBodiesDownloader.java | 2 +- .../org/ethereum/sync/BlockDownloader.java | 3 +- .../org/ethereum/sync/FastSyncDownloader.java | 2 +- .../org/ethereum/sync/HeadersDownloader.java | 2 +- .../java/org/ethereum/sync/SyncManager.java | 2 +- .../util/blockchain/StandaloneBlockchain.java | 7 ++- .../{BlockHeaderRule.java => EntityRule.java} | 25 +++----- .../ethereum/validator/EntityValidator.java | 54 ++++++++++++++++ .../validator/{ => block}/BestNumberRule.java | 2 +- .../{ => block}/BlockCustomHashRule.java | 2 +- .../validator/{ => block}/BlockHashRule.java | 2 +- .../validator/block/BlockHeaderRule.java | 36 +++++++++++ .../{ => block}/BlockHeaderValidator.java | 22 +++---- .../{ => block}/DependentBlockHeaderRule.java | 3 +- .../DependentBlockHeaderRuleAdapter.java | 2 +- .../validator/{ => block}/DifficultyRule.java | 3 +- .../{ => block}/ExtraDataPresenceRule.java | 3 +- .../validator/{ => block}/ExtraDataRule.java | 3 +- .../validator/{ => block}/GasLimitRule.java | 3 +- .../validator/{ => block}/GasValueRule.java | 3 +- .../ParentBlockHeaderValidator.java | 3 +- .../{ => block}/ParentGasLimitRule.java | 3 +- .../{ => block}/ParentNumberRule.java | 3 +- .../{ => block}/ProofOfWorkRule.java | 3 +- .../transaction/ReceiptCasperVoteRule.java | 55 ++++++++++++++++ .../transaction/ReceiptValidityRule.java | 35 +++++++++++ .../TransactionCasperVoteRule.java | 52 +++++++++++++++ .../transaction/TransactionFieldsRule.java | 39 ++++++++++++ .../TransactionMineGasPriceRule.java | 45 +++++++++++++ .../transaction/TransactionReceiptRule.java | 30 +++++++++ .../TransactionReceiptValidator.java | 43 +++++++++++++ .../transaction/TransactionRule.java | 31 +++++++++ .../transaction/TransactionValidator.java | 43 +++++++++++++ .../blockchain/TestBlockchainConfig.java | 2 +- .../org/ethereum/core/ImportLightTest.java | 7 ++- .../core/PendingStateLongRunTest.java | 7 ++- .../org/ethereum/core/casper/CasperBase.java | 17 +++-- .../jsontestsuite/suite/TestRunner.java | 6 +- .../validator/ProofOfWorkRuleTest.java | 1 + 54 files changed, 660 insertions(+), 181 deletions(-) delete mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java rename ethereumj-core/src/main/java/org/ethereum/validator/{BlockHeaderRule.java => EntityRule.java} (70%) create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/BestNumberRule.java (98%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/BlockCustomHashRule.java (97%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/BlockHashRule.java (98%) create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/BlockHeaderValidator.java (69%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/DependentBlockHeaderRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/DependentBlockHeaderRuleAdapter.java (96%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/DifficultyRule.java (94%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/ExtraDataPresenceRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/ExtraDataRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/GasLimitRule.java (94%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/GasValueRule.java (93%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/ParentBlockHeaderValidator.java (94%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/ParentGasLimitRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/ParentNumberRule.java (93%) rename ethereumj-core/src/main/java/org/ethereum/validator/{ => block}/ProofOfWorkRule.java (94%) create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index 40e7d91b0e..ef1b6fa88d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -17,14 +17,12 @@ */ package org.ethereum.casper.config; -import org.ethereum.casper.core.CasperPendingStateImpl; import org.ethereum.casper.manager.CasperWorldManager; import org.ethereum.casper.mine.CasperBlockMiner; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.Blockchain; -import org.ethereum.core.PendingState; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutor; @@ -81,12 +79,6 @@ public WorldManager worldManager() { return new CasperWorldManager(systemProperties(), repository(), blockchain()); } - @Bean - @Override - public PendingState pendingState() { - return new CasperPendingStateImpl(ethereumListener); - } - @Bean @Override public BlockMiner blockMiner() { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java index 0101bd5bc8..21bf0b4515 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java @@ -1,13 +1,7 @@ package org.ethereum.casper.config; -import org.apache.commons.lang3.tuple.Pair; -import org.ethereum.casper.config.net.CasperTestNetConfig; -import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.core.genesis.GenesisConfig; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.BlockCustomHashRule; -import org.ethereum.validator.BlockHeaderValidator; import java.io.BufferedReader; import java.io.IOException; diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 3ba776814d..807b344ffd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -33,6 +33,14 @@ import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; +import org.ethereum.validator.transaction.ReceiptCasperVoteRule; +import org.ethereum.validator.transaction.ReceiptValidityRule; +import org.ethereum.validator.transaction.TransactionCasperVoteRule; +import org.ethereum.validator.transaction.TransactionFieldsRule; +import org.ethereum.validator.transaction.TransactionMineGasPriceRule; +import org.ethereum.validator.transaction.TransactionReceiptValidator; +import org.ethereum.validator.transaction.TransactionRule; +import org.ethereum.validator.transaction.TransactionValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.Arrays; @@ -41,6 +49,7 @@ import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,6 +68,12 @@ public class CasperBlockchain extends BlockchainImpl { @Autowired private CasperFacade casper; + @Autowired + private TransactionValidator transactionValidator; + + @Autowired + private TransactionReceiptValidator receiptValidator; + private static final Logger logger = LoggerFactory.getLogger("blockchain"); private static final Logger stateLogger = LoggerFactory.getLogger("state"); @@ -364,6 +379,22 @@ coinbase, txTrack, blockStore, getProgramInvokeFactory(), block, listener, 0) track.addBalance(casperAddress, track.getBalance(casperAddress).negate()); track.addBalance(casperAddress, BigInteger.valueOf(10).pow(25)); }); + updateValidators(); // as casper contract is in place + } + + private void updateValidators() { + // Update transaction validator as casper txs are applied + transactionValidator.reInit( + new ArrayList() {{ + add(new TransactionFieldsRule()); + add(new TransactionCasperVoteRule((CasperProperties) config, new TransactionMineGasPriceRule(config))); + }} + ); + + // Update transaction receipts validator + receiptValidator.reInit(Collections.singletonList( + new ReceiptCasperVoteRule((CasperProperties) config, new ReceiptValidityRule())) + ); } /** @@ -447,4 +478,12 @@ private BigInteger getPoWDifficulty(final Block block) { public void setCasper(CasperFacade casper) { this.casper = casper; } + + public void setTransactionValidator(TransactionValidator transactionValidator) { + this.transactionValidator = transactionValidator; + } + + public void setReceiptValidator(TransactionReceiptValidator receiptValidator) { + this.receiptValidator = receiptValidator; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java deleted file mode 100644 index 99220e5eb2..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.casper.core; - -import org.ethereum.casper.config.CasperProperties; -import org.ethereum.core.PendingStateImpl; -import org.ethereum.core.Transaction; -import org.ethereum.core.TransactionReceipt; -import org.ethereum.listener.EthereumListener; -import org.ethereum.util.ByteUtil; - -public class CasperPendingStateImpl extends PendingStateImpl { - - public CasperPendingStateImpl(EthereumListener listener) { - super(listener); - } - - @Override - protected boolean receiptIsValid(TransactionReceipt receipt) { - boolean isValid = super.receiptIsValid(receipt); - if (isValid) { - return true; - } else if (CasperFacade.isVote(receipt.getTransaction(), ((CasperProperties) config).getCasperAddress())) { - return receipt.isSuccessful(); - } - - return false; - } - - @Override - protected String validate(Transaction tx) { - try { - tx.verify(); - } catch (Exception e) { - return String.format("Invalid transaction: %s", e.getMessage()); - } - - if (CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress())) { - return null; // Doesn't require more checks - } - - if (config.getMineMinGasPrice().compareTo(ByteUtil.bytesToBigInteger(tx.getGasPrice())) > 0) { - return "Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(tx.getGasPrice()); - } - - return null; - } -} 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 65a7462712..bc33fc161a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java @@ -21,7 +21,7 @@ import org.ethereum.core.*; import org.ethereum.db.BlockStore; import org.ethereum.mine.MinerIfc; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index c70b4be9a4..0507d06003 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -28,18 +28,25 @@ import org.ethereum.manager.WorldManager; import org.ethereum.mine.BlockMiner; import org.ethereum.sync.FastSyncManager; -import org.ethereum.validator.BlockHashRule; -import org.ethereum.validator.BlockHeaderRule; -import org.ethereum.validator.BlockHeaderValidator; -import org.ethereum.validator.DependentBlockHeaderRule; -import org.ethereum.validator.DifficultyRule; -import org.ethereum.validator.ExtraDataRule; -import org.ethereum.validator.GasLimitRule; -import org.ethereum.validator.GasValueRule; -import org.ethereum.validator.ParentBlockHeaderValidator; -import org.ethereum.validator.ParentGasLimitRule; -import org.ethereum.validator.ParentNumberRule; -import org.ethereum.validator.ProofOfWorkRule; +import org.ethereum.validator.block.BlockHashRule; +import org.ethereum.validator.block.BlockHeaderRule; +import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.block.DependentBlockHeaderRule; +import org.ethereum.validator.block.DifficultyRule; +import org.ethereum.validator.block.ExtraDataRule; +import org.ethereum.validator.block.GasLimitRule; +import org.ethereum.validator.block.GasValueRule; +import org.ethereum.validator.block.ParentBlockHeaderValidator; +import org.ethereum.validator.block.ParentGasLimitRule; +import org.ethereum.validator.block.ParentNumberRule; +import org.ethereum.validator.block.ProofOfWorkRule; +import org.ethereum.validator.transaction.ReceiptValidityRule; +import org.ethereum.validator.transaction.TransactionFieldsRule; +import org.ethereum.validator.transaction.TransactionMineGasPriceRule; +import org.ethereum.validator.transaction.TransactionReceiptRule; +import org.ethereum.validator.transaction.TransactionReceiptValidator; +import org.ethereum.validator.transaction.TransactionRule; +import org.ethereum.validator.transaction.TransactionValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.program.ProgramPrecompile; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; @@ -52,6 +59,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -279,6 +287,27 @@ public ParentBlockHeaderValidator parentHeaderValidator() { return new ParentBlockHeaderValidator(rules); } + @Bean + public TransactionValidator transactionValidator() { + + List rules = new ArrayList<>(asList( + new TransactionFieldsRule(), + new TransactionMineGasPriceRule(systemProperties()) + )); + + return new TransactionValidator(rules); + } + + @Bean + public TransactionReceiptValidator transactionReceiptValidator() { + + List rules = Collections.singletonList( + new ReceiptValidityRule() + ); + + return new TransactionReceiptValidator(rules); + } + @Bean @Lazy public PeerSource peerSource() { 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 40d3a76681..254b272a95 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -35,8 +35,8 @@ import org.ethereum.net.rlpx.Node; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.BlockCustomHashRule; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockCustomHashRule; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; 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 a886535f91..49e303a4bc 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 @@ -26,7 +26,7 @@ import org.ethereum.db.BlockStore; import org.ethereum.mine.EthashMiner; import org.ethereum.mine.MinerIfc; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java index c04867f577..36540595a0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java @@ -17,19 +17,16 @@ */ package org.ethereum.config.blockchain; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainConfig; import org.ethereum.core.BlockHeader; import org.ethereum.core.Transaction; -import org.ethereum.validator.BlockHeaderRule; -import org.ethereum.validator.BlockHeaderValidator; -import org.ethereum.validator.ExtraDataPresenceRule; +import org.ethereum.validator.block.BlockHeaderRule; +import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.block.ExtraDataPresenceRule; import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; -import java.util.Arrays; -import java.util.List; /** * Created by Stan Reshetnyk on 26.12.16. 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 2ce71310e0..f9fb3ef678 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 @@ -29,7 +29,7 @@ import org.ethereum.db.BlockStore; import org.ethereum.mine.MinerIfc; import org.ethereum.util.Utils; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java index 6f012286a9..306ca0a2e3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java @@ -19,14 +19,10 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainConfig; -import org.ethereum.validator.BlockCustomHashRule; -import org.ethereum.validator.BlockHeaderRule; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockCustomHashRule; +import org.ethereum.validator.block.BlockHeaderValidator; import org.spongycastle.util.encoders.Hex; -import java.util.Arrays; -import java.util.List; - /** * Created by Anton Nashatyrev on 21.11.2016. */ diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 0c0febc5eb..2f6fea55d9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -29,8 +29,8 @@ import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.manager.AdminInfo; import org.ethereum.util.*; -import org.ethereum.validator.DependentBlockHeaderRule; -import org.ethereum.validator.ParentBlockHeaderValidator; +import org.ethereum.validator.block.DependentBlockHeaderRule; +import org.ethereum.validator.block.ParentBlockHeaderValidator; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.slf4j.Logger; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 9363df46b5..6f3d52b8ec 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -40,6 +40,10 @@ import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; +import org.ethereum.validator.EntityValidator; +import org.ethereum.validator.transaction.TransactionReceiptValidator; +import org.ethereum.validator.transaction.TransactionRule; +import org.ethereum.validator.transaction.TransactionValidator; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,6 +84,12 @@ public TransactionSortedSet() { @Autowired private Blockchain blockchain; + @Autowired + private TransactionValidator transactionValidator; + + @Autowired + private TransactionReceiptValidator receiptValidator; + private BlockStore blockStore; private TransactionStore transactionStore; @@ -197,7 +207,8 @@ public synchronized List addPendingTransactions(List t } protected boolean receiptIsValid(TransactionReceipt receipt) { - return receipt.isValid(); + EntityValidator.ValidationResult res = receiptValidator.validate(receipt); + return res.success; } public synchronized void trackTransaction(Transaction tx) { @@ -237,13 +248,13 @@ private TransactionReceipt addPendingTransactionImpl(final Transaction tx) { TransactionReceipt newReceipt = new TransactionReceipt(); newReceipt.setTransaction(tx); - String err = validate(tx); + TransactionRule.ValidationResult res = transactionValidator.validate(tx); TransactionReceipt txReceipt; - if (err != null) { - txReceipt = createDroppedReceipt(tx, err); - } else { + if (res.success) { txReceipt = executeTx(tx); + } else { + txReceipt = createDroppedReceipt(tx, res.error); } if (!receiptIsValid(txReceipt)) { @@ -471,4 +482,12 @@ public void setBlockchain(BlockchainImpl blockchain) { public void setCommonConfig(CommonConfig commonConfig) { this.commonConfig = commonConfig; } + + public void setTransactionValidator(TransactionValidator transactionValidator) { + this.transactionValidator = transactionValidator; + } + + public void setReceiptValidator(TransactionReceiptValidator receiptValidator) { + this.receiptValidator = receiptValidator; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java index 555c795f21..5614fddde0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java @@ -22,7 +22,7 @@ import org.ethereum.core.*; import org.ethereum.db.DbFlushManager; import org.ethereum.util.*; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java index 2733bb121e..ded2e0b5f8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java @@ -35,8 +35,8 @@ import org.ethereum.sync.PeerState; import org.ethereum.sync.SyncStatistics; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.BlockHeaderRule; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderRule; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java index 9469af55bd..0513b7130f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java @@ -24,7 +24,7 @@ import org.ethereum.db.IndexedBlockStore; import org.ethereum.net.server.Channel; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java index e38f9e0b90..17e6c80bc7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java @@ -22,8 +22,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.ethereum.core.*; import org.ethereum.net.server.Channel; -import org.ethereum.util.ByteArrayMap; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java index 45fcb10eb0..a607f037ac 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java @@ -20,7 +20,7 @@ import org.ethereum.core.BlockHeaderWrapper; import org.ethereum.core.BlockWrapper; import org.ethereum.db.IndexedBlockStore; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java index f36c2c3ccc..dff654353a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java @@ -25,7 +25,7 @@ import org.ethereum.db.IndexedBlockStore; import org.ethereum.net.server.Channel; import org.ethereum.net.server.ChannelManager; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java index 2bed9b2837..d5c8b7107f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java @@ -26,7 +26,7 @@ import org.ethereum.net.server.Channel; import org.ethereum.net.server.ChannelManager; import org.ethereum.util.ExecutorPipeline; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index ca1b76a081..f6a6893f15 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -37,10 +37,9 @@ import org.ethereum.solidity.compiler.CompilationResult; import org.ethereum.solidity.compiler.CompilationResult.ContractMetadata; import org.ethereum.solidity.compiler.SolidityCompiler; -import org.ethereum.sync.SyncManager; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.DataWord; import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; @@ -518,6 +517,10 @@ private BlockchainImpl createBlockchain(Genesis genesis) { pendingState = new PendingStateImpl(listener); pendingState.setBlockchain(blockchain); + CommonConfig config = CommonConfig.getDefault(); + pendingState.setReceiptValidator(config.transactionReceiptValidator()); + pendingState.setTransactionValidator(config.transactionValidator() + ); blockchain.setPendingState(pendingState); Genesis.populateRepository(repository, genesis); diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/EntityRule.java similarity index 70% rename from ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/EntityRule.java index 35b151a7b0..ab1832faa6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/EntityRule.java @@ -17,28 +17,19 @@ */ package org.ethereum.validator; -import org.ethereum.core.BlockHeader; import org.slf4j.Logger; /** - * Parent class for {@link BlockHeader} validators - * - * @author Mikhail Kalinin - * @since 02.09.2015 + * Parent class for E class validators */ -public abstract class BlockHeaderRule extends AbstractValidationRule { - - @Override - public Class getEntityClass() { - return BlockHeader.class; - } +public abstract class EntityRule extends AbstractValidationRule { /** - * Runs header validation and returns its result + * Runs E validation and returns its result * - * @param header block header + * @param entity of E class */ - abstract public ValidationResult validate(BlockHeader header); + abstract public ValidationResult validate(E entity); protected ValidationResult fault(String error) { return new ValidationResult(false, error); @@ -46,10 +37,10 @@ protected ValidationResult fault(String error) { public static final ValidationResult Success = new ValidationResult(true, null); - public boolean validateAndLog(BlockHeader header, Logger logger) { - ValidationResult result = validate(header); + public boolean validateAndLog(E entity, Logger logger) { + ValidationResult result = validate(entity); if (!result.success && logger.isErrorEnabled()) { - logger.warn("{} invalid {}", getEntityClass(), result.error); + logger.warn("{} invalid {}", entity.getClass(), result.error); } return result.success; } diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java new file mode 100644 index 0000000000..20e335c09b --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator; + +import java.util.Arrays; +import java.util.List; + +/** + * Composite Entity validator + * aggregating list of simple validation rules + */ +public abstract class EntityValidator, E> extends EntityRule { + + protected List rules; + + public EntityValidator(List rules) { + this.rules = rules; + } + + @SafeVarargs + public EntityValidator(R ...rules) { + this.rules = Arrays.asList(rules); + } + + public void reInit(List rules) { + this.rules = rules; + } + + @Override + public ValidationResult validate(E entity) { + for (R rule : rules) { + ValidationResult result = rule.validate(entity); + if (!result.success) { + return result; + } + } + return Success; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/BestNumberRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/BestNumberRule.java similarity index 98% rename from ethereumj-core/src/main/java/org/ethereum/validator/BestNumberRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/BestNumberRule.java index b233ef2a01..292709466a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/BestNumberRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/BestNumberRule.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.config.Constants; import org.ethereum.config.SystemProperties; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/BlockCustomHashRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockCustomHashRule.java similarity index 97% rename from ethereumj-core/src/main/java/org/ethereum/validator/BlockCustomHashRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/BlockCustomHashRule.java index 2154ff37f0..566eab4889 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/BlockCustomHashRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockCustomHashRule.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; import org.ethereum.util.FastByteComparisons; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/BlockHashRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHashRule.java similarity index 98% rename from ethereumj-core/src/main/java/org/ethereum/validator/BlockHashRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHashRule.java index 3a0d08cfb8..4565920ceb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/BlockHashRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHashRule.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainNetConfig; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java new file mode 100644 index 0000000000..89268f9f40 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.block; + +import org.ethereum.core.BlockHeader; +import org.ethereum.validator.EntityRule; +import org.slf4j.Logger; + +/** + * Parent class for {@link BlockHeader} validators + * + * @author Mikhail Kalinin + * @since 02.09.2015 + */ +public abstract class BlockHeaderRule extends EntityRule { + + @Override + public Class getEntityClass() { + return BlockHeader.class; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderValidator.java similarity index 69% rename from ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderValidator.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderValidator.java index ada49c4644..5567312165 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderValidator.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderValidator.java @@ -15,11 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.EntityValidator; -import java.util.Arrays; import java.util.List; /** @@ -29,26 +29,18 @@ * @author Mikhail Kalinin * @since 02.09.2015 */ -public class BlockHeaderValidator extends BlockHeaderRule { - - private List rules; +public class BlockHeaderValidator extends EntityValidator { public BlockHeaderValidator(List rules) { - this.rules = rules; + super(rules); } public BlockHeaderValidator(BlockHeaderRule ...rules) { - this.rules = Arrays.asList(rules); + super(rules); } @Override - public ValidationResult validate(BlockHeader header) { - for (BlockHeaderRule rule : rules) { - ValidationResult result = rule.validate(header); - if (!result.success) { - return result; - } - } - return Success; + public Class getEntityClass() { + return BlockHeader.class; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRule.java index c5df953c63..a6dfd0659a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRule.java @@ -15,9 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.AbstractValidationRule; import org.slf4j.Logger; import java.util.LinkedList; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRuleAdapter.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRuleAdapter.java similarity index 96% rename from ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRuleAdapter.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRuleAdapter.java index 438f24c4bf..cbb46655c7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRuleAdapter.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRuleAdapter.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/DifficultyRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/DifficultyRule.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/DifficultyRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/DifficultyRule.java index db7e368f30..8a549ab737 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/DifficultyRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/DifficultyRule.java @@ -15,10 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.config.SystemProperties; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.DependentBlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataPresenceRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataPresenceRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataPresenceRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataPresenceRule.java index 31a49546da..0962b275f2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataPresenceRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataPresenceRule.java @@ -15,11 +15,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; +import org.ethereum.validator.block.BlockHeaderRule; import org.spongycastle.util.encoders.Hex; /** diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataRule.java index c23b548b5b..b347078722 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataRule.java @@ -15,11 +15,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.config.Constants; import org.ethereum.config.SystemProperties; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.BlockHeaderRule; /** * Checks {@link BlockHeader#extraData} size against {@link Constants#getMAXIMUM_EXTRA_DATA_SIZE} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/GasLimitRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/GasLimitRule.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/GasLimitRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/GasLimitRule.java index 799b340e5c..9a2ec2a5c5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/GasLimitRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/GasLimitRule.java @@ -15,11 +15,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.config.SystemProperties; import org.ethereum.config.Constants; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.BlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/GasValueRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/GasValueRule.java similarity index 93% rename from ethereumj-core/src/main/java/org/ethereum/validator/GasValueRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/GasValueRule.java index c5aa8a72a6..07da81ebc8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/GasValueRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/GasValueRule.java @@ -15,9 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.BlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/ParentBlockHeaderValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentBlockHeaderValidator.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/ParentBlockHeaderValidator.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/ParentBlockHeaderValidator.java index 35462e4052..934bd43a2e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/ParentBlockHeaderValidator.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentBlockHeaderValidator.java @@ -15,9 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.DependentBlockHeaderRule; import java.util.List; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/ParentGasLimitRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentGasLimitRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/ParentGasLimitRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/ParentGasLimitRule.java index e72965aeb2..126884ffac 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/ParentGasLimitRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentGasLimitRule.java @@ -15,10 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.config.SystemProperties; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.DependentBlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/ParentNumberRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentNumberRule.java similarity index 93% rename from ethereumj-core/src/main/java/org/ethereum/validator/ParentNumberRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/ParentNumberRule.java index 77762d9a6b..660c7a1386 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/ParentNumberRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentNumberRule.java @@ -15,9 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; +import org.ethereum.validator.block.DependentBlockHeaderRule; /** * Checks if {@link BlockHeader#number} == {@link BlockHeader#number} + 1 of parent's block diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/ProofOfWorkRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/ProofOfWorkRule.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/ProofOfWorkRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/block/ProofOfWorkRule.java index 2c4687272d..946ebc5160 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/ProofOfWorkRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/block/ProofOfWorkRule.java @@ -15,10 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator; +package org.ethereum.validator.block; import org.ethereum.core.BlockHeader; import org.ethereum.util.FastByteComparisons; +import org.ethereum.validator.block.BlockHeaderRule; /** * Checks proof value against its boundary for the block header diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java new file mode 100644 index 0000000000..8f9fa13693 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.casper.config.CasperProperties; +import org.ethereum.casper.core.CasperFacade; +import org.ethereum.core.TransactionReceipt; + +import java.util.Arrays; +import java.util.List; + +/** + * Checks {@link org.ethereum.core.TransactionReceipt} is from Casper contract vote + * if it is, the checks are over + * otherwise all other checks are applied + */ +public class ReceiptCasperVoteRule extends TransactionReceiptRule { + + private final byte[] CASPER_ADDRESS; + private List nextRules; + + public ReceiptCasperVoteRule(CasperProperties config, TransactionReceiptRule ...rules) { + this.CASPER_ADDRESS = config.getCasperAddress(); + this.nextRules = Arrays.asList(rules); + } + + @Override + public ValidationResult validate(TransactionReceipt receipt) { + boolean isCasperVote = CasperFacade.isVote(receipt.getTransaction(), CASPER_ADDRESS); + if (isCasperVote) { + if (receipt.isSuccessful()) { + return Success; + } else { + return fault("Receipt is not correct: Unsuccessful casper vote"); + } + } else { + return new TransactionReceiptValidator(nextRules).validate(receipt); + } + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java new file mode 100644 index 0000000000..d48c1684d4 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.core.TransactionReceipt; + +/** + * Checks {@link org.ethereum.core.TransactionReceipt} shows something was done in VM with related tx + */ +public class ReceiptValidityRule extends TransactionReceiptRule { + + @Override + public ValidationResult validate(TransactionReceipt receipt) { + if (!receipt.isValid()) { + return fault("Receipt is invalid: 0 gas used"); + } + + return Success; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java new file mode 100644 index 0000000000..b041a45e1e --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.casper.config.CasperProperties; +import org.ethereum.casper.core.CasperFacade; +import org.ethereum.core.Transaction; + +import java.util.Arrays; +import java.util.List; + +/** + * Checks {@link Transaction} is Casper contract vote + * if it is, the checks are over + * otherwise all other checks are applied + */ +public class TransactionCasperVoteRule extends TransactionRule { + + private final byte[] CASPER_ADDRESS; + private List nextRules; + + public TransactionCasperVoteRule(CasperProperties config, TransactionRule ...rules) { + this.CASPER_ADDRESS = config.getCasperAddress(); + this.nextRules = Arrays.asList(rules); + } + + + @Override + public ValidationResult validate(Transaction transaction) { + boolean isCasperVote = CasperFacade.isVote(transaction, CASPER_ADDRESS); + if (isCasperVote) { + return Success; + } else { + return new TransactionValidator(nextRules).validate(transaction); + } + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java new file mode 100644 index 0000000000..553de0192f --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.core.Transaction; + +import java.math.BigInteger; + +/** + * Checks {@link org.ethereum.core.Transaction} fields are with correct length and in allowable range + */ +public class TransactionFieldsRule extends TransactionRule { + + @Override + public ValidationResult validate(Transaction transaction) { + try { + transaction.verify(); + } catch (Exception ex) { + return fault(ex.getMessage()); + } + + return Success; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java new file mode 100644 index 0000000000..e4d076a22f --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.config.SystemProperties; +import org.ethereum.core.Transaction; +import org.ethereum.util.ByteUtil; + +import java.math.BigInteger; + +/** + * Checks {@link Transaction} fields are with correct length and in allowable range + */ +public class TransactionMineGasPriceRule extends TransactionRule { + + private final BigInteger MIN_GAS_PRICE; + + public TransactionMineGasPriceRule(SystemProperties config) { + this.MIN_GAS_PRICE = config.getMineMinGasPrice(); + } + + @Override + public ValidationResult validate(Transaction transaction) { + if (MIN_GAS_PRICE.compareTo(ByteUtil.bytesToBigInteger(transaction.getGasPrice())) >= 0) { + return fault("Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(transaction.getGasPrice())); + } + + return Success; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java new file mode 100644 index 0000000000..5019dc346f --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.core.TransactionReceipt; +import org.ethereum.validator.EntityRule; +/** + * Parent class for {@link org.ethereum.core.TransactionReceipt} validators + */ +public abstract class TransactionReceiptRule extends EntityRule { + @Override + public Class getEntityClass() { + return TransactionReceipt.class; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java new file mode 100644 index 0000000000..7d1cf5fa5d --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.core.TransactionReceipt; +import org.ethereum.validator.EntityValidator; + +import java.util.List; + +/** + * Composite {@link TransactionReceipt} validator + * aggregating list of simple validation rules + */ +public class TransactionReceiptValidator extends EntityValidator { + + public TransactionReceiptValidator(List rules) { + super(rules); + } + + public TransactionReceiptValidator(TransactionReceiptRule... rules) { + super(rules); + } + + @Override + public Class getEntityClass() { + return TransactionReceipt.class; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java new file mode 100644 index 0000000000..a8afa29464 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.core.Transaction; +import org.ethereum.validator.EntityRule; + +/** + * Parent class for {@link Transaction} validators + */ +public abstract class TransactionRule extends EntityRule { + @Override + public Class getEntityClass() { + return Transaction.class; + } +} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java new file mode 100644 index 0000000000..2c77e5d7e9 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.validator.transaction; + +import org.ethereum.core.Transaction; +import org.ethereum.validator.EntityValidator; + +import java.util.List; + +/** + * Composite {@link org.ethereum.core.Transaction} validator + * aggregating list of simple validation rules + */ +public class TransactionValidator extends EntityValidator { + + public TransactionValidator(List rules) { + super(rules); + } + + public TransactionValidator(TransactionRule... rules) { + super(rules); + } + + @Override + public Class getEntityClass() { + return Transaction.class; + } +} diff --git a/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java b/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java index 8821ea9784..229dfcd689 100644 --- a/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java +++ b/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java @@ -30,7 +30,7 @@ import org.ethereum.core.Transaction; import org.ethereum.db.BlockStore; import org.ethereum.mine.MinerIfc; -import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.block.BlockHeaderValidator; import java.math.BigInteger; import java.util.List; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java index b75e55c040..5a9d0fa10c 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java @@ -31,7 +31,7 @@ import org.ethereum.util.ByteUtil; import org.ethereum.util.blockchain.SolidityContract; import org.ethereum.util.blockchain.StandaloneBlockchain; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.*; @@ -895,8 +895,9 @@ public static BlockchainImpl createBlockchain(Genesis genesis) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); EthereumListenerAdapter listener = new EthereumListenerAdapter(); + CommonConfig config = new CommonConfig(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); + .withParentBlockHeaderValidator(config.parentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); @@ -905,6 +906,8 @@ public static BlockchainImpl createBlockchain(Genesis genesis) { PendingStateImpl pendingState = new PendingStateImpl(listener); pendingState.setBlockchain(blockchain); + pendingState.setReceiptValidator(config.transactionReceiptValidator()); + pendingState.setTransactionValidator(config.transactionValidator()); blockchain.setPendingState(pendingState); Repository track = repository.startTracking(); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java index ccb81b577f..d494a0811e 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java @@ -22,7 +22,7 @@ import org.ethereum.db.RepositoryRoot; import org.ethereum.db.IndexedBlockStore; import org.ethereum.listener.EthereumListenerAdapter; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.Before; import org.junit.Ignore; @@ -123,15 +123,18 @@ private Blockchain createBlockchain(Genesis genesis) { Repository repository = new RepositoryRoot(new HashMapDB()); ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); + CommonConfig config = new CommonConfig(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); + .withParentBlockHeaderValidator(config.parentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.byTest = true; PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter()); + pendingState.setReceiptValidator(config.transactionReceiptValidator()); + pendingState.setTransactionValidator(config.transactionValidator()); pendingState.setBlockchain(blockchain); blockchain.setPendingState(pendingState); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index e43781f29d..ff021d0486 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -21,7 +21,6 @@ import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperBlockchain; import org.ethereum.casper.core.CasperFacade; -import org.ethereum.casper.core.CasperPendingStateImpl; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; @@ -31,6 +30,7 @@ import org.ethereum.core.BlockchainImpl; import org.ethereum.core.EventDispatchThread; import org.ethereum.core.Genesis; +import org.ethereum.core.PendingStateImpl; import org.ethereum.core.Repository; import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutorFactory; @@ -52,7 +52,9 @@ import org.ethereum.manager.WorldManager; import org.ethereum.net.server.ChannelManager; import org.ethereum.util.blockchain.StandaloneBlockchain; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.transaction.TransactionReceiptValidator; +import org.ethereum.validator.transaction.TransactionValidator; import org.ethereum.vm.program.ProgramPrecompile; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.Before; @@ -74,7 +76,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; // We have all mocks here and not all of them are used in every test, so strict stubs should be turned off @RunWith(MockitoJUnitRunner.Silent.class) @@ -106,6 +107,12 @@ public SystemProperties systemProperties() { private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); + @Spy + TransactionValidator transactionValidator = commonConfig.transactionValidator(); + + @Spy + TransactionReceiptValidator receiptValidator = commonConfig.transactionReceiptValidator(); + @InjectMocks EthereumImpl ethereum = new EthereumImpl(systemProperties, defaultListener); @@ -115,7 +122,7 @@ public SystemProperties systemProperties() { Repository repository = new RepositoryWrapper(); @InjectMocks - CasperPendingStateImpl casperPendingState = new CasperPendingStateImpl(defaultListener); + PendingStateImpl casperPendingState = new PendingStateImpl(defaultListener); StandaloneBlockchain bc; @@ -194,6 +201,8 @@ private BlockchainImpl createBlockchain() { this.blockchain = (CasperBlockchain) bc.getBlockchain(); casper.setEthereum(ethereum); blockchain.setCasper(casper); + blockchain.setReceiptValidator(receiptValidator); + blockchain.setTransactionValidator(transactionValidator); Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); Mockito.when(worldManager.getBlockchain()).thenReturn(blockchain); Mockito.when(worldManager.getBlockStore()).thenReturn(blockchain.getBlockStore()); 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 9fdf981fd5..67aef40bab 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 @@ -33,7 +33,6 @@ import org.ethereum.jsontestsuite.suite.validators.RepositoryValidator; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.DataWord; import org.ethereum.vm.LogInfo; import org.ethereum.vm.VM; @@ -99,11 +98,14 @@ public List runTestCase(BlockTestCase testCase) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); + CommonConfig config = CommonConfig.getDefault(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(CommonConfig.getDefault().parentHeaderValidator()); + .withParentBlockHeaderValidator(config.parentHeaderValidator()); blockchain.byTest = true; PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter()); + pendingState.setTransactionValidator(config.transactionValidator()); + pendingState.setReceiptValidator(config.transactionReceiptValidator()); blockchain.setBestBlock(genesis); blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); diff --git a/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java b/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java index a001922fa3..8ff9cd69c2 100644 --- a/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java @@ -18,6 +18,7 @@ package org.ethereum.validator; import org.ethereum.core.Block; +import org.ethereum.validator.block.ProofOfWorkRule; import org.junit.Ignore; import org.junit.Test; import org.spongycastle.util.encoders.Hex; From 56f7d0440ed4ae764036fa34477d3c5907ee40fe Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 13 Mar 2018 15:58:55 +0300 Subject: [PATCH 43/67] Revert "Added validators for transaction and transaction receipt in PendingState" This reverts commit 2b1db0f0b6f8c6935782fb0890b8f860f29e90e7. --- .../casper/config/CasperBeanConfig.java | 8 +++ .../casper/config/CasperProperties.java | 6 ++ .../casper/core/CasperBlockchain.java | 39 ------------ .../casper/core/CasperPendingStateImpl.java | 63 +++++++++++++++++++ .../org/ethereum/config/BlockchainConfig.java | 2 +- .../org/ethereum/config/CommonConfig.java | 53 ++++------------ .../org/ethereum/config/SystemProperties.java | 4 +- .../config/blockchain/AbstractConfig.java | 2 +- .../config/blockchain/AbstractDaoConfig.java | 9 ++- .../config/blockchain/Eip150HFConfig.java | 2 +- .../config/blockchain/RopstenConfig.java | 8 ++- .../org/ethereum/core/BlockchainImpl.java | 4 +- .../org/ethereum/core/PendingStateImpl.java | 29 ++------- .../org/ethereum/manager/BlockLoader.java | 2 +- .../org/ethereum/net/eth/handler/Eth62.java | 4 +- .../ethereum/sync/BlockBodiesDownloader.java | 2 +- .../org/ethereum/sync/BlockDownloader.java | 3 +- .../org/ethereum/sync/FastSyncDownloader.java | 2 +- .../org/ethereum/sync/HeadersDownloader.java | 2 +- .../java/org/ethereum/sync/SyncManager.java | 2 +- .../util/blockchain/StandaloneBlockchain.java | 7 +-- .../validator/{block => }/BestNumberRule.java | 2 +- .../{block => }/BlockCustomHashRule.java | 2 +- .../validator/{block => }/BlockHashRule.java | 2 +- .../{EntityRule.java => BlockHeaderRule.java} | 25 +++++--- .../{block => }/BlockHeaderValidator.java | 22 ++++--- .../{block => }/DependentBlockHeaderRule.java | 3 +- .../DependentBlockHeaderRuleAdapter.java | 2 +- .../validator/{block => }/DifficultyRule.java | 3 +- .../ethereum/validator/EntityValidator.java | 54 ---------------- .../{block => }/ExtraDataPresenceRule.java | 3 +- .../validator/{block => }/ExtraDataRule.java | 3 +- .../validator/{block => }/GasLimitRule.java | 3 +- .../validator/{block => }/GasValueRule.java | 3 +- .../ParentBlockHeaderValidator.java | 3 +- .../{block => }/ParentGasLimitRule.java | 3 +- .../{block => }/ParentNumberRule.java | 3 +- .../{block => }/ProofOfWorkRule.java | 3 +- .../validator/block/BlockHeaderRule.java | 36 ----------- .../transaction/ReceiptCasperVoteRule.java | 55 ---------------- .../transaction/ReceiptValidityRule.java | 35 ----------- .../TransactionCasperVoteRule.java | 52 --------------- .../transaction/TransactionFieldsRule.java | 39 ------------ .../TransactionMineGasPriceRule.java | 45 ------------- .../transaction/TransactionReceiptRule.java | 30 --------- .../TransactionReceiptValidator.java | 43 ------------- .../transaction/TransactionRule.java | 31 --------- .../transaction/TransactionValidator.java | 43 ------------- .../blockchain/TestBlockchainConfig.java | 2 +- .../org/ethereum/core/ImportLightTest.java | 7 +-- .../core/PendingStateLongRunTest.java | 7 +-- .../org/ethereum/core/casper/CasperBase.java | 17 ++--- .../jsontestsuite/suite/TestRunner.java | 6 +- .../validator/ProofOfWorkRuleTest.java | 1 - 54 files changed, 181 insertions(+), 660 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/BestNumberRule.java (98%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/BlockCustomHashRule.java (97%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/BlockHashRule.java (98%) rename ethereumj-core/src/main/java/org/ethereum/validator/{EntityRule.java => BlockHeaderRule.java} (70%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/BlockHeaderValidator.java (69%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/DependentBlockHeaderRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/DependentBlockHeaderRuleAdapter.java (96%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/DifficultyRule.java (94%) delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/ExtraDataPresenceRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/ExtraDataRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/GasLimitRule.java (94%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/GasValueRule.java (93%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/ParentBlockHeaderValidator.java (94%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/ParentGasLimitRule.java (95%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/ParentNumberRule.java (93%) rename ethereumj-core/src/main/java/org/ethereum/validator/{block => }/ProofOfWorkRule.java (94%) delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java delete mode 100644 ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index ef1b6fa88d..40e7d91b0e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -17,12 +17,14 @@ */ package org.ethereum.casper.config; +import org.ethereum.casper.core.CasperPendingStateImpl; import org.ethereum.casper.manager.CasperWorldManager; import org.ethereum.casper.mine.CasperBlockMiner; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.Blockchain; +import org.ethereum.core.PendingState; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutor; @@ -79,6 +81,12 @@ public WorldManager worldManager() { return new CasperWorldManager(systemProperties(), repository(), blockchain()); } + @Bean + @Override + public PendingState pendingState() { + return new CasperPendingStateImpl(ethereumListener); + } + @Bean @Override public BlockMiner blockMiner() { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java index 21bf0b4515..0101bd5bc8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java @@ -1,7 +1,13 @@ package org.ethereum.casper.config; +import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.casper.config.net.CasperTestNetConfig; +import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.SystemProperties; +import org.ethereum.core.genesis.GenesisConfig; import org.ethereum.util.ByteUtil; +import org.ethereum.validator.BlockCustomHashRule; +import org.ethereum.validator.BlockHeaderValidator; import java.io.BufferedReader; import java.io.IOException; diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 807b344ffd..3ba776814d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -33,14 +33,6 @@ import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; -import org.ethereum.validator.transaction.ReceiptCasperVoteRule; -import org.ethereum.validator.transaction.ReceiptValidityRule; -import org.ethereum.validator.transaction.TransactionCasperVoteRule; -import org.ethereum.validator.transaction.TransactionFieldsRule; -import org.ethereum.validator.transaction.TransactionMineGasPriceRule; -import org.ethereum.validator.transaction.TransactionReceiptValidator; -import org.ethereum.validator.transaction.TransactionRule; -import org.ethereum.validator.transaction.TransactionValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.Arrays; @@ -49,7 +41,6 @@ import java.math.BigInteger; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -68,12 +59,6 @@ public class CasperBlockchain extends BlockchainImpl { @Autowired private CasperFacade casper; - @Autowired - private TransactionValidator transactionValidator; - - @Autowired - private TransactionReceiptValidator receiptValidator; - private static final Logger logger = LoggerFactory.getLogger("blockchain"); private static final Logger stateLogger = LoggerFactory.getLogger("state"); @@ -379,22 +364,6 @@ coinbase, txTrack, blockStore, getProgramInvokeFactory(), block, listener, 0) track.addBalance(casperAddress, track.getBalance(casperAddress).negate()); track.addBalance(casperAddress, BigInteger.valueOf(10).pow(25)); }); - updateValidators(); // as casper contract is in place - } - - private void updateValidators() { - // Update transaction validator as casper txs are applied - transactionValidator.reInit( - new ArrayList() {{ - add(new TransactionFieldsRule()); - add(new TransactionCasperVoteRule((CasperProperties) config, new TransactionMineGasPriceRule(config))); - }} - ); - - // Update transaction receipts validator - receiptValidator.reInit(Collections.singletonList( - new ReceiptCasperVoteRule((CasperProperties) config, new ReceiptValidityRule())) - ); } /** @@ -478,12 +447,4 @@ private BigInteger getPoWDifficulty(final Block block) { public void setCasper(CasperFacade casper) { this.casper = casper; } - - public void setTransactionValidator(TransactionValidator transactionValidator) { - this.transactionValidator = transactionValidator; - } - - public void setReceiptValidator(TransactionReceiptValidator receiptValidator) { - this.receiptValidator = receiptValidator; - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java new file mode 100644 index 0000000000..99220e5eb2 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.core; + +import org.ethereum.casper.config.CasperProperties; +import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionReceipt; +import org.ethereum.listener.EthereumListener; +import org.ethereum.util.ByteUtil; + +public class CasperPendingStateImpl extends PendingStateImpl { + + public CasperPendingStateImpl(EthereumListener listener) { + super(listener); + } + + @Override + protected boolean receiptIsValid(TransactionReceipt receipt) { + boolean isValid = super.receiptIsValid(receipt); + if (isValid) { + return true; + } else if (CasperFacade.isVote(receipt.getTransaction(), ((CasperProperties) config).getCasperAddress())) { + return receipt.isSuccessful(); + } + + return false; + } + + @Override + protected String validate(Transaction tx) { + try { + tx.verify(); + } catch (Exception e) { + return String.format("Invalid transaction: %s", e.getMessage()); + } + + if (CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress())) { + return null; // Doesn't require more checks + } + + if (config.getMineMinGasPrice().compareTo(ByteUtil.bytesToBigInteger(tx.getGasPrice())) > 0) { + return "Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(tx.getGasPrice()); + } + + return null; + } +} 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 bc33fc161a..65a7462712 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/BlockchainConfig.java @@ -21,7 +21,7 @@ import org.ethereum.core.*; import org.ethereum.db.BlockStore; import org.ethereum.mine.MinerIfc; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index 0507d06003..c70b4be9a4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -28,25 +28,18 @@ import org.ethereum.manager.WorldManager; import org.ethereum.mine.BlockMiner; import org.ethereum.sync.FastSyncManager; -import org.ethereum.validator.block.BlockHashRule; -import org.ethereum.validator.block.BlockHeaderRule; -import org.ethereum.validator.block.BlockHeaderValidator; -import org.ethereum.validator.block.DependentBlockHeaderRule; -import org.ethereum.validator.block.DifficultyRule; -import org.ethereum.validator.block.ExtraDataRule; -import org.ethereum.validator.block.GasLimitRule; -import org.ethereum.validator.block.GasValueRule; -import org.ethereum.validator.block.ParentBlockHeaderValidator; -import org.ethereum.validator.block.ParentGasLimitRule; -import org.ethereum.validator.block.ParentNumberRule; -import org.ethereum.validator.block.ProofOfWorkRule; -import org.ethereum.validator.transaction.ReceiptValidityRule; -import org.ethereum.validator.transaction.TransactionFieldsRule; -import org.ethereum.validator.transaction.TransactionMineGasPriceRule; -import org.ethereum.validator.transaction.TransactionReceiptRule; -import org.ethereum.validator.transaction.TransactionReceiptValidator; -import org.ethereum.validator.transaction.TransactionRule; -import org.ethereum.validator.transaction.TransactionValidator; +import org.ethereum.validator.BlockHashRule; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.DependentBlockHeaderRule; +import org.ethereum.validator.DifficultyRule; +import org.ethereum.validator.ExtraDataRule; +import org.ethereum.validator.GasLimitRule; +import org.ethereum.validator.GasValueRule; +import org.ethereum.validator.ParentBlockHeaderValidator; +import org.ethereum.validator.ParentGasLimitRule; +import org.ethereum.validator.ParentNumberRule; +import org.ethereum.validator.ProofOfWorkRule; import org.ethereum.vm.DataWord; import org.ethereum.vm.program.ProgramPrecompile; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; @@ -59,7 +52,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -287,27 +279,6 @@ public ParentBlockHeaderValidator parentHeaderValidator() { return new ParentBlockHeaderValidator(rules); } - @Bean - public TransactionValidator transactionValidator() { - - List rules = new ArrayList<>(asList( - new TransactionFieldsRule(), - new TransactionMineGasPriceRule(systemProperties()) - )); - - return new TransactionValidator(rules); - } - - @Bean - public TransactionReceiptValidator transactionReceiptValidator() { - - List rules = Collections.singletonList( - new ReceiptValidityRule() - ); - - return new TransactionReceiptValidator(rules); - } - @Bean @Lazy public PeerSource peerSource() { 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 254b272a95..40d3a76681 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -35,8 +35,8 @@ import org.ethereum.net.rlpx.Node; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.block.BlockCustomHashRule; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockCustomHashRule; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; 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 49e303a4bc..a886535f91 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 @@ -26,7 +26,7 @@ import org.ethereum.db.BlockStore; import org.ethereum.mine.EthashMiner; import org.ethereum.mine.MinerIfc; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java index 36540595a0..c04867f577 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/AbstractDaoConfig.java @@ -17,16 +17,19 @@ */ package org.ethereum.config.blockchain; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainConfig; import org.ethereum.core.BlockHeader; import org.ethereum.core.Transaction; -import org.ethereum.validator.block.BlockHeaderRule; -import org.ethereum.validator.block.BlockHeaderValidator; -import org.ethereum.validator.block.ExtraDataPresenceRule; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; +import org.ethereum.validator.ExtraDataPresenceRule; import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; /** * Created by Stan Reshetnyk on 26.12.16. 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 f9fb3ef678..2ce71310e0 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 @@ -29,7 +29,7 @@ import org.ethereum.db.BlockStore; import org.ethereum.mine.MinerIfc; import org.ethereum.util.Utils; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java index 306ca0a2e3..6f012286a9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/RopstenConfig.java @@ -19,10 +19,14 @@ import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainConfig; -import org.ethereum.validator.block.BlockCustomHashRule; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockCustomHashRule; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; import org.spongycastle.util.encoders.Hex; +import java.util.Arrays; +import java.util.List; + /** * Created by Anton Nashatyrev on 21.11.2016. */ diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 2f6fea55d9..0c0febc5eb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -29,8 +29,8 @@ import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.manager.AdminInfo; import org.ethereum.util.*; -import org.ethereum.validator.block.DependentBlockHeaderRule; -import org.ethereum.validator.block.ParentBlockHeaderValidator; +import org.ethereum.validator.DependentBlockHeaderRule; +import org.ethereum.validator.ParentBlockHeaderValidator; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.slf4j.Logger; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 6f3d52b8ec..9363df46b5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -40,10 +40,6 @@ import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.EntityValidator; -import org.ethereum.validator.transaction.TransactionReceiptValidator; -import org.ethereum.validator.transaction.TransactionRule; -import org.ethereum.validator.transaction.TransactionValidator; import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,12 +80,6 @@ public TransactionSortedSet() { @Autowired private Blockchain blockchain; - @Autowired - private TransactionValidator transactionValidator; - - @Autowired - private TransactionReceiptValidator receiptValidator; - private BlockStore blockStore; private TransactionStore transactionStore; @@ -207,8 +197,7 @@ public synchronized List addPendingTransactions(List t } protected boolean receiptIsValid(TransactionReceipt receipt) { - EntityValidator.ValidationResult res = receiptValidator.validate(receipt); - return res.success; + return receipt.isValid(); } public synchronized void trackTransaction(Transaction tx) { @@ -248,13 +237,13 @@ private TransactionReceipt addPendingTransactionImpl(final Transaction tx) { TransactionReceipt newReceipt = new TransactionReceipt(); newReceipt.setTransaction(tx); - TransactionRule.ValidationResult res = transactionValidator.validate(tx); + String err = validate(tx); TransactionReceipt txReceipt; - if (res.success) { - txReceipt = executeTx(tx); + if (err != null) { + txReceipt = createDroppedReceipt(tx, err); } else { - txReceipt = createDroppedReceipt(tx, res.error); + txReceipt = executeTx(tx); } if (!receiptIsValid(txReceipt)) { @@ -482,12 +471,4 @@ public void setBlockchain(BlockchainImpl blockchain) { public void setCommonConfig(CommonConfig commonConfig) { this.commonConfig = commonConfig; } - - public void setTransactionValidator(TransactionValidator transactionValidator) { - this.transactionValidator = transactionValidator; - } - - public void setReceiptValidator(TransactionReceiptValidator receiptValidator) { - this.receiptValidator = receiptValidator; - } } diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java index 5614fddde0..555c795f21 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/BlockLoader.java @@ -22,7 +22,7 @@ import org.ethereum.core.*; import org.ethereum.db.DbFlushManager; import org.ethereum.util.*; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java index ded2e0b5f8..2733bb121e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth62.java @@ -35,8 +35,8 @@ import org.ethereum.sync.PeerState; import org.ethereum.sync.SyncStatistics; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.block.BlockHeaderRule; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderRule; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java index 0513b7130f..9469af55bd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/BlockBodiesDownloader.java @@ -24,7 +24,7 @@ import org.ethereum.db.IndexedBlockStore; import org.ethereum.net.server.Channel; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java index 17e6c80bc7..e38f9e0b90 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/BlockDownloader.java @@ -22,7 +22,8 @@ import com.google.common.util.concurrent.ListenableFuture; import org.ethereum.core.*; import org.ethereum.net.server.Channel; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.util.ByteArrayMap; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java index a607f037ac..45fcb10eb0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/FastSyncDownloader.java @@ -20,7 +20,7 @@ import org.ethereum.core.BlockHeaderWrapper; import org.ethereum.core.BlockWrapper; import org.ethereum.db.IndexedBlockStore; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java b/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java index dff654353a..f36c2c3ccc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/HeadersDownloader.java @@ -25,7 +25,7 @@ import org.ethereum.db.IndexedBlockStore; import org.ethereum.net.server.Channel; import org.ethereum.net.server.ChannelManager; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java index d5c8b7107f..2bed9b2837 100644 --- a/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/sync/SyncManager.java @@ -26,7 +26,7 @@ import org.ethereum.net.server.Channel; import org.ethereum.net.server.ChannelManager; import org.ethereum.util.ExecutorPipeline; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index f6a6893f15..ca1b76a081 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -37,9 +37,10 @@ import org.ethereum.solidity.compiler.CompilationResult; import org.ethereum.solidity.compiler.CompilationResult.ContractMetadata; import org.ethereum.solidity.compiler.SolidityCompiler; +import org.ethereum.sync.SyncManager; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.DataWord; import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; @@ -517,10 +518,6 @@ private BlockchainImpl createBlockchain(Genesis genesis) { pendingState = new PendingStateImpl(listener); pendingState.setBlockchain(blockchain); - CommonConfig config = CommonConfig.getDefault(); - pendingState.setReceiptValidator(config.transactionReceiptValidator()); - pendingState.setTransactionValidator(config.transactionValidator() - ); blockchain.setPendingState(pendingState); Genesis.populateRepository(repository, genesis); diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/BestNumberRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/BestNumberRule.java similarity index 98% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/BestNumberRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/BestNumberRule.java index 292709466a..b233ef2a01 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/BestNumberRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/BestNumberRule.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.config.Constants; import org.ethereum.config.SystemProperties; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockCustomHashRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/BlockCustomHashRule.java similarity index 97% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/BlockCustomHashRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/BlockCustomHashRule.java index 566eab4889..2154ff37f0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockCustomHashRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/BlockCustomHashRule.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; import org.ethereum.util.FastByteComparisons; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHashRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/BlockHashRule.java similarity index 98% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHashRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/BlockHashRule.java index 4565920ceb..3a0d08cfb8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHashRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/BlockHashRule.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainNetConfig; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/EntityRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderRule.java similarity index 70% rename from ethereumj-core/src/main/java/org/ethereum/validator/EntityRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderRule.java index ab1832faa6..35b151a7b0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/EntityRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderRule.java @@ -17,19 +17,28 @@ */ package org.ethereum.validator; +import org.ethereum.core.BlockHeader; import org.slf4j.Logger; /** - * Parent class for E class validators + * Parent class for {@link BlockHeader} validators + * + * @author Mikhail Kalinin + * @since 02.09.2015 */ -public abstract class EntityRule extends AbstractValidationRule { +public abstract class BlockHeaderRule extends AbstractValidationRule { + + @Override + public Class getEntityClass() { + return BlockHeader.class; + } /** - * Runs E validation and returns its result + * Runs header validation and returns its result * - * @param entity of E class + * @param header block header */ - abstract public ValidationResult validate(E entity); + abstract public ValidationResult validate(BlockHeader header); protected ValidationResult fault(String error) { return new ValidationResult(false, error); @@ -37,10 +46,10 @@ protected ValidationResult fault(String error) { public static final ValidationResult Success = new ValidationResult(true, null); - public boolean validateAndLog(E entity, Logger logger) { - ValidationResult result = validate(entity); + public boolean validateAndLog(BlockHeader header, Logger logger) { + ValidationResult result = validate(header); if (!result.success && logger.isErrorEnabled()) { - logger.warn("{} invalid {}", entity.getClass(), result.error); + logger.warn("{} invalid {}", getEntityClass(), result.error); } return result.success; } diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderValidator.java similarity index 69% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderValidator.java rename to ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderValidator.java index 5567312165..ada49c4644 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderValidator.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/BlockHeaderValidator.java @@ -15,11 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.EntityValidator; +import java.util.Arrays; import java.util.List; /** @@ -29,18 +29,26 @@ * @author Mikhail Kalinin * @since 02.09.2015 */ -public class BlockHeaderValidator extends EntityValidator { +public class BlockHeaderValidator extends BlockHeaderRule { + + private List rules; public BlockHeaderValidator(List rules) { - super(rules); + this.rules = rules; } public BlockHeaderValidator(BlockHeaderRule ...rules) { - super(rules); + this.rules = Arrays.asList(rules); } @Override - public Class getEntityClass() { - return BlockHeader.class; + public ValidationResult validate(BlockHeader header) { + for (BlockHeaderRule rule : rules) { + ValidationResult result = rule.validate(header); + if (!result.success) { + return result; + } + } + return Success; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRule.java index a6dfd0659a..c5df953c63 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRule.java @@ -15,10 +15,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.AbstractValidationRule; import org.slf4j.Logger; import java.util.LinkedList; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRuleAdapter.java b/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRuleAdapter.java similarity index 96% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRuleAdapter.java rename to ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRuleAdapter.java index cbb46655c7..438f24c4bf 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/DependentBlockHeaderRuleAdapter.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/DependentBlockHeaderRuleAdapter.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/DifficultyRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/DifficultyRule.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/DifficultyRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/DifficultyRule.java index 8a549ab737..db7e368f30 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/DifficultyRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/DifficultyRule.java @@ -15,11 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.config.SystemProperties; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.DependentBlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java deleted file mode 100644 index 20e335c09b..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/EntityValidator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator; - -import java.util.Arrays; -import java.util.List; - -/** - * Composite Entity validator - * aggregating list of simple validation rules - */ -public abstract class EntityValidator, E> extends EntityRule { - - protected List rules; - - public EntityValidator(List rules) { - this.rules = rules; - } - - @SafeVarargs - public EntityValidator(R ...rules) { - this.rules = Arrays.asList(rules); - } - - public void reInit(List rules) { - this.rules = rules; - } - - @Override - public ValidationResult validate(E entity) { - for (R rule : rules) { - ValidationResult result = rule.validate(entity); - if (!result.success) { - return result; - } - } - return Success; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataPresenceRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataPresenceRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataPresenceRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataPresenceRule.java index 0962b275f2..31a49546da 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataPresenceRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataPresenceRule.java @@ -15,12 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.block.BlockHeaderRule; import org.spongycastle.util.encoders.Hex; /** diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataRule.java index b347078722..c23b548b5b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/ExtraDataRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/ExtraDataRule.java @@ -15,12 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.config.Constants; import org.ethereum.config.SystemProperties; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.BlockHeaderRule; /** * Checks {@link BlockHeader#extraData} size against {@link Constants#getMAXIMUM_EXTRA_DATA_SIZE} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/GasLimitRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/GasLimitRule.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/GasLimitRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/GasLimitRule.java index 9a2ec2a5c5..799b340e5c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/GasLimitRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/GasLimitRule.java @@ -15,12 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.config.SystemProperties; import org.ethereum.config.Constants; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.BlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/GasValueRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/GasValueRule.java similarity index 93% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/GasValueRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/GasValueRule.java index 07da81ebc8..c5aa8a72a6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/GasValueRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/GasValueRule.java @@ -15,10 +15,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.BlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentBlockHeaderValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/ParentBlockHeaderValidator.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/ParentBlockHeaderValidator.java rename to ethereumj-core/src/main/java/org/ethereum/validator/ParentBlockHeaderValidator.java index 934bd43a2e..35462e4052 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentBlockHeaderValidator.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/ParentBlockHeaderValidator.java @@ -15,10 +15,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.DependentBlockHeaderRule; import java.util.List; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentGasLimitRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/ParentGasLimitRule.java similarity index 95% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/ParentGasLimitRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/ParentGasLimitRule.java index 126884ffac..e72965aeb2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentGasLimitRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/ParentGasLimitRule.java @@ -15,11 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.config.SystemProperties; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.DependentBlockHeaderRule; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentNumberRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/ParentNumberRule.java similarity index 93% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/ParentNumberRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/ParentNumberRule.java index 660c7a1386..77762d9a6b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/ParentNumberRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/ParentNumberRule.java @@ -15,10 +15,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; -import org.ethereum.validator.block.DependentBlockHeaderRule; /** * Checks if {@link BlockHeader#number} == {@link BlockHeader#number} + 1 of parent's block diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/ProofOfWorkRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/ProofOfWorkRule.java similarity index 94% rename from ethereumj-core/src/main/java/org/ethereum/validator/block/ProofOfWorkRule.java rename to ethereumj-core/src/main/java/org/ethereum/validator/ProofOfWorkRule.java index 946ebc5160..2c4687272d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/ProofOfWorkRule.java +++ b/ethereumj-core/src/main/java/org/ethereum/validator/ProofOfWorkRule.java @@ -15,11 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ -package org.ethereum.validator.block; +package org.ethereum.validator; import org.ethereum.core.BlockHeader; import org.ethereum.util.FastByteComparisons; -import org.ethereum.validator.block.BlockHeaderRule; /** * Checks proof value against its boundary for the block header diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java deleted file mode 100644 index 89268f9f40..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/block/BlockHeaderRule.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.block; - -import org.ethereum.core.BlockHeader; -import org.ethereum.validator.EntityRule; -import org.slf4j.Logger; - -/** - * Parent class for {@link BlockHeader} validators - * - * @author Mikhail Kalinin - * @since 02.09.2015 - */ -public abstract class BlockHeaderRule extends EntityRule { - - @Override - public Class getEntityClass() { - return BlockHeader.class; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java deleted file mode 100644 index 8f9fa13693..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptCasperVoteRule.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.casper.config.CasperProperties; -import org.ethereum.casper.core.CasperFacade; -import org.ethereum.core.TransactionReceipt; - -import java.util.Arrays; -import java.util.List; - -/** - * Checks {@link org.ethereum.core.TransactionReceipt} is from Casper contract vote - * if it is, the checks are over - * otherwise all other checks are applied - */ -public class ReceiptCasperVoteRule extends TransactionReceiptRule { - - private final byte[] CASPER_ADDRESS; - private List nextRules; - - public ReceiptCasperVoteRule(CasperProperties config, TransactionReceiptRule ...rules) { - this.CASPER_ADDRESS = config.getCasperAddress(); - this.nextRules = Arrays.asList(rules); - } - - @Override - public ValidationResult validate(TransactionReceipt receipt) { - boolean isCasperVote = CasperFacade.isVote(receipt.getTransaction(), CASPER_ADDRESS); - if (isCasperVote) { - if (receipt.isSuccessful()) { - return Success; - } else { - return fault("Receipt is not correct: Unsuccessful casper vote"); - } - } else { - return new TransactionReceiptValidator(nextRules).validate(receipt); - } - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java deleted file mode 100644 index d48c1684d4..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/ReceiptValidityRule.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.core.TransactionReceipt; - -/** - * Checks {@link org.ethereum.core.TransactionReceipt} shows something was done in VM with related tx - */ -public class ReceiptValidityRule extends TransactionReceiptRule { - - @Override - public ValidationResult validate(TransactionReceipt receipt) { - if (!receipt.isValid()) { - return fault("Receipt is invalid: 0 gas used"); - } - - return Success; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java deleted file mode 100644 index b041a45e1e..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionCasperVoteRule.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.casper.config.CasperProperties; -import org.ethereum.casper.core.CasperFacade; -import org.ethereum.core.Transaction; - -import java.util.Arrays; -import java.util.List; - -/** - * Checks {@link Transaction} is Casper contract vote - * if it is, the checks are over - * otherwise all other checks are applied - */ -public class TransactionCasperVoteRule extends TransactionRule { - - private final byte[] CASPER_ADDRESS; - private List nextRules; - - public TransactionCasperVoteRule(CasperProperties config, TransactionRule ...rules) { - this.CASPER_ADDRESS = config.getCasperAddress(); - this.nextRules = Arrays.asList(rules); - } - - - @Override - public ValidationResult validate(Transaction transaction) { - boolean isCasperVote = CasperFacade.isVote(transaction, CASPER_ADDRESS); - if (isCasperVote) { - return Success; - } else { - return new TransactionValidator(nextRules).validate(transaction); - } - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java deleted file mode 100644 index 553de0192f..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionFieldsRule.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.core.Transaction; - -import java.math.BigInteger; - -/** - * Checks {@link org.ethereum.core.Transaction} fields are with correct length and in allowable range - */ -public class TransactionFieldsRule extends TransactionRule { - - @Override - public ValidationResult validate(Transaction transaction) { - try { - transaction.verify(); - } catch (Exception ex) { - return fault(ex.getMessage()); - } - - return Success; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java deleted file mode 100644 index e4d076a22f..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionMineGasPriceRule.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.config.SystemProperties; -import org.ethereum.core.Transaction; -import org.ethereum.util.ByteUtil; - -import java.math.BigInteger; - -/** - * Checks {@link Transaction} fields are with correct length and in allowable range - */ -public class TransactionMineGasPriceRule extends TransactionRule { - - private final BigInteger MIN_GAS_PRICE; - - public TransactionMineGasPriceRule(SystemProperties config) { - this.MIN_GAS_PRICE = config.getMineMinGasPrice(); - } - - @Override - public ValidationResult validate(Transaction transaction) { - if (MIN_GAS_PRICE.compareTo(ByteUtil.bytesToBigInteger(transaction.getGasPrice())) >= 0) { - return fault("Too low gas price for transaction: " + ByteUtil.bytesToBigInteger(transaction.getGasPrice())); - } - - return Success; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java deleted file mode 100644 index 5019dc346f..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptRule.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.core.TransactionReceipt; -import org.ethereum.validator.EntityRule; -/** - * Parent class for {@link org.ethereum.core.TransactionReceipt} validators - */ -public abstract class TransactionReceiptRule extends EntityRule { - @Override - public Class getEntityClass() { - return TransactionReceipt.class; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java deleted file mode 100644 index 7d1cf5fa5d..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionReceiptValidator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.core.TransactionReceipt; -import org.ethereum.validator.EntityValidator; - -import java.util.List; - -/** - * Composite {@link TransactionReceipt} validator - * aggregating list of simple validation rules - */ -public class TransactionReceiptValidator extends EntityValidator { - - public TransactionReceiptValidator(List rules) { - super(rules); - } - - public TransactionReceiptValidator(TransactionReceiptRule... rules) { - super(rules); - } - - @Override - public Class getEntityClass() { - return TransactionReceipt.class; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java deleted file mode 100644 index a8afa29464..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionRule.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.core.Transaction; -import org.ethereum.validator.EntityRule; - -/** - * Parent class for {@link Transaction} validators - */ -public abstract class TransactionRule extends EntityRule { - @Override - public Class getEntityClass() { - return Transaction.class; - } -} diff --git a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java b/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java deleted file mode 100644 index 2c77e5d7e9..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/validator/transaction/TransactionValidator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.validator.transaction; - -import org.ethereum.core.Transaction; -import org.ethereum.validator.EntityValidator; - -import java.util.List; - -/** - * Composite {@link org.ethereum.core.Transaction} validator - * aggregating list of simple validation rules - */ -public class TransactionValidator extends EntityValidator { - - public TransactionValidator(List rules) { - super(rules); - } - - public TransactionValidator(TransactionRule... rules) { - super(rules); - } - - @Override - public Class getEntityClass() { - return Transaction.class; - } -} diff --git a/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java b/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java index 229dfcd689..8821ea9784 100644 --- a/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java +++ b/ethereumj-core/src/test/java/org/ethereum/config/blockchain/TestBlockchainConfig.java @@ -30,7 +30,7 @@ import org.ethereum.core.Transaction; import org.ethereum.db.BlockStore; import org.ethereum.mine.MinerIfc; -import org.ethereum.validator.block.BlockHeaderValidator; +import org.ethereum.validator.BlockHeaderValidator; import java.math.BigInteger; import java.util.List; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java index 5a9d0fa10c..b75e55c040 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java @@ -31,7 +31,7 @@ import org.ethereum.util.ByteUtil; import org.ethereum.util.blockchain.SolidityContract; import org.ethereum.util.blockchain.StandaloneBlockchain; -import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.*; @@ -895,9 +895,8 @@ public static BlockchainImpl createBlockchain(Genesis genesis) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); EthereumListenerAdapter listener = new EthereumListenerAdapter(); - CommonConfig config = new CommonConfig(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(config.parentHeaderValidator()); + .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); @@ -906,8 +905,6 @@ public static BlockchainImpl createBlockchain(Genesis genesis) { PendingStateImpl pendingState = new PendingStateImpl(listener); pendingState.setBlockchain(blockchain); - pendingState.setReceiptValidator(config.transactionReceiptValidator()); - pendingState.setTransactionValidator(config.transactionValidator()); blockchain.setPendingState(pendingState); Repository track = repository.startTracking(); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java index d494a0811e..ccb81b577f 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/PendingStateLongRunTest.java @@ -22,7 +22,7 @@ import org.ethereum.db.RepositoryRoot; import org.ethereum.db.IndexedBlockStore; import org.ethereum.listener.EthereumListenerAdapter; -import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.Before; import org.junit.Ignore; @@ -123,18 +123,15 @@ private Blockchain createBlockchain(Genesis genesis) { Repository repository = new RepositoryRoot(new HashMapDB()); ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); - CommonConfig config = new CommonConfig(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(config.parentHeaderValidator()); + .withParentBlockHeaderValidator(new CommonConfig().parentHeaderValidator()); blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.byTest = true; PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter()); - pendingState.setReceiptValidator(config.transactionReceiptValidator()); - pendingState.setTransactionValidator(config.transactionValidator()); pendingState.setBlockchain(blockchain); blockchain.setPendingState(pendingState); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index ff021d0486..e43781f29d 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -21,6 +21,7 @@ import org.ethereum.casper.config.CasperProperties; import org.ethereum.casper.core.CasperBlockchain; import org.ethereum.casper.core.CasperFacade; +import org.ethereum.casper.core.CasperPendingStateImpl; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; @@ -30,7 +31,6 @@ import org.ethereum.core.BlockchainImpl; import org.ethereum.core.EventDispatchThread; import org.ethereum.core.Genesis; -import org.ethereum.core.PendingStateImpl; import org.ethereum.core.Repository; import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutorFactory; @@ -52,9 +52,7 @@ import org.ethereum.manager.WorldManager; import org.ethereum.net.server.ChannelManager; import org.ethereum.util.blockchain.StandaloneBlockchain; -import org.ethereum.validator.block.DependentBlockHeaderRuleAdapter; -import org.ethereum.validator.transaction.TransactionReceiptValidator; -import org.ethereum.validator.transaction.TransactionValidator; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.program.ProgramPrecompile; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.Before; @@ -76,6 +74,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doCallRealMethod; // We have all mocks here and not all of them are used in every test, so strict stubs should be turned off @RunWith(MockitoJUnitRunner.Silent.class) @@ -107,12 +106,6 @@ public SystemProperties systemProperties() { private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); - @Spy - TransactionValidator transactionValidator = commonConfig.transactionValidator(); - - @Spy - TransactionReceiptValidator receiptValidator = commonConfig.transactionReceiptValidator(); - @InjectMocks EthereumImpl ethereum = new EthereumImpl(systemProperties, defaultListener); @@ -122,7 +115,7 @@ public SystemProperties systemProperties() { Repository repository = new RepositoryWrapper(); @InjectMocks - PendingStateImpl casperPendingState = new PendingStateImpl(defaultListener); + CasperPendingStateImpl casperPendingState = new CasperPendingStateImpl(defaultListener); StandaloneBlockchain bc; @@ -201,8 +194,6 @@ private BlockchainImpl createBlockchain() { this.blockchain = (CasperBlockchain) bc.getBlockchain(); casper.setEthereum(ethereum); blockchain.setCasper(casper); - blockchain.setReceiptValidator(receiptValidator); - blockchain.setTransactionValidator(transactionValidator); Mockito.when(context.getBean(CasperBlockchain.class)).thenReturn(blockchain); Mockito.when(worldManager.getBlockchain()).thenReturn(blockchain); Mockito.when(worldManager.getBlockStore()).thenReturn(blockchain.getBlockStore()); 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 67aef40bab..9fdf981fd5 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 @@ -33,6 +33,7 @@ import org.ethereum.jsontestsuite.suite.validators.RepositoryValidator; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; +import org.ethereum.validator.DependentBlockHeaderRuleAdapter; import org.ethereum.vm.DataWord; import org.ethereum.vm.LogInfo; import org.ethereum.vm.VM; @@ -98,14 +99,11 @@ public List runTestCase(BlockTestCase testCase) { ProgramInvokeFactoryImpl programInvokeFactory = new ProgramInvokeFactoryImpl(); - CommonConfig config = CommonConfig.getDefault(); BlockchainImpl blockchain = new BlockchainImpl(blockStore, repository) - .withParentBlockHeaderValidator(config.parentHeaderValidator()); + .withParentBlockHeaderValidator(CommonConfig.getDefault().parentHeaderValidator()); blockchain.byTest = true; PendingStateImpl pendingState = new PendingStateImpl(new EthereumListenerAdapter()); - pendingState.setTransactionValidator(config.transactionValidator()); - pendingState.setReceiptValidator(config.transactionReceiptValidator()); blockchain.setBestBlock(genesis); blockchain.setTotalDifficulty(genesis.getCumulativeDifficulty()); diff --git a/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java b/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java index 8ff9cd69c2..a001922fa3 100644 --- a/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/validator/ProofOfWorkRuleTest.java @@ -18,7 +18,6 @@ package org.ethereum.validator; import org.ethereum.core.Block; -import org.ethereum.validator.block.ProofOfWorkRule; import org.junit.Ignore; import org.junit.Test; import org.spongycastle.util.encoders.Hex; From 73fddc3fbdcc87c6881127d5dedb045901614ba2 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 13 Mar 2018 20:23:02 +0300 Subject: [PATCH 44/67] Decreased validator gas limit to make it easy passing in block with any other txs --- .../main/java/org/ethereum/casper/core/CasperBlockchain.java | 5 +++-- .../org/ethereum/casper/service/CasperValidatorService.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 3ba776814d..4723290da5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -52,10 +52,11 @@ import static org.ethereum.core.ImportResult.IMPORTED_NOT_BEST; import static org.ethereum.core.ImportResult.INVALID_BLOCK; import static org.ethereum.core.ImportResult.NO_PARENT; -import static org.ethereum.casper.service.CasperValidatorService.DEFAULT_GASLIMIT; public class CasperBlockchain extends BlockchainImpl { + private static final long EPOCH_SWITCH_GASLIMIT = 3_141_592; // Sames as block gas limit + @Autowired private CasperFacade casper; @@ -255,7 +256,7 @@ protected BlockSummary applyBlock(Repository track, Block block) { Transaction tx = new Transaction( ByteUtil.bigIntegerToBytes(track.getNonce(NULL_SIGN_SENDER.getAddress())), new byte[0], - ByteUtil.longToBytesNoLeadZeroes(DEFAULT_GASLIMIT), + ByteUtil.longToBytesNoLeadZeroes(EPOCH_SWITCH_GASLIMIT), casper.getAddress(), new byte[0], data diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 17c052c57a..4e39c64a29 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -81,7 +81,7 @@ public class CasperValidatorService { private static final int LOGOUT_COOLDOWN = 60 * 1000; // In millis - public static final long DEFAULT_GASLIMIT = 3_141_592; // Just copied it, don't ask! + private static final long DEFAULT_GASLIMIT = 2_500_000; // Enough for deposit and logout private Map votes = new HashMap<>(); From 43b3f965b56579386be7f5267faf625ac6b2bd09 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 13 Mar 2018 21:21:53 +0300 Subject: [PATCH 45/67] Fixed failure when no validator options configured --- .../org/ethereum/casper/service/CasperValidatorService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 4e39c64a29..a430405855 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -168,8 +168,6 @@ public String toString() { public CasperValidatorService(Ethereum ethereum, SystemProperties config) { this.ethereum = ethereum; this.config = (CasperProperties) config; - this.coinbase = ECKey.fromPrivate(this.config.getCasperValidatorPrivateKey()); - this.depositSize = EtherUtil.convert(this.config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); handlers.put(UNINITIATED, this::checkLoggedIn); handlers.put(WAITING_FOR_VALCODE, this::checkValcode); @@ -183,6 +181,8 @@ public CasperValidatorService(Ethereum ethereum, SystemProperties config) { public void init() { if (Boolean.TRUE.equals(config.getCasperValidatorEnabled())) { + this.coinbase = ECKey.fromPrivate(this.config.getCasperValidatorPrivateKey()); + this.depositSize = EtherUtil.convert(this.config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); start(); } } From 1f0e5dc4cedb4d79d3e8c537fad13e7efaf01d48 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 13 Mar 2018 23:50:28 +0300 Subject: [PATCH 46/67] Fixed: unsuccessful txs with 0 gas used were included in mined blocks --- .../casper/mine/CasperBlockMiner.java | 4 +-- .../java/org/ethereum/core/Blockchain.java | 2 ++ .../org/ethereum/core/BlockchainImpl.java | 14 ++++++-- .../java/org/ethereum/mine/BlockMiner.java | 29 ++++++++++++++-- .../org/ethereum/core/ImportLightTest.java | 34 +++++++++++++++++++ 5 files changed, 74 insertions(+), 9 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java index b59eb1d250..1d27b0cc12 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/mine/CasperBlockMiner.java @@ -63,8 +63,6 @@ protected Block getNewBlockForMining() { return Boolean.compare(tx1isVote, tx2isVote); }); - Block newMiningBlock = blockchain.createNewBlock(bestPendingState, pendingTxs, - getUncles(bestPendingState)); - return newMiningBlock; + return createOptimizedBlock(bestPendingState, pendingTxs, getUncles(bestPendingState)); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java index 03322a5acb..455fafc4b8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -77,4 +77,6 @@ public interface Blockchain { List getListOfBodiesByHashes(List hashes); Block createNewBlock(Block parent, List transactions, List uncles); + + BlockSummary createNewBlockSummary(Block parent, List transactions, List uncles); } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 0c0febc5eb..972831145a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -472,15 +472,23 @@ protected ImportResult tryToConnectImpl(final Block block) { return ret; } - public synchronized Block createNewBlock(Block parent, List txs, List uncles) { + public synchronized BlockSummary createNewBlockSummary(Block parent, List txs, List uncles) { long time = System.currentTimeMillis() / 1000; // adjust time to parent block this may happen due to system clocks difference if (parent.getTimestamp() >= time) time = parent.getTimestamp() + 1; - return createNewBlock(parent, txs, uncles, time); + return createNewBlockSummary(parent, txs, uncles, time); + } + + public synchronized Block createNewBlock(Block parent, List txs, List uncles) { + return createNewBlockSummary(parent, txs, uncles).getBlock(); } public synchronized Block createNewBlock(Block parent, List txs, List uncles, long time) { + return createNewBlockSummary(parent, txs, uncles, time).getBlock(); + } + + public synchronized BlockSummary createNewBlockSummary(Block parent, List txs, List uncles, long time) { final long blockNumber = parent.getNumber() + 1; final byte[] extraData = config.getBlockchainConfig().getConfigForBlock(blockNumber).getExtraData(minerExtraData, blockNumber); @@ -523,7 +531,7 @@ public synchronized Block createNewBlock(Block parent, List txs, Li block.getHeader().setGasUsed(receipts.size() > 0 ? receipts.get(receipts.size() - 1).getCumulativeGasLong() : 0); block.getHeader().setReceiptsRoot(calcReceiptsTrie(receipts)); - return block; + return summary; } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java index eda816bf8b..d3514dddec 100644 --- a/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java +++ b/ethereumj-core/src/main/java/org/ethereum/mine/BlockMiner.java @@ -22,7 +22,6 @@ import org.apache.commons.collections4.CollectionUtils; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; -import org.ethereum.casper.core.CasperTransactionExecutor; import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.IndexedBlockStore; @@ -31,6 +30,7 @@ import org.ethereum.listener.CompositeEthereumListener; import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.mine.MinerIfc.MiningResult; +import org.ethereum.util.FastByteComparisons; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -39,6 +39,7 @@ import java.math.BigInteger; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; import static java.lang.Math.max; @@ -245,8 +246,30 @@ protected Block getNewBlockForMining() { logger.debug("getNewBlockForMining best blocks: PendingState: " + bestPendingState.getShortDescr() + ", Blockchain: " + bestBlockchain.getShortDescr()); - Block newMiningBlock = blockchain.createNewBlock(bestPendingState, getAllPendingTransactions(), - getUncles(bestPendingState)); + return createOptimizedBlock(bestPendingState, getAllPendingTransactions(), getUncles(bestPendingState)); + } + + protected Block createOptimizedBlock(Block bestPendingBlock, final List txs, List uncles) { + boolean optimized = false; + Block newMiningBlock = null; + while(!optimized) { + List transactions = new ArrayList<>(txs); + BlockSummary summary = blockchain.createNewBlockSummary(bestPendingBlock, transactions, uncles); + AtomicBoolean badTxFound = new AtomicBoolean(false); + summary.getReceipts().forEach(receipt -> { + if (!receipt.isSuccessful() && (receipt.getGasUsed() == null || receipt.getGasUsed().length == 0)) { + transactions.removeIf(transaction -> { + boolean match = FastByteComparisons.equal(transaction.getHash(), receipt.getTransaction().getHash()); + badTxFound.set(true); + return match; + }); + } + }); + if (!badTxFound.get()) { + optimized = true; + newMiningBlock = summary.getBlock(); + } + } return newMiningBlock; } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java index b75e55c040..60b57d2466 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/ImportLightTest.java @@ -301,6 +301,40 @@ public void doubleTransactionTest() throws Exception { Assert.assertTrue(importResult == ImportResult.IMPORTED_BEST); } + @Test + public void gasLimitExceed() throws Exception { + // Testing that tx in block when block.gasUsed + tx.gasLimit is not successful + // while block is correctly imported + + BlockchainImpl blockchain = createBlockchain(GenesisLoader.loadGenesis( + getClass().getResourceAsStream("/genesis/genesis-light.json"))); + blockchain.setMinerCoinbase(Hex.decode("ee0250c19ad59305b2bdb61f34b45b72fe37154f")); + Block parent = blockchain.getBestBlock(); + + ECKey senderKey = ECKey.fromPrivate(Hex.decode("3ec771c31cac8c0dba77a69e503765701d3c2bb62435888d4ffa38fed60c445c")); + byte[] receiverAddr = Hex.decode("31e2e1ed11951c7091dfba62cd4b7145e947219c"); + + Transaction tx1 = new Transaction(ByteUtil.intToBytesNoLeadZeroes(0), + ByteUtil.longToBytesNoLeadZeroes(50_000_000_000L), + ByteUtil.longToBytesNoLeadZeroes(0xfffff), + receiverAddr, new byte[]{88}, new byte[0]); + tx1.sign(senderKey); + Transaction tx2 = new Transaction(ByteUtil.intToBytesNoLeadZeroes(1), + ByteUtil.longToBytesNoLeadZeroes(50_000_000_000L), + Hex.decode("1000000000"), // same as block gas limit + receiverAddr, new byte[]{88}, new byte[0]); + tx2.sign(senderKey); + + Block b = blockchain.createNewBlock(parent, Arrays.asList(tx1, tx2), Collections.EMPTY_LIST); + Ethash.getForBlock(SystemProperties.getDefault(), b.getNumber()).mineLight(b).get(); + Repository repo = blockchain.getRepository().getSnapshotTo(parent.getStateRoot()); + BlockSummary summary = blockchain.add(repo, b); + Assert.assertNotNull(summary); + Assert.assertTrue(summary.getReceipts().get(0).isSuccessful()); + Assert.assertTrue(!summary.getReceipts().get(1).isSuccessful()); // second tx fails because of too big gas limit + Assert.assertEquals(0, summary.getReceipts().get(1).getGasUsed().length); // and no gas is used + } + @Test public void invalidBlockTotalDiff() throws Exception { // Check that importing invalid block doesn't affect totalDifficulty From 0423bbf566e30ae7dd2ba8ad792c66f46003b56a Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 00:48:42 +0300 Subject: [PATCH 47/67] Fixed wrong init in CasperValidatorService --- .../org/ethereum/casper/service/CasperValidatorService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index a430405855..3bed76f556 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -181,14 +181,14 @@ public CasperValidatorService(Ethereum ethereum, SystemProperties config) { public void init() { if (Boolean.TRUE.equals(config.getCasperValidatorEnabled())) { - this.coinbase = ECKey.fromPrivate(this.config.getCasperValidatorPrivateKey()); - this.depositSize = EtherUtil.convert(this.config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); start(); } } public synchronized void start() { if (!started) { + this.coinbase = ECKey.fromPrivate(this.config.getCasperValidatorPrivateKey()); + this.depositSize = EtherUtil.convert(this.config.getCasperValidatorDeposit(), EtherUtil.Unit.ETHER); logger.info("Starting casper validator with coinbase 0x{}", Hex.toHexString(coinbase.getAddress())); // FIXME: Actually we should listen only to HEAD changes ethereum.addListener(new EthereumListenerAdapter() { From 8ec6864b8c2bf7e011d7253fbfea1e4b0a64567e Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 17:04:35 +0300 Subject: [PATCH 48/67] Make casper epoch switch free --- .../ethereum/casper/core/CasperFacade.java | 26 +++++++++++++++++++ .../core/CasperTransactionExecutor.java | 14 +++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 49e4e6f719..96d223b495 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -49,6 +49,7 @@ public class CasperFacade { private static final byte[] CASPER_VOTE_DATA_HEAD = Hex.decode("e9dc0614"); + private static final byte[] CASPER_EPOCH_DATA_HEAD = Hex.decode("5dcffc17"); private CasperProperties systemProperties; @@ -96,10 +97,23 @@ public Object[] constCall(Block block, String func, Object... funcArgs) { return casper.getByName(func).decodeResult(r.getHReturn()); } + /** + * All service txs shouldn't use gas + * Currently it's votes and epoch change + */ + public boolean isServiceTx(Transaction transaction) { + return isServiceTx(transaction, getAddress()); + } + public boolean isVote(Transaction transaction) { return isVote(transaction, getAddress()); } + public static boolean isServiceTx(Transaction transaction, byte[] casperAddress) { + return isVote(transaction, casperAddress) || + isEpochSwitch(transaction, casperAddress); + } + public static boolean isVote(Transaction transaction, byte[] casperAddress) { if (!Arrays.equals(transaction.getSender(), Transaction.NULL_SENDER)) return false; @@ -112,6 +126,18 @@ public static boolean isVote(Transaction transaction, byte[] casperAddress) { CASPER_VOTE_DATA_HEAD, 0, CASPER_VOTE_DATA_HEAD.length) == 0; } + private static boolean isEpochSwitch(Transaction transaction, byte[] casperAddress) { + if (!Arrays.equals(transaction.getSender(), NULL_SIGN_SENDER.getAddress())) + return false; + if (casperAddress == null) + return false; + if (!Arrays.equals(transaction.getReceiveAddress(), casperAddress)) + return false; + + return FastByteComparisons.compareTo(transaction.getData(), 0, CASPER_EPOCH_DATA_HEAD.length, + CASPER_EPOCH_DATA_HEAD, 0, CASPER_EPOCH_DATA_HEAD.length) == 0; + } + public byte[] getAddress() { init(); return systemProperties.getCasperAddress(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 7e88e57604..a50f927cc0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -76,7 +76,7 @@ public void init() { @Override protected boolean isSignatureValid() { - return isCasperVote() || super.isSignatureValid(); + return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()) || super.isSignatureValid(); } @Override @@ -84,7 +84,7 @@ public void execute() { if (!readyToExecute) return; - if (!localCall && !isCasperVote()) { + if (!localCall && !isCasperServiceTx()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -102,14 +102,14 @@ public void execute() { } } - private boolean isCasperVote() { - return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); + private boolean isCasperServiceTx() { + return CasperFacade.isServiceTx(tx, ((CasperProperties) config).getCasperAddress()); } @Override protected void payRewards(final TransactionExecutionSummary summary) { - if (execError == null && isCasperVote()) { - // Return money to sender for succesful Casper vote + if (execError == null && isCasperServiceTx()) { + // Return money to sender for service Casper tx track.addBalance(tx.getSender(), summary.getFee()); logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); } else { @@ -124,7 +124,7 @@ protected void payRewards(final TransactionExecutionSummary summary) { public long getGasUsed() { long gasUsed = super.getGasUsed(); // Successful Casper vote 0 cost - if (getResult() != null && execError == null && isCasperVote()) { + if (getResult() != null && execError == null && isCasperServiceTx()) { gasUsed = 0; } return gasUsed; From 845c0bfd38762d508e5e36359bfa7f3bcea9d294 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 17:04:52 +0300 Subject: [PATCH 49/67] Revert "Make casper epoch switch free" This reverts commit 8ec6864b8c2bf7e011d7253fbfea1e4b0a64567e. --- .../ethereum/casper/core/CasperFacade.java | 26 ------------------- .../core/CasperTransactionExecutor.java | 14 +++++----- 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 96d223b495..49e4e6f719 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -49,7 +49,6 @@ public class CasperFacade { private static final byte[] CASPER_VOTE_DATA_HEAD = Hex.decode("e9dc0614"); - private static final byte[] CASPER_EPOCH_DATA_HEAD = Hex.decode("5dcffc17"); private CasperProperties systemProperties; @@ -97,23 +96,10 @@ public Object[] constCall(Block block, String func, Object... funcArgs) { return casper.getByName(func).decodeResult(r.getHReturn()); } - /** - * All service txs shouldn't use gas - * Currently it's votes and epoch change - */ - public boolean isServiceTx(Transaction transaction) { - return isServiceTx(transaction, getAddress()); - } - public boolean isVote(Transaction transaction) { return isVote(transaction, getAddress()); } - public static boolean isServiceTx(Transaction transaction, byte[] casperAddress) { - return isVote(transaction, casperAddress) || - isEpochSwitch(transaction, casperAddress); - } - public static boolean isVote(Transaction transaction, byte[] casperAddress) { if (!Arrays.equals(transaction.getSender(), Transaction.NULL_SENDER)) return false; @@ -126,18 +112,6 @@ public static boolean isVote(Transaction transaction, byte[] casperAddress) { CASPER_VOTE_DATA_HEAD, 0, CASPER_VOTE_DATA_HEAD.length) == 0; } - private static boolean isEpochSwitch(Transaction transaction, byte[] casperAddress) { - if (!Arrays.equals(transaction.getSender(), NULL_SIGN_SENDER.getAddress())) - return false; - if (casperAddress == null) - return false; - if (!Arrays.equals(transaction.getReceiveAddress(), casperAddress)) - return false; - - return FastByteComparisons.compareTo(transaction.getData(), 0, CASPER_EPOCH_DATA_HEAD.length, - CASPER_EPOCH_DATA_HEAD, 0, CASPER_EPOCH_DATA_HEAD.length) == 0; - } - public byte[] getAddress() { init(); return systemProperties.getCasperAddress(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index a50f927cc0..7e88e57604 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -76,7 +76,7 @@ public void init() { @Override protected boolean isSignatureValid() { - return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()) || super.isSignatureValid(); + return isCasperVote() || super.isSignatureValid(); } @Override @@ -84,7 +84,7 @@ public void execute() { if (!readyToExecute) return; - if (!localCall && !isCasperServiceTx()) { + if (!localCall && !isCasperVote()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -102,14 +102,14 @@ public void execute() { } } - private boolean isCasperServiceTx() { - return CasperFacade.isServiceTx(tx, ((CasperProperties) config).getCasperAddress()); + private boolean isCasperVote() { + return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); } @Override protected void payRewards(final TransactionExecutionSummary summary) { - if (execError == null && isCasperServiceTx()) { - // Return money to sender for service Casper tx + if (execError == null && isCasperVote()) { + // Return money to sender for succesful Casper vote track.addBalance(tx.getSender(), summary.getFee()); logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); } else { @@ -124,7 +124,7 @@ protected void payRewards(final TransactionExecutionSummary summary) { public long getGasUsed() { long gasUsed = super.getGasUsed(); // Successful Casper vote 0 cost - if (getResult() != null && execError == null && isCasperServiceTx()) { + if (getResult() != null && execError == null && isCasperVote()) { gasUsed = 0; } return gasUsed; From c72cb9de217e0abf34174c21e8d84d2ff26ab781 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 17:45:20 +0300 Subject: [PATCH 50/67] Don't subtract fee from null sender on succesful casper vote. Instead, block should be INVALID --- .../casper/core/CasperBlockchain.java | 27 +++++++ .../core/CasperTransactionExecutor.java | 8 +- .../org/ethereum/core/BlockchainImpl.java | 73 ++++++++++--------- 3 files changed, 69 insertions(+), 39 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 4723290da5..8d87bd3f08 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -231,6 +231,33 @@ private void finalizeCheckpoint(final Block block) { } } + @Override + protected boolean checkBlockSummary(BlockSummary summary, Repository track) { + boolean res = super.checkBlockSummary(summary, track); + if (!res) { // Already bad block + return res; + } + + // More checks + + // Check for failed casper txs + TransactionReceipt failedCasperVote = null; + for (int i = 0; i < summary.getReceipts().size(); ++i) { + TransactionReceipt receipt = summary.getReceipts().get(i); + if(!receipt.isSuccessful() && casper.isVote(receipt.getTransaction())) { + failedCasperVote = receipt; + break; + } + } + if (failedCasperVote != null) { + logger.warn("Block contains failed casper vote (receipt: {}, tx: {})", + failedCasperVote, failedCasperVote.getTransaction()); + return false; + } + + return true; + } + @Override protected BlockSummary applyBlock(Repository track, Block block) { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 7e88e57604..9f209d5079 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -108,8 +108,8 @@ private boolean isCasperVote() { @Override protected void payRewards(final TransactionExecutionSummary summary) { - if (execError == null && isCasperVote()) { - // Return money to sender for succesful Casper vote + if (isCasperVote()) { + // Return money to sender for Casper vote track.addBalance(tx.getSender(), summary.getFee()); logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); } else { @@ -123,8 +123,8 @@ protected void payRewards(final TransactionExecutionSummary summary) { @Override public long getGasUsed() { long gasUsed = super.getGasUsed(); - // Successful Casper vote 0 cost - if (getResult() != null && execError == null && isCasperVote()) { + // Casper vote 0 cost + if (isCasperVote()) { gasUsed = 0; } return gasUsed; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 972831145a..89afbc6058 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -592,64 +592,67 @@ public synchronized BlockSummary addImpl(Repository repo, final Block block) { } BlockSummary summary = processBlock(repo, block); - final List receipts = summary.getReceipts(); // Sanity checks + if(!checkBlockSummary(summary, repo)) { + repo.rollback(); + summary = null; + } + + if (summary != null) { + final List receipts = summary.getReceipts(); + repo.commit(); + updateTotalDifficulty(block); + summary.setTotalDifficulty(getTotalDifficulty()); + + if (!byTest) { + dbFlushManager.commit(() -> { + storeBlock(block, receipts); + repository.commit(); + }); + } else { + storeBlock(block, receipts); + } + } + + return summary; + } + + /** + * Sanity checks of block import result + * @return true if block is good, otherwise false + */ + protected boolean checkBlockSummary(final BlockSummary summary, final Repository track) { + Block block = summary.getBlock(); + final List receipts = summary.getReceipts(); if (!FastByteComparisons.equal(block.getReceiptsRoot(), calcReceiptsTrie(receipts))) { logger.warn("Block's given Receipt Hash doesn't match: {} != {}", Hex.toHexString(block.getReceiptsRoot()), Hex.toHexString(calcReceiptsTrie(receipts))); logger.warn("Calculated receipts: " + receipts); - repo.rollback(); - summary = null; + return false; } if (!FastByteComparisons.equal(block.getLogBloom(), calcLogBloom(receipts))) { logger.warn("Block's given logBloom Hash doesn't match: {} != {}", Hex.toHexString(block.getLogBloom()), Hex.toHexString(calcLogBloom(receipts))); - repo.rollback(); - summary = null; + return false; } - if (!FastByteComparisons.equal(block.getStateRoot(), repo.getRoot())) { + if (!FastByteComparisons.equal(block.getStateRoot(), track.getRoot())) { - stateLogger.warn("BLOCK: State conflict or received invalid block. block: {} worldstate {} mismatch", block.getNumber(), Hex.toHexString(repo.getRoot())); + stateLogger.warn("BLOCK: State conflict or received invalid block. block: {} worldstate {} mismatch", block.getNumber(), Hex.toHexString(track.getRoot())); stateLogger.warn("Conflict block dump: {}", Hex.toHexString(block.getEncoded())); -// track.rollback(); -// repository.rollback(); - repository = repository.getSnapshotTo(origRoot); - - // block is bad so 'rollback' the state root to the original state -// ((RepositoryImpl) repository).setRoot(origRoot); - -// track.rollback(); - // block is bad so 'rollback' the state root to the original state -// ((RepositoryImpl) repository).setRoot(origRoot); - if (config.exitOnBlockConflict()) { + track.rollback(); adminInfo.lostConsensus(); System.out.println("CONFLICT: BLOCK #" + block.getNumber() + ", dump: " + Hex.toHexString(block.getEncoded())); System.exit(1); } else { - summary = null; - } - } - - if (summary != null) { - repo.commit(); - updateTotalDifficulty(block); - summary.setTotalDifficulty(getTotalDifficulty()); - - if (!byTest) { - dbFlushManager.commit(() -> { - storeBlock(block, receipts); - repository.commit(); - }); - } else { - storeBlock(block, receipts); + return false; } } - return summary; + return true; // Everything is good! } @Override From 2117fdc9b1ca4dda26b4a8e07f45ddf4ffa56136 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 19:05:19 +0300 Subject: [PATCH 51/67] Fixed makeInitTxs --- .../src/main/java/org/ethereum/casper/core/CasperFacade.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 49e4e6f719..ed0624f8d6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -23,6 +23,7 @@ import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CallTransaction; +import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.crypto.ECKey; import org.ethereum.facade.Ethereum; @@ -147,7 +148,9 @@ private Pair> makeInitTxes() { txStrs.add(VIPER_RLP_DECODER_TX); txStrs.add(SIG_HASHER_TX); txStrs.add(PURITY_CHECKER_TX); - BigInteger nonce = ethereum.getRepository().getNonce(NULL_SIGN_SENDER.getAddress()); + + Repository track = (Repository) ethereum.getSnapshotTo(ethereum.getBlockchain().getBlockByNumber(0).getStateRoot()); + BigInteger nonce = track.getNonce(NULL_SIGN_SENDER.getAddress()); List txs = new ArrayList<>(); final long gasPriceFund = 25_000_000_000L; for (int i = 0; i < txStrs.size(); ++i) { From 3a3e5367213af8a33867d4925e141abf4569f6e0 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 20:16:23 +0300 Subject: [PATCH 52/67] Logging of casper address added --- .../src/main/java/org/ethereum/casper/core/CasperFacade.java | 5 +++++ ethereumj-core/src/main/resources/logback.xml | 1 + 2 files changed, 6 insertions(+) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index ed0624f8d6..fa3efb581b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -30,6 +30,8 @@ import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; import org.ethereum.vm.program.ProgramResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -49,6 +51,8 @@ @Component public class CasperFacade { + private static final Logger logger = LoggerFactory.getLogger("casper"); + private static final byte[] CASPER_VOTE_DATA_HEAD = Hex.decode("e9dc0614"); private CasperProperties systemProperties; @@ -76,6 +80,7 @@ private void init() { this.initTxs = res.getValue(); systemProperties.setCasperAddress(casperAddress); this.contractAddress = Hex.toHexString(casperAddress); + logger.info("Casper contract address set to [0x{}]", contractAddress); String casperAbi = systemProperties.getCasperAbi(); this.casper = new CallTransaction.Contract(casperAbi); } diff --git a/ethereumj-core/src/main/resources/logback.xml b/ethereumj-core/src/main/resources/logback.xml index af224c7f12..2c8c6709eb 100644 --- a/ethereumj-core/src/main/resources/logback.xml +++ b/ethereumj-core/src/main/resources/logback.xml @@ -71,6 +71,7 @@ + From 13fda702a052a18c5e3332302d20df088df7c420 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 22:04:53 +0300 Subject: [PATCH 53/67] Trying to fix github tests with delay after failed request --- .../java/org/ethereum/jsontestsuite/suite/JSONReader.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/JSONReader.java b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/JSONReader.java index 84dfebe2e8..624df357e6 100644 --- a/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/JSONReader.java +++ b/ethereumj-core/src/test/java/org/ethereum/jsontestsuite/suite/JSONReader.java @@ -98,6 +98,12 @@ public static String getFromUrl(String urlToRead) { break; } catch (Exception ex) { logger.debug(String.format("Failed to retrieve %s, retry %d/%d", urlToRead, (i + 1), MAX_RETRIES), ex); + if (i < (MAX_RETRIES - 1)) { + try { + Thread.sleep(2000); // adding delay after fail + } catch (InterruptedException e) { + } + } } } if (result == null) throw new RuntimeException(String.format("Failed to retrieve file from url %s", urlToRead)); From 0cc765dc4698382d92b651ed7a047aa60653405e Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 14 Mar 2018 22:06:11 +0300 Subject: [PATCH 54/67] Revert "Don't subtract fee from null sender on succesful casper vote. Instead, block should be INVALID" This reverts commit c72cb9de217e0abf34174c21e8d84d2ff26ab781. --- .../casper/core/CasperBlockchain.java | 27 ------- .../core/CasperTransactionExecutor.java | 8 +- .../org/ethereum/core/BlockchainImpl.java | 73 +++++++++---------- 3 files changed, 39 insertions(+), 69 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 8d87bd3f08..4723290da5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -231,33 +231,6 @@ private void finalizeCheckpoint(final Block block) { } } - @Override - protected boolean checkBlockSummary(BlockSummary summary, Repository track) { - boolean res = super.checkBlockSummary(summary, track); - if (!res) { // Already bad block - return res; - } - - // More checks - - // Check for failed casper txs - TransactionReceipt failedCasperVote = null; - for (int i = 0; i < summary.getReceipts().size(); ++i) { - TransactionReceipt receipt = summary.getReceipts().get(i); - if(!receipt.isSuccessful() && casper.isVote(receipt.getTransaction())) { - failedCasperVote = receipt; - break; - } - } - if (failedCasperVote != null) { - logger.warn("Block contains failed casper vote (receipt: {}, tx: {})", - failedCasperVote, failedCasperVote.getTransaction()); - return false; - } - - return true; - } - @Override protected BlockSummary applyBlock(Repository track, Block block) { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 9f209d5079..7e88e57604 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -108,8 +108,8 @@ private boolean isCasperVote() { @Override protected void payRewards(final TransactionExecutionSummary summary) { - if (isCasperVote()) { - // Return money to sender for Casper vote + if (execError == null && isCasperVote()) { + // Return money to sender for succesful Casper vote track.addBalance(tx.getSender(), summary.getFee()); logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); } else { @@ -123,8 +123,8 @@ protected void payRewards(final TransactionExecutionSummary summary) { @Override public long getGasUsed() { long gasUsed = super.getGasUsed(); - // Casper vote 0 cost - if (isCasperVote()) { + // Successful Casper vote 0 cost + if (getResult() != null && execError == null && isCasperVote()) { gasUsed = 0; } return gasUsed; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 89afbc6058..972831145a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -592,67 +592,64 @@ public synchronized BlockSummary addImpl(Repository repo, final Block block) { } BlockSummary summary = processBlock(repo, block); + final List receipts = summary.getReceipts(); // Sanity checks - if(!checkBlockSummary(summary, repo)) { - repo.rollback(); - summary = null; - } - - if (summary != null) { - final List receipts = summary.getReceipts(); - repo.commit(); - updateTotalDifficulty(block); - summary.setTotalDifficulty(getTotalDifficulty()); - - if (!byTest) { - dbFlushManager.commit(() -> { - storeBlock(block, receipts); - repository.commit(); - }); - } else { - storeBlock(block, receipts); - } - } - - return summary; - } - - /** - * Sanity checks of block import result - * @return true if block is good, otherwise false - */ - protected boolean checkBlockSummary(final BlockSummary summary, final Repository track) { - Block block = summary.getBlock(); - final List receipts = summary.getReceipts(); if (!FastByteComparisons.equal(block.getReceiptsRoot(), calcReceiptsTrie(receipts))) { logger.warn("Block's given Receipt Hash doesn't match: {} != {}", Hex.toHexString(block.getReceiptsRoot()), Hex.toHexString(calcReceiptsTrie(receipts))); logger.warn("Calculated receipts: " + receipts); - return false; + repo.rollback(); + summary = null; } if (!FastByteComparisons.equal(block.getLogBloom(), calcLogBloom(receipts))) { logger.warn("Block's given logBloom Hash doesn't match: {} != {}", Hex.toHexString(block.getLogBloom()), Hex.toHexString(calcLogBloom(receipts))); - return false; + repo.rollback(); + summary = null; } - if (!FastByteComparisons.equal(block.getStateRoot(), track.getRoot())) { + if (!FastByteComparisons.equal(block.getStateRoot(), repo.getRoot())) { - stateLogger.warn("BLOCK: State conflict or received invalid block. block: {} worldstate {} mismatch", block.getNumber(), Hex.toHexString(track.getRoot())); + stateLogger.warn("BLOCK: State conflict or received invalid block. block: {} worldstate {} mismatch", block.getNumber(), Hex.toHexString(repo.getRoot())); stateLogger.warn("Conflict block dump: {}", Hex.toHexString(block.getEncoded())); +// track.rollback(); +// repository.rollback(); + repository = repository.getSnapshotTo(origRoot); + + // block is bad so 'rollback' the state root to the original state +// ((RepositoryImpl) repository).setRoot(origRoot); + +// track.rollback(); + // block is bad so 'rollback' the state root to the original state +// ((RepositoryImpl) repository).setRoot(origRoot); + if (config.exitOnBlockConflict()) { - track.rollback(); adminInfo.lostConsensus(); System.out.println("CONFLICT: BLOCK #" + block.getNumber() + ", dump: " + Hex.toHexString(block.getEncoded())); System.exit(1); } else { - return false; + summary = null; + } + } + + if (summary != null) { + repo.commit(); + updateTotalDifficulty(block); + summary.setTotalDifficulty(getTotalDifficulty()); + + if (!byTest) { + dbFlushManager.commit(() -> { + storeBlock(block, receipts); + repository.commit(); + }); + } else { + storeBlock(block, receipts); } } - return true; // Everything is good! + return summary; } @Override From 3f39e57be2605c470a1ffd398fae65773af3c0bf Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 15 Mar 2018 00:24:45 +0300 Subject: [PATCH 55/67] Removed TransactionExecutorFactory --- .../casper/config/CasperBeanConfig.java | 33 ----------------- .../casper/core/CasperBlockchain.java | 23 +++++++----- .../casper/core/CasperPendingStateImpl.java | 13 +++++++ .../org/ethereum/config/CommonConfig.java | 23 ------------ .../java/org/ethereum/core/Blockchain.java | 3 ++ .../org/ethereum/core/BlockchainImpl.java | 13 ++++--- .../org/ethereum/core/PendingStateImpl.java | 21 ++++++----- .../core/TransactionExecutorFactory.java | 36 ------------------- .../org/ethereum/facade/EthereumImpl.java | 12 +++---- .../util/blockchain/StandaloneBlockchain.java | 5 +-- .../org/ethereum/core/casper/CasperBase.java | 5 --- .../ethereum/longrun/SyncWithLoadTest.java | 8 ++--- 12 files changed, 59 insertions(+), 136 deletions(-) delete mode 100644 ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java index 40e7d91b0e..6489fe8a83 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperBeanConfig.java @@ -22,21 +22,12 @@ import org.ethereum.casper.mine.CasperBlockMiner; import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.PendingState; -import org.ethereum.core.Repository; -import org.ethereum.core.Transaction; -import org.ethereum.core.TransactionExecutor; -import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.casper.core.CasperBlockchain; -import org.ethereum.casper.core.CasperTransactionExecutor; -import org.ethereum.db.BlockStore; import org.ethereum.listener.CompositeEthereumListener; -import org.ethereum.listener.EthereumListener; import org.ethereum.manager.WorldManager; import org.ethereum.mine.BlockMiner; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -51,30 +42,6 @@ public Blockchain blockchain() { return new CasperBlockchain(systemProperties()); } - @Override - @Bean - public TransactionExecutorFactory transactionExecutorFactory() { - return new CasperTransactionExecutorFactory(); - } - - class CasperTransactionExecutorFactory implements TransactionExecutorFactory { - - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock) { - return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); - } - - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { - return new CasperTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, - listener, gasUsedInTheBlock); - } - } - @Bean @Override public WorldManager worldManager() { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 4723290da5..706d702229 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -28,11 +28,13 @@ import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutor; -import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; +import org.ethereum.db.BlockStore; import org.ethereum.db.ByteArrayWrapper; +import org.ethereum.listener.EthereumListener; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; +import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.Arrays; @@ -269,10 +271,8 @@ protected BlockSummary applyBlock(Repository track, Block block) { stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); Repository txTrack = track.startTracking(); - TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); - TransactionExecutor executor = txFactory.createTransactionExecutor(tx, block.getCoinbase(), - txTrack, blockStore, getProgramInvokeFactory(), block, listener, totalGasUsed) - .withCommonConfig(commonConfig); + TransactionExecutor executor = createTransactionExecutor(tx, block.getCoinbase(), txTrack, + block, totalGasUsed); executor.init(); executor.execute(); @@ -326,6 +326,14 @@ txTrack, blockStore, getProgramInvokeFactory(), block, listener, totalGasUsed) return new BlockSummary(block, rewards, receipts, summaries); } + @Override + public TransactionExecutor createTransactionExecutor(Transaction transaction, byte[] minerCoinbase, Repository track, + Block currentBlock, long gasUsedInTheBlock) { + return new CasperTransactionExecutor(transaction, minerCoinbase, + track, blockStore, getProgramInvokeFactory(), currentBlock, listener, gasUsedInTheBlock) + .withCommonConfig(commonConfig); + } + private void initCasper(Repository track, Block block) { // All changes should be applied only just after genesis, before 1st block state changes if (block.getNumber() != 1) @@ -340,10 +348,7 @@ private void initCasper(Repository track, Block block) { track.addBalance(NULL_SIGN_SENDER.getAddress(), BigInteger.valueOf(15).pow(18)); Repository txTrack = track.startTracking(); - TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); - TransactionExecutor executor = txFactory.createTransactionExecutor(tx, - coinbase, txTrack, blockStore, getProgramInvokeFactory(), block, listener, 0) - .withCommonConfig(commonConfig); + TransactionExecutor executor = createTransactionExecutor(tx, coinbase, txTrack, block, 0); executor.init(); executor.execute(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java index 99220e5eb2..557b55c3b5 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperPendingStateImpl.java @@ -18,10 +18,14 @@ package org.ethereum.casper.core; import org.ethereum.casper.config.CasperProperties; +import org.ethereum.core.Block; import org.ethereum.core.PendingStateImpl; +import org.ethereum.core.Repository; import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionExecutor; import org.ethereum.core.TransactionReceipt; import org.ethereum.listener.EthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.util.ByteUtil; public class CasperPendingStateImpl extends PendingStateImpl { @@ -60,4 +64,13 @@ protected String validate(Transaction tx) { return null; } + + + @Override + protected TransactionExecutor createTransactionExecutor(Transaction transaction, byte[] minerCoinbase, + Repository track, Block currentBlock) { + return new CasperTransactionExecutor(transaction, minerCoinbase, + track, blockStore, programInvokeFactory, currentBlock, new EthereumListenerAdapter(), 0) + .withCommonConfig(commonConfig); + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java index c70b4be9a4..842edf8173 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/CommonConfig.java @@ -42,7 +42,6 @@ import org.ethereum.validator.ProofOfWorkRule; import org.ethereum.vm.DataWord; import org.ethereum.vm.program.ProgramPrecompile; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -292,28 +291,6 @@ public Blockchain blockchain() { return new BlockchainImpl(systemProperties()); } - @Bean - public TransactionExecutorFactory transactionExecutorFactory() { - return new CommonTransactionExecutorFactory(); - } - - class CommonTransactionExecutorFactory implements TransactionExecutorFactory { - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock) { - return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock); - } - - @Override - public TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock, EthereumListener listener, long gasUsedInTheBlock) { - return new CommonTransactionExecutor(tx, coinbase, track, blockStore, programInvokeFactory, currentBlock, - listener, gasUsedInTheBlock); - } - } - @Bean public WorldManager worldManager() { return new WorldManager(systemProperties(), repository(), blockchain()); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java index 455fafc4b8..16019e8176 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -76,6 +76,9 @@ public interface Blockchain { List getListOfBodiesByHashes(List hashes); + TransactionExecutor createTransactionExecutor(Transaction transaction, byte[] minerCoinbase, Repository track, + Block currentBlock, long gasUsedInTheBlock); + Block createNewBlock(Block parent, List transactions, List uncles); BlockSummary createNewBlockSummary(Block parent, List transactions, List uncles); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 972831145a..e2b5796b9a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -884,10 +884,8 @@ protected BlockSummary applyBlock(Repository track, Block block) { stateLogger.debug("apply block: [{}] tx: [{}] ", block.getNumber(), i); Repository txTrack = track.startTracking(); - TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); - TransactionExecutor executor = txFactory.createTransactionExecutor(tx, block.getCoinbase(), - txTrack, blockStore, programInvokeFactory, block, listener, totalGasUsed) - .withCommonConfig(commonConfig); + TransactionExecutor executor = createTransactionExecutor(tx, block.getCoinbase(), + txTrack, block, totalGasUsed); executor.init(); executor.execute(); @@ -941,6 +939,13 @@ protected BlockSummary applyBlock(Repository track, Block block) { return new BlockSummary(block, rewards, receipts, summaries); } + public TransactionExecutor createTransactionExecutor(Transaction transaction, byte[] minerCoinbase, Repository track, + Block currentBlock, long gasUsedInTheBlock) { + return new CommonTransactionExecutor(transaction, minerCoinbase, + track, blockStore, programInvokeFactory, currentBlock, listener, gasUsedInTheBlock) + .withCommonConfig(commonConfig); + } + /** * Add reward to block- and every uncle coinbase * assuming the entire block is valid. diff --git a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java index 9363df46b5..b1181978b9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/PendingStateImpl.java @@ -73,18 +73,18 @@ public TransactionSortedSet() { protected SystemProperties config = SystemProperties.getDefault(); @Autowired - CommonConfig commonConfig = CommonConfig.getDefault(); + protected CommonConfig commonConfig = CommonConfig.getDefault(); private EthereumListener listener; @Autowired private Blockchain blockchain; - private BlockStore blockStore; + protected BlockStore blockStore; private TransactionStore transactionStore; - private ProgramInvokeFactory programInvokeFactory; + protected ProgramInvokeFactory programInvokeFactory; // private Repository repository; @@ -423,12 +423,8 @@ private TransactionReceipt executeTx(Transaction tx) { logger.trace("Apply pending state tx: {}", Hex.toHexString(tx.getHash())); Block best = getBestBlock(); - - TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); - TransactionExecutor executor = txFactory.createTransactionExecutor( - tx, best.getCoinbase(), getRepository(), - blockStore, programInvokeFactory, createFakePendingBlock(), new EthereumListenerAdapter(), 0) - .withCommonConfig(commonConfig); + TransactionExecutor executor = createTransactionExecutor(tx, best.getCoinbase(), getRepository(), + createFakePendingBlock()); executor.init(); executor.execute(); @@ -438,6 +434,13 @@ blockStore, programInvokeFactory, createFakePendingBlock(), new EthereumListener return executor.getReceipt(); } + protected TransactionExecutor createTransactionExecutor(Transaction transaction, byte[] minerCoinbase, + Repository track, Block currentBlock) { + return new CommonTransactionExecutor(transaction, minerCoinbase, + track, blockStore, programInvokeFactory, currentBlock, new EthereumListenerAdapter(), 0) + .withCommonConfig(commonConfig); + } + private Block createFakePendingBlock() { // creating fake lightweight calculated block with no hashes calculations Block block = new Block(best.getHash(), diff --git a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java b/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java deleted file mode 100644 index 5d13df7c02..0000000000 --- a/ethereumj-core/src/main/java/org/ethereum/core/TransactionExecutorFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ -package org.ethereum.core; - -import org.ethereum.db.BlockStore; -import org.ethereum.listener.EthereumListener; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; - -/** - * Creates custom {@link TransactionExecutor} tailored for current environment - */ -public interface TransactionExecutorFactory { - - TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock); - - TransactionExecutor createTransactionExecutor(Transaction tx, byte[] coinbase, Repository track, - BlockStore blockStore, ProgramInvokeFactory programInvokeFactory, - Block currentBlock, EthereumListener listener, long gasUsedInTheBlock); -} diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index e40eb93517..495ab78b6b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -278,11 +278,10 @@ public BlockSummary replayBlock(Block block) { for (Transaction tx : block.getTransactionsList()) { Repository txTrack = track.startTracking(); - TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); - org.ethereum.core.TransactionExecutor executor = txFactory.createTransactionExecutor( - tx, block.getCoinbase(), txTrack, worldManager.getBlockStore(), - programInvokeFactory, block, worldManager.getListener(), 0) - .withCommonConfig(commonConfig); + org.ethereum.core.TransactionExecutor executor = + ((org.ethereum.core.Blockchain) getBlockchain()).createTransactionExecutor( + tx, block.getCoinbase(), txTrack, block, 0 + ); executor.init(); executor.execute(); @@ -311,8 +310,7 @@ private org.ethereum.core.TransactionExecutor callConstantImpl(Transaction tx, B .startTracking(); try { - TransactionExecutorFactory txFactory = commonConfig.transactionExecutorFactory(); - org.ethereum.core.TransactionExecutor executor = txFactory.createTransactionExecutor( + org.ethereum.core.TransactionExecutor executor = new CommonTransactionExecutor( tx, block.getCoinbase(), repository, worldManager.getBlockStore(), programInvokeFactory, block, new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig) diff --git a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java index ca1b76a081..f224fc148b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/blockchain/StandaloneBlockchain.java @@ -18,7 +18,6 @@ package org.ethereum.util.blockchain; import org.ethereum.config.BlockchainNetConfig; -import org.ethereum.config.CommonConfig; import org.ethereum.config.SystemProperties; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.core.*; @@ -37,7 +36,6 @@ import org.ethereum.solidity.compiler.CompilationResult; import org.ethereum.solidity.compiler.CompilationResult.ContractMetadata; import org.ethereum.solidity.compiler.SolidityCompiler; -import org.ethereum.sync.SyncManager; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; import org.ethereum.validator.DependentBlockHeaderRuleAdapter; @@ -616,8 +614,7 @@ public Object[] callConstFunction(Block callBlock, String functionName, Object.. Repository repository = getBlockchain().getRepository().getSnapshotTo(callBlock.getStateRoot()).startTracking(); try { - TransactionExecutorFactory transactionExecutorFactory = CommonConfig.getDefault().transactionExecutorFactory(); - org.ethereum.core.TransactionExecutor executor = transactionExecutorFactory.createTransactionExecutor( + org.ethereum.core.TransactionExecutor executor = new CommonTransactionExecutor( tx, callBlock.getCoinbase(), repository, getBlockchain().getBlockStore(), getBlockchain().getProgramInvokeFactory(), callBlock) .setLocalCall(true); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index e43781f29d..55ffaccab5 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -33,7 +33,6 @@ import org.ethereum.core.Genesis; import org.ethereum.core.Repository; import org.ethereum.core.TransactionExecutionSummary; -import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; import org.ethereum.datasource.CountingBytesSource; import org.ethereum.datasource.JournalSource; @@ -98,10 +97,6 @@ public SystemProperties systemProperties() { } }; - - @Spy - private TransactionExecutorFactory transactionExecutorFactory = commonConfig.transactionExecutorFactory(); - CasperBlockchain blockchain; private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); diff --git a/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java b/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java index d642e56fbf..06e9dae334 100644 --- a/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/longrun/SyncWithLoadTest.java @@ -24,10 +24,10 @@ import org.ethereum.core.AccountState; import org.ethereum.core.Block; import org.ethereum.core.BlockSummary; +import org.ethereum.core.CommonTransactionExecutor; import org.ethereum.core.Repository; import org.ethereum.core.Transaction; import org.ethereum.core.TransactionExecutor; -import org.ethereum.core.TransactionExecutorFactory; import org.ethereum.core.TransactionReceipt; import org.ethereum.db.ContractDetails; import org.ethereum.facade.Ethereum; @@ -49,7 +49,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -161,9 +160,6 @@ static class RegularNode extends BasicNode { @Autowired SyncManager syncManager; - @Autowired - TransactionExecutorFactory transactionExecutorFactory; - /** * The main EthereumJ callback. */ @@ -210,7 +206,7 @@ public void onPendingTransactionsReceived(List transactions) { .getSnapshotTo(block.getStateRoot()) .startTracking(); try { - TransactionExecutor executor = transactionExecutorFactory.createTransactionExecutor( + TransactionExecutor executor = new CommonTransactionExecutor( tx, block.getCoinbase(), repository, ethereum.getBlockchain().getBlockStore(), programInvokeFactory, block, new EthereumListenerAdapter(), 0) .withCommonConfig(commonConfig) From bc829f6ea5b0b82a8e74eda7156d054353aafe66 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 15 Mar 2018 01:03:26 +0300 Subject: [PATCH 56/67] Storing finalized checkpoints in separate source --- .../ethereum/casper/config/CasperConfig.java | 5 ++++ .../casper/core/CasperBlockchain.java | 26 ++++++++++--------- .../main/java/org/ethereum/db/BlockStore.java | 5 ---- .../java/org/ethereum/db/BlockStoreDummy.java | 10 ------- .../org/ethereum/db/IndexedBlockStore.java | 8 ------ .../src/main/resources/version.properties | 2 +- 6 files changed, 20 insertions(+), 36 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java index 7d47e2a704..033c312205 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperConfig.java @@ -71,6 +71,11 @@ public BlockStore blockStore(){ return indexedBlockStore; } + @Bean(name = "finalizedBlocks") + public Source finalizedBlockStore() { + return beanConfig.cachedDbSource("finalized"); + } + @Bean public TransactionStore transactionStore() { beanConfig.fastSyncCleanUp(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 706d702229..9eeef06658 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -29,17 +29,15 @@ import org.ethereum.core.TransactionExecutionSummary; import org.ethereum.core.TransactionExecutor; import org.ethereum.core.TransactionReceipt; -import org.ethereum.db.BlockStore; +import org.ethereum.datasource.Source; import org.ethereum.db.ByteArrayWrapper; -import org.ethereum.listener.EthereumListener; import org.ethereum.util.ByteUtil; -import org.ethereum.util.RLP; -import org.ethereum.vm.program.invoke.ProgramInvokeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.Arrays; import org.spongycastle.util.encoders.Hex; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import java.math.BigInteger; import java.util.ArrayList; @@ -57,17 +55,21 @@ public class CasperBlockchain extends BlockchainImpl { - private static final long EPOCH_SWITCH_GASLIMIT = 3_141_592; // Sames as block gas limit - - @Autowired - private CasperFacade casper; - private static final Logger logger = LoggerFactory.getLogger("blockchain"); private static final Logger stateLogger = LoggerFactory.getLogger("state"); private static final BigInteger PRETTY_BIG = BigInteger.valueOf(10).pow(40); private static final BigInteger NON_REVERT_MIN_DEPOSIT = BigInteger.valueOf(10).pow(18); + private static final long EPOCH_SWITCH_GASLIMIT = 3_141_592; // Sames as block gas limit + + @Autowired + private CasperFacade casper; + + @Autowired + @Qualifier("finalizedBlocks") + private Source finalizedBlocks; + public CasperBlockchain() { throw new RuntimeException("Empty constructor not available"); } @@ -84,7 +86,7 @@ private boolean switchRevertsFinalizedBlock(final Block block) { // Assuming old head > new head and there are no finalized blocks between while (oldHead.getNumber() > newHead.getNumber()) { - byte[] finalized = blockStore.loadMeta("finalized" + Hex.toHexString(oldHead.getHash())); + byte[] finalized = finalizedBlocks.get(oldHead.getHash()); if (finalized != null) { logger.warn("Attempt to revert failed: checkpoint {} is finalized", oldHead.getShortDescr()); return true; @@ -103,7 +105,7 @@ private boolean switchRevertsFinalizedBlock(final Block block) { // As we are currently on one height we could be on one chain before any finalized block while(!Arrays.areEqual(oldHead.getHash(), newHead.getHash())) { - byte[] finalized = blockStore.loadMeta("finalized" + Hex.toHexString(oldHead.getHash())); + byte[] finalized = finalizedBlocks.get(oldHead.getHash()); if (finalized != null) { logger.warn("Attempt to revert failed: checkpoint {} is finalized", oldHead.getShortDescr()); return true; @@ -224,7 +226,7 @@ private void finalizeCheckpoint(final Block block) { BigInteger prevDeposits = (BigInteger) res5[0]; if (curDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0 && prevDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0) { - blockStore.saveMeta("finalized" + Hex.toHexString(checkpointHash), RLP.encodeByte((byte) 0x01)); // True + finalizedBlocks.put(checkpointHash, new byte[] {0x01}); // True logger.info("Finalized checkpoint {} {}", finalizedEpoch, Hex.toHexString(checkpointHash)); } else { logger.info("Trivially finalized checkpoint {}", finalizedEpoch); diff --git a/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java b/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java index 52fe138d07..e566cb0def 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/BlockStore.java @@ -64,11 +64,6 @@ public interface BlockStore { void reBranch(Block forkBlock); - // FIXME: Do something universal instead like BlockInfoV2 - void saveMeta(String name, byte[] value); - - byte[] loadMeta(String name); - void load(); void close(); diff --git a/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java b/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java index 675e5341da..8f0ac33c07 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/BlockStoreDummy.java @@ -109,16 +109,6 @@ public void reBranch(Block forkBlock) { } - @Override - public void saveMeta(String name, byte[] value) { - - } - - @Override - public byte[] loadMeta(String name) { - return new byte[0]; - } - @Override public BigInteger getTotalDifficultyForHash(byte[] hash) { return null; diff --git a/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java b/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java index a0c395da87..d675e3d959 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/IndexedBlockStore.java @@ -509,14 +509,6 @@ private static BlockInfo getBlockInfoForHash(List blocks, byte[] hash return null; } - public void saveMeta(String name, byte[] value) { - blocksDS.put(RLP.encode(sha3(name.getBytes())), value); - } - - public byte[] loadMeta(String name) { - return blocksDS.get(RLP.encode(sha3(name.getBytes()))); - } - @Override public synchronized void load() { } diff --git a/ethereumj-core/src/main/resources/version.properties b/ethereumj-core/src/main/resources/version.properties index c7a7acd67f..6e3adb0e00 100644 --- a/ethereumj-core/src/main/resources/version.properties +++ b/ethereumj-core/src/main/resources/version.properties @@ -1,2 +1,2 @@ versionNumber='1.7.0' -databaseVersion=5 \ No newline at end of file +databaseVersion=6 \ No newline at end of file From d7703cb2a0ad8614f09b9fc76e2ad1d74c5a4a29 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 19 Mar 2018 00:16:00 +0300 Subject: [PATCH 57/67] Fixed Casper test (finalizedBlocks storage was not set) --- .../main/java/org/ethereum/casper/core/CasperBlockchain.java | 4 ++++ .../src/test/java/org/ethereum/core/casper/CasperBase.java | 1 + 2 files changed, 5 insertions(+) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 9eeef06658..e732390e33 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -455,4 +455,8 @@ private BigInteger getPoWDifficulty(final Block block) { public void setCasper(CasperFacade casper) { this.casper = casper; } + + public void setFinalizedBlocks(Source finalizedBlocks) { + this.finalizedBlocks = finalizedBlocks; + } } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 55ffaccab5..ca46c0dd52 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -174,6 +174,7 @@ private BlockchainImpl createBlockchain() { blockchain.setParentHeaderValidator(new DependentBlockHeaderRuleAdapter()); blockchain.setProgramInvokeFactory(programInvokeFactory); blockchain.setPruneManager(pruneManager); + ((CasperBlockchain) blockchain).setFinalizedBlocks(new HashMapDB<>()); blockchain.byTest = true; From cce4815a6cdbf2ecdc5536bef5251f9fce8481eb Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 20 Mar 2018 18:32:40 +0300 Subject: [PATCH 58/67] Revert "Revert "Make casper epoch switch free"" This reverts commit 845c0bfd38762d508e5e36359bfa7f3bcea9d294. --- .../ethereum/casper/core/CasperFacade.java | 26 +++++++++++++++++++ .../core/CasperTransactionExecutor.java | 14 +++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index fa3efb581b..5ef5e3924b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -54,6 +54,7 @@ public class CasperFacade { private static final Logger logger = LoggerFactory.getLogger("casper"); private static final byte[] CASPER_VOTE_DATA_HEAD = Hex.decode("e9dc0614"); + private static final byte[] CASPER_EPOCH_DATA_HEAD = Hex.decode("5dcffc17"); private CasperProperties systemProperties; @@ -102,10 +103,23 @@ public Object[] constCall(Block block, String func, Object... funcArgs) { return casper.getByName(func).decodeResult(r.getHReturn()); } + /** + * All service txs shouldn't use gas + * Currently it's votes and epoch change + */ + public boolean isServiceTx(Transaction transaction) { + return isServiceTx(transaction, getAddress()); + } + public boolean isVote(Transaction transaction) { return isVote(transaction, getAddress()); } + public static boolean isServiceTx(Transaction transaction, byte[] casperAddress) { + return isVote(transaction, casperAddress) || + isEpochSwitch(transaction, casperAddress); + } + public static boolean isVote(Transaction transaction, byte[] casperAddress) { if (!Arrays.equals(transaction.getSender(), Transaction.NULL_SENDER)) return false; @@ -118,6 +132,18 @@ public static boolean isVote(Transaction transaction, byte[] casperAddress) { CASPER_VOTE_DATA_HEAD, 0, CASPER_VOTE_DATA_HEAD.length) == 0; } + private static boolean isEpochSwitch(Transaction transaction, byte[] casperAddress) { + if (!Arrays.equals(transaction.getSender(), NULL_SIGN_SENDER.getAddress())) + return false; + if (casperAddress == null) + return false; + if (!Arrays.equals(transaction.getReceiveAddress(), casperAddress)) + return false; + + return FastByteComparisons.compareTo(transaction.getData(), 0, CASPER_EPOCH_DATA_HEAD.length, + CASPER_EPOCH_DATA_HEAD, 0, CASPER_EPOCH_DATA_HEAD.length) == 0; + } + public byte[] getAddress() { init(); return systemProperties.getCasperAddress(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 7e88e57604..a50f927cc0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -76,7 +76,7 @@ public void init() { @Override protected boolean isSignatureValid() { - return isCasperVote() || super.isSignatureValid(); + return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()) || super.isSignatureValid(); } @Override @@ -84,7 +84,7 @@ public void execute() { if (!readyToExecute) return; - if (!localCall && !isCasperVote()) { + if (!localCall && !isCasperServiceTx()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -102,14 +102,14 @@ public void execute() { } } - private boolean isCasperVote() { - return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); + private boolean isCasperServiceTx() { + return CasperFacade.isServiceTx(tx, ((CasperProperties) config).getCasperAddress()); } @Override protected void payRewards(final TransactionExecutionSummary summary) { - if (execError == null && isCasperVote()) { - // Return money to sender for succesful Casper vote + if (execError == null && isCasperServiceTx()) { + // Return money to sender for service Casper tx track.addBalance(tx.getSender(), summary.getFee()); logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); } else { @@ -124,7 +124,7 @@ protected void payRewards(final TransactionExecutionSummary summary) { public long getGasUsed() { long gasUsed = super.getGasUsed(); // Successful Casper vote 0 cost - if (getResult() != null && execError == null && isCasperVote()) { + if (getResult() != null && execError == null && isCasperServiceTx()) { gasUsed = 0; } return gasUsed; From 5e13b15c6b353fbb89a02a83bc5e038e647dcf33 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 20 Mar 2018 19:02:40 +0300 Subject: [PATCH 59/67] Revert "Revert "Don't subtract fee from null sender on succesful casper vote. Instead, block should be INVALID"" This reverts commit 0cc765dc4698382d92b651ed7a047aa60653405e. --- .../casper/core/CasperBlockchain.java | 27 +++++++ .../core/CasperTransactionExecutor.java | 14 ++-- .../org/ethereum/core/BlockchainImpl.java | 73 ++++++++++--------- 3 files changed, 74 insertions(+), 40 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index e732390e33..3eda993f20 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -235,6 +235,33 @@ private void finalizeCheckpoint(final Block block) { } } + @Override + protected boolean checkBlockSummary(BlockSummary summary, Repository track) { + boolean res = super.checkBlockSummary(summary, track); + if (!res) { // Already bad block + return false; + } + + // Casper-specific checks + + // Check for failed casper txs + TransactionReceipt failedCasperVote = null; + for (int i = 0; i < summary.getReceipts().size(); ++i) { + TransactionReceipt receipt = summary.getReceipts().get(i); + if(!receipt.isSuccessful() && casper.isVote(receipt.getTransaction())) { + failedCasperVote = receipt; + break; + } + } + if (failedCasperVote != null) { + logger.warn("Block contains failed casper vote (receipt: {}, tx: {})", + failedCasperVote, failedCasperVote.getTransaction()); + return false; + } + + return true; + } + @Override protected BlockSummary applyBlock(Repository track, Block block) { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index a50f927cc0..c2ccc53e7c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -76,7 +76,7 @@ public void init() { @Override protected boolean isSignatureValid() { - return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()) || super.isSignatureValid(); + return isCasperVote() || super.isSignatureValid(); } @Override @@ -84,7 +84,7 @@ public void execute() { if (!readyToExecute) return; - if (!localCall && !isCasperServiceTx()) { + if (!localCall && !isCasperVote()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -106,9 +106,13 @@ private boolean isCasperServiceTx() { return CasperFacade.isServiceTx(tx, ((CasperProperties) config).getCasperAddress()); } + private boolean isCasperVote() { + return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); + } + @Override protected void payRewards(final TransactionExecutionSummary summary) { - if (execError == null && isCasperServiceTx()) { + if (isCasperServiceTx()) { // Return money to sender for service Casper tx track.addBalance(tx.getSender(), summary.getFee()); logger.info("Refunded successful Casper Vote from [{}]", Hex.toHexString(tx.getSender())); @@ -123,8 +127,8 @@ protected void payRewards(final TransactionExecutionSummary summary) { @Override public long getGasUsed() { long gasUsed = super.getGasUsed(); - // Successful Casper vote 0 cost - if (getResult() != null && execError == null && isCasperServiceTx()) { + // Casper service txs have 0 cost. If it's failed, it'll be discarded on higher level + if (isCasperServiceTx()) { gasUsed = 0; } return gasUsed; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java index 24fbb8f9db..22894691ce 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/BlockchainImpl.java @@ -592,64 +592,67 @@ public synchronized BlockSummary addImpl(Repository repo, final Block block) { } BlockSummary summary = processBlock(repo, block); - final List receipts = summary.getReceipts(); // Sanity checks + if(!checkBlockSummary(summary, repo)) { + repo.rollback(); + summary = null; + } + + if (summary != null) { + final List receipts = summary.getReceipts(); + repo.commit(); + updateTotalDifficulty(block); + summary.setTotalDifficulty(getTotalDifficulty()); + + if (!byTest) { + dbFlushManager.commit(() -> { + storeBlock(block, receipts); + repository.commit(); + }); + } else { + storeBlock(block, receipts); + } + } + + return summary; + } + + /** + * Sanity checks of block import result + * @return true if block is good, otherwise false + */ + protected boolean checkBlockSummary(final BlockSummary summary, final Repository track) { + Block block = summary.getBlock(); + final List receipts = summary.getReceipts(); if (!FastByteComparisons.equal(block.getReceiptsRoot(), calcReceiptsTrie(receipts))) { logger.warn("Block's given Receipt Hash doesn't match: {} != {}", Hex.toHexString(block.getReceiptsRoot()), Hex.toHexString(calcReceiptsTrie(receipts))); logger.warn("Calculated receipts: " + receipts); - repo.rollback(); - summary = null; + return false; } if (!FastByteComparisons.equal(block.getLogBloom(), calcLogBloom(receipts))) { logger.warn("Block's given logBloom Hash doesn't match: {} != {}", Hex.toHexString(block.getLogBloom()), Hex.toHexString(calcLogBloom(receipts))); - repo.rollback(); - summary = null; + return false; } - if (!FastByteComparisons.equal(block.getStateRoot(), repo.getRoot())) { + if (!FastByteComparisons.equal(block.getStateRoot(), track.getRoot())) { - stateLogger.warn("BLOCK: State conflict or received invalid block. block: {} worldstate {} mismatch", block.getNumber(), Hex.toHexString(repo.getRoot())); + stateLogger.warn("BLOCK: State conflict or received invalid block. block: {} worldstate {} mismatch", block.getNumber(), Hex.toHexString(track.getRoot())); stateLogger.warn("Conflict block dump: {}", Hex.toHexString(block.getEncoded())); -// track.rollback(); -// repository.rollback(); - repository = repository.getSnapshotTo(origRoot); - - // block is bad so 'rollback' the state root to the original state -// ((RepositoryImpl) repository).setRoot(origRoot); - -// track.rollback(); - // block is bad so 'rollback' the state root to the original state -// ((RepositoryImpl) repository).setRoot(origRoot); - if (config.exitOnBlockConflict() && !byTest) { + track.rollback(); adminInfo.lostConsensus(); System.out.println("CONFLICT: BLOCK #" + block.getNumber() + ", dump: " + Hex.toHexString(block.getEncoded())); System.exit(1); } else { - summary = null; - } - } - - if (summary != null) { - repo.commit(); - updateTotalDifficulty(block); - summary.setTotalDifficulty(getTotalDifficulty()); - - if (!byTest) { - dbFlushManager.commit(() -> { - storeBlock(block, receipts); - repository.commit(); - }); - } else { - storeBlock(block, receipts); + return false; } } - return summary; + return true; // Everything is good! } @Override From 9840b716be4ad25b930df497bda041a880633187 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 21 Mar 2018 00:43:01 +0300 Subject: [PATCH 60/67] Testing that no gas was used for casper service txs and bad casper votes are not included in blocks --- .../service/CasperValidatorService.java | 2 +- .../core/casper/BadCasperValidatorTest.java | 152 ++++++++++++++++++ .../org/ethereum/core/casper/CasperBase.java | 2 +- .../core/casper/CasperEpochSwitchTest.java | 52 +----- .../core/casper/CasperValidatorTest.java | 92 +++++++++-- 5 files changed, 231 insertions(+), 69 deletions(-) create mode 100644 ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 3bed76f556..18bfb3191f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -115,7 +115,7 @@ private byte[] validationContractCode(byte[] address) { return Hex.decode(part1 + Hex.toHexString(address) + part2); } - private byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { + protected byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { byte[] sigHash = sha3(RLP.smartEncodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch)); byte[] vrs = make3IntSignature(sigHash, sender); return RLP.smartEncodeList(validatorIndex, new ByteArrayWrapper(targetHash), targetEpoch, sourceEpoch, new ByteArrayWrapper(vrs)); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java new file mode 100644 index 0000000000..5aadf567d1 --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.core.casper; + +import org.ethereum.casper.service.CasperValidatorService; +import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.core.Block; +import org.ethereum.core.BlockSummary; +import org.ethereum.crypto.ECKey; +import org.ethereum.listener.EthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; +import org.ethereum.sync.SyncManager; +import org.ethereum.util.FastByteComparisons; +import org.ethereum.util.blockchain.EtherUtil; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import org.spongycastle.util.encoders.Hex; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; +import static org.ethereum.crypto.HashUtil.sha3; + +@Ignore // Takes too long to run usually +public class BadCasperValidatorTest extends CasperBase { + + private int totalVotes = 0; + private int totalEpochs = 0; + + private Integer DEPOSIT_SIZE_ETH = 2000; + + protected CasperValidatorService service; + + final ECKey coinbase = ECKey.fromPrivate(sha3("cow".getBytes())); // Premined in light genesis + + @Override + BlockchainNetConfig config() { + return CasperValidatorTest.CASPER_EASY_CONFIG; + } + + @Before + @Override + public void setup() throws Exception { + super.setup(); + // Init with light Genesis + Resource casperGenesis = new ClassPathResource("/genesis/casper-test.json"); + systemProperties.useGenesis(casperGenesis.getInputStream()); + loadBlockchain(); + + + + BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; + assertEquals(0, zeroEpoch.longValue()); + + systemProperties.overrideParams( + "casper.validator.enabled", "true", + "casper.validator.privateKey", Hex.toHexString(coinbase.getPrivKeyBytes()), + "casper.validator.deposit", DEPOSIT_SIZE_ETH.toString() + ); + + bc.createBlock(); + + this.service = new CasperValidatorService(ethereum, systemProperties) { + @Override + protected byte[] makeVote(long validatorIndex, byte[] targetHash, long targetEpoch, long sourceEpoch, ECKey sender) { + // Make it send incorrect votes + return super.makeVote(validatorIndex, targetHash, targetEpoch + 1, sourceEpoch, sender); + } + }; + service.setBlockchain(blockchain); + SyncManager syncManager = Mockito.mock(SyncManager.class); + Mockito.when(syncManager.isSyncDone()).thenReturn(true); + service.setSyncManager(syncManager); + service.setCasper(casper); + service.setRepository(repository); + service.start(); + } + + private EthereumListener assertCasperReceipts = new EthereumListenerAdapter(){ + @Override + public void onBlock(BlockSummary blockSummary) { + blockSummary.getReceipts().stream().forEach(receipt -> { + if (FastByteComparisons.equal(receipt.getTransaction().getReceiveAddress(), casper.getAddress())) { + // We don't expect any error receipts + assert receipt.isSuccessful(); + // Following should be true for new epoch and votes, let's check it + if (casper.isServiceTx(receipt.getTransaction())) { + assert receipt.getGasUsed().length == 0; + assert blockSummary.getBlock().getGasUsed() == 0; + if (casper.isVote(receipt.getTransaction())) { + ++totalVotes; + } else { + ++totalEpochs; + } + } + } + }); + } + }; + + + /** + * Let's send bad votes + * these votes should not be included in blocks + * plus deposit size should decrease + */ + @Test + public void badVotesValidatorTest() throws Exception { + defaultListener.addListener(assertCasperReceipts); + + for (int i = 0; i < 10; ++i) { + Block block = bc.createBlock(); + } + BigDecimal curDeposit = calculateCurrentDepositSize(1); + assertTrue(curDeposit.compareTo(new BigDecimal(EtherUtil.convert(DEPOSIT_SIZE_ETH, EtherUtil.Unit.ETHER))) == 0); + + for (int i = 0; i < 300; ++i) { + Block block = bc.createBlock(); + } + assertEquals(6, totalEpochs); // floor division (300 + 10) / 50 + assertEquals(0, totalVotes); // No vote was included in any block + + // We've lost some money from our deposit because we are sleeping + BigDecimal decreasedDeposit = calculateCurrentDepositSize(1); + assertTrue(decreasedDeposit.compareTo(new BigDecimal(EtherUtil.convert(DEPOSIT_SIZE_ETH, EtherUtil.Unit.ETHER))) < 0); + } + + protected BigDecimal calculateCurrentDepositSize(long validatorIndex) { + return CasperValidatorTest.calculateCurrentDepositSize(validatorIndex, casper); + } +} diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index 24966bd023..f1fba2c209 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -99,7 +99,7 @@ public SystemProperties systemProperties() { CasperBlockchain blockchain; - private CompositeEthereumListener defaultListener = new CompositeEthereumListener(); + protected CompositeEthereumListener defaultListener = new CompositeEthereumListener(); @InjectMocks EthereumImpl ethereum = new EthereumImpl(systemProperties, defaultListener); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index 9c5332725e..dfcebad014 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -37,59 +37,9 @@ public class CasperEpochSwitchTest extends CasperBase { - class CasperEasyConfig extends BaseNetConfig { - class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { - public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork - } - - private final GasCost NEW_GAS_COST = new CasperEasyConfig.CasperGasCost(); - - private class CasperConfig extends ByzantiumConfig { - private final Constants constants; - CasperConfig(BlockchainConfig parent) { - - super(parent); - constants = new ConstantsAdapter(super.getConstants()) { - private final BigInteger BLOCK_REWARD = new BigInteger("1000000000000000000"); // 1 ETH - - private final BigInteger MINIMUM_DIFFICULTY = BigInteger.ONE; - - @Override - public BigInteger getBLOCK_REWARD() { - return BLOCK_REWARD; - } - - @Override - public BigInteger getMINIMUM_DIFFICULTY() { - return MINIMUM_DIFFICULTY; - } - }; - } - - @Override - public GasCost getGasCost() { - return NEW_GAS_COST; - } - - @Override - public boolean eip161() { - return false; - } - - @Override - public Constants getConstants() { - return constants; - } - } - - public CasperEasyConfig() { - add(0, new CasperConfig(new FrontierConfig())); - } - } - @Override BlockchainNetConfig config() { - return new CasperEasyConfig(); + return CasperValidatorTest.CASPER_EASY_CONFIG; } @Test diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 730f68b389..1293c86a0e 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -17,6 +17,7 @@ */ package org.ethereum.core.casper; +import org.ethereum.casper.core.CasperFacade; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.Constants; @@ -26,11 +27,16 @@ import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; import org.ethereum.core.Block; +import org.ethereum.core.BlockSummary; import org.ethereum.crypto.ECKey; import org.ethereum.casper.service.CasperValidatorService; +import org.ethereum.listener.EthereumListener; +import org.ethereum.listener.EthereumListenerAdapter; import org.ethereum.sync.SyncManager; +import org.ethereum.util.FastByteComparisons; import org.ethereum.util.blockchain.EtherUtil; import org.ethereum.vm.GasCost; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; @@ -48,7 +54,16 @@ @Ignore // Takes too long to run usually public class CasperValidatorTest extends CasperBase { - class CasperEasyConfig extends BaseNetConfig { + private int totalVotes = 0; + private int totalEpochs = 0; + + private Integer DEPOSIT_SIZE_ETH = 2000; + + protected CasperValidatorService service; + + final ECKey coinbase = ECKey.fromPrivate(sha3("cow".getBytes())); // Premined in light genesis + + private static class CasperEasyConfig extends BaseNetConfig { class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork } @@ -98,19 +113,23 @@ public CasperEasyConfig() { } } + protected final static BlockchainNetConfig CASPER_EASY_CONFIG = new CasperEasyConfig(); + @Override BlockchainNetConfig config() { - return new CasperEasyConfig(); + return CASPER_EASY_CONFIG; } - @Test - public void validatorTest() throws Exception { + @Before + @Override + public void setup() throws Exception { + super.setup(); // Init with light Genesis Resource casperGenesis = new ClassPathResource("/genesis/casper-test.json"); systemProperties.useGenesis(casperGenesis.getInputStream()); loadBlockchain(); - final ECKey coinbase = ECKey.fromPrivate(sha3("cow".getBytes())); // Premined in light genesis + BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); @@ -118,13 +137,13 @@ public void validatorTest() throws Exception { systemProperties.overrideParams( "casper.validator.enabled", "true", "casper.validator.privateKey", Hex.toHexString(coinbase.getPrivKeyBytes()), - "casper.validator.deposit", "2000" + "casper.validator.deposit", DEPOSIT_SIZE_ETH.toString() ); - bc.createBlock(); - CasperValidatorService service = new CasperValidatorService(ethereum, systemProperties); + + this.service = new CasperValidatorService(ethereum, systemProperties); service.setBlockchain(blockchain); SyncManager syncManager = Mockito.mock(SyncManager.class); Mockito.when(syncManager.isSyncDone()).thenReturn(true); @@ -132,25 +151,29 @@ public void validatorTest() throws Exception { service.setCasper(casper); service.setRepository(repository); service.start(); + } + @Test + public void complexValidatorTest() throws Exception { + defaultListener.addListener(assertCasperReceipts); BigInteger initialBalance = ethereum.getRepository().getBalance(coinbase.getAddress()); for (int i = 0; i < 10; ++i) { Block block = bc.createBlock(); } - // Deposit is scaled, so it's neither in wei nor in ETH. Should be 2000 ETH - // TODO: Convert to ETH or wei - BigDecimal curDeposit = (BigDecimal) casper.constCall("get_validators__deposit", 1)[0]; - assertTrue(curDeposit.compareTo(new BigDecimal("200000000000")) == 0); + + BigDecimal curDeposit = calculateCurrentDepositSize(1); + assertTrue(curDeposit.compareTo(new BigDecimal(EtherUtil.convert(DEPOSIT_SIZE_ETH, EtherUtil.Unit.ETHER))) == 0); for (int i = 0; i < 300; ++i) { Block block = bc.createBlock(); } // We've earned some money on top of our deposit as premium for our votes, which finalized epochs!! - BigDecimal increasedDeposit = (BigDecimal) casper.constCall("get_validators__deposit", 1)[0]; - assertTrue(increasedDeposit.compareTo(new BigDecimal("200000000000")) > 0); + BigDecimal increasedDeposit = calculateCurrentDepositSize(1); + assertTrue(increasedDeposit.compareTo(new BigDecimal(EtherUtil.convert(DEPOSIT_SIZE_ETH, EtherUtil.Unit.ETHER))) > 0); // We've left less than (initial - 2000 ETH) - assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(initialBalance.subtract(EtherUtil.convert(2000, EtherUtil.Unit.ETHER))) < 0); + assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()) + .compareTo(initialBalance.subtract(EtherUtil.convert(DEPOSIT_SIZE_ETH, EtherUtil.Unit.ETHER))) < 0); // Let's logout service.voteThenLogout(); // Withdrawal delay is 5 epochs + 1 vote epoch + overhead @@ -160,7 +183,44 @@ public void validatorTest() throws Exception { // We should have more than initialBalance in the end assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(initialBalance) > 0); - // TODO: add more checking with listeners etc. + // Check that assertCasperReceipts was called + assertEquals(14, totalEpochs); // floor division (300 + 400 + 10) / 50 + assertEquals(6, totalVotes); + // TODO: add more validators } + + protected BigDecimal calculateCurrentDepositSize(long validatorIndex) { + return calculateCurrentDepositSize(validatorIndex, casper); + } + + protected static BigDecimal calculateCurrentDepositSize(long validatorIndex, CasperFacade casperFacade) { + BigDecimal scaleFactor = (BigDecimal) casperFacade.constCall("get_deposit_scale_factor", + (BigInteger) casperFacade.constCall("get_current_epoch")[0])[0]; + BigDecimal curDeposit = (BigDecimal) casperFacade.constCall("get_validators__deposit", validatorIndex)[0]; + BigDecimal scaledDepositWei = curDeposit.multiply(scaleFactor); + return scaledDepositWei; + } + + private EthereumListener assertCasperReceipts = new EthereumListenerAdapter(){ + @Override + public void onBlock(BlockSummary blockSummary) { + blockSummary.getReceipts().stream().forEach(receipt -> { + if (FastByteComparisons.equal(receipt.getTransaction().getReceiveAddress(), casper.getAddress())) { + // We don't expect any error receipts + assert receipt.isSuccessful(); + // Following should be true for new epoch and votes, let's check it + if (casper.isServiceTx(receipt.getTransaction())) { + assert receipt.getGasUsed().length == 0; + assert blockSummary.getBlock().getGasUsed() == 0; + if (casper.isVote(receipt.getTransaction())) { + ++totalVotes; + } else { + ++totalEpochs; + } + } + } + }); + } + }; } From feb3f917c9b9ea8dd1b776fb69f6194addb4aa74 Mon Sep 17 00:00:00 2001 From: Mikhail Kalinin Date: Sun, 8 Apr 2018 17:42:30 +0600 Subject: [PATCH 61/67] CasperFacade: use apache.commons Pair instead of javafx.util Pair --- .../src/main/java/org/ethereum/casper/core/CasperFacade.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 5ef5e3924b..4fc8ed9f4e 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -17,8 +17,8 @@ */ package org.ethereum.casper.core; -import javafx.util.Pair; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Pair; import org.ethereum.casper.config.CasperProperties; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; @@ -248,6 +248,6 @@ private Pair> makeInitTxes() { throw new RuntimeException("Failed to generate Casper init transactions", ex); } - return new Pair<>(casperAddress, txs); + return Pair.of(casperAddress, txs); } } From 84a32546f34cfd0359d41508fc0be56f07f0b379 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 9 Apr 2018 20:27:08 +0300 Subject: [PATCH 62/67] Added transaction executor note for casper service txs --- .../java/org/ethereum/casper/core/CasperTransactionExecutor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index c2ccc53e7c..6276f58083 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -128,6 +128,7 @@ protected void payRewards(final TransactionExecutionSummary summary) { public long getGasUsed() { long gasUsed = super.getGasUsed(); // Casper service txs have 0 cost. If it's failed, it'll be discarded on higher level + // FIXME: NOTE: (gasLeftOver + gasRefund) is used in rewards debug, so adjusting only gasUsed may produce some bugs in the future if (isCasperServiceTx()) { gasUsed = 0; } From 6760e96561ffb09ff85ce81afe76cc2ebc7e0eef Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Mon, 9 Apr 2018 21:12:28 +0300 Subject: [PATCH 63/67] Bump Casper contract to commit #251a1a349fddd90b40febf9781ffc92e8c6a4a0e --- .../config/net/CasperTestNetConfig.java | 1 + .../casper/core/CasperBlockchain.java | 12 +- .../ethereum/casper/core/CasperFacade.java | 2 + .../service/CasperValidatorService.java | 58 +- .../org/ethereum/core/CallTransaction.java | 2 + .../src/main/resources/casper/casper.abi | 1267 ++++---- .../src/main/resources/casper/casper.bin | 2 +- .../src/main/resources/casper/casper.lll | 2666 ----------------- .../core/casper/BadCasperValidatorTest.java | 2 +- .../core/casper/CasperEpochSwitchTest.java | 10 +- .../core/casper/CasperStateInitTest.java | 1 + .../core/casper/CasperValidatorTest.java | 18 +- 12 files changed, 782 insertions(+), 3259 deletions(-) delete mode 100644 ethereumj-core/src/main/resources/casper/casper.lll diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java index f9224dc4b0..e9be295c4b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java @@ -34,6 +34,7 @@ public class CasperTestNetConfig extends BaseNetConfig { public static final int EPOCH_LENGTH = 50; public static final int WITHDRAWAL_DELAY = 5; + public static final int DYNASTY_LOGOUT_DELAY = 5; public static final double BASE_INTEREST_FACTOR = 0.1; public static final double BASE_PENALTY_FACTOR = 0.0001; public static final int MIN_DEPOSIT_ETH = 1500; diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 3eda993f20..83fbd6dd99 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -121,7 +121,7 @@ private boolean switchRevertsFinalizedBlock(final Block block) { } private BigInteger getScore(final Block block) { - Object[] res = casper.constCall(block, "get_last_justified_epoch"); + Object[] res = casper.constCall(block, "last_justified_epoch"); return ((BigInteger) res[0]).multiply(PRETTY_BIG).add(getPoWDifficulty(block)); } @@ -210,19 +210,19 @@ private synchronized ImportResult casperConnect(final Block block) { * Finalizes Casper epoch checkpoint if needed */ private void finalizeCheckpoint(final Block block) { - Object[] res = casper.constCall(block, "get_last_finalized_epoch"); + Object[] res = casper.constCall(block, "last_finalized_epoch"); long finalizedEpoch = ((BigInteger) res[0]).longValue(); - Object[] res2 = casper.constCall(block, "get_current_epoch"); + Object[] res2 = casper.constCall(block, "current_epoch"); long currentEpoch = ((BigInteger) res2[0]).longValue(); if (finalizedEpoch == currentEpoch - 1) { // Actually one hash per epoch, just the getter for array - Object[] res3 = casper.constCall(block, "get_checkpoint_hashes", finalizedEpoch); + Object[] res3 = casper.constCall(block, "checkpoint_hashes", finalizedEpoch); byte[] checkpointHash = (byte[]) res3[0]; if (!Arrays.areEqual(checkpointHash, new byte[32])) { // new byte[32] == 00-filled Block histBlock = getBlockByHash(checkpointHash); - Object[] res4 = casper.constCall(histBlock, "get_total_curdyn_deposits"); + Object[] res4 = casper.constCall(histBlock, "total_curdyn_deposits_scaled"); BigInteger curDeposits = (BigInteger) res4[0]; - Object[] res5 = casper.constCall(histBlock, "get_total_prevdyn_deposits"); + Object[] res5 = casper.constCall(histBlock, "total_prevdyn_deposits_scaled"); BigInteger prevDeposits = (BigInteger) res5[0]; if (curDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0 && prevDeposits.compareTo(NON_REVERT_MIN_DEPOSIT) > 0) { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index 4fc8ed9f4e..a2549d721f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -43,6 +43,7 @@ import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_INTEREST_FACTOR; import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_PENALTY_FACTOR; +import static org.ethereum.casper.config.net.CasperTestNetConfig.DYNASTY_LOGOUT_DELAY; import static org.ethereum.casper.config.net.CasperTestNetConfig.MIN_DEPOSIT_ETH; import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; @@ -223,6 +224,7 @@ private Pair> makeInitTxes() { byte[] casperInit = contract.getConstructor().encodeArguments( systemProperties.getCasperEpochLength(), // Epoch length WITHDRAWAL_DELAY, // Withdrawal delay + DYNASTY_LOGOUT_DELAY, // Logout delay ECKey.fromPrivate(sha3("0".getBytes())).getAddress(), // Owner sigHasherContract, // Signature hasher contract purityCheckerContract, // Purity checker contract diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index 18bfb3191f..e4ab02a42d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -299,13 +299,13 @@ private Transaction makeTx(byte[] receiveAddress, BigInteger value, byte[] data, private long getValidatorIndex() { - return constCallCasperForLong("get_validator_indexes", new ByteArrayWrapper(coinbase.getAddress())); + return constCallCasperForLong("validator_indexes", new ByteArrayWrapper(coinbase.getAddress())); } private void initValContractAddress() { // Actually it's not used after deposit if (valContractAddress != null) return; - byte[] address = (byte[]) casper.constCall("get_validators__addr", getValidatorIndex())[0]; + byte[] address = (byte[]) casper.constCall("validators__addr", getValidatorIndex())[0]; if (!Arrays.equals(address, new byte[20])) { logger.info("Valcode contract found at {}", address); this.valContractAddress = address; @@ -380,9 +380,9 @@ private Transaction makeWithdrawTx(long validatorIndex) { } private boolean isLoggedIn(long targetEpoch, long validatorIndex) { - long startDynasty = constCallCasperForLong("get_validators__start_dynasty", validatorIndex); - long endDynasty = constCallCasperForLong("get_validators__end_dynasty", validatorIndex); - long currentDynasty = constCallCasperForLong("get_dynasty_in_epoch", targetEpoch); + long startDynasty = constCallCasperForLong("validators__start_dynasty", validatorIndex); + long endDynasty = constCallCasperForLong("validators__end_dynasty", validatorIndex); + long currentDynasty = constCallCasperForLong("dynasty_in_epoch", targetEpoch); long pastDynasty = currentDynasty - 1; boolean inCurrentDynasty = ((startDynasty <= currentDynasty) && (currentDynasty < endDynasty)); @@ -426,7 +426,7 @@ private long getEpoch() { } private long getCurrentEpoch() { // FIXME: WHY there are 2 methods for the same thing??? - return constCallCasperForLong("get_current_epoch"); + return constCallCasperForLong("current_epoch"); } private boolean vote() { @@ -492,12 +492,12 @@ private void checkWithdrawable() { setState(LOGGED_OUT); return; } - long validatorEndDynasty = constCallCasperForLong("get_validators__end_dynasty", validatorIndex); - long endEpoch = constCallCasperForLong("get_dynasty_start_epoch", validatorEndDynasty + 1); + long validatorEndDynasty = constCallCasperForLong("validators__end_dynasty", validatorIndex); + long endEpoch = constCallCasperForLong("dynasty_start_epoch", validatorEndDynasty + 1); // Check Casper to see if we can withdraw long curEpoch = getCurrentEpoch(); - long withdrawalDelay = constCallCasperForLong("get_withdrawal_delay"); + long withdrawalDelay = constCallCasperForLong("withdrawal_delay"); if (curEpoch >= (endEpoch + withdrawalDelay)) { // Make withdraw tx & broadcast Transaction withdrawTx = makeWithdrawTx(validatorIndex); @@ -513,44 +513,44 @@ private void checkWithdrawable() { private void checkWithdrawn() { // Check that we have been withdrawn--validator index will now be zero - if (constCallCasperForLong("get_validator_indexes", new ByteArrayWrapper(coinbase.getAddress())) == 0) { + if (constCallCasperForLong("validator_indexes", new ByteArrayWrapper(coinbase.getAddress())) == 0) { setState(LOGGED_OUT); } } private void logCasperInfo() { long curEpoch = getCurrentEpoch(); - long expectedSourceEpoch = constCallCasperForLong("get_expected_source_epoch"); - BigInteger curDeposits = (BigInteger) casper.constCall("get_total_curdyn_deposits")[0]; - BigInteger prevDeposits = (BigInteger) casper.constCall("get_total_prevdyn_deposits")[0]; - BigDecimal curVotes = (BigDecimal) casper.constCall("get_votes__cur_dyn_votes", curEpoch, expectedSourceEpoch)[0]; - BigDecimal prevVotes = (BigDecimal) casper.constCall("get_votes__prev_dyn_votes", curEpoch, expectedSourceEpoch)[0]; - BigDecimal scaleFactor = (BigDecimal) casper.constCall("get_deposit_scale_factor", curEpoch)[0]; + long expectedSourceEpoch = constCallCasperForLong("expected_source_epoch"); + BigInteger curDepositsScaled = (BigInteger) casper.constCall("total_curdyn_deposits_scaled")[0]; + BigInteger prevDepositsScaled = (BigInteger) casper.constCall("total_prevdyn_deposits_scaled")[0]; + BigDecimal curVotes = (BigDecimal) casper.constCall("votes__cur_dyn_votes", curEpoch, expectedSourceEpoch)[0]; + BigDecimal prevVotes = (BigDecimal) casper.constCall("votes__prev_dyn_votes", curEpoch, expectedSourceEpoch)[0]; + BigDecimal scaleFactor = (BigDecimal) casper.constCall("deposit_scale_factor", curEpoch)[0]; BigDecimal curVotesScaled = curVotes.multiply(scaleFactor); BigDecimal prevVotesScaled = prevVotes.multiply(scaleFactor); BigDecimal curVotesPct = BigDecimal.ZERO; BigDecimal prevVotesPct = BigDecimal.ZERO; - if (curDeposits.compareTo(BigInteger.ZERO) > 0 ) { - curVotesPct = curVotesScaled.multiply(BigDecimal.valueOf(100)).divide(new BigDecimal(curDeposits), MathContext.DECIMAL32); + if (curDepositsScaled.compareTo(BigInteger.ZERO) > 0 ) { + curVotesPct = curVotesScaled.multiply(BigDecimal.valueOf(100)).divide(new BigDecimal(curDepositsScaled), MathContext.DECIMAL32); } - if (prevDeposits.compareTo(BigInteger.ZERO) > 0 ) { - prevVotesPct = prevVotesScaled.multiply(BigDecimal.valueOf(100)).divide(new BigDecimal(prevDeposits), MathContext.DECIMAL32); + if (prevDepositsScaled.compareTo(BigInteger.ZERO) > 0 ) { + prevVotesPct = prevVotesScaled.multiply(BigDecimal.valueOf(100)).divide(new BigDecimal(prevDepositsScaled), MathContext.DECIMAL32); } - long lastFinalizedEpoch = constCallCasperForLong("get_last_finalized_epoch"); - long lastJustifiedEpoch = constCallCasperForLong("get_last_justified_epoch"); - BigDecimal lastNonvoterRescale = (BigDecimal) casper.constCall("get_last_nonvoter_rescale")[0]; - BigDecimal lastVoterRescale = (BigDecimal) casper.constCall("get_last_voter_rescale")[0]; + long lastFinalizedEpoch = constCallCasperForLong("last_finalized_epoch"); + long lastJustifiedEpoch = constCallCasperForLong("last_justified_epoch"); + BigDecimal lastNonvoterRescale = (BigDecimal) casper.constCall("last_nonvoter_rescale")[0]; + BigDecimal lastVoterRescale = (BigDecimal) casper.constCall("last_voter_rescale")[0]; String logStr = String.format( "CASPER STATUS: epoch %d, %.3f / %.3f ETH (%.2f %%) voted from current dynasty, " + "%.3f / %.3f ETH (%.2f %%) voted from previous dynasty, last finalized epoch %d justified %d " + "expected source %d. Nonvoter deposits last rescaled %.5fx, voter deposits %.5fx", curEpoch, curVotesScaled.divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), - new BigDecimal(curDeposits).divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), + new BigDecimal(curDepositsScaled).divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), curVotesPct, prevVotesScaled.divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), - new BigDecimal(prevDeposits).divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), + new BigDecimal(prevDepositsScaled).divide(BigDecimal.TEN.pow(18), MathContext.DECIMAL32), prevVotesPct, lastFinalizedEpoch, lastJustifiedEpoch, @@ -560,7 +560,7 @@ private void logCasperInfo() { logger.info(logStr); long valIndex = getValidatorIndex(); - BigDecimal myDeposit = (BigDecimal) casper.constCall("get_validators__deposit", valIndex)[0]; + BigDecimal myDeposit = (BigDecimal) casper.constCall("validators__deposit", valIndex)[0]; BigDecimal myDepositScaled = myDeposit.multiply(scaleFactor); String myStr = String.format( "MY VALIDATOR STATUS: epoch %d, index #%d, deposit: %.3f ETH", @@ -581,8 +581,8 @@ private byte[] getRecommendedVoteData(long validatorIndex) { // target_hash = self.epoch_blockhash(current_epoch) // ANSWER: Though, I'll try - byte[] targetHash = (byte[]) casper.constCall("get_recommended_target_hash")[0]; - long sourceEpoch = constCallCasperForLong("get_recommended_source_epoch"); + byte[] targetHash = (byte[]) casper.constCall("recommended_target_hash")[0]; + long sourceEpoch = constCallCasperForLong("recommended_source_epoch"); if (targetHash == null) { return null; diff --git a/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java b/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java index 1a0422ff33..c93277a3f1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/CallTransaction.java @@ -26,6 +26,7 @@ import static org.ethereum.util.ByteUtil.longToBytesNoLeadZeroes; import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -100,6 +101,7 @@ public enum FunctionType { fallback } + @JsonIgnoreProperties(ignoreUnknown = true) public static class Function { public boolean anonymous; public boolean constant; diff --git a/ethereumj-core/src/main/resources/casper/casper.abi b/ethereumj-core/src/main/resources/casper/casper.abi index 7bf16fa1ad..46d0b96b9d 100644 --- a/ethereumj-core/src/main/resources/casper/casper.abi +++ b/ethereumj-core/src/main/resources/casper/casper.abi @@ -1,545 +1,726 @@ [{ - "name": "__init__", - "outputs": [], - "inputs": [{ - "type": "int128", - "name": "_epoch_length" - }, { - "type": "int128", - "name": "_withdrawal_delay" - }, { - "type": "address", - "name": "_owner" - }, { - "type": "address", - "name": "_sighasher" - }, { - "type": "address", - "name": "_purity_checker" - }, { - "type": "decimal10", - "name": "_base_interest_factor" - }, { - "type": "decimal10", - "name": "_base_penalty_factor" - }, { - "type": "int128", - "name": "_min_deposit_size" - }], - "constant": false, - "payable": false, - "type": "constructor" -}, { - "name": "get_main_hash_voted_frac", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_deposit_size", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "validator_index" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_total_curdyn_deposits", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_total_prevdyn_deposits", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_recommended_source_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_recommended_target_hash", - "outputs": [{ - "type": "bytes32", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "initialize_epoch", - "outputs": [], - "inputs": [{ - "type": "int128", - "name": "epoch" - }], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "deposit", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "validation_addr" - }, { - "type": "address", - "name": "withdrawal_addr" - }], - "constant": false, - "payable": true, - "type": "function" -}, { - "name": "logout", - "outputs": [], - "inputs": [{ - "type": "bytes", - "name": "logout_msg" - }], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "withdraw", - "outputs": [], - "inputs": [{ - "type": "int128", - "name": "validator_index" - }], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "vote", - "outputs": [], - "inputs": [{ - "type": "bytes", - "name": "vote_msg" - }], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "slash", - "outputs": [], - "inputs": [{ - "type": "bytes", - "name": "vote_msg_1" - }, { - "type": "bytes", - "name": "vote_msg_2" - }], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "owner_withdraw", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "change_owner", - "outputs": [], - "inputs": [{ - "type": "address", - "name": "new_owner" - }], - "constant": false, - "payable": false, - "type": "function" -}, { - "name": "get_validators__deposit", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_validators__start_dynasty", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_validators__end_dynasty", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_validators__addr", - "outputs": [{ - "type": "address", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_validators__withdrawal_addr", - "outputs": [{ - "type": "address", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_checkpoint_hashes", - "outputs": [{ - "type": "bytes32", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_nextValidatorIndex", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_validator_indexes", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [{ - "type": "address", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_dynasty", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_next_dynasty_wei_delta", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_second_next_dynasty_wei_delta", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_dynasty_start_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_dynasty_in_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_votes__cur_dyn_votes", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }, { - "type": "int128", - "name": "arg1" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_votes__prev_dyn_votes", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }, { - "type": "int128", - "name": "arg1" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_votes__vote_bitmap", - "outputs": [{ - "type": "uint256", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }, { - "type": "bytes32", - "name": "arg1" - }, { - "type": "int128", - "name": "arg2" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_votes__is_justified", - "outputs": [{ - "type": "bool", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_votes__is_finalized", - "outputs": [{ - "type": "bool", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_main_hash_justified", - "outputs": [{ - "type": "bool", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_deposit_scale_factor", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [{ - "type": "int128", - "name": "arg0" - }], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_last_nonvoter_rescale", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_last_voter_rescale", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_epoch_length", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_withdrawal_delay", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_current_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_last_finalized_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_last_justified_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_expected_source_epoch", - "outputs": [{ - "type": "int128", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_reward_factor", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_base_interest_factor", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" -}, { - "name": "get_base_penalty_factor", - "outputs": [{ - "type": "decimal10", - "name": "out" - }], - "inputs": [], - "constant": true, - "payable": false, - "type": "function" + "name": "Deposit", + "inputs": [{ + "type": "address", + "name": "_from", + "indexed": true + }, { + "type": "int128", + "name": "_validator_index", + "indexed": true + }, { + "type": "address", + "name": "_validation_address", + "indexed": false + }, { + "type": "int128", + "name": "_start_dyn", + "indexed": false + }, { + "type": "int128", + "name": "_amount", + "indexed": false + }], + "anonymous": false, + "type": "event" +}, { + "name": "Vote", + "inputs": [{ + "type": "address", + "name": "_from", + "indexed": true + }, { + "type": "int128", + "name": "_validator_index", + "indexed": true + }, { + "type": "bytes32", + "name": "_target_hash", + "indexed": true + }, { + "type": "int128", + "name": "_target_epoch", + "indexed": false + }, { + "type": "int128", + "name": "_source_epoch", + "indexed": false + }], + "anonymous": false, + "type": "event" +}, { + "name": "Logout", + "inputs": [{ + "type": "address", + "name": "_from", + "indexed": true + }, { + "type": "int128", + "name": "_validator_index", + "indexed": true + }, { + "type": "int128", + "name": "_end_dyn", + "indexed": false + }], + "anonymous": false, + "type": "event" +}, { + "name": "Withdraw", + "inputs": [{ + "type": "address", + "name": "_to", + "indexed": true + }, { + "type": "int128", + "name": "_validator_index", + "indexed": true + }, { + "type": "int128", + "name": "_amount", + "indexed": false + }], + "anonymous": false, + "type": "event" +}, { + "name": "Slash", + "inputs": [{ + "type": "address", + "name": "_from", + "indexed": true + }, { + "type": "address", + "name": "_offender", + "indexed": true + }, { + "type": "int128", + "name": "_offender_index", + "indexed": true + }, { + "type": "int128", + "name": "_bounty", + "indexed": false + }, { + "type": "int128", + "name": "_destroyed", + "indexed": false + }], + "anonymous": false, + "type": "event" +}, { + "name": "Epoch", + "inputs": [{ + "type": "int128", + "name": "_number", + "indexed": true + }, { + "type": "bytes32", + "name": "_checkpoint_hash", + "indexed": true + }, { + "type": "bool", + "name": "_is_justified", + "indexed": false + }, { + "type": "bool", + "name": "_is_finalized", + "indexed": false + }], + "anonymous": false, + "type": "event" +}, { + "name": "__init__", + "outputs": [], + "inputs": [{ + "type": "int128", + "name": "_epoch_length" + }, { + "type": "int128", + "name": "_withdrawal_delay" + }, { + "type": "int128", + "name": "_dynasty_logout_delay" + }, { + "type": "address", + "name": "_owner" + }, { + "type": "address", + "name": "_sighasher" + }, { + "type": "address", + "name": "_purity_checker" + }, { + "type": "decimal10", + "name": "_base_interest_factor" + }, { + "type": "decimal10", + "name": "_base_penalty_factor" + }, { + "type": "int128", + "name": "_min_deposit_size" + }], + "constant": false, + "payable": false, + "type": "constructor" +}, { + "name": "main_hash_voted_frac", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 2683 +}, { + "name": "deposit_size", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "validator_index" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 2691 +}, { + "name": "total_curdyn_deposits_scaled", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 2295 +}, { + "name": "total_prevdyn_deposits_scaled", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 2325 +}, { + "name": "recommended_source_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 603 +}, { + "name": "recommended_target_hash", + "outputs": [{ + "type": "bytes32", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 480 +}, { + "name": "initialize_epoch", + "outputs": [], + "inputs": [{ + "type": "int128", + "name": "epoch" + }], + "constant": false, + "payable": false, + "type": "function", + "gas": 359815 +}, { + "name": "deposit", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "validation_addr" + }, { + "type": "address", + "name": "withdrawal_addr" + }], + "constant": false, + "payable": true, + "type": "function", + "gas": 672097 +}, { + "name": "logout", + "outputs": [], + "inputs": [{ + "type": "bytes", + "name": "logout_msg" + }], + "constant": false, + "payable": false, + "type": "function", + "gas": 759852 +}, { + "name": "withdraw", + "outputs": [], + "inputs": [{ + "type": "int128", + "name": "validator_index" + }], + "constant": false, + "payable": false, + "type": "function", + "gas": 89731 +}, { + "name": "vote", + "outputs": [], + "inputs": [{ + "type": "bytes", + "name": "vote_msg" + }], + "constant": false, + "payable": false, + "type": "function", + "gas": 1017478 +}, { + "name": "slash", + "outputs": [], + "inputs": [{ + "type": "bytes", + "name": "vote_msg_1" + }, { + "type": "bytes", + "name": "vote_msg_2" + }], + "constant": false, + "payable": false, + "type": "function", + "gas": 1582631 +}, { + "name": "owner_withdraw", + "outputs": [], + "inputs": [], + "constant": false, + "payable": false, + "type": "function", + "gas": 41080 +}, { + "name": "change_owner", + "outputs": [], + "inputs": [{ + "type": "address", + "name": "new_owner" + }], + "constant": false, + "payable": false, + "type": "function", + "gas": 21221 +}, { + "name": "validators__deposit", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1410 +}, { + "name": "validators__start_dynasty", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1440 +}, { + "name": "validators__end_dynasty", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1470 +}, { + "name": "validators__addr", + "outputs": [{ + "type": "address", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1494 +}, { + "name": "validators__withdrawal_addr", + "outputs": [{ + "type": "address", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1530 +}, { + "name": "checkpoint_hashes", + "outputs": [{ + "type": "bytes32", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1482 +}, { + "name": "next_validator_index", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1323 +}, { + "name": "validator_indexes", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "address", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1491 +}, { + "name": "dynasty", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1383 +}, { + "name": "dynasty_wei_delta", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1602 +}, { + "name": "dynasty_start_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1632 +}, { + "name": "dynasty_in_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1662 +}, { + "name": "votes__cur_dyn_votes", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }, { + "type": "int128", + "name": "arg1" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1941 +}, { + "name": "votes__prev_dyn_votes", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }, { + "type": "int128", + "name": "arg1" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1977 +}, { + "name": "votes__vote_bitmap", + "outputs": [{ + "type": "uint256", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }, { + "type": "bytes32", + "name": "arg1" + }, { + "type": "int128", + "name": "arg2" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 2094 +}, { + "name": "votes__is_justified", + "outputs": [{ + "type": "bool", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1860 +}, { + "name": "votes__is_finalized", + "outputs": [{ + "type": "bool", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1890 +}, { + "name": "main_hash_justified", + "outputs": [{ + "type": "bool", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1653 +}, { + "name": "deposit_scale_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [{ + "type": "int128", + "name": "arg0" + }], + "constant": true, + "payable": false, + "type": "function", + "gas": 1872 +}, { + "name": "last_nonvoter_rescale", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1713 +}, { + "name": "last_voter_rescale", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1743 +}, { + "name": "current_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1773 +}, { + "name": "last_finalized_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1803 +}, { + "name": "last_justified_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1833 +}, { + "name": "expected_source_epoch", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1863 +}, { + "name": "epoch_length", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1893 +}, { + "name": "withdrawal_delay", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1923 +}, { + "name": "dynasty_logout_delay", + "outputs": [{ + "type": "int128", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1953 +}, { + "name": "reward_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 1983 +}, { + "name": "base_interest_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 2013 +}, { + "name": "base_penalty_factor", + "outputs": [{ + "type": "decimal10", + "name": "out" + }], + "inputs": [], + "constant": true, + "payable": false, + "type": "function", + "gas": 2043 }] \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/casper/casper.bin b/ethereumj-core/src/main/resources/casper/casper.bin index 52cb435173..a6c615b867 100644 --- a/ethereumj-core/src/main/resources/casper/casper.bin +++ b/ethereumj-core/src/main/resources/casper/casper.bin @@ -1 +1 @@ -600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05261010061377f6101403934156100a857600080fd5b606051602061377f60c03960c051806040519013585780919012156100cc57600080fd5b506060516020602061377f0160c03960c051806040519013585780919012156100f457600080fd5b506020604061377f0160c03960c051602051811061011157600080fd5b506020606061377f0160c03960c051602051811061012e57600080fd5b506020608061377f0160c03960c051602051811061014b57600080fd5b50606051602060e061377f0160c03960c0518060405190135857809190121561017357600080fd5b50610140516010556101605160115560016002556101805160165568056bc75e2d63100000600d60c052602060c020556000600455606051601054806101b857600080fd5b4305806040519013585780919012156101d057600080fd5b6012556101a0516018556101c051601955600060075560006008556101e051601b5561020051601c557f632a9a52ef120699847d16b5c0f45b7d5ff4404dd8054906681967edc6094fbf601d5561022051601e5561376756600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526394113f78600051141561017b5734156100ac57600080fd5b60a051601554601254600b60c052602060c0200160c052602060c02060c052602060c0200154600754806100df57600080fd5b806402540be400830205905090508060805190135857809190121561010357600080fd5b60a0516015546003601254600b60c052602060c0200160c052602060c0200160c052602060c02001546008548061013957600080fd5b806402540be400830205905090508060805190135857809190121561015d57600080fd5b8082131561016b578061016d565b815b9050905060005260206000f3005b63843b0890600051141561022f576020600461014037341561019c57600080fd5b606051600435806040519013585780919012156101b857600080fd5b506402540be40060a051601254600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c0200154818102811983838305141761020057600080fd5b6402540be40081059050905090508060805190135857809190121561022457600080fd5b0560005260206000f3005b633b812ec360005114156102a657341561024857600080fd5b6402540be40060a051601254600d60c052602060c0200154600754818102811983838305141761027757600080fd5b6402540be40081059050905090508060805190135857809190121561029b57600080fd5b0560005260206000f3005b63679dea62600051141561031d5734156102bf57600080fd5b6402540be40060a051601254600d60c052602060c020015460085481810281198383830514176102ee57600080fd5b6402540be40081059050905090508060805190135857809190121561031257600080fd5b0560005260206000f3005b63b2ae3f50600051141561034357341561033657600080fd5b60155460005260206000f3005b63cadbbfc160005114156103c057341561035c57600080fd5b6060516001606051601054601254028060405190135857809190121561038157600080fd5b038060405190135857809190121561039857600080fd5b61010043038112156103a957600080fd5b4381106103b557600080fd5b4060005260206000f3005b63de7f997560005114156103fc5734156103d957600080fd5b3033146103e557600080fd5b6000600854136000600754131660005260206000f3005b63d286bb82600051141561051657341561041557600080fd5b30331461042157600080fd5b601254610140526001606051600261014051038060405190135857809190121561044a57600080fd5b600b60c052602060c0200160c052602060c0200154156104d057600460605160018254018060405190135857809190121561048457600080fd5b815550600754600855600760a051600554825401806080519013585780919012156104ae57600080fd5b815550600654600555600060065561014051600454600960c052602060c02001555b60045461014051600a60c052602060c0200155600c541561050f57606051600161014051038060405190135857809190121561050b57600080fd5b6015555b6000600c55005b63fa650b2a600051141561056d57341561052f57600080fd5b30331461053b57600080fd5b6012546101405260605160135461014051038060405190135857809190121561056357600080fd5b60005260206000f3005b6370af50be600051141561077d57341561058657600080fd5b30331461059257600080fd5b60125461014052600260206101c0600463fa650b2a6101605261017c6000305af16105bc57600080fd5b6101c05113156101e0526101e051156020610260600463de7f99756102005261021c6000305af16105ec57600080fd5b6102605115171561060257600060005260206000f35b60a051601554606051600161014051038060405190135857809190121561062857600080fd5b600b60c052602060c0200160c052602060c02060c052602060c02001546007548061065257600080fd5b806402540be400830205905090508060805190135857809190121561067657600080fd5b6102805260a051601554600360605160016101405103806040519013585780919012156106a257600080fd5b600b60c052602060c0200160c052602060c0200160c052602060c0200154600854806106cd57600080fd5b806402540be40083020590509050806080519013585780919012156106f157600080fd5b6102a052610280516102a0518082131561070b578061070d565b815b905090506102c05260a051600260a051601a546102c051818102811983838305141761073857600080fd5b6402540be40081059050905090508060805190135857809190121561075c57600080fd5b058060805190135857809190121561077357600080fd5b60005260206000f3005b636526ed72600051141561086857341561079657600080fd5b3033146107a257600080fd5b601254610140526001600c556001600260605160016101405103806040519013585780919012156107d257600080fd5b600b60c052602060c0200160c052602060c020015560016001606051600161014051038060405190135857809190121561080b57600080fd5b600b60c052602060c0200160c052602060c0200155606051600161014051038060405190135857809190121561084057600080fd5b601455606051600161014051038060405190135857809190121561086357600080fd5b601355005b63d9d341b96000511415610a52576020600461014037341561088957600080fd5b30331461089557600080fd5b606051600435806040519013585780919012156108b157600080fd5b5060605160016402540be40060a051670de0b6b3a764000060a05160605160016101405103806040519013585780919012156108ec57600080fd5b600d60c052602060c02001546008546007548082121561090c578061090e565b815b90509050818102811983838305141761092657600080fd5b6402540be40081059050905090508060805190135857809190121561094a57600080fd5b058060805190135857809190121561096157600080fd5b05018060405190135857809190121561097957600080fd5b6101605260a0516404a817c80068056bc75e2d63100000610160510205806080519013585780919012156109ac57600080fd5b610180526101a060006014818352015b60a051600260a05160a05161018051806109d557600080fd5b68056bc75e2d63100000610160510205806080519013585780919012156109fb57600080fd5b610180510180608051901358578091901215610a1657600080fd5b0580608051901358578091901215610a2d57600080fd5b610180525b81516001018083528114156109bc575b50506101805160005260206000f3005b635dcffc176000511415610ddb5760206004610140373415610a7357600080fd5b60605160043580604051901358578091901215610a8f57600080fd5b5060605160105480610aa057600080fd5b430580604051901358578091901215610ab857600080fd5b6101605260605160016012540180604051901358578091901215610adb57600080fd5b61014051146101605161014051131516610af457600080fd5b6101405160125560a051601a5460a05160206101e060046370af50be6101805261019c6000305af1610b2557600080fd5b6101e0516402540be4000180608051901358578091901215610b4657600080fd5b0380608051901358578091901215610b5d57600080fd5b600e5560a05160a051601a546402540be4000180608051901358578091901215610b8657600080fd5b600e548181028119838383051417610b9d57600080fd5b6402540be400810590509050905080608051901358578091901215610bc157600080fd5b600f5560a051600e546060516001610140510380604051901358578091901215610bea57600080fd5b600d60c052602060c02001548181028119838383051417610c0a57600080fd5b6402540be400810590509050905080608051901358578091901215610c2e57600080fd5b61014051600d60c052602060c020015560206102c0600463de7f99756102605261027c6000305af1610c5f57600080fd5b6102c05115610d5e5760a051601b546020610360602463d9d341b96102e05261014051610300526102fc6000305af1610c9757600080fd5b6103605180610ca557600080fd5b806402540be4008302059050905080608051901358578091901215610cc957600080fd5b6103805260a05160a0516020610400600463fa650b2a6103a0526103bc6000305af1610cf457600080fd5b61040051601c548181028119838383051417610d0f57600080fd5b8090509050905080608051901358578091901215610d2c57600080fd5b610380510180608051901358578091901215610d4757600080fd5b601a556000601a5413610d5957600080fd5b610d84565b600060006004636526ed726102005261021c6000305af1610d7e57600080fd5b6000601a555b60006000600463d286bb826104205261043c6000305af1610da457600080fd5b60206104e0600463cadbbfc16104805261049c6000305af1610dc557600080fd5b6104e05161014051600160c052602060c0200155005b63f9609f0860005114156110915760406004610140376004356020518110610e0257600080fd5b506024356020518110610e1457600080fd5b5060605160105480610e2557600080fd5b430580604051901358578091901215610e3d57600080fd5b60125414610e4a57600080fd5b600060006004610180527fa1903eab000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101e001018260208501600060046012f1505080518201915050610140516020826101e0010152602081019050806101e0526101e09050805160200180610260828460006004600a8704601201f1610ed957600080fd5b505060206103006102605161028060006019546207a120f1610efa57600080fd5b60206102e0526102e0602060006020835103811315610f1857600080fd5b0460200260200181015190501415610f2f57600080fd5b61016051600360c052602060c020015415610f4957600080fd5b601e54341215610f5857600080fd5b600254600060c052602060c0200160c052602060c02061014051815560a051601254600d60c052602060c020015480610f9057600080fd5b68056bc75e2d6310000034020580608051901358578091901215610fb357600080fd5b60018201556c0c9f2c9cd04674edea40000000600282015560605160026004540180604051901358578091901215610fea57600080fd5b60038201556101605160048201555060025461016051600360c052602060c0200155600260605160018254018060405190135857809190121561102c57600080fd5b815550600660a05160a051601254600d60c052602060c02001548061105057600080fd5b68056bc75e2d631000003402058060805190135857809190121561107357600080fd5b8254018060805190135857809190121561108c57600080fd5b815550005b6342310c32600051141561148557602060046101403734156110b257600080fd5b610420600435600401610160376104006004356004013511156110d457600080fd5b606051601054806110e457600080fd5b4305806040519013585780919012156110fc57600080fd5b6012541461110957600080fd5b6101608051602001806105a0828460006004600a8704601201f161112c57600080fd5b50506020610a006105a0516105c0600060185462030d40f161114d57600080fd5b60206109e0526109e060206000602083510381131561116b57600080fd5b046020026020018101519050610a4052611000610160610560610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610aa0f150506080610a6051146111ba57600080fd5b610a6051610a60018060200151600082518060209013585780919012156111e057600080fd5b601f6101000a82048115176111f457600080fd5b606051816020036101000a83048060405190135857809190121561121757600080fd5b9050905090508152610a8051610a600180602001516000825180602090135857809190121561124557600080fd5b601f6101000a820481151761125957600080fd5b606051816020036101000a83048060405190135857809190121561127c57600080fd5b9050905090508160200152610aa051610a600180516020018083604001828460006004600a8704601201f16112b057600080fd5b5050506110005161148052611020516114a0526110408051602001806114c0828460006004600a8704601201f16112e657600080fd5b50506114a05160125412156112fa57600080fd5b60016000610a40516020826119000101526020810190506114c06104008060208461190001018260208501600060046078f150508051820191505080611900526119009050805160200180611d60828460006004600a8704601201f161135f57600080fd5b505060206121e0611d6051611d80600061148051600060c052602060c0200160c052602060c020546207a120f161139557600080fd5b60206121c0526121c06020600060208351038113156113b357600080fd5b046020026020018101519050146113c957600080fd5b606051600260045401806040519013585780919012156113e857600080fd5b600261148051600060c052602060c0200160c052602060c02001541361140d57600080fd5b6060516002600454018060405190135857809190121561142c57600080fd5b600261148051600060c052602060c0200160c052602060c0200155600660a051600161148051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561148057600080fd5b815550005b6301b7af1860005114156115af57602060046101403734156114a657600080fd5b3033146114b257600080fd5b606051600435806040519013585780919012156114ce57600080fd5b50606051600260045401806040519013585780919012156114ee57600080fd5b600261014051600060c052602060c0200160c052602060c0200154131561154c57600560a051600161014051600060c052602060c0200160c052602060c02001548254038060805190135857809190121561154857600080fd5b8155505b6000600461014051600060c052602060c0200160c052602060c0200154600360c052602060c020015561014051600060c052602060c0200160c052602060c020600081556000600182015560006002820155600060038201556000600482015550005b63edea1480600051141561177657602060046101403734156115d057600080fd5b606051600435806040519013585780919012156115ec57600080fd5b506060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561162457600080fd5b600454121561163257600080fd5b6060516001600261014051600060c052602060c0200160c052602060c0200154018060405190135857809190121561166957600080fd5b600960c052602060c02001546101605260605160115461016051018060405190135857809190121561169a57600080fd5b60125412156116a857600080fd5b6402540be40060a05161016051600d60c052602060c0200154600161014051600060c052602060c0200160c052602060c020015481810281198383830514176116f057600080fd5b6402540be40081059050905090508060805190135857809190121561171457600080fd5b0561018052600060006000600061018051600461014051600060c052602060c0200160c052602060c02001546000f161174c57600080fd5b6000600060246301b7af186101a052610140516101c0526101bc6000305af161177457600080fd5b005b63579f38b26000511415611a70576040600461014037341561179757600080fd5b3033146117a357600080fd5b606051600435806040519013585780919012156117bf57600080fd5b50606051602435806040519013585780919012156117dc57600080fd5b50600361014051600060c052602060c0200160c052602060c0200154600960c052602060c020015461018052600161014051600060c052602060c0200160c052602060c0200160a0516402540be40061016051028254018060805190135857809190121561184957600080fd5b815550600361014051600060c052602060c0200160c052602060c02001546101a052600261014051600060c052602060c0200160c052602060c02001546101c0526004546101e05260605160016101e05103806040519013585780919012156118b157600080fd5b610200526101c0516101e051126101e0516101a051131516156118fb57600760a0516402540be4006101605102825401806080519013585780919012156118f757600080fd5b8155505b6101c0516102005112610200516101a0511315161561194157600860a0516402540be40061016051028254018060805190135857809190121561193d57600080fd5b8155505b60605160016101c051038060405190135857809190121561196157600080fd5b6101e051141561199857600560a0516402540be40061016051028254038060805190135857809190121561199457600080fd5b8155505b60605160026101c05103806040519013585780919012156119b857600080fd5b6101e05114156119ef57600660a0516402540be4006101605102825403806080519013585780919012156119eb57600080fd5b8155505b60006000600060006402540be40060a051600860a051601254600d60c052602060c0200154610160518181028119838383051417611a2c57600080fd5b8090509050905080608051901358578091901215611a4957600080fd5b0580608051901358578091901215611a6057600080fd5b05416000f1611a6e57600080fd5b005b63e9dc061460005114156123ec5760206004610140373415611a9157600080fd5b61042060043560040161016037610400600435600401351115611ab357600080fd5b6101608051602001806105a0828460006004600a8704601201f1611ad657600080fd5b50506020610a006105a0516105c0600060185462030d40f1611af757600080fd5b60206109e0526109e0602060006020835103811315611b1557600080fd5b046020026020018101519050610a40526110c0610160610620610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610a605114611b6457600080fd5b610a6051610a6001806020015160008251806020901358578091901215611b8a57600080fd5b601f6101000a8204811517611b9e57600080fd5b606051816020036101000a830480604051901358578091901215611bc157600080fd5b90509050905081526020610a8051610a60015114611bde57600080fd5b610a8051610a8001518160200152610aa051610a6001806020015160008251806020901358578091901215611c1257600080fd5b601f6101000a8204811517611c2657600080fd5b606051816020036101000a830480604051901358578091901215611c4957600080fd5b9050905090508160400152610ac051610a6001806020015160008251806020901358578091901215611c7a57600080fd5b601f6101000a8204811517611c8e57600080fd5b606051816020036101000a830480604051901358578091901215611cb157600080fd5b9050905090508160600152610ae051610a600180516020018083608001828460006004600a8704601201f1611ce557600080fd5b5050506110c051611580526110e0516115a052611100516115c052611120516115e052611140805160200180611600828460006004600a8704601201f1611d2b57600080fd5b505060016000610a4051602082611a4001015260208101905061160061040080602084611a4001018260208501600060046078f150508051820191505080611a4052611a409050805160200180611ea0828460006004600a8704601201f1611d9257600080fd5b50506020612320611ea051611ec0600061158051600060c052602060c0200160c052602060c020546207a120f1611dc857600080fd5b602061230052612300602060006020835103811315611de657600080fd5b04602002602001810151905014611dfc57600080fd5b6001606051610100611580510780604051901358578091901215611e1f57600080fd5b600081131515611e37578060000360020a8204611e3e565b8060020a82025b90509050606051610100611580510580604051901358578091901215611e6357600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541615611e9f57600080fd5b60206123c0600463cadbbfc16123605261237c6000305af1611ec057600080fd5b6123c0516115a05114611ed257600080fd5b60026115e051600b60c052602060c0200160c052602060c0200154611ef657600080fd5b600361158051600060c052602060c0200160c052602060c02001546123e052600261158051600060c052602060c0200160c052602060c0200154612400526115c051600a60c052602060c0200154612420526060516001612420510380604051901358578091901215611f6857600080fd5b61244052612400516124205112612420516123e05113151661246052612400516124405112612440516123e05113151661248052612480516124605117611fae57600080fd5b6001606051610100611580510780604051901358578091901215611fd157600080fd5b600081131515611fe9578060000360020a8204611ff0565b8060020a82025b9050905060605161010061158051058060405190135857809190121561201557600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001541760605161010061158051058060405190135857809190121561206857600080fd5b6115a05160046115c051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001556115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001546124a0526115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001546124c052612460511561215e576124a060a051600161158051600060c052602060c0200160c052602060c02001548251018060805190135857809190121561213157600080fd5b8152506124a0516115e0516115c051600b60c052602060c0200160c052602060c02060c052602060c02001555b61248051156121d1576124c060a051600161158051600060c052602060c0200160c052602060c0200154825101806080519013585780919012156121a157600080fd5b8152506124c0516115e05160036115c051600b60c052602060c0200160c052602060c0200160c052602060c02001555b6115e051601554146115c05160125414161561227c576402540be40060a051601a54600161158051600060c052602060c0200160c052602060c0200154818102811983838305141761222257600080fd5b6402540be40081059050905090508060805190135857809190121561224657600080fd5b056124e05260006000604463579f38b26125005261158051612520526124e0516125405261251c6000305af161227b57600080fd5b5b60026115c051600b60c052602060c0200160c052602060c02001541560a051600360a051600260085481810281198383830514176122b957600080fd5b80905090509050806080519013585780919012156122d657600080fd5b05806080519013585780919012156122ed57600080fd5b6124c051121560a051600360a0516002600754818102811983838305141761231457600080fd5b809050905090508060805190135857809190121561233157600080fd5b058060805190135857809190121561234857600080fd5b6124a05112151616156123dc57600160026115c051600b60c052602060c0200160c052602060c02001556115c0516014556012546115c051141561238c576001600c555b60605160016115e05101806040519013585780919012156123ac57600080fd5b6115c05114156123db57600160016115e051600b60c052602060c0200160c052602060c02001556115e0516013555b5b610160601d54815160208301a150005b63cc20f16b6000511415612c4d576040600461014037341561240d57600080fd5b6104206004356004016101803761040060043560040135111561242f57600080fd5b6104206024356004016105c03761040060243560040135111561245157600080fd5b610180805160200180610a00828460006004600a8704601201f161247457600080fd5b50506020610e60610a0051610a20600060185462030d40f161249557600080fd5b6020610e4052610e406020600060208351038113156124b357600080fd5b046020026020018101519050610ea052611520610180610620610ec08251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610ec0511461250257600080fd5b610ec051610ec00180602001516000825180602090135857809190121561252857600080fd5b601f6101000a820481151761253c57600080fd5b606051816020036101000a83048060405190135857809190121561255f57600080fd5b90509050905081526020610ee051610ec001511461257c57600080fd5b610ee051610ee001518160200152610f0051610ec0018060200151600082518060209013585780919012156125b057600080fd5b601f6101000a82048115176125c457600080fd5b606051816020036101000a8304806040519013585780919012156125e757600080fd5b9050905090508160400152610f2051610ec00180602001516000825180602090135857809190121561261857600080fd5b601f6101000a820481151761262c57600080fd5b606051816020036101000a83048060405190135857809190121561264f57600080fd5b9050905090508160600152610f4051610ec00180516020018083608001828460006004600a8704601201f161268357600080fd5b505050611520516119e05261156051611a005261158051611a20526115a0805160200180611a40828460006004600a8704601201f16126c157600080fd5b505060016000610ea051602082611e80010152602081019050611a4061040080602084611e8001018260208501600060046078f150508051820191505080611e8052611e8090508051602001806122e0828460006004600a8704601201f161272857600080fd5b505060206127606122e05161230060006119e051600060c052602060c0200160c052602060c020546207a120f161275e57600080fd5b60206127405261274060206000602083510381131561277c57600080fd5b0460200260200181015190501461279257600080fd5b6105c08051602001806127a0828460006004600a8704601201f16127b557600080fd5b50506020612c006127a0516127c0600060185462030d40f16127d657600080fd5b6020612be052612be06020600060208351038113156127f457600080fd5b046020026020018101519050612c40526115206105c0610620612c608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0612c60511461284357600080fd5b612c6051612c600180602001516000825180602090135857809190121561286957600080fd5b601f6101000a820481151761287d57600080fd5b606051816020036101000a8304806040519013585780919012156128a057600080fd5b90509050905081526020612c8051612c600151146128bd57600080fd5b612c8051612c8001518160200152612ca051612c60018060200151600082518060209013585780919012156128f157600080fd5b601f6101000a820481151761290557600080fd5b606051816020036101000a83048060405190135857809190121561292857600080fd5b9050905090508160400152612cc051612c600180602001516000825180602090135857809190121561295957600080fd5b601f6101000a820481151761296d57600080fd5b606051816020036101000a83048060405190135857809190121561299057600080fd5b9050905090508160600152612ce051612c600180516020018083608001828460006004600a8704601201f16129c457600080fd5b505050611520516132c052611560516132e05261158051613300526115a0805160200180613320828460006004600a8704601201f1612a0257600080fd5b505060016000612c40516020826137600101526020810190506133206104008060208461376001018260208501600060046078f150508051820191505080613760526137609050805160200180613bc0828460006004600a8704601201f1612a6957600080fd5b50506020614040613bc051613be060006132c051600060c052602060c0200160c052602060c020546207a120f1612a9f57600080fd5b602061402052614020602060006020835103811315612abd57600080fd5b04602002602001810151905014612ad357600080fd5b6132c0516119e05114612ae557600080fd5b612c4051610ea0511415612af857600080fd5b6000614080526132e051611a00511415612b1757600161408052612b4b565b611a20516133005112611a00516132e051131661330051611a2051126132e051611a005113161715612b4a576001614080525b5b61408051612b5857600080fd5b6020614120602463843b08906140a0526119e0516140c0526140bc6000305af1612b8157600080fd5b61412051614140526060516019614140510580604051901358578091901215612ba957600080fd5b61416052601760605160605160196060516018614140510280604051901358578091901215612bd757600080fd5b0580604051901358578091901215612bee57600080fd5b82540180604051901358578091901215612c0757600080fd5b8155506000600060246301b7af18614180526119e0516141a05261419c6000305af1612c3257600080fd5b600060006000600061416051336000f1612c4b57600080fd5b005b6334ef39f16000511415612c87573415612c6657600080fd5b60006000600060006017546016546000f1612c8057600080fd5b6000601755005b63253c8bd46000511415612cce5760206004610140373415612ca857600080fd5b6004356020518110612cb957600080fd5b50336016541415612ccc57610140516016555b005b63e395dc656000511415612d315760206004610140373415612cef57600080fd5b60605160043580604051901358578091901215612d0b57600080fd5b50600161014051600060c052602060c0200160c052602060c020015460005260206000f3005b6312b2a50a6000511415612d945760206004610140373415612d5257600080fd5b60605160043580604051901358578091901215612d6e57600080fd5b50600361014051600060c052602060c0200160c052602060c020015460005260206000f3005b63fc2d45406000511415612df75760206004610140373415612db557600080fd5b60605160043580604051901358578091901215612dd157600080fd5b50600261014051600060c052602060c0200160c052602060c020015460005260206000f3005b635302508f6000511415612e575760206004610140373415612e1857600080fd5b60605160043580604051901358578091901215612e3457600080fd5b5061014051600060c052602060c0200160c052602060c0205460005260206000f3005b637601d5636000511415612eba5760206004610140373415612e7857600080fd5b60605160043580604051901358578091901215612e9457600080fd5b50600461014051600060c052602060c0200160c052602060c020015460005260206000f3005b639abcf69c6000511415612f125760206004610140373415612edb57600080fd5b60605160043580604051901358578091901215612ef757600080fd5b5061014051600160c052602060c020015460005260206000f3005b63363258856000511415612f38573415612f2b57600080fd5b60025460005260206000f3005b63e46cec606000511415612f855760206004610140373415612f5957600080fd5b6004356020518110612f6a57600080fd5b5061014051600360c052602060c020015460005260206000f3005b63a0b286d66000511415612fab573415612f9e57600080fd5b60045460005260206000f3005b632c7e5aa26000511415612fd1573415612fc457600080fd5b60055460005260206000f3005b63a5fd35156000511415612ff7573415612fea57600080fd5b60065460005260206000f3005b62bc82df600051141561304e576020600461014037341561301757600080fd5b6060516004358060405190135857809190121561303357600080fd5b5061014051600960c052602060c020015460005260206000f3005b635320e5ba60005114156130a6576020600461014037341561306f57600080fd5b6060516004358060405190135857809190121561308b57600080fd5b5061014051600a60c052602060c020015460005260206000f3005b63f64927c3600051141561313057604060046101403734156130c757600080fd5b606051600435806040519013585780919012156130e357600080fd5b506060516024358060405190135857809190121561310057600080fd5b506101605161014051600b60c052602060c0200160c052602060c02060c052602060c020015460005260206000f3005b6348e821a960005114156131bd576040600461014037341561315157600080fd5b6060516004358060405190135857809190121561316d57600080fd5b506060516024358060405190135857809190121561318a57600080fd5b5061016051600361014051600b60c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b6356b861a1600051141561325757606060046101403734156131de57600080fd5b606051600435806040519013585780919012156131fa57600080fd5b506060516044358060405190135857809190121561321757600080fd5b506101805161016051600461014051600b60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b63668d56fd60005114156132ba576020600461014037341561327857600080fd5b6060516004358060405190135857809190121561329457600080fd5b50600261014051600b60c052602060c0200160c052602060c020015460005260206000f3005b63625f375b600051141561331d57602060046101403734156132db57600080fd5b606051600435806040519013585780919012156132f757600080fd5b50600161014051600b60c052602060c0200160c052602060c020015460005260206000f3005b633f98cdef600051141561334357341561333657600080fd5b600c5460005260206000f3005b63a219390b600051141561339b576020600461014037341561336457600080fd5b6060516004358060405190135857809190121561338057600080fd5b5061014051600d60c052602060c020015460005260206000f3005b63ef5212dd60005114156133c15734156133b457600080fd5b600e5460005260206000f3005b636a5df9f460005114156133e75734156133da57600080fd5b600f5460005260206000f3005b6305fb1083600051141561340d57341561340057600080fd5b60105460005260206000f3005b63c3826907600051141561343357341561342657600080fd5b60115460005260206000f3005b63837a9bc7600051141561345957341561344c57600080fd5b60125460005260206000f3005b63634d0f77600051141561347f57341561347257600080fd5b60135460005260206000f3005b638370f33860005114156134a557341561349857600080fd5b60145460005260206000f3005b63ffb7619b60005114156134cb5734156134be57600080fd5b60155460005260206000f3005b63350d3fae60005114156134f15734156134e457600080fd5b601a5460005260206000f3005b63fba2b1b3600051141561351757341561350a57600080fd5b601b5460005260206000f3005b63199dfefa600051141561353d57341561353057600080fd5b601c5460005260206000f3005b5b61022961376703610229600039610229613767036000f3 \ No newline at end of file +600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526101206145686101403934156100a857600080fd5b606051602061456860c03960c051806040519013585780919012156100cc57600080fd5b50606051602060206145680160c03960c051806040519013585780919012156100f457600080fd5b50606051602060406145680160c03960c0518060405190135857809190121561011c57600080fd5b50602060606145680160c03960c051602051811061013957600080fd5b50602060806145680160c03960c051602051811061015657600080fd5b50602060a06145680160c03960c051602051811061017357600080fd5b5060605160206101006145680160c03960c0518060405190135857809190121561019c57600080fd5b506101405160145561016051601555610180516016556101a05160175561020051601b5561022051601c5561024051601d556101c0516018556101e051601955600160025568056bc75e2d63100000600c60c052602060c020556000600455600060a0516014548061020d57600080fd5b6402540be4004302058060805190135857809190121561022c57600080fd5b1215610274576402540be4006402540be3ff60a0516014548061024e57600080fd5b6402540be4004302058060805190135857809190121561026d57600080fd5b03056102ab565b6402540be40060a0516014548061028a57600080fd5b6402540be400430205806080519013585780919012156102a957600080fd5b055b600f55600060065560006007556c0c9f2c9cd04674edea40000000601e5561455056600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526337df0ba8600051141561017b5734156100ac57600080fd5b60a051601254600f54600a60c052602060c0200160c052602060c02060c052602060c0200154600654806100df57600080fd5b806402540be400830205905090508060805190135857809190121561010357600080fd5b60a0516012546003600f54600a60c052602060c0200160c052602060c0200160c052602060c02001546007548061013957600080fd5b806402540be400830205905090508060805190135857809190121561015d57600080fd5b8082131561016b578061016d565b815b9050905060005260206000f3005b6399fb5eec6000511415610315576020600461014037341561019c57600080fd5b606051600435806040519013585780919012156101b857600080fd5b50600060a051600f54600c60c052602060c0200154600161014051600060c052602060c0200160c052602060c020015481810281198383830514176101fc57600080fd5b6402540be40081059050905090508060805190135857809190121561022057600080fd5b121561029e576402540be4006402540be3ff60a051600f54600c60c052602060c0200154600161014051600060c052602060c0200160c052602060c0200154818102811983838305141761027357600080fd5b6402540be40081059050905090508060805190135857809190121561029757600080fd5b030561030b565b6402540be40060a051600f54600c60c052602060c0200154600161014051600060c052602060c0200160c052602060c020015481810281198383830514176102e557600080fd5b6402540be40081059050905090508060805190135857809190121561030957600080fd5b055b60005260206000f3005b638ed137b0600051141561044257341561032e57600080fd5b600060a051600f54600c60c052602060c0200154600654818102811983838305141761035957600080fd5b6402540be40081059050905090508060805190135857809190121561037d57600080fd5b12156103e3576402540be4006402540be3ff60a051600f54600c60c052602060c020015460065481810281198383830514176103b857600080fd5b6402540be4008105905090509050806080519013585780919012156103dc57600080fd5b0305610438565b6402540be40060a051600f54600c60c052602060c0200154600654818102811983838305141761041257600080fd5b6402540be40081059050905090508060805190135857809190121561043657600080fd5b055b60005260206000f3005b6385f44a88600051141561056f57341561045b57600080fd5b600060a051600f54600c60c052602060c0200154600754818102811983838305141761048657600080fd5b6402540be4008105905090509050806080519013585780919012156104aa57600080fd5b1215610510576402540be4006402540be3ff60a051600f54600c60c052602060c020015460075481810281198383830514176104e557600080fd5b6402540be40081059050905090508060805190135857809190121561050957600080fd5b0305610565565b6402540be40060a051600f54600c60c052602060c0200154600754818102811983838305141761053f57600080fd5b6402540be40081059050905090508060805190135857809190121561056357600080fd5b055b60005260206000f3005b6310f24635600051141561059557341561058857600080fd5b60125460005260206000f3005b63855f372c60005114156106125734156105ae57600080fd5b6060516001606051601454600f5402806040519013585780919012156105d357600080fd5b03806040519013585780919012156105ea57600080fd5b61010043038112156105fb57600080fd5b43811061060757600080fd5b4060005260206000f3005b63de7f9975600051141561064e57341561062b57600080fd5b30331461063757600080fd5b6000600754136000600654131660005260206000f3005b63d286bb82600051141561076957341561066757600080fd5b30331461067357600080fd5b600f54610140526001606051600261014051038060405190135857809190121561069c57600080fd5b600a60c052602060c0200160c052602060c0200154156107235760046060516001825401806040519013585780919012156106d657600080fd5b815550600654600755600660a051600454600560c052602060c02001548254018060805190135857809190121561070c57600080fd5b81555061014051600454600860c052602060c02001555b60045461014051600960c052602060c0200155600b541561076257606051600161014051038060405190135857809190121561075e57600080fd5b6012555b6000600b55005b639a8eec7760005114156107b857341561078257600080fd5b30331461078e57600080fd5b606051601054600f5403806040519013585780919012156107ae57600080fd5b60005260206000f3005b63acc619c360005114156109c85734156107d157600080fd5b3033146107dd57600080fd5b600f5461014052600260206101e06004639a8eec776101805261019c6000305af161080757600080fd5b6101e05113156101605261016051156020610260600463de7f99756102005261021c6000305af161083757600080fd5b6102605115171561084d57600060005260206000f35b60a051601254606051600161014051038060405190135857809190121561087357600080fd5b600a60c052602060c0200160c052602060c02060c052602060c02001546006548061089d57600080fd5b806402540be40083020590509050806080519013585780919012156108c157600080fd5b6102805260a051601254600360605160016101405103806040519013585780919012156108ed57600080fd5b600a60c052602060c0200160c052602060c0200160c052602060c02001546007548061091857600080fd5b806402540be400830205905090508060805190135857809190121561093c57600080fd5b6102a052610280516102a051808213156109565780610958565b815b905090506102c05260a051600260a051601a546102c051818102811983838305141761098357600080fd5b6402540be4008105905090509050806080519013585780919012156109a757600080fd5b05806080519013585780919012156109be57600080fd5b60005260206000f3005b636526ed726000511415610b465734156109e157600080fd5b3033146109ed57600080fd5b600f54610140526001600b55600160026060516001610140510380604051901358578091901215610a1d57600080fd5b600a60c052602060c0200160c052602060c0200155600160016060516001610140510380604051901358578091901215610a5657600080fd5b600a60c052602060c0200160c052602060c02001556060516001610140510380604051901358578091901215610a8b57600080fd5b6011556060516001610140510380604051901358578091901215610aae57600080fd5b60105560016101a05260016101c05260406101605260016101a05260016101c0526060516001610140510380604051901358578091901215610aef57600080fd5b600160c052602060c02001546060516001610140510380604051901358578091901215610b1b57600080fd5b7f6940a3069a76fdb79d757f4dca548d7930f85e4bce3a3e2d06f5562bda0b10b9610160516101a0a3005b63db23eee06000511415610e76573415610b5f57600080fd5b303314610b6b57600080fd5b600f54610140526060516001600060a051670de0b6b3a764000060a0516060516001610140510380604051901358578091901215610ba857600080fd5b600c60c052602060c020015460075460065480821215610bc85780610bca565b815b905090508181028119838383051417610be257600080fd5b6402540be400810590509050905080608051901358578091901215610c0657600080fd5b0580608051901358578091901215610c1d57600080fd5b1215610cda576402540be4006402540be3ff60a051670de0b6b3a764000060a0516060516001610140510380604051901358578091901215610c5e57600080fd5b600c60c052602060c020015460075460065480821215610c7e5780610c80565b815b905090508181028119838383051417610c9857600080fd5b6402540be400810590509050905080608051901358578091901215610cbc57600080fd5b0580608051901358578091901215610cd357600080fd5b0305610d86565b6402540be40060a051670de0b6b3a764000060a0516060516001610140510380604051901358578091901215610d0f57600080fd5b600c60c052602060c020015460075460065480821215610d2f5780610d31565b815b905090508181028119838383051417610d4957600080fd5b6402540be400810590509050905080608051901358578091901215610d6d57600080fd5b0580608051901358578091901215610d8457600080fd5b055b0180604051901358578091901215610d9d57600080fd5b6101605260a0516404a817c80068056bc75e2d6310000061016051020580608051901358578091901215610dd057600080fd5b610180526101a060006014818352015b60a051600260a05160a0516101805180610df957600080fd5b68056bc75e2d6310000061016051020580608051901358578091901215610e1f57600080fd5b610180510180608051901358578091901215610e3a57600080fd5b0580608051901358578091901215610e5157600080fd5b610180525b8151600101808352811415610de0575b50506101805160005260206000f3005b635dcffc1760005114156112b35760206004610140373415610e9757600080fd5b60605160043580604051901358578091901215610eb357600080fd5b50600060a05160145480610ec657600080fd5b6402540be40043020580608051901358578091901215610ee557600080fd5b1215610f2d576402540be4006402540be3ff60a05160145480610f0757600080fd5b6402540be40043020580608051901358578091901215610f2657600080fd5b0305610f64565b6402540be40060a05160145480610f4357600080fd5b6402540be40043020580608051901358578091901215610f6257600080fd5b055b610160526060516001600f540180604051901358578091901215610f8757600080fd5b61014051146101605161014051131516610fa057600080fd5b61014051600f5560a05160206101e0600463acc619c36101805261019c6000305af1610fcb57600080fd5b6101e0516402540be4000180608051901358578091901215610fec57600080fd5b600e5560a051600e5460a051601a546402540be400018060805190135857809190121561101857600080fd5b8061102257600080fd5b806402540be400830205905090508060805190135857809190121561104657600080fd5b600d5560a051600d54606051600161014051038060405190135857809190121561106f57600080fd5b600c60c052602060c0200154818102811983838305141761108f57600080fd5b6402540be4008105905090509050806080519013585780919012156110b357600080fd5b61014051600c60c052602060c020015560206102c0600463de7f99756102605261027c6000305af16110e457600080fd5b6102c051156111db5760a051601b546020610360600463db23eee06103005261031c6000305af161111457600080fd5b610360518061112257600080fd5b806402540be400830205905090508060805190135857809190121561114657600080fd5b6102e05260a05160a05160206103e06004639a8eec776103805261039c6000305af161117157600080fd5b6103e051601c54818102811983838305141761118c57600080fd5b80905090509050806080519013585780919012156111a957600080fd5b6102e05101806080519013585780919012156111c457600080fd5b601a556000601a54136111d657600080fd5b611201565b600060006004636526ed726102005261021c6000305af16111fb57600080fd5b6000601a555b60006000600463d286bb826104005261041c6000305af161122157600080fd5b60206104c0600463855f372c6104605261047c6000305af161124257600080fd5b6104c05161014051600160c052602060c020015560006105205260006105405260406104e05260006105205260006105405261014051600160c052602060c0200154610140517f6940a3069a76fdb79d757f4dca548d7930f85e4bce3a3e2d06f5562bda0b10b96104e051610520a3005b63f9609f08600051141561167b57604060046101403760043560205181106112da57600080fd5b5060243560205181106112ec57600080fd5b50600060a051601454806112ff57600080fd5b6402540be4004302058060805190135857809190121561131e57600080fd5b1215611366576402540be4006402540be3ff60a0516014548061134057600080fd5b6402540be4004302058060805190135857809190121561135f57600080fd5b030561139d565b6402540be40060a0516014548061137c57600080fd5b6402540be4004302058060805190135857809190121561139b57600080fd5b055b600f54146113aa57600080fd5b600060006004610180527fa1903eab000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101e001018260208501600060046012f1505080518201915050610140516020826101e0010152602081019050806101e0526101e09050805160200180610260828460006004600a8704601201f161143957600080fd5b505060206103006102605161028060006019546207a120f161145a57600080fd5b60206102e0526102e060206000602083510381131561147857600080fd5b046020026020018101519050141561148f57600080fd5b61016051600360c052602060c0200154156114a957600080fd5b601d543412156114b857600080fd5b606051600260045401806040519013585780919012156114d757600080fd5b6103405260a051600f54600c60c052602060c0200154806114f757600080fd5b68056bc75e2d631000003402058060805190135857809190121561151a57600080fd5b61036052600254600060c052602060c0200160c052602060c020610140518155610360516001820155601e5460028201556103405160038201556101605160048201555060025461016051600360c052602060c0200155600260605160018254018060405190135857809190121561159157600080fd5b81555061034051600560c052602060c0200160a05161036051825401806080519013585780919012156115c357600080fd5b815550610140516103c052600361016051600360c052602060c0200154600060c052602060c0200160c052602060c02001546103e0523461040052606061038052610140516103c052600361016051600360c052602060c0200154600060c052602060c0200160c052602060c02001546103e052346104005261016051600360c052602060c0200154610160517fc913dcae46368ac8a73eb63d4f2077a2de58e994bf2cddf074ab3a0fcaa3a0e1610380516103c0a3005b6342310c326000511415611b7e576020600461014037341561169c57600080fd5b610420600435600401610160376104006004356004013511156116be57600080fd5b600060a051601454806116d057600080fd5b6402540be400430205806080519013585780919012156116ef57600080fd5b1215611737576402540be4006402540be3ff60a0516014548061171157600080fd5b6402540be4004302058060805190135857809190121561173057600080fd5b030561176e565b6402540be40060a0516014548061174d57600080fd5b6402540be4004302058060805190135857809190121561176c57600080fd5b055b600f541461177b57600080fd5b6101608051602001806105c0828460006004600a8704601201f161179e57600080fd5b50506020610a206105c0516105e0600060185462030d40f16117bf57600080fd5b6020610a0052610a006020600060208351038113156117dd57600080fd5b0460200260200181015190506105a052611000610160610560610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610aa0f150506080610a60511461182c57600080fd5b610a6051610a600180602001516000825180602090135857809190121561185257600080fd5b601f6101000a820481151761186657600080fd5b606051816020036101000a83048060405190135857809190121561188957600080fd5b9050905090508152610a8051610a60018060200151600082518060209013585780919012156118b757600080fd5b601f6101000a82048115176118cb57600080fd5b606051816020036101000a8304806040519013585780919012156118ee57600080fd5b9050905090508160200152610aa051610a600180516020018083604001828460006004600a8704601201f161192257600080fd5b5050506110005161148052611020516114a0526110408051602001806114c0828460006004600a8704601201f161195857600080fd5b50506114a051600f54121561196c57600080fd5b600160006105a0516020826119000101526020810190506114c06104008060208461190001018260208501600060046078f150508051820191505080611900526119009050805160200180611d60828460006004600a8704601201f16119d157600080fd5b505060206121e0611d6051611d80600061148051600060c052602060c0200160c052602060c020546207a120f1611a0757600080fd5b60206121c0526121c0602060006020835103811315611a2557600080fd5b04602002602001810151905014611a3b57600080fd5b6060516016546004540180604051901358578091901215611a5b57600080fd5b6122205261222051600261148051600060c052602060c0200160c052602060c020015413611a8857600080fd5b61222051600261148051600060c052602060c0200160c052602060c020015561222051600560c052602060c0200160a051600161148051600060c052602060c0200160c052602060c020015482540380608051901358578091901215611aed57600080fd5b815550600261148051600060c052602060c0200160c052602060c020015461228052602061224052600261148051600060c052602060c0200160c052602060c02001546122805261148051600461148051600060c052602060c0200160c052602060c02001547fb0da0cd4d3f901fa403fa301bd3cad4934e079e9f1a5b61bdb33a03da2c9aaaf61224051612280a3005b6301b7af186000511415611c2b5760206004610140373415611b9f57600080fd5b303314611bab57600080fd5b60605160043580604051901358578091901215611bc757600080fd5b506000600461014051600060c052602060c0200160c052602060c0200154600360c052602060c020015561014051600060c052602060c0200160c052602060c020600081556000600182015560006002820155600060038201556000600482015550005b63edea14806000511415611f385760206004610140373415611c4c57600080fd5b60605160043580604051901358578091901215611c6857600080fd5b506060516001600261014051600060c052602060c0200160c052602060c02001540180604051901358578091901215611ca057600080fd5b6004541215611cae57600080fd5b6060516001600261014051600060c052602060c0200160c052602060c02001540180604051901358578091901215611ce557600080fd5b600860c052602060c020015461016052606051601554610160510180604051901358578091901215611d1657600080fd5b600f541215611d2457600080fd5b600060a05161016051600c60c052602060c0200154600161014051600060c052602060c0200160c052602060c02001548181028119838383051417611d6857600080fd5b6402540be400810590509050905080608051901358578091901215611d8c57600080fd5b1215611e0b576402540be4006402540be3ff60a05161016051600c60c052602060c0200154600161014051600060c052602060c0200160c052602060c02001548181028119838383051417611de057600080fd5b6402540be400810590509050905080608051901358578091901215611e0457600080fd5b0305611e79565b6402540be40060a05161016051600c60c052602060c0200154600161014051600060c052602060c0200160c052602060c02001548181028119838383051417611e5357600080fd5b6402540be400810590509050905080608051901358578091901215611e7757600080fd5b055b61018052600060006000600061018051600461014051600060c052602060c0200160c052602060c02001546000f1611eb057600080fd5b610180516101e05260206101a052610180516101e05261014051600461014051600060c052602060c0200160c052602060c02001547f499b9fc824d01426cfde5b95eebcfc53494a24d6316bb139b2333377f7c00e476101a0516101e0a36000600060246301b7af1861020052610140516102205261021c6000305af1611f3657600080fd5b005b63579f38b260005114156122825760406004610140373415611f5957600080fd5b303314611f6557600080fd5b60605160043580604051901358578091901215611f8157600080fd5b5060605160243580604051901358578091901215611f9e57600080fd5b50600161014051600060c052602060c0200160c052602060c0200160a0516402540be400610160510282540180608051901358578091901215611fe057600080fd5b815550600361014051600060c052602060c0200160c052602060c020015461018052600261014051600060c052602060c0200160c052602060c02001546101a0526004546101c05260605160016101c051038060405190135857809190121561204857600080fd5b6101e0526101a0516101c051126101c051610180511315161561209257600660a0516402540be40061016051028254018060805190135857809190121561208e57600080fd5b8155505b6101a0516101e051126101e05161018051131516156120d857600760a0516402540be4006101605102825401806080519013585780919012156120d457600080fd5b8155505b601e546101a051121561211f576101a051600560c052602060c0200160a0516402540be40061016051028254038060805190135857809190121561211b57600080fd5b8155505b6000600060006000600060a051600860a051600f54600c60c052602060c020015461016051818102811983838305141761215857600080fd5b809050905090508060805190135857809190121561217557600080fd5b058060805190135857809190121561218c57600080fd5b1215612208576402540be4006402540be3ff60a051600860a051600f54600c60c052602060c02001546101605181810281198383830514176121cd57600080fd5b80905090509050806080519013585780919012156121ea57600080fd5b058060805190135857809190121561220157600080fd5b0305612273565b6402540be40060a051600860a051600f54600c60c052602060c020015461016051818102811983838305141761223d57600080fd5b809050905090508060805190135857809190121561225a57600080fd5b058060805190135857809190121561227157600080fd5b055b416000f161228057600080fd5b005b63e9dc06146000511415612f4e57602060046101403734156122a357600080fd5b610420600435600401610160376104006004356004013511156122c557600080fd5b6101608051602001806105c0828460006004600a8704601201f16122e857600080fd5b50506020610a206105c0516105e0600060185462030d40f161230957600080fd5b6020610a0052610a0060206000602083510381131561232757600080fd5b0460200260200181015190506105a0526110c0610160610620610a608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610a60511461237657600080fd5b610a6051610a600180602001516000825180602090135857809190121561239c57600080fd5b601f6101000a82048115176123b057600080fd5b606051816020036101000a8304806040519013585780919012156123d357600080fd5b90509050905081526020610a8051610a600151146123f057600080fd5b610a8051610a8001518160200152610aa051610a600180602001516000825180602090135857809190121561242457600080fd5b601f6101000a820481151761243857600080fd5b606051816020036101000a83048060405190135857809190121561245b57600080fd5b9050905090508160400152610ac051610a600180602001516000825180602090135857809190121561248c57600080fd5b601f6101000a82048115176124a057600080fd5b606051816020036101000a8304806040519013585780919012156124c357600080fd5b9050905090508160600152610ae051610a600180516020018083608001828460006004600a8704601201f16124f757600080fd5b5050506110c051611580526110e0516115a052611100516115c052611120516115e052611140805160200180611600828460006004600a8704601201f161253d57600080fd5b5050600160006105a051602082611a4001015260208101905061160061040080602084611a4001018260208501600060046078f150508051820191505080611a4052611a409050805160200180611ea0828460006004600a8704601201f16125a457600080fd5b50506020612320611ea051611ec0600061158051600060c052602060c0200160c052602060c020546207a120f16125da57600080fd5b6020612300526123006020600060208351038113156125f857600080fd5b0460200260200181015190501461260e57600080fd5b600160605161010061158051078060405190135857809190121561263157600080fd5b600081131515612649578060000360020a8204612650565b8060020a82025b90509050600060a0516101006402540be4006115805102058060805190135857809190121561267e57600080fd5b12156126bf576402540be4006402540be3ff60a0516101006402540be400611580510205806080519013585780919012156126b857600080fd5b03056126ef565b6402540be40060a0516101006402540be400611580510205806080519013585780919012156126ed57600080fd5b055b6115a05160046115c051600a60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c0200154161561272b57600080fd5b60206123c0600463855f372c6123605261237c6000305af161274c57600080fd5b6123c0516115a0511461275e57600080fd5b600f546115c0511461276f57600080fd5b60026115e051600a60c052602060c0200160c052602060c020015461279357600080fd5b600361158051600060c052602060c0200160c052602060c02001546123e052600261158051600060c052602060c0200160c052602060c0200154612400526115c051600960c052602060c020015461242052606051600161242051038060405190135857809190121561280557600080fd5b61244052612400516124205112612420516123e05113151661246052612400516124405112612440516123e0511315166124805261248051612460511761284b57600080fd5b600160605161010061158051078060405190135857809190121561286e57600080fd5b600081131515612886578060000360020a820461288d565b8060020a82025b90509050600060a0516101006402540be400611580510205806080519013585780919012156128bb57600080fd5b12156128fc576402540be4006402540be3ff60a0516101006402540be400611580510205806080519013585780919012156128f557600080fd5b030561292c565b6402540be40060a0516101006402540be4006115805102058060805190135857809190121561292a57600080fd5b055b6115a05160046115c051600a60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c020015417600060a0516101006402540be4006115805102058060805190135857809190121561298857600080fd5b12156129c9576402540be4006402540be3ff60a0516101006402540be400611580510205806080519013585780919012156129c257600080fd5b03056129f9565b6402540be40060a0516101006402540be400611580510205806080519013585780919012156129f757600080fd5b055b6115a05160046115c051600a60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c02001556115e0516115c051600a60c052602060c0200160c052602060c02060c052602060c02001546124a0526115e05160036115c051600a60c052602060c0200160c052602060c0200160c052602060c02001546124c0526124605115612aef576124a060a051600161158051600060c052602060c0200160c052602060c020015482510180608051901358578091901215612ac257600080fd5b8152506124a0516115e0516115c051600a60c052602060c0200160c052602060c02060c052602060c02001555b6124805115612b62576124c060a051600161158051600060c052602060c0200160c052602060c020015482510180608051901358578091901215612b3257600080fd5b8152506124c0516115e05160036115c051600a60c052602060c0200160c052602060c0200160c052602060c02001555b6115e0516012541415612cd257600060a051601a54600161158051600060c052602060c0200160c052602060c02001548181028119838383051417612ba657600080fd5b6402540be400810590509050905080608051901358578091901215612bca57600080fd5b1215612c3c576402540be4006402540be3ff60a051601a54600161158051600060c052602060c0200160c052602060c02001548181028119838383051417612c1157600080fd5b6402540be400810590509050905080608051901358578091901215612c3557600080fd5b0305612c9d565b6402540be40060a051601a54600161158051600060c052602060c0200160c052602060c02001548181028119838383051417612c7757600080fd5b6402540be400810590509050905080608051901358578091901215612c9b57600080fd5b055b6124e05260006000604463579f38b26125005261158051612520526124e0516125405261251c6000305af1612cd157600080fd5b5b60026115c051600a60c052602060c0200160c052602060c02001541560a051600360a05160026007548181028119838383051417612d0f57600080fd5b8090509050905080608051901358578091901215612d2c57600080fd5b0580608051901358578091901215612d4357600080fd5b6124c051121560a051600360a05160026006548181028119838383051417612d6a57600080fd5b8090509050905080608051901358578091901215612d8757600080fd5b0580608051901358578091901215612d9e57600080fd5b6124a0511215161615612eda57600160026115c051600a60c052602060c0200160c052602060c02001556115c0516011556001600b5560016125e05260006126005260406125a05260016125e0526000612600526115c051600160c052602060c02001546115c0517f6940a3069a76fdb79d757f4dca548d7930f85e4bce3a3e2d06f5562bda0b10b96125a0516125e0a360605160016115e0510180604051901358578091901215612e4f57600080fd5b6115c0511415612ed957600160016115e051600a60c052602060c0200160c052602060c02001556115e0516010556001612660526001612680526040612620526001612660526001612680526115e051600160c052602060c02001546115e0517f6940a3069a76fdb79d757f4dca548d7930f85e4bce3a3e2d06f5562bda0b10b961262051612660a35b5b6115c0516126e0526115e0516127005260406126a0526115c0516126e0526115e051612700526115a05161158051600461158051600060c052602060c0200160c052602060c02001547f0fa814a7606272ed601db3d9974a12a26536f050d147ad209b7e7b0a95746f176126a0516126e0a4005b63cc20f16b600051141561395e5760406004610140373415612f6f57600080fd5b61042060043560040161018037610400600435600401351115612f9157600080fd5b6104206024356004016105c037610400602435600401351115612fb357600080fd5b610180805160200180610a20828460006004600a8704601201f1612fd657600080fd5b50506020610e80610a2051610a40600060185462030d40f1612ff757600080fd5b6020610e6052610e6060206000602083510381131561301557600080fd5b046020026020018101519050610a0052611520610180610620610ec08251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0610ec0511461306457600080fd5b610ec051610ec00180602001516000825180602090135857809190121561308a57600080fd5b601f6101000a820481151761309e57600080fd5b606051816020036101000a8304806040519013585780919012156130c157600080fd5b90509050905081526020610ee051610ec00151146130de57600080fd5b610ee051610ee001518160200152610f0051610ec00180602001516000825180602090135857809190121561311257600080fd5b601f6101000a820481151761312657600080fd5b606051816020036101000a83048060405190135857809190121561314957600080fd5b9050905090508160400152610f2051610ec00180602001516000825180602090135857809190121561317a57600080fd5b601f6101000a820481151761318e57600080fd5b606051816020036101000a8304806040519013585780919012156131b157600080fd5b9050905090508160600152610f4051610ec00180516020018083608001828460006004600a8704601201f16131e557600080fd5b505050611520516119e05261156051611a005261158051611a20526115a0805160200180611a40828460006004600a8704601201f161322357600080fd5b505060016000610a0051602082611e80010152602081019050611a4061040080602084611e8001018260208501600060046078f150508051820191505080611e8052611e8090508051602001806122e0828460006004600a8704601201f161328a57600080fd5b505060206127606122e05161230060006119e051600060c052602060c0200160c052602060c020546207a120f16132c057600080fd5b6020612740526127406020600060208351038113156132de57600080fd5b046020026020018101519050146132f457600080fd5b6105c08051602001806127c0828460006004600a8704601201f161331757600080fd5b50506020612c206127c0516127e0600060185462030d40f161333857600080fd5b6020612c0052612c0060206000602083510381131561335657600080fd5b0460200260200181015190506127a0526132c06105c0610620612c608251602084016000735185d17c44699cecc3133114f8df70753b856709610dc0f1505060c0612c6051146133a557600080fd5b612c6051612c60018060200151600082518060209013585780919012156133cb57600080fd5b601f6101000a82048115176133df57600080fd5b606051816020036101000a83048060405190135857809190121561340257600080fd5b90509050905081526020612c8051612c6001511461341f57600080fd5b612c8051612c8001518160200152612ca051612c600180602001516000825180602090135857809190121561345357600080fd5b601f6101000a820481151761346757600080fd5b606051816020036101000a83048060405190135857809190121561348a57600080fd5b9050905090508160400152612cc051612c60018060200151600082518060209013585780919012156134bb57600080fd5b601f6101000a82048115176134cf57600080fd5b606051816020036101000a8304806040519013585780919012156134f257600080fd5b9050905090508160600152612ce051612c600180516020018083608001828460006004600a8704601201f161352657600080fd5b5050506132c05161378052613300516137a052613320516137c0526133408051602001806137e0828460006004600a8704601201f161356457600080fd5b5050600160006127a051602082613c200101526020810190506137e061040080602084613c2001018260208501600060046078f150508051820191505080613c2052613c209050805160200180614080828460006004600a8704601201f16135cb57600080fd5b50506020614500614080516140a0600061378051600060c052602060c0200160c052602060c020546207a120f161360157600080fd5b60206144e0526144e060206000602083510381131561361f57600080fd5b0460200260200181015190501461363557600080fd5b613780516119e0511461364757600080fd5b6127a051610a0051141561365a57600080fd5b6000614540526137a051611a00511415613679576001614540526136ad565b611a20516137c05112611a00516137a05113166137c051611a2051126137a051611a0051131617156136ac576001614540525b5b614540516136ba57600080fd5b602061460060246399fb5eec614580526119e0516145a05261459c6000305af16136e357600080fd5b6146005161456052600060a05160196402540be4006145605102058060805190135857809190121561371457600080fd5b1215613754576402540be4006402540be3ff60a05160196402540be4006145605102058060805190135857809190121561374d57600080fd5b0305613783565b6402540be40060a05160196402540be4006145605102058060805190135857809190121561378157600080fd5b055b61462052606051614620516145605103806040519013585780919012156137a957600080fd5b61464052601360605161464051825401806040519013585780919012156137cf57600080fd5b815550614620516146a052614640516146c052604061466052614620516146a052614640516146c0526119e05160046119e051600060c052602060c0200160c052602060c0200154337fb63bb46c05149b79f409b978407acff3bb3bfb5fb728ed2909fdb52677c220da614660516146a0a460016119e051600060c052602060c0200160c052602060c02001546146e0526060516001600454018060405190135857809190121561387f57600080fd5b600560c052602060c0200160a0516146e051825403806080519013585780919012156138aa57600080fd5b815550601e5460026119e051600060c052602060c0200160c052602060c0200154121561391b5760026119e051600060c052602060c0200160c052602060c0200154600560c052602060c0200160a0516146e0518254018060805190135857809190121561391757600080fd5b8155505b6000600060246301b7af18614700526119e0516147205261471c6000305af161394357600080fd5b600060006000600061462051336000f161395c57600080fd5b005b6334ef39f1600051141561399857341561397757600080fd5b60006000600060006013546017546000f161399157600080fd5b6000601355005b63253c8bd460005114156139df57602060046101403734156139b957600080fd5b60043560205181106139ca57600080fd5b503360175414156139dd57610140516017555b005b63bcc44d996000511415613a425760206004610140373415613a0057600080fd5b60605160043580604051901358578091901215613a1c57600080fd5b50600161014051600060c052602060c0200160c052602060c020015460005260206000f3005b63faf944fa6000511415613aa55760206004610140373415613a6357600080fd5b60605160043580604051901358578091901215613a7f57600080fd5b50600361014051600060c052602060c0200160c052602060c020015460005260206000f3005b63c253bf416000511415613b085760206004610140373415613ac657600080fd5b60605160043580604051901358578091901215613ae257600080fd5b50600261014051600060c052602060c0200160c052602060c020015460005260206000f3005b63bb0115f06000511415613b685760206004610140373415613b2957600080fd5b60605160043580604051901358578091901215613b4557600080fd5b5061014051600060c052602060c0200160c052602060c0205460005260206000f3005b635dbfd1ce6000511415613bcb5760206004610140373415613b8957600080fd5b60605160043580604051901358578091901215613ba557600080fd5b50600461014051600060c052602060c0200160c052602060c020015460005260206000f3005b638208b8756000511415613c235760206004610140373415613bec57600080fd5b60605160043580604051901358578091901215613c0857600080fd5b5061014051600160c052602060c020015460005260206000f3005b637d69c5d96000511415613c49573415613c3c57600080fd5b60025460005260206000f3005b63dc2059b36000511415613c965760206004610140373415613c6a57600080fd5b6004356020518110613c7b57600080fd5b5061014051600360c052602060c020015460005260206000f3005b637060054d6000511415613cbc573415613caf57600080fd5b60045460005260206000f3005b63c44dc6596000511415613d145760206004610140373415613cdd57600080fd5b60605160043580604051901358578091901215613cf957600080fd5b5061014051600560c052602060c020015460005260206000f3005b63a2630bae6000511415613d6c5760206004610140373415613d3557600080fd5b60605160043580604051901358578091901215613d5157600080fd5b5061014051600860c052602060c020015460005260206000f3005b6365ca80e66000511415613dc45760206004610140373415613d8d57600080fd5b60605160043580604051901358578091901215613da957600080fd5b5061014051600960c052602060c020015460005260206000f3005b63fd87ef9d6000511415613e4e5760406004610140373415613de557600080fd5b60605160043580604051901358578091901215613e0157600080fd5b5060605160243580604051901358578091901215613e1e57600080fd5b506101605161014051600a60c052602060c0200160c052602060c02060c052602060c020015460005260206000f3005b634ac756cb6000511415613edb5760406004610140373415613e6f57600080fd5b60605160043580604051901358578091901215613e8b57600080fd5b5060605160243580604051901358578091901215613ea857600080fd5b5061016051600361014051600a60c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b63eb56ba9c6000511415613f755760606004610140373415613efc57600080fd5b60605160043580604051901358578091901215613f1857600080fd5b5060605160443580604051901358578091901215613f3557600080fd5b506101805161016051600461014051600a60c052602060c0200160c052602060c0200160c052602060c0200160c052602060c020015460005260206000f3005b63cce38da56000511415613fd85760206004610140373415613f9657600080fd5b60605160043580604051901358578091901215613fb257600080fd5b50600261014051600a60c052602060c0200160c052602060c020015460005260206000f3005b63634f21d2600051141561403b5760206004610140373415613ff957600080fd5b6060516004358060405190135857809190121561401557600080fd5b50600161014051600a60c052602060c0200160c052602060c020015460005260206000f3005b6399787ac6600051141561406157341561405457600080fd5b600b5460005260206000f3005b63e430757f60005114156140b9576020600461014037341561408257600080fd5b6060516004358060405190135857809190121561409e57600080fd5b5061014051600c60c052602060c020015460005260206000f3005b638a48440760005114156140df5734156140d257600080fd5b600d5460005260206000f3005b63e6b5736660005114156141055734156140f857600080fd5b600e5460005260206000f3005b639372b4e4600051141561412b57341561411e57600080fd5b600f5460005260206000f3005b632eff8759600051141561415157341561414457600080fd5b60105460005260206000f3005b635f611650600051141561417757341561416a57600080fd5b60115460005260206000f3005b635b03544a600051141561419d57341561419057600080fd5b60125460005260206000f3005b634231bfe160005114156141c35734156141b657600080fd5b60145460005260206000f3005b63eaa26f0f60005114156141e95734156141dc57600080fd5b60155460005260206000f3005b63a914bee8600051141561420f57341561420257600080fd5b60165460005260206000f3005b6307dcf45b600051141561423557341561422857600080fd5b601a5460005260206000f3005b63feaf82bd600051141561425b57341561424e57600080fd5b601b5460005260206000f3005b630f58c218600051141561428157341561427457600080fd5b601c5460005260206000f3005b5b6102ce614550036102ce6000396102ce614550036000f3 \ No newline at end of file diff --git a/ethereumj-core/src/main/resources/casper/casper.lll b/ethereumj-core/src/main/resources/casper/casper.lll deleted file mode 100644 index 55f236919d..0000000000 --- a/ethereumj-core/src/main/resources/casper/casper.lll +++ /dev/null @@ -1,2666 +0,0 @@ -[seq, - [mstore, 28, [calldataload, 0]], - [mstore, 32, 1461501637330902918203684832716283019655932542976], - [mstore, 64, 170141183460469231731687303715884105727], - [mstore, 96, -170141183460469231731687303715884105728], - [mstore, 128, 1701411834604692317316873037158841057270000000000], - [mstore, 160, -1701411834604692317316873037158841057280000000000], - # Line 116 - [codecopy, 320, ~codelen, 256], - [assert, [iszero, callvalue]], - /* checking num input */ - [clamp, - [mload, 96], - [codeload, ~codelen], - [mload, 64]], - /* checking num input */ - [clamp, - [mload, 96], - [codeload, [add, ~codelen, 32]], - [mload, 64]], - /* checking address input */ - [uclamplt, - [codeload, [add, ~codelen, 64]], - [mload, 32]], - /* checking address input */ - [uclamplt, - [codeload, [add, ~codelen, 96]], - [mload, 32]], - /* checking address input */ - [uclamplt, - [codeload, [add, ~codelen, 128]], - [mload, 32]], - /* checking num input */ - [clamp, - [mload, 96], - [codeload, [add, ~codelen, 224]], - [mload, 64]], - # Line 126 - [sstore, 16 , [mload, 320 <_epoch_length>]], - # Line 128 - [sstore, 17 , [mload, 352 <_withdrawal_delay>]], - # Line 130 - [sstore, 2 , 1], - # Line 132 - [sstore, 22 , [mload, 384 <_owner>]], - # Line 134 - [sstore, [sha3_32, 13 ], 100000000000000000000], - # Line 136 - [sstore, 4 , 0], - # Line 138 - [sstore, - 18 , - [clamp, - [mload, 96], - [sdiv, number, [clamp_nonzero, [sload, 16 ]]], - [mload, 64]]], - # Line 140 - [sstore, 24 , [mload, 416 <_sighasher>]], - # Line 142 - [sstore, 25 , [mload, 448 <_purity_checker>]], - # Line 145 - [sstore, 7 , 0], - # Line 146 - [sstore, 8 , 0], - # Line 148 - [sstore, 27 , [mload, 480 <_base_interest_factor>]], - # Line 149 - [sstore, 28 , [mload, 512 <_base_penalty_factor>]], - # Line 150 - [sstore, - 29 , - 44854244691294150128543874285586038746497872340133682954055806415933027209151], - # Line 152 - [sstore, 30 , [mload, 544 <_min_deposit_size>]], - [return, - 0, - [lll, - [seq, - [mstore, 28, [calldataload, 0]], - [mstore, 32, 1461501637330902918203684832716283019655932542976], - [mstore, 64, 170141183460469231731687303715884105727], - [mstore, 96, -170141183460469231731687303715884105728], - [mstore, 128, 1701411834604692317316873037158841057270000000000], - [mstore, 160, -1701411834604692317316873037158841057280000000000], - # Line 155 - [if, - [eq, [mload, 0], 2484158328 ], - [seq, - [assert, [iszero, callvalue]], - # Line 158 - [mstore, - 0, - [with, - _l, - [clamp, - [mload, 160], - [with, - l, - [sload, - [add, - [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [sload, 18 ]]]], - [sload, 21 ]]], - [with, - r, - [clamp_nonzero, [sload, 7 ]], - [sdiv, [mul, l, 10000000000], r]]], - [mload, 128]], - [with, - _r, - [clamp, - [mload, 160], - [with, - l, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [sload, 18 ]]], - 3 ]], - [sload, 21 ]]], - [with, - r, - [clamp_nonzero, [sload, 8 ]], - [sdiv, [mul, l, 10000000000], r]]], - [mload, 128]], - [if, [sgt, _l, _r], _r, _l]]]], - [return, 0, 32], - # Line 155 - stop]], - # Line 161 - [if, - [eq, [mload, 0], 2218461328 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 164 - [mstore, - 0, - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, - [add, - [sha3_32, 13 ], - [sload, 18 ]]], - [with, - l, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 1 ]], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 10000000000]], - [return, 0, 32], - # Line 161 - stop]], - # Line 166 - [if, - [eq, [mload, 0], 998321859 ], - [seq, - [assert, [iszero, callvalue]], - # Line 169 - [mstore, - 0, - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, - [add, - [sha3_32, 13 ], - [sload, 18 ]]], - [with, - l, - [sload, 7 ], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 10000000000]], - [return, 0, 32], - # Line 166 - stop]], - # Line 171 - [if, - [eq, [mload, 0], 1738402402 ], - [seq, - [assert, [iszero, callvalue]], - # Line 174 - [mstore, - 0, - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, - [add, - [sha3_32, 13 ], - [sload, 18 ]]], - [with, - l, - [sload, 8 ], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 10000000000]], - [return, 0, 32], - # Line 171 - stop]], - # Line 177 - [if, - [eq, [mload, 0], 2997763920 ], - [seq, - [assert, [iszero, callvalue]], - # Line 180 - [mstore, 0, [sload, 21 ]], - [return, 0, 32], - # Line 177 - stop]], - # Line 182 - [if, - [eq, [mload, 0], 3403399105 ], - [seq, - [assert, [iszero, callvalue]], - # Line 185 - [mstore, - 0, - [blockhash, - [uclamplt, - [clampge, - [clamp, - [mload, 96], - [sub, - [clamp, - [mload, 96], - [mul, [sload, 18 ], [sload, 16 ]], - [mload, 64]], - 1], - [mload, 64]], - [sub, number, 256]], - number]]], - [return, 0, 32], - # Line 182 - stop]], - # Line 187 - [if, - [eq, [mload, 0], 3732904309 ], - [seq, - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - # Line 190 - [mstore, - 0, - [and, - [sgt, [sload, 7 ], 0], - [sgt, [sload, 8 ], 0]]], - [return, 0, 32], - # Line 187 - stop]], - # Line 196 - [if, - [eq, [mload, 0], 3532045186 ], - [seq, - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - # Line 198 - [mstore, 320 , [sload, 18 ]], - # Line 200 - [if, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, 11 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 2], [mload, 64]]]], - 1 ]], - # Line 201 - [seq, - [with, - _stloc, - 4 , - [sstore, _stloc, [clamp, [mload, 96], [add, [sload, _stloc], 1], [mload, 64]]]], - # Line 202 - [sstore, - 8 , - [sload, 7 ]], - # Line 203 - [with, - _stloc, - 7 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [add, [sload, _stloc], [sload, 5 ]], - [mload, 128]]]], - # Line 204 - [sstore, - 5 , - [sload, 6 ]], - # Line 205 - [sstore, 6 , 0], - # Line 206 - [sstore, - [add, [sha3_32, 9 ], [sload, 4 ]], - [mload, 320 ]]]], - # Line 207 - [sstore, - [add, [sha3_32, 10 ], [mload, 320 ]], - [sload, 4 ]], - # Line 208 - [if, - [sload, 12 ], - # Line 209 - [seq, - [sstore, - 21 , - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]]], - # Line 210 - [sstore, 12 , 0], - # Line 196 - stop]], - # Line 213 - [if, - [eq, [mload, 0], 4200925994 ], - [seq, - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - # Line 215 - [mstore, 320 , [sload, 18 ]], - # Line 216 - [mstore, - 0, - [clamp, - [mload, 96], - [sub, [mload, 320 ], [sload, 19 ]], - [mload, 64]]], - [return, 0, 32], - # Line 213 - stop]], - # Line 219 - [if, - [eq, [mload, 0], 1890537662 ], - [seq, - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - # Line 221 - [mstore, 320 , [sload, 18 ]], - # Line 222 - [mstore, - 480 , - [sle, - [mload, - /* Internal Call: get_esf */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 352, 4200925994], 380], 4, 448, 32]], - 448]], - 2]], - # Line 223 - [if, - [or, - [iszero, - [mload, - /* Internal Call: deposit_exists */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 512, 3732904309], 540], 4, 608, 32]], - 608]]], - [iszero, [mload, 480 ]]], - # Line 224 - [seq, [mstore, 0, 0], [return, 0, 32]]], - # Line 226 - [mstore, - 640 , - [clamp, - [mload, 160], - [with, - l, - [sload, - [add, - [sha3_32, - [sha3_32, - [add, - [sha3_32, 11 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]]], - [sload, 21 ]]], - [with, - r, - [clamp_nonzero, [sload, 7 ]], - [sdiv, [mul, l, 10000000000], r]]], - [mload, 128]]], - # Line 227 - [mstore, - 672 , - [clamp, - [mload, 160], - [with, - l, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, - [add, - [sha3_32, 11 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], - 3 ]], - [sload, 21 ]]], - [with, - r, - [clamp_nonzero, [sload, 8 ]], - [sdiv, [mul, l, 10000000000], r]]], - [mload, 128]]], - # Line 228 - [mstore, - 704 , - [with, - _l, - [mload, 640 ], - [with, _r, [mload, 672 ], [if, [sgt, _l, _r], _r, _l]]]], - # Line 229 - [mstore, - 0, - [clamp, - [mload, 160], - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, 26 ], - [with, - l, - [mload, 704 ], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 2], - [mload, 128]]], - [return, 0, 32], - # Line 219 - stop]], - # Line 231 - [if, - [eq, [mload, 0], 1697049970 ], - [seq, - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - # Line 233 - [mstore, 320 , [sload, 18 ]], - # Line 234 - [sstore, 12 , 1], - # Line 235 - [sstore, - [add, - [sha3_32, - [add, - [sha3_32, 11 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], - 2 ], - 1], - # Line 236 - [sstore, - [add, - [sha3_32, - [add, - [sha3_32, 11 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], - 1 ], - 1], - # Line 237 - [sstore, - 20 , - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]], - # Line 238 - [sstore, - 19 , - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]], - # Line 231 - stop]], - # Line 241 - [if, - [eq, [mload, 0], 2609002115 ], - [seq, - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - # Line 243 - [mstore, 320 , [sload, 18 ]], - # Line 244 - [mstore, - 352 , - [clamp, - [mload, 96], - [add, - [sdiv, - [clamp, - [mload, 160], - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, - [add, - [sha3_32, 13 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], - [with, - l, - [with, - _l, - [sload, 8 ], - [with, - _r, - [sload, 7 ], - [if, [slt, _l, _r], _r, _l]]], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 1000000000000000000], - [mload, 128]], - 10000000000], - 1], - [mload, 64]]], - # Line 246 - [mstore, - 384 , - [clamp, - [mload, 160], - [sdiv, - [mul, [mload, 352 ], 100000000000000000000], - 20000000000], - [mload, 128]]], - # Line 247 - [repeat, - 416, - 0, - 20, - [seq, - [mstore, - 384 , - [clamp, - [mload, 160], - [sdiv, - [clamp, - [mload, 160], - [add, - [mload, 384 ], - [clamp, - [mload, 160], - [sdiv, - [mul, [mload, 352 ], 100000000000000000000], - [clamp_nonzero, [mload, 384 ]]], - [mload, 128]]], - [mload, 128]], - 2], - [mload, 128]]]]], - # Line 249 - [mstore, 0, [mload, 384 ]], - [return, 0, 32], - # Line 241 - stop]], - # Line 254 - [if, - [eq, [mload, 0], 1573911575 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 257 - [mstore, - 352 , - [clamp, - [mload, 96], - [sdiv, number, [clamp_nonzero, [sload, 16 ]]], - [mload, 64]]], - # Line 258 - [assert, - [and, - [sle, [mload, 320 ], [mload, 352 ]], - [eq, - [mload, 320 ], - [clamp, [mload, 96], [add, [sload, 18 ], 1], [mload, 64]]]]], - # Line 261 - [sstore, 18 , [mload, 320 ]], - # Line 264 - [sstore, - 14 , - [clamp, - [mload, 160], - [sub, - [clamp, - [mload, 160], - [add, - 10000000000, - [mload, - /* Internal Call: get_collective_reward */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 384, 1890537662], 412], 4, 480, 32]], - 480]]], - [mload, 128]], - [sload, 26 ]], - [mload, 128]]], - # Line 265 - [sstore, - 15 , - [clamp, - [mload, 160], - [with, - r, - [clamp, - [mload, 160], - [add, 10000000000, [sload, 26 ]], - [mload, 128]], - [with, - l, - [sload, 14 ], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]]], - # Line 266 - [sstore, - [add, [sha3_32, 13 ], [mload, 320 ]], - [clamp, - [mload, 160], - [with, - r, - [sload, 14 ], - [with, - l, - [sload, - [add, - [sha3_32, 13 ], - [clamp, [mload, 96], [sub, [mload, 320 ], 1], [mload, 64]]]], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]]], - # Line 268 - [if, - [mload, - /* Internal Call: deposit_exists */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 608, 3732904309], 636], 4, 704, 32]], - 704]], - # Line 270 - [seq, - [mstore, - 864 , - [clamp, - [mload, 160], - [with, - l, - [sload, 27 ], - [with, - r, - [clamp_nonzero, - [mload, - /* Internal Call: get_sqrt_of_total_deposits */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 736, 2609002115], 764], 4, 832, 32]], - 832]]], - [sdiv, [mul, l, 10000000000], r]]], - [mload, 128]]], - # Line 271 - [sstore, - 26 , - [clamp, - [mload, 160], - [add, - [mload, 864 ], - [clamp, - [mload, 160], - [with, - r, - [mload, - /* Internal Call: get_esf */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 896, 4200925994], 924], 4, 992, 32]], - 992]], - [with, - l, - [sload, 28 ], - [with, - ans, - [mul, l, r], - [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], - [mload, 128]]], - [mload, 128]]], - # Line 273 - [assert, [sgt, [sload, 26 ], 0]]], - # Line 275 - [seq, - /* Internal Call: insta_finalize */ [assert, [call, gas, address, 0, [seq, [mstore, 512, 1697049970], 540], 4, 0, 0]], - # Line 276 - [sstore, 26 , 0]]], - # Line 279 - /* Internal Call: increment_dynasty */ [assert, [call, gas, address, 0, [seq, [mstore, 1024, 3532045186], 1052], 4, 0, 0]], - # Line 282 - [sstore, - [add, [sha3_32, 1 ], [mload, 320 ]], - [mload, - /* Internal Call: get_recommended_target_hash */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 1120, 3403399105], 1148], 4, 1216, 32]], - 1216]]], - # Line 254 - stop]], - # Line 285 - [if, - [eq, [mload, 0], 4183858952 ], - [seq, - [calldatacopy, 320, 4, 64], - /* checking address input */ [uclamplt, [calldataload, 4], [mload, 32]], - /* checking address input */ [uclamplt, [calldataload, 36], [mload, 32]], - # Line 288 - [assert, - [eq, - [sload, 18 ], - [clamp, - [mload, 96], - [sdiv, number, [clamp_nonzero, [sload, 16 ]]], - [mload, 64]]]], - # Line 289 - [assert, - [ne, - /* extracting 32 bytes */ - [with, - _sub, - [seq, - [with, - _source, - /* concat */ - [with, - _poz, - 0, - [seq, - [with, - _arg, - [seq, - [mstore, 384, 4], - [mstore, - 416, - 73077227117658356969279410473650150870559631135483570926313946830681982107648], - 384], - [seq, - /* copy byte slice */ - [with, - _l, - 4, - [pop, [call, 18, 4, 0, [add, _arg, 32], _l, [add, [add, 480, _poz], 32], _l]]], - [set, _poz, [add, _poz, [mload, _arg]]]]], - [mstore, [add, [add, 480, _poz], 32], [mload, 320 ]], - [set, _poz, [add, _poz, 32]], - [mstore, 480, _poz], - 480]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 608, _sz]]]], - [assert, - [call, - 500000, - [sload, 25 ], - 0, - 640, - [mload, 608], - 768, - 32]], - [mstore, 736, 32], - 736], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], - 0]], - # Line 290 - [assert, [iszero, [sload, [add, [sha3_32, 3 ], [mload, 352 ]]]]], - # Line 291 - [assert, [sge, callvalue, [sload, 30 ]]], - # Line 292 - [with, - _L, - [sha3_32, [add, [sha3_32, 0 ], [sload, 2 ]]], - [seq, - [sstore, _L, [mload, 320 ]], - [sstore, - [add, _L, 1 ], - [clamp, - [mload, 160], - [sdiv, - [mul, callvalue, 100000000000000000000], - [clamp_nonzero, - [sload, - [add, - [sha3_32, 13 ], - [sload, 18 ]]]]], - [mload, 128]]], - [sstore, [add, _L, 2 ], 1000000000000000000000000000000], - [sstore, - [add, _L, 3 ], - [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]], - [sstore, [add, _L, 4 ], [mload, 352 ]]]], - # Line 299 - [sstore, - [add, [sha3_32, 3 ], [mload, 352 ]], - [sload, 2 ]], - # Line 300 - [with, - _stloc, - 2 , - [sstore, _stloc, [clamp, [mload, 96], [add, [sload, _stloc], 1], [mload, 64]]]], - # Line 301 - [with, - _stloc, - 6 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [add, - [sload, _stloc], - [clamp, - [mload, 160], - [sdiv, - [mul, callvalue, 100000000000000000000], - [clamp_nonzero, - [sload, - [add, - [sha3_32, 13 ], - [sload, 18 ]]]]], - [mload, 128]]], - [mload, 128]]]], - # Line 285 - stop]], - # Line 306 - [if, - [eq, [mload, 0], 1110510642 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - [calldatacopy, 352, [add, 4, [calldataload, 4]], 1056], - [assert, [le, [calldataload, [add, 4, [calldataload, 4]]], 1024]], - # Line 308 - [assert, - [eq, - [sload, 18 ], - [clamp, - [mload, 96], - [sdiv, number, [clamp_nonzero, [sload, 16 ]]], - [mload, 64]]]], - # Line 311 - [mstore, - 2624 , - [with, - _sub, - [seq, - [with, - _source, - 352 , - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 1440, _sz]]]], - [assert, [call, 200000, [sload, 24 ], 0, 1472, [mload, 1440], 2560, 32]], - [mstore, 2528, 32], - 2528], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], - # Line 313 - [with, - _L, - 4096 , - [seq, - [mstore, - _L, - [seq, - [with, - _sub, - 352 , - [pop, - [call, - 2720, - 611804413765252988754013619680738151377063423597 , - 0, - [add, _sub, 32], - [mload, _sub], - 2656, - 1376]]], - [assert, [eq, [mload, 2656], 128]], - /* bytearray to number, verify no leading zbytes */ - [with, - _sub, - /* getting and checking num */ [add, 2656, [mload, 2656]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], - [mstore, - [add, 32, _L], - [with, - _sub, - /* getting and checking num */ [add, 2656, [mload, 2688]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [with, - _source, - /* getting byte array */ [add, 2656, [mload, 2720]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 64, _L], _sz]]]]]], - # Line 314 - [mstore, 5248 , [mload, 4096 <0+values>]], - # Line 315 - [mstore, 5280 , [mload, 4128 <32+values>]], - # Line 316 - [with, - _source, - 4160 <64+values>, - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 5312 , _sz]]]], - # Line 317 - [assert, [sge, [sload, 18 ], [mload, 5280 ]]], - # Line 319 - [assert, - [eq, - /* extracting 32 bytes */ - [with, - _sub, - [seq, - [with, - _source, - /* concat */ - [with, - _poz, - 0, - [seq, - [mstore, [add, [add, 6400, _poz], 32], [mload, 2624 ]], - [set, _poz, [add, _poz, 32]], - [with, - _arg, - 5312 , - [seq, - /* copy byte slice */ - [with, - _l, - 1024, - [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 6400, _poz], 32], _l]]], - [set, _poz, [add, _poz, [mload, _arg]]]]], - [mstore, 6400, _poz], - 6400]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 7520, _sz]]]], - [assert, - [call, - 500000, - [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]]], - 0, - 7552, - [mload, 7520], - 8672, - 32]], - [mstore, 8640, 32], - 8640], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], - 1]], - # Line 321 - [assert, - [sgt, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]], - 2 ]], - [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]]], - # Line 323 - [sstore, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]], - 2 ], - [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]], - # Line 324 - [with, - _stloc, - 6 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [sub, - [sload, _stloc], - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5248 ]]], - 1 ]]], - [mload, 128]]]], - # Line 306 - stop]], - # Line 327 - [if, - [eq, [mload, 0], 28815128 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 329 - [if, - [sgt, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 2 ]], - [clamp, [mload, 96], [add, [sload, 4 ], 2], [mload, 64]]], - # Line 330 - [seq, - [with, - _stloc, - 5 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [sub, - [sload, _stloc], - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 1 ]]], - [mload, 128]]]]]], - # Line 331 - [sstore, - [add, - [sha3_32, 3 ], - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 4 ]]], - 0], - # Line 332 - [with, - _L, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - [seq, - [sstore, _L, 0], - [sstore, [add, _L, 1 ], 0], - [sstore, [add, _L, 2 ], 0], - [sstore, [add, _L, 3 ], 0], - [sstore, [add, _L, 4 ], 0]]], - # Line 327 - stop]], - # Line 341 - [if, - [eq, [mload, 0], 3991540864 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 344 - [assert, - [sge, - [sload, 4 ], - [clamp, - [mload, 96], - [add, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 2 ]], - 1], - [mload, 64]]]], - # Line 345 - [mstore, - 352 , - [sload, - [add, - [sha3_32, 9 ], - [clamp, - [mload, 96], - [add, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 2 ]], - 1], - [mload, 64]]]]], - # Line 346 - [assert, - [sge, - [sload, 18 ], - [clamp, - [mload, 96], - [add, [mload, 352 ], [sload, 17 ]], - [mload, 64]]]], - # Line 348 - [mstore, - 384 , - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, [add, [sha3_32, 13 ], [mload, 352 ]]], - [with, - l, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 1 ]], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 10000000000]], - # Line 349 - [assert, - [call, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 4 ]], - [mload, 384 ], - 0, - 0, - 0, - 0]], - # Line 350 - /* Internal Call: delete_validator */ - [assert, - [call, - gas, - address, - 0, - [seq, - [mstore, 416, 28815128], - [mstore, 448, [mload, 320 ]], - 444], - 36, - 0, - 0]], - # Line 341 - stop]], - # Line 353 - [if, - [eq, [mload, 0], 1470052530 ], - [seq, - [calldatacopy, 320, 4, 64], - [assert, [iszero, callvalue]], - [assert, [eq, caller, address]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 36], [mload, 64]], - # Line 355 - [mstore, - 384 , - [sload, - [add, - [sha3_32, 9 ], - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 3 ]]]]], - # Line 356 - [with, - _stloc, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 1 ], - [sstore, - _stloc, - [clamp, - [mload, 160], - [add, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], - [mload, 128]]]], - # Line 357 - [mstore, - 416 , - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 3 ]]], - # Line 358 - [mstore, - 448 , - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 2 ]]], - # Line 359 - [mstore, 480 , [sload, 4 ]], - # Line 360 - [mstore, - 512 , - [clamp, [mload, 96], [sub, [mload, 480 ], 1], [mload, 64]]], - # Line 361 - [if, - [and, - [sle, [mload, 416 ], [mload, 480 ]], - [slt, [mload, 480 ], [mload, 448 ]]], - # Line 362 - [seq, - [with, - _stloc, - 7 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [add, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], - [mload, 128]]]]]], - # Line 363 - [if, - [and, - [sle, [mload, 416 ], [mload, 512 ]], - [slt, [mload, 512 ], [mload, 448 ]]], - # Line 364 - [seq, - [with, - _stloc, - 8 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [add, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], - [mload, 128]]]]]], - # Line 365 - [if, - [eq, - [mload, 480 ], - [clamp, [mload, 96], [sub, [mload, 448 ], 1], [mload, 64]]], - # Line 366 - [seq, - [with, - _stloc, - 5 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [sub, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], - [mload, 128]]]]]], - # Line 367 - [if, - [eq, - [mload, 480 ], - [clamp, [mload, 96], [sub, [mload, 448 ], 2], [mload, 64]]], - # Line 368 - [seq, - [with, - _stloc, - 6 , - [sstore, - _stloc, - [clamp, - [mload, 160], - [sub, [sload, _stloc], [mul, [mload, 352 ], 10000000000]], - [mload, 128]]]]]], - # Line 369 - [assert, - [call, - 0, - coinbase, - [sdiv, - [clamp, - [mload, 160], - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, - [add, - [sha3_32, 13 ], - [sload, 18 ]]], - [with, - l, - [mload, 352 ], - [with, - ans, - [mul, l, r], - [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], - [mload, 128]], - 8], - [mload, 128]], - 10000000000], - 0, - 0, - 0, - 0]], - # Line 353 - stop]], - # Line 372 - [if, - [eq, [mload, 0], 3923510804 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - [calldatacopy, 352, [add, 4, [calldataload, 4]], 1056], - [assert, [le, [calldataload, [add, 4, [calldataload, 4]]], 1024]], - # Line 376 - [mstore, - 2624 , - [with, - _sub, - [seq, - [with, - _source, - 352 , - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 1440, _sz]]]], - [assert, [call, 200000, [sload, 24 ], 0, 1472, [mload, 1440], 2560, 32]], - [mstore, 2528, 32], - 2528], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], - # Line 378 - [with, - _L, - 4288 , - [seq, - [mstore, - _L, - [seq, - [with, - _sub, - 352 , - [pop, - [call, - 3520, - 611804413765252988754013619680738151377063423597 , - 0, - [add, _sub, 32], - [mload, _sub], - 2656, - 1568]]], - [assert, [eq, [mload, 2656], 192]], - /* bytearray to number, verify no leading zbytes */ - [with, - _sub, - /* getting and checking num */ [add, 2656, [mload, 2656]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], - [mstore, - [add, 32, _L], - [seq, - [assert, [eq, [mload, [add, 2656, [mload, 2688]]], 32]], - [mload, [add, 2688, [mload, 2688]]]]], - [mstore, - [add, 64, _L], - [with, - _sub, - /* getting and checking num */ [add, 2656, [mload, 2720]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [mstore, - [add, 96, _L], - [with, - _sub, - /* getting and checking num */ [add, 2656, [mload, 2752]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [with, - _source, - /* getting byte array */ [add, 2656, [mload, 2784]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 128, _L], _sz]]]]]], - # Line 379 - [mstore, 5504 , [mload, 4288 <0+values>]], - # Line 380 - [mstore, 5536 , [mload, 4320 <32+values>]], - # Line 381 - [mstore, 5568 , [mload, 4352 <64+values>]], - # Line 382 - [mstore, 5600 , [mload, 4384 <96+values>]], - # Line 383 - [with, - _source, - 4416 <128+values>, - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 5632 , _sz]]]], - # Line 385 - [assert, - [eq, - /* extracting 32 bytes */ - [with, - _sub, - [seq, - [with, - _source, - /* concat */ - [with, - _poz, - 0, - [seq, - [mstore, [add, [add, 6720, _poz], 32], [mload, 2624 ]], - [set, _poz, [add, _poz, 32]], - [with, - _arg, - 5632 , - [seq, - /* copy byte slice */ - [with, - _l, - 1024, - [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 6720, _poz], 32], _l]]], - [set, _poz, [add, _poz, [mload, _arg]]]]], - [mstore, 6720, _poz], - 6720]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 7840, _sz]]]], - [assert, - [call, - 500000, - [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]]], - 0, - 7872, - [mload, 7840], - 8992, - 32]], - [mstore, 8960, 32], - 8960], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], - 1]], - # Line 387 - [assert, - [iszero, - [and, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 4 ]], - [mload, 5536 ]]], - [clamp, [mload, 96], [sdiv, [mload, 5504 ], 256], [mload, 64]]]], - [with, - _v, - 1, - [with, - _s, - [clamp, [mload, 96], [smod, [mload, 5504 ], 256], [mload, 64]], - [if, [sle, _s, 0], [div, _v, [exp, 2, [sub, 0, _s]]], [mul, _v, [exp, 2, _s]]]]]]]], - # Line 390 - [assert, - [eq, - [mload, 5536 ], - [mload, - /* Internal Call: get_recommended_target_hash */ - [seq, - [assert, [call, gas, address, 0, [seq, [mstore, 9056, 3403399105], 9084], 4, 9152, 32]], - 9152]]]], - # Line 392 - [assert, - [sload, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5600 ]]], - 2 ]]], - # Line 396 - [mstore, - 9184 , - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], - 3 ]]], - # Line 398 - [mstore, - 9216 , - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], - 2 ]]], - # Line 400 - [mstore, - 9248 , - [sload, [add, [sha3_32, 10 ], [mload, 5568 ]]]], - # Line 401 - [mstore, - 9280 , - [clamp, [mload, 96], [sub, [mload, 9248 ], 1], [mload, 64]]], - # Line 402 - [mstore, - 9312 , - [and, - [sle, [mload, 9184 ], [mload, 9248 ]], - [slt, [mload, 9248 ], [mload, 9216 ]]]], - # Line 403 - [mstore, - 9344 , - [and, - [sle, [mload, 9184 ], [mload, 9280 ]], - [slt, [mload, 9280 ], [mload, 9216 ]]]], - # Line 404 - [assert, [or, [mload, 9312 ], [mload, 9344 ]]], - # Line 406 - [sstore, - [add, - [sha3_32, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 4 ]], - [mload, 5536 ]]], - [clamp, [mload, 96], [sdiv, [mload, 5504 ], 256], [mload, 64]]], - [or, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 4 ]], - [mload, 5536 ]]], - [clamp, [mload, 96], [sdiv, [mload, 5504 ], 256], [mload, 64]]]], - [with, - _v, - 1, - [with, - _s, - [clamp, [mload, 96], [smod, [mload, 5504 ], 256], [mload, 64]], - [if, [sle, _s, 0], [div, _v, [exp, 2, [sub, 0, _s]]], [mul, _v, [exp, 2, _s]]]]]]], - # Line 410 - [mstore, - 9376 , - [sload, - [add, - [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]]], - [mload, 5600 ]]]], - # Line 411 - [mstore, - 9408 , - [sload, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 3 ]], - [mload, 5600 ]]]], - # Line 412 - [if, - [mload, 9312 ], - # Line 413 - [seq, - [with, - _mloc, - 9376 , - [mstore, - _mloc, - [clamp, - [mload, 160], - [add, - [mload, _mloc], - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], - 1 ]]], - [mload, 128]]]], - # Line 414 - [sstore, - [add, - [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]]], - [mload, 5600 ]], - [mload, 9376 ]]]], - # Line 415 - [if, - [mload, 9344 ], - # Line 416 - [seq, - [with, - _mloc, - 9408 , - [mstore, - _mloc, - [clamp, - [mload, 160], - [add, - [mload, _mloc], - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], - 1 ]]], - [mload, 128]]]], - # Line 417 - [sstore, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 3 ]], - [mload, 5600 ]], - [mload, 9408 ]]]], - # Line 421 - [if, - [and, - [eq, [sload, 18 ], [mload, 5568 ]], - [eq, [sload, 21 ], [mload, 5600 ]]], - # Line 422 - [seq, - [mstore, - 9440 , - [sdiv, - [clamp, - [mload, 160], - [with, - r, - [sload, 26 ], - [with, - l, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 5504 ]]], - 1 ]], - [with, - ans, - [mul, l, r], - [seq, - [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], - [sdiv, ans, 10000000000]]]]], - [mload, 128]], - 10000000000]], - # Line 423 - /* Internal Call: proc_reward */ - [assert, - [call, - gas, - address, - 0, - [seq, - [mstore, 9472, 1470052530], - [mstore, 9504, [mload, 5504 ]], - [mstore, 9536, [mload, 9440 ]], - 9500], - 68, - 0, - 0]]]], - # Line 426 - [if, - [and, - [and, - [sge, - [mload, 9376 ], - [clamp, - [mload, 160], - [sdiv, - [clamp, - [mload, 160], - [with, - r, - 2, - [with, - l, - [sload, 7 ], - [with, - ans, - [mul, l, r], - [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], - [mload, 128]], - 3], - [mload, 128]]], - [sge, - [mload, 9408 ], - [clamp, - [mload, 160], - [sdiv, - [clamp, - [mload, 160], - [with, - r, - 2, - [with, - l, - [sload, 8 ], - [with, - ans, - [mul, l, r], - [seq, [assert, [or, [eq, [sdiv, ans, l], r], [not, l]]], ans]]]], - [mload, 128]], - 3], - [mload, 128]]]], - [iszero, - [sload, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 2 ]]]], - # Line 429 - [seq, - [sstore, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5568 ]]], - 2 ], - 1], - # Line 430 - [sstore, 20 , [mload, 5568 ]], - # Line 431 - [if, - [eq, [mload, 5568 ], [sload, 18 ]], - # Line 432 - [seq, [sstore, 12 , 1]]], - # Line 435 - [if, - [eq, - [mload, 5568 ], - [clamp, [mload, 96], [add, [mload, 5600 ], 1], [mload, 64]]], - # Line 436 - [seq, - [sstore, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 5600 ]]], - 1 ], - 1], - # Line 437 - [sstore, 19 , [mload, 5600 ]]]]]], - # Line 438 - [with, - _arr, - 352 , - [log1, [add, _arr, 32], [mload, _arr], [sload, 29 ]]], - # Line 372 - stop]], - # Line 441 - [if, - [eq, [mload, 0], 3424711019 ], - [seq, - [calldatacopy, 320, 4, 64], - [assert, [iszero, callvalue]], - [calldatacopy, 384, [add, 4, [calldataload, 4]], 1056], - [assert, [le, [calldataload, [add, 4, [calldataload, 4]]], 1024]], - [calldatacopy, 1472, [add, 4, [calldataload, 36]], 1056], - [assert, [le, [calldataload, [add, 4, [calldataload, 36]]], 1024]], - # Line 444 - [mstore, - 3744 , - [with, - _sub, - [seq, - [with, - _source, - 384 , - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 2560, _sz]]]], - [assert, [call, 200000, [sload, 24 ], 0, 2592, [mload, 2560], 3680, 32]], - [mstore, 3648, 32], - 3648], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], - # Line 445 - [with, - _L, - 5408 , - [seq, - [mstore, - _L, - [seq, - [with, - _sub, - 384 , - [pop, - [call, - 3520, - 611804413765252988754013619680738151377063423597 , - 0, - [add, _sub, 32], - [mload, _sub], - 3776, - 1568]]], - [assert, [eq, [mload, 3776], 192]], - /* bytearray to number, verify no leading zbytes */ - [with, - _sub, - /* getting and checking num */ [add, 3776, [mload, 3776]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], - [mstore, - [add, 32, _L], - [seq, - [assert, [eq, [mload, [add, 3776, [mload, 3808]]], 32]], - [mload, [add, 3808, [mload, 3808]]]]], - [mstore, - [add, 64, _L], - [with, - _sub, - /* getting and checking num */ [add, 3776, [mload, 3840]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [mstore, - [add, 96, _L], - [with, - _sub, - /* getting and checking num */ [add, 3776, [mload, 3872]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [with, - _source, - /* getting byte array */ [add, 3776, [mload, 3904]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 128, _L], _sz]]]]]], - # Line 446 - [mstore, 6624 , [mload, 5408 <0+values>]], - # Line 447 - [mstore, 6656 , [mload, 5472 <64+values>]], - # Line 448 - [mstore, 6688 , [mload, 5504 <96+values>]], - # Line 449 - [with, - _source, - 5536 <128+values>, - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 6720 , _sz]]]], - # Line 451 - [assert, - [eq, - /* extracting 32 bytes */ - [with, - _sub, - [seq, - [with, - _source, - /* concat */ - [with, - _poz, - 0, - [seq, - [mstore, [add, [add, 7808, _poz], 32], [mload, 3744 ]], - [set, _poz, [add, _poz, 32]], - [with, - _arg, - 6720 , - [seq, - /* copy byte slice */ - [with, - _l, - 1024, - [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 7808, _poz], 32], _l]]], - [set, _poz, [add, _poz, [mload, _arg]]]]], - [mstore, 7808, _poz], - 7808]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 8928, _sz]]]], - [assert, - [call, - 500000, - [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 6624 ]]]], - 0, - 8960, - [mload, 8928], - 10080, - 32]], - [mstore, 10048, 32], - 10048], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], - 1]], - # Line 453 - [mstore, - 11328 , - [with, - _sub, - [seq, - [with, - _source, - 1472 , - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 10144, _sz]]]], - [assert, - [call, - 200000, - [sload, 24 ], - 0, - 10176, - [mload, 10144], - 11264, - 32]], - [mstore, 11232, 32], - 11232], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]]], - # Line 454 - [with, - _L, - 5408 , - [seq, - [mstore, - _L, - [seq, - [with, - _sub, - 1472 , - [pop, - [call, - 3520, - 611804413765252988754013619680738151377063423597 , - 0, - [add, _sub, 32], - [mload, _sub], - 11360, - 1568]]], - [assert, [eq, [mload, 11360], 192]], - /* bytearray to number, verify no leading zbytes */ - [with, - _sub, - /* getting and checking num */ [add, 11360, [mload, 11360]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]]], - [mstore, - [add, 32, _L], - [seq, - [assert, [eq, [mload, [add, 11360, [mload, 11392]]], 32]], - [mload, [add, 11392, [mload, 11392]]]]], - [mstore, - [add, 64, _L], - [with, - _sub, - /* getting and checking num */ [add, 11360, [mload, 11424]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [mstore, - [add, 96, _L], - [with, - _sub, - /* getting and checking num */ [add, 11360, [mload, 11456]], - [with, - _el1, - [mload, [add, 32, _sub]], - [with, - _len, - [clamp, 0, [mload, _sub], 32], - [seq, - [assert, [or, [iszero, _len], [div, _el1, [exp, 256, 31]]]], - [clamp, [mload, 96], [div, _el1, [exp, 256, [sub, 32, _len]]], [mload, 64]]]]]]], - [with, - _source, - /* getting byte array */ [add, 11360, [mload, 11488]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, [add, 128, _L], _sz]]]]]], - # Line 455 - [mstore, 12992 , [mload, 5408 <0+values>]], - # Line 456 - [mstore, 13024 , [mload, 5472 <64+values>]], - # Line 457 - [mstore, 13056 , [mload, 5504 <96+values>]], - # Line 458 - [with, - _source, - 5536 <128+values>, - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 13088 , _sz]]]], - # Line 460 - [assert, - [eq, - /* extracting 32 bytes */ - [with, - _sub, - [seq, - [with, - _source, - /* concat */ - [with, - _poz, - 0, - [seq, - [mstore, [add, [add, 14176, _poz], 32], [mload, 11328 ]], - [set, _poz, [add, _poz, 32]], - [with, - _arg, - 13088 , - [seq, - /* copy byte slice */ - [with, - _l, - 1024, - [pop, [call, 120, 4, 0, [add, _arg, 32], _l, [add, [add, 14176, _poz], 32], _l]]], - [set, _poz, [add, _poz, [mload, _arg]]]]], - [mstore, 14176, _poz], - 14176]], - [with, - _sz, - [add, 32, [mload, _source]], - [assert, [call, [add, 18, [div, _sz, 10]], 4, 0, _source, _sz, 15296, _sz]]]], - [assert, - [call, - 500000, - [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 12992 ]]]], - 0, - 15328, - [mload, 15296], - 16448, - 32]], - [mstore, 16416, 32], - 16416], - [mload, - [add, - _sub, - [add, 32, [mul, 32, [div, [clample, 0, [sub, [mload, _sub], 32]], 32]]]]]], - 1]], - # Line 462 - [assert, [eq, [mload, 6624 ], [mload, 12992 ]]], - # Line 464 - [assert, [ne, [mload, 3744 ], [mload, 11328 ]]], - # Line 466 - [mstore, 16512 , 0], - # Line 467 - [if, - [eq, [mload, 6656 ], [mload, 13024 ]], - # Line 469 - [seq, [mstore, 16512 , 1]], - # Line 470 - [seq, - [if, - [or, - [and, - [sgt, [mload, 6656 ], [mload, 13024 ]], - [slt, [mload, 6688 ], [mload, 13056 ]]], - [and, - [sgt, [mload, 13024 ], [mload, 6656 ]], - [slt, [mload, 13056 ], [mload, 6688 ]]]], - # Line 473 - [seq, [mstore, 16512 , 1]]]]], - # Line 474 - [assert, [mload, 16512 ]], - # Line 476 - [mstore, - 16704 , - [mload, - /* Internal Call: get_deposit_size */ - [seq, - [assert, - [call, - gas, - address, - 0, - [seq, - [mstore, 16544, 2218461328], - [mstore, 16576, [mload, 6624 ]], - 16572], - 36, - 16672, - 32]], - 16672]]], - # Line 477 - [mstore, - 16736 , - [clamp, - [mload, 96], - [sdiv, [mload, 16704 ], 25], - [mload, 64]]], - # Line 478 - [with, - _stloc, - 23 , - [sstore, - _stloc, - [clamp, - [mload, 96], - [add, - [sload, _stloc], - [clamp, - [mload, 96], - [sdiv, - [clamp, - [mload, 96], - [mul, [mload, 16704 ], 24], - [mload, 64]], - 25], - [mload, 64]]], - [mload, 64]]]], - # Line 479 - /* Internal Call: delete_validator */ - [assert, - [call, - gas, - address, - 0, - [seq, - [mstore, 16768, 28815128], - [mstore, 16800, [mload, 6624 ]], - 16796], - 36, - 0, - 0]], - # Line 480 - [assert, [call, 0, caller, [mload, 16736 ], 0, 0, 0, 0]], - # Line 441 - stop]], - # Line 483 - [if, - [eq, [mload, 0], 888093169 ], - [seq, - [assert, [iszero, callvalue]], - # Line 485 - [assert, - [call, - 0, - [sload, 22 ], - [sload, 23 ], - 0, - 0, - 0, - 0]], - # Line 486 - [sstore, 23 , 0], - # Line 483 - stop]], - # Line 489 - [if, - [eq, [mload, 0], 624724948 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking address input */ [uclamplt, [calldataload, 4], [mload, 32]], - # Line 491 - [if, - [eq, [sload, 22 ], caller], - # Line 492 - [seq, [sstore, 22 , [mload, 320 ]]]], - # Line 489 - stop]], - # Line 2 - [if, - [eq, [mload, 0], 3818249317 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 4 - [mstore, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 1 ]]], - [return, 0, 32], - # Line 2 - stop]], - [if, - [eq, [mload, 0], 313697546 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 4 - [mstore, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 3 ]]], - [return, 0, 32], - # Line 2 - stop]], - [if, - [eq, [mload, 0], 4230825280 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 4 - [mstore, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 2 ]]], - [return, 0, 32], - # Line 2 - stop]], - [if, - [eq, [mload, 0], 1392660623 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 4 - [mstore, - 0, - [sload, [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]]]], - [return, 0, 32], - # Line 2 - stop]], - [if, - [eq, [mload, 0], 1979831651 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 4 - [mstore, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 0 ], [mload, 320 ]]], - 4 ]]], - [return, 0, 32], - # Line 2 - stop]], - # Line 17 - [if, - [eq, [mload, 0], 2596075164 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 19 - [mstore, - 0, - [sload, [add, [sha3_32, 1 ], [mload, 320 ]]]], - [return, 0, 32], - # Line 17 - stop]], - # Line 20 - [if, - [eq, [mload, 0], 909269125 ], - [seq, - [assert, [iszero, callvalue]], - # Line 22 - [mstore, 0, [sload, 2 ]], - [return, 0, 32], - # Line 20 - stop]], - # Line 23 - [if, - [eq, [mload, 0], 3832343648 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking address input */ [uclamplt, [calldataload, 4], [mload, 32]], - # Line 25 - [mstore, - 0, - [sload, [add, [sha3_32, 3 ], [mload, 320 ]]]], - [return, 0, 32], - # Line 23 - stop]], - # Line 26 - [if, - [eq, [mload, 0], 2696054486 ], - [seq, - [assert, [iszero, callvalue]], - # Line 28 - [mstore, 0, [sload, 4 ]], - [return, 0, 32], - # Line 26 - stop]], - # Line 29 - [if, - [eq, [mload, 0], 746478242 ], - [seq, - [assert, [iszero, callvalue]], - # Line 31 - [mstore, 0, [sload, 5 ]], - [return, 0, 32], - # Line 29 - stop]], - # Line 32 - [if, - [eq, [mload, 0], 2784834837 ], - [seq, - [assert, [iszero, callvalue]], - # Line 34 - [mstore, 0, [sload, 6 ]], - [return, 0, 32], - # Line 32 - stop]], - # Line 41 - [if, - [eq, [mload, 0], 12354271 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 43 - [mstore, - 0, - [sload, [add, [sha3_32, 9 ], [mload, 320 ]]]], - [return, 0, 32], - # Line 41 - stop]], - # Line 44 - [if, - [eq, [mload, 0], 1394664890 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 46 - [mstore, - 0, - [sload, [add, [sha3_32, 10 ], [mload, 320 ]]]], - [return, 0, 32], - # Line 44 - stop]], - # Line 47 - [if, - [eq, [mload, 0], 4131989443 ], - [seq, - [calldatacopy, 320, 4, 64], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 36], [mload, 64]], - # Line 49 - [mstore, - 0, - [sload, - [add, - [sha3_32, [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]]], - [mload, 352 ]]]], - [return, 0, 32], - # Line 47 - stop]], - [if, - [eq, [mload, 0], 1223172521 ], - [seq, - [calldatacopy, 320, 4, 64], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 36], [mload, 64]], - # Line 49 - [mstore, - 0, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], - 3 ]], - [mload, 352 ]]]], - [return, 0, 32], - # Line 47 - stop]], - [if, - [eq, [mload, 0], 1454924193 ], - [seq, - [calldatacopy, 320, 4, 96], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 68], [mload, 64]], - # Line 49 - [mstore, - 0, - [sload, - [add, - [sha3_32, - [add, - [sha3_32, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], - 4 ]], - [mload, 352 ]]], - [mload, 384 ]]]], - [return, 0, 32], - # Line 47 - stop]], - [if, - [eq, [mload, 0], 1720538877 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 49 - [mstore, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], - 2 ]]], - [return, 0, 32], - # Line 47 - stop]], - [if, - [eq, [mload, 0], 1650407259 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 49 - [mstore, - 0, - [sload, - [add, - [sha3_32, [add, [sha3_32, 11 ], [mload, 320 ]]], - 1 ]]], - [return, 0, 32], - # Line 47 - stop]], - # Line 61 - [if, - [eq, [mload, 0], 1066978799 ], - [seq, - [assert, [iszero, callvalue]], - # Line 63 - [mstore, 0, [sload, 12 ]], - [return, 0, 32], - # Line 61 - stop]], - # Line 64 - [if, - [eq, [mload, 0], 2719561995 ], - [seq, - [calldatacopy, 320, 4, 32], - [assert, [iszero, callvalue]], - /* checking num input */ [clamp, [mload, 96], [calldataload, 4], [mload, 64]], - # Line 66 - [mstore, - 0, - [sload, [add, [sha3_32, 13 ], [mload, 320 ]]]], - [return, 0, 32], - # Line 64 - stop]], - # Line 68 - [if, - [eq, [mload, 0], 4015133405 ], - [seq, - [assert, [iszero, callvalue]], - # Line 70 - [mstore, 0, [sload, 14 ]], - [return, 0, 32], - # Line 68 - stop]], - # Line 69 - [if, - [eq, [mload, 0], 1784543732 ], - [seq, - [assert, [iszero, callvalue]], - # Line 71 - [mstore, 0, [sload, 15 ]], - [return, 0, 32], - # Line 69 - stop]], - # Line 72 - [if, - [eq, [mload, 0], 100339843 ], - [seq, - [assert, [iszero, callvalue]], - # Line 74 - [mstore, 0, [sload, 16 ]], - [return, 0, 32], - # Line 72 - stop]], - # Line 75 - [if, - [eq, [mload, 0], 3280103687 ], - [seq, - [assert, [iszero, callvalue]], - # Line 77 - [mstore, 0, [sload, 17 ]], - [return, 0, 32], - # Line 75 - stop]], - # Line 78 - [if, - [eq, [mload, 0], 2205850567 ], - [seq, - [assert, [iszero, callvalue]], - # Line 80 - [mstore, 0, [sload, 18 ]], - [return, 0, 32], - # Line 78 - stop]], - # Line 81 - [if, - [eq, [mload, 0], 1665994615 ], - [seq, - [assert, [iszero, callvalue]], - # Line 83 - [mstore, 0, [sload, 19 ]], - [return, 0, 32], - # Line 81 - stop]], - # Line 84 - [if, - [eq, [mload, 0], 2205217592 ], - [seq, - [assert, [iszero, callvalue]], - # Line 86 - [mstore, 0, [sload, 20 ]], - [return, 0, 32], - # Line 84 - stop]], - # Line 87 - [if, - [eq, [mload, 0], 4290208155 ], - [seq, - [assert, [iszero, callvalue]], - # Line 89 - [mstore, 0, [sload, 21 ]], - [return, 0, 32], - # Line 87 - stop]], - # Line 102 - [if, - [eq, [mload, 0], 890060718 ], - [seq, - [assert, [iszero, callvalue]], - # Line 104 - [mstore, 0, [sload, 26 ]], - [return, 0, 32], - # Line 102 - stop]], - # Line 105 - [if, - [eq, [mload, 0], 4221743539 ], - [seq, - [assert, [iszero, callvalue]], - # Line 107 - [mstore, 0, [sload, 27 ]], - [return, 0, 32], - # Line 105 - stop]], - # Line 108 - [if, - [eq, [mload, 0], 429784826 ], - [seq, - [assert, [iszero, callvalue]], - # Line 110 - [mstore, 0, [sload, 28 ]], - [return, 0, 32], - # Line 108 - stop]]], - 0]]] \ No newline at end of file diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java index 5aadf567d1..98f21bb42f 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java @@ -70,7 +70,7 @@ public void setup() throws Exception { - BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; + BigInteger zeroEpoch = (BigInteger) casper.constCall("current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); systemProperties.overrideParams( diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index dfcebad014..477023a911 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -49,14 +49,14 @@ public void epochStartTest() throws Exception { systemProperties.useGenesis(casperGenesis.getInputStream()); loadBlockchain(); - BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; + BigInteger zeroEpoch = (BigInteger) casper.constCall("current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); for (int i = 0; i < 50; ++i) { Block block = bc.createBlock(); } - BigInteger firstEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; + BigInteger firstEpoch = (BigInteger) casper.constCall("current_epoch")[0]; assertEquals(1, firstEpoch.longValue()); for (int i = 0; i < 50; ++i) { @@ -64,13 +64,13 @@ public void epochStartTest() throws Exception { } // Epochs switches and they are finalized and justified because there no deposits yet [insta_finalize] - BigInteger secondEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; + BigInteger secondEpoch = (BigInteger) casper.constCall("current_epoch")[0]; assertEquals(2, secondEpoch.longValue()); - BigInteger lastFinalized = (BigInteger) casper.constCall("get_last_finalized_epoch")[0]; + BigInteger lastFinalized = (BigInteger) casper.constCall("last_finalized_epoch")[0]; assertEquals(1, lastFinalized.longValue()); - BigInteger lastJustified = (BigInteger) casper.constCall("get_last_justified_epoch")[0]; + BigInteger lastJustified = (BigInteger) casper.constCall("last_justified_epoch")[0]; assertEquals(1, lastJustified.longValue()); } } diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java index ec02a8aecd..f14ab8e155 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperStateInitTest.java @@ -27,6 +27,7 @@ import static junit.framework.TestCase.assertEquals; @Ignore // Takes too long to run usually +// FIXME: Update it with new casper address and state init from Pyeth when available public class CasperStateInitTest extends CasperBase { /** diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 1293c86a0e..08306348a3 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -49,6 +49,8 @@ import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; +import static org.ethereum.casper.config.net.CasperTestNetConfig.DYNASTY_LOGOUT_DELAY; +import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; import static org.ethereum.crypto.HashUtil.sha3; @Ignore // Takes too long to run usually @@ -131,7 +133,7 @@ public void setup() throws Exception { - BigInteger zeroEpoch = (BigInteger) casper.constCall("get_current_epoch")[0]; + BigInteger zeroEpoch = (BigInteger) casper.constCall("current_epoch")[0]; assertEquals(0, zeroEpoch.longValue()); systemProperties.overrideParams( @@ -176,16 +178,16 @@ public void complexValidatorTest() throws Exception { .compareTo(initialBalance.subtract(EtherUtil.convert(DEPOSIT_SIZE_ETH, EtherUtil.Unit.ETHER))) < 0); // Let's logout service.voteThenLogout(); - // Withdrawal delay is 5 epochs + 1 vote epoch + overhead - for (int i = 0; i < 400; ++i) { + // Withdrawal delay is 5 logout epochs delay + 5 withdrawal + 1 overhead epoch + for (int i = 0; i < 50 * (DYNASTY_LOGOUT_DELAY + WITHDRAWAL_DELAY + 1); ++i) { Block block = bc.createBlock(); } // We should have more than initialBalance in the end assertTrue(ethereum.getRepository().getBalance(coinbase.getAddress()).compareTo(initialBalance) > 0); // Check that assertCasperReceipts was called - assertEquals(14, totalEpochs); // floor division (300 + 400 + 10) / 50 - assertEquals(6, totalVotes); + assertEquals(17, totalEpochs); // floor division (300 + 550 + 10) / 50 + assertEquals(9, totalVotes); // 5 votes for first 300 blocks (5 epochs as validator) + 4 votes for logout delay, last epoch is w/o vote // TODO: add more validators } @@ -195,9 +197,9 @@ protected BigDecimal calculateCurrentDepositSize(long validatorIndex) { } protected static BigDecimal calculateCurrentDepositSize(long validatorIndex, CasperFacade casperFacade) { - BigDecimal scaleFactor = (BigDecimal) casperFacade.constCall("get_deposit_scale_factor", - (BigInteger) casperFacade.constCall("get_current_epoch")[0])[0]; - BigDecimal curDeposit = (BigDecimal) casperFacade.constCall("get_validators__deposit", validatorIndex)[0]; + BigDecimal scaleFactor = (BigDecimal) casperFacade.constCall("deposit_scale_factor", + (BigInteger) casperFacade.constCall("current_epoch")[0])[0]; + BigDecimal curDeposit = (BigDecimal) casperFacade.constCall("validators__deposit", validatorIndex)[0]; BigDecimal scaledDepositWei = curDeposit.multiply(scaleFactor); return scaledDepositWei; } From 179888a7d3cf27e99c8ce80e2732bd3ace586cf7 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 10 Apr 2018 16:58:22 +0300 Subject: [PATCH 64/67] Temporary EIP-86 partial implementation --- .../config/net/CasperTestNetConfig.java | 22 +++++++++++++++++++ .../ethereum/casper/core/CasperFacade.java | 6 +++++ .../core/CasperTransactionExecutor.java | 11 +--------- .../config/blockchain/HomesteadConfig.java | 3 +-- .../java/org/ethereum/core/Transaction.java | 11 ++++++---- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java index e9be295c4b..f3060e6554 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java @@ -17,6 +17,7 @@ */ package org.ethereum.casper.config.net; +import org.ethereum.casper.core.CasperFacade; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.Constants; import org.ethereum.config.ConstantsAdapter; @@ -24,11 +25,15 @@ import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; +import org.ethereum.core.Transaction; import org.ethereum.crypto.ECKey; import org.ethereum.vm.GasCost; import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; +import java.util.Objects; + +import static org.ethereum.config.blockchain.HomesteadConfig.SECP256K1N_HALF; public class CasperTestNetConfig extends BaseNetConfig { @@ -38,6 +43,7 @@ public class CasperTestNetConfig extends BaseNetConfig { public static final double BASE_INTEREST_FACTOR = 0.1; public static final double BASE_PENALTY_FACTOR = 0.0001; public static final int MIN_DEPOSIT_ETH = 1500; + private byte[] casperAddress = null; public final static ECKey NULL_SIGN_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); @@ -85,9 +91,25 @@ public boolean eip161() { public Constants getConstants() { return constants; } + + @Override + public boolean acceptTransactionSignature(Transaction tx) { + if (tx.getSignature() != null) { + // Homestead-like check + if (!tx.getSignature().validateComponents() || + tx.getSignature().s.compareTo(SECP256K1N_HALF) > 0) return false; + } else { + if (casperAddress == null || !CasperFacade.isVote(tx, casperAddress)) return false; + } + return tx.getChainId() == null || Objects.equals(getChainId(), tx.getChainId()); + } } public CasperTestNetConfig() { add(0, new CasperConfig(new FrontierConfig())); } + + public void setCasperAddress(byte[] casperAddress) { + this.casperAddress = casperAddress; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index a2549d721f..d28011e583 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -20,6 +20,8 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.casper.config.CasperProperties; +import org.ethereum.casper.config.net.CasperTestNetConfig; +import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CallTransaction; @@ -81,6 +83,10 @@ private void init() { byte[] casperAddress = res.getKey(); this.initTxs = res.getValue(); systemProperties.setCasperAddress(casperAddress); + BlockchainNetConfig netConfig = systemProperties.getBlockchainConfig(); + if (netConfig instanceof CasperTestNetConfig) { + ((CasperTestNetConfig) netConfig).setCasperAddress(casperAddress); + } this.contractAddress = Hex.toHexString(casperAddress); logger.info("Casper contract address set to [0x{}]", contractAddress); String casperAbi = systemProperties.getCasperAbi(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 6276f58083..ab73b17235 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -74,17 +74,12 @@ public void init() { } } - @Override - protected boolean isSignatureValid() { - return isCasperVote() || super.isSignatureValid(); - } - @Override public void execute() { if (!readyToExecute) return; - if (!localCall && !isCasperVote()) { + if (!localCall && !isCasperServiceTx()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -106,10 +101,6 @@ private boolean isCasperServiceTx() { return CasperFacade.isServiceTx(tx, ((CasperProperties) config).getCasperAddress()); } - private boolean isCasperVote() { - return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); - } - @Override protected void payRewards(final TransactionExecutionSummary summary) { if (isCasperServiceTx()) { 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 745d7e212a..270fd7f670 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 @@ -29,7 +29,7 @@ */ public class HomesteadConfig extends FrontierConfig { - static final BigInteger SECP256K1N_HALF = Constants.getSECP256K1N().divide(BigInteger.valueOf(2)); + public static final BigInteger SECP256K1N_HALF = Constants.getSECP256K1N().divide(BigInteger.valueOf(2)); public static class HomesteadConstants extends FrontierConstants { @Override @@ -68,7 +68,6 @@ public long getTransactionCost(Transaction tx) { @Override public boolean acceptTransactionSignature(Transaction tx) { if (!super.acceptTransactionSignature(tx)) return false; - if (tx.getSignature() == null) return false; return tx.getSignature().s.compareTo(SECP256K1N_HALF) <= 0; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java index a1254e4025..59e84f11b1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java @@ -160,7 +160,8 @@ public Transaction(byte[] nonce, byte[] gasPrice, byte[] gasLimit, byte[] receiv } - private Integer extractChainIdFromV(BigInteger bv) { + private Integer extractChainIdFromRawSignature(BigInteger bv, byte[] r, byte[] s) { + if (r == null && s == null) return bv.intValue(); // EIP 86 if (bv.bitLength() > 31) return Integer.MAX_VALUE; // chainId is limited to 31 bits, longer are not valid for now long v = bv.longValue(); if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) return null; @@ -213,10 +214,12 @@ public synchronized void rlpParse() { if (transaction.get(6).getRLPData() != null) { byte[] vData = transaction.get(6).getRLPData(); BigInteger v = ByteUtil.bytesToBigInteger(vData); - this.chainId = extractChainIdFromV(v); byte[] r = transaction.get(7).getRLPData(); byte[] s = transaction.get(8).getRLPData(); - this.signature = ECDSASignature.fromComponents(r, s, getRealV(v)); + this.chainId = extractChainIdFromRawSignature(v, r, s); + if (r != null && s != null) { + this.signature = ECDSASignature.fromComponents(r, s, getRealV(v)); + } } else { logger.debug("RLP encoded tx is not signed!"); } @@ -381,7 +384,7 @@ public synchronized byte[] getSender() { if (sendAddress == null && getSignature() != null) { sendAddress = ECKey.signatureToAddress(getRawHash(), getSignature()); } - // FIXME: Casper votes, we shouldn't do it this for Transaction itself + // TODO: check for side-effects return sendAddress == null ? NULL_SENDER : sendAddress; } catch (SignatureException e) { logger.error(e.getMessage(), e); From e835c4a0bc8ddcb54798d78b6b8239878f60a9ed Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 11 Apr 2018 18:24:20 +0300 Subject: [PATCH 65/67] Fixing Circle CI for Casper branch --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 2d46999d4d..8e0ad34370 100644 --- a/circle.yml +++ b/circle.yml @@ -27,7 +27,7 @@ dependencies: - cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/ethash/. ~/.ethash # Cache gradle artifacts - (cd ~/ethereumj && ./gradlew compileJava) - - (cd ~ && git clone --depth 1 -b develop https://github.com/ether-camp/ethereum-harmony.git) + - (cd ~ && git clone --depth 1 -b research/casper https://github.com/ether-camp/ethereum-harmony.git) - (cd ~/ethereum-harmony && ./gradlew dependencyManagement) test: From 316c43df0cb8c45470ab971f0b90b3d102cd51a0 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Wed, 11 Apr 2018 23:49:40 +0300 Subject: [PATCH 66/67] Refactored tx validation --- .../casper/config/CasperProperties.java | 8 +- .../casper/config/net/CasperTestConfig.java | 116 ++++++++++++++++++ .../config/net/CasperTestNetConfig.java | 87 +------------ .../casper/core/CasperBlockchain.java | 2 +- .../ethereum/casper/core/CasperFacade.java | 22 ++-- .../validator/NullSenderTxValidator.java | 48 ++++++++ .../core/casper/BadCasperValidatorTest.java | 2 +- .../org/ethereum/core/casper/CasperBase.java | 7 +- .../core/casper/CasperEpochSwitchTest.java | 8 -- .../core/casper/CasperValidatorTest.java | 38 ++---- 10 files changed, 193 insertions(+), 145 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java create mode 100644 ethereumj-core/src/main/java/org/ethereum/casper/validator/NullSenderTxValidator.java diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java index 0101bd5bc8..4137a174f2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/CasperProperties.java @@ -1,13 +1,7 @@ package org.ethereum.casper.config; -import org.apache.commons.lang3.tuple.Pair; -import org.ethereum.casper.config.net.CasperTestNetConfig; -import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.SystemProperties; -import org.ethereum.core.genesis.GenesisConfig; import org.ethereum.util.ByteUtil; -import org.ethereum.validator.BlockCustomHashRule; -import org.ethereum.validator.BlockHeaderValidator; import java.io.BufferedReader; import java.io.IOException; @@ -15,7 +9,7 @@ import java.io.InputStreamReader; import java.util.stream.Collectors; -import static org.ethereum.casper.config.net.CasperTestNetConfig.EPOCH_LENGTH; +import static org.ethereum.casper.config.net.CasperTestConfig.EPOCH_LENGTH; public class CasperProperties extends SystemProperties { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java new file mode 100644 index 0000000000..cb7925d872 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.config.net; + +import org.ethereum.casper.validator.NullSenderTxValidator; +import org.ethereum.config.BlockchainConfig; +import org.ethereum.config.Constants; +import org.ethereum.config.ConstantsAdapter; +import org.ethereum.config.blockchain.ByzantiumConfig; +import org.ethereum.config.blockchain.Eip150HFConfig; +import org.ethereum.core.Transaction; +import org.ethereum.crypto.ECKey; +import org.ethereum.vm.GasCost; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static org.ethereum.config.blockchain.HomesteadConfig.SECP256K1N_HALF; + +public class CasperTestConfig extends ByzantiumConfig { + + public static final int EPOCH_LENGTH = 50; + public static final int WITHDRAWAL_DELAY = 5; + public static final int DYNASTY_LOGOUT_DELAY = 5; + public static final double BASE_INTEREST_FACTOR = 0.1; + public static final double BASE_PENALTY_FACTOR = 0.0001; + public static final int MIN_DEPOSIT_ETH = 1500; + public final static ECKey NULL_SIGN_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + + private final Constants constants; + + private List nullSenderTxValidators = new ArrayList<>(); + + public CasperTestConfig(BlockchainConfig parent) { + + super(parent); + constants = new ConstantsAdapter(super.getConstants()) { + private final BigInteger BLOCK_REWARD = new BigInteger("1000000000000000000"); // 1 ETH + + private final BigInteger MINIMUM_DIFFICULTY = BigInteger.valueOf(8192); + + @Override + public BigInteger getBLOCK_REWARD() { + return BLOCK_REWARD; + } + + @Override + public BigInteger getMINIMUM_DIFFICULTY() { + return MINIMUM_DIFFICULTY; + } + }; + } + + static class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { + public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork + } + + private static final GasCost NEW_GAS_COST = new CasperGasCost(); + + + @Override + public GasCost getGasCost() { + return NEW_GAS_COST; + } + + @Override + public boolean eip161() { + return false; + } + + @Override + public Constants getConstants() { + return constants; + } + + @Override + public boolean acceptTransactionSignature(Transaction tx) { + if (tx.getSignature() != null) { + // Homestead-like check + if (!tx.getSignature().validateComponents() || + tx.getSignature().s.compareTo(SECP256K1N_HALF) > 0) return false; + } else { + boolean success = false; + for (NullSenderTxValidator validator : nullSenderTxValidators) { + if (validator.validate(tx)) { + success = true; + break; + } + } + if(!success) return false; + } + return tx.getChainId() == null || Objects.equals(getChainId(), tx.getChainId()); + } + + public void addNullSenderTxValidators(NullSenderTxValidator validator) { + nullSenderTxValidators.add(validator); + } +} \ No newline at end of file diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java index f3060e6554..e89a745ceb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java @@ -17,99 +17,14 @@ */ package org.ethereum.casper.config.net; -import org.ethereum.casper.core.CasperFacade; -import org.ethereum.config.BlockchainConfig; -import org.ethereum.config.Constants; -import org.ethereum.config.ConstantsAdapter; -import org.ethereum.config.blockchain.ByzantiumConfig; -import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; -import org.ethereum.core.Transaction; -import org.ethereum.crypto.ECKey; -import org.ethereum.vm.GasCost; -import org.spongycastle.util.encoders.Hex; - -import java.math.BigInteger; -import java.util.Objects; - -import static org.ethereum.config.blockchain.HomesteadConfig.SECP256K1N_HALF; public class CasperTestNetConfig extends BaseNetConfig { - public static final int EPOCH_LENGTH = 50; - public static final int WITHDRAWAL_DELAY = 5; - public static final int DYNASTY_LOGOUT_DELAY = 5; - public static final double BASE_INTEREST_FACTOR = 0.1; - public static final double BASE_PENALTY_FACTOR = 0.0001; - public static final int MIN_DEPOSIT_ETH = 1500; - private byte[] casperAddress = null; - - public final static ECKey NULL_SIGN_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); - public static final CasperTestNetConfig INSTANCE = new CasperTestNetConfig(); - static class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { - public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork - } - - private static final GasCost NEW_GAS_COST = new CasperGasCost(); - - private class CasperConfig extends ByzantiumConfig { - private final Constants constants; - public CasperConfig(BlockchainConfig parent) { - - super(parent); - constants = new ConstantsAdapter(super.getConstants()) { - private final BigInteger BLOCK_REWARD = new BigInteger("1000000000000000000"); // 1 ETH - - private final BigInteger MINIMUM_DIFFICULTY = BigInteger.valueOf(8192); - - @Override - public BigInteger getBLOCK_REWARD() { - return BLOCK_REWARD; - } - - @Override - public BigInteger getMINIMUM_DIFFICULTY() { - return MINIMUM_DIFFICULTY; - } - }; - } - - @Override - public GasCost getGasCost() { - return NEW_GAS_COST; - } - - @Override - public boolean eip161() { - return false; - } - - @Override - public Constants getConstants() { - return constants; - } - - @Override - public boolean acceptTransactionSignature(Transaction tx) { - if (tx.getSignature() != null) { - // Homestead-like check - if (!tx.getSignature().validateComponents() || - tx.getSignature().s.compareTo(SECP256K1N_HALF) > 0) return false; - } else { - if (casperAddress == null || !CasperFacade.isVote(tx, casperAddress)) return false; - } - return tx.getChainId() == null || Objects.equals(getChainId(), tx.getChainId()); - } - } - public CasperTestNetConfig() { - add(0, new CasperConfig(new FrontierConfig())); - } - - public void setCasperAddress(byte[] casperAddress) { - this.casperAddress = casperAddress; + add(0, new CasperTestConfig(new FrontierConfig())); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java index 83fbd6dd99..e17ddae3b3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperBlockchain.java @@ -46,7 +46,7 @@ import java.util.Map; import static java.math.BigInteger.ONE; -import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; +import static org.ethereum.casper.config.net.CasperTestConfig.NULL_SIGN_SENDER; import static org.ethereum.core.ImportResult.EXIST; import static org.ethereum.core.ImportResult.IMPORTED_BEST; import static org.ethereum.core.ImportResult.IMPORTED_NOT_BEST; diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index d28011e583..1c1d762945 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -20,8 +20,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.casper.config.CasperProperties; -import org.ethereum.casper.config.net.CasperTestNetConfig; -import org.ethereum.config.BlockchainNetConfig; +import org.ethereum.casper.config.net.CasperTestConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CallTransaction; @@ -31,6 +30,7 @@ import org.ethereum.facade.Ethereum; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; +import org.ethereum.casper.validator.NullSenderTxValidator; import org.ethereum.vm.program.ProgramResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,12 +43,12 @@ import java.util.Arrays; import java.util.List; -import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_INTEREST_FACTOR; -import static org.ethereum.casper.config.net.CasperTestNetConfig.BASE_PENALTY_FACTOR; -import static org.ethereum.casper.config.net.CasperTestNetConfig.DYNASTY_LOGOUT_DELAY; -import static org.ethereum.casper.config.net.CasperTestNetConfig.MIN_DEPOSIT_ETH; -import static org.ethereum.casper.config.net.CasperTestNetConfig.NULL_SIGN_SENDER; -import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; +import static org.ethereum.casper.config.net.CasperTestConfig.BASE_INTEREST_FACTOR; +import static org.ethereum.casper.config.net.CasperTestConfig.BASE_PENALTY_FACTOR; +import static org.ethereum.casper.config.net.CasperTestConfig.DYNASTY_LOGOUT_DELAY; +import static org.ethereum.casper.config.net.CasperTestConfig.MIN_DEPOSIT_ETH; +import static org.ethereum.casper.config.net.CasperTestConfig.NULL_SIGN_SENDER; +import static org.ethereum.casper.config.net.CasperTestConfig.WITHDRAWAL_DELAY; import static org.ethereum.crypto.HashUtil.sha3; @Component @@ -83,10 +83,8 @@ private void init() { byte[] casperAddress = res.getKey(); this.initTxs = res.getValue(); systemProperties.setCasperAddress(casperAddress); - BlockchainNetConfig netConfig = systemProperties.getBlockchainConfig(); - if (netConfig instanceof CasperTestNetConfig) { - ((CasperTestNetConfig) netConfig).setCasperAddress(casperAddress); - } + CasperTestConfig config = (CasperTestConfig) systemProperties.getBlockchainConfig().getConfigForBlock(0); + config.addNullSenderTxValidators(new NullSenderTxValidator(this::isVote)); this.contractAddress = Hex.toHexString(casperAddress); logger.info("Casper contract address set to [0x{}]", contractAddress); String casperAbi = systemProperties.getCasperAbi(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/validator/NullSenderTxValidator.java b/ethereumj-core/src/main/java/org/ethereum/casper/validator/NullSenderTxValidator.java new file mode 100644 index 0000000000..808ecfa085 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/casper/validator/NullSenderTxValidator.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.ethereum.casper.validator; + +import java.util.function.Function; +import org.ethereum.core.Transaction; +import org.ethereum.validator.AbstractValidationRule; + +/** + * Customizable validator for checking NULL_SENDER tx for acceptance + */ +public class NullSenderTxValidator extends AbstractValidationRule { + + private Function validator; + + public NullSenderTxValidator(Function validator) { + this.validator = validator; + } + + @Override + public Class getEntityClass() { + return Transaction.class; + } + + /** + * Runs transaction validation and returns its result + * + * @param transaction + */ + public Boolean validate(Transaction transaction) { + return validator.apply(transaction); + } +} diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java index 98f21bb42f..c3892e3fb7 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/BadCasperValidatorTest.java @@ -42,7 +42,7 @@ import static junit.framework.TestCase.assertEquals; import static org.ethereum.crypto.HashUtil.sha3; -@Ignore // Takes too long to run usually +@Ignore // Takes too long to run regularly public class BadCasperValidatorTest extends CasperBase { private int totalVotes = 0; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java index f1fba2c209..dc681e2198 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperBase.java @@ -19,6 +19,7 @@ import org.ethereum.casper.config.CasperBeanConfig; import org.ethereum.casper.config.CasperProperties; +import org.ethereum.casper.config.net.CasperTestConfig; import org.ethereum.casper.core.CasperBlockchain; import org.ethereum.casper.core.CasperFacade; import org.ethereum.casper.core.CasperPendingStateImpl; @@ -52,6 +53,7 @@ import org.ethereum.net.server.ChannelManager; import org.ethereum.util.blockchain.StandaloneBlockchain; import org.ethereum.validator.DependentBlockHeaderRuleAdapter; +import org.ethereum.casper.validator.NullSenderTxValidator; import org.ethereum.vm.program.ProgramPrecompile; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; import org.junit.Before; @@ -73,7 +75,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doCallRealMethod; // We have all mocks here and not all of them are used in every test, so strict stubs should be turned off @RunWith(MockitoJUnitRunner.Silent.class) @@ -121,7 +122,9 @@ public void setup() throws Exception { // Just trust me! // FIXME: Make it a little bit readable - systemProperties.setBlockchainConfig(config()); + BlockchainNetConfig config = config(); + ((CasperTestConfig) config.getConfigForBlock(0)).addNullSenderTxValidators(new NullSenderTxValidator(casper::isVote)); + systemProperties.setBlockchainConfig(config); Resource casperGenesis = new ClassPathResource("/genesis/casper.json"); systemProperties.useGenesis(casperGenesis.getInputStream()); systemProperties.overrideParams( diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java index 477023a911..8d74454590 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperEpochSwitchTest.java @@ -17,16 +17,8 @@ */ package org.ethereum.core.casper; -import org.ethereum.config.BlockchainConfig; import org.ethereum.config.BlockchainNetConfig; -import org.ethereum.config.Constants; -import org.ethereum.config.ConstantsAdapter; -import org.ethereum.config.blockchain.ByzantiumConfig; -import org.ethereum.config.blockchain.Eip150HFConfig; -import org.ethereum.config.blockchain.FrontierConfig; -import org.ethereum.config.net.BaseNetConfig; import org.ethereum.core.Block; -import org.ethereum.vm.GasCost; import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 08306348a3..5e1451d030 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -17,13 +17,12 @@ */ package org.ethereum.core.casper; +import org.ethereum.casper.config.net.CasperTestConfig; import org.ethereum.casper.core.CasperFacade; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.Constants; import org.ethereum.config.ConstantsAdapter; -import org.ethereum.config.blockchain.ByzantiumConfig; -import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; import org.ethereum.core.Block; @@ -35,7 +34,6 @@ import org.ethereum.sync.SyncManager; import org.ethereum.util.FastByteComparisons; import org.ethereum.util.blockchain.EtherUtil; -import org.ethereum.vm.GasCost; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -49,11 +47,11 @@ import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; -import static org.ethereum.casper.config.net.CasperTestNetConfig.DYNASTY_LOGOUT_DELAY; -import static org.ethereum.casper.config.net.CasperTestNetConfig.WITHDRAWAL_DELAY; +import static org.ethereum.casper.config.net.CasperTestConfig.DYNASTY_LOGOUT_DELAY; +import static org.ethereum.casper.config.net.CasperTestConfig.WITHDRAWAL_DELAY; import static org.ethereum.crypto.HashUtil.sha3; -@Ignore // Takes too long to run usually +@Ignore // Takes too long to run regularly public class CasperValidatorTest extends CasperBase { private int totalVotes = 0; @@ -65,16 +63,10 @@ public class CasperValidatorTest extends CasperBase { final ECKey coinbase = ECKey.fromPrivate(sha3("cow".getBytes())); // Premined in light genesis - private static class CasperEasyConfig extends BaseNetConfig { - class CasperGasCost extends Eip150HFConfig.GasCostEip150HF { - public int getEXP_BYTE_GAS() { return 10; } // before spurious dragon hard fork - } - - private final GasCost NEW_GAS_COST = new CasperEasyConfig.CasperGasCost(); - - private class CasperConfig extends ByzantiumConfig { + protected static class CasperEasyNetConfig extends BaseNetConfig { + private class CasperEasyConfig extends CasperTestConfig { private final Constants constants; - CasperConfig(BlockchainConfig parent) { + CasperEasyConfig(BlockchainConfig parent) { super(parent); constants = new ConstantsAdapter(super.getConstants()) { @@ -94,28 +86,18 @@ public BigInteger getMINIMUM_DIFFICULTY() { }; } - @Override - public GasCost getGasCost() { - return NEW_GAS_COST; - } - - @Override - public boolean eip161() { - return false; - } - @Override public Constants getConstants() { return constants; } } - public CasperEasyConfig() { - add(0, new CasperConfig(new FrontierConfig())); + public CasperEasyNetConfig() { + add(0, new CasperEasyConfig(new FrontierConfig())); } } - protected final static BlockchainNetConfig CASPER_EASY_CONFIG = new CasperEasyConfig(); + protected final static BlockchainNetConfig CASPER_EASY_CONFIG = new CasperEasyNetConfig(); @Override BlockchainNetConfig config() { From 29614b4f591cbcf4bae19d92ba27650f7dae68a1 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Thu, 12 Apr 2018 00:04:23 +0300 Subject: [PATCH 67/67] Testing chainId compatibility --- .../org/ethereum/casper/config/net/CasperTestConfig.java | 5 +++++ .../org/ethereum/casper/service/CasperValidatorService.java | 3 ++- .../java/org/ethereum/core/casper/CasperValidatorTest.java | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java index cb7925d872..b682c2fd65 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestConfig.java @@ -91,6 +91,11 @@ public Constants getConstants() { return constants; } + @Override + public Integer getChainId() { + return null; + } + @Override public boolean acceptTransactionSignature(Transaction tx) { if (tx.getSignature() != null) { diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java index e4ab02a42d..c38b779b5c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/service/CasperValidatorService.java @@ -289,7 +289,8 @@ private Transaction makeTx(byte[] receiveAddress, BigInteger value, byte[] data, gasLimit, receiveAddress, ByteUtil.bigIntegerToBytes(value), - data); + data, + ethereum.getChainIdForNextBlock()); if (signed) tx.sign(coinbase); diff --git a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java index 5e1451d030..e68e87b213 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/casper/CasperValidatorTest.java @@ -90,6 +90,11 @@ public BigInteger getMINIMUM_DIFFICULTY() { public Constants getConstants() { return constants; } + + @Override + public Integer getChainId() { + return 345; + } } public CasperEasyNetConfig() {