diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/chainparams.cpp | 29 | ||||
| -rw-r--r-- | src/consensus/params.h | 1 | ||||
| -rw-r--r-- | src/dogecoin.cpp | 43 | ||||
| -rw-r--r-- | src/dogecoin.h | 3 | ||||
| -rw-r--r-- | src/miner.cpp | 3 | ||||
| -rw-r--r-- | src/qt/test/rpcnestedtests.cpp | 2 | ||||
| -rw-r--r-- | src/rpc/blockchain.cpp | 3 | ||||
| -rw-r--r-- | src/test/blockfilter_index_tests.cpp | 8 | ||||
| -rw-r--r-- | src/test/dogecoin_tests.cpp | 55 | ||||
| -rw-r--r-- | src/test/validation_block_tests.cpp | 5 | ||||
| -rw-r--r-- | src/test/validation_tests.cpp | 4 | ||||
| -rw-r--r-- | src/validation.cpp | 3 | ||||
| -rw-r--r-- | src/wallet/test/wallet_tests.cpp | 6 |
13 files changed, 144 insertions, 21 deletions
diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ac5ff10cc..f6b8324a6 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -66,7 +66,7 @@ public: strNetworkID = CBaseChainParams::MAIN; consensus.signet_blocks = false; consensus.signet_challenge.clear(); - consensus.nSubsidyHalvingInterval = 210000; + consensus.nSubsidyHalvingInterval = 100000; consensus.BIP16Exception = uint256(); // BIP34 is never enforced in Dogecoin v2 blocks, so we enforce from v3 consensus.BIP34Height = 1034383; @@ -96,6 +96,7 @@ public: consensus.defaultAssumeValid = uint256S("0x014c0753de886b81dffa11e99f37416930b67d55bda17589d886aeb053414942"); // 3,692,828 consensus.nAssumeValidMinTime = 60 * 60 * 24 * 7 * 2; + consensus.fSimplifiedRewards = false; consensus.fShortEarlyCoinbase = true; /** @@ -112,10 +113,10 @@ public: m_assumed_blockchain_size = 350; m_assumed_chain_state_size = 6; - genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1386325540, 1930484355, 0x1d00ffff, 1, 88 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); + assert(consensus.hashGenesisBlock == uint256S("0x000000007610a818e726d4f943b5936e750de86c142a5f59606456c945350ec3")); + assert(genesis.hashMerkleRoot == uint256S("0x13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df")); // Note that of those which support the service bits prefix, most only support a subset of // possible options. @@ -189,7 +190,7 @@ public: strNetworkID = CBaseChainParams::TESTNET; consensus.signet_blocks = false; consensus.signet_challenge.clear(); - consensus.nSubsidyHalvingInterval = 210000; + consensus.nSubsidyHalvingInterval = 100000; consensus.BIP16Exception = uint256(); // BIP34 is never enforced in Dogecoin v2 blocks, so we enforce from v3 consensus.BIP34Height = 708658; @@ -219,6 +220,7 @@ public: consensus.defaultAssumeValid = uint256S("0x1f19a9290d1f83a59bd8e05c5b1216dca14fc580fe548f64150575cad98d4714"); // 3149245 consensus.nAssumeValidMinTime = 60 * 60 * 24 * 7 * 2; + consensus.fSimplifiedRewards = false; consensus.fShortEarlyCoinbase = true; pchMessageStart[0] = 0xfc; @@ -230,10 +232,11 @@ public: m_assumed_blockchain_size = 40; m_assumed_chain_state_size = 2; - genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN); + // Dogecoin: Note timestamp is tweaked for SHA256 interim mining, will need correcting for Scrypt + genesis = CreateGenesisBlock(1391503288, 1182687315, 0x1d00ffff, 1, 88 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); + assert(consensus.hashGenesisBlock == uint256S("0x00000000543fd974f37140a6192f890d744f220bd82ae428dbe684c7588347ad")); + assert(genesis.hashMerkleRoot == uint256S("0x13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df")); vFixedSeeds.clear(); vSeeds.clear(); @@ -337,7 +340,7 @@ public: strNetworkID = CBaseChainParams::SIGNET; consensus.signet_blocks = true; consensus.signet_challenge.assign(bin.begin(), bin.end()); - consensus.nSubsidyHalvingInterval = 210000; + consensus.nSubsidyHalvingInterval = 100000; consensus.BIP16Exception = uint256{}; consensus.BIP34Height = 1; consensus.BIP34Hash = uint256{}; @@ -363,6 +366,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + consensus.fSimplifiedRewards = true; consensus.fShortEarlyCoinbase = true; // message start is defined as the first 4 bytes of the sha256d of the block script @@ -434,6 +438,7 @@ public: consensus.defaultAssumeValid = uint256{}; consensus.nAssumeValidMinTime = 60 * 60 * 24 * 7 * 2 / 10; // One tenth of main/test networks + consensus.fSimplifiedRewards = true; consensus.fShortEarlyCoinbase = false; pchMessageStart[0] = 0xfa; @@ -447,10 +452,10 @@ public: UpdateActivationParametersFromArgs(args); - genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 88 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); + assert(consensus.hashGenesisBlock == uint256S("0x4ebcb24a7efa4e2050e74d6c95f1ee318ed2b4df2b6f28b0d6b8318cb43762e8")); + assert(genesis.hashMerkleRoot == uint256S("0x13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df")); vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. diff --git a/src/consensus/params.h b/src/consensus/params.h index 370712d4d..b7223b2fc 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -93,6 +93,7 @@ struct Params { bool signet_blocks{false}; std::vector<uint8_t> signet_challenge; + bool fSimplifiedRewards; bool fShortEarlyCoinbase; }; } // namespace Consensus diff --git a/src/dogecoin.cpp b/src/dogecoin.cpp index 7af47d5d4..31cd69bfc 100644 --- a/src/dogecoin.cpp +++ b/src/dogecoin.cpp @@ -2,10 +2,53 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <boost/random/mersenne_twister.hpp> +#include <boost/random/uniform_int.hpp> + #include <arith_uint256.h> #include <dogecoin.h> #include <logging.h> +int static generateMTRandom(unsigned int s, int range) +{ + boost::mt19937 gen(s); + boost::uniform_int<> dist(1, range); + return dist(gen); +} + +CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, uint256 prevHash) +{ + int halvings = nHeight / consensusParams.nSubsidyHalvingInterval; + + if (nHeight < 145000 && !consensusParams.fSimplifiedRewards) + { + // Old-style rewards derived from the previous block hash + + // This extracts 7*4 bits out of the middle of the previous block hash to use as a seed. + // It's longer than the 1.14 code, but avoids the locale-sensitive strtol() function. + const int bitsPerNibble = 4; + const int totalNibbles = 256 / bitsPerNibble; + const int nibblesToClear = 7; + const int nibblesToKeep = 7; + arith_uint256 upperBits = UintToArith256(prevHash) << (nibblesToClear * bitsPerNibble); + arith_uint256 cleanedBits = upperBits >> ((totalNibbles - nibblesToKeep) * bitsPerNibble); + uint64_t seed = ArithToUint256(cleanedBits).GetUint64(0); + + // Convert the seed into a subsidy value. + CAmount maxReward = (1000000 >> halvings) - 1; + int rand = generateMTRandom(seed, maxReward); + + return (1 + rand) * COIN; + } else if (nHeight < (6 * consensusParams.nSubsidyHalvingInterval)) { + // New-style constant rewards for each halving interval + return (500000 * COIN) >> halvings; + } else { + // Constant inflation + return 10000 * COIN; + } +} + + // Dogecoin: Normally minimum difficulty blocks can only occur in between // retarget blocks. However, once we introduce Digishield every block is // a retarget, so we need to handle minimum difficulty on all blocks. diff --git a/src/dogecoin.h b/src/dogecoin.h index 134caa629..4ff44998e 100644 --- a/src/dogecoin.h +++ b/src/dogecoin.h @@ -5,10 +5,13 @@ #ifndef BITCOIN_DOGECOIN_H #define BITCOIN_DOGECOIN_H +#include <amount.h> #include <chain.h> #include <chainparams.h> +#include <uint256.h> bool AllowDigishieldMinDifficultyForBlock(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params); unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params); +CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, uint256 prevHash); #endif // BITCOIN_DOGECOIN_H diff --git a/src/miner.cpp b/src/miner.cpp index 41a835f70..b44cb947d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -13,6 +13,7 @@ #include <consensus/merkle.h> #include <consensus/tx_verify.h> #include <consensus/validation.h> +#include <dogecoin.h> #include <policy/feerate.h> #include <policy/policy.h> #include <pow.h> @@ -160,7 +161,7 @@ std::unique_ptr<CBlockTemplate> 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()); + coinbaseTx.vout[0].nValue = nFees + GetDogecoinBlockSubsidy(nHeight, chainparams.GetConsensus(), pindexPrev->GetBlockHash()); 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/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index de1fbcb94..a82adc251 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -69,7 +69,7 @@ void RPCNestedTests::rpcNestedTests() QVERIFY(result == result2); RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())[tx][0]", &filtered); - QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + QVERIFY(result == "13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df"); QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]"); RPCConsole::RPCParseCommandLine(nullptr, result, "importprivkey", false, &filtered); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 392073d04..b72181cc1 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -12,6 +12,7 @@ #include <coins.h> #include <consensus/validation.h> #include <core_io.h> +#include <dogecoin.h> #include <hash.h> #include <index/blockfilterindex.h> #include <node/coinstats.h> @@ -2004,7 +2005,7 @@ static RPCHelpMan getblockstats() ret_all.pushKV("minfeerate", (minfeerate == MAX_MONEY) ? 0 : minfeerate); ret_all.pushKV("mintxsize", mintxsize == MAX_BLOCK_SERIALIZED_SIZE ? 0 : mintxsize); ret_all.pushKV("outs", outputs); - ret_all.pushKV("subsidy", GetBlockSubsidy(pindex->nHeight, Params().GetConsensus())); + ret_all.pushKV("subsidy", GetDogecoinBlockSubsidy(pindex->nHeight, Params().GetConsensus(), block.hashPrevBlock)); ret_all.pushKV("swtotal_size", swtotal_size); ret_all.pushKV("swtotal_weight", swtotal_weight); ret_all.pushKV("swtxs", swtxs); diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index 2b893d018..753c1bb5f 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -67,8 +67,14 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev, block.hashPrevBlock = prev->GetBlockHash(); block.nTime = prev->nTime + 1; + // Dogecoin: Fix rewards at a low value we know is always acceptable, rather than use pseudo-random rewards. + CMutableTransaction txCoinbase(*block.vtx[0]); + txCoinbase.vout[0].nValue = 10000 * COIN; + // Replace mempool-selected txns with just coinbase plus passed-in txns: - block.vtx.resize(1); + block.vtx.clear(); + block.vtx.push_back(MakeTransactionRef(txCoinbase)); + for (const CMutableTransaction& tx : txns) { block.vtx.push_back(MakeTransactionRef(tx)); } diff --git a/src/test/dogecoin_tests.cpp b/src/test/dogecoin_tests.cpp index b446ff685..2932824d3 100644 --- a/src/test/dogecoin_tests.cpp +++ b/src/test/dogecoin_tests.cpp @@ -12,6 +12,61 @@ BOOST_FIXTURE_TEST_SUITE(dogecoin_tests, TestingSetup) +BOOST_AUTO_TEST_CASE(subsidy_test) +{ + const int nHeight = 36; + const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN); + const auto params = chainParams->GetConsensus(); + uint256 prevHash = uint256S("0x4eb7c3f5914a84a25ea0ae12c39d1e5390a8ea576490035b63dcd03fcc14d106"); // Block 35 + + CAmount nSubsidy = GetDogecoinBlockSubsidy(nHeight, params, prevHash); + BOOST_CHECK_EQUAL(nSubsidy, 228450 * COIN); +} + +BOOST_AUTO_TEST_CASE(subsidy_limit_test) +{ + int nHeight = 0; + int nStepSize= 1; + const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN); + const auto params = chainParams->GetConsensus(); + CAmount nSum = 0; + uint256 prevHash = uint256S("0"); + + for (nHeight = 0; nHeight <= 100000; nHeight++) { + CAmount nSubsidy = GetDogecoinBlockSubsidy(nHeight, params, prevHash); + BOOST_CHECK(MoneyRange(nSubsidy)); + BOOST_CHECK(nSubsidy <= 1000000 * COIN); + nSum += nSubsidy * nStepSize; + } + for (; nHeight <= 145000; nHeight++) { + CAmount nSubsidy = GetDogecoinBlockSubsidy(nHeight, params, prevHash); + BOOST_CHECK(MoneyRange(nSubsidy)); + BOOST_CHECK(nSubsidy <= 500000 * COIN); + nSum += nSubsidy * nStepSize; + } + for (; nHeight < 600000; nHeight++) { + CAmount nSubsidy = GetDogecoinBlockSubsidy(nHeight, params, prevHash); + CAmount nExpectedSubsidy = (500000 >> (nHeight / 100000)) * COIN; + BOOST_CHECK(MoneyRange(nSubsidy)); + BOOST_CHECK_EQUAL(nSubsidy, nExpectedSubsidy); + nSum += nSubsidy * nStepSize; + } + + //test sum +- ~10billion + arith_uint256 upperlimit = arith_uint256("95e14ec776380000"); //108 billion doge + BOOST_CHECK(nSum <= upperlimit); + + arith_uint256 lowerlimit = arith_uint256("7a1fe16027700000"); //88 billion doge + BOOST_CHECK(nSum >= lowerlimit); + + // Test reward at 600k+ is constant + CAmount nConstantSubsidy = GetDogecoinBlockSubsidy(600000, params, prevHash); + BOOST_CHECK_EQUAL(nConstantSubsidy, 10000 * COIN); + + nConstantSubsidy = GetDogecoinBlockSubsidy(700000, params, prevHash); + BOOST_CHECK_EQUAL(nConstantSubsidy, 10000 * COIN); +} + BOOST_AUTO_TEST_CASE(get_next_work_difficulty_limit) { SelectParams(CBaseChainParams::MAIN); diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index ea17cb50f..a32b25899 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -85,7 +85,10 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash) CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.vout.resize(2); txCoinbase.vout[1].scriptPubKey = pubKey; - txCoinbase.vout[1].nValue = txCoinbase.vout[0].nValue; + // Dogecoin: Override the calculated reward with a fixed value we know is going to be safe for every block. + // We need this as the blocks are not added to the chain as they're built, and as such the random subsidy + // calculation uses an incorrect previous block hash. + txCoinbase.vout[1].nValue = 10000 * COIN; txCoinbase.vout[0].nValue = 0; txCoinbase.vin[0].scriptWitness.SetNull(); pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp index c3816af0c..f32c7d1db 100644 --- a/src/test/validation_tests.cpp +++ b/src/test/validation_tests.cpp @@ -55,7 +55,9 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test) nSum += nSubsidy * 1000; BOOST_CHECK(MoneyRange(nSum)); } - BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000}); + // Dogecoin: Supply is uncapped, so the test doesn't apply in the same way. + // Instead we update this to the potential maximum at block 14000000 as nearest equivalent. + BOOST_CHECK_EQUAL(nSum, CAmount{999999998900000}); } BOOST_AUTO_TEST_CASE(signet_parse_tests) diff --git a/src/validation.cpp b/src/validation.cpp index b0a805ef1..7457ab50a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -15,6 +15,7 @@ #include <consensus/tx_verify.h> #include <consensus/validation.h> #include <cuckoocache.h> +#include <dogecoin.h> #include <flatfile.h> #include <hash.h> #include <index/txindex.h> @@ -2209,7 +2210,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal); - CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()); + CAmount blockReward = nFees + GetDogecoinBlockSubsidy(pindex->nHeight, chainparams.GetConsensus(), hashPrevBlock); if (block.vtx[0]->GetValueOut() > blockReward) { LogPrintf("ERROR: ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)\n", block.vtx[0]->GetValueOut(), blockReward); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cb-amount"); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index f0682fc97..d1c467888 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -147,7 +147,8 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain240Setup) BOOST_CHECK_EQUAL(result.last_failed_block, oldTip->GetBlockHash()); BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash()); BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight); - BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 25 * COIN); + // Dogecoin: Scaled up by 10,000 + BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 250000 * COIN); } // Prune the remaining block file. @@ -339,7 +340,8 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain240Setup) // credit amount is calculated. wtx.MarkDirty(); BOOST_CHECK(spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey())); - BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 25*COIN); + // Dogecoin: Scaled up by 10,000 + BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 250000*COIN); } static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime) |