Skip to content

Commit

Permalink
Modify chain consensus parameters to be height aware (dogecoin#1396)
Browse files Browse the repository at this point in the history
* Modify chain consensus parameters to be height aware
* Correct implementation of simplified rewards in parameters
* Correct max money
* Use base block version in IsSuperMajority() instead of full version
* Correct mining of blocks in AuxPoW tests
* Add in missing pre-AuxPoW consensus checks
  • Loading branch information
Ross Nicoll committed Sep 19, 2018
1 parent a89d54c commit 1be681a
Show file tree
Hide file tree
Showing 29 changed files with 356 additions and 172 deletions.
2 changes: 1 addition & 1 deletion src/amount.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern const std::string CURRENCY_UNIT;
* critical; in unusual circumstances like a(nother) overflow bug that allowed
* for the creation of coins out of thin air modification could lead to a fork.
* */
static const CAmount MAX_MONEY = 1000000000 * COIN; // Dogecoin: maximum of 100B coins (given some randomness), max transaction 10,000,000,000
static const CAmount MAX_MONEY = 10000000000 * COIN; // Dogecoin: maximum of 100B coins (given some randomness), max transaction 10,000,000,000
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }

/**
Expand Down
4 changes: 1 addition & 3 deletions src/bench/checkblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
char a;
stream.write(&a, 1); // Prevent compaction

Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();

while (state.KeepRunning()) {
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
stream >> block;
assert(stream.Rewind(sizeof(block_bench::block413567)));

CValidationState validationState;
assert(CheckBlock(block, validationState, params));
assert(CheckBlock(block, validationState));
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/blockencodings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
return READ_STATUS_INVALID;

CValidationState state;
if (!CheckBlock(block, state, Params().GetConsensus())) {
// TODO: Make sure lack of block height doesn't cause verification problems
if (!CheckBlock(block, state)) {
// TODO: We really want to just check merkle tree manually here,
// but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to
Expand Down
112 changes: 103 additions & 9 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,14 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
*/

