diff --git a/configure.ac b/configure.ac index e9a8fb2cdfa79..f313185636aac 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 14) -define(_CLIENT_VERSION_REVISION, 3) +define(_CLIENT_VERSION_REVISION, 4) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/doc/mip3.md b/doc/mip3.md new file mode 100644 index 0000000000000..681953e655db4 --- /dev/null +++ b/doc/mip3.md @@ -0,0 +1,56 @@ +MIP 3: Longblocks + +Status: Under development + + +Motivation + + +With the emergence of layer 2 solutions, the need for fast block confirmations +is lessened. Additionally, chainindex bloat is a significant issue to the +long-term health of Myriadcoin. + +This proposal implements a gradual increase in block time from 1 to 8 minutes +using multiple intervals of block time adjustments. + +Additional reasons for this change: + +* Capturing additional improvements from upstream indexing and development. +* Individual block security is improved due to the higher difficulty. +* Orphan count is expected to decrease. + + +Implementation + +In three phases this proposal plans an increase in block time while keeping +the reward amount essentially the same. In practice, this requires raising the +block reward at a scale proportional to the block time increase. Myriadcoin +would not see another block halving until the 6th block halving. Then block +halvings continue at the original schedule of ~2yrs. + +Below is an approximate table to show how this progresses. + +| Subsidy Halving Interval | Reward | Block Time | Final Blk | Aprox. Date | +| ------------------------ | ------- | ---------- | --------- | ----------- | +| 1 (967680 blocks) | 1000.0 | 0.5 min | 967680 | Feb 2015 | +| 2 (967680 blocks) | 500.0 | ~1 min | 1935360 | Jan 2017 | +| 3 (967680 blocks) | 250.0 | 1 min | 2903040 | ~May 2019 | +| 4 **(483840 blocks)** | 250.0 | **2 min** | 3386880 | ~May 2021 | +| 5 **(241920 blocks)** | 250.0 | **4 min** | 3628800 | ~May 2023 | +| 6 **(120960 blocks)** | 250.0 | **8 min** | 3749760 | ~May 2025 | +| 7 (120960 blocks) | 125.0 | 8 min | 3870720 | ~May 2027 | +| 8 (120960 blocks) | 62.5 | 8 min | 3991680 | ~May 2029 | +| ... (120960 blocks) | ... | 8 min | ... | ... | + +Halvings would then continue at 120960 block intervals. + +It should be noted that MAX_MONEY is not changed and emission rate vs. clock +time should not be affected. + +Deployment of this rule is through version bit 5. + + + +Reference implementation + +https://github.com/cryptapus/bitcoin/tree/myriadcoin.master.lngblcks/doc/mip3.md diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 408fa742cfc7b..e2dd66517f012 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -106,6 +106,17 @@ class CMainParams : public CChainParams { consensus.nGeoAvgWork_Start = 1400000; consensus.nFork1MinBlock = 1764000; // minimum block height where fork 1 takes effect (algo switch, seq algo count change) + // MIP3 parameters + consensus.nPowTargetSpacingV3a = 2 * 60; // new target time for block spacing across all algorithms (2min) + consensus.nPowTargetSpacingV3b = 4 * 60; // new target time for block spacing across all algorithms (4min) + consensus.nPowTargetSpacingV3c = 8 * 60; // new target time for block spacing across all algorithms (8min) + consensus.nLongblocks_StartV1a = 2903040; // Start of longblocks, original 3rd block halving + consensus.nLongblocks_StartV1b = 3386880; // Start of longblocks, original 4th block halving + consensus.nLongblocks_StartV1c = 3628800; // Start of longblocks, original 5th block halving + consensus.nSubsidyHalvingIntervalV2a = 483840; // Longblocks Subsidy halving after adjust block time (2min) + consensus.nSubsidyHalvingIntervalV2b = 241920; // Longblocks Subsidy halving after adjust block time (4min) + consensus.nSubsidyHalvingIntervalV2c = 120960; // Longblocks Subsidy halving after adjust block time (8min) + // Deployment of Legacy Blocks. Once activated, keeps v0.11 nodes on the same chain. Should be the first softfork. consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].nStartTime = 1507420800; // October 8th, 2017 @@ -116,9 +127,14 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_RESERVEALGO].nStartTime = 1516320000; // Jan 19th, 2018 consensus.vDeployments[Consensus::DEPLOYMENT_RESERVEALGO].nTimeout = 1548979200; // Feb 1st, 2019 + // Deployment of MIP3 (longblocks) + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].bit = 5; + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].nStartTime = 1525132800; // May 1st, 2018 + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].nTimeout = 1556668800; // May 1st, 2019 + /*** Upstream Chainparams ***/ - consensus.nSubsidyHalvingInterval = 80640 * 12; + consensus.nSubsidyHalvingInterval = 967680; consensus.BIP34Height = 1; consensus.BIP34Hash = uint256S("0xcb41589c918fba1beccca8bc6b34b2b928b4f9888595d7664afd6ec60a576291"); consensus.BIP65Height = 1764000; // 2ca9968704301897b956f7e326375413be505509489c06aee2b16fe73805481e @@ -272,6 +288,17 @@ class CTestNetParams : public CChainParams { consensus.nGeoAvgWork_Start = 150; consensus.nFork1MinBlock = 601; // minimum block height where fork 1 takes effect (algo switch, seq algo count change) + // MIP3 parameters + consensus.nPowTargetSpacingV3a = 2 * 60; // new target time for block spacing across all algorithms (2min) + consensus.nPowTargetSpacingV3b = 4 * 60; // new target time for block spacing across all algorithms (4min) + consensus.nPowTargetSpacingV3c = 8 * 60; // new target time for block spacing across all algorithms (8min) + consensus.nLongblocks_StartV1a = 2903040; // Start of longblocks, original 3rd block halving + consensus.nLongblocks_StartV1b = 3386880; // Start of longblocks, original 4th block halving + consensus.nLongblocks_StartV1c = 3628800; // Start of longblocks, original 5th block halving + consensus.nSubsidyHalvingIntervalV2a = 483840; // Longblocks Subsidy halving after adjust block time (2min) + consensus.nSubsidyHalvingIntervalV2b = 241920; // Longblocks Subsidy halving after adjust block time (4min) + consensus.nSubsidyHalvingIntervalV2c = 120960; // Longblocks Subsidy halving after adjust block time (8min) + // Deployment of Legacy Blocks. Once activated, keeps v0.11 nodes on the same chain. Should be the first softfork. consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].nStartTime = 1504224000; // September 1st, 2017 @@ -281,9 +308,14 @@ class CTestNetParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_RESERVEALGO].nStartTime = 1516320000; // Jan 19th, 2018 consensus.vDeployments[Consensus::DEPLOYMENT_RESERVEALGO].nTimeout = 1548979200; // Feb 1st, 2019 + // Deployment of MIP3 (longblocks) + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].bit = 5; + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].nStartTime = 1525132800; // May 1st, 2018 + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].nTimeout = 1556668800; // May 1st, 2019 + /*** Upstream Chainparams ***/ - consensus.nSubsidyHalvingInterval = 80640 * 12; + consensus.nSubsidyHalvingInterval = 967680; consensus.BIP34Height = 1; consensus.BIP34Hash = uint256S("0x0000d23adc28e33bc05f4bee57c873ae0aab584a6a436e75ac0ed40396f6d86b"); consensus.BIP65Height = 641; // ff983c72147a81ac5b8ebfc68b62b39358cac4b8eb5518242e87f499b71c6a51 @@ -406,6 +438,17 @@ class CRegTestParams : public CChainParams { consensus.nGeoAvgWork_Start = 0; consensus.nFork1MinBlock = 601; // minimum block height where fork 1 takes effect (algo switch, seq algo count change) + // MIP3 parameters + consensus.nPowTargetSpacingV3a = 2 * 60; // new target time for block spacing across all algorithms (2min) + consensus.nPowTargetSpacingV3b = 4 * 60; // new target time for block spacing across all algorithms (4min) + consensus.nPowTargetSpacingV3c = 8 * 60; // new target time for block spacing across all algorithms (8min) + consensus.nLongblocks_StartV1a = 450; // Start of longblocks, original 3rd block halving + consensus.nLongblocks_StartV1b = 525; // Start of longblocks, original 4th block halving + consensus.nLongblocks_StartV1c = 562; // Start of longblocks, original 5th block halving + consensus.nSubsidyHalvingIntervalV2a = 75; // Longblocks Subsidy halving after adjust block time (2min) + consensus.nSubsidyHalvingIntervalV2b = 37; // Longblocks Subsidy halving after adjust block time (4min) + consensus.nSubsidyHalvingIntervalV2c = 18; // Longblocks Subsidy halving after adjust block time (8min) + consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].bit = 2; consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_LEGBIT].nTimeout = 999999999999ULL; @@ -415,6 +458,11 @@ class CRegTestParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_RESERVEALGO].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_RESERVEALGO].nTimeout = 999999999999ULL; + // Deployment of MIP3 (longblocks) + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].bit = 5; + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].nStartTime = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_LONGBLOCKS].nTimeout = 999999999999ULL; + /*** Upstream Chainparams ***/ consensus.nSubsidyHalvingInterval = 150; diff --git a/src/clientversion.h b/src/clientversion.h index 0e0fdec28751a..fc1741f0f3267 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,7 +16,7 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 14 -#define CLIENT_VERSION_REVISION 3 +#define CLIENT_VERSION_REVISION 4 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build diff --git a/src/consensus/params.h b/src/consensus/params.h index 6cfeb4df33268..27bd115b9f836 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -19,6 +19,7 @@ enum DeploymentPos DEPLOYMENT_SEGWIT, // Deployment of BIP141, BIP143, and BIP147. DEPLOYMENT_LEGBIT, // Deployment of Legacy Bits. DEPLOYMENT_RESERVEALGO, // Deployment of MIP2 (Reserve algos) + DEPLOYMENT_LONGBLOCKS, // Deployment of MIP3 (longblocks) // NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp MAX_VERSION_BITS_DEPLOYMENTS }; @@ -89,6 +90,15 @@ struct Params { int64_t nBlockAlgoNormalisedWorkDecayStart2; int64_t nGeoAvgWork_Start; int64_t nFork1MinBlock; + int64_t nPowTargetSpacingV3a; + int64_t nPowTargetSpacingV3b; + int64_t nPowTargetSpacingV3c; + int64_t nLongblocks_StartV1a; + int64_t nLongblocks_StartV1b; + int64_t nLongblocks_StartV1c; + int nSubsidyHalvingIntervalV2a; + int nSubsidyHalvingIntervalV2b; + int nSubsidyHalvingIntervalV2c; /** Auxpow parameters */ int16_t nAuxpowChainId; diff --git a/src/miner.cpp b/src/miner.cpp index 0156399abeb02..11686442ae6f8 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -197,7 +197,9 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc coinbaseTx.vin[0].prevout.SetNull(); coinbaseTx.vout.resize(1); coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn; - coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); + // TODO Myriadcoin LONGBLOCKS: GetBlockSubsidy needs pindexPrev. Remove after activation. + //coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); + coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus(), pindexPrev); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx)); pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus()); diff --git a/src/pow.cpp b/src/pow.cpp index e361fd4fd7b70..5beabeeaf1fa3 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -11,6 +11,7 @@ #include "primitives/block.h" #include "uint256.h" #include "util.h" +#include "validation.h" // TODO Myriadcoin LONGBLOCKS: needed for versionbitscache, remove after activation. #include "bignum.h" unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, int algo, const Consensus::Params& params) @@ -158,7 +159,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead if (pindexLast->nHeight >= params.Phase2Timespan_Start) { - return CalculateNextWorkRequiredV2(pindexPrev, pindexFirst, params, algo, nActualTimespan); + return CalculateNextWorkRequiredV2(pindexPrev, pindexFirst, params, algo, nActualTimespan, pindexLast->nHeight); } else { @@ -222,7 +223,7 @@ unsigned int CalculateNextWorkRequiredV1(const CBlockIndex* pindexPrev, const CB } -unsigned int CalculateNextWorkRequiredV2(const CBlockIndex* pindexPrev, const CBlockIndex* pindexFirst, const Consensus::Params& params, int algo, int64_t nActualTimespan) +unsigned int CalculateNextWorkRequiredV2(const CBlockIndex* pindexPrev, const CBlockIndex* pindexFirst, const Consensus::Params& params, int algo, int64_t nActualTimespan, int nHeight) { if (params.fPowNoRetargeting) return pindexPrev->nBits; @@ -230,7 +231,21 @@ unsigned int CalculateNextWorkRequiredV2(const CBlockIndex* pindexPrev, const CB const arith_uint256 nProofOfWorkLimit = UintToArith256(params.powLimit); int64_t nTargetSpacingPerAlgo = params.nPowTargetSpacingV2 * NUM_ALGOS; // 60 * 5 = 300s per algo - int64_t nAveragingTargetTimespan = params.nAveragingInterval * nTargetSpacingPerAlgo; // 10 * 300 = 3000s, 50 minutes + std::string sBlockTime = "V2"; + // TODO Myriadcoin LONGBLOCKS: remove VersionBitsState check post activation. + if (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_LONGBLOCKS, versionbitscache) == THRESHOLD_ACTIVE) { + if (nHeight >= params.nLongblocks_StartV1c) { + nTargetSpacingPerAlgo = params.nPowTargetSpacingV3c * NUM_ALGOS; // 8 * 60 * 5 = 2400s per algo + sBlockTime = "V2_longblocks_8min"; + } else if (nHeight >= params.nLongblocks_StartV1b) { + nTargetSpacingPerAlgo = params.nPowTargetSpacingV3b * NUM_ALGOS; // 4 * 60 * 5 = 1200s per algo + sBlockTime = "V2_longblocks_4min"; + } else if (nHeight >= params.nLongblocks_StartV1a) { + nTargetSpacingPerAlgo = params.nPowTargetSpacingV3a * NUM_ALGOS; // 2 * 60 * 5 = 600s per algo + sBlockTime = "V2_longblocks_2min"; + } + } + int64_t nAveragingTargetTimespan = params.nAveragingInterval * nTargetSpacingPerAlgo; // 10 blocks per algo int64_t nMinActualTimespan = nAveragingTargetTimespan * (100 - params.nMaxAdjustUpV2) / 100; int64_t nMaxActualTimespan = nAveragingTargetTimespan * (100 + params.nMaxAdjustDown) / 100; @@ -256,10 +271,10 @@ unsigned int CalculateNextWorkRequiredV2(const CBlockIndex* pindexPrev, const CB /// debug print if(fDebug) { - LogPrintf("CalculateNextWorkRequiredV2(Algo=%d): RETARGET\n", algo); - LogPrintf("CalculateNextWorkRequiredV2(Algo=%d): nTargetTimespan = %d nActualTimespan = %d\n", algo, nAveragingTargetTimespan, nActualTimespan); - LogPrintf("CalculateNextWorkRequiredV2(Algo=%d): Before: %08x %s\n", algo, pindexPrev->nBits, bnOld.ToString()); - LogPrintf("CalculateNextWorkRequiredV2(Algo=%d): After: %08x %s\n", algo, bnNew.GetCompact(), bnNew.ToString()); + LogPrintf("CalculateNextWorkRequired%s(Algo=%d): RETARGET\n", sBlockTime, algo); + LogPrintf("CalculateNextWorkRequired%s(Algo=%d): nTargetTimespan = %d nActualTimespan = %d\n", sBlockTime, algo, nAveragingTargetTimespan, nActualTimespan); + LogPrintf("CalculateNextWorkRequired%s(Algo=%d): Before: %08x %s\n", sBlockTime, algo, pindexPrev->nBits, bnOld.ToString()); + LogPrintf("CalculateNextWorkRequired%s(Algo=%d): After: %08x %s\n", sBlockTime, algo, bnNew.GetCompact(), bnNew.ToString()); } return bnNew.GetCompact(); diff --git a/src/pow.h b/src/pow.h index 0639cac9cc911..0aaf47835e1a0 100644 --- a/src/pow.h +++ b/src/pow.h @@ -16,7 +16,7 @@ class uint256; unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, int algo, const Consensus::Params&); unsigned int CalculateNextWorkRequiredV1(const CBlockIndex* pindexPrev, const CBlockIndex* pindexFirst, const Consensus::Params& params, int algo, int64_t nActualTimespan, int nHeight); -unsigned int CalculateNextWorkRequiredV2(const CBlockIndex* pindexPrev, const CBlockIndex* pindexFirst, const Consensus::Params& params, int algo, int64_t nActualTimespan); +unsigned int CalculateNextWorkRequiredV2(const CBlockIndex* pindexPrev, const CBlockIndex* pindexFirst, const Consensus::Params& params, int algo, int64_t nActualTimespan, int nHeight); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, int algo, unsigned int nBits, const Consensus::Params&); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 182e751e5dd93..5962cfc01d10f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1230,6 +1230,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT); BIP9SoftForkDescPushBack(bip9_softforks, "legbit", consensusParams, Consensus::DEPLOYMENT_LEGBIT); BIP9SoftForkDescPushBack(bip9_softforks, "reservealgo", consensusParams, Consensus::DEPLOYMENT_RESERVEALGO); + BIP9SoftForkDescPushBack(bip9_softforks, "longblocks", consensusParams, Consensus::DEPLOYMENT_LONGBLOCKS); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 56c4680936977..d7157fdd6471e 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -22,11 +22,33 @@ static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0 BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2); for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) { - int nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval; + // Myriadcoin: nSubsidyHalvingInterval has been altered in 3 stages for MIP3-longblocks + //int nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval; + int nHeight = 0; + if (nHalvings<=3) { + nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval; + } else if (nHalvings==4) { + nHeight = 3 * consensusParams.nSubsidyHalvingInterval; + nHeight += consensusParams.nSubsidyHalvingIntervalV2a; + } else if (nHalvings==5) { + nHeight = 3 * consensusParams.nSubsidyHalvingInterval; + nHeight += consensusParams.nSubsidyHalvingIntervalV2a; + nHeight += consensusParams.nSubsidyHalvingIntervalV2b; + } else if (nHalvings>=6) { + nHeight = 3 * consensusParams.nSubsidyHalvingInterval; + nHeight += consensusParams.nSubsidyHalvingIntervalV2a; + nHeight += consensusParams.nSubsidyHalvingIntervalV2b; + nHeight += (nHalvings - 5) * consensusParams.nSubsidyHalvingIntervalV2c; + } CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); BOOST_CHECK(nSubsidy <= nInitialSubsidy); - if (nHalvings < 10) { - BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2); + if (nHalvings < 13) { + // Myriadcoin: nSubidy is held for block halvings 3-5 and block time increased for MIP3-longblocks + //BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2); + if (nHalvings==3 || nHalvings==4 || nHalvings==5) + BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy); + else + BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2); } else { BOOST_CHECK_EQUAL(nSubsidy, nFinalSubsidy); } @@ -35,31 +57,37 @@ static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) BOOST_CHECK_EQUAL(GetBlockSubsidy(maxHalvings * consensusParams.nSubsidyHalvingInterval, consensusParams), nFinalSubsidy); } +/* Myriadcoin: we don't test other intervals due to MIP3-longblocks static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval) { Consensus::Params consensusParams; consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval; TestBlockSubsidyHalvings(consensusParams); } +*/ BOOST_AUTO_TEST_CASE(block_subsidy_test) { TestBlockSubsidyHalvings(Params(CBaseChainParams::MAIN).GetConsensus()); // As in main - TestBlockSubsidyHalvings(150); // As in regtest - TestBlockSubsidyHalvings(1000); // Just another interval + TestBlockSubsidyHalvings(Params(CBaseChainParams::TESTNET).GetConsensus()); // As in testnet + TestBlockSubsidyHalvings(Params(CBaseChainParams::REGTEST).GetConsensus()); // As in regtest + // Myriadcoin: we don't test other intervals due to MIP3-longblocks + //TestBlockSubsidyHalvings(150); // As in regtest + //TestBlockSubsidyHalvings(1000); // Just another interval } BOOST_AUTO_TEST_CASE(subsidy_limit_test) { const Consensus::Params& consensusParams = Params(CBaseChainParams::MAIN).GetConsensus(); CAmount nSum = 0; - for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) { + // Myriadcoin: step must be integer factor of our MIP3 120960 halving intervals, all interval steps are divisible by 945 + for (int nHeight = 0; nHeight < 14000000; nHeight += 945) { CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); BOOST_CHECK(nSubsidy <= 1000 * COIN); - nSum += nSubsidy * 1000; + nSum += nSubsidy * 945; BOOST_CHECK(MoneyRange(nSum)); } - BOOST_CHECK_EQUAL(nSum, 193828979687500000ULL); + BOOST_CHECK_EQUAL(nSum, 194452744500000000ULL); } bool ReturnFalse() { return false; } diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 983abc628ce5a..8a6eeb215b9e9 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -30,7 +30,28 @@ BOOST_AUTO_TEST_CASE(get_next_work) pindexLast.nTime = 1420071000; // Block #(not real) pindexLast.nBits = 0x1d00ffff; BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV1(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d00f5c1); - BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan), 0x1d00f5c1); + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d00f5c1); + // Check MIP3-longblocks intervals + nActualTimespan = 3010; // Target is 3000s + pindexFirst.nHeight = 2903020; // nPowTargetSpacingV2 + pindexLast.nHeight = 2903030; + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d0100d9); + nActualTimespan = 6050; // Target is 6000s + pindexFirst.nHeight = 2903040; // nPowTargetSpacingV3a + pindexLast.nHeight = 2903050; + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d010221); + nActualTimespan = 12020; // Target is 12000s + pindexFirst.nHeight = 3386880; // nPowTargetSpacingV3b + pindexLast.nHeight = 3386890; + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d01006c); + nActualTimespan = 24070; // Target is 24000s + pindexFirst.nHeight = 3628800; // nPowTargetSpacingV3c + pindexLast.nHeight = 3628810; + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d0100be); + nActualTimespan = 24100; // Target is 24000s + pindexFirst.nHeight = 3749760; // nPowTargetSpacingV3c + pindexLast.nHeight = 3749770; + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d010110); } /* Test the constraint on the upper bound for next work */ @@ -50,7 +71,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) pindexLast.nTime = 1420076400; // Block #(not real) pindexLast.nBits = 0x1d00ffff; BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV1(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d010a3c); - BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan), 0x1d010a3c); + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d010a3c); } /* Test the constraint on the lower bound for actual time taken */ @@ -70,7 +91,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) pindexLast.nTime = 1420070410; // Block #(not real) pindexLast.nBits = 0x1d00ffff; BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV1(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d00f5c1); - BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan), 0x1d00f5c1); + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d00f5c1); } /* Test the constraint on the upper bound for actual time taken */ @@ -90,7 +111,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) pindexLast.nTime = 1421193600; // Block #(not real) pindexLast.nBits = 0x1d00ffff; BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV1(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d010a3c); - BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan), 0x1d010a3c); + BOOST_CHECK_EQUAL(CalculateNextWorkRequiredV2(&pindexLast, &pindexFirst, params, algo, nActualTimespan, pindexLast.nHeight+1), 0x1d010a3c); } BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) diff --git a/src/validation.cpp b/src/validation.cpp index 6994b95a1e6e9..9287b7fe3fb71 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1238,14 +1238,42 @@ bool ReadBlockHeaderFromDisk(CBlockHeader& block, const CBlockIndex* pindex, con return ReadBlockOrHeader(block, pindex, consensusParams); } -CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) +// TODO Myriadcoin LONGBLOCKS: remove pindex arg and VersionBitsState check post activation +//CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) +CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, const CBlockIndex* pindex) { int halvings = nHeight / consensusParams.nSubsidyHalvingInterval; - // Force block reward to 1 after 10 halvings (tail emission). - if (halvings >= 10) - return 1 * COIN; + if (VersionBitsState(pindex, consensusParams, Consensus::DEPLOYMENT_LONGBLOCKS, versionbitscache) == THRESHOLD_ACTIVE) { + if (nHeight >= consensusParams.nLongblocks_StartV1a) { + halvings = consensusParams.nLongblocks_StartV1a / consensusParams.nSubsidyHalvingInterval; + } + if (nHeight >= consensusParams.nLongblocks_StartV1b) { + halvings += 1; + } + if (nHeight >= consensusParams.nLongblocks_StartV1c) { + halvings += 1; + halvings += ( nHeight - consensusParams.nLongblocks_StartV1c ) / consensusParams.nSubsidyHalvingIntervalV2c; + } + // Force block reward to 1 after 10 halvings (tail emission). + if (halvings >= 13) // tail emission happens later with longblocks. + return 1 * COIN; + } else { + // Force block reward to 1 after 10 halvings (tail emission). + if (halvings >= 10) + return 1 * COIN; + } CAmount nSubsidy = 1000 * COIN; + if (VersionBitsState(pindex, consensusParams, Consensus::DEPLOYMENT_LONGBLOCKS, versionbitscache) == THRESHOLD_ACTIVE) { + // longblocks require larger reward scaled for time. + if (nHeight >= consensusParams.nLongblocks_StartV1c) { + nSubsidy *= 8; // 1min -> 8min + } else if (nHeight >= consensusParams.nLongblocks_StartV1b) { + nSubsidy *= 4; // 1min -> 4min + } else if (nHeight >= consensusParams.nLongblocks_StartV1a) { + nSubsidy *= 2; // 1min -> 2min + } + } // Subsidy is cut in half every 967680 blocks. nSubsidy >>= halvings; return nSubsidy; @@ -1776,6 +1804,11 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para if (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_LEGBIT, versionbitscache) == THRESHOLD_ACTIVE) { nVersion += 4; } + /* TODO Myriadcoin LONGBLOCKS: remove legbit if LONGBLOCKS activates, now 0.11 clients are forked off network, + remove this and above legbit check once LONGBLOCKS is activated */ + if (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_LONGBLOCKS, versionbitscache) == THRESHOLD_ACTIVE) { + nVersion -= 4; + } return nVersion; } @@ -2012,7 +2045,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001); - CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()); + // TODO Myriadcoin LONGBLOCKS: pindex needed for versionbits check. Remove if activated. + //CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()); + CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus(), pindex); if (block.vtx[0]->GetValueOut() > blockReward) return state.DoS(100, error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", diff --git a/src/validation.h b/src/validation.h index c44f1a4d5c3e8..3cca3652f329a 100644 --- a/src/validation.h +++ b/src/validation.h @@ -287,7 +287,9 @@ std::string GetWarnings(const std::string& strFor); bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr pblock = std::shared_ptr()); -CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); +// TODO Myriadcoin LONGBLOCKS: remove pindex if activated. +//CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); +CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, const CBlockIndex* pindex = nullptr); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */ double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex); diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 7b7a92e3a64d6..f9be4ce95a473 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -26,6 +26,10 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION { /*.name =*/ "reservealgo", /*.gbt_force =*/ true, + }, + { + /*.name =*/ "longblocks", + /*.gbt_force =*/ true, } };