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?
You can load this script to your geth console
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"
admin.sleep()
but this seems not to work. Mining is done instantly.
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.
geth
logs when transactions are pending.
Commented
Mar 6, 2019 at 12:28
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.
If you use PoW you can modify the Go code under
consensus/ethash/sealer.go
and add a condition to refuse seal if there are no transactions:
// Seal implements consensus.Engine, attempting to find a nonce that satisfies
// the block's difficulty requirements.
func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
.....
if len(block.Transactions()) == 0 {
log.Info("Sealing paused, waiting for transactions")
return nil, nil
}
.....
After that, run make geth
to regenerate the executables with the new code.
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();
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
).