class CMainParams : public CChainParams {
private:
Consensus::Params digishieldConsensus;
Consensus::Params auxpowConsensus;
public:
CMainParams() {
strNetworkID = "main";

// Blocks 0 - 144999 are conventional difficulty calculation
consensus.nSubsidyHalvingInterval = 100000;
consensus.nMajorityEnforceBlockUpgrade = 1500;
consensus.nMajorityRejectBlockOutdated = 1900;
Expand All @@ -82,7 +87,9 @@ class CMainParams : public CChainParams {
consensus.powLimit = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.nPowTargetSpacing = 60; // 1 minute
consensus.fDigishieldDifficultyCalculation = false;
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowAllowDigishieldMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
Expand All @@ -108,10 +115,30 @@ class CMainParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0xca5eb72f1e0d160f1481f74d56d7cc4a27d91aa585ba012da8018a5fe934d61b"); // 1,600,000

// AuxPoW parameters
consensus.nAuxpowChainId = 0x0062; // 98 - Josh Wise!
consensus.nAuxpowStartHeight = 371337;
consensus.fStrictChainId = true;
consensus.nLegacyBlocksBefore = 371337;
consensus.fAllowLegacyBlocks = true;
consensus.nHeightEffective = 0;

// Blocks 145000 - 371336 are Digishield without AuxPoW
digishieldConsensus = consensus;
digishieldConsensus.nHeightEffective = 145000;
digishieldConsensus.fSimplifiedRewards = true;
digishieldConsensus.fDigishieldDifficultyCalculation = true;
digishieldConsensus.nPowTargetTimespan = 60; // post-digishield: 1 minute
digishieldConsensus.nCoinbaseMaturity = 240;

// Blocks 371337+ are AuxPoW
auxpowConsensus = digishieldConsensus;
auxpowConsensus.nHeightEffective = 371337;
auxpowConsensus.fAllowLegacyBlocks = false;

// Assemble the binary search tree of consensus parameters
pConsensusRoot = &digishieldConsensus;
digishieldConsensus.pLeft = &consensus;
digishieldConsensus.pRight = &auxpowConsensus;

/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
Expand All @@ -127,6 +154,8 @@ class CMainParams : public CChainParams {
genesis = CreateGenesisBlock(1386325540, 99943, 0x1e0ffff0, 1, 88 * COIN);

consensus.hashGenesisBlock = genesis.GetHash();
digishieldConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
auxpowConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
assert(consensus.hashGenesisBlock == uint256S("0x1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691"));
assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"));

Expand Down Expand Up @@ -181,9 +210,20 @@ static CMainParams mainParams;
* Testnet (v3)
*/
class CTestNetParams : public CChainParams {
private:
Consensus::Params digishieldConsensus;
Consensus::Params auxpowConsensus;
Consensus::Params minDifficultyConsensus;
public:
CTestNetParams() {
strNetworkID = "test";

// Blocks 0 - 144999 are pre-Digishield
consensus.nHeightEffective = 0;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.fDigishieldDifficultyCalculation = false;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowAllowDigishieldMinDifficultyBlocks = false;
consensus.nSubsidyHalvingInterval = 100000;
consensus.nMajorityEnforceBlockUpgrade = 501;
consensus.nMajorityRejectBlockOutdated = 750;
Expand All @@ -196,7 +236,6 @@ class CTestNetParams : public CChainParams {
consensus.powLimit = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.nPowTargetSpacing = 60; // 1 minute
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
consensus.nMinerConfirmationWindow = 240; // nPowTargetTimespan / nPowTargetSpacing
Expand All @@ -222,9 +261,38 @@ class CTestNetParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x6943eaeaba98dc7d09f7e73398daccb4abcabb18b66c8c875e52b07638d93951"); // 900,000

consensus.nAuxpowStartHeight = 158100;
// AuxPoW parameters
consensus.nAuxpowChainId = 0x0062; // 98 - Josh Wise!
consensus.fStrictChainId = false;
consensus.nLegacyBlocksBefore = -1;
consensus.nHeightEffective = 0;
consensus.fAllowLegacyBlocks = true;

// Blocks 145000 - 157499 are Digishield without minimum difficulty on all blocks
digishieldConsensus = consensus;
digishieldConsensus.nHeightEffective = 145000;
digishieldConsensus.nPowTargetTimespan = 60; // post-digishield: 1 minute
digishieldConsensus.fDigishieldDifficultyCalculation = true;
digishieldConsensus.fSimplifiedRewards = true;
digishieldConsensus.fPowAllowMinDifficultyBlocks = false;
digishieldConsensus.nCoinbaseMaturity = 240;

// Blocks 157500 - 158099 are Digishield with minimum difficulty on all blocks
minDifficultyConsensus = digishieldConsensus;
minDifficultyConsensus.nHeightEffective = 157500;
minDifficultyConsensus.fPowAllowDigishieldMinDifficultyBlocks = true;
minDifficultyConsensus.fPowAllowMinDifficultyBlocks = true;

// Enable AuxPoW at 158100
auxpowConsensus = minDifficultyConsensus;
auxpowConsensus.nHeightEffective = 158100;
auxpowConsensus.fPowAllowDigishieldMinDifficultyBlocks = true;
auxpowConsensus.fAllowLegacyBlocks = false;

// Assemble the binary search tree of parameters
pConsensusRoot = &digishieldConsensus;
digishieldConsensus.pLeft = &consensus;
digishieldConsensus.pRight = &minDifficultyConsensus;
minDifficultyConsensus.pRight = &auxpowConsensus;

pchMessageStart[0] = 0xfc;
pchMessageStart[1] = 0xc1;
Expand All @@ -235,6 +303,9 @@ class CTestNetParams : public CChainParams {

genesis = CreateGenesisBlock(1391503289, 997879, 0x1e0ffff0, 1, 88 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
digishieldConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
minDifficultyConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
auxpowConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
assert(consensus.hashGenesisBlock == uint256S("0xbb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e"));
assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"));

Expand All @@ -257,7 +328,6 @@ class CTestNetParams : public CChainParams {
fRequireStandard = false;
fMineBlocksOnDemand = false;


checkpointData = (CCheckpointData) {
boost::assign::map_list_of
( 0, uint256S("0xbb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e"))
Expand All @@ -282,6 +352,9 @@ static CTestNetParams testNetParams;
* Regression test
*/
class CRegTestParams : public CChainParams {
private:
Consensus::Params digishieldConsensus;
Consensus::Params auxpowConsensus;
public:
CRegTestParams() {
strNetworkID = "regtest";
Expand All @@ -294,8 +367,8 @@ class CRegTestParams : public CChainParams {
// consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests)
consensus.powLimit = uint256S("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1;
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.nPowTargetSpacing = 1; // regtest: 1 second blocks
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = true;
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
Expand All @@ -316,8 +389,29 @@ class CRegTestParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x00");

// AuxPow parameters
consensus.nAuxpowChainId = 0x0062; // 98 - Josh Wise!
consensus.fStrictChainId = true;
consensus.nLegacyBlocksBefore = 0;
consensus.fAllowLegacyBlocks = true;

// Dogecoin parameters
consensus.fSimplifiedRewards = true;
consensus.nCoinbaseMaturity = 60; // For easier testability in RPC tests

digishieldConsensus = consensus;
digishieldConsensus.nHeightEffective = 10;
digishieldConsensus.nPowTargetTimespan = 1; // regtest: also retarget every second in digishield mode, for conformity
digishieldConsensus.fDigishieldDifficultyCalculation = true;

auxpowConsensus = digishieldConsensus;
auxpowConsensus.fAllowLegacyBlocks = false;
auxpowConsensus.nHeightEffective = 20;

// Assemble the binary search tree of parameters
digishieldConsensus.pLeft = &consensus;
digishieldConsensus.pRight = &auxpowConsensus;
pConsensusRoot = &digishieldConsensus;

pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
pchMessageStart[2] = 0xb5;
Expand Down
20 changes: 19 additions & 1 deletion src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,24 @@ class CChainParams
MAX_BASE58_TYPES
};

const Consensus::Params& GetConsensus() const { return consensus; }
const Consensus::Params& GetConsensus(uint32_t nTargetHeight) const {
return *GetConsensus(nTargetHeight, pConsensusRoot);
}

Consensus::Params *GetConsensus(uint32_t nTargetHeight, Consensus::Params *pRoot) const {
if (nTargetHeight < pRoot -> nHeightEffective && pRoot -> pLeft != NULL) {
return GetConsensus(nTargetHeight, pRoot -> pLeft);
} else if (nTargetHeight > pRoot -> nHeightEffective && pRoot -> pRight != NULL) {
Consensus::Params *pCandidate = GetConsensus(nTargetHeight, pRoot -> pRight);
if (pCandidate->nHeightEffective <= nTargetHeight) {
return pCandidate;
}
}

// No better match below the target height
return pRoot;
}

const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
int GetDefaultPort() const { return nDefaultPort; }

Expand All @@ -82,6 +99,7 @@ class CChainParams
CChainParams() {}

Consensus::Params consensus;
Consensus::Params *pConsensusRoot; // Binary search tree root
CMessageHeader::MessageStartChars pchMessageStart;
int nDefaultPort;
uint64_t nPruneAfterHeight;
Expand Down
24 changes: 11 additions & 13 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,24 @@ struct Params {
int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan;
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }

/** Dogecoin-specific parameters */
bool fDigishieldDifficultyCalculation;
bool fPowAllowDigishieldMinDifficultyBlocks; // Allow minimum difficulty blocks where a retarget would normally occur
bool fSimplifiedRewards; // Use block height derived rewards rather than previous block hash derived

uint256 nMinimumChainWork;
uint256 defaultAssumeValid;

/** Auxpow parameters */
int32_t nAuxpowChainId;
int nAuxpowStartHeight;
bool fStrictChainId;
int nLegacyBlocksBefore; // -1 for "always allow"
bool fAllowLegacyBlocks;

/**
* Check whether or not to allow legacy blocks at the given height.
* @param nHeight Height of the block to check.
* @return True if it is allowed to have a legacy version.
*/
bool AllowLegacyBlocks(unsigned nHeight) const
{
if (nLegacyBlocksBefore < 0)
return true;
return static_cast<int> (nHeight) < nLegacyBlocksBefore;
}
/** Height-aware consensus parameters */
uint32_t nHeightEffective; // When these parameters come into use
struct Params *pLeft; // Left hand branch
struct Params *pRight; // Right hand branch
};
} // namespace Consensus

Expand Down
17 changes: 3 additions & 14 deletions src/dogecoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,13 @@ bool AllowDigishieldMinDifficultyForBlock(const CBlockIndex* pindexLast, const C
unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
int nHeight = pindexLast->nHeight + 1;
bool fNewDifficultyProtocol = (nHeight >= 145000);
// bool fNewDifficultyProtocol = (nHeight >= params.GetDigiShieldForkBlock());
const int64_t retargetTimespan = fNewDifficultyProtocol ? 60 // params.DigiShieldTargetTimespan()
:
params.nPowTargetTimespan;

const int64_t retargetTimespan = params.nPowTargetTimespan;
const int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
int64_t nModulatedTimespan = nActualTimespan;
int64_t nMaxTimespan;
int64_t nMinTimespan;

if (fNewDifficultyProtocol) //DigiShield implementation - thanks to RealSolid & WDC for this code
if (params.fDigishieldDifficultyCalculation) //DigiShield implementation - thanks to RealSolid & WDC for this code
{
// amplitude filter - thanks to daft27 for this code
nModulatedTimespan = retargetTimespan + (nModulatedTimespan - retargetTimespan) / 8;
Expand Down Expand Up @@ -84,12 +79,6 @@ unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, in
if (bnNew > bnPowLimit)
bnNew = bnPowLimit;

/// debug print
LogPrintf("GetNextWorkRequired RETARGET\n");
LogPrintf("params.nPowTargetTimespan = %d nActualTimespan = %d\n", params.nPowTargetTimespan, nActualTimespan);
LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString());
LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());

return bnNew.GetCompact();
}

Expand Down Expand Up @@ -134,7 +123,7 @@ CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusP
{
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;

if (nHeight < 145000) // && !consensusParams.SimplifiedRewards())
if (!consensusParams.fSimplifiedRewards)
{
// Old-style rewards derived from the previous block hash
const std::string cseed_str = prevHash.ToString().substr(7, 7);
Expand Down
Loading

0 comments on commit 1be681a

Please sign in to comment.