/* * Copyright (c) [2016] [ <ether.camp> ] * 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 <http://www.gnu.org/licenses/>. */ package org.ethereum.config.blockchain; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.Constants; import org.ethereum.config.SystemProperties; import org.ethereum.core.*; import org.ethereum.db.BlockStore; import org.ethereum.mine.EthashMiner; import org.ethereum.mine.MinerIfc; import org.ethereum.validator.BlockHeaderValidator; import org.ethereum.vm.DataWord; import org.ethereum.vm.GasCost; import org.ethereum.vm.OpCode; import org.ethereum.vm.program.Program; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Objects; import static org.ethereum.util.BIUtil.max; /** * BlockchainForkConfig is also implemented by this class - its (mostly testing) purpose to represent * the specific config for all blocks on the chain (kinda constant config). * * Created by Anton Nashatyrev on 25.02.2016. */ public abstract class AbstractConfig implements BlockchainConfig, BlockchainNetConfig { private static final GasCost GAS_COST = new GasCost(); protected Constants constants; protected MinerIfc miner; private List<Pair<Long, BlockHeaderValidator>> headerValidators = new ArrayList<>(); public AbstractConfig() { this(new Constants()); } public AbstractConfig(Constants constants) { this.constants = constants; } @Override public Constants getConstants() { return constants; } @Override public BlockchainConfig getConfigForBlock(long blockHeader) { return this; } @Override public Constants getCommonConstants() { return getConstants(); } @Override public MinerIfc getMineAlgorithm(SystemProperties config) { if (miner == null) miner = new EthashMiner(config); return miner; } @Override public BigInteger calcDifficulty(BlockHeader curBlock, BlockHeader parent) { BigInteger pd = parent.getDifficultyBI(); BigInteger quotient = pd.divide(getConstants().getDIFFICULTY_BOUND_DIVISOR()); BigInteger sign = getCalcDifficultyMultiplier(curBlock, parent); BigInteger fromParent = pd.add(quotient.multiply(sign)); BigInteger difficulty = max(getConstants().getMINIMUM_DIFFICULTY(), fromParent); int explosion = getExplosion(curBlock, parent); if (explosion >= 0) { difficulty = max(getConstants().getMINIMUM_DIFFICULTY(), difficulty.add(BigInteger.ONE.shiftLeft(explosion))); } return difficulty; } protected abstract BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader parent); protected int getExplosion(BlockHeader curBlock, BlockHeader parent) { int periodCount = (int) (curBlock.getNumber() / getConstants().getEXP_DIFFICULTY_PERIOD()); return periodCount - 2; } @Override public boolean acceptTransactionSignature(Transaction tx) { return Objects.equals(tx.getChainId(), getChainId()); } @Override public String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transaction tx, Repository repository) { return null; } @Override public void hardForkTransfers(Block block, Repository repo) {} @Override public byte[] getExtraData(byte[] minerExtraData, long blockNumber) { return minerExtraData; } @Override public List<Pair<Long, BlockHeaderValidator>> headerValidators() { return headerValidators; } @Override public GasCost getGasCost() { return GAS_COST; } @Override public DataWord getCallGas(OpCode op, DataWord requestedGas, DataWord availableGas) throws Program.OutOfGasException { if (requestedGas.compareTo(availableGas) > 0) { throw Program.Exception.notEnoughOpGas(op, requestedGas, availableGas); } return requestedGas.clone(); } @Override public DataWord getCreateGas(DataWord availableGas) { return availableGas; } @Override public boolean eip161() { return false; } @Override public Integer getChainId() { return null; } @Override public String toString() { return getClass().getSimpleName(); } }