aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/chainparams.cpp7
-rw-r--r--src/chainparams.h5
-rw-r--r--src/main.cpp113
-rw-r--r--src/main.h10
-rw-r--r--src/miner.cpp1
-rw-r--r--src/pow.cpp119
-rw-r--r--src/pow.h23
-rw-r--r--src/rpcmining.cpp1
-rw-r--r--src/test/DoS_tests.cpp1
-rw-r--r--src/txdb.cpp5
11 files changed, 163 insertions, 124 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ecded442c..7e7fa0c3ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -71,6 +71,7 @@ BITCOIN_CORE_H = \
netbase.h \
net.h \
noui.h \
+ pow.h \
protocol.h \
rpcclient.h \
rpcprotocol.h \
@@ -121,6 +122,7 @@ libbitcoin_server_a_SOURCES = \
miner.cpp \
net.cpp \
noui.cpp \
+ pow.cpp \
rpcblockchain.cpp \
rpcmining.cpp \
rpcmisc.cpp \
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index afbae6fc57..eb56af750e 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -117,6 +117,8 @@ public:
nRejectBlockOutdatedMajority = 950;
nToCheckBlockUpgradeMajority = 1000;
nMinerThreads = 0;
+ nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
+ nTargetSpacing = 10 * 60;
// Build the genesis block. Note that the output of the genesis coinbase cannot
// be spent as it did not originally exist in the database.
@@ -204,6 +206,9 @@ public:
nEnforceBlockUpgradeMajority = 51;
nRejectBlockOutdatedMajority = 75;
nToCheckBlockUpgradeMajority = 100;
+ nMinerThreads = 0;
+ nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
+ nTargetSpacing = 10 * 60;
strDataDir = "testnet3";
// Modify the testnet genesis block so the timestamp is valid for a later start.
@@ -251,6 +256,8 @@ public:
nRejectBlockOutdatedMajority = 950;
nToCheckBlockUpgradeMajority = 1000;
nMinerThreads = 1;
+ nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
+ nTargetSpacing = 10 * 60;
bnProofOfWorkLimit = ~uint256(0) >> 1;
genesis.nTime = 1296688602;
genesis.nBits = 0x207fffff;
diff --git a/src/chainparams.h b/src/chainparams.h
index c0a6ebda6b..e9774bbfa2 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -70,6 +70,9 @@ public:
bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; }
/* Make standard checks */
bool RequireStandard() const { return fRequireStandard; }
+ int64_t TargetTimespan() const { return nTargetTimespan; }
+ int64_t TargetSpacing() const { return nTargetSpacing; }
+ int64_t Interval() const { return nTargetTimespan / nTargetSpacing; }
const std::string& DataDir() const { return strDataDir; }
/* Make miner stop after a block is found. In RPC, don't return
* until nGenProcLimit blocks are generated */
@@ -95,6 +98,8 @@ protected:
int nEnforceBlockUpgradeMajority;
int nRejectBlockOutdatedMajority;
int nToCheckBlockUpgradeMajority;
+ int64_t nTargetTimespan;
+ int64_t nTargetSpacing;
std::string strDataDir;
int nMinerThreads;
std::vector<CDNSSeedData> vSeeds;
diff --git a/src/main.cpp b/src/main.cpp
index d3f04b95fa..ea47601081 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -12,6 +12,7 @@
#include "checkqueue.h"
#include "init.h"
#include "net.h"
+#include "pow.h"
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
@@ -1194,118 +1195,6 @@ int64_t GetBlockValue(int nHeight, int64_t nFees)
return nSubsidy + nFees;
}
-static const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
-static const int64_t nTargetSpacing = 10 * 60;
-static const int64_t nInterval = nTargetTimespan / nTargetSpacing;
-
-//
-// minimum amount of work that could possibly be required nTime after
-// minimum work required was nBase
-//
-unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
-{
- const uint256 &bnLimit = Params().ProofOfWorkLimit();
- // Testnet has min-difficulty blocks
- // after nTargetSpacing*2 time between blocks:
- if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2)
- return bnLimit.GetCompact();
-
- uint256 bnResult;
- bnResult.SetCompact(nBase);
- while (nTime > 0 && bnResult < bnLimit)
- {
- // Maximum 400% adjustment...
- bnResult *= 4;
- // ... in best-case exactly 4-times-normal target time
- nTime -= nTargetTimespan*4;
- }
- if (bnResult > bnLimit)
- bnResult = bnLimit;
- return bnResult.GetCompact();
-}
-
-unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
-{
- unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact();
-
- // Genesis block
- if (pindexLast == NULL)
- return nProofOfWorkLimit;
-
- // Only change once per interval
- if ((pindexLast->nHeight+1) % nInterval != 0)
- {
- if (Params().AllowMinDifficultyBlocks())
- {
- // Special difficulty rule for testnet:
- // If the new block's timestamp is more than 2* 10 minutes
- // then allow mining of a min-difficulty block.
- if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2)
- return nProofOfWorkLimit;
- else
- {
- // Return the last non-special-min-difficulty-rules-block
- const CBlockIndex* pindex = pindexLast;
- while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit)
- pindex = pindex->pprev;
- return pindex->nBits;
- }
- }
- return pindexLast->nBits;
- }
-
- // Go back by what we want to be 14 days worth of blocks
- const CBlockIndex* pindexFirst = pindexLast;
- for (int i = 0; pindexFirst && i < nInterval-1; i++)
- pindexFirst = pindexFirst->pprev;
- assert(pindexFirst);
-
- // Limit adjustment step
- int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
- LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
- if (nActualTimespan < nTargetTimespan/4)
- nActualTimespan = nTargetTimespan/4;
- if (nActualTimespan > nTargetTimespan*4)
- nActualTimespan = nTargetTimespan*4;
-
- // Retarget
- uint256 bnNew;
- uint256 bnOld;
- bnNew.SetCompact(pindexLast->nBits);
- bnOld = bnNew;
- bnNew *= nActualTimespan;
- bnNew /= nTargetTimespan;
-
- if (bnNew > Params().ProofOfWorkLimit())
- bnNew = Params().ProofOfWorkLimit();
-
- /// debug print
- LogPrintf("GetNextWorkRequired RETARGET\n");
- LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan);
- LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString());
- LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());
-
- return bnNew.GetCompact();
-}
-
-bool CheckProofOfWork(uint256 hash, unsigned int nBits)
-{
- bool fNegative;
- bool fOverflow;
- uint256 bnTarget;
- bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
-
- // Check range
- if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
- return error("CheckProofOfWork() : nBits below minimum work");
-
- // Check proof of work matches claimed amount
- if (hash > bnTarget)
- return error("CheckProofOfWork() : hash doesn't match nBits");
-
- return true;
-}
-
bool IsInitialBlockDownload()
{
LOCK(cs_main);
diff --git a/src/main.h b/src/main.h
index 27041a0026..9858bcfd69 100644
--- a/src/main.h
+++ b/src/main.h
@@ -146,10 +146,6 @@ bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
/** Run an instance of the script checking thread */
void ThreadScriptCheck();
-/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
-bool CheckProofOfWork(uint256 hash, unsigned int nBits);
-/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */
-unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime);
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core */
@@ -159,7 +155,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b
/** Find the best known block, and make it the tip of the block chain */
bool ActivateBestChain(CValidationState &state);
int64_t GetBlockValue(int nHeight, int64_t nFees);
-unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock);
void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev);
@@ -812,11 +807,6 @@ public:
return (~bnTarget / (bnTarget + 1)) + 1;
}
- bool CheckIndex() const
- {
- return CheckProofOfWork(GetBlockHash(), nBits);
- }
-
enum { nMedianTimeSpan=11 };
int64_t GetMedianTimePast() const
diff --git a/src/miner.cpp b/src/miner.cpp
index 6b1f58b229..19b4694357 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -9,6 +9,7 @@
#include "hash.h"
#include "main.h"
#include "net.h"
+#include "pow.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
diff --git a/src/pow.cpp b/src/pow.cpp
new file mode 100644
index 0000000000..952250decd
--- /dev/null
+++ b/src/pow.cpp
@@ -0,0 +1,119 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "pow.h"
+
+#include "chainparams.h"
+#include "core.h"
+#include "main.h"
+#include "uint256.h"
+
+unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
+{
+ unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact();
+
+ // Genesis block
+ if (pindexLast == NULL)
+ return nProofOfWorkLimit;
+
+ // Only change once per interval
+ if ((pindexLast->nHeight+1) % Params().Interval() != 0)
+ {
+ if (Params().AllowMinDifficultyBlocks())
+ {
+ // Special difficulty rule for testnet:
+ // If the new block's timestamp is more than 2* 10 minutes
+ // then allow mining of a min-difficulty block.
+ if (pblock->nTime > pindexLast->nTime + Params().TargetSpacing()*2)
+ return nProofOfWorkLimit;
+ else
+ {
+ // Return the last non-special-min-difficulty-rules-block
+ const CBlockIndex* pindex = pindexLast;
+ while (pindex->pprev && pindex->nHeight % Params().Interval() != 0 && pindex->nBits == nProofOfWorkLimit)
+ pindex = pindex->pprev;
+ return pindex->nBits;
+ }
+ }
+ return pindexLast->nBits;
+ }
+
+ // Go back by what we want to be 14 days worth of blocks
+ const CBlockIndex* pindexFirst = pindexLast;
+ for (int i = 0; pindexFirst && i < Params().Interval()-1; i++)
+ pindexFirst = pindexFirst->pprev;
+ assert(pindexFirst);
+
+ // Limit adjustment step
+ int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
+ LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
+ if (nActualTimespan < Params().TargetTimespan()/4)
+ nActualTimespan = Params().TargetTimespan()/4;
+ if (nActualTimespan > Params().TargetTimespan()*4)
+ nActualTimespan = Params().TargetTimespan()*4;
+
+ // Retarget
+ uint256 bnNew;
+ uint256 bnOld;
+ bnNew.SetCompact(pindexLast->nBits);
+ bnOld = bnNew;
+ bnNew *= nActualTimespan;
+ bnNew /= Params().TargetTimespan();
+
+ if (bnNew > Params().ProofOfWorkLimit())
+ bnNew = Params().ProofOfWorkLimit();
+
+ /// debug print
+ LogPrintf("GetNextWorkRequired RETARGET\n");
+ LogPrintf("Params().TargetTimespan() = %d nActualTimespan = %d\n", Params().TargetTimespan(), nActualTimespan);
+ LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString());
+ LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());
+
+ return bnNew.GetCompact();
+}
+
+bool CheckProofOfWork(uint256 hash, unsigned int nBits)
+{
+ bool fNegative;
+ bool fOverflow;
+ uint256 bnTarget;
+ bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
+
+ // Check range
+ if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
+ return error("CheckProofOfWork() : nBits below minimum work");
+
+ // Check proof of work matches claimed amount
+ if (hash > bnTarget)
+ return error("CheckProofOfWork() : hash doesn't match nBits");
+
+ return true;
+}
+
+//
+// minimum amount of work that could possibly be required nTime after
+// minimum work required was nBase
+//
+unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
+{
+ const uint256 &bnLimit = Params().ProofOfWorkLimit();
+ // Testnet has min-difficulty blocks
+ // after Params().TargetSpacing()*2 time between blocks:
+ if (Params().AllowMinDifficultyBlocks() && nTime > Params().TargetSpacing()*2)
+ return bnLimit.GetCompact();
+
+ uint256 bnResult;
+ bnResult.SetCompact(nBase);
+ while (nTime > 0 && bnResult < bnLimit)
+ {
+ // Maximum 400% adjustment...
+ bnResult *= 4;
+ // ... in best-case exactly 4-times-normal target time
+ nTime -= Params().TargetTimespan()*4;
+ }
+ if (bnResult > bnLimit)
+ bnResult = bnLimit;
+ return bnResult.GetCompact();
+}
diff --git a/src/pow.h b/src/pow.h
new file mode 100644
index 0000000000..0ce5b48766
--- /dev/null
+++ b/src/pow.h
@@ -0,0 +1,23 @@
+
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_POW_H
+#define BITCOIN_POW_H
+
+#include <stdint.h>
+
+class CBlockIndex;
+class CBlockHeader;
+class uint256;
+
+unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock);
+
+/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
+bool CheckProofOfWork(uint256 hash, unsigned int nBits);
+/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */
+unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime);
+
+#endif
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index a1410f0e41..f60070eb5b 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -9,6 +9,7 @@
#include "net.h"
#include "main.h"
#include "miner.h"
+#include "pow.h"
#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 3a45844411..d512053051 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -11,6 +11,7 @@
#include "keystore.h"
#include "main.h"
#include "net.h"
+#include "pow.h"
#include "script.h"
#include "serialize.h"
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 4eab8525a5..92137f71ff 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -6,6 +6,7 @@
#include "txdb.h"
#include "core.h"
+#include "pow.h"
#include "uint256.h"
#include <stdint.h>
@@ -212,8 +213,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
- if (!pindexNew->CheckIndex())
- return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString());
+ if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
+ return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());
pcursor->Next();
} else {