diff options
| author | Daniel Kraft <[email protected]> | 2014-11-12 13:56:22 +0100 |
|---|---|---|
| committer | Ross Nicoll <[email protected]> | 2015-07-05 18:45:24 +0100 |
| commit | eabf633f13bef26d5775f00b9c5c59d72ad232cf (patch) | |
| tree | aadb413abd944ed8b996ef9d65e8e26b20ac6249 /src/main.cpp | |
| parent | [tests] fix partition alerts for Dogecoin (diff) | |
| download | discoin-eabf633f13bef26d5775f00b9c5c59d72ad232cf.tar.xz discoin-eabf633f13bef26d5775f00b9c5c59d72ad232cf.zip | |
Merge AuxPoW support from Namecore
Includes the following commits:
commit 2ea1b5cd8cf2bdd08e43ae39fb76352eebe14895
commit f2a8220c34275f022f02d81e9e84d4cec33bd51c
commit 84b8b56113e6057b0253475b83e797dc1fed2eed
commit 8471d5db221f145f5a40022ed1897c1b996b628e
commit 2f125ad0a67e1b8f71b18a14a3b41d7e577391d1
commit e01dbc3608703b4cb4e9882738125f2b7816cdb8
commit f0421312631cd44669f9f84d339a0c470b4423b9
commit 1fd522db5dfddfd0e1b0c794b82fae2cc7bdb099
commit 71f63ad99f70ff6461c795fd728aea16aa1008f8
commit a7c44d98a8ded4df0e8455c4c5629b1a5b303bbf
commit e1d7b4fc15addf3dfeb3853fa66230a8bdacd75f
commit d016f2fa02572fd340129176b942b3f19bd5260b
commit f4716e5a168a697afce854a37350fdae0988bdd8
commit 03a575e3b13bf06cbb0a007d6672b05d2085c26e
commit d7ea37444bd9e9ac461a3dda0b16afefd160b062
commit db22affa01e050ff847a12e20c83b88952d80b59
commit 9b7e14986655f914b2d0903ca1d79367c92c6c7e
commit e21034f9c124893d5b9631e9ca231b0b9ede3d52
Changes are as below:
Wrap CBlockHeader::nVersion into a new class (CBlockVersion). This allows to take care of interpreting the field into a base version, auxpow flag and the chain ID.
Update getauxblock.py for new 'generate' RPC call.
Add 'auxpow' to block JSON.
Accept auxpow as PoW verification.
Add unit tests for auxpow verification.
Add check for memory-layout of CBlockVersion.
Weaken auxpow chain ID checks for the testnet.
Allow Params() to overrule when to check the auxpow chain ID and for legacy blocks. Use this to disable the checks on testnet.
Introduce CPureBlockHeader.
Split the block header part that is used by auxpow and the "real" block header (that uses auxpow) to resolve the cyclic dependency between the two.
Differentiate between uint256 and arith_uint256.
This change was done upstream, modify the auxpow code.
Add missing lock in auxpow_tests.
Fix REST header check for auxpow headers.
Those can be longer, thus take that into account. Also perform the check actually on an auxpow header.
Correctly set the coinbase for getauxblock results.
Call IncrementExtraNonce in getauxblock so that the coinbase is actually initialised with the stuff it should be. (BIP30 block height and COINBASE_FLAGS.)
Implement getauxblock plus regression test.
Turn auxpow test into FIXTURE test.
This allows using of the Params() calls.
Move CMerkleTx code to auxpow.cpp.
Otherwise we get linker errors when building without wallet.
Fix rebase with BIP66.
Update the code to handle BIP66's nVersion=3.
Enforce that auxpow parent blocks have no auxpow block version.
This is for compatibility with namecoind. See also https://github.com/namecoin/namecoin/pull/199.
Move auxpow-related parameters to Consensus::Params.
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 95 |
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; } |