From 34e5015cd21e27c1bf635d92531afac93f553096 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Sat, 21 Feb 2015 12:57:44 +0000 Subject: [PATCH] Add unit tests for next difficulty calculations Split GetNextWorkRequired() into two functions to allow the difficulty calculations to be tested without requiring a full blockchain. Add unit tests to cover basic difficulty calculation, plus each of the min/max actual time, and maximum difficulty target conditions. --- src/Makefile.test.include | 1 + src/pow.cpp | 7 ++++- src/pow.h | 1 + src/test/pow_tests.cpp | 66 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/test/pow_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 90494439f..6774745de 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -55,6 +55,7 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ + test/pow_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ test/script_P2SH_tests.cpp \ diff --git a/src/pow.cpp b/src/pow.cpp index 6dd5c4c12..b75b293c9 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -48,8 +48,13 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead pindexFirst = pindexFirst->pprev; assert(pindexFirst); + return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime()); +} + +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime) +{ // Limit adjustment step - int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); + int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); if (nActualTimespan < Params().TargetTimespan()/4) nActualTimespan = Params().TargetTimespan()/4; diff --git a/src/pow.h b/src/pow.h index 3337a30a5..a5fbba623 100644 --- a/src/pow.h +++ b/src/pow.h @@ -14,6 +14,7 @@ class uint256; class arith_uint256; unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits); diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp new file mode 100644 index 000000000..e42c1b0a8 --- /dev/null +++ b/src/test/pow_tests.cpp @@ -0,0 +1,66 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "main.h" +#include "pow.h" +#include "util.h" + +#include + +using namespace std; + +BOOST_AUTO_TEST_SUITE(pow_tests) + +/* Test calculation of next difficulty target with no constraints applying */ +BOOST_AUTO_TEST_CASE(get_next_work) +{ + SelectParams(CBaseChainParams::MAIN); + + int64_t nLastRetargetTime = 1261130161; // Block #30240 + CBlockIndex pindexLast; + pindexLast.nHeight = 32255; + pindexLast.nTime = 1262152739; // Block #32255 + pindexLast.nBits = 0x1d00ffff; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00d86a); +} + +/* Test the constraint on the upper bound for next work */ +BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) +{ + SelectParams(CBaseChainParams::MAIN); + + int64_t nLastRetargetTime = 1231006505; // Block #0 + CBlockIndex pindexLast; + pindexLast.nHeight = 2015; + pindexLast.nTime = 1233061996; // Block #2015 + pindexLast.nBits = 0x1d00ffff; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00ffff); +} + +/* Test the constraint on the lower bound for actual time taken */ +BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) +{ + SelectParams(CBaseChainParams::MAIN); + + int64_t nLastRetargetTime = 1279008237; // Block #66528 + CBlockIndex pindexLast; + pindexLast.nHeight = 68543; + pindexLast.nTime = 1279297671; // Block #68543 + pindexLast.nBits = 0x1c05a3f4; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1c0168fd); +} + +/* Test the constraint on the upper bound for actual time taken */ +BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) +{ + SelectParams(CBaseChainParams::MAIN); + int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time + CBlockIndex pindexLast; + pindexLast.nHeight = 46367; + pindexLast.nTime = 1269211443; // Block #46367 + pindexLast.nBits = 0x1c387f6f; + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00e1fd); +} + +BOOST_AUTO_TEST_SUITE_END()