0

I would like to know approximately how long it will take my geth node to complete syncing. There was a previous question that was similar to mine, but less specific, and it was closed in favor of a question about how to get the highest block number. Since it was not possible to add an answer to the closed question, and the other question does not answer my question, I am asking this version of the question.

2 Answers 2

1

You can enter the following code to estimate the time remaining in minutes. It samples the current block at two different times to estimate the time remaining. Note that if your current block doesn't change during this time, then it can't estimate it.

In geth console:

function printSyncForecast() {
    if (!eth.syncing) return "Your node isn't syncing."
    var sampleSeconds = 10
    var currentBlock = eth.syncing.currentBlock;
    admin.sleep(sampleSeconds);
    if (!eth.syncing) return "Your node stopped syncing."
    var blocksSynced = eth.syncing.currentBlock - currentBlock
    var blocksPerMinute = blocksSynced * 60 / sampleSeconds;
    if (blocksPerMinute === 0) return "Current block didn't change; try increasing the sample time";
    var blocksRemaining = eth.syncing.highestBlock - eth.syncing.currentBlock;
    var minutesRemaining = blocksRemaining / blocksPerMinute;
    return "node synced " + blocksSynced + " blocks in " + sampleSeconds + " seconds (" + blocksPerMinute + 
      " blocks/minute.)  If these 📈 continue, node will sync the remaining " + blocksRemaining + " blocks in " + 
      minutesRemaining + " minutes."
}
printSyncForecast()

Here's a one-liner from the command line using a minified version of that code:

geth attach --exec '(function(){if(!eth.syncing)return"Your node isnt syncing.";var n=eth.syncing.currentBlock;if(admin.sleep(10),!eth.syncing)return"Your node stopped syncing.";var e=eth.syncing.currentBlock-n,t=60*e/10;if(0===t)return"Current block didnt change; try increasing the sample time";var c=eth.syncing.highestBlock-eth.syncing.currentBlock;return"node synced "+e+" blocks in 10 seconds ("+t+" blocks/minute.)  If these 📈 continue, node will sync the remaining "+c+" blocks in "+c/t+" minutes."})()'
2
  • 2
    I realize it's an estimate, but I'm also not sure it's a particularly useful estimate, at least until you're almost done syncing. The reason for this is that different slices of time in the Ethereum blockchain's history yield very different block processing rates. Early blocks process very quickly because the chain can live in cache and there were few transactions. Fast forward to fall 2016. The state chain bloat attack slows down processing of blocks despite blocks not being full. Late 2017 results in slow processing due to heavy transactions (read: CryptoKitties). It works for you, great :)
    – lungj
    Mar 9, 2018 at 6:24
  • I updated the code to highlight that the forecast is speculative.
    – Carl G
    Mar 10, 2018 at 15:08
1

You might try pasting this in the geth console (geth attach http://localhost:8545 to open the console, or other URL depending on your config), noting to tweak the block production rate for your chain of interest. For example, on ethereum it becomes var networkBlocksPerSec = 1 / 13.2;. Note that other snippets floating around online do not account for the blocks the network will produce while you are syncing, so they are not giving an accurate estimate! This one does :)

(function () {

    var secPerSample = 10;
    var sampleWindow = 200;
    var networkBlocksPerSec = 1 / 2.3; // network block time (polygon makes a block every ~2 seconds)
    var decimals = 3;
    
    var dataPoints = [];
    
    var topBlock = eth.syncing.highestBlock;
    var curBlock = eth.syncing.currentBlock;

    
    function checkETA() {
        if (!eth || !eth.syncing) return 'Your node isn\'t syncing.';

        var blocksSynced = eth.syncing.currentBlock - curBlock;
    
        dataPoints.push(blocksSynced);
    
        console.log('\nMade it from block ' + curBlock + ' to block ' + eth.syncing.currentBlock + ' in the last ' + secPerSample + ' seconds (' + blocksSynced + ' blocks)');
    
        if (dataPoints.length > sampleWindow) {
            dataPoints.splice(0, dataPoints.length - sampleWindow); // keep only 100 data points
        }
    
        var avgBlocksPerWindow = 0;
        for (var i = 0; i < dataPoints.length; i++) {
            avgBlocksPerWindow += dataPoints[i];
        }
    
        avgBlocksPerWindow /= dataPoints.length;

        var avgBlocksPerSecond = avgBlocksPerWindow / secPerSample;
    
        console.log('Catching up ' + avgBlocksPerSecond.toFixed(decimals) + ' blocks/sec on average (' + avgBlocksPerWindow.toFixed(decimals) + ' blocks every ' + secPerSample + ' seconds, over last ' + dataPoints.length + ' samples)');
    

        topBlock = eth.syncing.highestBlock;
        curBlock = eth.syncing.currentBlock;

    
        var blocksRemaining = topBlock - curBlock;
        var secondsToReachTopBlock = blocksRemaining / avgBlocksPerSecond;
    
        console.log('With ' + blocksRemaining + ' blocks left to catch up on, getting to highest block known thus far (' + topBlock + ') should take ' + fancyTimeFormat(secondsToReachTopBlock, false));

        var effectiveCatchupRate = avgBlocksPerSecond - networkBlocksPerSec;

        console.log('Network also creates ' + networkBlocksPerSec.toFixed(decimals) + ' blocks/second, making our effective catchup rate ' + effectiveCatchupRate.toFixed(decimals) + ' blocks/sec');

        if (effectiveCatchupRate > 0) {
            var catchupSeconds = blocksRemaining / effectiveCatchupRate;
            var expectedCaughtUpBlock = topBlock + catchupSeconds * networkBlocksPerSec;
    
            console.log('Factoring in the rate of future block creation, we will be synced in ' + fancyTimeFormat(catchupSeconds, false) + ', at block #' + Math.ceil(expectedCaughtUpBlock));
        } else {
            console.log('At this rate, network is producing faster, so we will never catch up');
        }
    }


    function fancyTimeFormat(duration, withSeconds) {   // duration is in seconds
        var ret = ''; // Hours, minutes and seconds  
        var hrs = ~~(duration / 3600);  
    
        if (hrs > 0) ret += hrs + ' hrs ';
    
        ret += ~~((duration % 3600) / 60) + ' mins';

        if (withSeconds) ret += ' ' + (~~duration % 60) + ' secs';
        return ret;
    }
    
    
    var handle = setInterval(checkETA, secPerSample * 1000);

    function stop() {
        clearInterval(handle)
    }

    this.stopChecking = stop;
})()

To stop the function running on an interval, run stopChecking() in the geth console

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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