Modify chain consensus parameters to be height aware

This commit is contained in:
Ross Nicoll 2015-07-09 22:06:41 +01:00
parent b66e509800
commit 949b1ccd88
14 changed files with 258 additions and 92 deletions

View file

@ -28,9 +28,14 @@ using namespace std;
*/
class CMainParams : public CChainParams {
protected:
Consensus::Params digishieldConsensus;
Consensus::Params auxpowConsensus;
public:
CMainParams() {
strNetworkID = "main";
// Blocks 0 - 144999 are conventional difficulty calculation
consensus.nSubsidyHalvingInterval = 100000;
consensus.nMajorityEnforceBlockUpgrade = 750;
consensus.nMajorityRejectBlockOutdated = 950;
@ -39,10 +44,29 @@ public:
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.nPowTargetSpacing = 60; // 1 minute
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowAllowDigishieldMinDifficultyBlocks = false;
consensus.nAuxpowChainId = 0x0062; // 98 - Josh Wise!
consensus.nAuxpowStartHeight = 371337;
consensus.fStrictChainId = true;
consensus.nLegacyBlocksBefore = 371337;
consensus.fAllowLegacyBlocks = true;
consensus.nHeightEffective = 0;
consensus.fDigishieldDifficultyCalculation = false;
// Blocks 145000 - 371336 are Digishield without AuxPoW
digishieldConsensus = consensus;
digishieldConsensus.nHeightEffective = 145000;
digishieldConsensus.fDigishieldDifficultyCalculation = true;
digishieldConsensus.nPowTargetTimespan = 60; // post-digishield: 1 minute
// 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
@ -84,6 +108,8 @@ public:
genesis.nNonce = 99943;
consensus.hashGenesisBlock = genesis.GetHash();
digishieldConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
auxpowConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
assert(consensus.hashGenesisBlock == uint256S("0x1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691"));
assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"));
@ -145,16 +171,53 @@ static CMainParams mainParams;
* Testnet (v3)
*/
class CTestNetParams : public CMainParams {
private:
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.nMajorityEnforceBlockUpgrade = 51;
consensus.nMajorityRejectBlockOutdated = 75;
consensus.nMajorityWindow = 100;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.nAuxpowStartHeight = 158100;
consensus.fStrictChainId = false;
consensus.nLegacyBlocksBefore = 158100;
consensus.nHeightEffective = 0;
consensus.fAllowLegacyBlocks = true;
// Reset links before we copy parameters
consensus.pLeft = NULL;
consensus.pRight = NULL;
// 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.fPowAllowMinDifficultyBlocks = false;
// 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;
@ -169,6 +232,9 @@ public:
genesis.nTime = 1391503289;
genesis.nNonce = 997879;
consensus.hashGenesisBlock = genesis.GetHash();
digishieldConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
minDifficultyConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
auxpowConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
assert(consensus.hashGenesisBlock == uint256S("0xbb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e"));
vFixedSeeds.clear();
@ -215,9 +281,28 @@ public:
consensus.nMajorityEnforceBlockUpgrade = 750;
consensus.nMajorityRejectBlockOutdated = 950;
consensus.nMajorityWindow = 1000;
consensus.nPowTargetTimespan = 4 * 60 * 60; // pre-digishield: 4 hours
consensus.powLimit = uint256S("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1;
consensus.fStrictChainId = true;
consensus.nLegacyBlocksBefore = 0;
consensus.fAllowLegacyBlocks = false; // Never allow legacy blocks on RegTest
// Reset links before we copy parameters
consensus.pLeft = NULL;
consensus.pRight = NULL;
digishieldConsensus = consensus;
digishieldConsensus.nHeightEffective = 10;
digishieldConsensus.nPowTargetTimespan = 60; // post-digishield: 1 minute
digishieldConsensus.fDigishieldDifficultyCalculation = true;
auxpowConsensus = digishieldConsensus;
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;
@ -227,6 +312,8 @@ public:
genesis.nBits = 0x207fffff;
genesis.nNonce = 2;
consensus.hashGenesisBlock = genesis.GetHash();
digishieldConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
auxpowConsensus.hashGenesisBlock = consensus.hashGenesisBlock;
nDefaultPort = 18444;
assert(consensus.hashGenesisBlock == uint256S("0x3d2160a3b5dc4a9d62e7e66a295f70313ac808440ef7400d6c0772171ce973a5"));
nPruneAfterHeight = 1000;

View file

@ -45,7 +45,24 @@ public:
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; }
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
int GetDefaultPort() const { return nDefaultPort; }
@ -76,6 +93,7 @@ protected:
CChainParams() {}
Consensus::Params consensus;
Consensus::Params *pConsensusRoot; // Binary search tree root
CMessageHeader::MessageStartChars pchMessageStart;
//! Raw pub key bytes for the broadcast alert signing key.
std::vector<unsigned char> vAlertPubKey;

View file

@ -25,23 +25,20 @@ struct Params {
int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan;
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
/** Auxpow parameters */
int32_t nAuxpowChainId;
int nAuxpowStartHeight;
bool fStrictChainId;
int nLegacyBlocksBefore; // -1 for "always allow"
/**
* 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;
}
/** Dogecoin-specific parameters */
bool fDigishieldDifficultyCalculation;
bool fPowAllowDigishieldMinDifficultyBlocks; // Allow minimum difficulty blocks where a retarget would normally occur
/** Auxpow parameters */
int16_t nAuxpowChainId;
bool fStrictChainId;
bool fAllowLegacyBlocks;
/** 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

View file

@ -16,21 +16,34 @@ int static generateMTRandom(unsigned int s, int range)
return dist(gen);
}
// 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.
bool AllowDigishieldMinDifficultyForBlock(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
// check if the chain allows minimum difficulty blocks
if (!params.fPowAllowMinDifficultyBlocks)
return false;
// check if the chain allows minimum difficulty blocks on recalc blocks
if (pindexLast->nHeight < 157500)
// if (!params.fPowAllowDigishieldMinDifficultyBlocks)
return false;
// Allow for a minimum block time if the elapsed time > 2*nTargetSpacing
return (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2);
}
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;
@ -66,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();
}

View file

@ -6,6 +6,7 @@
#include "chain.h"
#include "chainparams.h"
bool AllowDigishieldMinDifficultyForBlock(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params);
CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, uint256 prevHash);
unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params);

View file

@ -1150,7 +1150,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around).
if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0)
if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus(0).hashGenesisBlock) == 0)
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
// Initialize the block index (no-op if non-empty database was already loaded)

View file

@ -1182,7 +1182,7 @@ static bool ReadBlockOrHeader(T& block, const CDiskBlockPos& pos)
}
// Check the header
if (!CheckAuxPowProofOfWork(block, Params().GetConsensus()))
if (!CheckAuxPowProofOfWork(block, Params().GetConsensus(0))) // FIXME: Can we get height at all?
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
return true;
@ -1800,6 +1800,7 @@ static int64_t nTimeTotal = 0;
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
{
const CChainParams& chainparams = Params();
const Consensus::Params consensus = chainparams.GetConsensus(pindex->nHeight);
AssertLockHeld(cs_main);
// Check it again in case a previous version let a bad block in
if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
@ -1811,7 +1812,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) {
if (block.GetHash() == consensus.hashGenesisBlock) {
if (!fJustCheck)
view.SetBestBlock(pindex->GetBlockHash());
return true;
@ -1850,7 +1851,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE;
// Start enforcing the DERSIG (BIP66) rules, for block.nVersion=3 blocks, when 75% of the network has upgraded:
if (block.nVersion >= 3 && IsSuperMajority(3, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
if (block.nVersion >= 3 && IsSuperMajority(3, pindex->pprev, consensus.nMajorityEnforceBlockUpgrade, consensus)) {
flags |= SCRIPT_VERIFY_DERSIG;
}
@ -1913,7 +1914,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
CAmount blockReward = nFees + GetDogecoinBlockSubsidy(pindex->nHeight, chainparams.GetConsensus(), hashPrevBlock);
CAmount blockReward = nFees + GetDogecoinBlockSubsidy(pindex->nHeight, consensus, hashPrevBlock);
if (block.vtx[0].GetValueOut() > blockReward)
return state.DoS(100,
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
@ -2667,7 +2668,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW)
{
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckAuxPowProofOfWork(block, Params().GetConsensus()))
if (fCheckPOW && !CheckAuxPowProofOfWork(block, Params().GetConsensus(0))) // FIXME: Get actual height
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
REJECT_INVALID, "high-hash");
@ -2742,7 +2743,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev)
{
const CChainParams& chainParams = Params();
const Consensus::Params& consensusParams = chainParams.GetConsensus();
const Consensus::Params& consensusParams = chainParams.GetConsensus(pindexPrev->nHeight + 1);
uint256 hash = block.GetHash();
if (hash == consensusParams.hashGenesisBlock)
return true;
@ -2752,15 +2753,15 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight+1;
// Disallow legacy blocks after merge-mining start.
if (!Params().GetConsensus().AllowLegacyBlocks(nHeight)
if (!consensusParams.fAllowLegacyBlocks
&& block.nVersion.IsLegacy())
return state.DoS(100, error("%s : legacy block after auxpow start",
__func__),
return state.DoS(100, error("%s : legacy block after auxpow start at height %d, parameters effective from %d",
__func__, pindexPrev->nHeight + 1, consensusParams.nHeightEffective),
REJECT_INVALID, "late-legacy-block");
// Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
return state.DoS(100, error("%s: incorrect proof of work", __func__),
return state.DoS(100, error("%s: incorrect proof of work at height %d", __func__, nHeight),
REJECT_INVALID, "bad-diffbits");
// Check timestamp against prev
@ -2797,7 +2798,6 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev)
{
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
const Consensus::Params& consensusParams = Params().GetConsensus();
// Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@ -2807,7 +2807,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
if (block.nVersion >= 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))
// Dogecoin: Block v2 was never enforced
if (block.nVersion >= 3)
{
CScript expect = CScript() << nHeight;
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
@ -2842,7 +2843,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
// Get prev block index
CBlockIndex* pindexPrev = NULL;
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
if (hash != chainparams.GetConsensus(0).hashGenesisBlock) {
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk");
@ -3485,7 +3486,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
// detect out of order blocks, and store them for later
uint256 hash = block.GetHash();
if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) {
if (hash != chainparams.GetConsensus(0).hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) {
LogPrint("reindex", "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
block.hashPrevBlock.ToString());
if (dbp)
@ -3500,7 +3501,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
nLoaded++;
if (state.IsError())
break;
} else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) {
} else if (hash != chainparams.GetConsensus(0).hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) {
LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight);
}
@ -3542,7 +3543,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
void static CheckBlockIndex()
{
const Consensus::Params& consensusParams = Params().GetConsensus();
if (!fCheckBlockIndex) {
return;
}
@ -3557,6 +3557,7 @@ void static CheckBlockIndex()
return;
}
// Build forward-pointing map of the entire block tree.
std::multimap<CBlockIndex*,CBlockIndex*> forward;
for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) {
@ -3583,6 +3584,7 @@ void static CheckBlockIndex()
CBlockIndex* pindexFirstNotChainValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
CBlockIndex* pindexFirstNotScriptsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
while (pindex != NULL) {
const Consensus::Params& consensusParams = Params().GetConsensus(nHeight);
nNodes++;
if (pindexFirstInvalid == NULL && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
if (pindexFirstMissing == NULL && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex;
@ -3816,8 +3818,8 @@ bool static AlreadyHave(const CInv& inv)
void static ProcessGetData(CNode* pfrom)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
vector<CInv> vNotFound;
const Consensus::Params &consensus = Params().GetConsensus(chainActive.Height());
LOCK(cs_main);
@ -3846,7 +3848,7 @@ void static ProcessGetData(CNode* pfrom)
// best equivalent proof of work) than the best header chain we know about.
send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
(pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) &&
(GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, Params().GetConsensus()) < nOneMonth);
(GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, consensus) < nOneMonth);
if (!send) {
LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
}
@ -4208,12 +4210,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// not a direct successor.
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash);
CNodeState *nodestate = State(pfrom->GetId());
if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 &&
if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus(chainActive.Height()).nPowTargetSpacing * 20 &&
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
vToFetch.push_back(inv);
// Mark block as in flight already, even though the actual "getdata" message only goes out
// later (within the same cs_main lock, though).
MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus(chainActive.Height()));
}
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
}
@ -4876,7 +4878,7 @@ bool ProcessMessages(CNode* pfrom)
bool SendMessages(CNode* pto, bool fSendTrickle)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
const Consensus::Params& consensusParams = Params().GetConsensus(chainActive.Height());
{
// Don't send anything until we get its version message
if (pto->nVersion == 0)

View file

@ -328,15 +328,16 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
// Compute final coinbase transaction.
txNew.vout[0].nValue = nFees + GetDogecoinBlockSubsidy(nHeight, chainparams.GetConsensus(), pindexPrev->GetBlockHash());
const Consensus::Params &consensus = chainparams.GetConsensus(nHeight);
txNew.vout[0].nValue = nFees + GetDogecoinBlockSubsidy(nHeight, consensus, pindexPrev->GetBlockHash());
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
UpdateTime(pblock, consensus, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensus);
pblock->nNonce = 0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
@ -482,6 +483,7 @@ void static BitcoinMiner(CWallet *pwallet)
//
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip();
const Consensus::Params &consensus = Params().GetConsensus(pindexPrev -> nHeight + 1);
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
if (!pblocktemplate.get())
@ -540,8 +542,8 @@ void static BitcoinMiner(CWallet *pwallet)
break;
// Update nTime every few seconds
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
UpdateTime(pblock, consensus, pindexPrev);
if (consensus.fPowAllowMinDifficultyBlocks)
{
// Changing pblock->nTime can change work required on testnet:
hashTarget.SetCompact(pblock->nBits);

View file

@ -12,6 +12,22 @@
#include "uint256.h"
#include "util.h"
// Determine if the for the given block, a min difficulty setting applies
bool AllowMinDifficultyForBlock(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
// check if the chain allows minimum difficulty blocks
if (!params.fPowAllowMinDifficultyBlocks)
return false;
// Dogecoin: Magic number at which reset protocol switches
// check if we allow minimum difficulty at this block-height
if (pindexLast->nHeight < 157500)
return false;
// Allow for a minimum block time if the elapsed time > 2*nTargetSpacing
return (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2);
}
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
@ -20,6 +36,15 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
if (pindexLast == NULL)
return nProofOfWorkLimit;
// Dogecoin: Special rules for minimum difficulty blocks with Digishield
if (AllowDigishieldMinDifficultyForBlock(pindexLast, pblock, params))
{
// Special difficulty rule for testnet:
// If the new block's timestamp is more than 2* nTargetSpacing minutes
// then allow mining of a min-difficulty block.
return nProofOfWorkLimit;
}
// Only change once per difficulty adjustment interval
if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
{
@ -55,7 +80,6 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
{
// Limit adjustment step
int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
if (nActualTimespan < params.nPowTargetTimespan/4)
nActualTimespan = params.nPowTargetTimespan/4;
if (nActualTimespan > params.nPowTargetTimespan*4)

View file

@ -47,7 +47,7 @@ Value GetNetworkHashPS(int lookup, int height) {
// If lookup is -1, then use blocks since last difficulty change.
if (lookup <= 0)
lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1;
lookup = pb->nHeight % Params().GetConsensus(pb->nHeight).DifficultyAdjustmentInterval() + 1;
// If lookup is larger than chain, then set it to chain length.
if (lookup > pb->nHeight)
@ -159,7 +159,7 @@ Value generate(const Array& params, bool fHelp)
LOCK(cs_main);
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
}
while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus(nHeight))) {
// Yes, there is a chance every nonce could fail to satisfy the -regtest
// target -- 1 in 2^(2^32). That ain't gonna happen.
++pblock->nNonce;
@ -518,7 +518,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
UpdateTime(pblock, Params().GetConsensus(pindexPrev->nHeight), pindexPrev);
pblock->nNonce = 0;
static const Array aCaps = boost::assign::list_of("proposal");
@ -773,14 +773,6 @@ Value getauxblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD,
"Namecoin is downloading blocks...");
/* This should never fail, since the chain is already
past the point of merge-mining start. Check nevertheless. */
{
LOCK(cs_main);
if (chainActive.Height() + 1 < Params().GetConsensus().nAuxpowStartHeight)
throw std::runtime_error("getauxblock method is not yet available");
}
/* The variables below are used to keep track of created and not yet
submitted auxpow blocks. Lock them, just in case. In principle
there's only one RPC thread, so it should be fine without locking

View file

@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert)
CCriticalSection csDummy;
CBlockIndex indexDummy[800];
CChainParams& params = Params(CBaseChainParams::MAIN);
int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing;
int64_t nPowTargetSpacing = params.GetConsensus(0).nPowTargetSpacing;
// Generate fake blockchain timestamps relative to
// an arbitrary time:

View file

@ -180,7 +180,7 @@ CAuxpowBuilder::buildCoinbaseData(bool header, const std::vector<unsigned char>&
BOOST_AUTO_TEST_CASE(check_auxpow)
{
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(371337);
CAuxpowBuilder builder(5, 42);
CAuxPow auxpow;
@ -339,16 +339,16 @@ mineBlock(CBlockHeader& block, bool ok, int nBits = -1)
}
if (ok)
BOOST_CHECK(CheckProofOfWork(block.GetPoWHash(), nBits, Params().GetConsensus()));
BOOST_CHECK(CheckProofOfWork(block.GetPoWHash(), nBits, Params().GetConsensus(371337)));
else
BOOST_CHECK(!CheckProofOfWork(block.GetPoWHash(), nBits, Params().GetConsensus()));
BOOST_CHECK(!CheckProofOfWork(block.GetPoWHash(), nBits, Params().GetConsensus(371337)));
}
BOOST_AUTO_TEST_CASE(auxpow_pow)
{
/* Use regtest parameters to allow mining with easy difficulty. */
SelectParams(CBaseChainParams::REGTEST);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(371337);
const arith_uint256 target = (~arith_uint256(0) >> 1);
CBlockHeader block;

View file

@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
int nHeight = 0;
int nStepSize= 1;
const Consensus::Params& params = Params(CBaseChainParams::MAIN).GetConsensus();
const Consensus::Params& params = Params(CBaseChainParams::MAIN).GetConsensus(0);
CAmount nSum = 0;
uint256 prevHash = uint256S("0");
@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test)
BOOST_AUTO_TEST_CASE(get_next_work_difficulty_limit)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
CBlockIndex pindexLast;
int64_t nLastRetargetTime = 1386474927; // Block # 1
@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_difficulty_limit)
BOOST_AUTO_TEST_CASE(get_next_work_pre_digishield)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
CBlockIndex pindexLast;
int64_t nLastRetargetTime = 1386942008; // Block 9359
@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pre_digishield)
BOOST_AUTO_TEST_CASE(get_next_work_digishield)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(145000);
CBlockIndex pindexLast;
int64_t nLastRetargetTime = 1395094427;
@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_digishield)
BOOST_AUTO_TEST_CASE(get_next_work_digishield_modulated_upper)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(145000);
CBlockIndex pindexLast;
int64_t nLastRetargetTime = 1395100835;
@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_digishield_modulated_upper)
BOOST_AUTO_TEST_CASE(get_next_work_digishield_modulated_lower)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(145000);
CBlockIndex pindexLast;
int64_t nLastRetargetTime = 1395380517;
@ -178,7 +178,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_digishield_modulated_lower)
BOOST_AUTO_TEST_CASE(get_next_work_digishield_rounding)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(145000);
CBlockIndex pindexLast;
int64_t nLastRetargetTime = 1395094679;
@ -191,4 +191,40 @@ BOOST_AUTO_TEST_CASE(get_next_work_digishield_rounding)
BOOST_CHECK_EQUAL(CalculateDogecoinNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1b6558a4);
}
BOOST_AUTO_TEST_CASE(hardfork_parameters)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& initialParams = Params().GetConsensus(0);
BOOST_CHECK_EQUAL(initialParams.nPowTargetTimespan, 14400);
BOOST_CHECK_EQUAL(initialParams.fAllowLegacyBlocks, true);
BOOST_CHECK_EQUAL(initialParams.fDigishieldDifficultyCalculation, false);
const Consensus::Params& initialParamsEnd = Params().GetConsensus(144999);
BOOST_CHECK_EQUAL(initialParamsEnd.nPowTargetTimespan, 14400);
BOOST_CHECK_EQUAL(initialParamsEnd.fAllowLegacyBlocks, true);
BOOST_CHECK_EQUAL(initialParamsEnd.fDigishieldDifficultyCalculation, false);
const Consensus::Params& digishieldParams = Params().GetConsensus(145000);
BOOST_CHECK_EQUAL(digishieldParams.nPowTargetTimespan, 60);
BOOST_CHECK_EQUAL(digishieldParams.fAllowLegacyBlocks, true);
BOOST_CHECK_EQUAL(digishieldParams.fDigishieldDifficultyCalculation, true);
const Consensus::Params& digishieldParamsEnd = Params().GetConsensus(371336);
BOOST_CHECK_EQUAL(digishieldParamsEnd.nPowTargetTimespan, 60);
BOOST_CHECK_EQUAL(digishieldParamsEnd.fAllowLegacyBlocks, true);
BOOST_CHECK_EQUAL(digishieldParamsEnd.fDigishieldDifficultyCalculation, true);
const Consensus::Params& auxpowParams = Params().GetConsensus(371337);
BOOST_CHECK_EQUAL(auxpowParams.nHeightEffective, 371337);
BOOST_CHECK_EQUAL(auxpowParams.nPowTargetTimespan, 60);
BOOST_CHECK_EQUAL(auxpowParams.fAllowLegacyBlocks, false);
BOOST_CHECK_EQUAL(auxpowParams.fDigishieldDifficultyCalculation, true);
const Consensus::Params& auxpowHighParams = Params().GetConsensus(700000); // Arbitrary point after last hard-fork
BOOST_CHECK_EQUAL(auxpowHighParams.nPowTargetTimespan, 60);
BOOST_CHECK_EQUAL(auxpowHighParams.fAllowLegacyBlocks, false);
BOOST_CHECK_EQUAL(auxpowHighParams.fDigishieldDifficultyCalculation, true);
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -18,7 +18,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* BOOST_AUTO_TEST_CASE(get_next_work)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
int64_t nLastRetargetTime = 1261130161; // Block #30240
CBlockIndex pindexLast;
@ -33,7 +33,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
int64_t nLastRetargetTime = 1231006505; // Block #0
CBlockIndex pindexLast;
@ -48,7 +48,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
int64_t nLastRetargetTime = 1279008237; // Block #66528
CBlockIndex pindexLast;
@ -63,7 +63,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time
CBlockIndex pindexLast;
@ -76,7 +76,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
{
SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus();
const Consensus::Params& params = Params().GetConsensus(0);
std::vector<CBlockIndex> blocks(10000);
for (int i = 0; i < 10000; i++) {