Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class CMainParams : public CChainParams {
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000003f94d1ad391682fe038bf5");

consensus.HardforkTime = std::numeric_limits<int64_t>::max();
consensus.nPowChangeTargetShift = 20;

// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x00000000000000000013176bf8d7dfeab4e1db31dc93bc311b436e82ab226b90"); //453354

Expand All @@ -115,7 +118,7 @@ class CMainParams : public CChainParams {
nPruneAfterHeight = 100000;

genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
consensus.hashGenesisBlock = genesis.GetHash(consensus);
assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

Expand Down Expand Up @@ -203,6 +206,9 @@ class CTestNetParams : public CChainParams {
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000001f057509eba81aed91");

consensus.HardforkTime = std::numeric_limits<int64_t>::max();
consensus.nPowChangeTargetShift = 20;

// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x00000000000128796ee387cf110ccb9d2f36cffaf7f73079c995377c65ac0dcc"); //1079274

Expand All @@ -214,7 +220,7 @@ class CTestNetParams : public CChainParams {
nPruneAfterHeight = 1000;

genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
consensus.hashGenesisBlock = genesis.GetHash(consensus);
assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

Expand Down Expand Up @@ -288,6 +294,10 @@ class CRegTestParams : public CChainParams {
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");

consensus.HardforkTime = 1296688603; // Just past the genesis block
consensus.PowChangeAlgo = HashAlgorithm::NUM_HASH_ALGOS;
consensus.nPowChangeTargetShift = 20;

// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x00");

Expand All @@ -299,7 +309,7 @@ class CRegTestParams : public CChainParams {
nPruneAfterHeight = 1000;

genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
consensus.hashGenesisBlock = genesis.GetHash(consensus);
assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

Expand Down
18 changes: 18 additions & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef BITCOIN_CONSENSUS_PARAMS_H
#define BITCOIN_CONSENSUS_PARAMS_H

#include "hash.h"
#include "uint256.h"
#include <map>
#include <string>
Expand Down Expand Up @@ -62,6 +63,23 @@ struct Params {
int64_t nPowTargetTimespan;
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
uint256 nMinimumChainWork;

/** Hardfork parameters */
int64_t HardforkTime;
HashAlgorithm PowChangeAlgo;
int nPowChangeTargetShift;
HashAlgorithm PowAlgorithmForTime(int64_t nTime) const {
if (nTime >= HardforkTime) {
if (PowChangeAlgo == HashAlgorithm::NUM_HASH_ALGOS) {
// Indicates a rotating hash algo, for testing
return (HashAlgorithm)((nTime / 3600) % (unsigned int)HashAlgorithm::NUM_HASH_ALGOS);
}
return PowChangeAlgo;
} else {
return HashAlgorithm::SHA256d;
}
}

uint256 defaultAssumeValid;
};
} // namespace Consensus
Expand Down
8 changes: 8 additions & 0 deletions src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@

#include <vector>

enum class HashAlgorithm: unsigned int {
SHA256,
SHA256d,
RIPEMD160,
HASH160,
NUM_HASH_ALGOS,
};

typedef uint256 ChainCode;

/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */
Expand Down
35 changes: 26 additions & 9 deletions src/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
if (pindexLast == NULL)
return nProofOfWorkLimit;

uint32_t nBits;

// Only change once per difficulty adjustment interval
if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
{
Expand All @@ -30,23 +32,38 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
return nProofOfWorkLimit;
else
{
// Return the last non-special-min-difficulty-rules-block
// Look back to the last non-special-min-difficulty-rules-block
const CBlockIndex* pindex = pindexLast;
while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
pindex = pindex->pprev;
return pindex->nBits;
nBits = pindex->nBits;
}
} else {
nBits = pindexLast->nBits;
}
return pindexLast->nBits;
} else {
// Go back by what we want to be 14 days worth of blocks
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
assert(nHeightFirst >= 0);
const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
assert(pindexFirst);

nBits = CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
}

// Go back by what we want to be 14 days worth of blocks
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
assert(nHeightFirst >= 0);
const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
assert(pindexFirst);
if (params.PowAlgorithmForTime(pblock->nTime) != params.PowAlgorithmForTime(pindexLast->nTime)) {
// Adjust target for PoW change
arith_uint256 bnNew;
bnNew.SetCompact(nBits);
bnNew <<= params.nPowChangeTargetShift;
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
if (bnNew > bnPowLimit) {
bnNew = bnPowLimit;
}
nBits = bnNew.GetCompact();
}

return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
return nBits;
}

unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
Expand Down
38 changes: 37 additions & 1 deletion src/primitives/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,47 @@
#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "chainparams.h"
#include "consensus/params.h"
#include "crypto/common.h"
#include "streams.h"

#include <cstdlib>

uint256 CBlockHeader::GetHash(const Consensus::Params& consensusParams) const
{
CDataStream ss(SER_GETHASH, PROTOCOL_VERSION);
ss << *this;

const auto pbegin = (const unsigned char *)&ss.begin()[0];
uint256 hash;

const HashAlgorithm algo = consensusParams.PowAlgorithmForTime(nTime);
switch (algo) {
case HashAlgorithm::SHA256:
CSHA256().Write(pbegin, ss.size()).Finalize((unsigned char*)&hash);
break;
case HashAlgorithm::SHA256d:
CHash256().Write(pbegin, ss.size()).Finalize((unsigned char*)&hash);
break;
case HashAlgorithm::RIPEMD160:
CRIPEMD160().Write(pbegin, ss.size()).Finalize((unsigned char*)&hash);
break;
case HashAlgorithm::HASH160:
CHash160().Write(pbegin, ss.size()).Finalize((unsigned char*)&hash);
break;
case HashAlgorithm::NUM_HASH_ALGOS:
// Should be impossible
abort();
}

return hash;
}

uint256 CBlockHeader::GetHash() const
{
return SerializeHash(*this);
const Consensus::Params& consensusParams = Params().GetConsensus();
return GetHash(consensusParams);
}

std::string CBlock::ToString() const
Expand Down
5 changes: 5 additions & 0 deletions src/primitives/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include "serialize.h"
#include "uint256.h"

namespace Consensus {
struct Params;
}

/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
* requirements. When they solve the proof-of-work, they broadcast the block
Expand Down Expand Up @@ -60,6 +64,7 @@ class CBlockHeader
return (nBits == 0);
}

uint256 GetHash(const Consensus::Params&) const;
uint256 GetHash() const;

int64_t GetBlockTime() const
Expand Down
4 changes: 4 additions & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2989,6 +2989,10 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60)
return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");

if (consensusParams.PowAlgorithmForTime(block.GetBlockTime()) != consensusParams.PowAlgorithmForTime(pindexPrev->GetBlockTime()) && block.GetBlockTime() < pindexPrev->GetBlockTime()) {
return state.Invalid(false, REJECT_INVALID, "pow-reversed", "cannot reverse PoW change");
}

// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
// check for version 2, 3 and 4 upgrades
if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
Expand Down