Package test.ethereum.mine

Source Code of test.ethereum.mine.MinerThread

package test.ethereum.mine;

import org.ethereum.core.Block;
import org.ethereum.core.BlockHeader;
import org.ethereum.core.Chain;
import org.ethereum.core.Genesis;
import org.ethereum.mine.Miner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;

import java.util.ArrayList;
import java.util.List;

/**
* @author Roman Mandeleil
* Created on: 22/05/2014 09:26
*/
public class MinerThread implements Runnable {


  private final static Logger logger = LoggerFactory.getLogger("miner");
    private final byte[] coinbase;

    private MineSwarm   mineSwarm;
    private String      name;
    private boolean     done = false;
    private Miner miner = new Miner();

    private Chain mainChain  = new Chain();
    private List<Chain> altChains  = new ArrayList<>();
    private Block       tmpBlock   = null;
    private List<Block> uncles     = new ArrayList<>();

    private Block announcedBlock = null;

  public MinerThread(String name,  MineSwarm mineSwarm, byte[] coinbase) {
        this.name = name;
        this.mineSwarm = mineSwarm;
        this.coinbase = coinbase;

        Block genesis = Genesis.getInstance();
        mainChain.add(genesis);

  }

  @Override
  public void run() {
    logger.debug("{} start", name);
        doRun();
    logger.debug("{} end", name);
  }

    public void onNewBlock(Block foundBlock){

        if (mainChain.getLast().isEqual(foundBlock)){
            // That is our announcement, do nothing.
            return;
        }

        logger.info("{}: Ohh.. I heard the block was found already: {}: {} ^ {}", name,
                foundBlock.getNumber(), Hex.toHexString(foundBlock.getHash()).substring(0, 6),
                Hex.toHexString(foundBlock.getParentHash()).substring(0, 6));


        if ( mainChain.getLast().isParentOf(foundBlock) ){
            logger.info("{}: adding by announce to main chain. hash:{} ", name,
                    Hex.toHexString(foundBlock.getHash()).substring(0, 6));
            // add it as main block
            announcedBlock = foundBlock;
            miner.stop();
        } else{

            if (mainChain.isParentOnTheChain(foundBlock)){

                logger.info("{} found an uncle. on index: {}", name, foundBlock.getNumber());
                // add it as a future uncle
                uncles.add(foundBlock);
            } else{
                logger.info("{}: nothing to do, maybe alt chain: {}: {} ^ {}", name,
                        foundBlock.getNumber(), Hex.toHexString(foundBlock.getHash()).substring(0, 6),
                        Hex.toHexString(foundBlock.getParentHash()).substring(0, 6));
            }
        }
    }

    public void announceBlock(Block block){
        mineSwarm.announceBlock(block);
    }

  private void doRun() {

        Block genesis = mainChain.getLast();
        tmpBlock = createBlock(genesis, coinbase);
        while (!done){

            this.announcedBlock = null;
            logger.info("{}: before mining: chain.size: [{}], chain.TD: [{}]", name,
                    mainChain.getSize(), mainChain.getTotalDifficulty());
            boolean found = miner.mine(tmpBlock, tmpBlock.getDifficulty());
            logger.info("{}: finished mining, found: [{}]", name, found);

            if (!found && announcedBlock != null){
                mainChain.add(announcedBlock);
                tmpBlock = createBlock(announcedBlock, coinbase);
            }

            if (found) {
                mineSwarm.addToQueue(tmpBlock);
                logger.info("{}: mined block: {} --> {} ^ {}", name, tmpBlock.getNumber(),
                        Hex.toHexString(tmpBlock.getHash()).substring(0, 6),
                        Hex.toHexString(tmpBlock.getParentHash()).substring(0, 6));
                if (announcedBlock != null)
                    logger.info("{}: forked on: {}",name, tmpBlock.getNumber());

                logger.info("{}: adding to main chain. hash:{} ", name,
                        Hex.toHexString(tmpBlock.getHash()).substring(0, 6));
                mainChain.add(tmpBlock);
                sleep();
                announceBlock(tmpBlock);
                tmpBlock = createBlock(tmpBlock, coinbase);
            }

            if (!uncles.isEmpty()){
                for (Block uncle : uncles){
                    BlockHeader uncleHeader = uncle.getHeader();
                    tmpBlock.addUncle(uncleHeader);
                    logger.info("{} adding {} uncles to block: {}", name, uncles.size(), tmpBlock.getNumber());
                }
                uncles.clear();
            }

            if (mainChain.getSize() == 100) done = true;
        }

    }


    public static Block createBlock(Block lastBlock, byte[] coinbase) {

       long timeDiff = System.currentTimeMillis() - lastBlock.getTimestamp();

       byte[] difficulty = lastBlock.getDifficulty();
//       if (timeDiff < 5000){
//           System.out.println("increase");
//           BigInteger diff = (new BigInteger(1, lastBlock.getDifficulty()).add(new BigInteger("FFF", 16)));
//           difficulty = diff.toByteArray();
//       }

        Block newBlock = new Block(lastBlock.getHash(), lastBlock.getUnclesHash(), coinbase, lastBlock.getLogBloom(),
                difficulty , lastBlock.getNumber() + 1, lastBlock.getMinGasPrice(),
                lastBlock.getGasLimit(), lastBlock.getGasUsed(), System.currentTimeMillis() / 1000,
                null, null,  null, null);

        return newBlock;
    }

    public boolean isDone() {
        return done;
    }

    public Chain getChain() {
        return mainChain;
    }

    private void sleep(){
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}
TOP

Related Classes of test.ethereum.mine.MinerThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.