Jack Grigg
7 years ago
10 changed files with 203 additions and 2 deletions
@ -0,0 +1,55 @@ |
|||
// Copyright (c) 2017 The Zcash developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "deprecation.h" |
|||
|
|||
#include "clientversion.h" |
|||
#include "init.h" |
|||
#include "ui_interface.h" |
|||
#include "util.h" |
|||
|
|||
static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); |
|||
|
|||
void EnforceNodeDeprecation(int nHeight, bool forceLogging) { |
|||
int blocksToDeprecation = DEPRECATION_HEIGHT - nHeight; |
|||
bool disableDeprecation = (GetArg("-disabledeprecation", "") == CLIENT_VERSION_STR); |
|||
if (blocksToDeprecation <= 0) { |
|||
// In order to ensure we only log once per process when deprecation is
|
|||
// disabled (to avoid log spam), we only need to log in two cases:
|
|||
// - The deprecating block just arrived
|
|||
// - This can be triggered more than once if a block chain reorg
|
|||
// occurs, but that's an irregular event that won't cause spam.
|
|||
// - The node is starting
|
|||
if (blocksToDeprecation == 0 || forceLogging) { |
|||
auto msg = strprintf(_("This version has been deprecated as of block height %d."), |
|||
DEPRECATION_HEIGHT) + " " + |
|||
_("You should upgrade to the latest version of Zcash."); |
|||
if (!disableDeprecation) { |
|||
msg += " " + strprintf(_("To disable deprecation for this version, set %s%s."), |
|||
"-disabledeprecation=", CLIENT_VERSION_STR); |
|||
} |
|||
LogPrintf("*** %s\n", msg); |
|||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR); |
|||
} |
|||
if (!disableDeprecation) { |
|||
StartShutdown(); |
|||
} |
|||
} else if (blocksToDeprecation == DEPRECATION_WARN_LIMIT || |
|||
(blocksToDeprecation < DEPRECATION_WARN_LIMIT && forceLogging)) { |
|||
std::string msg; |
|||
if (disableDeprecation) { |
|||
msg = strprintf(_("This version will be deprecated at block height %d."), |
|||
DEPRECATION_HEIGHT) + " " + |
|||
_("You should upgrade to the latest version of Zcash."); |
|||
} else { |
|||
msg = strprintf(_("This version will be deprecated at block height %d, and will automatically shut down."), |
|||
DEPRECATION_HEIGHT) + " " + |
|||
_("You should upgrade to the latest version of Zcash.") + " " + |
|||
strprintf(_("To disable deprecation for this version, set %s%s."), |
|||
"-disabledeprecation=", CLIENT_VERSION_STR); |
|||
} |
|||
LogPrintf("*** %s\n", msg); |
|||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_WARNING); |
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
// Copyright (c) 2017 The Zcash developers
|
|||
// Distributed under the MIT software license, see the accompanying
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifndef ZCASH_DEPRECATION_H |
|||
#define ZCASH_DEPRECATION_H |
|||
|
|||
// Deprecation policy is 4th third-Tuesday after a release
|
|||
static const int APPROX_RELEASE_HEIGHT = 115000; |
|||
static const int WEEKS_UNTIL_DEPRECATION = 18; |
|||
static const int DEPRECATION_HEIGHT = APPROX_RELEASE_HEIGHT + (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 24); |
|||
|
|||
// Number of blocks before deprecation to warn users
|
|||
static const int DEPRECATION_WARN_LIMIT = 14 * 24 * 24; // 2 weeks
|
|||
|
|||
/**
|
|||
* Checks whether the node is deprecated based on the current block height, and |
|||
* shuts down the node with an error if so (and deprecation is not disabled for |
|||
* the current client version). |
|||
*/ |
|||
void EnforceNodeDeprecation(int nHeight, bool forceLogging=false); |
|||
|
|||
#endif // ZCASH_DEPRECATION_H
|
@ -0,0 +1,105 @@ |
|||
#include <gmock/gmock.h> |
|||
#include <gtest/gtest.h> |
|||
|
|||
#include "clientversion.h" |
|||
#include "deprecation.h" |
|||
#include "init.h" |
|||
#include "ui_interface.h" |
|||
#include "util.h" |
|||
|
|||
using ::testing::StrictMock; |
|||
|
|||
static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); |
|||
extern std::atomic<bool> fRequestShutdown; |
|||
|
|||
class MockUIInterface { |
|||
public: |
|||
MOCK_METHOD3(ThreadSafeMessageBox, bool(const std::string& message, |
|||
const std::string& caption, |
|||
unsigned int style)); |
|||
}; |
|||
|
|||
static bool ThreadSafeMessageBox(MockUIInterface *mock, |
|||
const std::string& message, |
|||
const std::string& caption, |
|||
unsigned int style) |
|||
{ |
|||
mock->ThreadSafeMessageBox(message, caption, style); |
|||
} |
|||
|
|||
class DeprecationTest : public ::testing::Test { |
|||
protected: |
|||
virtual void SetUp() { |
|||
uiInterface.ThreadSafeMessageBox.disconnect_all_slots(); |
|||
uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, &mock_, _1, _2, _3)); |
|||
} |
|||
|
|||
virtual void TearDown() { |
|||
fRequestShutdown = false; |
|||
mapArgs["-disabledeprecation"] = ""; |
|||
} |
|||
|
|||
StrictMock<MockUIInterface> mock_; |
|||
}; |
|||
|
|||
TEST_F(DeprecationTest, NonDeprecatedNodeKeepsRunning) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT - DEPRECATION_WARN_LIMIT - 1); |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, NodeNearDeprecationIsWarned) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_WARNING)); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT - DEPRECATION_WARN_LIMIT); |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, NodeNearDeprecationWarningIsNotDuplicated) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT - DEPRECATION_WARN_LIMIT + 1); |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, NodeNearDeprecationWarningIsRepeatedOnStartup) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_WARNING)); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT - DEPRECATION_WARN_LIMIT + 1, true); |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, DeprecatedNodeShutsDown) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_ERROR)); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT); |
|||
EXPECT_TRUE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, DeprecatedNodeErrorIsNotDuplicated) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT + 1); |
|||
EXPECT_TRUE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, DeprecatedNodeErrorIsRepeatedOnStartup) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_ERROR)); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT + 1, true); |
|||
EXPECT_TRUE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, DeprecatedNodeShutsDownIfOldVersionDisabled) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
mapArgs["-disabledeprecation"] = "1.0.0"; |
|||
EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_ERROR)); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT); |
|||
EXPECT_TRUE(ShutdownRequested()); |
|||
} |
|||
|
|||
TEST_F(DeprecationTest, DeprecatedNodeKeepsRunningIfCurrentVersionDisabled) { |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
mapArgs["-disabledeprecation"] = CLIENT_VERSION_STR; |
|||
EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_ERROR)); |
|||
EnforceNodeDeprecation(DEPRECATION_HEIGHT); |
|||
EXPECT_FALSE(ShutdownRequested()); |
|||
} |
Loading…
Reference in new issue