aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp95
1 files changed, 84 insertions, 11 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 91d89cea7..4046330e9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -8,6 +8,7 @@
#include "addrman.h"
#include "alert.h"
#include "arith_uint256.h"
+#include "auxpow.h"
#include "chainparams.h"
#include "checkpoints.h"
#include "checkqueue.h"
@@ -1138,6 +1139,51 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex
//
+bool CheckProofOfWork(const CBlockHeader& block, const Consensus::Params& params)
+{
+ /* Except for legacy blocks with full version 1, ensure that
+ the chain ID is correct. Legacy blocks are not allowed since
+ the merge-mining start, which is checked in AcceptBlockHeader
+ where the height is known. */
+ if (!block.nVersion.IsLegacy() && params.fStrictChainId
+ && block.nVersion.GetChainId() != params.nAuxpowChainId)
+ return error("%s : block does not have our chain ID"
+ " (got %d, expected %d, full nVersion %d)",
+ __func__, block.nVersion.GetChainId(),
+ params.nAuxpowChainId, block.nVersion.GetFullVersion());
+
+ /* If there is no auxpow, just check the block hash. */
+ if (!block.auxpow)
+ {
+ if (block.nVersion.IsAuxpow())
+ return error("%s : no auxpow on block with auxpow version",
+ __func__);
+
+ if (!CheckProofOfWork(block.GetHash(), block.nBits, params))
+ return error("%s : non-AUX proof of work failed", __func__);
+
+ return true;
+ }
+
+ /* We have auxpow. Check it. */
+
+ if (!block.nVersion.IsAuxpow())
+ return error("%s : auxpow on block with non-auxpow version", __func__);
+
+ /* Temporary check: Disallow parent blocks with auxpow version. This is
+ for compatibility with the old client. */
+ /* FIXME: Remove this check with a hardfork later on. */
+ if (block.auxpow->getParentBlock().nVersion.IsAuxpow())
+ return error("%s : auxpow parent block has auxpow version", __func__);
+
+ if (!block.auxpow->check(block.GetHash(), block.nVersion.GetChainId(), params))
+ return error("%s : AUX POW is not valid", __func__);
+ if (!CheckProofOfWork(block.auxpow->getParentBlockHash(), block.nBits, params))
+ return error("%s : AUX proof of work failed", __func__);
+
+ return true;
+}
+
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
{
// Open history file to append
@@ -1159,7 +1205,11 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::M
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
+/* Generic implementation of block reading that can handle
+ both a block and its header. */
+
+template<typename T>
+static bool ReadBlockOrHeader(T& block, const CDiskBlockPos& pos)
{
block.SetNull();
@@ -1177,15 +1227,16 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
}
// Check the header
- if (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
+ if (!CheckProofOfWork(block, Params().GetConsensus()))
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
+template<typename T>
+static bool ReadBlockOrHeader(T& block, const CBlockIndex* pindex)
{
- if (!ReadBlockFromDisk(block, pindex->GetBlockPos()))
+ if (!ReadBlockOrHeader(block, pindex->GetBlockPos()))
return false;
if (block.GetHash() != pindex->GetBlockHash())
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
@@ -1193,6 +1244,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
return true;
}
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
+{
+ return ReadBlockOrHeader(block, pos);
+}
+
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
+{
+ return ReadBlockOrHeader(block, pindex);
+}
+
+bool ReadBlockHeaderFromDisk(CBlockHeader& block, const CBlockIndex* pindex)
+{
+ return ReadBlockOrHeader(block, pindex);
+}
+
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
@@ -1829,7 +1895,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.GetBaseVersion() >= 3 && IsSuperMajority(3, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
flags |= SCRIPT_VERIFY_DERSIG;
}
@@ -2091,7 +2157,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
const CBlockIndex* pindex = chainActive.Tip();
for (int i = 0; i < 100 && pindex != NULL; i++)
{
- if (pindex->nVersion > CBlock::CURRENT_VERSION)
+ if (pindex->nVersion.GetBaseVersion() > CBlock::CURRENT_VERSION)
++nUpgraded;
pindex = pindex->pprev;
}
@@ -2646,7 +2712,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 && !CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus()))
+ if (fCheckPOW && !CheckProofOfWork(block, Params().GetConsensus()))
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
REJECT_INVALID, "high-hash");
@@ -2730,6 +2796,13 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight+1;
+ // Disallow legacy blocks after merge-mining start.
+ if (!Params().GetConsensus().AllowLegacyBlocks(nHeight)
+ && block.nVersion.IsLegacy())
+ return state.DoS(100, error("%s : legacy block after auxpow start",
+ __func__),
+ 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__),
@@ -2754,12 +2827,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
}
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
- if (block.nVersion < 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
+ if (block.nVersion.GetBaseVersion() < 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
return state.Invalid(error("%s: rejected nVersion=1 block", __func__),
REJECT_OBSOLETE, "bad-version");
// Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded:
- if (block.nVersion < 3 && IsSuperMajority(3, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
+ if (block.nVersion.GetBaseVersion() < 3 && IsSuperMajority(3, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
return state.Invalid(error("%s : rejected nVersion=2 block", __func__),
REJECT_OBSOLETE, "bad-version");
@@ -2779,7 +2852,7 @@ 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))
+ if (block.nVersion.GetBaseVersion() >= 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))
{
CScript expect = CScript() << nHeight;
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
@@ -2897,7 +2970,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
unsigned int nFound = 0;
for (int i = 0; i < consensusParams.nMajorityWindow && nFound < nRequired && pstart != NULL; i++)
{
- if (pstart->nVersion >= minVersion)
+ if (pstart->nVersion.GetBaseVersion() >= minVersion)
++nFound;
pstart = pstart->pprev;
}