aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bloom.h2
-rw-r--r--src/chainparams.cpp3
-rw-r--r--src/chainparamsbase.cpp3
-rw-r--r--src/core.cpp4
-rw-r--r--src/core.h48
-rw-r--r--src/db.cpp2
-rw-r--r--src/init.cpp12
-rw-r--r--src/key.h2
-rw-r--r--src/main.cpp276
-rw-r--r--src/main.h81
-rw-r--r--src/miner.cpp4
-rw-r--r--src/net.cpp2
-rw-r--r--src/pow.cpp48
-rw-r--r--src/pow.h8
-rw-r--r--src/protocol.h1
-rw-r--r--src/qt/clientmodel.cpp8
-rw-r--r--src/qt/splashscreen.cpp1
-rw-r--r--src/rpcblockchain.cpp10
-rw-r--r--src/rpcdump.cpp6
-rw-r--r--src/rpcmining.cpp2
-rw-r--r--src/sync.cpp3
-rw-r--r--src/test/DoS_tests.cpp6
-rw-r--r--src/test/multisig_tests.cpp4
-rw-r--r--src/txmempool.cpp7
-rw-r--r--src/ui_interface.h6
-rw-r--r--src/version.h2
-rw-r--r--src/wallet.cpp99
-rw-r--r--src/wallet.h58
28 files changed, 313 insertions, 395 deletions
diff --git a/src/bloom.h b/src/bloom.h
index d0caf9e9fa..54d16d7126 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -60,7 +60,7 @@ public:
// It should generally always be a random value (and is largely only exposed for unit testing)
// nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK)
CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn);
- CBloomFilter() : isFull(true) {}
+ CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {}
IMPLEMENT_SERIALIZE
(
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index f32d4ed235..ce99f268f3 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -5,10 +5,11 @@
#include "chainparams.h"
-#include "assert.h"
#include "random.h"
#include "util.h"
+#include <assert.h>
+
#include <boost/assign/list_of.hpp>
using namespace std;
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 720e24c4a8..d1e19871c3 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -5,9 +5,10 @@
#include "chainparamsbase.h"
-#include "assert.h"
#include "util.h"
+#include <assert.h>
+
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
diff --git a/src/core.cpp b/src/core.cpp
index 71d6fea610..e6636ae04f 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -12,14 +12,14 @@ std::string COutPoint::ToString() const
return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);
}
-CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, unsigned int nSequenceIn)
+CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn)
{
prevout = prevoutIn;
scriptSig = scriptSigIn;
nSequence = nSequenceIn;
}
-CTxIn::CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn, unsigned int nSequenceIn)
+CTxIn::CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn)
{
prevout = COutPoint(hashPrevTx, nOut);
scriptSig = scriptSigIn;
diff --git a/src/core.h b/src/core.h
index e3ceac97aa..126e1baa98 100644
--- a/src/core.h
+++ b/src/core.h
@@ -26,13 +26,13 @@ class COutPoint
{
public:
uint256 hash;
- unsigned int n;
+ uint32_t n;
COutPoint() { SetNull(); }
- COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
+ COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; }
IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { hash = 0; n = (unsigned int) -1; }
- bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }
+ void SetNull() { hash = 0; n = (uint32_t) -1; }
+ bool IsNull() const { return (hash == 0 && n == (uint32_t) -1); }
friend bool operator<(const COutPoint& a, const COutPoint& b)
{
@@ -57,12 +57,12 @@ class CInPoint
{
public:
const CTransaction* ptx;
- unsigned int n;
+ uint32_t n;
CInPoint() { SetNull(); }
- CInPoint(const CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
- void SetNull() { ptx = NULL; n = (unsigned int) -1; }
- bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
+ CInPoint(const CTransaction* ptxIn, uint32_t nIn) { ptx = ptxIn; n = nIn; }
+ void SetNull() { ptx = NULL; n = (uint32_t) -1; }
+ bool IsNull() const { return (ptx == NULL && n == (uint32_t) -1); }
};
/** An input of a transaction. It contains the location of the previous
@@ -74,15 +74,15 @@ class CTxIn
public:
COutPoint prevout;
CScript scriptSig;
- unsigned int nSequence;
+ uint32_t nSequence;
CTxIn()
{
nSequence = std::numeric_limits<unsigned int>::max();
}
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max());
- CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max());
+ explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max());
+ CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<uint32_t>::max());
IMPLEMENT_SERIALIZE
(
@@ -93,7 +93,7 @@ public:
bool IsFinal() const
{
- return (nSequence == std::numeric_limits<unsigned int>::max());
+ return (nSequence == std::numeric_limits<uint32_t>::max());
}
friend bool operator==(const CTxIn& a, const CTxIn& b)
@@ -217,17 +217,17 @@ private:
void UpdateHash() const;
public:
- static const int CURRENT_VERSION=1;
+ static const int32_t CURRENT_VERSION=1;
// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not
// actually immutable; deserialization and assignment are implemented,
// and bypass the constness. This is safe, as they update the entire
// structure, including the hash.
- const int nVersion;
+ const int32_t nVersion;
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
- const unsigned int nLockTime;
+ const uint32_t nLockTime;
/** Construct a CTransaction that qualifies as IsNull() */
CTransaction();
@@ -238,11 +238,11 @@ public:
CTransaction& operator=(const CTransaction& tx);
IMPLEMENT_SERIALIZE(
- READWRITE(*const_cast<int*>(&this->nVersion));
+ READWRITE(*const_cast<int32_t*>(&this->nVersion));
nVersion = this->nVersion;
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
- READWRITE(*const_cast<unsigned int*>(&nLockTime));
+ READWRITE(*const_cast<uint32_t*>(&nLockTime));
if (fRead)
UpdateHash();
)
@@ -284,10 +284,10 @@ public:
/** A mutable version of CTransaction. */
struct CMutableTransaction
{
- int nVersion;
+ int32_t nVersion;
std::vector<CTxIn> vin;
std::vector<CTxOut> vout;
- unsigned int nLockTime;
+ uint32_t nLockTime;
CMutableTransaction();
CMutableTransaction(const CTransaction& tx);
@@ -399,13 +399,13 @@ class CBlockHeader
{
public:
// header
- static const int CURRENT_VERSION=2;
- int nVersion;
+ static const int32_t CURRENT_VERSION=2;
+ int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
+ uint32_t nTime;
+ uint32_t nBits;
+ uint32_t nNonce;
CBlockHeader()
{
diff --git a/src/db.cpp b/src/db.cpp
index 8c139843a1..23d2cc988d 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -227,10 +227,10 @@ CDB::CDB(const char *pszFile, const char* pszMode) :
pdb(NULL), activeTxn(NULL)
{
int ret;
+ fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
if (pszFile == NULL)
return;
- fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
bool fCreate = strchr(pszMode, 'c');
unsigned int nFlags = DB_THREAD;
if (fCreate)
diff --git a/src/init.cpp b/src/init.cpp
index 7b1318654f..b8988f8b75 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -35,6 +35,7 @@
#include "compat/sanity.h"
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/thread.hpp>
@@ -369,6 +370,14 @@ std::string LicenseInfo()
"\n";
}
+static void BlockNotifyCallback(const uint256& hashNewTip)
+{
+ std::string strCmd = GetArg("-blocknotify", "");
+
+ boost::replace_all(strCmd, "%s", hashNewTip.GetHex());
+ boost::thread t(runCommand, strCmd); // thread runs free
+}
+
struct CImportingNow
{
CImportingNow() {
@@ -1185,6 +1194,9 @@ bool AppInit2(boost::thread_group& threadGroup)
#endif // !ENABLE_WALLET
// ********************************************************* Step 9: import blocks
+ if (mapArgs.count("-blocknotify"))
+ uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);
+
// scan for better chains in the block chain database, that are not yet connected in the active best chain
CValidationState state;
if (!ActivateBestChain(state))
diff --git a/src/key.h b/src/key.h
index 11dc65de8c..1de83cc738 100644
--- a/src/key.h
+++ b/src/key.h
@@ -189,7 +189,7 @@ private:
public:
// Construct an invalid private key.
- CKey() : fValid(false) {
+ CKey() : fValid(false), fCompressed(false) {
LockObject(vch);
}
diff --git a/src/main.cpp b/src/main.cpp
index de5730a388..4aebdadd3b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -20,7 +20,6 @@
#include <sstream>
-#include <boost/dynamic_bitset.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@@ -733,53 +732,6 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}
-int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
-{
- AssertLockHeld(cs_main);
- CBlock blockTmp;
-
- if (pblock == NULL) {
- CCoins coins;
- if (pcoinsTip->GetCoins(GetHash(), coins)) {
- CBlockIndex *pindex = chainActive[coins.nHeight];
- if (pindex) {
- if (!ReadBlockFromDisk(blockTmp, pindex))
- return 0;
- pblock = &blockTmp;
- }
- }
- }
-
- if (pblock) {
- // Update the tx's hashBlock
- hashBlock = pblock->GetHash();
-
- // Locate the transaction
- for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
- if (pblock->vtx[nIndex] == *(CTransaction*)this)
- break;
- if (nIndex == (int)pblock->vtx.size())
- {
- vMerkleBranch.clear();
- nIndex = -1;
- LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
- return 0;
- }
-
- // Fill in merkle branch
- vMerkleBranch = pblock->GetMerkleBranch(nIndex);
- }
-
- // Is the tx in a block that's in the main chain
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi == mapBlockIndex.end())
- return 0;
- CBlockIndex* pindex = (*mi).second;
- if (!pindex || !chainActive.Contains(pindex))
- return 0;
-
- return chainActive.Height() - pindex->nHeight + 1;
-}
@@ -1029,58 +981,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return true;
}
-
-int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
-{
- if (hashBlock == 0 || nIndex == -1)
- return 0;
- AssertLockHeld(cs_main);
-
- // Find the block it claims to be in
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi == mapBlockIndex.end())
- return 0;
- CBlockIndex* pindex = (*mi).second;
- if (!pindex || !chainActive.Contains(pindex))
- return 0;
-
- // Make sure the merkle branch connects to this block
- if (!fMerkleVerified)
- {
- if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
- return 0;
- fMerkleVerified = true;
- }
-
- pindexRet = pindex;
- return chainActive.Height() - pindex->nHeight + 1;
-}
-
-int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
-{
- AssertLockHeld(cs_main);
- int nResult = GetDepthInMainChainINTERNAL(pindexRet);
- if (nResult == 0 && !mempool.exists(GetHash()))
- return -1; // Not in chain, not in mempool
-
- return nResult;
-}
-
-int CMerkleTx::GetBlocksToMaturity() const
-{
- if (!IsCoinBase())
- return 0;
- return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
-}
-
-
-bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee)
-{
- CValidationState state;
- return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee);
-}
-
-
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{
@@ -1388,10 +1288,8 @@ void Misbehaving(NodeId pnode, int howmuch)
void static InvalidChainFound(CBlockIndex* pindexNew)
{
if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
- {
pindexBestInvalid = pindexNew;
- uiInterface.NotifyBlocksChanged();
- }
+
LogPrintf("InvalidChainFound: invalid block=%s height=%d log2_work=%.8g date=%s\n",
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
@@ -1421,25 +1319,6 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
}
}
-void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
-{
- block.nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
-
- // Updating time can change work required on testnet:
- if (Params().AllowMinDifficultyBlocks())
- block.nBits = GetNextWorkRequired(pindexPrev, &block);
-}
-
-
-
-
-
-
-
-
-
-
-
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight)
{
bool ret;
@@ -1976,15 +1855,19 @@ static int64_t nTimeFlush = 0;
static int64_t nTimeChainState = 0;
static int64_t nTimePostConnect = 0;
-// Connect a new block to chainActive.
-bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
+// Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
+// corresponding to pindexNew, to bypass loading it again from disk.
+bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
// Read block from disk.
int64_t nTime1 = GetTimeMicros();
CBlock block;
- if (!ReadBlockFromDisk(block, pindexNew))
- return state.Abort(_("Failed to read block"));
+ if (!pblock) {
+ if (!ReadBlockFromDisk(block, pindexNew))
+ return state.Abort(_("Failed to read block"));
+ pblock = &block;
+ }
// Apply the block atomically to the chain state.
int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1;
int64_t nTime3;
@@ -1992,7 +1875,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
{
CCoinsViewCache view(*pcoinsTip, true);
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
- if (!ConnectBlock(block, state, pindexNew, view)) {
+ if (!ConnectBlock(*pblock, state, pindexNew, view)) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
return error("ConnectTip() : ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
@@ -2011,7 +1894,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
// Remove conflicting transactions from the mempool.
list<CTransaction> txConflicted;
- mempool.removeForBlock(block.vtx, pindexNew->nHeight, txConflicted);
+ mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted);
mempool.check(pcoinsTip);
// Update chainActive & related variables.
UpdateTip(pindexNew);
@@ -2021,8 +1904,8 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
SyncWithWallets(tx, NULL);
}
// ... and about transactions that got confirmed:
- BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- SyncWithWallets(tx, &block);
+ BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
+ SyncWithWallets(tx, pblock);
}
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
@@ -2071,7 +1954,8 @@ static CBlockIndex* FindMostWorkChain() {
}
// Try to make some progress towards making pindexMostWork the active block.
-static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) {
+// pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
+static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
AssertLockHeld(cs_main);
bool fInvalidFound = false;
const CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -2086,14 +1970,15 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
// Build list of new blocks to connect.
std::vector<CBlockIndex*> vpindexToConnect;
vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1));
- while (pindexMostWork && pindexMostWork != pindexFork) {
- vpindexToConnect.push_back(pindexMostWork);
- pindexMostWork = pindexMostWork->pprev;
+ CBlockIndex *pindexIter = pindexMostWork;
+ while (pindexIter && pindexIter != pindexFork) {
+ vpindexToConnect.push_back(pindexIter);
+ pindexIter = pindexIter->pprev;
}
// Connect new blocks.
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
- if (!ConnectTip(state, pindexConnect)) {
+ if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
@@ -2134,7 +2019,10 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
return true;
}
-bool ActivateBestChain(CValidationState &state) {
+// Make the best chain active, in multiple steps. The result is either failure
+// or an activated best chain. pblock is either NULL or a pointer to a block
+// that is already loaded (to avoid loading it again from disk).
+bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL;
do {
@@ -2149,7 +2037,7 @@ bool ActivateBestChain(CValidationState &state) {
if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip())
return true;
- if (!ActivateBestChainStep(state, pindexMostWork))
+ if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL))
return false;
pindexNewTip = chainActive.Tip();
@@ -2162,18 +2050,15 @@ bool ActivateBestChain(CValidationState &state) {
uint256 hashNewTip = pindexNewTip->GetBlockHash();
// Relay inventory, but don't relay old inventory during initial block download.
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
+ {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
-
- std::string strCmd = GetArg("-blocknotify", "");
- if (!strCmd.empty()) {
- boost::replace_all(strCmd, "%s", hashNewTip.GetHex());
- boost::thread t(runCommand, strCmd); // thread runs free
}
+
+ uiInterface.NotifyBlockTip(hashNewTip);
}
- uiInterface.NotifyBlocksChanged();
} while(pindexMostWork != chainActive.Tip());
return true;
@@ -2427,12 +2312,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
REJECT_CHECKPOINT, "time-too-old");
}
- bool fOverflow = false;
- uint256 bnNewBlock;
- bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow);
- uint256 bnRequired;
- bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
- if (fOverflow || bnNewBlock > bnRequired)
+ if (!CheckMinWork(block.nBits, pcheckpoint->nBits, deltaTime))
{
return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
REJECT_INVALID, "bad-diffbits");
@@ -2697,7 +2577,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
}
- if (!ActivateBestChain(state))
+ if (!ActivateBestChain(state, pblock))
return error("ProcessBlock() : ActivateBestChain failed");
return true;
@@ -3137,7 +3017,7 @@ bool InitBlockIndex() {
CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("LoadBlockIndex() : genesis block not accepted");
- if (!ActivateBestChain(state))
+ if (!ActivateBestChain(state, &block))
return error("LoadBlockIndex() : genesis block cannot be activated");
} catch(std::runtime_error &e) {
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
@@ -3289,15 +3169,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
return nLoaded > 0;
}
-
-
-
-
-
-
-
-
-
//////////////////////////////////////////////////////////////////////////////
//
// CAlert
@@ -3519,75 +3390,6 @@ void static ProcessGetData(CNode* pfrom)
}
}
-struct CCoin {
- uint32_t nTxVer; // Don't call this nVersion, that name has a special meaning inside IMPLEMENT_SERIALIZE
- uint32_t nHeight;
- CTxOut out;
-
- IMPLEMENT_SERIALIZE(
- READWRITE(nTxVer);
- READWRITE(nHeight);
- READWRITE(out);
- )
-};
-
-bool ProcessGetUTXOs(const vector<COutPoint> &vOutPoints, bool fCheckMemPool, vector<unsigned char> *result, vector<CCoin> *resultCoins)
-{
- // Defined by BIP 64.
- //
- // Allows a peer to retrieve the CTxOut structures corresponding to the given COutPoints.
- // Note that this data is not authenticated by anything: this code could just invent any
- // old rubbish and hand it back, with the peer being unable to tell unless they are checking
- // the outpoints against some out of band data.
- //
- // Also the answer could change the moment after we give it. However some apps can tolerate
- // this, because they're only using the result as a hint or are willing to trust the results
- // based on something else. For example we may be a "trusted node" for the peer, or it may
- // be checking the results given by several nodes for consistency, it may
- // run the UTXOs returned against scriptSigs of transactions obtained elsewhere (after checking
- // for a standard script form), and because the height in which the UTXO was defined is provided
- // a client that has a map of heights to block headers (as SPV clients do, for recent blocks)
- // can request the creating block via hash.
- //
- // IMPORTANT: Clients expect ordering to be preserved!
- if (vOutPoints.size() > MAX_INV_SZ)
- return error("message getutxos size() = %u", vOutPoints.size());
-
- LogPrint("net", "getutxos for %d queries %s mempool\n", vOutPoints.size(), fCheckMemPool ? "with" : "without");
-
- boost::dynamic_bitset<unsigned char> hits(vOutPoints.size());
- {
- LOCK2(cs_main, mempool.cs);
- CCoinsViewMemPool cvMemPool(*pcoinsTip, mempool);
- CCoinsViewCache view(fCheckMemPool ? cvMemPool : *pcoinsTip);
- for (size_t i = 0; i < vOutPoints.size(); i++)
- {
- CCoins coins;
- uint256 hash = vOutPoints[i].hash;
- if (view.GetCoins(hash, coins))
- {
- mempool.pruneSpent(hash, coins);
- if (coins.IsAvailable(vOutPoints[i].n))
- {
- hits[i] = true;
- // Safe to index into vout here because IsAvailable checked if it's off the end of the array, or if
- // n is valid but points to an already spent output (IsNull).
- CCoin coin;
- coin.nTxVer = coins.nVersion;
- coin.nHeight = coins.nHeight;
- coin.out = coins.vout.at(vOutPoints[i].n);
- assert(!coin.out.IsNull());
- resultCoins->push_back(coin);
- }
- }
- }
- }
-
- boost::to_block_range(hits, std::back_inserter(*result));
- return true;
-}
-
-
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
{
RandAddSeedPerfmon();
@@ -3936,22 +3738,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "getutxos")
- {
- bool fCheckMemPool;
- vector<COutPoint> vOutPoints;
- vRecv >> fCheckMemPool;
- vRecv >> vOutPoints;
-
- vector<unsigned char> bitmap;
- vector<CCoin> outs;
- if (ProcessGetUTXOs(vOutPoints, fCheckMemPool, &bitmap, &outs))
- pfrom->PushMessage("utxos", chainActive.Height(), chainActive.Tip()->GetBlockHash(), bitmap, outs);
- else
- Misbehaving(pfrom->GetId(), 20);
- }
-
-
else if (strCommand == "tx")
{
vector<uint256> vWorkQueue;
diff --git a/src/main.h b/src/main.h
index fae8990d20..6b78356642 100644
--- a/src/main.h
+++ b/src/main.h
@@ -14,6 +14,7 @@
#include "coins.h"
#include "core.h"
#include "net.h"
+#include "pow.h"
#include "script.h"
#include "sync.h"
#include "txmempool.h"
@@ -160,11 +161,9 @@ std::string GetWarnings(std::string strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false);
/** Find the best known block, and make it the tip of the block chain */
-bool ActivateBestChain(CValidationState &state);
+bool ActivateBestChain(CValidationState &state, CBlock *pblock = NULL);
int64_t GetBlockValue(int nHeight, int64_t nFees);
-void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev);
-
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash);
/** Verify a signature */
@@ -329,7 +328,7 @@ private:
int nHashType;
public:
- CScriptCheck() {}
+ CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), nHashType(0) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, int nHashTypeIn) :
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), nHashType(nHashTypeIn) { }
@@ -345,66 +344,6 @@ public:
}
};
-/** A transaction with a merkle branch linking it to the block chain. */
-class CMerkleTx : public CTransaction
-{
-private:
- int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const;
-
-public:
- uint256 hashBlock;
- std::vector<uint256> vMerkleBranch;
- int nIndex;
-
- // memory only
- mutable bool fMerkleVerified;
-
-
- CMerkleTx()
- {
- Init();
- }
-
- CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
- {
- Init();
- }
-
- void Init()
- {
- hashBlock = 0;
- nIndex = -1;
- fMerkleVerified = false;
- }
-
-
- IMPLEMENT_SERIALIZE
- (
- nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
- nVersion = this->nVersion;
- READWRITE(hashBlock);
- READWRITE(vMerkleBranch);
- READWRITE(nIndex);
- )
-
-
- int SetMerkleBranch(const CBlock* pblock=NULL);
-
- // Return depth of transaction in blockchain:
- // -1 : not in blockchain, and not in memory pool (conflicted transaction)
- // 0 : in memory pool, waiting to be included in a block
- // >=1 : this many blocks deep in the main chain
- int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
- int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
- bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
- int GetBlocksToMaturity() const;
- bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
-};
-
-
-
-
-
/** Data structure that represents a partial merkle tree.
*
* It respresents a subset of the txid's of a known block, in a way that
@@ -736,17 +675,7 @@ public:
uint256 GetBlockWork() const
{
- uint256 bnTarget;
- bool fNegative;
- bool fOverflow;
- bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
- if (fNegative || fOverflow || bnTarget == 0)
- return 0;
- // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
- // as it's too large for a uint256. However, as 2**256 is at least as large
- // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
- // or ~bnTarget / (nTarget+1) + 1.
- return (~bnTarget / (bnTarget + 1)) + 1;
+ return GetProofIncrement(nBits);
}
enum { nMedianTimeSpan=11 };
@@ -887,7 +816,7 @@ private:
unsigned char chRejectCode;
bool corruptionPossible;
public:
- CValidationState() : mode(MODE_VALID), nDoS(0), corruptionPossible(false) {}
+ CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {}
bool DoS(int level, bool ret = false,
unsigned char chRejectCodeIn=0, std::string strRejectReasonIn="",
bool corruptionIn=false) {
diff --git a/src/miner.cpp b/src/miner.cpp
index 8696edcf6e..96dc80a26d 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -307,7 +307,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
- UpdateTime(*pblock, pindexPrev);
+ UpdateTime(pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
@@ -540,7 +540,7 @@ void static BitcoinMiner(CWallet *pwallet)
break;
// Update nTime every few seconds
- UpdateTime(*pblock, pindexPrev);
+ UpdateTime(pblock, pindexPrev);
if (Params().AllowMinDifficultyBlocks())
{
// Changing pblock->nTime can change work required on testnet:
diff --git a/src/net.cpp b/src/net.cpp
index e2adba8517..3966706207 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -67,7 +67,7 @@ namespace {
//
bool fDiscover = true;
bool fListen = true;
-uint64_t nLocalServices = NODE_NETWORK | NODE_GETUTXOS;
+uint64_t nLocalServices = NODE_NETWORK;
CCriticalSection cs_mapLocalHost;
map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfReachable[NET_MAX] = {};
diff --git a/src/pow.cpp b/src/pow.cpp
index b091cbec3d..893f6c18be 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -8,6 +8,7 @@
#include "chainparams.h"
#include "core.h"
#include "main.h"
+#include "timedata.h"
#include "uint256.h"
#include "util.h"
@@ -94,27 +95,58 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
}
//
-// minimum amount of work that could possibly be required nTime after
-// minimum work required was nBase
+// true if nBits is greater than the minimum amount of work that could
+// possibly be required deltaTime after minimum work required was nBase
//
-unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
+bool CheckMinWork(unsigned int nBits, unsigned int nBase, int64_t deltaTime)
{
+ bool fOverflow = false;
+ uint256 bnNewBlock;
+ bnNewBlock.SetCompact(nBits, NULL, &fOverflow);
+ if (fOverflow)
+ return false;
+
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();
+ if (Params().AllowMinDifficultyBlocks() && deltaTime > Params().TargetSpacing()*2)
+ return bnNewBlock <= bnLimit;
uint256 bnResult;
bnResult.SetCompact(nBase);
- while (nTime > 0 && bnResult < bnLimit)
+ while (deltaTime > 0 && bnResult < bnLimit)
{
// Maximum 400% adjustment...
bnResult *= 4;
// ... in best-case exactly 4-times-normal target time
- nTime -= Params().TargetTimespan()*4;
+ deltaTime -= Params().TargetTimespan()*4;
}
if (bnResult > bnLimit)
bnResult = bnLimit;
- return bnResult.GetCompact();
+
+ return bnNewBlock <= bnResult;
+}
+
+void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev)
+{
+ pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+
+ // Updating time can change work required on testnet:
+ if (Params().AllowMinDifficultyBlocks())
+ pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
+}
+
+uint256 GetProofIncrement(unsigned int nBits)
+{
+ uint256 bnTarget;
+ bool fNegative;
+ bool fOverflow;
+ bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
+ if (fNegative || fOverflow || bnTarget == 0)
+ return 0;
+ // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
+ // as it's too large for a uint256. However, as 2**256 is at least as large
+ // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
+ // or ~bnTarget / (nTarget+1) + 1.
+ return (~bnTarget / (bnTarget + 1)) + 1;
}
diff --git a/src/pow.h b/src/pow.h
index 0ce5b48766..f350d763f4 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -17,7 +17,11 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
/** 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 the work is more than the minimum a received block needs, without knowing its direct parent */
+bool CheckMinWork(unsigned int nBits, unsigned int nBase, int64_t deltaTime);
+
+void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev);
+
+uint256 GetProofIncrement(unsigned int nBits);
#endif
diff --git a/src/protocol.h b/src/protocol.h
index 94d313e9c0..d7565584af 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -64,7 +64,6 @@ class CMessageHeader
enum
{
NODE_NETWORK = (1 << 0),
- NODE_GETUTXOS = (1 << 1),
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
// isn't getting used, or one not being used much, and notify the
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 9c9ff5b3a1..738fb48ef8 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -209,12 +209,6 @@ static void ShowProgress(ClientModel *clientmodel, const std::string &title, int
Q_ARG(int, nProgress));
}
-static void NotifyBlocksChanged(ClientModel *clientmodel)
-{
- // This notification is too frequent. Don't trigger a signal.
- // Don't remove it, though, as it might be useful later.
-}
-
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
{
// Too noisy: qDebug() << "NotifyNumConnectionsChanged : " + QString::number(newNumConnections);
@@ -234,7 +228,6 @@ void ClientModel::subscribeToCoreSignals()
{
// Connect signals to client
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
- uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this));
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
}
@@ -243,7 +236,6 @@ void ClientModel::unsubscribeFromCoreSignals()
{
// Disconnect signals from client
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
- uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this));
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
}
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 1162e2d87f..5dd110b36a 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -4,6 +4,7 @@
#include "splashscreen.h"
+#include "version.h"
#include "clientversion.h"
#include "init.h"
#include "ui_interface.h"
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index b71d5a0804..83fe629351 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -54,9 +54,11 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
{
Object result;
result.push_back(Pair("hash", block.GetHash().GetHex()));
- CMerkleTx txGen(block.vtx[0]);
- txGen.SetMerkleBranch(&block);
- result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
+ int confirmations = -1;
+ // Only report confirmations if the block is on the main chain
+ if (chainActive.Contains(blockindex))
+ confirmations = chainActive.Height() - blockindex->nHeight + 1;
+ result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
@@ -242,7 +244,7 @@ Value getblock(const Array& params, bool fHelp)
"\nResult (for verbose = true):\n"
"{\n"
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
- " \"confirmations\" : n, (numeric) The number of confirmations\n"
+ " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"size\" : n, (numeric) The block size\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index e68ddee040..c286626fd3 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -165,14 +165,14 @@ Value importaddress(const Array& params, bool fHelp)
std::vector<unsigned char> data(ParseHex(params[0].get_str()));
script = CScript(data.begin(), data.end());
} else {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
}
string strLabel = "";
if (params.size() > 1)
strLabel = params[1].get_str();
- // Whether to perform rescan after import
+ // Whether to perform rescan after import
bool fRescan = true;
if (params.size() > 2)
fRescan = params[2].get_bool();
@@ -191,7 +191,7 @@ Value importaddress(const Array& params, bool fHelp)
pwalletMain->MarkDirty();
if (!pwalletMain->AddWatchOnly(script))
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
if (fRescan)
{
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 6e508abcda..e4a5bc4162 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -458,7 +458,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime
- UpdateTime(*pblock, pindexPrev);
+ UpdateTime(pblock, pindexPrev);
pblock->nNonce = 0;
Array transactions;
diff --git a/src/sync.cpp b/src/sync.cpp
index e624a9ee84..066c1ca744 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -5,8 +5,11 @@
#include "sync.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
+#include <stdio.h>
#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 4ecf6e2535..8fa38c3605 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -107,11 +107,7 @@ static bool CheckNBits(unsigned int nbits1, int64_t time1, unsigned int nbits2,
return CheckNBits(nbits2, time2, nbits1, time1);
int64_t deltaTime = time2-time1;
- uint256 required;
- required.SetCompact(ComputeMinWork(nbits1, deltaTime));
- uint256 have;
- have.SetCompact(nbits2);
- return (have <= required);
+ return CheckMinWork(nbits2, nbits1, deltaTime);
}
BOOST_AUTO_TEST_CASE(DoS_checknbits)
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 2a0466e928..02c6d095f2 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -164,9 +164,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
// Tests Solver() that returns lists of keys that are
// required to satisfy a ScriptPubKey
//
- // Also tests IsMine() and ExtractAddress()
+ // Also tests IsMine() and ExtractDestination()
//
- // Note: ExtractAddress for the multisignature transactions
+ // Note: ExtractDestination for the multisignature transactions
// always returns false for this release, even if you have
// one key that would satisfy an (a|b) or 2-of-3 keys needed
// to spend an escrow transaction.
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 8af1f1c91b..238d5bab16 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -11,7 +11,8 @@
using namespace std;
-CTxMemPoolEntry::CTxMemPoolEntry()
+CTxMemPoolEntry::CTxMemPoolEntry():
+ nFee(0), nTxSize(0), nTime(0), dPriority(0.0)
{
nHeight = MEMPOOL_HEIGHT;
}
@@ -345,7 +346,9 @@ public:
};
-CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) : minRelayFee(_minRelayFee)
+CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
+ nTransactionsUpdated(0),
+ minRelayFee(_minRelayFee)
{
// Sanity checks off by default for performance, because otherwise
// accepting transactions becomes O(N^2) where N is the number
diff --git a/src/ui_interface.h b/src/ui_interface.h
index b3df2b5a85..bbc8a203c9 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -78,9 +78,6 @@ public:
/** Translate a message to the native language of the user. */
boost::signals2::signal<std::string (const char* psz)> Translate;
- /** Block chain changed. */
- boost::signals2::signal<void ()> NotifyBlocksChanged;
-
/** Number of network connections changed. */
boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
@@ -95,6 +92,9 @@ public:
/** Show progress e.g. for verifychain */
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
+
+ /** New block has been accepted */
+ boost::signals2::signal<void (const uint256& hash)> NotifyBlockTip;
};
extern CClientUIInterface uiInterface;
diff --git a/src/version.h b/src/version.h
index 3a6c0f3719..b87aa8258c 100644
--- a/src/version.h
+++ b/src/version.h
@@ -27,7 +27,7 @@ extern const std::string CLIENT_DATE;
// network protocol versioning
//
-static const int PROTOCOL_VERSION = 70003;
+static const int PROTOCOL_VERSION = 70002;
// initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 786b2f6a92..18a5b3971c 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -2194,3 +2194,102 @@ CWalletKey::CWalletKey(int64_t nExpires)
nTimeCreated = (nExpires ? GetTime() : 0);
nTimeExpires = nExpires;
}
+
+int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
+{
+ AssertLockHeld(cs_main);
+ CBlock blockTmp;
+
+ if (pblock == NULL) {
+ CCoins coins;
+ if (pcoinsTip->GetCoins(GetHash(), coins)) {
+ CBlockIndex *pindex = chainActive[coins.nHeight];
+ if (pindex) {
+ if (!ReadBlockFromDisk(blockTmp, pindex))
+ return 0;
+ pblock = &blockTmp;
+ }
+ }
+ }
+
+ if (pblock) {
+ // Update the tx's hashBlock
+ hashBlock = pblock->GetHash();
+
+ // Locate the transaction
+ for (nIndex = 0; nIndex < (int)pblock->vtx.size(); nIndex++)
+ if (pblock->vtx[nIndex] == *(CTransaction*)this)
+ break;
+ if (nIndex == (int)pblock->vtx.size())
+ {
+ vMerkleBranch.clear();
+ nIndex = -1;
+ LogPrintf("ERROR: SetMerkleBranch() : couldn't find tx in block\n");
+ return 0;
+ }
+
+ // Fill in merkle branch
+ vMerkleBranch = pblock->GetMerkleBranch(nIndex);
+ }
+
+ // Is the tx in a block that's in the main chain
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi == mapBlockIndex.end())
+ return 0;
+ CBlockIndex* pindex = (*mi).second;
+ if (!pindex || !chainActive.Contains(pindex))
+ return 0;
+
+ return chainActive.Height() - pindex->nHeight + 1;
+}
+
+int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
+{
+ if (hashBlock == 0 || nIndex == -1)
+ return 0;
+ AssertLockHeld(cs_main);
+
+ // Find the block it claims to be in
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi == mapBlockIndex.end())
+ return 0;
+ CBlockIndex* pindex = (*mi).second;
+ if (!pindex || !chainActive.Contains(pindex))
+ return 0;
+
+ // Make sure the merkle branch connects to this block
+ if (!fMerkleVerified)
+ {
+ if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
+ return 0;
+ fMerkleVerified = true;
+ }
+
+ pindexRet = pindex;
+ return chainActive.Height() - pindex->nHeight + 1;
+}
+
+int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
+{
+ AssertLockHeld(cs_main);
+ int nResult = GetDepthInMainChainINTERNAL(pindexRet);
+ if (nResult == 0 && !mempool.exists(GetHash()))
+ return -1; // Not in chain, not in mempool
+
+ return nResult;
+}
+
+int CMerkleTx::GetBlocksToMaturity() const
+{
+ if (!IsCoinBase())
+ return 0;
+ return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
+}
+
+
+bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee)
+{
+ CValidationState state;
+ return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee);
+}
+
diff --git a/src/wallet.h b/src/wallet.h
index 052da24609..544b4f5bfb 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -457,6 +457,63 @@ struct COutputEntry
int vout;
};
+/** A transaction with a merkle branch linking it to the block chain. */
+class CMerkleTx : public CTransaction
+{
+private:
+ int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const;
+
+public:
+ uint256 hashBlock;
+ std::vector<uint256> vMerkleBranch;
+ int nIndex;
+
+ // memory only
+ mutable bool fMerkleVerified;
+
+
+ CMerkleTx()
+ {
+ Init();
+ }
+
+ CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
+ {
+ Init();
+ }
+
+ void Init()
+ {
+ hashBlock = 0;
+ nIndex = -1;
+ fMerkleVerified = false;
+ }
+
+
+ IMPLEMENT_SERIALIZE
+ (
+ nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
+ nVersion = this->nVersion;
+ READWRITE(hashBlock);
+ READWRITE(vMerkleBranch);
+ READWRITE(nIndex);
+ )
+
+
+ int SetMerkleBranch(const CBlock* pblock=NULL);
+
+ // Return depth of transaction in blockchain:
+ // -1 : not in blockchain, and not in memory pool (conflicted transaction)
+ // 0 : in memory pool, waiting to be included in a block
+ // >=1 : this many blocks deep in the main chain
+ int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
+ int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
+ bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
+ int GetBlocksToMaturity() const;
+ bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
+};
+
+
/** A transaction with a bunch of additional info that only the owner cares about.
* It includes any unrecorded transactions needed to link it back to the block chain.
*/
@@ -905,6 +962,7 @@ public:
strOtherAccount.clear();
strComment.clear();
nOrderPos = -1;
+ nEntryNo = 0;
}
IMPLEMENT_SERIALIZE