diff --git a/src/Makefile.test.include b/src/Makefile.test.include
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -40,6 +40,7 @@
   test/bswap_tests.cpp \
   test/cashaddr_tests.cpp \
   test/cashaddrenc_tests.cpp \
+  test/checkpoints_tests.cpp \
   test/coins_tests.cpp \
   test/compress_tests.cpp \
   test/config_tests.cpp \
diff --git a/src/checkpoints.h b/src/checkpoints.h
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -18,6 +18,9 @@
  */
 namespace Checkpoints {
 
+//! Returns true if block passes checkpoint checks
+bool CheckBlock(const CCheckpointData &data, int nHeight, const uint256 &hash);
+
 //! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
 CBlockIndex *GetLastCheckpoint(const CCheckpointData &data);
 
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -13,6 +13,16 @@
 
 namespace Checkpoints {
 
+bool CheckBlock(const CCheckpointData &data, int nHeight, const uint256 &hash) {
+    const MapCheckpoints &checkpoints = data.mapCheckpoints;
+
+    MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
+    if (i == checkpoints.end()) {
+        return true;
+    }
+    return hash == i->second;
+}
+
 CBlockIndex *GetLastCheckpoint(const CCheckpointData &data) {
     const MapCheckpoints &checkpoints = data.mapCheckpoints;
 
diff --git a/src/init.cpp b/src/init.cpp
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -647,8 +647,8 @@
             strprintf("Run checks every <n> transactions (default: %u)",
                       defaultChainParams->DefaultConsistencyChecks()));
         strUsage += HelpMessageOpt(
-            "-checkpoints", strprintf("Disable expensive verification for "
-                                      "known chain history (default: %d)",
+            "-checkpoints", strprintf("Only accept block chain matching "
+                                      "built-in checkpoints (default: %d)",
                                       DEFAULT_CHECKPOINTS_ENABLED));
         strUsage += HelpMessageOpt(
             "-disablesafemode", strprintf("Disable safemode, override a real "
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -66,6 +66,7 @@
 	bswap_tests.cpp
 	cashaddr_tests.cpp
 	cashaddrenc_tests.cpp
+	checkpoints_tests.cpp
 	coins_tests.cpp
 	compress_tests.cpp
 	config_tests.cpp
diff --git a/src/test/checkpoints_tests.cpp b/src/test/checkpoints_tests.cpp
new file mode 100644
--- /dev/null
+++ b/src/test/checkpoints_tests.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2018 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+//
+// Unit tests for block-chain checkpoints
+//
+
+#include "checkpoints.h"
+
+#include "chainparams.h"
+#include "test/test_bitcoin.h"
+#include "uint256.h"
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(checkpoints_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(sanity) {
+    const auto params = CreateChainParams(CBaseChainParams::MAIN);
+    const CCheckpointData &checkpoints = params->Checkpoints();
+    uint256 p11111 = uint256S(
+        "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d");
+    uint256 p134444 = uint256S(
+        "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe");
+    BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111));
+    BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444));
+
+    // Wrong hashes at checkpoints should fail:
+    BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 11111, p134444));
+    BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 134444, p11111));
+
+    // ... but any hash not at a checkpoint should succeed:
+    BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111 + 1, p134444));
+    BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444 + 1, p11111));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3543,11 +3543,20 @@
     }
 
     int nHeight = pindexPrev->nHeight + 1;
+    const CCheckpointData &checkpoints = chainparams.Checkpoints();
+
+    // Check that the block chain matches the known block chain up to a
+    // checkpoint.
+    if (!Checkpoints::CheckBlock(checkpoints, nHeight, hash)) {
+        return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d",
+                                    __func__, nHeight),
+                         REJECT_CHECKPOINT, "checkpoint mismatch");
+    }
+
     // Don't accept any forks from the main chain prior to last checkpoint.
     // GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in
     // our MapBlockIndex.
-    CBlockIndex *pcheckpoint =
-        Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
+    CBlockIndex *pcheckpoint = Checkpoints::GetLastCheckpoint(checkpoints);
     if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
         return state.DoS(
             100,