From 3b30d8361ad969b8168a1014cf994e52ea791d19 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 22 Sep 2016 16:38:44 -0700 Subject: [PATCH] Founders reward: changed index computation, added new test and some refactoring. --- src/chainparams.cpp | 14 ++++-- src/chainparams.h | 5 +- src/gtest/test_foundersreward.cpp | 78 ++++++++++++++++++++----------- src/main.cpp | 2 +- src/miner.cpp | 2 +- 5 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 94813a0c7..b8dafa8d7 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -341,25 +341,31 @@ bool SelectParamsFromCommandLine() // Block height must be >0 and <=last founders reward block height // Index variable i ranges from 0 - (vFoundersRewardAddress.size()-1) -std::string CChainParams::GetFoundersRewardAddress(int nHeight) const +std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const { int maxHeight = consensus.GetLastFoundersRewardBlockHeight(); assert(nHeight>0 && nHeight<=maxHeight); - size_t i = (size_t)floor((double(nHeight-1)/maxHeight)*vFoundersRewardAddress.size()); + size_t addressChangeInterval = (maxHeight + vFoundersRewardAddress.size()) / vFoundersRewardAddress.size(); + size_t i = nHeight / addressChangeInterval; return vFoundersRewardAddress[i]; } // Block height must be >0 and <=last founders reward block height // The founders reward address is expected to be a multisig (P2SH) address -CScript CChainParams::GetFoundersRewardScript(int nHeight) const +CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const { assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight()); - CBitcoinAddress address(GetFoundersRewardAddress(nHeight).c_str()); + CBitcoinAddress address(GetFoundersRewardAddressAtHeight(nHeight).c_str()); assert(address.IsValid()); assert(address.IsScript()); CScriptID scriptID = get(address.Get()); // Get() returns a boost variant CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return script; } + +std::string CChainParams::GetFoundersRewardAddressAtIndex(int i) const { + assert(i>=0 && i& FixedSeeds() const { return vFixedSeeds; } const Checkpoints::CCheckpointData& Checkpoints() const { return checkpointData; } /** Return the founder's reward address and script for a given block height */ - std::string GetFoundersRewardAddress(int height) const; - CScript GetFoundersRewardScript(int height) const; + std::string GetFoundersRewardAddressAtHeight(int height) const; + CScript GetFoundersRewardScriptAtHeight(int height) const; + std::string GetFoundersRewardAddressAtIndex(int i) const; protected: CChainParams() {} diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index 01a72d846..7c3f224bf 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -69,9 +69,17 @@ TEST(founders_reward_test, create_testnet_2of3multisig) { #endif -#define NUM_TESTNET_FOUNDER_ADDRESSES 48 +// Utility method to check the number of unique addresses from height 1 to maxHeight +void checkNumberOfUniqueAddresses(int maxHeight, int nUnique) { + std::set addresses; + for (int i=1; i<=maxHeight; i++) { + addresses.insert(Params().GetFoundersRewardAddressAtHeight(i)); + } + ASSERT_TRUE(addresses.size()==nUnique); +} -TEST(founders_reward_test, testnet) { + +TEST(founders_reward_test, general) { SelectParams(CBaseChainParams::TESTNET); CChainParams params = Params(); @@ -79,24 +87,16 @@ TEST(founders_reward_test, testnet) { // For Testnet, the first address is derived from the old script. // FOUNDERS_REWARD_SCRIPT = a9146708e6670db0b950dac68031025cc5b63213a49187 // address = 2N2e2FRfP9D1dRN1oRWkH7pbFM69eGNAuQ4 - EXPECT_EQ(params.GetFoundersRewardScript(1), ParseHex("a9146708e6670db0b950dac68031025cc5b63213a49187")); - EXPECT_EQ(params.GetFoundersRewardAddress(1), "2N2e2FRfP9D1dRN1oRWkH7pbFM69eGNAuQ4"); + EXPECT_EQ(params.GetFoundersRewardScriptAtHeight(1), ParseHex("a9146708e6670db0b950dac68031025cc5b63213a49187")); + EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(1), "2N2e2FRfP9D1dRN1oRWkH7pbFM69eGNAuQ4"); int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); // If the block height parameter is out of bounds, there is an assert. - EXPECT_DEATH(params.GetFoundersRewardScript(0), "nHeight"); - EXPECT_DEATH(params.GetFoundersRewardScript(maxHeight+1), "nHeight"); - EXPECT_DEATH(params.GetFoundersRewardAddress(0), "nHeight"); - EXPECT_DEATH(params.GetFoundersRewardAddress(maxHeight+1), "nHeight"); - - // Check that different addresses are used for testnet - std::set addresses; - for (int i=1; i<=maxHeight; i++) { - addresses.insert(params.GetFoundersRewardAddress(i)); - } - ASSERT_TRUE(addresses.size()==NUM_TESTNET_FOUNDER_ADDRESSES); - + EXPECT_DEATH(params.GetFoundersRewardScriptAtHeight(0), "nHeight"); + EXPECT_DEATH(params.GetFoundersRewardScriptAtHeight(maxHeight+1), "nHeight"); + EXPECT_DEATH(params.GetFoundersRewardAddressAtHeight(0), "nHeight"); + EXPECT_DEATH(params.GetFoundersRewardAddressAtHeight(maxHeight+1), "nHeight"); } @@ -107,11 +107,18 @@ TEST(founders_reward_test, mainnet) { CChainParams params = Params(); int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); - std::set addresses; - for (int i=1; i<=maxHeight; i++) { - addresses.insert(params.GetFoundersRewardAddress(i)); - } - ASSERT_TRUE(addresses.size()==NUM_MAINNET_FOUNDER_ADDRESSES); + checkNumberOfUniqueAddresses(maxHeight, NUM_MAINNET_FOUNDER_ADDRESSES); +} + + +#define NUM_TESTNET_FOUNDER_ADDRESSES 48 + +TEST(founders_reward_test, testnet) { + SelectParams(CBaseChainParams::TESTNET); + CChainParams params = Params(); + + int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); + checkNumberOfUniqueAddresses(maxHeight, NUM_TESTNET_FOUNDER_ADDRESSES); } @@ -120,13 +127,9 @@ TEST(founders_reward_test, mainnet) { TEST(founders_reward_test, regtest) { SelectParams(CBaseChainParams::REGTEST); CChainParams params = Params(); - + int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); - std::set addresses; - for (int i=1; i<=maxHeight; i++) { - addresses.insert(params.GetFoundersRewardAddress(i)); - } - ASSERT_TRUE(addresses.size()==NUM_REGTEST_FOUNDER_ADDRESSES); + checkNumberOfUniqueAddresses(maxHeight, NUM_REGTEST_FOUNDER_ADDRESSES); } @@ -146,3 +149,24 @@ TEST(founders_reward_test, slow_start_subsidy) { ASSERT_TRUE(totalSubsidy == MAX_MONEY/10.0); } + + +// Verify the number of rewards going to each mainnet/testnet address +TEST(founders_reward_test, per_address_reward) { + SelectParams(CBaseChainParams::TESTNET); + CChainParams params = Params(); + + int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight(); + std::multiset ms; + for (int nHeight=1; nHeight<=maxHeight; nHeight++) { + ms.insert(params.GetFoundersRewardAddressAtHeight(nHeight)); + } + + ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(0)) == 17708); + for (int i = 1; i <= 46; i++) { + ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(i)) == 17709); + } + ASSERT_TRUE(ms.count(params.GetFoundersRewardAddressAtIndex(47)) == 17677); + +} + diff --git a/src/main.cpp b/src/main.cpp index c6b1f1fcb..5a8cd147d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3090,7 +3090,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn bool found = false; BOOST_FOREACH(const CTxOut& output, block.vtx[0].vout) { - if (output.scriptPubKey == Params().GetFoundersRewardScript(nHeight)) { + if (output.scriptPubKey == Params().GetFoundersRewardScriptAtHeight(nHeight)) { if (output.nValue == (GetBlockSubsidy(nHeight, consensusParams) / 5)) { found = true; break; diff --git a/src/miner.cpp b/src/miner.cpp index 0d655249c..8c0c2ad81 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -342,7 +342,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) txNew.vout[0].nValue -= vFoundersReward; // And give it to the founders - txNew.vout.push_back(CTxOut(vFoundersReward, chainparams.GetFoundersRewardScript(nHeight))); + txNew.vout.push_back(CTxOut(vFoundersReward, chainparams.GetFoundersRewardScriptAtHeight(nHeight))); } // Add fees