aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp94
1 files changed, 40 insertions, 54 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 46118fff81..27ab677eb1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -106,11 +106,6 @@ map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);
map<COutPoint, set<map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main);
void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/**
- * Returns true if there are nRequired or more blocks of minVersion or above
- * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
- */
-static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams);
static void CheckBlockIndex(const Consensus::Params& consensusParams);
/** Constant stuff for coinbase transactions we create: */
@@ -1179,7 +1174,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// nSequence >= maxint-1 on all inputs.
//
// maxint-1 is picked to still allow use of nLockTime by
- // non-replacable transactions. All inputs rather than just one
+ // non-replaceable transactions. All inputs rather than just one
// is for the sake of multi-party protocols, where we don't
// want a single party to be able to disable replacement.
//
@@ -1546,7 +1541,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
- SyncWithWallets(tx, NULL, NULL);
+ SyncWithWallets(tx, NULL);
return true;
}
@@ -1993,7 +1988,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// is safe because block merkle hashes are still computed and checked,
// and any change will be caught at the next checkpoint. Of course, if
// the checkpoint is for a chain that's invalid due to false scriptSigs
- // this optimisation would allow an invalid chain to be accepted.
+ // this optimization would allow an invalid chain to be accepted.
if (fScriptChecks) {
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
@@ -2372,15 +2367,13 @@ 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())) {
+ // Start enforcing the DERSIG (BIP66) rule
+ if (pindex->nHeight >= chainparams.GetConsensus().BIP66Height) {
flags |= SCRIPT_VERIFY_DERSIG;
}
- // Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) for block.nVersion=4
- // blocks, when 75% of the network has upgraded:
- if (block.nVersion >= 4 && IsSuperMajority(4, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
+ // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
+ if (pindex->nHeight >= chainparams.GetConsensus().BIP65Height) {
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
@@ -2777,7 +2770,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- SyncWithWallets(tx, pindexDelete->pprev, NULL);
+ SyncWithWallets(tx, pindexDelete->pprev);
}
return true;
}
@@ -2792,7 +2785,7 @@ static int64_t nTimePostConnect = 0;
* 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, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock)
+bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::list<CTransaction> &txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*,int> > &txChanged)
{
assert(pindexNew->pprev == chainActive.Tip());
// Read block from disk.
@@ -2828,20 +2821,13 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
return false;
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
- // Remove conflicting transactions from the mempool.
- list<CTransaction> txConflicted;
+ // Remove conflicting transactions from the mempool.;
mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload());
// Update chainActive & related variables.
UpdateTip(pindexNew, chainparams);
- // Tell wallet about transactions that went from mempool
- // to conflicted:
- BOOST_FOREACH(const CTransaction &tx, txConflicted) {
- SyncWithWallets(tx, pindexNew, NULL);
- }
- // ... and about transactions that got confirmed:
- BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
- SyncWithWallets(tx, pindexNew, pblock);
- }
+
+ for(unsigned int i=0; i < pblock->vtx.size(); i++)
+ txChanged.push_back(std::make_tuple(pblock->vtx[i], pindexNew, i));
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
@@ -2923,7 +2909,7 @@ static void PruneBlockIndexCandidates() {
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
-static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound)
+static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::list<CTransaction>& txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*,int> >& txChanged)
{
AssertLockHeld(cs_main);
const CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -2956,7 +2942,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
// Connect new blocks.
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
- if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
+ if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL, txConflicted, txChanged)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
@@ -3031,6 +3017,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
break;
const CBlockIndex *pindexFork;
+ std::list<CTransaction> txConflicted;
+ std::vector<std::tuple<CTransaction,CBlockIndex*,int> > txChanged;
bool fInitialDownload;
int nNewHeight;
{
@@ -3045,7 +3033,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
return true;
bool fInvalidFound = false;
- if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound))
+ if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound, txConflicted, txChanged))
return false;
if (fInvalidFound) {
@@ -3060,6 +3048,17 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
// Notifications/callbacks that can run without cs_main
+
+ // throw all transactions though the signal-interface
+ // while _not_ holding the cs_main lock
+ BOOST_FOREACH(const CTransaction &tx, txConflicted)
+ {
+ SyncWithWallets(tx, pindexNewTip);
+ }
+ // ... and about transactions that got confirmed:
+ for(unsigned int i = 0; i < txChanged.size(); i++)
+ SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
+
// Always notify the UI if a new block tip was connected
if (pindexFork != pindexNewTip) {
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
@@ -3504,6 +3503,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
{
+ const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
// Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");
@@ -3517,10 +3517,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
- for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades
- if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
- return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", version - 1),
- strprintf("rejected nVersion=0x%08x block", version - 1));
+ // check for version 2, 3 and 4 upgrades
+ if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
+ (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
+ (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
+ return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
+ strprintf("rejected nVersion=0x%08x block", block.nVersion));
return true;
}
@@ -3546,9 +3548,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
}
}
- // 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))
+ // Enforce rule that the coinbase starts with serialized block height
+ if (nHeight >= consensusParams.BIP34Height)
{
CScript expect = CScript() << nHeight;
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
@@ -3722,19 +3723,6 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true;
}
-static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams)
-{
- unsigned int nFound = 0;
- for (int i = 0; i < consensusParams.nMajorityWindow && nFound < nRequired && pstart != NULL; i++)
- {
- if (pstart->nVersion >= minVersion)
- ++nFound;
- pstart = pstart->pprev;
- }
- return (nFound >= nRequired);
-}
-
-
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp)
{
{
@@ -3954,7 +3942,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash)
// Create new
CBlockIndex* pindexNew = new CBlockIndex();
if (!pindexNew)
- throw runtime_error("LoadBlockIndex(): new CBlockIndex failed");
+ throw runtime_error(std::string(__func__) + ": new CBlockIndex failed");
mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
@@ -4331,8 +4319,6 @@ bool InitBlockIndex(const CChainParams& chainparams)
CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("LoadBlockIndex(): genesis block not accepted");
- if (!ActivateBestChain(state, chainparams, &block))
- return error("LoadBlockIndex(): genesis block cannot be activated");
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} catch (const std::runtime_error& e) {
@@ -4815,7 +4801,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
{
// If a peer is asking for old blocks, we're almost guaranteed
// they wont have a useful mempool to match against a compact block,
- // and we dont feel like constructing the object for them, so
+ // and we don't feel like constructing the object for them, so
// instead we respond with the full, non-compact block.
if (mi->second->nHeight >= chainActive.Height() - 10) {
CBlockHeaderAndShortTxIDs cmpctblock(block);