diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -26,7 +26,6 @@ class CBlockIndex; -static const int64_t nClientStartupTime = GetTime(); static int64_t nLastHeaderTipUpdateNotification = 0; static int64_t nLastBlockTipUpdateNotification = 0; @@ -190,7 +189,7 @@ } QString ClientModel::formatClientStartupTime() const { - return QDateTime::fromTime_t(nClientStartupTime).toString(); + return QDateTime::fromTime_t(GetStartupTime()).toString(); } QString ClientModel::dataDir() const { diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -260,6 +260,22 @@ return "Bitcoin server stopping"; } +static UniValue uptime(const Config &config, + const JSONRPCRequest &jsonRequest) { + if (jsonRequest.fHelp || jsonRequest.params.size() > 1) { + throw std::runtime_error("uptime\n" + "\nReturns the total uptime of the server.\n" + "\nResult:\n" + "ttt (numeric) The number of seconds " + "that the server has been running\n" + "\nExamples:\n" + + HelpExampleCli("uptime", "") + + HelpExampleRpc("uptime", "")); + } + + return GetTime() - GetStartupTime(); +} + /** * Call Table */ @@ -270,6 +286,7 @@ /* Overall control/query calls */ { "control", "help", help, true, {"command"} }, { "control", "stop", stop, true, {} }, + { "control", "uptime", uptime, true, {} }, }; // clang-format on diff --git a/src/util.h b/src/util.h --- a/src/util.h +++ b/src/util.h @@ -5,7 +5,7 @@ /** * Server/client environment: argument handling, config file parsing, logging, - * thread wrappers. + * thread wrappers, startup time */ #ifndef BITCOIN_UTIL_H #define BITCOIN_UTIL_H @@ -30,6 +30,9 @@ #include #include +// Application startup time (used for uptime calculation) +int64_t GetStartupTime(); + static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; static const bool DEFAULT_LOGTIMESTAMPS = true; diff --git a/src/util.cpp b/src/util.cpp --- a/src/util.cpp +++ b/src/util.cpp @@ -87,6 +87,9 @@ #include #include +// Application startup time (used for uptime calculation) +const int64_t nStartupTime = GetTime(); + const char *const BITCOIN_CONF_FILENAME = "bitcoin.conf"; const char *const BITCOIN_PID_FILENAME = "bitcoind.pid"; @@ -865,3 +868,8 @@ } return strCopyrightHolders; } + +// Obtain the application startup time (used for uptime calculation) +int64_t GetStartupTime() { + return nStartupTime; +} diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -116,6 +116,7 @@ 'abc-rpc.py', 'mempool-accept-txn.py', 'wallet-encryption.py', + 'uptime.py', ] EXTENDED_SCRIPTS = [ diff --git a/test/functional/uptime.py b/test/functional/uptime.py new file mode 100755 --- /dev/null +++ b/test/functional/uptime.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test the RPC call related to the uptime command. + +Test corresponds to code in rpc/server.cpp. +""" + +import time + +from test_framework.test_framework import BitcoinTestFramework + + +class UptimeTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + + self.num_nodes = 1 + self.setup_clean_chain = True + + def run_test(self): + self._test_uptime() + + def _test_uptime(self): + wait_time = 10 + self.nodes[0].setmocktime(int(time.time() + wait_time)) + assert(self.nodes[0].uptime() >= wait_time) + + +if __name__ == '__main__': + UptimeTest().main()