As of now the geth miner running on my system mines even empty blocks. All i wanted is miner should mine only when there are Transactions to mine, after mining the miner should immediately sleep.

How to achieve this?

up vote 26 down vote accepted

You can load this script to your geth console

Mine only when there are transactions!

var mining_threads = 1

function checkWork() {
    if (eth.getBlock("pending").transactions.length > 0) {
        if (eth.mining) return;
        console.log("== Pending transactions! Mining...");
        miner.start(mining_threads);
    } else {
        miner.stop();
        console.log("== No transactions! Mining stopped.");
    }
}

eth.filter("latest", function(err, block) { checkWork(); });
eth.filter("pending", function(err, block) { checkWork(); });

checkWork();

See other useful snippets here

Mining until x confirmations have been achieved

This question is particularly relevant to private chains where transactions may be more sporadic than on public chains. In some applications it may be beneficial to continue mining for a set number of blocks after the latest transaction to ensure adequate confirmations are reached before mining stops and avoiding the latest transaction only receiving one confirmation (e.g. when using mist on private networks it likes to see 12 confirmations):

var mining_threads = 1
var txBlock = 0

function checkWork() {
if (eth.getBlock("pending").transactions.length > 0) {
    txBlock = eth.getBlock("pending").number
    if (eth.mining) return;
    console.log("  Transactions pending. Mining...");
    miner.start(mining_threads)
    while (eth.getBlock("latest").number < txBlock + 12) {
      if (eth.getBlock("pending").transactions.length > 0) txBlock = eth.getBlock("pending").number;
        }
    console.log("  12 confirmations achieved; mining stopped.");
    miner.stop()
}
else {
    miner.stop()
     }
}

eth.filter("latest", function(err, block) { checkWork(); });
eth.filter("pending", function(err, block) { checkWork(); });

checkWork();

This can also be saved as a .js script and preloaded using the --preload function when starting geth:

geth --preload "/path/to/mineWhenNeeded.js"
  • This answer can be improved by listing the source (the link to the other SE answer isn't the original source). – Jeffrey W. Apr 18 '16 at 8:34
  • @JeffreyW. feel free to edit and add source. – niksmac Apr 20 '16 at 0:48
  • to clear/stop auto-mining script checkWork=null – Subhod I Nov 15 '17 at 6:43

I was using @niksmac answer for mining until n confirmations are achieved but the while loop caused a very high CPU usage (above 110%). I changed it for an interval and now the CPU usage is below 5%. I check every 600ms, but any number that is < block time would work.

var minimum_confirmations = 3;
var mining_threads = 1
var txBlock = 0
function checkWork() {
    if (eth.getBlock("pending").transactions.length > 0) {
        txBlock = eth.getBlock("pending").number
        if (eth.mining) return;
        console.log("  Transactions pending. Mining...");
        miner.start(mining_threads)
        interval = setInterval(function () {
            if (eth.getBlock("latest").number < txBlock + minimum_confirmations) {
                if (eth.getBlock("pending").transactions.length > 0) txBlock = eth.getBlock("pending").number;
            } else {
                console.log(minimum_confirmations + " confirmations achieved; mining stopped.");
                miner.stop()
                clearInterval(interval);
            }
        }, 600)
    }
}

eth.filter("latest", function (err, block) { checkWork(); });
eth.filter("pending", function (err, block) { checkWork(); });

checkWork();
  • Can also do admin.sleep(1) to sleep for 1 second – rustyx Apr 8 at 20:05
  • @rustyx I will have to try that because my proposed solution sometimes does not work as expected. – facumedica Apr 9 at 18:57

If you're using geth POA, you can set block sealing period to 0 in genesis file, this will automatically force geth to only create new block whenever there is a transaction in network.

For 0-period chains, refuse to seal empty blocks

You may install eth-mine-when-need. Which starts a web3 client and listens for events. When there are pending transactions or transactions yet to be confirmed, it will start the miner until they are confirmed. It functions same as @niksmac 's answer. But, you don't have to execute the script every time you start eth and it allows you to specify the number of threads for mining and the number of blocks that is needed to say a transaction is confirmed by passing those values as arguments (for detail you can see the readme at npm).

In POA, In continuation to @jadd22 answer, during the truffle migrate we face the below issue.

https://github.com/trufflesuite/truffle/issues/853

To overcome this, we can run enough number dummy transactions asynchronously, {from:"0xAcc1",to:"0xAcc1",value:0} to ensure the deployment success.

After deployment all other operations are happening as required, i.e., mining happens only when there are pending transactions. No unnecessary empty block generation.

We can use " clique.period " inside genesis.json file to zero, as given below, to ensure mining only when ever required with out empty block generation. ( Only for POA )

clique": {
        "period": 0,
        "epoch": 30000
    }, 

Only we need to handle the truffle migration with some dummy transactions, Hope this is not required if the deployment of the contracts are done programatically using web3 and solc compilers.

  • Sorry @M.Gupal, on a second read I deleted the flag. – Paul Berg Nov 22 at 8:47

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.