/* * 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.mine; import org.ethereum.core.Block; import org.ethereum.util.ByteUtil; import org.ethereum.util.FastByteComparisons; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.Arrays; import org.spongycastle.util.BigIntegers; import java.math.BigInteger; import static org.ethereum.crypto.HashUtil.sha3; /** * The Miner performs the proof-of-work needed for a valid block * * The mining proof-of-work (PoW) exists as a cryptographically secure nonce * that proves beyond reasonable doubt that a particular amount of computation * has been expended in the determination of some token value n. * It is utilised to enforce the blockchain security by giving meaning * and credence to the notion of difficulty (and, by extension, total difficulty). * * However, since mining new blocks comes with an attached reward, * the proof-of-work not only functions as a method of securing confidence * that the blockchain will remain canonical into the future, but also as * a wealth distribution mechanism. * * See Yellow Paper: http://www.gavwood.com/Paper.pdf (chapter 11.5 Mining Proof-of-Work) */ public class Miner { private static final Logger logger = LoggerFactory.getLogger("miner"); private boolean stop = false; /** * Adds a nonce to given block which complies with the given difficulty * * For the PoC series, we use a simplified proof-of-work. * This is not ASIC resistant and is meant merely as a placeholder. * It utilizes the bare SHA3 hash function to secure the block chain by requiring * the SHA3 hash of the concatenation of the nonce and the header’s SHA3 hash to be * sufficiently low. It is formally defined as PoW: * * PoW(H, n) ≡ BE(SHA3(SHA3(RLP(H!n)) ◦ n)) * * where: * RLP(H!n) is the RLP encoding of the block header H, not including the * final nonce component; * SHA3 is the SHA3 hash function accepting an arbitrary length series of * bytes and evaluating to a series of 32 bytes (i.e. 256-bit); * n is the nonce, a series of 32 bytes; * o is the series concatenation operator; * BE(X) evaluates to the value equal to X when interpreted as a * big-endian-encoded integer. * * @param newBlock without a valid nonce * @param difficulty - the mining difficulty * @return true if valid nonce has been added to the block */ public boolean mine(Block newBlock, byte[] difficulty) { // eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; } stop = false; BigInteger max = BigInteger.valueOf(2).pow(255); byte[] target = BigIntegers.asUnsignedByteArray(32, max.divide(new BigInteger(1, difficulty))); long newGasLimit = Math.max(125000, (new BigInteger(1, newBlock.getGasLimit()).longValue() * (1024 - 1) + (newBlock.getGasUsed() * 6 / 5)) / 1024); newBlock.getHeader().setGasLimit(BigInteger.valueOf(newGasLimit).toByteArray()); byte[] hash = sha3(newBlock.getEncodedWithoutNonce()); byte[] testNonce = new byte[32]; byte[] concat; while (ByteUtil.increment(testNonce) && !stop) { if (testNonce[31] == 0 && testNonce[30] == 0) { System.out.println("mining: " + new BigInteger(1, testNonce)); } if (testNonce[31] == 0) sleep(); concat = Arrays.concatenate(hash, testNonce); byte[] result = sha3(concat); if (FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0) { newBlock.setNonce(testNonce); return true; } } return false; // couldn't find a valid nonce } public void stop() { stop = true; } private void sleep() { try { // Thread.sleep(1); Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } }