]> Git Repo - VerusCoin.git/blame - src/main.cpp
Test
[VerusCoin.git] / src / main.cpp
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
c5b390b6 3// Distributed under the MIT software license, see the accompanying
3a25a2b9
F
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
51ed9ec9 6#include "main.h"
319b1160 7
320f2cc7
SB
8#include "sodium.h"
9
51ed9ec9 10#include "addrman.h"
f35c6c4f 11#include "alert.h"
26c16d9d 12#include "arith_uint256.h"
20c3ac51 13#include "importcoin.h"
319b1160 14#include "chainparams.h"
eb5fff9e 15#include "checkpoints.h"
319b1160 16#include "checkqueue.h"
9e851450 17#include "consensus/upgrades.h"
da29ecbc 18#include "consensus/validation.h"
5b3bc971 19#include "deprecation.h"
edd309e5 20#include "init.h"
afd4b94b 21#include "merkleblock.h"
a6df7ab5 22#include "metrics.h"
20c3ac51 23#include "notarisationdb.h"
319b1160 24#include "net.h"
df852d2b 25#include "pow.h"
0cb91a8d 26#include "script/interpreter.h"
319b1160
GA
27#include "txdb.h"
28#include "txmempool.h"
ed6d0b5f 29#include "ui_interface.h"
937ba572 30#include "undo.h"
51ed9ec9 31#include "util.h"
217a5c92 32#include "utilmoneystr.h"
26c16d9d 33#include "validationinterface.h"
9ddb6ad0 34#include "wallet/asyncrpcoperation_sendmany.h"
06c19063 35#include "wallet/asyncrpcoperation_shieldcoinbase.h"
51ed9ec9 36
358ce266 37#include <sstream>
51ed9ec9
BD
38
39#include <boost/algorithm/string/replace.hpp>
40#include <boost/filesystem.hpp>
41#include <boost/filesystem/fstream.hpp>
36cba8f1 42#include <boost/math/distributions/poisson.hpp>
ad49c256 43#include <boost/thread.hpp>
7c68cc07 44#include <boost/static_assert.hpp>
0a61b0df 45
4dc5eb05 46using namespace std;
0a61b0df 47
9b59e3bd 48#if defined(NDEBUG)
7662d72b 49# error "Zcash cannot be compiled without assertions."
9b59e3bd
GM
50#endif
51
d27afb07 52
c5b390b6
MF
53/**
54 * Global state
55 */
0a61b0df 56
57CCriticalSection cs_main;
8dcf7f94 58extern uint8_t NOTARY_PUBKEY33[33];
6477ad07 59extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN;
03e2210d 60int32_t KOMODO_NEWBLOCKS;
9464ac21 61int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
395f10cf 62void komodo_broadcast(CBlock *pblock,int32_t limit);
0a61b0df 63
145d5be8 64BlockMap mapBlockIndex;
4c6d41b8 65CChain chainActive;
ad6e6017 66CBlockIndex *pindexBestHeader = NULL;
51ed9ec9 67int64_t nTimeBestReceived = 0;
ff6a7af1
LD
68CWaitableCriticalSection csBestBlock;
69CConditionVariable cvBlockChange;
f9cae832 70int nScriptCheckThreads = 0;
1f015f6a 71bool fExperimentalMode = false;
66b02c93 72bool fImporting = false;
7fea4846 73bool fReindex = false;
2d1fa42e 74bool fTxIndex = false;
8b78a819
T
75bool fAddressIndex = false;
76bool fTimestampIndex = false;
77bool fSpentIndex = false;
f9ec3f0f 78bool fHavePruned = false;
79bool fPruneMode = false;
3da434a2 80bool fIsBareMultisigStd = true;
3fcfbc8a 81bool fCheckBlockIndex = false;
a8cdaf5c 82bool fCheckpointsEnabled = true;
d212ba32 83bool fCoinbaseEnforcedProtectionEnabled = true;
fc684ad8 84size_t nCoinCacheUsage = 5000 * 300;
f9ec3f0f 85uint64_t nPruneTarget = 0;
4d9c7fe6 86bool fAlerts = DEFAULT_ALERTS;
0a61b0df 87
9bb37bf0
JG
88unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA;
89
037b4f14 90/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
ba0625f2 91CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
13fc83c7
GA
92
93CTxMemPool mempool(::minRelayTxFee);
000dc551 94
c74332c6
GA
95struct COrphanTx {
96 CTransaction tx;
97 NodeId fromPeer;
98};
72b25b0f
CF
99map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);;
100map<uint256, set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY(cs_main);;
101void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
0a61b0df 102
9dcd524f
PW
103/**
104 * Returns true if there are nRequired or more blocks of minVersion or above
51aa2492 105 * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
9dcd524f 106 */
51aa2492 107static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams);
3fcfbc8a 108static void CheckBlockIndex();
9dcd524f 109
c5b390b6 110/** Constant stuff for coinbase transactions we create: */
7bf8b7c2 111CScript COINBASE_FLAGS;
0a61b0df 112
1a321777 113const string strMessageMagic = "Komodo Signed Message:\n";
2bc4fd60 114
caca6aa4
PW
115// Internal stuff
116namespace {
8d655683 117
6b29ccc9
B
118 struct CBlockIndexWorkComparator
119 {
3fcfbc8a 120 bool operator()(CBlockIndex *pa, CBlockIndex *pb) const {
6b29ccc9
B
121 // First sort by most total work, ...
122 if (pa->nChainWork > pb->nChainWork) return false;
123 if (pa->nChainWork < pb->nChainWork) return true;
8d655683 124
6b29ccc9
B
125 // ... then by earliest time received, ...
126 if (pa->nSequenceId < pb->nSequenceId) return false;
127 if (pa->nSequenceId > pb->nSequenceId) return true;
8d655683 128
6b29ccc9
B
129 // Use pointer address as tie breaker (should only happen with blocks
130 // loaded from disk, as those all have id 0).
131 if (pa < pb) return false;
132 if (pa > pb) return true;
8d655683 133
6b29ccc9
B
134 // Identical blocks.
135 return false;
136 }
137 };
8d655683 138
6b29ccc9 139 CBlockIndex *pindexBestInvalid;
8d655683 140
c5b390b6 141 /**
3fcfbc8a 142 * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
f9ec3f0f 143 * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
144 * missing the data for the block.
c5b390b6 145 */
e17bd583 146 set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
c5b390b6 147 /** Number of nodes with fSyncStarted. */
341735eb 148 int nSyncStarted = 0;
f9ec3f0f 149 /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions.
8d655683 150 * Pruned nodes may have entries where B is missing data.
151 */
341735eb 152 multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
8d655683 153
6b29ccc9 154 CCriticalSection cs_LastBlockFile;
ed6d1a2c 155 std::vector<CBlockFileInfo> vinfoBlockFile;
6b29ccc9 156 int nLastBlockFile = 0;
f9ec3f0f 157 /** Global flag to indicate we should check to see if there are
158 * block/undo files that should be deleted. Set on startup
159 * or if we allocate more file space when we're in prune mode
160 */
161 bool fCheckForPruning = false;
8d655683 162
c5b390b6
MF
163 /**
164 * Every received block is assigned a unique and increasing identifier, so we
165 * know which one to give priority in case of a fork.
166 */
6b29ccc9 167 CCriticalSection cs_nBlockSequenceId;
c5b390b6 168 /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
6b29ccc9 169 uint32_t nBlockSequenceId = 1;
8d655683 170
c5b390b6 171 /**
b05a89b2
LD
172 * Sources of received blocks, saved to be able to send them reject
173 * messages or ban them when processing happens afterwards. Protected by
174 * cs_main.
c5b390b6 175 */
6b29ccc9 176 map<uint256, NodeId> mapBlockSource;
8d655683 177
ec9b6c33
PT
178 /**
179 * Filter for transactions that were recently rejected by
180 * AcceptToMemoryPool. These are not rerequested until the chain tip
181 * changes, at which point the entire filter is reset. Protected by
182 * cs_main.
183 *
184 * Without this filter we'd be re-requesting txs from each of our peers,
185 * increasing bandwidth consumption considerably. For instance, with 100
186 * peers, half of which relay a tx we don't accept, that might be a 50x
187 * bandwidth increase. A flooding attacker attempting to roll-over the
188 * filter using minimum-sized, 60byte, transactions might manage to send
189 * 1000/sec if we have fast peers, so we pick 120,000 to give our peers a
190 * two minute window to send invs to us.
191 *
192 * Decreasing the false positive rate is fairly cheap, so we pick one in a
193 * million to make it highly unlikely for users to have issues with this
194 * filter.
195 *
196 * Memory used: 1.7MB
197 */
198 boost::scoped_ptr<CRollingBloomFilter> recentRejects;
199 uint256 hashRecentRejectsChainTip;
8d655683 200
c5b390b6 201 /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
6b29ccc9
B
202 struct QueuedBlock {
203 uint256 hash;
c5b390b6
MF
204 CBlockIndex *pindex; //! Optional.
205 int64_t nTime; //! Time of "getdata" request in microseconds.
91613034 206 bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
8ba7f842 207 int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer)
6b29ccc9
B
208 };
209 map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
8d655683 210
91613034
PW
211 /** Number of blocks in flight with validated headers. */
212 int nQueuedValidatedHeaders = 0;
8d655683 213
c5b390b6 214 /** Number of preferable block download peers. */
b4ee0bdd 215 int nPreferredDownload = 0;
8d655683 216
c5b390b6 217 /** Dirty block index entries. */
51ce901a 218 set<CBlockIndex*> setDirtyBlockIndex;
8d655683 219
c5b390b6 220 /** Dirty block file entries. */
51ce901a 221 set<int> setDirtyFileInfo;
e10dcf27 222} // anon namespace
0a61b0df 223
501da250
EL
224//////////////////////////////////////////////////////////////////////////////
225//
226// Registration of network node signals.
227//
228
b2864d2f 229namespace {
8d655683 230
231 struct CBlockReject {
232 unsigned char chRejectCode;
233 string strRejectReason;
234 uint256 hashBlock;
235 };
236
237 /**
238 * Maintain validation-specific state about nodes, protected by cs_main, instead
239 * by CNode's own locks. This simplifies asynchronous operation, where
240 * processing of incoming data is done after the ProcessMessage call returns,
241 * and we're no longer holding the node's locks.
242 */
243 struct CNodeState {
244 //! The peer's address
245 CService address;
246 //! Whether we have a fully established connection.
247 bool fCurrentlyConnected;
248 //! Accumulated misbehaviour score for this peer.
249 int nMisbehavior;
250 //! Whether this peer should be disconnected and banned (unless whitelisted).
251 bool fShouldBan;
252 //! String name of this peer (debugging/logging purposes).
253 std::string name;
254 //! List of asynchronously-determined block rejections to notify this peer about.
255 std::vector<CBlockReject> rejects;
256 //! The best known block we know this peer has announced.
257 CBlockIndex *pindexBestKnownBlock;
258 //! The hash of the last unknown block this peer has announced.
259 uint256 hashLastUnknownBlock;
260 //! The last full block we both have.
261 CBlockIndex *pindexLastCommonBlock;
262 //! Whether we've started headers synchronization with this peer.
263 bool fSyncStarted;
264 //! Since when we're stalling block download progress (in microseconds), or 0.
265 int64_t nStallingSince;
266 list<QueuedBlock> vBlocksInFlight;
267 int nBlocksInFlight;
268 int nBlocksInFlightValidHeaders;
269 //! Whether we consider this a preferred download peer.
270 bool fPreferredDownload;
271
272 CNodeState() {
273 fCurrentlyConnected = false;
274 nMisbehavior = 0;
275 fShouldBan = false;
276 pindexBestKnownBlock = NULL;
277 hashLastUnknownBlock.SetNull();
278 pindexLastCommonBlock = NULL;
279 fSyncStarted = false;
280 nStallingSince = 0;
281 nBlocksInFlight = 0;
282 nBlocksInFlightValidHeaders = 0;
283 fPreferredDownload = false;
284 }
285 };
286
287 /** Map maintaining per-node state. Requires cs_main. */
288 map<NodeId, CNodeState> mapNodeState;
289
290 // Requires cs_main.
291 CNodeState *State(NodeId pnode) {
292 map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
293 if (it == mapNodeState.end())
294 return NULL;
295 return &it->second;
b2864d2f 296 }
8d655683 297
298 int GetHeight()
299 {
300 LOCK(cs_main);
301 return chainActive.Height();
9c273790 302 }
14aa6cc0 303
8d655683 304 void UpdatePreferredDownload(CNode* node, CNodeState* state)
305 {
306 nPreferredDownload -= state->fPreferredDownload;
307
308 // Whether this node should be marked as a preferred download node.
309 state->fPreferredDownload = (!node->fInbound || node->fWhitelisted) && !node->fOneShot && !node->fClient;
310
311 nPreferredDownload += state->fPreferredDownload;
312 }
14aa6cc0 313
8d655683 314 // Returns time at which to timeout block request (nTime in microseconds)
315 int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams)
316 {
317 return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore);
f59d8f0b 318 }
8d655683 319
320 void InitializeNode(NodeId nodeid, const CNode *pnode) {
321 LOCK(cs_main);
322 CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
323 state.name = pnode->addrName;
324 state.address = pnode->addr;
325 }
326
327 void FinalizeNode(NodeId nodeid) {
328 LOCK(cs_main);
329 CNodeState *state = State(nodeid);
330
331 if (state->fSyncStarted)
332 nSyncStarted--;
333
334 if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
335 AddressCurrentlyConnected(state->address);
aa815647 336 }
8d655683 337
338 BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight)
339 mapBlocksInFlight.erase(entry.hash);
340 EraseOrphansFor(nodeid);
341 nPreferredDownload -= state->fPreferredDownload;
342
343 mapNodeState.erase(nodeid);
aa815647 344 }
8d655683 345
346 void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
0a0ec219 347 {
8d655683 348 /* int expired = pool.Expire(GetTime() - age);
349 if (expired != 0)
350 LogPrint("mempool", "Expired %i transactions from the memory pool\n", expired);
351
352 std::vector<uint256> vNoSpendsRemaining;
353 pool.TrimToSize(limit, &vNoSpendsRemaining);
354 BOOST_FOREACH(const uint256& removed, vNoSpendsRemaining)
355 pcoinsTip->Uncache(removed);*/
aa815647 356 }
8d655683 357
358 // Requires cs_main.
359 // Returns a bool indicating whether we requested this block.
360 bool MarkBlockAsReceived(const uint256& hash) {
361 map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
362 if (itInFlight != mapBlocksInFlight.end()) {
363 CNodeState *state = State(itInFlight->second.first);
364 nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
365 state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders;
366 state->vBlocksInFlight.erase(itInFlight->second.second);
367 state->nBlocksInFlight--;
368 state->nStallingSince = 0;
369 mapBlocksInFlight.erase(itInFlight);
370 return true;
371 }
372 return false;
341735eb 373 }
8d655683 374
375 // Requires cs_main.
376 void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, CBlockIndex *pindex = NULL) {
377 CNodeState *state = State(nodeid);
378 assert(state != NULL);
379
380 // Make sure it's not listed somewhere already.
381 MarkBlockAsReceived(hash);
382
383 int64_t nNow = GetTimeMicros();
384 QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)};
385 nQueuedValidatedHeaders += newentry.fValidatedHeaders;
386 list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
387 state->nBlocksInFlight++;
388 state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders;
389 mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
341735eb 390 }
8d655683 391
392 /** Check whether the last unknown block a peer advertized is not yet known. */
393 void ProcessBlockAvailability(NodeId nodeid) {
394 CNodeState *state = State(nodeid);
395 assert(state != NULL);
396
397 if (!state->hashLastUnknownBlock.IsNull()) {
398 BlockMap::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock);
399 if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0)
400 {
401 if (state->pindexBestKnownBlock == NULL || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
402 state->pindexBestKnownBlock = itOld->second;
403 state->hashLastUnknownBlock.SetNull();
404 }
405 }
341735eb 406 }
8d655683 407
408 /** Update tracking information about which blocks a peer is assumed to have. */
409 void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
410 CNodeState *state = State(nodeid);
411 assert(state != NULL);
412
413 /*ProcessBlockAvailability(nodeid);
414
415 BlockMap::iterator it = mapBlockIndex.find(hash);
416 if (it != mapBlockIndex.end() && it->second->nChainWork > 0) {
417 // An actually better block was announced.
418 if (state->pindexBestKnownBlock == NULL || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
419 state->pindexBestKnownBlock = it->second;
420 } else*/
421 {
422 // An unknown block was announced; just assume that the latest one is the best one.
423 state->hashLastUnknownBlock = hash;
424 }
341735eb 425 }
8d655683 426
427 /** Find the last common ancestor two blocks have.
428 * Both pa and pb must be non-NULL. */
429 CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) {
430 if (pa->nHeight > pb->nHeight) {
431 pa = pa->GetAncestor(pb->nHeight);
432 } else if (pb->nHeight > pa->nHeight) {
433 pb = pb->GetAncestor(pa->nHeight);
434 }
435
436 while (pa != pb && pa && pb) {
437 pa = pa->pprev;
438 pb = pb->pprev;
439 }
440
441 // Eventually all chain branches meet at the genesis block.
442 assert(pa == pb);
443 return pa;
444 }
445
446 /** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
447 * at most count entries. */
448 void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBlockIndex*>& vBlocks, NodeId& nodeStaller) {
449 if (count == 0)
450 return;
451
452 vBlocks.reserve(vBlocks.size() + count);
453 CNodeState *state = State(nodeid);
454 assert(state != NULL);
455
456 // Make sure pindexBestKnownBlock is up to date, we'll need it.
457 ProcessBlockAvailability(nodeid);
458
459 if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork) {
460 // This peer has nothing interesting.
461 return;
462 }
463
464 if (state->pindexLastCommonBlock == NULL) {
465 // Bootstrap quickly by guessing a parent of our best tip is the forking point.
466 // Guessing wrong in either direction is not a problem.
467 state->pindexLastCommonBlock = chainActive[std::min(state->pindexBestKnownBlock->nHeight, chainActive.Height())];
468 }
469
470 // If the peer reorganized, our previous pindexLastCommonBlock may not be an ancestor
471 // of its current tip anymore. Go back enough to fix that.
472 state->pindexLastCommonBlock = LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
473 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
474 return;
475
476 std::vector<CBlockIndex*> vToFetch;
477 CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
478 // Never fetch further than the best block we know the peer has, or more than BLOCK_DOWNLOAD_WINDOW + 1 beyond the last
479 // linked block we have in common with this peer. The +1 is so we can detect stalling, namely if we would be able to
480 // download that next block if the window were 1 larger.
481 int nWindowEnd = state->pindexLastCommonBlock->nHeight + BLOCK_DOWNLOAD_WINDOW;
482 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
483 NodeId waitingfor = -1;
484 while (pindexWalk->nHeight < nMaxHeight) {
485 // Read up to 128 (or more, if more blocks than that are needed) successors of pindexWalk (towards
486 // pindexBestKnownBlock) into vToFetch. We fetch 128, because CBlockIndex::GetAncestor may be as expensive
487 // as iterating over ~100 CBlockIndex* entries anyway.
488 int nToFetch = std::min(nMaxHeight - pindexWalk->nHeight, std::max<int>(count - vBlocks.size(), 128));
489 vToFetch.resize(nToFetch);
490 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->nHeight + nToFetch);
491 vToFetch[nToFetch - 1] = pindexWalk;
492 for (unsigned int i = nToFetch - 1; i > 0; i--) {
493 vToFetch[i - 1] = vToFetch[i]->pprev;
34970223 494 }
8d655683 495
496 // Iterate over those blocks in vToFetch (in forward direction), adding the ones that
497 // are not yet downloaded and not in flight to vBlocks. In the meantime, update
498 // pindexLastCommonBlock as long as all ancestors are already downloaded, or if it's
499 // already part of our chain (and therefore don't need it even if pruned).
500 BOOST_FOREACH(CBlockIndex* pindex, vToFetch) {
501 if (!pindex->IsValid(BLOCK_VALID_TREE)) {
502 // We consider the chain that this peer is on invalid.
341735eb
PW
503 return;
504 }
8d655683 505 if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) {
506 if (pindex->nChainTx)
507 state->pindexLastCommonBlock = pindex;
508 } else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) {
509 // The block is not already downloaded, and not yet in flight.
510 if (pindex->nHeight > nWindowEnd) {
511 // We reached the end of the window.
512 if (vBlocks.size() == 0 && waitingfor != nodeid) {
513 // We aren't able to fetch anything, but we would be if the download window was one larger.
514 nodeStaller = waitingfor;
515 }
516 return;
517 }
518 vBlocks.push_back(pindex);
519 if (vBlocks.size() == count) {
520 return;
521 }
522 } else if (waitingfor == -1) {
523 // This is the first already-in-flight block.
524 waitingfor = mapBlocksInFlight[pindex->GetBlockHash()].first;
341735eb 525 }
341735eb
PW
526 }
527 }
528 }
8d655683 529
e10dcf27 530} // anon namespace
b2864d2f
PW
531
532bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
533 LOCK(cs_main);
534 CNodeState *state = State(nodeid);
535 if (state == NULL)
536 return false;
537 stats.nMisbehavior = state->nMisbehavior;
aa815647 538 stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
ad6e6017
PW
539 stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
540 BOOST_FOREACH(const QueuedBlock& queue, state->vBlocksInFlight) {
541 if (queue.pindex)
542 stats.vHeightInFlight.push_back(queue.pindex->nHeight);
543 }
b2864d2f
PW
544 return true;
545}
546
501da250
EL
547void RegisterNodeSignals(CNodeSignals& nodeSignals)
548{
4c6d41b8 549 nodeSignals.GetHeight.connect(&GetHeight);
501da250
EL
550 nodeSignals.ProcessMessages.connect(&ProcessMessages);
551 nodeSignals.SendMessages.connect(&SendMessages);
b2864d2f
PW
552 nodeSignals.InitializeNode.connect(&InitializeNode);
553 nodeSignals.FinalizeNode.connect(&FinalizeNode);
501da250 554}
64c7ee7e 555
501da250
EL
556void UnregisterNodeSignals(CNodeSignals& nodeSignals)
557{
4c6d41b8 558 nodeSignals.GetHeight.disconnect(&GetHeight);
501da250
EL
559 nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
560 nodeSignals.SendMessages.disconnect(&SendMessages);
b2864d2f
PW
561 nodeSignals.InitializeNode.disconnect(&InitializeNode);
562 nodeSignals.FinalizeNode.disconnect(&FinalizeNode);
501da250 563}
64c7ee7e 564
6db83db3 565CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
566{
70e7fba0 567 // Find the first block the caller has in the main chain
e4daecda 568 BOOST_FOREACH(const uint256& hash, locator.vHave) {
145d5be8 569 BlockMap::iterator mi = mapBlockIndex.find(hash);
e4d89f43 570 if (mi != mapBlockIndex.end())
70e7fba0
MH
571 {
572 CBlockIndex* pindex = (*mi).second;
43450135 573 if (pindex != 0 && chain.Contains(pindex))
70e7fba0 574 return pindex;
409c28a2 575 if (pindex != 0 && pindex->GetAncestor(chain.Height()) == chain.Tip()) {
89f20450
PW
576 return chain.Tip();
577 }
70e7fba0
MH
578 }
579 }
6db83db3 580 return chain.Genesis();
77339e5a
PW
581}
582
ae8bfd12 583CCoinsViewCache *pcoinsTip = NULL;
d979e6e3 584CBlockTreeDB *pblocktree = NULL;
b62d7030 585
586// Komodo globals
b62d7030 587
7637aa7f 588#define KOMODO_ZCASH
eab0d89c 589#include "komodo.h"
450cbb09 590
92dc28a3 591UniValue komodo_snapshot()
329d80d2 592{
9ef7fec1 593 LOCK(cs_main);
67d2e41b 594 int64_t total = -1;
92dc28a3 595 UniValue result(UniValue::VOBJ);
3eb535b8 596
cbce9f1f
DL
597 if (fAddressIndex) {
598 if ( pblocktree != 0 ) {
92dc28a3 599 result = pblocktree->Snapshot();
cbce9f1f
DL
600 } else {
601 fprintf(stderr,"null pblocktree start with -addressindex=true\n");
602 }
603 } else {
604 fprintf(stderr,"getsnapshot requires -addressindex=true\n");
605 }
92dc28a3 606 return(result);
329d80d2 607}
608
0a61b0df 609//////////////////////////////////////////////////////////////////////////////
610//
611// mapOrphanTransactions
612//
613
72b25b0f 614bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
0a61b0df 615{
805344dc 616 uint256 hash = tx.GetHash();
0a61b0df 617 if (mapOrphanTransactions.count(hash))
77b99cf7 618 return false;
8d655683 619
77b99cf7
GA
620 // Ignore big transactions, to avoid a
621 // send-big-orphans memory exhaustion attack. If a peer has a legitimate
622 // large transaction with a missing parent then we assume
623 // it will rebroadcast it later, after the parent transaction(s)
624 // have been mined or received.
625 // 10,000 orphans, each of which is at most 5,000 bytes big is
626 // at most 500 megabytes of orphans:
e923e3ae 627 unsigned int sz = tx.GetSerializeSize(SER_NETWORK, tx.nVersion);
159bc481 628 if (sz > 5000)
77b99cf7 629 {
7d9d134b 630 LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
77b99cf7
GA
631 return false;
632 }
8d655683 633
c74332c6
GA
634 mapOrphanTransactions[hash].tx = tx;
635 mapOrphanTransactions[hash].fromPeer = peer;
223b6f1b 636 BOOST_FOREACH(const CTxIn& txin, tx.vin)
8d655683 637 mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
638
c74332c6
GA
639 LogPrint("mempool", "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(),
640 mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size());
77b99cf7 641 return true;
0a61b0df 642}
643
72b25b0f 644void static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
0a61b0df 645{
c74332c6 646 map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(hash);
89d91f6a 647 if (it == mapOrphanTransactions.end())
0a61b0df 648 return;
c74332c6 649 BOOST_FOREACH(const CTxIn& txin, it->second.tx.vin)
0a61b0df 650 {
89d91f6a 651 map<uint256, set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash);
def2fdb4
GA
652 if (itPrev == mapOrphanTransactionsByPrev.end())
653 continue;
89d91f6a
WL
654 itPrev->second.erase(hash);
655 if (itPrev->second.empty())
656 mapOrphanTransactionsByPrev.erase(itPrev);
0a61b0df 657 }
89d91f6a 658 mapOrphanTransactions.erase(it);
0a61b0df 659}
660
c74332c6
GA
661void EraseOrphansFor(NodeId peer)
662{
663 int nErased = 0;
664 map<uint256, COrphanTx>::iterator iter = mapOrphanTransactions.begin();
665 while (iter != mapOrphanTransactions.end())
666 {
667 map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
668 if (maybeErase->second.fromPeer == peer)
669 {
805344dc 670 EraseOrphanTx(maybeErase->second.tx.GetHash());
c74332c6
GA
671 ++nErased;
672 }
673 }
674 if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx from peer %d\n", nErased, peer);
675}
676
677
72b25b0f 678unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
142e6041 679{
7bd9c3a3 680 unsigned int nEvicted = 0;
142e6041
GA
681 while (mapOrphanTransactions.size() > nMaxOrphans)
682 {
683 // Evict a random orphan:
f718aedd 684 uint256 randomhash = GetRandHash();
c74332c6 685 map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
142e6041
GA
686 if (it == mapOrphanTransactions.end())
687 it = mapOrphanTransactions.begin();
8d655683 688 EraseOrphanTx(it->first);
689 ++nEvicted;
142e6041
GA
690 }
691 return nEvicted;
692}
0a61b0df 693
694
072099d7 695bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
000dc551 696{
072099d7 697 bool isOverwinter = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
8d655683 698
072099d7
S
699 if (isOverwinter) {
700 // Overwinter standard rules apply
701 if (tx.nVersion > CTransaction::OVERWINTER_MAX_CURRENT_VERSION || tx.nVersion < CTransaction::OVERWINTER_MIN_CURRENT_VERSION) {
702 reason = "overwinter-version";
703 return false;
704 }
705 } else {
706 // Sprout standard rules apply
707 if (tx.nVersion > CTransaction::SPROUT_MAX_CURRENT_VERSION || tx.nVersion < CTransaction::SPROUT_MIN_CURRENT_VERSION) {
708 reason = "version";
709 return false;
710 }
980bfe6e 711 }
8d655683 712
05df3fc6 713 BOOST_FOREACH(const CTxIn& txin, tx.vin)
e679ec96 714 {
4d79098a
PT
715 // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
716 // keys. (remember the 520 byte limit on redeemScript size) That works
675bcd58 717 // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
4d79098a
PT
718 // bytes of scriptSig, which we round off to 1650 bytes for some minor
719 // future-proofing. That's also enough to spend a 20-of-20
720 // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
721 // considered standard)
722 if (txin.scriptSig.size() > 1650) {
980bfe6e 723 reason = "scriptsig-size";
922e8e29 724 return false;
980bfe6e
JG
725 }
726 if (!txin.scriptSig.IsPushOnly()) {
727 reason = "scriptsig-not-pushonly";
922e8e29 728 return false;
87fe71e1 729 }
e679ec96 730 }
8d655683 731
9632af31 732 unsigned int v=0,nDataOut = 0;
a7934247 733 txnouttype whichType;
9632af31 734 BOOST_FOREACH(const CTxOut& txout, tx.vout)
735 {
cc0f93da 736 if (!::IsStandard(txout.scriptPubKey, whichType))
737 {
7a82f2fc 738 reason = "scriptpubkey";
cc0f93da 739 fprintf(stderr,">>>>>>>>>>>>>>> vout.%d nDataout.%d\n",v,nDataOut);
922e8e29 740 return false;
980bfe6e 741 }
9632af31 742
a7934247 743 if (whichType == TX_NULL_DATA)
cc0f93da 744 {
a7934247 745 nDataOut++;
7a82f2fc 746 //fprintf(stderr,"is OP_RETURN\n");
cc0f93da 747 }
3da434a2
JG
748 else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
749 reason = "bare-multisig";
750 return false;
b72f0608 751 } else if (txout.scriptPubKey.IsPayToCryptoCondition() == 0 && txout.IsDust(::minRelayTxFee)) {
980bfe6e 752 reason = "dust";
65ce2156 753 return false;
980bfe6e 754 }
9632af31 755 v++;
65ce2156 756 }
8d655683 757
a7934247
JG
758 // only one OP_RETURN txout is permitted
759 if (nDataOut > 1) {
b34e88a8 760 reason = "multi-op-return";
a7934247
JG
761 return false;
762 }
8d655683 763
e679ec96
GA
764 return true;
765}
766
14aa6cc0 767bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
912af0a6 768{
b5284a65 769 int32_t i;
05df3fc6
EL
770 if (tx.nLockTime == 0)
771 return true;
fb50dd55 772 if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
773 return true;
05df3fc6 774 BOOST_FOREACH(const CTxIn& txin, tx.vin)
69988609 775 {
420b712a 776 if ( txin.nSequence == 0xfffffffe && (((int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockTime) || ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockHeight)) )
69988609 777 {
778
779 }
780 else if (!txin.IsFinal())
14512c96 781 {
60aee10d 782 //printf("non-final txin seq.%x locktime.%u vs nTime.%u\n",txin.nSequence,(uint32_t)tx.nLockTime,(uint32_t)nBlockTime);
05df3fc6 783 return false;
14512c96 784 }
69988609 785 }
05df3fc6
EL
786 return true;
787}
788
9bb37bf0
JG
789bool IsExpiredTx(const CTransaction &tx, int nBlockHeight)
790{
791 if (tx.nExpiryHeight == 0 || tx.IsCoinBase()) {
792 return false;
793 }
794 return static_cast<uint32_t>(nBlockHeight) > tx.nExpiryHeight;
795}
796
a1d3c6fb 797bool CheckFinalTx(const CTransaction &tx, int flags)
75a4d512
PT
798{
799 AssertLockHeld(cs_main);
8d655683 800
a1d3c6fb
MF
801 // By convention a negative value for flags indicates that the
802 // current network-enforced consensus rules should be used. In
803 // a future soft-fork scenario that would mean checking which
804 // rules would be enforced for the next block and setting the
805 // appropriate flags. At the present time no soft-forks are
806 // scheduled, so no flags are set.
807 flags = std::max(flags, 0);
8d655683 808
a1d3c6fb
MF
809 // CheckFinalTx() uses chainActive.Height()+1 to evaluate
810 // nLockTime because when IsFinalTx() is called within
811 // CBlock::AcceptBlock(), the height of the block *being*
812 // evaluated is what is used. Thus if we want to know if a
813 // transaction can be part of the *next* block, we need to call
814 // IsFinalTx() with one more than chainActive.Height().
815 const int nBlockHeight = chainActive.Height() + 1;
8d655683 816
a1d3c6fb
MF
817 // Timestamps on the other hand don't get any special treatment,
818 // because we can't know what timestamp the next block will have,
819 // and there aren't timestamp applications where it matters.
820 // However this changes once median past time-locks are enforced:
821 const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST)
8d655683 822 ? chainActive.Tip()->GetMedianTimePast()
823 : GetAdjustedTime();
824
14aa6cc0 825 return IsFinalTx(tx, nBlockHeight, nBlockTime);
75a4d512
PT
826}
827
c5b390b6
MF
828/**
829 * Check transaction inputs to mitigate two
830 * potential denial-of-service attacks:
db954a65 831 *
c5b390b6
MF
832 * 1. scriptSigs with extra data stuffed into them,
833 * not consumed by scriptPubKey (or P2SH script)
834 * 2. P2SH scripts with a crazy number of expensive
835 * CHECKSIG/CHECKMULTISIG operations
836 */
be126699 837bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, uint32_t consensusBranchId)
e679ec96 838{
05df3fc6 839 if (tx.IsCoinBase())
575bdcde 840 return true; // Coinbases don't use vin normally
0cb91a8d
SS
841
842 if (tx.IsCoinImport())
843 return tx.vin[0].scriptSig.IsCoinImport();
844
05df3fc6 845 for (unsigned int i = 0; i < tx.vin.size(); i++)
e679ec96 846 {
05df3fc6 847 const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
8d655683 848
e679ec96 849 vector<vector<unsigned char> > vSolutions;
2a45a494
GA
850 txnouttype whichType;
851 // get the scriptPubKey corresponding to this input:
8d7849b6 852 const CScript& prevScript = prev.scriptPubKey;
2a45a494 853 if (!Solver(prevScript, whichType, vSolutions))
922e8e29 854 return false;
39f0d968 855 int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
c0a0a93d
JG
856 if (nArgsExpected < 0)
857 return false;
8d655683 858
39f0d968
GA
859 // Transactions with extra stuff in their scriptSigs are
860 // non-standard. Note that this EvalScript() call will
861 // be quick, because if there are any operations
7f3b4e95 862 // beside "push data" in the scriptSig
bd2b73bb 863 // IsStandardTx() will have already returned false
7f3b4e95 864 // and this method isn't called.
39f0d968 865 vector<vector<unsigned char> > stack;
be126699 866 if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), consensusBranchId))
39f0d968 867 return false;
8d655683 868
e679ec96
GA
869 if (whichType == TX_SCRIPTHASH)
870 {
922e8e29 871 if (stack.empty())
e679ec96 872 return false;
2a45a494 873 CScript subscript(stack.back().begin(), stack.back().end());
39f0d968
GA
874 vector<vector<unsigned char> > vSolutions2;
875 txnouttype whichType2;
7f3b4e95
GA
876 if (Solver(subscript, whichType2, vSolutions2))
877 {
878 int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
879 if (tmpExpected < 0)
880 return false;
881 nArgsExpected += tmpExpected;
882 }
883 else
884 {
885 // Any other Script with less than 15 sigops OK:
886 unsigned int sigops = subscript.GetSigOpCount(true);
887 // ... extra data left on the stack after execution is OK, too:
888 return (sigops <= MAX_P2SH_SIGOPS);
889 }
e679ec96 890 }
8d655683 891
c0a0a93d 892 if (stack.size() != (unsigned int)nArgsExpected)
39f0d968 893 return false;
e679ec96 894 }
8d655683 895
e679ec96
GA
896 return true;
897}
898
05df3fc6 899unsigned int GetLegacySigOpCount(const CTransaction& tx)
922e8e29 900{
7bd9c3a3 901 unsigned int nSigOps = 0;
05df3fc6 902 BOOST_FOREACH(const CTxIn& txin, tx.vin)
922e8e29
GA
903 {
904 nSigOps += txin.scriptSig.GetSigOpCount(false);
905 }
05df3fc6 906 BOOST_FOREACH(const CTxOut& txout, tx.vout)
922e8e29
GA
907 {
908 nSigOps += txout.scriptPubKey.GetSigOpCount(false);
909 }
910 return nSigOps;
911}
0a61b0df 912
d0867acb 913unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
05df3fc6 914{
0cb91a8d 915 if (tx.IsCoinBase() || tx.IsCoinImport())
05df3fc6 916 return 0;
8d655683 917
05df3fc6
EL
918 unsigned int nSigOps = 0;
919 for (unsigned int i = 0; i < tx.vin.size(); i++)
920 {
921 const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
922 if (prevout.scriptPubKey.IsPayToScriptHash())
923 nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
924 }
925 return nSigOps;
926}
0a61b0df 927
072099d7
S
928/**
929 * Check a transaction contextually against a set of consensus rules valid at a given block height.
8d655683 930 *
072099d7
S
931 * Notes:
932 * 1. AcceptToMemoryPool calls CheckTransaction and this function.
933 * 2. ProcessNewBlock calls AcceptBlock, which calls CheckBlock (which calls CheckTransaction)
934 * and ContextualCheckBlock (which calls this function).
935 */
936bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, const int nHeight, const int dosLevel)
937{
938 bool isOverwinter = NetworkUpgradeActive(nHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER);
939 bool isSprout = !isOverwinter;
8d655683 940
072099d7
S
941 // If Sprout rules apply, reject transactions which are intended for Overwinter and beyond
942 if (isSprout && tx.fOverwintered) {
943 return state.DoS(dosLevel, error("ContextualCheckTransaction(): overwinter is not active yet"),
944 REJECT_INVALID, "tx-overwinter-not-active");
945 }
8d655683 946
072099d7
S
947 // If Overwinter rules apply:
948 if (isOverwinter) {
949 // Reject transactions with valid version but missing overwinter flag
950 if (tx.nVersion >= OVERWINTER_MIN_TX_VERSION && !tx.fOverwintered) {
951 return state.DoS(dosLevel, error("ContextualCheckTransaction(): overwinter flag must be set"),
8d655683 952 REJECT_INVALID, "tx-overwinter-flag-not-set");
072099d7 953 }
8d655683 954
072099d7
S
955 // Reject transactions with invalid version
956 if (tx.fOverwintered && tx.nVersion > OVERWINTER_MAX_TX_VERSION ) {
957 return state.DoS(100, error("CheckTransaction(): overwinter version too high"),
8d655683 958 REJECT_INVALID, "bad-tx-overwinter-version-too-high");
072099d7 959 }
8d655683 960
072099d7
S
961 // Reject transactions intended for Sprout
962 if (!tx.fOverwintered) {
963 return state.DoS(dosLevel, error("ContextualCheckTransaction: overwinter is active"),
8d655683 964 REJECT_INVALID, "tx-overwinter-active");
072099d7 965 }
8d655683 966
9bb37bf0
JG
967 // Check that all transactions are unexpired
968 if (IsExpiredTx(tx, nHeight)) {
969 return state.DoS(dosLevel, error("ContextualCheckTransaction(): transaction is expired"), REJECT_INVALID, "tx-overwinter-expired");
970 }
072099d7 971 }
0cb91a8d
SS
972
973 if (!(tx.IsMint() || tx.vjoinsplit.empty())) {
be126699
JG
974 auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
975 // Empty output script.
976 CScript scriptCode;
977 uint256 dataToBeSigned;
978 try {
979 dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
980 } catch (std::logic_error ex) {
981 return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
8d655683 982 REJECT_INVALID, "error-computing-signature-hash");
be126699 983 }
8d655683 984
be126699 985 BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
8d655683 986
be126699
JG
987 // We rely on libsodium to check that the signature is canonical.
988 // https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
989 if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
990 dataToBeSigned.begin(), 32,
991 tx.joinSplitPubKey.begin()
992 ) != 0) {
993 return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
8d655683 994 REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
be126699
JG
995 }
996 }
072099d7
S
997 return true;
998}
999
6fb8d0c2
JG
1000bool CheckTransaction(const CTransaction& tx, CValidationState &state,
1001 libzcash::ProofVerifier& verifier)
948d4e6c 1002{
c2123afe 1003 static uint256 array[64]; static int32_t numbanned,indallvouts; int32_t j,k,n;
782e1a56 1004 if ( *(int32_t *)&array[0] == 0 )
c2123afe 1005 numbanned = komodo_bannedset(&indallvouts,array,(int32_t)(sizeof(array)/sizeof(*array)));
6d1d0330 1006 n = tx.vin.size();
782e1a56 1007 for (j=0; j<n; j++)
1008 {
c2123afe 1009 for (k=0; k<numbanned; k++)
782e1a56 1010 {
464fe491 1011 if ( tx.vin[j].prevout.hash == array[k] && (tx.vin[j].prevout.n == 1 || k >= indallvouts) )
782e1a56 1012 {
c40ec31d 1013 static uint32_t counter;
1014 if ( counter++ < 100 )
c2123afe 1015 printf("MEMPOOL: banned tx.%d being used at ht.%d vout.%d\n",k,(int32_t)chainActive.Tip()->nHeight,j);
782e1a56 1016 return(false);
1017 }
1018 }
1019 }
8d655683 1020 // Don't count coinbase transactions because mining skews the count
a6df7ab5
JG
1021 if (!tx.IsCoinBase()) {
1022 transactionsValidated.increment();
1023 }
8d655683 1024
948d4e6c
TH
1025 if (!CheckTransactionWithoutProofVerification(tx, state)) {
1026 return false;
1027 } else {
0cb91a8d 1028 // Ensure that zk-SNARKs v|| y
b7e4abd6 1029 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
bc59f537 1030 if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) {
b7e4abd6 1031 return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"),
8d655683 1032 REJECT_INVALID, "bad-txns-joinsplit-verification-failed");
948d4e6c
TH
1033 }
1034 }
1035 return true;
1036 }
1037}
1038
1039bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidationState &state)
a790fa46 1040{
1041 // Basic checks that don't depend on any context
8d655683 1042
072099d7
S
1043 /**
1044 * Previously:
1045 * 1. The consensus rule below was:
1046 * if (tx.nVersion < SPROUT_MIN_TX_VERSION) { ... }
1047 * which checked if tx.nVersion fell within the range:
1048 * INT32_MIN <= tx.nVersion < SPROUT_MIN_TX_VERSION
1049 * 2. The parser allowed tx.nVersion to be negative
1050 *
1051 * Now:
1052 * 1. The consensus rule checks to see if tx.Version falls within the range:
1053 * 0 <= tx.nVersion < SPROUT_MIN_TX_VERSION
1054 * 2. The previous consensus rule checked for negative values within the range:
1055 * INT32_MIN <= tx.nVersion < 0
1056 * This is unnecessary for Overwinter transactions since the parser now
1057 * interprets the sign bit as fOverwintered, so tx.nVersion is always >=0,
1058 * and when Overwinter is not active ContextualCheckTransaction rejects
1059 * transactions with fOverwintered set. When fOverwintered is set,
1060 * this function and ContextualCheckTransaction will together check to
1061 * ensure tx.nVersion avoids the following ranges:
1062 * 0 <= tx.nVersion < OVERWINTER_MIN_TX_VERSION
1063 * OVERWINTER_MAX_TX_VERSION < tx.nVersion <= INT32_MAX
1064 */
1065 if (!tx.fOverwintered && tx.nVersion < SPROUT_MIN_TX_VERSION) {
7ac924cd 1066 return state.DoS(100, error("CheckTransaction(): version too low"),
cb124619 1067 REJECT_INVALID, "bad-txns-version-too-low");
7ac924cd 1068 }
072099d7
S
1069 else if (tx.fOverwintered) {
1070 if (tx.nVersion < OVERWINTER_MIN_TX_VERSION) {
1071 return state.DoS(100, error("CheckTransaction(): overwinter version too low"),
8d655683 1072 REJECT_INVALID, "bad-tx-overwinter-version-too-low");
072099d7
S
1073 }
1074 if (tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) {
1075 return state.DoS(100, error("CheckTransaction(): unknown tx version group id"),
8d655683 1076 REJECT_INVALID, "bad-tx-version-group-id");
072099d7
S
1077 }
1078 if (tx.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD) {
1079 return state.DoS(100, error("CheckTransaction(): expiry height is too high"),
8d655683 1080 REJECT_INVALID, "bad-tx-expiry-height-too-high");
072099d7
S
1081 }
1082 }
8d655683 1083
69761d82 1084 // Transactions can contain empty `vin` and `vout` so long as
8675d94b 1085 // `vjoinsplit` is non-empty.
0cb91a8d 1086 // Migrations may also have empty `vin`
8675d94b 1087 if (tx.vin.empty() && tx.vjoinsplit.empty())
5262fde0 1088 return state.DoS(10, error("CheckTransaction(): vin empty"),
14e7ffcc 1089 REJECT_INVALID, "bad-txns-vin-empty");
8675d94b 1090 if (tx.vout.empty() && tx.vjoinsplit.empty())
5262fde0 1091 return state.DoS(10, error("CheckTransaction(): vout empty"),
14e7ffcc 1092 REJECT_INVALID, "bad-txns-vout-empty");
8d655683 1093
a790fa46 1094 // Size limits
74f15a73
SB
1095 BOOST_STATIC_ASSERT(MAX_BLOCK_SIZE > MAX_TX_SIZE); // sanity
1096 if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_TX_SIZE)
5262fde0 1097 return state.DoS(100, error("CheckTransaction(): size limits failed"),
14e7ffcc 1098 REJECT_INVALID, "bad-txns-oversize");
8d655683 1099
a790fa46 1100 // Check for negative or overflow output values
a372168e 1101 CAmount nValueOut = 0;
36f9e6d6 1102 int32_t iscoinbase = tx.IsCoinBase();
05df3fc6 1103 BOOST_FOREACH(const CTxOut& txout, tx.vout)
a790fa46 1104 {
1105 if (txout.nValue < 0)
5262fde0 1106 return state.DoS(100, error("CheckTransaction(): txout.nValue negative"),
14e7ffcc 1107 REJECT_INVALID, "bad-txns-vout-negative");
a790fa46 1108 if (txout.nValue > MAX_MONEY)
4e038ef5 1109 {
1110 fprintf(stderr,"%.8f > max %.8f\n",(double)txout.nValue/COIN,(double)MAX_MONEY/COIN);
1111 return state.DoS(100, error("CheckTransaction(): txout.nValue too high"),REJECT_INVALID, "bad-txns-vout-toolarge");
1112 }
471f1b83 1113 if ( ASSETCHAINS_PRIVATE != 0 )
36f9e6d6 1114 {
471f1b83 1115 fprintf(stderr,"private chain nValue %.8f iscoinbase.%d\n",(double)txout.nValue/COIN,iscoinbase);
3118a070 1116 if ( (txout.nValue > 0 && iscoinbase == 0) || tx.GetJoinSplitValueOut() > 0 )
471f1b83 1117 return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain");
36f9e6d6 1118 }
a790fa46 1119 nValueOut += txout.nValue;
1120 if (!MoneyRange(nValueOut))
5262fde0 1121 return state.DoS(100, error("CheckTransaction(): txout total out of range"),
14e7ffcc 1122 REJECT_INVALID, "bad-txns-txouttotal-toolarge");
a790fa46 1123 }
8d655683 1124
b7e4abd6
SB
1125 // Ensure that joinsplit values are well-formed
1126 BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit)
69761d82 1127 {
626179f1 1128 if ( ASSETCHAINS_PUBLIC != 0 )
1129 {
1130 return state.DoS(100, error("CheckTransaction(): this is a public chain, no privacy allowed"),
1131 REJECT_INVALID, "bad-txns-acprivacy-chain");
1132 }
b7e4abd6
SB
1133 if (joinsplit.vpub_old < 0) {
1134 return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old negative"),
69761d82 1135 REJECT_INVALID, "bad-txns-vpub_old-negative");
6ad4db22 1136 }
8d655683 1137
b7e4abd6
SB
1138 if (joinsplit.vpub_new < 0) {
1139 return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_new negative"),
69761d82 1140 REJECT_INVALID, "bad-txns-vpub_new-negative");
6ad4db22 1141 }
8d655683 1142
b7e4abd6
SB
1143 if (joinsplit.vpub_old > MAX_MONEY) {
1144 return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old too high"),
69761d82 1145 REJECT_INVALID, "bad-txns-vpub_old-toolarge");
6ad4db22 1146 }
8d655683 1147
b7e4abd6
SB
1148 if (joinsplit.vpub_new > MAX_MONEY) {
1149 return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_new too high"),
69761d82 1150 REJECT_INVALID, "bad-txns-vpub_new-toolarge");
6ad4db22 1151 }
8d655683 1152
b7e4abd6
SB
1153 if (joinsplit.vpub_new != 0 && joinsplit.vpub_old != 0) {
1154 return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_new and joinsplit.vpub_old both nonzero"),
6ad4db22
TH
1155 REJECT_INVALID, "bad-txns-vpubs-both-nonzero");
1156 }
8d655683 1157
d7eeb745 1158 nValueOut += joinsplit.vpub_old;
6ad4db22 1159 if (!MoneyRange(nValueOut)) {
69761d82
SB
1160 return state.DoS(100, error("CheckTransaction(): txout total out of range"),
1161 REJECT_INVALID, "bad-txns-txouttotal-toolarge");
6ad4db22 1162 }
69761d82 1163 }
8d655683 1164
d7eeb745
SB
1165 // Ensure input values do not exceed MAX_MONEY
1166 // We have not resolved the txin values at this stage,
1167 // but we do know what the joinsplits claim to add
1168 // to the value pool.
1169 {
1170 CAmount nValueIn = 0;
1171 for (std::vector<JSDescription>::const_iterator it(tx.vjoinsplit.begin()); it != tx.vjoinsplit.end(); ++it)
1172 {
1173 nValueIn += it->vpub_new;
8d655683 1174
d7eeb745
SB
1175 if (!MoneyRange(it->vpub_new) || !MoneyRange(nValueIn)) {
1176 return state.DoS(100, error("CheckTransaction(): txin total out of range"),
1177 REJECT_INVALID, "bad-txns-txintotal-toolarge");
1178 }
1179 }
1180 }
8d655683 1181
1182
33208fb5
MC
1183 // Check for duplicate inputs
1184 set<COutPoint> vInOutPoints;
05df3fc6 1185 BOOST_FOREACH(const CTxIn& txin, tx.vin)
33208fb5
MC
1186 {
1187 if (vInOutPoints.count(txin.prevout))
5262fde0 1188 return state.DoS(100, error("CheckTransaction(): duplicate inputs"),
14e7ffcc 1189 REJECT_INVALID, "bad-txns-inputs-duplicate");
33208fb5
MC
1190 vInOutPoints.insert(txin.prevout);
1191 }
8d655683 1192
b7e4abd6 1193 // Check for duplicate joinsplit nullifiers in this transaction
bfeaf004 1194 set<uint256> vJoinSplitNullifiers;
b7e4abd6 1195 BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit)
69761d82 1196 {
cc01120a 1197 BOOST_FOREACH(const uint256& nf, joinsplit.nullifiers)
69761d82 1198 {
cc01120a 1199 if (vJoinSplitNullifiers.count(nf))
bfeaf004 1200 return state.DoS(100, error("CheckTransaction(): duplicate nullifiers"),
8d655683 1201 REJECT_INVALID, "bad-joinsplits-nullifiers-duplicate");
1202
cc01120a 1203 vJoinSplitNullifiers.insert(nf);
69761d82
SB
1204 }
1205 }
8d655683 1206
0cb91a8d 1207 if (tx.IsMint())
a790fa46 1208 {
b7e4abd6 1209 // There should be no joinsplits in a coinbase transaction
8675d94b 1210 if (tx.vjoinsplit.size() > 0)
b7e4abd6
SB
1211 return state.DoS(100, error("CheckTransaction(): coinbase has joinsplits"),
1212 REJECT_INVALID, "bad-cb-has-joinsplits");
8d655683 1213
05df3fc6 1214 if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
5262fde0 1215 return state.DoS(100, error("CheckTransaction(): coinbase script size"),
14e7ffcc 1216 REJECT_INVALID, "bad-cb-length");
a790fa46 1217 }
1218 else
1219 {
05df3fc6 1220 BOOST_FOREACH(const CTxIn& txin, tx.vin)
8d655683 1221 if (txin.prevout.IsNull())
1222 return state.DoS(10, error("CheckTransaction(): prevout is null"),
1223 REJECT_INVALID, "bad-txns-prevout-null");
a790fa46 1224 }
8d655683 1225
a790fa46 1226 return true;
1227}
1228
a372168e 1229CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
76970091 1230{
f24b36ca 1231 extern int32_t KOMODO_ON_DEMAND;
2a72d459
LD
1232 {
1233 LOCK(mempool.cs);
805344dc 1234 uint256 hash = tx.GetHash();
2a72d459 1235 double dPriorityDelta = 0;
a372168e 1236 CAmount nFeeDelta = 0;
2a72d459
LD
1237 mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
1238 if (dPriorityDelta > 0 || nFeeDelta > 0)
1239 return 0;
1240 }
8d655683 1241
a372168e 1242 CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes);
8d655683 1243
76970091
JG
1244 if (fAllowFree)
1245 {
87cce04c
MC
1246 // There is a free transaction area in blocks created by most miners,
1247 // * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
16b3ff66
GA
1248 // to be considered to fall into this category. We don't want to encourage sending
1249 // multiple transactions instead of one big transaction to avoid fees.
b33d1f5e 1250 if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000))
87cce04c 1251 nMinFee = 0;
76970091 1252 }
8d655683 1253
76970091
JG
1254 if (!MoneyRange(nMinFee))
1255 nMinFee = MAX_MONEY;
1256 return nMinFee;
1257}
1258
450cbb09 1259
3fef7c32 1260bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee)
0a61b0df 1261{
e07c943c 1262 AssertLockHeld(cs_main);
0a61b0df 1263 if (pfMissingInputs)
1264 *pfMissingInputs = false;
9000990c 1265
be126699
JG
1266 int nextBlockHeight = chainActive.Height() + 1;
1267 auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus());
9000990c 1268
da6d9391
S
1269 // Node operator can choose to reject tx by number of transparent inputs
1270 static_assert(std::numeric_limits<size_t>::max() >= std::numeric_limits<int64_t>::max(), "size_t too small");
1271 size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0);
1272 if (limit > 0) {
1273 size_t n = tx.vin.size();
1274 if (n > limit) {
1275 LogPrint("mempool", "Dropping txid %s : too many transparent inputs %zu > limit %zu\n", tx.GetHash().ToString(), n, limit );
1276 return false;
1277 }
1278 }
9000990c 1279
6fb8d0c2 1280 auto verifier = libzcash::ProofVerifier::Strict();
86131275 1281 if ( komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 )
e7fa1876 1282 {
66294e69 1283 //fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n");
e7fa1876 1284 return error("AcceptToMemoryPool: komodo_validate_interest failed");
14aa6cc0 1285 }
6fb8d0c2 1286 if (!CheckTransaction(tx, state, verifier))
c7a1d234 1287 {
1288
4f1ee565 1289 return error("AcceptToMemoryPool: CheckTransaction failed");
c7a1d234 1290 }
072099d7
S
1291 // DoS level set to 10 to be more forgiving.
1292 // Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
c7a1d234 1293 if (!ContextualCheckTransaction(tx, state, nextBlockHeight, 10))
1294 {
072099d7 1295 return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
68c266b2 1296 }
9000990c 1297
0a61b0df 1298 // Coinbase is only valid in a block, not as a loose transaction
d01903e7 1299 if (tx.IsCoinBase())
9eb44c75 1300 {
1301 fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n");
1302 return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"),REJECT_INVALID, "coinbase");
1303 }
d9ace8ab 1304 // Rather not work on nonstandard transactions (unless -testnet/-regtest)
980bfe6e 1305 string reason;
072099d7 1306 if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight))
9eb44c75 1307 {
9000990c 1308 fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\n",reason.c_str());
9eb44c75 1309 return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason),REJECT_NONSTANDARD, reason);
1310 }
0ea28bae
PT
1311 // Only accept nLockTime-using transactions that can be mined in the next
1312 // block; we don't want our mempool filled up with transactions that can't
1313 // be mined yet.
a1d3c6fb 1314 if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
9eb44c75 1315 {
9e8b81f6 1316 //fprintf(stderr,"AcceptToMemoryPool reject non-final\n");
a1d3c6fb 1317 return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
9eb44c75 1318 }
450cbb09 1319 // is it already in the memory pool?
805344dc 1320 uint256 hash = tx.GetHash();
319b1160 1321 if (pool.exists(hash))
ff2d88cc 1322 {
99fb7ab3 1323 //fprintf(stderr,"already in mempool\n");
0cb91a8d 1324 return state.Invalid(false, REJECT_DUPLICATE, "already in mempool");
ff2d88cc 1325 }
9000990c 1326
0a61b0df 1327 // Check for conflicts with in-memory transactions
319b1160 1328 {
9000990c 1329 LOCK(pool.cs); // protect pool.mapNextTx
1330 for (unsigned int i = 0; i < tx.vin.size(); i++)
0a61b0df 1331 {
9000990c 1332 COutPoint outpoint = tx.vin[i].prevout;
1333 if (pool.mapNextTx.count(outpoint))
d66877af 1334 {
d6eb511b 1335 //static uint32_t counter;
9000990c 1336 // Disable replacement feature for now
1337 //if ( counter++ < 100 )
d6eb511b 1338 //fprintf(stderr,"Disable replacement feature for now\n");
d66877af
SB
1339 return false;
1340 }
0a61b0df 1341 }
9000990c 1342 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit)
1343 {
1344 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers)
d66877af 1345 {
9000990c 1346 if (pool.mapNullifiers.count(nf))
1347 {
1348 fprintf(stderr,"pool.mapNullifiers.count\n");
1349 return false;
1350 }
d66877af
SB
1351 }
1352 }
1353 }
8d655683 1354
0a61b0df 1355 {
4afc0b54 1356 CCoinsView dummy;
7c70438d 1357 CCoinsViewCache view(&dummy);
355ca565 1358 int64_t interest;
a372168e 1359 CAmount nValueIn = 0;
4afc0b54 1360 {
9000990c 1361 LOCK(pool.cs);
1362 CCoinsViewMemPool viewMemPool(pcoinsTip, pool);
1363 view.SetBackend(viewMemPool);
1364
1365 // do we already have it?
1366 if (view.HaveCoins(hash))
1367 {
46d1074a 1368 //fprintf(stderr,"view.HaveCoins(hash) error\n");
0cb91a8d 1369 return state.Invalid(false, REJECT_DUPLICATE, "already have coins");
450cbb09 1370 }
9000990c 1371
3c760413
SS
1372 if (tx.IsCoinImport())
1373 {
1374 // Inverse of normal case; if input exists, it's been spent
1375 if (ExistsImportTombstone(tx, view))
1376 return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
1377 }
1378 else
9000990c 1379 {
0cb91a8d
SS
1380 // do all inputs exist?
1381 // Note that this does not check for the presence of actual outputs (see the next check for that),
1382 // and only helps with filling in pfMissingInputs (to determine missing vs spent).
1383 BOOST_FOREACH(const CTxIn txin, tx.vin)
9000990c 1384 {
0cb91a8d
SS
1385 if (!view.HaveCoins(txin.prevout.hash))
1386 {
1387 if (pfMissingInputs)
1388 *pfMissingInputs = true;
1389 //fprintf(stderr,"missing inputs\n");
1390 return false;
1391 }
1392 }
1393
1394 // are the actual inputs available?
1395 if (!view.HaveInputs(tx))
1396 {
1397 //fprintf(stderr,"accept failure.1\n");
1398 return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
9000990c 1399 }
9000990c 1400 }
1401 // are the joinsplit's requirements met?
1402 if (!view.HaveJoinSplitRequirements(tx))
1403 {
60aee10d 1404 //fprintf(stderr,"accept failure.2\n");
9000990c 1405 return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met");
1406 }
1407
1408 // Bring the best block into scope
1409 view.GetBestBlock();
1410
86131275 1411 nValueIn = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime);
f595c2e0 1412 if ( 0 && interest != 0 )
4a4e912b 1413 fprintf(stderr,"add interest %.8f\n",(double)interest/COIN);
9000990c 1414 // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
1415 view.SetBackend(dummy);
4afc0b54 1416 }
9000990c 1417
922e8e29 1418 // Check for non-standard pay-to-script-hash in inputs
be126699 1419 if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId))
9000990c 1420 return error("AcceptToMemoryPool: reject nonstandard transaction input");
1421
9ee09dc6
PT
1422 // Check that the transaction doesn't have an excessive number of
1423 // sigops, making it impossible to mine. Since the coinbase transaction
23f34359 1424 // itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
9ee09dc6
PT
1425 // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
1426 // merely non-standard transaction.
1427 unsigned int nSigOps = GetLegacySigOpCount(tx);
1428 nSigOps += GetP2SHSigOpCount(tx, view);
23f34359 1429 if (nSigOps > MAX_STANDARD_TX_SIGOPS)
68c266b2 1430 {
1431 fprintf(stderr,"accept failure.4\n");
1432 return state.DoS(0, error("AcceptToMemoryPool: too many sigops %s, %d > %d", hash.ToString(), nSigOps, MAX_STANDARD_TX_SIGOPS),REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
1433 }
8d655683 1434
a372168e
MF
1435 CAmount nValueOut = tx.GetValueOut();
1436 CAmount nFees = nValueIn-nValueOut;
4d707d51 1437 double dPriority = view.GetPriority(tx, chainActive.Height());
9000990c 1438
a4b25180
SD
1439 // Keep track of transactions that spend a coinbase, which we re-scan
1440 // during reorgs to ensure COINBASE_MATURITY is still met.
1441 bool fSpendsCoinbase = false;
0cb91a8d
SS
1442 if (!tx.IsCoinImport()) {
1443 BOOST_FOREACH(const CTxIn &txin, tx.vin) {
1444 const CCoins *coins = view.AccessCoins(txin.prevout.hash);
1445 if (coins->IsCoinBase()) {
1446 fSpendsCoinbase = true;
1447 break;
1448 }
a4b25180
SD
1449 }
1450 }
9000990c 1451
34a64fe0
JG
1452 // Grab the branch ID we expect this transaction to commit to. We don't
1453 // yet know if it does, but if the entry gets added to the mempool, then
1454 // it has passed ContextualCheckInputs and therefore this is correct.
1455 auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
9000990c 1456
34a64fe0 1457 CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx), fSpendsCoinbase, consensusBranchId);
4d707d51 1458 unsigned int nSize = entry.GetTxSize();
9000990c 1459
9ddb6ad0
S
1460 // Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany.
1461 if (tx.vjoinsplit.size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) {
1462 // In future we will we have more accurate and dynamic computation of fees for tx with joinsplits.
1463 } else {
1464 // Don't accept it if it can't get into a block
1465 CAmount txMinFee = GetMinRelayFee(tx, nSize, true);
1466 if (fLimitFree && nFees < txMinFee)
68c266b2 1467 {
ad4ca5c5 1468 //fprintf(stderr,"accept failure.5\n");
68c266b2 1469 return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee");
1470 }
9ddb6ad0 1471 }
9000990c 1472
1c52aad5 1473 // Require that free transactions have sufficient priority to be mined in the next block.
a5150a15 1474 if (GetBoolArg("-relaypriority", false) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
68c266b2 1475 fprintf(stderr,"accept failure.6\n");
1c52aad5
PW
1476 return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
1477 }
9000990c 1478
bf7835c2 1479 // Continuously rate-limit free (really, very-low-fee) transactions
88abf703 1480 // This mitigates 'penny-flooding' -- sending thousands of free transactions just to
b49f1398 1481 // be annoying or make others' transactions take longer to confirm.
13fc83c7 1482 if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
97ee01ad 1483 {
98e84aae 1484 static CCriticalSection csFreeLimiter;
5de8b54c 1485 static double dFreeCount;
98e84aae
WL
1486 static int64_t nLastTime;
1487 int64_t nNow = GetTime();
9000990c 1488
98e84aae 1489 LOCK(csFreeLimiter);
9000990c 1490
98e84aae
WL
1491 // Use an exponentially decaying ~10-minute window:
1492 dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
1493 nLastTime = nNow;
1494 // -limitfreerelay unit is thousand-bytes-per-minute
1495 // At default rate it would take over a month to fill 1GB
1496 if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
68c266b2 1497 {
1498 fprintf(stderr,"accept failure.7\n");
3fef7c32 1499 return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "rate limited free transaction");
68c266b2 1500 }
319b1160 1501 LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
98e84aae 1502 dFreeCount += nSize;
97ee01ad 1503 }
9000990c 1504
b310d585 1505 if (fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19 )
68c266b2 1506 {
1507 fprintf(stderr,"accept failure.8\n");
1508 return error("AcceptToMemoryPool: absurdly high fees %s, %d > %d",hash.ToString(), nFees, ::minRelayTxFee.GetFee(nSize) * 10000);
1509 }
9000990c 1510
8d7849b6
GA
1511 // Check against previous transactions
1512 // This is done last to help prevent CPU exhaustion denial-of-service attacks.
6514771a 1513 PrecomputedTransactionData txdata(tx);
be126699 1514 if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
8d7849b6 1515 {
60aee10d 1516 //fprintf(stderr,"accept failure.9\n");
bf7835c2 1517 return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
8d7849b6 1518 }
9000990c 1519
7c041b3b
PT
1520 // Check again against just the consensus-critical mandatory script
1521 // verification flags, in case of bugs in the standard flags that cause
1522 // transactions to pass as valid when they're actually invalid. For
1523 // instance the STRICTENC flag was incorrectly allowing certain
1524 // CHECKSIG NOT scripts to pass, even though they were invalid.
1525 //
1526 // There is a similar check in CreateNewBlock() to prevent creating
1527 // invalid blocks, however allowing such transactions into the mempool
1528 // can be exploited as a DoS attack.
0cb91a8d 1529 // XXX: is this neccesary for CryptoConditions?
be126699 1530 if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
7c041b3b 1531 {
68c266b2 1532 fprintf(stderr,"accept failure.10\n");
4f1ee565 1533 return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString());
7c041b3b 1534 }
9000990c 1535
cd057bfd 1536 // Store transaction in memory
f24b36ca 1537 if ( komodo_is_notarytx(tx) == 0 )
1538 KOMODO_ON_DEMAND++;
b649e039 1539 pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
8b78a819
T
1540
1541 // Add memory address index
1542 if (fAddressIndex) {
1543 pool.addAddressIndex(entry, view);
1544 }
1545
1546 // Add memory spent index
1547 if (fSpentIndex) {
1548 pool.addSpentIndex(entry, view);
1549 }
d640a3ce 1550 }
9000990c 1551
0d27dad8 1552 SyncWithWallets(tx, NULL);
9000990c 1553
cd057bfd 1554 return true;
d640a3ce
TH
1555}
1556
8b78a819
T
1557bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector<std::pair<uint256, unsigned int> > &hashes)
1558{
1559 if (!fTimestampIndex)
1560 return error("Timestamp index not enabled");
1561
1562 if (!pblocktree->ReadTimestampIndex(high, low, fActiveOnly, hashes))
1563 return error("Unable to get hashes for timestamps");
1564
1565 return true;
1566}
1567
1568bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value)
1569{
1570 if (!fSpentIndex)
1571 return false;
1572
1573 if (mempool.getSpentIndex(key, value))
1574 return true;
1575
1576 if (!pblocktree->ReadSpentIndex(key, value))
1577 return false;
1578
1579 return true;
1580}
1581
1582bool GetAddressIndex(uint160 addressHash, int type,
1583 std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex, int start, int end)
1584{
1585 if (!fAddressIndex)
1586 return error("address index not enabled");
1587
1588 if (!pblocktree->ReadAddressIndex(addressHash, type, addressIndex, start, end))
1589 return error("unable to get txids for address");
1590
1591 return true;
1592}
1593
1594bool GetAddressUnspent(uint160 addressHash, int type,
1595 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs)
1596{
1597 if (!fAddressIndex)
1598 return error("address index not enabled");
1599
1600 if (!pblocktree->ReadAddressUnspentIndex(addressHash, type, unspentOutputs))
1601 return error("unable to get txids for address");
1602
1603 return true;
1604}
1605
21f17b88 1606bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock)
1607{
f7522720 1608 // need a GetTransaction without lock so the validation code for assets can run without deadlock
21f17b88 1609 {
2a6a442a 1610 //fprintf(stderr,"check mempool\n");
63a24829 1611 if (mempool.lookup(hash, txOut))
1612 {
2a6a442a 1613 //fprintf(stderr,"found in mempool\n");
63a24829 1614 return true;
1615 }
21f17b88 1616 }
2a6a442a 1617 //fprintf(stderr,"check disk\n");
21f17b88 1618
1619 if (fTxIndex) {
1620 CDiskTxPos postx;
2a6a442a 1621 //fprintf(stderr,"ReadTxIndex\n");
21f17b88 1622 if (pblocktree->ReadTxIndex(hash, postx)) {
2a6a442a 1623 //fprintf(stderr,"OpenBlockFile\n");
21f17b88 1624 CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
1625 if (file.IsNull())
1626 return error("%s: OpenBlockFile failed", __func__);
1627 CBlockHeader header;
2a6a442a 1628 //fprintf(stderr,"seek and read\n");
21f17b88 1629 try {
1630 file >> header;
1631 fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
1632 file >> txOut;
1633 } catch (const std::exception& e) {
1634 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
1635 }
1636 hashBlock = header.GetHash();
1637 if (txOut.GetHash() != hash)
1638 return error("%s: txid mismatch", __func__);
2a6a442a 1639 //fprintf(stderr,"found on disk\n");
21f17b88 1640 return true;
1641 }
1642 }
2a6a442a 1643 //fprintf(stderr,"not found\n");
21f17b88 1644 return false;
1645}
1646
c5b390b6 1647/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
450cbb09 1648bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
c73ba23e 1649{
450cbb09 1650 CBlockIndex *pindexSlow = NULL;
8d655683 1651
01878c9c 1652 LOCK(cs_main);
8d655683 1653
01878c9c 1654 if (mempool.lookup(hash, txOut))
c73ba23e 1655 {
01878c9c
AM
1656 return true;
1657 }
8d655683 1658
01878c9c
AM
1659 if (fTxIndex) {
1660 CDiskTxPos postx;
1661 if (pblocktree->ReadTxIndex(hash, postx)) {
1662 CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
1663 if (file.IsNull())
1664 return error("%s: OpenBlockFile failed", __func__);
1665 CBlockHeader header;
1666 try {
1667 file >> header;
1668 fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
1669 file >> txOut;
1670 } catch (const std::exception& e) {
1671 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
2d1fa42e 1672 }
01878c9c 1673 hashBlock = header.GetHash();
805344dc 1674 if (txOut.GetHash() != hash)
01878c9c
AM
1675 return error("%s: txid mismatch", __func__);
1676 return true;
2d1fa42e 1677 }
01878c9c 1678 }
8d655683 1679
01878c9c
AM
1680 if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it
1681 int nHeight = -1;
1682 {
1683 CCoinsViewCache &view = *pcoinsTip;
1684 const CCoins* coins = view.AccessCoins(hash);
1685 if (coins)
1686 nHeight = coins->nHeight;
c73ba23e 1687 }
01878c9c
AM
1688 if (nHeight > 0)
1689 pindexSlow = chainActive[nHeight];
c73ba23e 1690 }
8d655683 1691
450cbb09
PW
1692 if (pindexSlow) {
1693 CBlock block;
b8add6a4 1694 if (ReadBlockFromDisk(block, pindexSlow,1)) {
450cbb09 1695 BOOST_FOREACH(const CTransaction &tx, block.vtx) {
805344dc 1696 if (tx.GetHash() == hash) {
450cbb09
PW
1697 txOut = tx;
1698 hashBlock = pindexSlow->GetBlockHash();
1699 return true;
1700 }
1701 }
1702 }
1703 }
8d655683 1704
450cbb09
PW
1705 return false;
1706}
0a61b0df 1707
352f8081 1708/*char *komodo_getspendscript(uint256 hash,int32_t n)
8d655683 1709 {
1710 CTransaction tx; uint256 hashBlock;
1711 if ( !GetTransaction(hash,tx,hashBlock,true) )
1712 {
1713 printf("null GetTransaction\n");
1714 return(0);
1715 }
1716 if ( n >= 0 && n < tx.vout.size() )
1717 return((char *)tx.vout[n].scriptPubKey.ToString().c_str());
1718 else printf("getspendscript illegal n.%d\n",n);
1719 return(0);
1720 }*/
0a61b0df 1721
1722
1723//////////////////////////////////////////////////////////////////////////////
1724//
1725// CBlock and CBlockIndex
1726//
1727
e6973430 1728bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
226f8219
EL
1729{
1730 // Open history file to append
eee030f6 1731 CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
fef24cab 1732 if (fileout.IsNull())
5262fde0 1733 return error("WriteBlockToDisk: OpenBlockFile failed");
8d655683 1734
226f8219
EL
1735 // Write index header
1736 unsigned int nSize = fileout.GetSerializeSize(block);
e6973430 1737 fileout << FLATDATA(messageStart) << nSize;
8d655683 1738
226f8219 1739 // Write block
a8738238 1740 long fileOutPos = ftell(fileout.Get());
226f8219 1741 if (fileOutPos < 0)
5262fde0 1742 return error("WriteBlockToDisk: ftell failed");
226f8219
EL
1743 pos.nPos = (unsigned int)fileOutPos;
1744 fileout << block;
8d655683 1745
226f8219
EL
1746 return true;
1747}
1748
b8add6a4 1749bool ReadBlockFromDisk(int32_t height,CBlock& block, const CDiskBlockPos& pos,bool checkPOW)
80313994 1750{
f2dd868d 1751 uint8_t pubkey33[33];
80313994 1752 block.SetNull();
8d655683 1753
80313994 1754 // Open history file to read
eee030f6 1755 CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
fef24cab 1756 if (filein.IsNull())
81a77e92 1757 {
681589a5 1758 //fprintf(stderr,"readblockfromdisk err A\n");
4342e69b 1759 return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString());
81a77e92 1760 }
8d655683 1761
80313994
EL
1762 // Read block
1763 try {
1764 filein >> block;
1765 }
27df4123 1766 catch (const std::exception& e) {
81a77e92 1767 fprintf(stderr,"readblockfromdisk err B\n");
f5791c6a 1768 return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString());
80313994 1769 }
80313994 1770 // Check the header
02290a3f 1771 if ( 0 && checkPOW != 0 )
e4b3ad62 1772 {
b8add6a4 1773 komodo_block2pubkey33(pubkey33,(CBlock *)&block);
1774 if (!(CheckEquihashSolution(&block, Params()) && CheckProofOfWork(height,pubkey33,block.GetHash(), block.nBits, Params().GetConsensus(),block.nTime)))
1775 {
1776 int32_t i; for (i=0; i<33; i++)
1777 fprintf(stderr,"%02x",pubkey33[i]);
1778 fprintf(stderr," warning unexpected diff at ht.%d\n",height);
1779
1780 return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
1781 }
e4b3ad62 1782 }
80313994
EL
1783 return true;
1784}
1785
b8add6a4 1786bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW)
0a61b0df 1787{
446ad3a7 1788 if ( pindex == 0 )
1789 return false;
b8add6a4 1790 if (!ReadBlockFromDisk(pindex->nHeight,block, pindex->GetBlockPos(),checkPOW))
0a61b0df 1791 return false;
7db120d5 1792 if (block.GetHash() != pindex->GetBlockHash())
f5791c6a 1793 return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
8d655683 1794 pindex->ToString(), pindex->GetBlockPos().ToString());
0a61b0df 1795 return true;
1796}
1797
314350e6 1798//uint64_t komodo_moneysupply(int32_t height);
7c130297 1799extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
7a4c01c9 1800extern uint32_t ASSETCHAINS_MAGIC;
9339a0cb 1801extern uint64_t ASSETCHAINS_STAKED,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY;
36f9e6d6 1802extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE;
5203fc4b 1803
935bd0a4 1804CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
0a61b0df 1805{
6e94384f 1806 static uint64_t cached_subsidy; static int32_t cached_numhalvings;
53a94b28 1807 int32_t numhalvings,i; uint64_t numerator; CAmount nSubsidy = 3 * COIN;
9a2f3a40 1808 if ( ASSETCHAINS_SYMBOL[0] == 0 )
7a4c01c9 1809 {
9a2f3a40 1810 if ( nHeight == 1 )
7a4c01c9 1811 return(100000000 * COIN); // ICO allocation
314350e6 1812 else if ( nHeight < KOMODO_ENDOFERA ) //komodo_moneysupply(nHeight) < MAX_MONEY )
9a2f3a40 1813 return(3 * COIN);
1814 else return(0);
1815 }
1816 else
1817 {
1818 if ( nHeight == 1 )
9710a28a 1819 {
1820 if ( ASSETCHAINS_STAKED == 0 || strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 )
1821 return(ASSETCHAINS_SUPPLY * COIN + (ASSETCHAINS_MAGIC & 0xffffff));
1822 else return(ASSETCHAINS_SUPPLY * COIN + ASSETCHAINS_MAGIC);
1823 }
8683bd8d 1824 else if ( ASSETCHAINS_ENDSUBSIDY == 0 || nHeight < ASSETCHAINS_ENDSUBSIDY )
1825 {
1826 if ( ASSETCHAINS_REWARD == 0 )
1827 return(10000);
9757c8f9 1828 else if ( ASSETCHAINS_ENDSUBSIDY != 0 && nHeight >= ASSETCHAINS_ENDSUBSIDY )
8683bd8d 1829 return(0);
1830 else
1831 {
1832 nSubsidy = ASSETCHAINS_REWARD;
1833 if ( ASSETCHAINS_HALVING != 0 )
1834 {
1835 if ( (numhalvings= (nHeight / ASSETCHAINS_HALVING)) > 0 )
1836 {
1837 if ( numhalvings >= 64 && ASSETCHAINS_DECAY == 0 )
1838 return(0);
1839 if ( ASSETCHAINS_DECAY == 0 )
1840 nSubsidy >>= numhalvings;
9757c8f9 1841 else if ( ASSETCHAINS_DECAY == 100000000 && ASSETCHAINS_ENDSUBSIDY != 0 )
8683bd8d 1842 {
9757c8f9 1843 numerator = (ASSETCHAINS_ENDSUBSIDY - nHeight);
53a94b28 1844 nSubsidy = (nSubsidy * numerator) / ASSETCHAINS_ENDSUBSIDY;
8683bd8d 1845 }
1846 else
1847 {
6e94384f 1848 if ( cached_subsidy > 0 && cached_numhalvings == numhalvings )
1849 nSubsidy = cached_subsidy;
1850 else
1851 {
1852 for (i=0; i<numhalvings&&nSubsidy!=0; i++)
1853 nSubsidy = (nSubsidy * ASSETCHAINS_DECAY) / 100000000;
1854 cached_subsidy = nSubsidy;
1855 cached_numhalvings = numhalvings;
1856 }
8683bd8d 1857 }
1858 }
1859 }
1860 }
1861 return(nSubsidy);
1862 } else return(0);
7a4c01c9 1863 }
8d655683 1864 /*
1865 // Mining slow start
1866 // The subsidy is ramped up linearly, skipping the middle payout of
1867 // MAX_SUBSIDY/2 to keep the monetary curve consistent with no slow start.
1868 if (nHeight < consensusParams.nSubsidySlowStartInterval / 2) {
1869 nSubsidy /= consensusParams.nSubsidySlowStartInterval;
1870 nSubsidy *= nHeight;
1871 return nSubsidy;
1872 } else if (nHeight < consensusParams.nSubsidySlowStartInterval) {
1873 nSubsidy /= consensusParams.nSubsidySlowStartInterval;
1874 nSubsidy *= (nHeight+1);
1875 return nSubsidy;
1876 }
1877
1878 assert(nHeight > consensusParams.SubsidySlowStartShift());
1879 int halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nSubsidyHalvingInterval;*/
c5a9d2ca 1880 // Force block reward to zero when right shift is undefined.
5203fc4b 1881 //int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
1882 //if (halvings >= 64)
1883 // return 0;
8d655683 1884
45e3deea 1885 // Subsidy is cut in half every 840,000 blocks which will occur approximately every 4 years.
5203fc4b 1886 //nSubsidy >>= halvings;
935bd0a4 1887 return nSubsidy;
0a61b0df 1888}
1889
0a61b0df 1890bool IsInitialBlockDownload()
1891{
e1e3f309 1892 const CChainParams& chainParams = Params();
55a1db4f 1893 LOCK(cs_main);
a8cdaf5c 1894 if (fImporting || fReindex)
8e157f52 1895 {
03491950 1896 //fprintf(stderr,"IsInitialBlockDownload: fImporting %d || %d fReindex\n",(int32_t)fImporting,(int32_t)fReindex);
a8cdaf5c 1897 return true;
8e157f52 1898 }
a8cdaf5c 1899 if (fCheckpointsEnabled && chainActive.Height() < Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()))
8e157f52 1900 {
03491950 1901 //fprintf(stderr,"IsInitialBlockDownload: checkpoint -> initialdownload\n");
0a61b0df 1902 return true;
8e157f52 1903 }
9ec75c5e
RDP
1904 static bool lockIBDState = false;
1905 if (lockIBDState)
cb237ef8 1906 {
03491950 1907 //fprintf(stderr,"lockIBDState true %d < %d\n",chainActive.Height(),pindexBestHeader->nHeight - 10);
9ec75c5e 1908 return false;
cb237ef8 1909 }
03491950 1910 bool state; CBlockIndex *ptr = chainActive.Tip();
1911 if ( ptr == 0 )
1912 ptr = pindexBestHeader;
1dcfdab7 1913 else if ( pindexBestHeader != 0 && pindexBestHeader->nHeight > ptr->nHeight )
1914 ptr = pindexBestHeader;
1931844a 1915 //if ( ASSETCHAINS_SYMBOL[0] == 0 )
8d655683 1916 state = ((chainActive.Height() < ptr->nHeight - 24*60) ||
1917 ptr->GetBlockTime() < (GetTime() - chainParams.MaxTipAge()));
1931844a 1918 //else state = (chainActive.Height() < ptr->nHeight - 24*60);
b11963b5 1919 //fprintf(stderr,"state.%d ht.%d vs %d, t.%u %u\n",state,(int32_t)chainActive.Height(),(uint32_t)ptr->nHeight,(int32_t)ptr->GetBlockTime(),(uint32_t)(GetTime() - chainParams.MaxTipAge()));
9ec75c5e 1920 if (!state)
8e157f52 1921 {
9ec75c5e 1922 lockIBDState = true;
8e157f52 1923 }
9ec75c5e 1924 return state;
0a61b0df 1925}
1926
b8585384 1927bool fLargeWorkForkFound = false;
f65e7092 1928bool fLargeWorkInvalidChainFound = false;
b8585384
MC
1929CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
1930
1931void CheckForkWarningConditions()
1932{
e07c943c 1933 AssertLockHeld(cs_main);
55ed3f14
MC
1934 // Before we get past initial download, we cannot reliably alert about forks
1935 // (we assume we don't get stuck on a fork before the last checkpoint)
1936 if (IsInitialBlockDownload())
1937 return;
8d655683 1938
d4388ed5 1939 // If our best fork is no longer within 288 blocks (+/- 12 hours if no one mines it)
b8585384 1940 // of our head, drop it
d4388ed5 1941 if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 288)
b8585384 1942 pindexBestForkTip = NULL;
8d655683 1943
86131275 1944 if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.LastTip()->nChainWork + (GetBlockProof(*chainActive.LastTip()) * 6)))
b8585384 1945 {
730b1ed1 1946 if (!fLargeWorkForkFound && pindexBestForkBase)
f89faa25 1947 {
e01a7939 1948 std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
8d655683 1949 pindexBestForkBase->phashBlock->ToString() + std::string("'");
e01a7939 1950 CAlert::Notify(warning, true);
f89faa25 1951 }
730b1ed1 1952 if (pindexBestForkTip && pindexBestForkBase)
f65e7092 1953 {
30c1db1c 1954 LogPrintf("%s: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n", __func__,
8d655683 1955 pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(),
1956 pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString());
f65e7092
MC
1957 fLargeWorkForkFound = true;
1958 }
1959 else
1960 {
57c074e1
TH
1961 std::string warning = std::string("Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.");
1962 LogPrintf("%s: %s\n", warning.c_str(), __func__);
1963 CAlert::Notify(warning, true);
f65e7092
MC
1964 fLargeWorkInvalidChainFound = true;
1965 }
1966 }
1967 else
1968 {
b8585384 1969 fLargeWorkForkFound = false;
f65e7092
MC
1970 fLargeWorkInvalidChainFound = false;
1971 }
b8585384
MC
1972}
1973
1974void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
1975{
e07c943c 1976 AssertLockHeld(cs_main);
b8585384
MC
1977 // If we are on a fork that is sufficiently large, set a warning flag
1978 CBlockIndex* pfork = pindexNewForkTip;
86131275 1979 CBlockIndex* plonger = chainActive.LastTip();
b8585384
MC
1980 while (pfork && pfork != plonger)
1981 {
1982 while (plonger && plonger->nHeight > pfork->nHeight)
1983 plonger = plonger->pprev;
1984 if (pfork == plonger)
1985 break;
1986 pfork = pfork->pprev;
1987 }
8d655683 1988
7e6d23b1 1989 // We define a condition where we should warn the user about as a fork of at least 7 blocks
4e3ac9b0 1990 // with a tip within 72 blocks (+/- 3 hours if no one mines it) of ours
b8585384
MC
1991 // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network
1992 // hash rate operating on the fork.
1993 // or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
1994 // We define it this way because it allows us to only store the highest fork tip (+ base) which meets
1995 // the 7-block condition and from this always have the most-likely-to-cause-warning fork
1996 if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
8d655683 1997 pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) &&
1998 chainActive.Height() - pindexNewForkTip->nHeight < 72)
b8585384
MC
1999 {
2000 pindexBestForkTip = pindexNewForkTip;
2001 pindexBestForkBase = pfork;
2002 }
8d655683 2003
b8585384
MC
2004 CheckForkWarningConditions();
2005}
2006
f59d8f0b 2007// Requires cs_main.
75f51f2a
PW
2008void Misbehaving(NodeId pnode, int howmuch)
2009{
2010 if (howmuch == 0)
2011 return;
8d655683 2012
75f51f2a
PW
2013 CNodeState *state = State(pnode);
2014 if (state == NULL)
2015 return;
8d655683 2016
75f51f2a 2017 state->nMisbehavior += howmuch;
42bdb117 2018 int banscore = GetArg("-banscore", 101);
dc942e6f 2019 if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore)
75f51f2a 2020 {
30c1db1c 2021 LogPrintf("%s: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", __func__, state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
75f51f2a
PW
2022 state->fShouldBan = true;
2023 } else
30c1db1c 2024 LogPrintf("%s: %s (%d -> %d)\n", __func__, state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
75f51f2a
PW
2025}
2026
64c7ee7e 2027void static InvalidChainFound(CBlockIndex* pindexNew)
0a61b0df 2028{
85eb2cef 2029 if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
85eb2cef 2030 pindexBestInvalid = pindexNew;
8d655683 2031
30c1db1c 2032 LogPrintf("%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", __func__,
8d655683 2033 pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
2034 log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
2035 pindexNew->GetBlockTime()));
86131275 2036 CBlockIndex *tip = chainActive.LastTip();
4a374102 2037 assert (tip);
30c1db1c 2038 LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__,
8d655683 2039 tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0),
2040 DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime()));
b8585384 2041 CheckForkWarningConditions();
0a61b0df 2042}
2043
75f51f2a
PW
2044void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
2045 int nDoS = 0;
2046 if (state.IsInvalid(nDoS)) {
2047 std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash());
2048 if (it != mapBlockSource.end() && State(it->second)) {
307f7d48 2049 CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()};
75f51f2a
PW
2050 State(it->second)->rejects.push_back(reject);
2051 if (nDoS > 0)
2052 Misbehaving(it->second, nDoS);
857c61df 2053 }
75f51f2a
PW
2054 }
2055 if (!state.CorruptionPossible()) {
2056 pindex->nStatus |= BLOCK_FAILED_VALID;
51ce901a 2057 setDirtyBlockIndex.insert(pindex);
e17bd583 2058 setBlockIndexCandidates.erase(pindex);
75f51f2a
PW
2059 InvalidChainFound(pindex);
2060 }
857c61df
PW
2061}
2062
8cb98d91 2063void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight)
450cbb09 2064{
0cb91a8d 2065 if (!tx.IsMint()) // mark inputs spent
021f8bc6 2066 {
ab15b2ec 2067 txundo.vprevout.reserve(tx.vin.size());
f28aec01 2068 BOOST_FOREACH(const CTxIn &txin, tx.vin) {
c444c620 2069 CCoinsModifier coins = inputs.ModifyCoins(txin.prevout.hash);
2070 unsigned nPos = txin.prevout.n;
8d655683 2071
c444c620 2072 if (nPos >= coins->vout.size() || coins->vout[nPos].IsNull())
2073 assert(false);
2074 // mark an outpoint spent, and construct undo information
2075 txundo.vprevout.push_back(CTxInUndo(coins->vout[nPos]));
2076 coins->Spend(nPos);
2077 if (coins->vout.size() == 0) {
2078 CTxInUndo& undo = txundo.vprevout.back();
2079 undo.nHeight = coins->nHeight;
2080 undo.fCoinBase = coins->fCoinBase;
2081 undo.nVersion = coins->nVersion;
2082 }
450cbb09
PW
2083 }
2084 }
021f8bc6 2085 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { // spend nullifiers
cc01120a
SB
2086 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
2087 inputs.SetNullifier(nf, true);
d66877af
SB
2088 }
2089 }
021f8bc6 2090 inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); // add outputs
3c760413
SS
2091
2092 // Unorthodox state
2093 if (tx.IsCoinImport()) {
2094 // add a tombstone for the burnTx
2095 AddImportTombstone(tx, inputs, nHeight);
2096 }
2097
450cbb09
PW
2098}
2099
8cb98d91 2100void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
d7621ccf 2101{
2102 CTxUndo txundo;
8cb98d91 2103 UpdateCoins(tx, inputs, txundo, nHeight);
d7621ccf 2104}
2105
307f7d48 2106bool CScriptCheck::operator()() {
2800ce73 2107 const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
0cb91a8d
SS
2108 ServerTransactionSignatureChecker checker(ptxTo, nIn, amount, cacheStore, *txdata);
2109 if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) {
805344dc 2110 return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
307f7d48 2111 }
2800ce73
PW
2112 return true;
2113}
2114
e079f010 2115int GetSpendHeight(const CCoinsViewCache& inputs)
0a61b0df 2116{
e079f010
JT
2117 LOCK(cs_main);
2118 CBlockIndex* pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second;
2119 return pindexPrev->nHeight + 1;
2120}
f9cae832 2121
e079f010 2122namespace Consensus {
8d655683 2123 bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams)
2124 {
13c51f20
PW
2125 // This doesn't trigger the DoS code on purpose; if it did, it would make it easier
2126 // for an attacker to attempt to split the network.
05df3fc6 2127 if (!inputs.HaveInputs(tx))
805344dc 2128 return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString()));
8d655683 2129
b7e4abd6 2130 // are the JoinSplit's requirements met?
ee964faf 2131 if (!inputs.HaveJoinSplitRequirements(tx))
805344dc 2132 return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString()));
8d655683 2133
a372168e
MF
2134 CAmount nValueIn = 0;
2135 CAmount nFees = 0;
05df3fc6 2136 for (unsigned int i = 0; i < tx.vin.size(); i++)
0a61b0df 2137 {
05df3fc6 2138 const COutPoint &prevout = tx.vin[i].prevout;
629d75fa
PW
2139 const CCoins *coins = inputs.AccessCoins(prevout.hash);
2140 assert(coins);
8d655683 2141
629d75fa 2142 if (coins->IsCoinBase()) {
e079f010
JT
2143 // Ensure that coinbases are matured
2144 if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) {
2145 return state.Invalid(
8d655683 2146 error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
2147 REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
e079f010 2148 }
8d655683 2149
1d38795f 2150 // Ensure that coinbases cannot be spent to transparent outputs
c0dde76d 2151 // Disabled on regtest
d212ba32
SB
2152 if (fCoinbaseEnforcedProtectionEnabled &&
2153 consensusParams.fCoinbaseMustBeProtected &&
2154 !tx.vout.empty()) {
358ce266 2155 return state.Invalid(
8d655683 2156 error("CheckInputs(): tried to spend coinbase with transparent outputs"),
2157 REJECT_INVALID, "bad-txns-coinbase-spend-has-transparent-outputs");
1d38795f 2158 }
450cbb09 2159 }
8d655683 2160
4add41a2 2161 // Check for negative or overflow input values
629d75fa 2162 nValueIn += coins->vout[prevout.n].nValue;
782120ca 2163#ifdef KOMODO_ENABLE_INTEREST
86131275 2164 if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 )
782120ca 2165 {
98f68225 2166 if ( coins->vout[prevout.n].nValue >= 10*COIN )
782120ca 2167 {
2168 int64_t interest; int32_t txheight; uint32_t locktime;
c60397dd 2169 if ( (interest= komodo_accrued_interest(&txheight,&locktime,prevout.hash,prevout.n,0,coins->vout[prevout.n].nValue,(int32_t)nSpendHeight-1)) != 0 )
407de87c 2170 {
86131275 2171 //fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.LastTip()->nTime);
407de87c 2172 nValueIn += interest;
2173 }
782120ca 2174 }
2175 }
2176#endif
629d75fa 2177 if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn))
5262fde0 2178 return state.DoS(100, error("CheckInputs(): txin values out of range"),
14e7ffcc 2179 REJECT_INVALID, "bad-txns-inputvalues-outofrange");
8d655683 2180
4add41a2 2181 }
8d655683 2182
942bc467 2183 nValueIn += tx.GetJoinSplitValueIn();
f512cf7c
SB
2184 if (!MoneyRange(nValueIn))
2185 return state.DoS(100, error("CheckInputs(): vpub_old values out of range"),
2186 REJECT_INVALID, "bad-txns-inputvalues-outofrange");
8d655683 2187
0733c1bd 2188 if (nValueIn < tx.GetValueOut())
60aee10d 2189 {
2da1debd 2190 fprintf(stderr,"spentheight.%d valuein %s vs %s error\n",nSpendHeight,FormatMoney(nValueIn).c_str(), FormatMoney(tx.GetValueOut()).c_str());
2c0218f0 2191 return state.DoS(100, error("CheckInputs(): %s value in (%s) < value out (%s) diff %.8f",
407de87c 2192 tx.GetHash().ToString(), FormatMoney(nValueIn), FormatMoney(tx.GetValueOut()),((double)nValueIn - tx.GetValueOut())/COIN),REJECT_INVALID, "bad-txns-in-belowout");
60aee10d 2193 }
450cbb09 2194 // Tally transaction fees
a372168e 2195 CAmount nTxFee = nValueIn - tx.GetValueOut();
2c0218f0 2196 if (nTxFee < 0)
805344dc 2197 return state.DoS(100, error("CheckInputs(): %s nTxFee < 0", tx.GetHash().ToString()),
14e7ffcc 2198 REJECT_INVALID, "bad-txns-fee-negative");
450cbb09 2199 nFees += nTxFee;
2c0218f0 2200 if (!MoneyRange(nFees))
5262fde0 2201 return state.DoS(100, error("CheckInputs(): nFees out of range"),
14e7ffcc 2202 REJECT_INVALID, "bad-txns-fee-outofrange");
8d655683 2203 return true;
2204 }
e079f010
JT
2205}// namespace Consensus
2206
d55e5e77 2207bool ContextualCheckInputs(
8d655683 2208 const CTransaction& tx,
2209 CValidationState &state,
2210 const CCoinsViewCache &inputs,
2211 bool fScriptChecks,
2212 unsigned int flags,
2213 bool cacheStore,
2214 PrecomputedTransactionData& txdata,
2215 const Consensus::Params& consensusParams,
2216 uint32_t consensusBranchId,
2217 std::vector<CScriptCheck> *pvChecks)
e079f010 2218{
0cb91a8d 2219 if (!tx.IsMint())
e079f010 2220 {
30006a2e
JG
2221 if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), consensusParams)) {
2222 return false;
2223 }
8d655683 2224
e079f010
JT
2225 if (pvChecks)
2226 pvChecks->reserve(tx.vin.size());
8d655683 2227
4add41a2
GA
2228 // The first loop above does all the inexpensive checks.
2229 // Only if ALL inputs pass do we perform expensive ECDSA signature checks.
2230 // Helps prevent CPU exhaustion attacks.
8d655683 2231
450cbb09 2232 // Skip ECDSA signature verification when connecting blocks
729b1806 2233 // before the last block chain checkpoint. This is safe because block merkle hashes are
450cbb09 2234 // still computed and checked, and any change will be caught at the next checkpoint.
1d70f4bd 2235 if (fScriptChecks) {
05df3fc6
EL
2236 for (unsigned int i = 0; i < tx.vin.size(); i++) {
2237 const COutPoint &prevout = tx.vin[i].prevout;
629d75fa
PW
2238 const CCoins* coins = inputs.AccessCoins(prevout.hash);
2239 assert(coins);
8d655683 2240
b14bd4df 2241 // Verify signature
be126699 2242 CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, &txdata);
f9cae832
PW
2243 if (pvChecks) {
2244 pvChecks->push_back(CScriptCheck());
2245 check.swap(pvChecks->back());
97e7901a 2246 } else if (!check()) {
f80cffa2
PT
2247 if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) {
2248 // Check whether the failure was caused by a
2249 // non-mandatory script verification check, such as
2250 // non-standard DER encodings or non-null dummy
2251 // arguments; if so, don't trigger DoS protection to
2252 // avoid splitting the network between upgraded and
2253 // non-upgraded nodes.
838e7a29 2254 CScriptCheck check2(*coins, tx, i,
8d655683 2255 flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, &txdata);
838e7a29 2256 if (check2())
307f7d48 2257 return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
97e7901a 2258 }
f80cffa2
PT
2259 // Failures of other flags indicate a transaction that is
2260 // invalid in new blocks, e.g. a invalid P2SH. We DoS ban
2261 // such nodes as they are not following the protocol. That
2262 // said during an upgrade careful thought should be taken
2263 // as to the correct behavior - we may want to continue
2264 // peering with non-upgraded nodes even after a soft-fork
2265 // super-majority vote has passed.
307f7d48 2266 return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError())));
97e7901a 2267 }
2a45a494 2268 }
0a61b0df 2269 }
0a61b0df 2270 }
0cb91a8d
SS
2271
2272 if (tx.IsCoinImport())
2273 {
2274 ServerTransactionSignatureChecker checker(&tx, 0, 0, false, txdata);
2275 return VerifyCoinImport(tx.vin[0].scriptSig, checker, state);
2276 }
2277
0a61b0df 2278 return true;
2279}
2280
945f015d 2281
2282/*bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks)
8d655683 2283 {
2284 if (!NonContextualCheckInputs(tx, state, inputs, fScriptChecks, flags, cacheStore, consensusParams, pvChecks)) {
2285 fprintf(stderr,"ContextualCheckInputs failure.0\n");
2286 return false;
2287 }
2288
2289 if (!tx.IsCoinBase())
2290 {
2291 // While checking, GetBestBlock() refers to the parent block.
2292 // This is also true for mempool checks.
2293 CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second;
2294 int nSpendHeight = pindexPrev->nHeight + 1;
2295 for (unsigned int i = 0; i < tx.vin.size(); i++)
2296 {
2297 const COutPoint &prevout = tx.vin[i].prevout;
2298 const CCoins *coins = inputs.AccessCoins(prevout.hash);
2299 // Assertion is okay because NonContextualCheckInputs ensures the inputs
2300 // are available.
2301 assert(coins);
2302
2303 // If prev is coinbase, check that it's matured
2304 if (coins->IsCoinBase()) {
2305 if ( ASSETCHAINS_SYMBOL[0] == 0 )
2306 COINBASE_MATURITY = _COINBASE_MATURITY;
2307 if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) {
2308 fprintf(stderr,"ContextualCheckInputs failure.1 i.%d of %d\n",i,(int32_t)tx.vin.size());
2309
2310 return state.Invalid(
2311 error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
2312 }
2313 }
2314 }
2315 }
2316
2317 return true;
2318 }*/
89f3cd11 2319
8d655683 2320namespace {
2321
2322 bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
2c901fd8 2323 {
8d655683 2324 // Open history file to append
2325 CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
2326 if (fileout.IsNull())
2327 return error("%s: OpenUndoFile failed", __func__);
2328
2329 // Write index header
2330 unsigned int nSize = fileout.GetSerializeSize(blockundo);
2331 fileout << FLATDATA(messageStart) << nSize;
2332
2333 // Write undo data
2334 long fileOutPos = ftell(fileout.Get());
2335 if (fileOutPos < 0)
2336 return error("%s: ftell failed", __func__);
2337 pos.nPos = (unsigned int)fileOutPos;
2338 fileout << blockundo;
2339
2340 // calculate & write checksum
2341 CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
2342 hasher << hashBlock;
2343 hasher << blockundo;
2344 fileout << hasher.GetHash();
2345
2346 return true;
2c901fd8 2347 }
8d655683 2348
2349 bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock)
2350 {
2351 // Open history file to read
2352 CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
2353 if (filein.IsNull())
2354 return error("%s: OpenBlockFile failed", __func__);
2355
2356 // Read block
2357 uint256 hashChecksum;
2358 try {
2359 filein >> blockundo;
2360 filein >> hashChecksum;
2361 }
2362 catch (const std::exception& e) {
2363 return error("%s: Deserialize or I/O error - %s", __func__, e.what());
2364 }
8d655683 2365 // Verify checksum
2366 CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
2367 hasher << hashBlock;
2368 hasher << blockundo;
2369 if (hashChecksum != hasher.GetHash())
2370 return error("%s: Checksum mismatch", __func__);
2371
2372 return true;
87fb3108 2373 }
8d655683 2374
2375 /** Abort with a message */
2376 bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
2377 {
2378 strMiscWarning = strMessage;
2379 LogPrintf("*** %s\n", strMessage);
2380 uiInterface.ThreadSafeMessageBox(
2381 userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage,
2382 "", CClientUIInterface::MSG_ERROR);
2383 StartShutdown();
2384 return false;
87fb3108 2385 }
8d655683 2386
2387 bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="")
2388 {
2389 AbortNode(strMessage, userMessage);
2390 return state.Error(strMessage);
2391 }
2392
87fb3108 2393} // anon namespace
0a61b0df 2394
eb1c2cd3
DK
2395/**
2396 * Apply the undo operation of a CTxInUndo to the given chain state.
2397 * @param undo The undo object.
2398 * @param view The coins view to which to apply the changes.
2399 * @param out The out point that corresponds to the tx input.
2400 * @return True on success.
2401 */
2402static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
2403{
2404 bool fClean = true;
8d655683 2405
eb1c2cd3
DK
2406 CCoinsModifier coins = view.ModifyCoins(out.hash);
2407 if (undo.nHeight != 0) {
2408 // undo data contains height: this is the last output of the prevout tx being spent
2409 if (!coins->IsPruned())
2410 fClean = fClean && error("%s: undo data overwriting existing transaction", __func__);
2411 coins->Clear();
2412 coins->fCoinBase = undo.fCoinBase;
2413 coins->nHeight = undo.nHeight;
2414 coins->nVersion = undo.nVersion;
2415 } else {
2416 if (coins->IsPruned())
2417 fClean = fClean && error("%s: undo data adding output to missing transaction", __func__);
2418 }
2419 if (coins->IsAvailable(out.n))
2420 fClean = fClean && error("%s: undo data overwriting existing output", __func__);
2421 if (coins->vout.size() < out.n+1)
2422 coins->vout.resize(out.n+1);
2423 coins->vout[out.n] = undo.txout;
8d655683 2424
eb1c2cd3
DK
2425 return fClean;
2426}
2427
84964112
SS
2428
2429void ConnectNotarisations(const CBlock &block, int height)
2430{
2431 // Record Notarisations
2432 NotarisationsInBlock notarisations = ScanBlockNotarisations(block, height);
2433 if (notarisations.size() > 0) {
2434 CLevelDBBatch batch;
2435 batch.Write(block.GetHash(), notarisations);
2436 WriteBackNotarisations(notarisations, batch);
2437 pnotarisations->WriteBatch(batch, true);
2438 LogPrintf("ConnectBlock: wrote %i block notarisations in block: %s\n",
2439 notarisations.size(), block.GetHash().GetHex().data());
2440 }
2441}
2442
2443
2444void DisconnectNotarisations(const CBlock &block)
2445{
2446 // Delete from notarisations cache
2447 NotarisationsInBlock nibs;
2448 if (GetBlockNotarisations(block.GetHash(), nibs)) {
2449 CLevelDBBatch batch;
2450 batch.Erase(block.GetHash());
2451 EraseBackNotarisations(nibs, batch);
2452 pnotarisations->WriteBatch(batch, true);
2453 LogPrintf("DisconnectTip: deleted %i block notarisations in block: %s\n",
2454 nibs.size(), block.GetHash().GetHex().data());
2455 }
2456}
2457
2458
5c363ed6 2459bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
0a61b0df 2460{
84674082 2461 assert(pindex->GetBlockHash() == view.GetBestBlock());
8d655683 2462
2cbd71da
PW
2463 if (pfClean)
2464 *pfClean = false;
8d655683 2465
2cbd71da 2466 bool fClean = true;
4355e769 2467 komodo_disconnect(pindex,block);
450cbb09 2468 CBlockUndo blockUndo;
8539361e
PW
2469 CDiskBlockPos pos = pindex->GetUndoPos();
2470 if (pos.IsNull())
5262fde0 2471 return error("DisconnectBlock(): no undo data available");
e035c6a7 2472 if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash()))
5262fde0 2473 return error("DisconnectBlock(): failure reading undo data");
8d655683 2474
5c363ed6 2475 if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
5262fde0 2476 return error("DisconnectBlock(): block and undo data inconsistent");
8b78a819
T
2477 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
2478 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
2479 std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
2480
450cbb09 2481 // undo transactions in reverse order
5c363ed6
EL
2482 for (int i = block.vtx.size() - 1; i >= 0; i--) {
2483 const CTransaction &tx = block.vtx[i];
805344dc 2484 uint256 hash = tx.GetHash();
8b78a819
T
2485 if (fAddressIndex) {
2486
2487 for (unsigned int k = tx.vout.size(); k-- > 0;) {
2488 const CTxOut &out = tx.vout[k];
2489
2490 if (out.scriptPubKey.IsPayToScriptHash()) {
2491 vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
2492
2493 // undo receiving activity
2494 addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
2495
2496 // undo unspent index
2497 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), hash, k), CAddressUnspentValue()));
2498
fa7bf712 2499 }
2500 else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
2501 vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
8b78a819
T
2502
2503 // undo receiving activity
2504 addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
2505
2506 // undo unspent index
2507 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue()));
2508
fa7bf712 2509 }
2510 else if (out.scriptPubKey.IsPayToPublicKey()) {
2511 vector<unsigned char> hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
2512
2513 // undo receiving activity
31e2a04e 2514 addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
fa7bf712 2515
2516 // undo unspent index
31e2a04e 2517 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue()));
fa7bf712 2518
7f190223 2519 }
2520 else if (out.scriptPubKey.IsPayToCryptoCondition()) {
2521 vector<unsigned char> hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end());
2522
2523 // undo receiving activity
2524 addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
2525
2526 // undo unspent index
2527 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue()));
2528
fa7bf712 2529 }
2530 else {
8b78a819
T
2531 continue;
2532 }
2533
2534 }
2535
2536 }
2537
170e02de 2538 // Check that all outputs are available and match the outputs in the block itself
eb1c2cd3 2539 // exactly.
f28aec01 2540 {
8d655683 2541 CCoinsModifier outs = view.ModifyCoins(hash);
2542 outs->ClearUnspendable();
2543
2544 CCoins outsBlock(tx, pindex->nHeight);
2545 // The CCoins serialization does not serialize negative numbers.
2546 // No network rules currently depend on the version here, so an inconsistency is harmless
2547 // but it must be corrected before txout nversion ever influences a network rule.
2548 if (outsBlock.nVersion < 0)
2549 outs->nVersion = outsBlock.nVersion;
2550 if (*outs != outsBlock)
2551 fClean = fClean && error("DisconnectBlock(): added transaction mismatch? database corrupted");
2552
2553 // remove outputs
2554 outs->Clear();
f28aec01 2555 }
8d655683 2556
bfeaf004 2557 // unspend nullifiers
b7e4abd6 2558 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
cc01120a
SB
2559 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
2560 view.SetNullifier(nf, false);
d66877af
SB
2561 }
2562 }
8d655683 2563
450cbb09 2564 // restore inputs
0cb91a8d 2565 if (!tx.IsMint()) {
450cbb09 2566 const CTxUndo &txundo = blockUndo.vtxundo[i-1];
2cbd71da 2567 if (txundo.vprevout.size() != tx.vin.size())
5262fde0 2568 return error("DisconnectBlock(): transaction and undo data inconsistent");
450cbb09
PW
2569 for (unsigned int j = tx.vin.size(); j-- > 0;) {
2570 const COutPoint &out = tx.vin[j].prevout;
2571 const CTxInUndo &undo = txundo.vprevout[j];
eb1c2cd3
DK
2572 if (!ApplyTxInUndo(undo, view, out))
2573 fClean = false;
8b78a819
T
2574
2575 const CTxIn input = tx.vin[j];
2576
2577 if (fSpentIndex) {
2578 // undo and delete the spent index
2579 spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue()));
2580 }
2581
2582 if (fAddressIndex) {
2583 const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
2584 if (prevout.scriptPubKey.IsPayToScriptHash()) {
2585 vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22);
2586
2587 // undo spending activity
2588 addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
2589
2590 // restore unspent index
2591 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
2592
2593
fa7bf712 2594 }
2595 else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
2596 vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
8b78a819
T
2597
2598 // undo spending activity
2599 addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
2600
2601 // restore unspent index
2602 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
2603
fa7bf712 2604 }
2605 else if (prevout.scriptPubKey.IsPayToPublicKey()) {
2606 vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34);
2607
2608 // undo spending activity
dc276bd0 2609 addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
fa7bf712 2610
2611 // restore unspent index
dc276bd0 2612 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
fa7bf712 2613
7f190223 2614 }
2615 else if (prevout.scriptPubKey.IsPayToCryptoCondition()) {
2616 vector<unsigned char> hashBytes(prevout.scriptPubKey.begin(), prevout.scriptPubKey.end());
2617
2618 // undo spending activity
2619 addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
2620
2621 // restore unspent index
2622 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
2623
fa7bf712 2624 }
2625 else {
8b78a819
T
2626 continue;
2627 }
2628 }
450cbb09
PW
2629 }
2630 }
3c760413
SS
2631 else if (tx.IsCoinImport())
2632 {
2633 RemoveImportTombstone(tx, view);
2634 }
450cbb09 2635 }
69c67b51 2636
a8ac403d
SB
2637 // set the old best anchor back
2638 view.PopAnchor(blockUndo.old_tree_root);
8d655683 2639
450cbb09 2640 // move best block pointer to prevout block
84674082 2641 view.SetBestBlock(pindex->pprev->GetBlockHash());
8d655683 2642
2cbd71da
PW
2643 if (pfClean) {
2644 *pfClean = fClean;
2645 return true;
2cbd71da 2646 }
eb1c2cd3 2647
8b78a819
T
2648 if (fAddressIndex) {
2649 if (!pblocktree->EraseAddressIndex(addressIndex)) {
2650 return AbortNode(state, "Failed to delete address index");
2651 }
2652 if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) {
2653 return AbortNode(state, "Failed to write address unspent index");
2654 }
2655 }
69c67b51 2656
eb1c2cd3 2657 return fClean;
0a61b0df 2658}
2659
1eb57879 2660void static FlushBlockFile(bool fFinalize = false)
44d40f26
PW
2661{
2662 LOCK(cs_LastBlockFile);
8d655683 2663
a8a4b967 2664 CDiskBlockPos posOld(nLastBlockFile, 0);
8d655683 2665
44d40f26 2666 FILE *fileOld = OpenBlockFile(posOld);
b19388dd 2667 if (fileOld) {
1eb57879 2668 if (fFinalize)
ed6d1a2c 2669 TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize);
b19388dd
PK
2670 FileCommit(fileOld);
2671 fclose(fileOld);
2672 }
8d655683 2673
44d40f26 2674 fileOld = OpenUndoFile(posOld);
b19388dd 2675 if (fileOld) {
1eb57879 2676 if (fFinalize)
ed6d1a2c 2677 TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize);
b19388dd
PK
2678 FileCommit(fileOld);
2679 fclose(fileOld);
2680 }
44d40f26
PW
2681}
2682
ef3988ca 2683bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
5382bcf8 2684
f9cae832
PW
2685static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
2686
21eb5ada 2687void ThreadScriptCheck() {
7662d72b 2688 RenameThread("zcash-scriptch");
f9cae832 2689 scriptcheckqueue.Thread();
f9cae832
PW
2690}
2691
36cba8f1
GA
2692//
2693// Called periodically asynchronously; alerts if it smells like
2694// we're being fed a bad chain (blocks being generated much
2695// too slowly or too quickly).
2696//
fce474c9
GA
2697void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader,
2698 int64_t nPowTargetSpacing)
36cba8f1 2699{
fce474c9 2700 if (bestHeader == NULL || initialDownloadCheck()) return;
8d655683 2701
36cba8f1
GA
2702 static int64_t lastAlertTime = 0;
2703 int64_t now = GetAdjustedTime();
2704 if (lastAlertTime > now-60*60*24) return; // Alert at most once per day
8d655683 2705
36cba8f1
GA
2706 const int SPAN_HOURS=4;
2707 const int SPAN_SECONDS=SPAN_HOURS*60*60;
2708 int BLOCKS_EXPECTED = SPAN_SECONDS / nPowTargetSpacing;
8d655683 2709
36cba8f1 2710 boost::math::poisson_distribution<double> poisson(BLOCKS_EXPECTED);
8d655683 2711
36cba8f1
GA
2712 std::string strWarning;
2713 int64_t startTime = GetAdjustedTime()-SPAN_SECONDS;
8d655683 2714
36cba8f1 2715 LOCK(cs);
fce474c9
GA
2716 const CBlockIndex* i = bestHeader;
2717 int nBlocks = 0;
2718 while (i->GetBlockTime() >= startTime) {
2719 ++nBlocks;
2720 i = i->pprev;
c938fb1f 2721 if (i == NULL) return; // Ran out of chain, we must not be fully synced
fce474c9 2722 }
8d655683 2723
36cba8f1
GA
2724 // How likely is it to find that many by chance?
2725 double p = boost::math::pdf(poisson, nBlocks);
8d655683 2726
36cba8f1
GA
2727 LogPrint("partitioncheck", "%s : Found %d blocks in the last %d hours\n", __func__, nBlocks, SPAN_HOURS);
2728 LogPrint("partitioncheck", "%s : likelihood: %g\n", __func__, p);
8d655683 2729
36cba8f1
GA
2730 // Aim for one false-positive about every fifty years of normal running:
2731 const int FIFTY_YEARS = 50*365*24*60*60;
2732 double alertThreshold = 1.0 / (FIFTY_YEARS / SPAN_SECONDS);
8d655683 2733
36cba8f1
GA
2734 if (p <= alertThreshold && nBlocks < BLOCKS_EXPECTED)
2735 {
2736 // Many fewer blocks than expected: alert!
2737 strWarning = strprintf(_("WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)"),
2738 nBlocks, SPAN_HOURS, BLOCKS_EXPECTED);
2739 }
2740 else if (p <= alertThreshold && nBlocks > BLOCKS_EXPECTED)
2741 {
2742 // Many more blocks than expected: alert!
2743 strWarning = strprintf(_("WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)"),
2744 nBlocks, SPAN_HOURS, BLOCKS_EXPECTED);
2745 }
2746 if (!strWarning.empty())
2747 {
2748 strMiscWarning = strWarning;
2749 CAlert::Notify(strWarning, true);
2750 lastAlertTime = now;
2751 }
2752}
2753
20c3ac51 2754
d70bc52e
PW
2755static int64_t nTimeVerify = 0;
2756static int64_t nTimeConnect = 0;
2757static int64_t nTimeIndex = 0;
2758static int64_t nTimeCallbacks = 0;
2759static int64_t nTimeTotal = 0;
2760
96f9009e 2761bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW)
0a61b0df 2762{
4e382177 2763 const CChainParams& chainparams = Params();
6d2fc290 2764 if ( KOMODO_STOPAT != 0 && pindex->nHeight > KOMODO_STOPAT )
2765 return(false);
e0440cc3 2766 //fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->nHeight);
b39a07dc 2767 AssertLockHeld(cs_main);
bfa832c7
PW
2768 bool fExpensiveChecks = true;
2769 if (fCheckpointsEnabled) {
2770 CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
2771 if (pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex) {
2772 // This block is an ancestor of a checkpoint: disable script checks
2773 fExpensiveChecks = false;
2774 }
2775 }
6fb8d0c2
JG
2776 auto verifier = libzcash::ProofVerifier::Strict();
2777 auto disabledVerifier = libzcash::ProofVerifier::Disabled();
9f6cb8f0 2778 int32_t futureblock;
6fb8d0c2 2779 // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
9840ae39 2780 if (!CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
cdb2a22f 2781 {
4342e69b 2782 //fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock);
0a61b0df 2783 return false;
cdb2a22f 2784 }
8d655683 2785
450cbb09 2786 // verify that the view's current state corresponds to the previous block
4f152496 2787 uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
e3b04fea 2788 if ( hashPrevBlock != view.GetBestBlock() )
2789 {
2790 fprintf(stderr,"ConnectBlock(): hashPrevBlock != view.GetBestBlock()\n");
2791 return state.DoS(1, error("ConnectBlock(): hashPrevBlock != view.GetBestBlock()"),
2792 REJECT_INVALID, "hashPrevBlock-not-bestblock");
2793 }
84674082 2794 assert(hashPrevBlock == view.GetBestBlock());
8d655683 2795
8301ff50
PW
2796 // Special case for the genesis block, skipping connection of its transactions
2797 // (its coinbase is unspendable)
4e382177 2798 if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) {
6a7acc29 2799 if (!fJustCheck) {
1b178a7f 2800 view.SetBestBlock(pindex->GetBlockHash());
6a7acc29
JG
2801 // Before the genesis block, there was an empty tree
2802 ZCIncrementalMerkleTree tree;
2803 pindex->hashAnchor = tree.root();
0bc1e2c4
JG
2804 // The genesis block contained no JoinSplits
2805 pindex->hashAnchorEnd = pindex->hashAnchor;
6a7acc29 2806 }
8301ff50
PW
2807 return true;
2808 }
8d655683 2809
a8cdaf5c 2810 bool fScriptChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
f8b5c164 2811 //if ( KOMODO_TESTNET_EXPIRATION != 0 && pindex->nHeight > KOMODO_TESTNET_EXPIRATION ) // "testnet"
2812 // return(false);
a206b0ea
PW
2813 // Do not allow blocks that contain transactions which 'overwrite' older transactions,
2814 // unless those are already completely spent.
b3be1ef5 2815 BOOST_FOREACH(const CTransaction& tx, block.vtx) {
805344dc 2816 const CCoins* coins = view.AccessCoins(tx.GetHash());
b3be1ef5
SB
2817 if (coins && !coins->IsPruned())
2818 return state.DoS(100, error("ConnectBlock(): tried to overwrite transaction"),
2819 REJECT_INVALID, "bad-txns-BIP30");
450cbb09 2820 }
8d655683 2821
de609b8c 2822 unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
8d655683 2823
de609b8c 2824 // DERSIG (BIP66) is also always enforced, but does not have a flag.
8d655683 2825
8adf48dc 2826 CBlockUndo blockundo;
8d655683 2827
6fb8d0c2 2828 CCheckQueueControl<CScriptCheck> control(fExpensiveChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
8d655683 2829
d70bc52e 2830 int64_t nTimeStart = GetTimeMicros();
a372168e 2831 CAmount nFees = 0;
8a28bb6d 2832 int nInputs = 0;
355ca565 2833 int64_t interest,sum = 0;
7bd9c3a3 2834 unsigned int nSigOps = 0;
f3ae51dc 2835 CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
2d1fa42e 2836 std::vector<std::pair<uint256, CDiskTxPos> > vPos;
f3ae51dc 2837 vPos.reserve(block.vtx.size());
ab15b2ec 2838 blockundo.vtxundo.reserve(block.vtx.size() - 1);
8b78a819
T
2839 std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
2840 std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
2841 std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
a8ac403d
SB
2842 // Construct the incremental merkle tree at the current
2843 // block position,
2844 auto old_tree_root = view.GetBestAnchor();
b6961fc1 2845 // saving the top anchor in the block index as we go.
6a7acc29
JG
2846 if (!fJustCheck) {
2847 pindex->hashAnchor = old_tree_root;
2848 }
434f3284 2849 ZCIncrementalMerkleTree tree;
a8ac403d
SB
2850 // This should never fail: we should always be able to get the root
2851 // that is on the tip of our chain
2852 assert(view.GetAnchorAt(old_tree_root, tree));
8d655683 2853
a8ac403d
SB
2854 {
2855 // Consistency check: the root of the tree we're given should
2856 // match what we asked for.
434f3284 2857 assert(tree.root() == old_tree_root);
a8ac403d 2858 }
8d655683 2859
be126699
JG
2860 // Grab the consensus branch ID for the block's height
2861 auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, Params().GetConsensus());
8d655683 2862
6514771a
PW
2863 std::vector<PrecomputedTransactionData> txdata;
2864 txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
f3ae51dc 2865 for (unsigned int i = 0; i < block.vtx.size(); i++)
0a61b0df 2866 {
f3ae51dc 2867 const CTransaction &tx = block.vtx[i];
8b78a819 2868 const uint256 txhash = tx.GetHash();
8a28bb6d 2869 nInputs += tx.vin.size();
05df3fc6 2870 nSigOps += GetLegacySigOpCount(tx);
137d0685 2871 if (nSigOps > MAX_BLOCK_SIGOPS)
5262fde0 2872 return state.DoS(100, error("ConnectBlock(): too many sigops"),
14e7ffcc 2873 REJECT_INVALID, "bad-blk-sigops");
8d655683 2874 //fprintf(stderr,"ht.%d vout0 t%u\n",pindex->nHeight,tx.nLockTime);
0cb91a8d 2875 if (!tx.IsMint())
8d7849b6 2876 {
05df3fc6 2877 if (!view.HaveInputs(tx))
a9bad5a3 2878 {
5262fde0 2879 return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
14e7ffcc 2880 REJECT_INVALID, "bad-txns-inputs-missingorspent");
a9bad5a3 2881 }
b7e4abd6 2882 // are the JoinSplit's requirements met?
ee964faf 2883 if (!view.HaveJoinSplitRequirements(tx))
b7e4abd6
SB
2884 return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"),
2885 REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met");
8b78a819
T
2886 if (fAddressIndex || fSpentIndex)
2887 {
2888 for (size_t j = 0; j < tx.vin.size(); j++) {
2889
2890 const CTxIn input = tx.vin[j];
2891 const CTxOut &prevout = view.GetOutputFor(tx.vin[j]);
2892 uint160 hashBytes;
2893 int addressType;
2894
2895 if (prevout.scriptPubKey.IsPayToScriptHash()) {
2896 hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
2897 addressType = 2;
fa7bf712 2898 }
2899 else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
2900 hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
8b78a819 2901 addressType = 1;
fa7bf712 2902 }
2903 else if (prevout.scriptPubKey.IsPayToPublicKey()) {
31e2a04e 2904 hashBytes = Hash160(vector <unsigned char>(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34));
dc276bd0 2905 addressType = 1;
fa7bf712 2906 }
7f190223 2907 else if (prevout.scriptPubKey.IsPayToCryptoCondition()) {
2908 hashBytes = Hash160(vector <unsigned char>(prevout.scriptPubKey.begin(), prevout.scriptPubKey.end()));
2909 addressType = 1;
2910 }
fa7bf712 2911 else {
8b78a819
T
2912 hashBytes.SetNull();
2913 addressType = 0;
2914 }
2915
2916 if (fAddressIndex && addressType > 0) {
2917 // record spending activity
2918 addressIndex.push_back(make_pair(CAddressIndexKey(addressType, hashBytes, pindex->nHeight, i, txhash, j, true), prevout.nValue * -1));
2919
2920 // remove address from unspent index
2921 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(addressType, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue()));
2922 }
2923
2924 if (fSpentIndex) {
2925 // add the spent index to determine the txid and input that spent an output
2926 // and to find the amount and address from an input
2927 spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->nHeight, prevout.nValue, addressType, hashBytes)));
2928 }
2929 }
2930
2931 }
b3be1ef5
SB
2932 // Add in sigops done by pay-to-script-hash inputs;
2933 // this is to prevent a "rogue miner" from creating
2934 // an incredibly-expensive-to-validate block.
2935 nSigOps += GetP2SHSigOpCount(tx, view);
2936 if (nSigOps > MAX_BLOCK_SIGOPS)
2937 return state.DoS(100, error("ConnectBlock(): too many sigops"),
2938 REJECT_INVALID, "bad-blk-sigops");
f762d449 2939 }
8d655683 2940
6514771a 2941 txdata.emplace_back(tx);
8d655683 2942
f762d449
PW
2943 if (!tx.IsCoinBase())
2944 {
86131275 2945 nFees += view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime) - tx.GetValueOut();
355ca565 2946 sum += interest;
8d655683 2947
f9cae832 2948 std::vector<CScriptCheck> vChecks;
be126699 2949 if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL))
40634605 2950 return false;
f9cae832 2951 control.Add(vChecks);
8d7849b6 2952 }
8b78a819
T
2953
2954 if (fAddressIndex) {
2955 for (unsigned int k = 0; k < tx.vout.size(); k++) {
2956 const CTxOut &out = tx.vout[k];
ba31c2f4 2957//fprintf(stderr,"add %d vouts\n",(int32_t)tx.vout.size());
8b78a819
T
2958 if (out.scriptPubKey.IsPayToScriptHash()) {
2959 vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
2960
2961 // record receiving activity
2962 addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
2963
2964 // record unspent output
2965 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
2966
fa7bf712 2967 }
2968 else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
2969 vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
8b78a819
T
2970
2971 // record receiving activity
2972 addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
2973
2974 // record unspent output
2975 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
2976
fa7bf712 2977 }
2978 else if (out.scriptPubKey.IsPayToPublicKey()) {
2979 vector<unsigned char> hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
2980
2981 // record receiving activity
dc276bd0 2982 addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
fa7bf712 2983
2984 // record unspent output
dc276bd0 2985 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
fa7bf712 2986
7f190223 2987 }
2988 else if (out.scriptPubKey.IsPayToCryptoCondition()) {
2989 vector<unsigned char> hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end());
2990
2991 // record receiving activity
2992 addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
2993
2994 // record unspent output
2995 addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
2996
fa7bf712 2997 }
2998 else {
8b78a819
T
2999 continue;
3000 }
3001
3002 }
3003 }
3004
314350e6 3005 //if ( ASSETCHAINS_SYMBOL[0] == 0 )
3006 // komodo_earned_interest(pindex->nHeight,sum);
ab15b2ec
PW
3007 CTxUndo undoDummy;
3008 if (i > 0) {
3009 blockundo.vtxundo.push_back(CTxUndo());
3010 }
8cb98d91 3011 UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
8d655683 3012
b7e4abd6 3013 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
4bc00dc1
DH
3014 BOOST_FOREACH(const uint256 &note_commitment, joinsplit.commitments) {
3015 // Insert the note commitments into our temporary tree.
8d655683 3016
4bc00dc1 3017 tree.append(note_commitment);
a8ac403d
SB
3018 }
3019 }
8d655683 3020
805344dc 3021 vPos.push_back(std::make_pair(tx.GetHash(), pos));
2d1fa42e 3022 pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
0a61b0df 3023 }
84638476 3024
a8ac403d 3025 view.PushAnchor(tree);
0bc1e2c4
JG
3026 if (!fJustCheck) {
3027 pindex->hashAnchorEnd = tree.root();
3028 }
a8ac403d 3029 blockundo.old_tree_root = old_tree_root;
8d655683 3030
d70bc52e
PW
3031 int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
3032 LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
8d655683 3033
6b30b27c 3034 CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()) + sum;
18443f69 3035 if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 )
de4a435c 3036 {
3037 uint64_t checktoshis;
18443f69 3038 if ( (checktoshis= komodo_commission((CBlock *)&block)) != 0 )
de4a435c 3039 {
3040 if ( block.vtx[0].vout.size() == 2 && block.vtx[0].vout[1].nValue == checktoshis )
b7dc5699 3041 blockReward += checktoshis;
2808b68f 3042 else fprintf(stderr,"checktoshis %.8f numvouts %d\n",dstr(checktoshis),(int32_t)block.vtx[0].vout.size());
de4a435c 3043 }
3044 }
cf7f4402 3045 if ( block.vtx[0].GetValueOut() > blockReward+1 )
0b652b66 3046 {
ea124428 3047 if ( ASSETCHAINS_SYMBOL[0] != 0 || pindex->nHeight >= KOMODO_NOTARIES_HEIGHT1 || block.vtx[0].vout[0].nValue > blockReward )
0b652b66 3048 {
3049 return state.DoS(100,
8d655683 3050 error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
3051 block.vtx[0].GetValueOut(), blockReward),
3052 REJECT_INVALID, "bad-cb-amount");
4d068367 3053 } else if ( IS_KOMODO_NOTARY != 0 )
cf7f4402 3054 fprintf(stderr,"allow nHeight.%d coinbase %.8f vs %.8f interest %.8f\n",(int32_t)pindex->nHeight,dstr(block.vtx[0].GetValueOut()),dstr(blockReward),dstr(sum));
0b652b66 3055 }
f9cae832 3056 if (!control.Wait())
ef3988ca 3057 return state.DoS(100, false);
d70bc52e
PW
3058 int64_t nTime2 = GetTimeMicros(); nTimeVerify += nTime2 - nTimeStart;
3059 LogPrint("bench", " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime2 - nTimeStart), nInputs <= 1 ? 0 : 0.001 * (nTime2 - nTimeStart) / (nInputs-1), nTimeVerify * 0.000001);
8d655683 3060
3cd01fdf
LD
3061 if (fJustCheck)
3062 return true;
8d655683 3063
5382bcf8 3064 // Write undo information to disk
942b33a1 3065 if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS))
5382bcf8 3066 {
857c61df
PW
3067 if (pindex->GetUndoPos().IsNull()) {
3068 CDiskBlockPos pos;
ef3988ca 3069 if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
5262fde0 3070 return error("ConnectBlock(): FindUndoPos failed");
e6973430 3071 if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
27afcd89 3072 return AbortNode(state, "Failed to write undo data");
8d655683 3073
857c61df
PW
3074 // update nUndoPos in block index
3075 pindex->nUndoPos = pos.nPos;
3076 pindex->nStatus |= BLOCK_HAVE_UNDO;
3077 }
8d655683 3078
828940b1 3079 // Now that all consensus rules have been validated, set nCachedBranchId.
9e851450
JG
3080 // Move this if BLOCK_VALID_CONSENSUS is ever altered.
3081 static_assert(BLOCK_VALID_CONSENSUS == BLOCK_VALID_SCRIPTS,
8d655683 3082 "nCachedBranchId must be set after all consensus rules have been validated.");
9e851450
JG
3083 if (IsActivationHeightForAnyUpgrade(pindex->nHeight, Params().GetConsensus())) {
3084 pindex->nStatus |= BLOCK_ACTIVATES_UPGRADE;
828940b1 3085 pindex->nCachedBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus());
9e851450 3086 } else if (pindex->pprev) {
828940b1 3087 pindex->nCachedBranchId = pindex->pprev->nCachedBranchId;
9e851450 3088 }
8d655683 3089
942b33a1 3090 pindex->RaiseValidity(BLOCK_VALID_SCRIPTS);
51ce901a 3091 setDirtyBlockIndex.insert(pindex);
0a61b0df 3092 }
84638476 3093
84964112 3094 ConnectNotarisations(block, pindex->nHeight);
8d655683 3095
2d1fa42e 3096 if (fTxIndex)
ef3988ca 3097 if (!pblocktree->WriteTxIndex(vPos))
27afcd89 3098 return AbortNode(state, "Failed to write transaction index");
8b78a819
T
3099 if (fAddressIndex) {
3100 if (!pblocktree->WriteAddressIndex(addressIndex)) {
3101 return AbortNode(state, "Failed to write address index");
3102 }
3103
3104 if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) {
3105 return AbortNode(state, "Failed to write address unspent index");
3106 }
3107 }
3108
3109 if (fSpentIndex)
3110 if (!pblocktree->UpdateSpentIndex(spentIndex))
3111 return AbortNode(state, "Failed to write transaction index");
3112
3113 if (fTimestampIndex) {
3114 unsigned int logicalTS = pindex->nTime;
3115 unsigned int prevLogicalTS = 0;
3116
3117 // retrieve logical timestamp of the previous block
3118 if (pindex->pprev)
3119 if (!pblocktree->ReadTimestampBlockIndex(pindex->pprev->GetBlockHash(), prevLogicalTS))
3120 LogPrintf("%s: Failed to read previous block's logical timestamp\n", __func__);
3121
3122 if (logicalTS <= prevLogicalTS) {
3123 logicalTS = prevLogicalTS + 1;
3124 LogPrintf("%s: Previous logical timestamp is newer Actual[%d] prevLogical[%d] Logical[%d]\n", __func__, pindex->nTime, prevLogicalTS, logicalTS);
3125 }
3126
3127 if (!pblocktree->WriteTimestampIndex(CTimestampIndexKey(logicalTS, pindex->GetBlockHash())))
3128 return AbortNode(state, "Failed to write timestamp index");
3129
3130 if (!pblocktree->WriteTimestampBlockIndex(CTimestampBlockIndexKey(pindex->GetBlockHash()), CTimestampBlockIndexValue(logicalTS)))
3131 return AbortNode(state, "Failed to write blockhash index");
3132 }
3133
729b1806 3134 // add this block to the view's block chain
c9d1a81c 3135 view.SetBestBlock(pindex->GetBlockHash());
8d655683 3136
d70bc52e
PW
3137 int64_t nTime3 = GetTimeMicros(); nTimeIndex += nTime3 - nTime2;
3138 LogPrint("bench", " - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeIndex * 0.000001);
8d655683 3139
202e0194
PW
3140 // Watch for changes to the previous coinbase transaction.
3141 static uint256 hashPrevBestCoinBase;
26c16d9d 3142 GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase);
805344dc 3143 hashPrevBestCoinBase = block.vtx[0].GetHash();
8d655683 3144
d70bc52e
PW
3145 int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3;
3146 LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001);
a0344f90 3147
0f42af4c 3148 //FlushStateToDisk();
651989c7 3149 komodo_connectblock(pindex,*(CBlock *)&block);
0a61b0df 3150 return true;
3151}
3152
a2069500 3153enum FlushStateMode {
f9ec3f0f 3154 FLUSH_STATE_NONE,
a2069500
PW
3155 FLUSH_STATE_IF_NEEDED,
3156 FLUSH_STATE_PERIODIC,
3157 FLUSH_STATE_ALWAYS
3158};
3159
51ce901a
PW
3160/**
3161 * Update the on-disk chain state.
f9ec3f0f 3162 * The caches and indexes are flushed depending on the mode we're called with
3163 * if they're too large, if it's been a while since the last write,
3164 * or always and in all cases if we're in prune mode and are deleting files.
51ce901a 3165 */
a2069500 3166bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
f9ec3f0f 3167 LOCK2(cs_main, cs_LastBlockFile);
75f51f2a 3168 static int64_t nLastWrite = 0;
67708acf
PW
3169 static int64_t nLastFlush = 0;
3170 static int64_t nLastSetChain = 0;
f9ec3f0f 3171 std::set<int> setFilesToPrune;
3172 bool fFlushForPrune = false;
e4134579 3173 try {
8d655683 3174 if (fPruneMode && fCheckForPruning && !fReindex) {
3175 FindFilesToPrune(setFilesToPrune);
3176 fCheckForPruning = false;
3177 if (!setFilesToPrune.empty()) {
3178 fFlushForPrune = true;
3179 if (!fHavePruned) {
3180 pblocktree->WriteFlag("prunedblockfiles", true);
3181 fHavePruned = true;
3182 }
f9ec3f0f 3183 }
3184 }
8d655683 3185 int64_t nNow = GetTimeMicros();
3186 // Avoid writing/flushing immediately after startup.
3187 if (nLastWrite == 0) {
3188 nLastWrite = nNow;
3189 }
3190 if (nLastFlush == 0) {
3191 nLastFlush = nNow;
3192 }
3193 if (nLastSetChain == 0) {
3194 nLastSetChain = nNow;
3195 }
3196 size_t cacheSize = pcoinsTip->DynamicMemoryUsage();
3197 // The cache is large and close to the limit, but we have time now (not in the middle of a block processing).
3198 bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize * (10.0/9) > nCoinCacheUsage;
3199 // The cache is over the limit, we have to write now.
3200 bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nCoinCacheUsage;
3201 // It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash.
3202 bool fPeriodicWrite = mode == FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000;
3203 // It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
3204 bool fPeriodicFlush = mode == FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000;
3205 // Combine all conditions that result in a full cache flush.
3206 bool fDoFullFlush = (mode == FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
3207 // Write blocks and block index to disk.
3208 if (fDoFullFlush || fPeriodicWrite) {
3209 // Depend on nMinDiskSpace to ensure we can write block index
3210 if (!CheckDiskSpace(0))
3211 return state.Error("out of disk space");
3212 // First make sure all block and undo data is flushed to disk.
3213 FlushBlockFile();
3214 // Then update all block file information (which may refer to block and undo files).
3215 {
3216 std::vector<std::pair<int, const CBlockFileInfo*> > vFiles;
3217 vFiles.reserve(setDirtyFileInfo.size());
3218 for (set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) {
3219 vFiles.push_back(make_pair(*it, &vinfoBlockFile[*it]));
3220 setDirtyFileInfo.erase(it++);
3221 }
3222 std::vector<const CBlockIndex*> vBlocks;
3223 vBlocks.reserve(setDirtyBlockIndex.size());
3224 for (set<CBlockIndex*>::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) {
3225 vBlocks.push_back(*it);
3226 setDirtyBlockIndex.erase(it++);
3227 }
3228 if (!pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) {
3229 return AbortNode(state, "Files to write to block index database");
3230 }
51ce901a 3231 }
8d655683 3232 // Finally remove any pruned files
3233 if (fFlushForPrune)
3234 UnlinkPrunedFiles(setFilesToPrune);
3235 nLastWrite = nNow;
3236 }
3237 // Flush best chain related state. This can only be done if the blocks / block index write was also done.
3238 if (fDoFullFlush) {
3239 // Typical CCoins structures on disk are around 128 bytes in size.
3240 // Pushing a new one to the database can cause it to be written
3241 // twice (once in the log, and once in the tables). This is already
3242 // an overestimation, as most will delete an existing entry or
3243 // overwrite one. Still, use a conservative safety factor of 2.
3244 if (!CheckDiskSpace(128 * 2 * 2 * pcoinsTip->GetCacheSize()))
3245 return state.Error("out of disk space");
3246 // Flush the chainstate (which may refer to block index entries).
3247 if (!pcoinsTip->Flush())
3248 return AbortNode(state, "Failed to write to coin database");
3249 nLastFlush = nNow;
3250 }
3251 if ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000) {
3252 // Update best block in wallet (so we can detect restored wallets).
3253 GetMainSignals().SetBestChain(chainActive.GetLocator());
3254 nLastSetChain = nNow;
51ce901a 3255 }
e4134579 3256 } catch (const std::runtime_error& e) {
27afcd89 3257 return AbortNode(state, std::string("System error while flushing: ") + e.what());
e4134579 3258 }
0ec16f35
PW
3259 return true;
3260}
450cbb09 3261
51ce901a
PW
3262void FlushStateToDisk() {
3263 CValidationState state;
a2069500 3264 FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
51ce901a
PW
3265}
3266
f9ec3f0f 3267void PruneAndFlush() {
3268 CValidationState state;
3269 fCheckForPruning = true;
3270 FlushStateToDisk(state, FLUSH_STATE_NONE);
3271}
3272
c5b390b6 3273/** Update chainActive and related internal data structures. */
0ec16f35 3274void static UpdateTip(CBlockIndex *pindexNew) {
11982d36 3275 const CChainParams& chainParams = Params();
4c6d41b8 3276 chainActive.SetTip(pindexNew);
8d655683 3277
0a61b0df 3278 // New best block
0a61b0df 3279 nTimeBestReceived = GetTime();
319b1160 3280 mempool.AddTransactionsUpdated(1);
03e2210d 3281 KOMODO_NEWBLOCKS++;
7246f7f3
JDL
3282 double progress;
3283 if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
86131275 3284 progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip());
7246f7f3 3285 } else {
3bd2c3bd
DL
3286 int32_t longestchain = komodo_longestchain();
3287 progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0;
7246f7f3
JDL
3288 }
3289
b0ae7941 3290 LogPrintf("%s: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
86131275 3291 chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(),
3292 log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.LastTip()->nChainTx,
3293 DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), progress,
7246f7f3 3294 pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
8d655683 3295
ff6a7af1 3296 cvBlockChange.notify_all();
8d655683 3297
2a919e39 3298 // Check the version of the last 100 blocks to see if we need to upgrade:
dbca89b7
GA
3299 static bool fWarned = false;
3300 if (!IsInitialBlockDownload() && !fWarned)
2a919e39
GA
3301 {
3302 int nUpgraded = 0;
4c6d41b8 3303 const CBlockIndex* pindex = chainActive.Tip();
2a919e39
GA
3304 for (int i = 0; i < 100 && pindex != NULL; i++)
3305 {
3306 if (pindex->nVersion > CBlock::CURRENT_VERSION)
3307 ++nUpgraded;
3308 pindex = pindex->pprev;
3309 }
3310 if (nUpgraded > 0)
30c1db1c 3311 LogPrintf("%s: %d of last 100 blocks above version %d\n", __func__, nUpgraded, (int)CBlock::CURRENT_VERSION);
2a919e39 3312 if (nUpgraded > 100/2)
dbca89b7 3313 {
07cf4264 3314 // strMiscWarning is read by GetWarnings(), called by the JSON-RPC code to warn the user:
7e6d23b1 3315 strMiscWarning = _("Warning: This version is obsolete; upgrade required!");
dbca89b7
GA
3316 CAlert::Notify(strMiscWarning, true);
3317 fWarned = true;
3318 }
2a919e39 3319 }
75f51f2a 3320}
2a919e39 3321
34a64fe0
JG
3322/**
3323 * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and
3324 * mempool.removeWithoutBranchId after this, with cs_main held.
3325 */
89f20450 3326bool static DisconnectTip(CValidationState &state, bool fBare = false) {
75f51f2a
PW
3327 CBlockIndex *pindexDelete = chainActive.Tip();
3328 assert(pindexDelete);
75f51f2a
PW
3329 // Read block from disk.
3330 CBlock block;
b8add6a4 3331 if (!ReadBlockFromDisk(block, pindexDelete,1))
27afcd89 3332 return AbortNode(state, "Failed to read block");
75f51f2a 3333 // Apply the block atomically to the chain state.
a8ac403d 3334 uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor();
75f51f2a 3335 int64_t nStart = GetTimeMicros();
d237f62c 3336 {
7c70438d 3337 CCoinsViewCache view(pcoinsTip);
75f51f2a 3338 if (!DisconnectBlock(block, state, pindexDelete, view))
5262fde0 3339 return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
75f51f2a 3340 assert(view.Flush());
84964112 3341 DisconnectNotarisations(block);
d237f62c 3342 }
d70bc52e 3343 LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
a8ac403d 3344 uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor();
75f51f2a 3345 // Write the chain state to disk, if necessary.
a2069500 3346 if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
75f51f2a 3347 return false;
8d655683 3348
1cdb961b 3349 if (!fBare)
3350 {
89f20450 3351 // Resurrect mempool transactions from the disconnected block.
1cdb961b 3352 //BOOST_FOREACH(const CTransaction &tx, block.vtx) {
3353 for (int i = 0; i < block.vtx.size(); i++)
3354 {
3355 CTransaction &tx = block.vtx[i];
89f20450
PW
3356 // ignore validation errors in resurrected transactions
3357 list<CTransaction> removed;
3358 CValidationState stateDummy;
333cf46c 3359 if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
89f20450
PW
3360 mempool.remove(tx, removed, true);
3361 }
3362 if (anchorBeforeDisconnect != anchorAfterDisconnect) {
3363 // The anchor may not change between block disconnects,
3364 // in which case we don't want to evict from the mempool yet!
3365 mempool.removeWithAnchor(anchorBeforeDisconnect);
3366 }
89f20450 3367 }
8d655683 3368
75f51f2a
PW
3369 // Update chainActive and related variables.
3370 UpdateTip(pindexDelete->pprev);
de42390f
JG
3371 // Get the current commitment tree
3372 ZCIncrementalMerkleTree newTree;
3373 assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), newTree));
93a18a36
GA
3374 // Let wallets know transactions went from 1-confirmed to
3375 // 0-confirmed or conflicted:
1cdb961b 3376 //BOOST_FOREACH(const CTransaction &tx, block.vtx) {
3377 // SyncWithWallets(tx, NULL);
3378 //}
769e031c 3379 // Update cached incremental witnesses
e0440cc3 3380 //fprintf(stderr,"chaintip false\n");
1cdb961b 3381 for (int i = 0; i < block.vtx.size(); i++)
3382 {
3383 CTransaction &tx = block.vtx[i];
333cf46c 3384 if ( (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 )
1cdb961b 3385 {
3386 EraseFromWallets(tx.GetHash());
3387 }
3388 else
3389 {
3390 SyncWithWallets(tx, NULL);
3391 }
3392 }
de42390f 3393 GetMainSignals().ChainTip(pindexDelete, &block, newTree, false);
75f51f2a 3394 return true;
0ec16f35 3395}
d237f62c 3396
d70bc52e
PW
3397static int64_t nTimeReadFromDisk = 0;
3398static int64_t nTimeConnectTotal = 0;
3399static int64_t nTimeFlush = 0;
3400static int64_t nTimeChainState = 0;
3401static int64_t nTimePostConnect = 0;
3402
db954a65 3403/**
c5b390b6
MF
3404 * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
3405 * corresponding to pindexNew, to bypass loading it again from disk.
34a64fe0 3406 * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held.
c5b390b6 3407 */
92bb6f2f 3408bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
76374710 3409
75f51f2a 3410 assert(pindexNew->pprev == chainActive.Tip());
75f51f2a 3411 // Read block from disk.
d70bc52e 3412 int64_t nTime1 = GetTimeMicros();
75f51f2a 3413 CBlock block;
92bb6f2f 3414 if (!pblock) {
b8add6a4 3415 if (!ReadBlockFromDisk(block, pindexNew,1))
27afcd89 3416 return AbortNode(state, "Failed to read block");
92bb6f2f
PW
3417 pblock = &block;
3418 }
de42390f
JG
3419 // Get the current commitment tree
3420 ZCIncrementalMerkleTree oldTree;
3421 assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), oldTree));
75f51f2a 3422 // Apply the block atomically to the chain state.
d70bc52e
PW
3423 int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1;
3424 int64_t nTime3;
3425 LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
0a61b0df 3426 {
7c70438d 3427 CCoinsViewCache view(pcoinsTip);
96f9009e 3428 bool rv = ConnectBlock(*pblock, state, pindexNew, view, false, true);
26c16d9d 3429 GetMainSignals().BlockChecked(*pblock, state);
24e88964 3430 if (!rv) {
75f51f2a
PW
3431 if (state.IsInvalid())
3432 InvalidBlockFound(pindexNew, state);
5262fde0 3433 return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
7851033d 3434 }
2af5a650 3435 mapBlockSource.erase(pindexNew->GetBlockHash());
d70bc52e
PW
3436 nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
3437 LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
75f51f2a 3438 assert(view.Flush());
0a61b0df 3439 }
d70bc52e
PW
3440 int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
3441 LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
75f51f2a 3442 // Write the chain state to disk, if necessary.
a2069500 3443 if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
75f51f2a 3444 return false;
d70bc52e
PW
3445 int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
3446 LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
75f51f2a 3447 // Remove conflicting transactions from the mempool.
93a18a36 3448 list<CTransaction> txConflicted;
b649e039 3449 mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload());
8d655683 3450
9bb37bf0
JG
3451 // Remove transactions that expire at new block height from mempool
3452 mempool.removeExpired(pindexNew->nHeight);
8d655683 3453
75f51f2a 3454 // Update chainActive & related variables.
880b2931 3455 UpdateTip(pindexNew);
93a18a36
GA
3456 // Tell wallet about transactions that went from mempool
3457 // to conflicted:
3458 BOOST_FOREACH(const CTransaction &tx, txConflicted) {
d38da59b 3459 SyncWithWallets(tx, NULL);
93a18a36
GA
3460 }
3461 // ... and about transactions that got confirmed:
92bb6f2f
PW
3462 BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
3463 SyncWithWallets(tx, pblock);
93a18a36 3464 }
769e031c 3465 // Update cached incremental witnesses
e0440cc3 3466 //fprintf(stderr,"chaintip true\n");
de42390f 3467 GetMainSignals().ChainTip(pindexNew, pblock, oldTree, true);
8d655683 3468
5b3bc971 3469 EnforceNodeDeprecation(pindexNew->nHeight);
8d655683 3470
d70bc52e
PW
3471 int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
3472 LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
3473 LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
c4318f42 3474 if ( ASSETCHAINS_SYMBOL[0] == 0 )
395f10cf 3475 komodo_broadcast(pblock,8);
0a61b0df 3476 return true;
3477}
3478
c5b390b6
MF
3479/**
3480 * Return the tip of the chain with the most work in it, that isn't
3481 * known to be invalid (it's however far from certain to be valid).
3482 */
77339e5a 3483static CBlockIndex* FindMostWorkChain() {
75f51f2a 3484 do {
77339e5a 3485 CBlockIndex *pindexNew = NULL;
8d655683 3486
75f51f2a
PW
3487 // Find the best candidate header.
3488 {
e17bd583
PW
3489 std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin();
3490 if (it == setBlockIndexCandidates.rend())
77339e5a 3491 return NULL;
75f51f2a
PW
3492 pindexNew = *it;
3493 }
8d655683 3494
75f51f2a
PW
3495 // Check whether all blocks on the path between the currently active chain and the candidate are valid.
3496 // Just going until the active chain is an optimization, as we know all blocks in it are valid already.
3497 CBlockIndex *pindexTest = pindexNew;
3498 bool fInvalidAncestor = false;
3499 while (pindexTest && !chainActive.Contains(pindexTest)) {
341735eb 3500 assert(pindexTest->nChainTx || pindexTest->nHeight == 0);
8d655683 3501
f9ec3f0f 3502 // Pruned nodes may have entries in setBlockIndexCandidates for
3503 // which block files have been deleted. Remove those as candidates
3504 // for the most work chain if we come across them; we can't switch
3505 // to a chain unless we have all the non-active-chain parent blocks.
3506 bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_MASK;
3507 bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA);
3508 if (fFailedChain || fMissingData) {
3509 // Candidate chain is not usable (either invalid or missing data)
3510 if (fFailedChain && (pindexBestInvalid == NULL || pindexNew->nChainWork > pindexBestInvalid->nChainWork))
942b33a1
PW
3511 pindexBestInvalid = pindexNew;
3512 CBlockIndex *pindexFailed = pindexNew;
f9ec3f0f 3513 // Remove the entire chain from the set.
75f51f2a 3514 while (pindexTest != pindexFailed) {
f9ec3f0f 3515 if (fFailedChain) {
3516 pindexFailed->nStatus |= BLOCK_FAILED_CHILD;
3517 } else if (fMissingData) {
3518 // If we're missing data, then add back to mapBlocksUnlinked,
3519 // so that if the block arrives in the future we can try adding
3520 // to setBlockIndexCandidates again.
3521 mapBlocksUnlinked.insert(std::make_pair(pindexFailed->pprev, pindexFailed));
3522 }
e17bd583 3523 setBlockIndexCandidates.erase(pindexFailed);
75f51f2a
PW
3524 pindexFailed = pindexFailed->pprev;
3525 }
e17bd583 3526 setBlockIndexCandidates.erase(pindexTest);
75f51f2a
PW
3527 fInvalidAncestor = true;
3528 break;
ef3988ca 3529 }
75f51f2a 3530 pindexTest = pindexTest->pprev;
0a61b0df 3531 }
77339e5a
PW
3532 if (!fInvalidAncestor)
3533 return pindexNew;
75f51f2a 3534 } while(true);
75f51f2a 3535}
0a61b0df 3536
c5b390b6 3537/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
cca48f69 3538static void PruneBlockIndexCandidates() {
3539 // Note that we can't delete the current block itself, as we may need to return to it later in case a
3540 // reorganization to a better block fails.
3541 std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
86131275 3542 while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.LastTip())) {
cca48f69 3543 setBlockIndexCandidates.erase(it++);
3544 }
34559c7c
PW
3545 // Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
3546 assert(!setBlockIndexCandidates.empty());
cca48f69 3547}
3548
c5b390b6
MF
3549/**
3550 * Try to make some progress towards making pindexMostWork the active block.
3551 * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
3552 */
92bb6f2f 3553static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
4e0eed88 3554 AssertLockHeld(cs_main);
202e0194 3555 bool fInvalidFound = false;
b33bd7a3
DK
3556 const CBlockIndex *pindexOldTip = chainActive.Tip();
3557 const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
8d655683 3558
57e6ecda
JG
3559 // - On ChainDB initialization, pindexOldTip will be null, so there are no removable blocks.
3560 // - If pindexMostWork is in a chain that doesn't have the same genesis block as our chain,
3561 // then pindexFork will be null, and we would need to remove the entire chain including
3562 // our genesis block. In practice this (probably) won't happen because of checks elsewhere.
3563 auto reorgLength = pindexOldTip ? pindexOldTip->nHeight - (pindexFork ? pindexFork->nHeight : -1) : 0;
3564 static_assert(MAX_REORG_LENGTH > 0, "We must be able to reorg some distance");
3565 if (reorgLength > MAX_REORG_LENGTH) {
3566 auto msg = strprintf(_(
8d655683 3567 "A block chain reorganization has been detected that would roll back %d blocks! "
3568 "This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
3569 ), reorgLength, MAX_REORG_LENGTH) + "\n\n" +
3570 _("Reorganization details") + ":\n" +
3571 "- " + strprintf(_("Current tip: %s, height %d, work %s"),
3572 pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight, pindexOldTip->nChainWork.GetHex()) + "\n" +
3573 "- " + strprintf(_("New tip: %s, height %d, work %s"),
3574 pindexMostWork->phashBlock->GetHex(), pindexMostWork->nHeight, pindexMostWork->nChainWork.GetHex()) + "\n" +
5794aafc 3575 "- " + strprintf(_("Fork point: %s %s, height %d"),
a17a8c52 3576 ASSETCHAINS_SYMBOL,pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" +
8d655683 3577 _("Please help, human!");
57e6ecda
JG
3578 LogPrintf("*** %s\n", msg);
3579 uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
3580 StartShutdown();
3581 return false;
3582 }
8d655683 3583
4e0eed88 3584 // Disconnect active blocks which are no longer in the best chain.
fe5cef05 3585 bool fBlocksDisconnected = false;
4e0eed88
PW
3586 while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
3587 if (!DisconnectTip(state))
3588 return false;
fe5cef05 3589 fBlocksDisconnected = true;
4e0eed88 3590 }
8abcd819 3591 if ( KOMODO_REWIND != 0 )
8985164d 3592 {
2ca62c87 3593 CBlockIndex *tipindex;
86131275 3594 fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.LastTip()->nHeight,KOMODO_REWIND);
3595 while ( KOMODO_REWIND > 0 && (tipindex= chainActive.LastTip()) != 0 && tipindex->nHeight > KOMODO_REWIND )
297a4978 3596 {
cef5ad03 3597 fBlocksDisconnected = true;
2ca62c87 3598 fprintf(stderr,"%d ",(int32_t)tipindex->nHeight);
3599 InvalidateBlock(state,tipindex);
310bb0a1 3600 if ( !DisconnectTip(state) )
45142781 3601 break;
67d2b8b9 3602 }
fd836de7 3603 fprintf(stderr,"reached rewind.%d, best to do: ./komodo-cli -ac_name=%s stop\n",KOMODO_REWIND,ASSETCHAINS_SYMBOL);
5c888905 3604 sleep(20);
91165f19 3605 fprintf(stderr,"resuming normal operations\n");
d8be8b2e 3606 KOMODO_REWIND = 0;
cef5ad03 3607 //return(true);
d8be8b2e 3608 }
4e0eed88
PW
3609 // Build list of new blocks to connect.
3610 std::vector<CBlockIndex*> vpindexToConnect;
afc32c5e
PW
3611 bool fContinue = true;
3612 int nHeight = pindexFork ? pindexFork->nHeight : -1;
3613 while (fContinue && nHeight != pindexMostWork->nHeight) {
5aa165d5
MC
3614 // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need
3615 // a few blocks along the way.
3616 int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight);
3617 vpindexToConnect.clear();
3618 vpindexToConnect.reserve(nTargetHeight - nHeight);
3619 CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
3620 while (pindexIter && pindexIter->nHeight != nHeight) {
3621 vpindexToConnect.push_back(pindexIter);
3622 pindexIter = pindexIter->pprev;
3623 }
3624 nHeight = nTargetHeight;
8d655683 3625
5aa165d5
MC
3626 // Connect new blocks.
3627 BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
3628 if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
3629 if (state.IsInvalid()) {
3630 // The block violates a consensus rule.
3631 if (!state.CorruptionPossible())
3632 InvalidChainFound(vpindexToConnect.back());
3633 state = CValidationState();
3634 fInvalidFound = true;
3635 fContinue = false;
3636 break;
3637 } else {
3638 // A system error occurred (disk space, database error, ...).
3639 return false;
3640 }
4e0eed88 3641 } else {
5aa165d5
MC
3642 PruneBlockIndexCandidates();
3643 if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
3644 // We're in a better position than we were. Return temporarily to release the lock.
3645 fContinue = false;
3646 break;
3647 }
75f51f2a
PW
3648 }
3649 }
231b3999 3650 }
8d655683 3651
fe5cef05 3652 if (fBlocksDisconnected) {
233c9eb6 3653 mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
afc32c5e 3654 }
34a64fe0 3655 mempool.removeWithoutBranchId(
8d655683 3656 CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus()));
fe5cef05 3657 mempool.check(pcoinsTip);
8d655683 3658
202e0194
PW
3659 // Callbacks/notifications for a new best chain.
3660 if (fInvalidFound)
3661 CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
3662 else
3663 CheckForkWarningConditions();
8d655683 3664
0a61b0df 3665 return true;
3666}
0a61b0df 3667
c5b390b6
MF
3668/**
3669 * Make the best chain active, in multiple steps. The result is either failure
3670 * or an activated best chain. pblock is either NULL or a pointer to a block
3671 * that is already loaded (to avoid loading it again from disk).
3672 */
92bb6f2f 3673bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
202e0194
PW
3674 CBlockIndex *pindexNewTip = NULL;
3675 CBlockIndex *pindexMostWork = NULL;
11982d36 3676 const CChainParams& chainParams = Params();
4e0eed88
PW
3677 do {
3678 boost::this_thread::interruption_point();
8d655683 3679
202e0194
PW
3680 bool fInitialDownload;
3681 {
3682 LOCK(cs_main);
3683 pindexMostWork = FindMostWorkChain();
8d655683 3684
202e0194
PW
3685 // Whether we have anything to do at all.
3686 if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip())
3687 return true;
8d655683 3688
92bb6f2f 3689 if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL))
9083591a 3690 return false;
202e0194
PW
3691 pindexNewTip = chainActive.Tip();
3692 fInitialDownload = IsInitialBlockDownload();
3693 }
3694 // When we reach this point, we switched to a new tip (stored in pindexNewTip).
8d655683 3695
202e0194
PW
3696 // Notifications/callbacks that can run without cs_main
3697 if (!fInitialDownload) {
3698 uint256 hashNewTip = pindexNewTip->GetBlockHash();
3699 // Relay inventory, but don't relay old inventory during initial block download.
a8cdaf5c
CF
3700 int nBlockEstimate = 0;
3701 if (fCheckpointsEnabled)
3702 nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints());
f9ec3f0f 3703 // Don't relay blocks if pruning -- could cause a peer to try to download, resulting
3704 // in a stalled download if the block file is pruned before the request.
3705 if (nLocalServices & NODE_NETWORK) {
4dc5eb05
PK
3706 LOCK(cs_vNodes);
3707 BOOST_FOREACH(CNode* pnode, vNodes)
8d655683 3708 if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
3709 pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
202e0194 3710 }
51ce901a 3711 // Notify external listeners about the new tip.
6a793d9c 3712 GetMainSignals().UpdatedBlockTip(pindexNewTip);
c7b6117d 3713 uiInterface.NotifyBlockTip(hashNewTip);
b11963b5 3714 } //else fprintf(stderr,"initial download skips propagation\n");
202e0194 3715 } while(pindexMostWork != chainActive.Tip());
3fcfbc8a 3716 CheckBlockIndex();
8d655683 3717
51ce901a 3718 // Write changes periodically to disk, after relay.
a2069500 3719 if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) {
51ce901a
PW
3720 return false;
3721 }
8d655683 3722
4e0eed88
PW
3723 return true;
3724}
942b33a1 3725
9b0a8d31
PW
3726bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
3727 AssertLockHeld(cs_main);
8d655683 3728
9b0a8d31
PW
3729 // Mark the block itself as invalid.
3730 pindex->nStatus |= BLOCK_FAILED_VALID;
0dd06b25 3731 setDirtyBlockIndex.insert(pindex);
9b0a8d31 3732 setBlockIndexCandidates.erase(pindex);
8d655683 3733
9b0a8d31
PW
3734 while (chainActive.Contains(pindex)) {
3735 CBlockIndex *pindexWalk = chainActive.Tip();
3736 pindexWalk->nStatus |= BLOCK_FAILED_CHILD;
0dd06b25 3737 setDirtyBlockIndex.insert(pindexWalk);
9b0a8d31
PW
3738 setBlockIndexCandidates.erase(pindexWalk);
3739 // ActivateBestChain considers blocks already in chainActive
3740 // unconditionally valid already, so force disconnect away from it.
3741 if (!DisconnectTip(state)) {
233c9eb6 3742 mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
34a64fe0 3743 mempool.removeWithoutBranchId(
8d655683 3744 CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus()));
9b0a8d31
PW
3745 return false;
3746 }
3747 }
ea5f02cb 3748 //LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
8d655683 3749
9b0a8d31 3750 // The resulting new best tip may not be in setBlockIndexCandidates anymore, so
b05a89b2 3751 // add it again.
9b0a8d31 3752 BlockMap::iterator it = mapBlockIndex.begin();
e6528c64 3753 while (it != mapBlockIndex.end() && it->second != 0 ) {
cd3d67cf 3754 if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) {
a9af4158 3755 setBlockIndexCandidates.insert(it->second);
9b0a8d31
PW
3756 }
3757 it++;
3758 }
8d655683 3759
9b0a8d31 3760 InvalidChainFound(pindex);
233c9eb6 3761 mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
34a64fe0 3762 mempool.removeWithoutBranchId(
8d655683 3763 CurrentEpochBranchId(chainActive.Tip()->nHeight + 1, Params().GetConsensus()));
9b0a8d31
PW
3764 return true;
3765}
3766
3767bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) {
3768 AssertLockHeld(cs_main);
8d655683 3769
9b0a8d31 3770 int nHeight = pindex->nHeight;
8d655683 3771
9b0a8d31
PW
3772 // Remove the invalidity flag from this block and all its descendants.
3773 BlockMap::iterator it = mapBlockIndex.begin();
3774 while (it != mapBlockIndex.end()) {
3775 if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
3776 it->second->nStatus &= ~BLOCK_FAILED_MASK;
0dd06b25 3777 setDirtyBlockIndex.insert(it->second);
9b0a8d31
PW
3778 if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
3779 setBlockIndexCandidates.insert(it->second);
3780 }
3781 if (it->second == pindexBestInvalid) {
3782 // Reset invalid block marker if it was pointing to one of those.
3783 pindexBestInvalid = NULL;
3784 }
3785 }
3786 it++;
3787 }
8d655683 3788
9b0a8d31
PW
3789 // Remove the invalidity flag from all ancestors too.
3790 while (pindex != NULL) {
0dd06b25
PW
3791 if (pindex->nStatus & BLOCK_FAILED_MASK) {
3792 pindex->nStatus &= ~BLOCK_FAILED_MASK;
3793 setDirtyBlockIndex.insert(pindex);
9b0a8d31
PW
3794 }
3795 pindex = pindex->pprev;
3796 }
3797 return true;
3798}
3799
341735eb 3800CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
0a61b0df 3801{
3802 // Check for duplicate
1959997a 3803 uint256 hash = block.GetHash();
145d5be8 3804 BlockMap::iterator it = mapBlockIndex.find(hash);
b8513092 3805 BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
942b33a1 3806 if (it != mapBlockIndex.end())
fd835d94 3807 {
64b45b71 3808 if ( it->second != 0 ) // vNodes.size() >= KOMODO_LIMITED_NETWORKSIZE, change behavior to allow komodo_ensure to work
66dd02d2 3809 {
3810 // this is the strange case where somehow the hash is in the mapBlockIndex via as yet undetermined process, but the pindex for the hash is not there. Theoretically it is due to processing the block headers, but I have seen it get this case without having received it from the block headers or anywhere else... jl777
3811 //fprintf(stderr,"addtoblockindex already there %p\n",it->second);
7732dbc2 3812 return it->second;
66dd02d2 3813 }
b8513092 3814 if ( miPrev != mapBlockIndex.end() && (*miPrev).second == 0 )
3815 {
f190f354 3816 //fprintf(stderr,"edge case of both block and prevblock in the strange state\n");
b8513092 3817 return(0); // return here to avoid the state of pindex->nHeight not set and pprev NULL
3818 }
fd835d94 3819 }
0a61b0df 3820 // Construct new block index object
1959997a 3821 CBlockIndex* pindexNew = new CBlockIndex(block);
94c8bfb2 3822 assert(pindexNew);
341735eb
PW
3823 // We assign the sequence id to blocks only when the full data is available,
3824 // to avoid miners withholding blocks but broadcasting headers, to get a
3825 // competitive advantage.
3826 pindexNew->nSequenceId = 0;
145d5be8 3827 BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
0a61b0df 3828 pindexNew->phashBlock = &((*mi).first);
0a61b0df 3829 if (miPrev != mapBlockIndex.end())
3830 {
b92dfb1e 3831 if ( (pindexNew->pprev= (*miPrev).second) != 0 )
3832 pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
8dcf7f3f 3833 else fprintf(stderr,"unexpected null pprev %s\n",hash.ToString().c_str());
c9a09183 3834 pindexNew->BuildSkip();
0a61b0df 3835 }
092b58d1 3836 pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
942b33a1 3837 pindexNew->RaiseValidity(BLOCK_VALID_TREE);
341735eb
PW
3838 if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork)
3839 pindexBestHeader = pindexNew;
8d655683 3840
51ce901a 3841 setDirtyBlockIndex.insert(pindexNew);
66dd02d2 3842 //fprintf(stderr,"added to block index %s %p\n",hash.ToString().c_str(),pindexNew);
9cdde30c 3843 mi->second = pindexNew;
942b33a1
PW
3844 return pindexNew;
3845}
3846
c5b390b6 3847/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
942b33a1
PW
3848bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos)
3849{
3850 pindexNew->nTx = block.vtx.size();
341735eb 3851 pindexNew->nChainTx = 0;
ad6a36ad
JG
3852 CAmount sproutValue = 0;
3853 for (auto tx : block.vtx) {
3854 for (auto js : tx.vjoinsplit) {
3855 sproutValue += js.vpub_old;
3856 sproutValue -= js.vpub_new;
3857 }
3858 }
3859 pindexNew->nSproutValue = sproutValue;
3860 pindexNew->nChainSproutValue = boost::none;
857c61df
PW
3861 pindexNew->nFile = pos.nFile;
3862 pindexNew->nDataPos = pos.nPos;
5382bcf8 3863 pindexNew->nUndoPos = 0;
942b33a1 3864 pindexNew->nStatus |= BLOCK_HAVE_DATA;
341735eb 3865 pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
51ce901a 3866 setDirtyBlockIndex.insert(pindexNew);
8d655683 3867
341735eb
PW
3868 if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) {
3869 // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
3870 deque<CBlockIndex*> queue;
3871 queue.push_back(pindexNew);
8d655683 3872
341735eb
PW
3873 // Recursively process any descendant blocks that now may be eligible to be connected.
3874 while (!queue.empty()) {
3875 CBlockIndex *pindex = queue.front();
3876 queue.pop_front();
3877 pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
ad6a36ad
JG
3878 if (pindex->pprev) {
3879 if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
3880 pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
3881 } else {
3882 pindex->nChainSproutValue = boost::none;
3883 }
3884 } else {
3885 pindex->nChainSproutValue = pindex->nSproutValue;
3886 }
c1ecee8f
SD
3887 {
3888 LOCK(cs_nBlockSequenceId);
3889 pindex->nSequenceId = nBlockSequenceId++;
3890 }
3fcfbc8a
PW
3891 if (chainActive.Tip() == NULL || !setBlockIndexCandidates.value_comp()(pindex, chainActive.Tip())) {
3892 setBlockIndexCandidates.insert(pindex);
3893 }
341735eb
PW
3894 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex);
3895 while (range.first != range.second) {
3896 std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
3897 queue.push_back(it->second);
3898 range.first++;
3899 mapBlocksUnlinked.erase(it);
3900 }
341735eb
PW
3901 }
3902 } else {
3903 if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) {
3904 mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
3905 }
341735eb 3906 }
8d655683 3907
18e72167 3908 return true;
0a61b0df 3909}
3910
51ed9ec9 3911bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
5382bcf8 3912{
5382bcf8 3913 LOCK(cs_LastBlockFile);
8d655683 3914
ed6d1a2c
PW
3915 unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile;
3916 if (vinfoBlockFile.size() <= nFile) {
3917 vinfoBlockFile.resize(nFile + 1);
3918 }
8d655683 3919
ed6d1a2c
PW
3920 if (!fKnown) {
3921 while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
ed6d1a2c
PW
3922 nFile++;
3923 if (vinfoBlockFile.size() <= nFile) {
3924 vinfoBlockFile.resize(nFile + 1);
3925 }
7fea4846 3926 }
ed6d1a2c
PW
3927 pos.nFile = nFile;
3928 pos.nPos = vinfoBlockFile[nFile].nSize;
5382bcf8 3929 }
8d655683 3930
4e895b08
PW
3931 if (nFile != nLastBlockFile) {
3932 if (!fKnown) {
3933 LogPrintf("Leaving block file %i: %s\n", nFile, vinfoBlockFile[nFile].ToString());
3934 }
3935 FlushBlockFile(!fKnown);
3936 nLastBlockFile = nFile;
3937 }
8d655683 3938
ed6d1a2c 3939 vinfoBlockFile[nFile].AddBlock(nHeight, nTime);
bb6acff0
CF
3940 if (fKnown)
3941 vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize);
3942 else
3943 vinfoBlockFile[nFile].nSize += nAddSize;
8d655683 3944
7fea4846
PW
3945 if (!fKnown) {
3946 unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
ed6d1a2c 3947 unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
7fea4846 3948 if (nNewChunks > nOldChunks) {
f9ec3f0f 3949 if (fPruneMode)
3950 fCheckForPruning = true;
fa45c26a
PK
3951 if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) {
3952 FILE *file = OpenBlockFile(pos);
3953 if (file) {
881a85a2 3954 LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
fa45c26a
PK
3955 AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos);
3956 fclose(file);
3957 }
7fea4846 3958 }
fa45c26a 3959 else
c117d9e9 3960 return state.Error("out of disk space");
bba89aa8 3961 }
bba89aa8 3962 }
8d655683 3963
51ce901a 3964 setDirtyFileInfo.insert(nFile);
5382bcf8
PW
3965 return true;
3966}
3967
ef3988ca 3968bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
5382bcf8
PW
3969{
3970 pos.nFile = nFile;
8d655683 3971
5382bcf8 3972 LOCK(cs_LastBlockFile);
8d655683 3973
bba89aa8 3974 unsigned int nNewSize;
ed6d1a2c
PW
3975 pos.nPos = vinfoBlockFile[nFile].nUndoSize;
3976 nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize;
51ce901a 3977 setDirtyFileInfo.insert(nFile);
8d655683 3978
bba89aa8
PW
3979 unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
3980 unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
3981 if (nNewChunks > nOldChunks) {
f9ec3f0f 3982 if (fPruneMode)
3983 fCheckForPruning = true;
fa45c26a
PK
3984 if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos)) {
3985 FILE *file = OpenUndoFile(pos);
3986 if (file) {
881a85a2 3987 LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
fa45c26a
PK
3988 AllocateFileRange(file, pos.nPos, nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos);
3989 fclose(file);
3990 }
bba89aa8 3991 }
fa45c26a 3992 else
c117d9e9 3993 return state.Error("out of disk space");
5382bcf8 3994 }
8d655683 3995
5382bcf8
PW
3996 return true;
3997}
3998
9f6cb8f0 3999bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, const CBlockHeader& blockhdr, CValidationState& state, bool fCheckPOW)
0a61b0df 4000{
d7426190 4001 // Check timestamp
e40b78e9 4002 if ( 0 )
c0dbb034 4003 {
4004 uint256 hash; int32_t i;
4005 hash = blockhdr.GetHash();
92266e99 4006 for (i=31; i>=0; i--)
c0dbb034 4007 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
4008 fprintf(stderr," <- CheckBlockHeader\n");
86131275 4009 if ( chainActive.LastTip() != 0 )
807949f4 4010 {
86131275 4011 hash = chainActive.LastTip()->GetBlockHash();
807949f4 4012 for (i=31; i>=0; i--)
4013 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
4014 fprintf(stderr," <- chainTip\n");
4015 }
c0dbb034 4016 }
9f6cb8f0 4017 *futureblockp = 0;
48f12344 4018 if (blockhdr.GetBlockTime() > GetAdjustedTime() + 60)
8999ab66 4019 {
82b4714b 4020 CBlockIndex *tipindex;
4f61808f 4021 //fprintf(stderr,"ht.%d future block %u vs time.%u + 60\n",height,(uint32_t)blockhdr.GetBlockTime(),(uint32_t)GetAdjustedTime());
599c2c5f 4022 if ( (tipindex= chainActive.Tip()) != 0 && tipindex->GetBlockHash() == blockhdr.hashPrevBlock && blockhdr.GetBlockTime() < GetAdjustedTime() + 60 + 5 )
5d9f1119 4023 {
2fea1c97 4024 //fprintf(stderr,"it is the next block, let's wait for %d seconds\n",GetAdjustedTime() + 60 - blockhdr.GetBlockTime());
5d9f1119 4025 while ( blockhdr.GetBlockTime() > GetAdjustedTime() + 60 )
4026 sleep(1);
2fea1c97 4027 //fprintf(stderr,"now its valid\n");
5d9f1119 4028 }
4029 else
4030 {
9f6cb8f0 4031 if (blockhdr.GetBlockTime() < GetAdjustedTime() + 600)
4032 *futureblockp = 1;
992ae6c5 4033 //LogPrintf("CheckBlockHeader block from future %d error",blockhdr.GetBlockTime() - GetAdjustedTime());
5d9f1119 4034 return false; //state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new");
4035 }
8999ab66 4036 }
80f4cdcf 4037 // Check block version
5d173d2a 4038 if (height > 0 && blockhdr.nVersion < MIN_BLOCK_VERSION)
edddf5f0 4039 return state.DoS(100, error("CheckBlockHeader(): block version too low"),REJECT_INVALID, "version-too-low");
8d655683 4040
f2dd868d 4041 // Check Equihash solution is valid
dc4124de 4042 if ( fCheckPOW )
4043 {
4044 if ( !CheckEquihashSolution(&blockhdr, Params()) )
4045 return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),REJECT_INVALID, "invalid-solution");
b8add6a4 4046 }
f2dd868d 4047 // Check proof of work matches claimed amount
ec06a2e3 4048 /*komodo_index2pubkey33(pubkey33,pindex,height);
3ad8d247 4049 if ( fCheckPOW && !CheckProofOfWork(height,pubkey33,blockhdr.GetHash(), blockhdr.nBits, Params().GetConsensus(),blockhdr.nTime) )
8d655683 4050 return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),REJECT_INVALID, "high-hash");*/
f4573470
PW
4051 return true;
4052}
4053
ce5dd547 4054int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime);
18443f69 4055int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height);
b8add6a4 4056
9f6cb8f0 4057bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state,
6fb8d0c2
JG
4058 libzcash::ProofVerifier& verifier,
4059 bool fCheckPOW, bool fCheckMerkleRoot)
0a61b0df 4060{
e5d9a702 4061 uint8_t pubkey33[33]; uint256 hash;
8d655683 4062 // These are checks that are independent of context.
18dd6a3b 4063 hash = block.GetHash();
af58b81e 4064 // Check that the header is valid (particularly PoW). This is mostly redundant with the call in AcceptBlockHeader.
9f6cb8f0 4065 if (!CheckBlockHeader(futureblockp,height,pindex,block,state,fCheckPOW))
3283cb53 4066 {
9840ae39 4067 if ( *futureblockp == 0 )
e8314e82 4068 {
4069 LogPrintf("CheckBlock header error");
9840ae39 4070 return false;
e8314e82 4071 }
3283cb53 4072 }
18443f69 4073 if ( fCheckPOW )
4074 {
e5d9a702 4075 //if ( !CheckEquihashSolution(&block, Params()) )
18443f69 4076 // return state.DoS(100, error("CheckBlock: Equihash solution invalid"),REJECT_INVALID, "invalid-solution");
4077 komodo_block2pubkey33(pubkey33,(CBlock *)&block);
e5d9a702 4078 if ( !CheckProofOfWork(height,pubkey33,hash,block.nBits,Params().GetConsensus(),block.nTime) )
d3358987 4079 {
560da193 4080 int32_t z; for (z=31; z>=0; z--)
e5d9a702 4081 fprintf(stderr,"%02x",((uint8_t *)&hash)[z]);
80afe35b 4082 fprintf(stderr," failed hash ht.%d\n",height);
8fbee929 4083 return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash");
d3358987 4084 }
3acce042 4085 if ( komodo_checkPOW(1,(CBlock *)&block,height) < 0 ) // checks Equihash
18443f69 4086 return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW");
4087 }
341735eb
PW
4088 // Check the merkle root.
4089 if (fCheckMerkleRoot) {
4090 bool mutated;
4091 uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated);
4092 if (block.hashMerkleRoot != hashMerkleRoot2)
b8add6a4 4093 return state.DoS(100, error("CheckBlock: hashMerkleRoot mismatch"),
341735eb 4094 REJECT_INVALID, "bad-txnmrklroot", true);
8d655683 4095
341735eb
PW
4096 // Check for merkle tree malleability (CVE-2012-2459): repeating sequences
4097 // of transactions in a block without affecting the merkle root of a block,
4098 // while still invalidating it.
4099 if (mutated)
b8add6a4 4100 return state.DoS(100, error("CheckBlock: duplicate transaction"),
341735eb
PW
4101 REJECT_INVALID, "bad-txns-duplicate", true);
4102 }
8d655683 4103
341735eb
PW
4104 // All potential-corruption validation must be done before we do any
4105 // transaction validation, as otherwise we may mark the header as invalid
4106 // because we receive the wrong transactions for it.
8d655683 4107
0a61b0df 4108 // Size limits
38991ffa 4109 if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
b8add6a4 4110 return state.DoS(100, error("CheckBlock: size limits failed"),
14e7ffcc 4111 REJECT_INVALID, "bad-blk-length");
8d655683 4112
0a61b0df 4113 // First transaction must be coinbase, the rest must not be
38991ffa 4114 if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
b8add6a4 4115 return state.DoS(100, error("CheckBlock: first tx is not coinbase"),
14e7ffcc 4116 REJECT_INVALID, "bad-cb-missing");
38991ffa
EL
4117 for (unsigned int i = 1; i < block.vtx.size(); i++)
4118 if (block.vtx[i].IsCoinBase())
b8add6a4 4119 return state.DoS(100, error("CheckBlock: more than one coinbase"),
14e7ffcc 4120 REJECT_INVALID, "bad-cb-multiple");
8d655683 4121
0a61b0df 4122 // Check transactions
6613483b 4123 if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order
a5fc9157 4124 {
4125 CValidationState stateDummy;
6613483b 4126 fprintf(stderr,"put block's tx into mempool\n");
a5fc9157 4127 for (int i = 0; i < block.vtx.size(); i++)
4128 {
0b34402a 4129 const CTransaction &tx = block.vtx[i];
a5fc9157 4130 if (tx.IsCoinBase() != 0 )
4131 continue;
4132 else if ( ASSETCHAINS_STAKED != 0 && (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 )
4133 continue;
4134 AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL);
4135 }
6613483b 4136 fprintf(stderr,"done putting block's tx into mempool\n");
a5fc9157 4137 }
38991ffa 4138 BOOST_FOREACH(const CTransaction& tx, block.vtx)
837b94ee 4139 {
f8a07170 4140 if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,0) < 0 )
8d655683 4141 return error("CheckBlock: komodo_validate_interest failed");
6fb8d0c2 4142 if (!CheckTransaction(tx, state, verifier))
b8add6a4 4143 return error("CheckBlock: CheckTransaction failed");
837b94ee 4144 }
7bd9c3a3 4145 unsigned int nSigOps = 0;
38991ffa 4146 BOOST_FOREACH(const CTransaction& tx, block.vtx)
e679ec96 4147 {
05df3fc6 4148 nSigOps += GetLegacySigOpCount(tx);
e679ec96
GA
4149 }
4150 if (nSigOps > MAX_BLOCK_SIGOPS)
b8add6a4 4151 return state.DoS(100, error("CheckBlock: out-of-bounds SigOpCount"),
14e7ffcc 4152 REJECT_INVALID, "bad-blk-sigops", true);
b1e74295 4153 if ( komodo_check_deposit(height,block,(pindex==0||pindex->pprev==0)?0:pindex->pprev->nTime) < 0 )
e699e13d 4154 {
1a26c3fa 4155 //static uint32_t counter;
4156 //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
41427baa 4157 // fprintf(stderr,"check deposit rejection\n");
e8314e82 4158 LogPrintf("CheckBlockHeader komodo_check_deposit error");
59642d51 4159 return(false);
e699e13d 4160 }
0a61b0df 4161 return true;
4162}
4163
a48f2d6d
LD
4164bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev)
4165{
11982d36
CF
4166 const CChainParams& chainParams = Params();
4167 const Consensus::Params& consensusParams = chainParams.GetConsensus();
a48f2d6d 4168 uint256 hash = block.GetHash();
4e382177 4169 if (hash == consensusParams.hashGenesisBlock)
a48f2d6d 4170 return true;
8d655683 4171
a48f2d6d 4172 assert(pindexPrev);
8d655683 4173
a48f2d6d 4174 int nHeight = pindexPrev->nHeight+1;
8d655683 4175
a48f2d6d 4176 // Check proof of work
8f95f7e1 4177 if ( (ASSETCHAINS_SYMBOL[0] != 0 || nHeight < 235300 || nHeight > 236000) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
5645d111 4178 {
c939721c 4179 cout << block.nBits << " block.nBits vs. calc " << GetNextWorkRequired(pindexPrev, &block, consensusParams) << endl;
5262fde0 4180 return state.DoS(100, error("%s: incorrect proof of work", __func__),
a48f2d6d 4181 REJECT_INVALID, "bad-diffbits");
5645d111 4182 }
8d655683 4183
a48f2d6d
LD
4184 // Check timestamp against prev
4185 if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
5262fde0 4186 return state.Invalid(error("%s: block's timestamp is too early", __func__),
a48f2d6d 4187 REJECT_INVALID, "time-too-old");
8d655683 4188
bfa832c7 4189 if (fCheckpointsEnabled)
a8cdaf5c
CF
4190 {
4191 // Check that the block chain matches the known block chain up to a checkpoint
4192 if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash))
8d787d25 4193 {
49601901 4194 /*CBlockIndex *heightblock = chainActive[nHeight];
8d787d25 4195 if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
4196 {
4197 //fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight);
4198 return true;
49601901 4199 }*/
4200 return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight),REJECT_CHECKPOINT, "checkpoint mismatch");
8d787d25 4201 }
a8cdaf5c
CF
4202 // Don't accept any forks from the main chain prior to last checkpoint
4203 CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
b62d7030 4204 int32_t notarized_height;
86131275 4205 if ( nHeight == 1 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight > 1 )
333cf46c 4206 {
4207 CBlockIndex *heightblock = chainActive[nHeight];
4208 if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
4209 return true;
42bbeb4f 4210 return state.DoS(1, error("%s: trying to change height 1 forbidden", __func__));
333cf46c 4211 }
e7433b08 4212 if ( nHeight != 0 )
e2c2f297 4213 {
2d28ad9c 4214 if ( pcheckpoint != 0 && nHeight < pcheckpoint->nHeight )
9aa708af 4215 return state.DoS(1, error("%s: forked chain older than last checkpoint (height %d) vs %d", __func__, nHeight,pcheckpoint->nHeight));
2d28ad9c 4216 if ( komodo_checkpoint(&notarized_height,nHeight,hash) < 0 )
e2c2f297 4217 {
9aa708af 4218 CBlockIndex *heightblock = chainActive[nHeight];
4219 if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
4220 {
4221 //fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight);
4222 return true;
4223 } else return state.DoS(1, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height));
4224 }
e2c2f297 4225 }
a8cdaf5c 4226 }
542da618
SB
4227 // Reject block.nVersion < 4 blocks
4228 if (block.nVersion < 4)
4229 return state.Invalid(error("%s : rejected nVersion<4 block", __func__),
5e82e1c8 4230 REJECT_OBSOLETE, "bad-version");
8d655683 4231
a48f2d6d
LD
4232 return true;
4233}
4234
4235bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev)
4236{
4237 const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
51aa2492 4238 const Consensus::Params& consensusParams = Params().GetConsensus();
8d655683 4239
a48f2d6d 4240 // Check that all transactions are finalized
a1d3c6fb 4241 BOOST_FOREACH(const CTransaction& tx, block.vtx) {
8d655683 4242
072099d7
S
4243 // Check transaction contextually against consensus rules at block height
4244 if (!ContextualCheckTransaction(tx, state, nHeight, 100)) {
4245 return false; // Failure reason has been set in validation state object
4246 }
8d655683 4247
a1d3c6fb
MF
4248 int nLockTimeFlags = 0;
4249 int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
8d655683 4250 ? pindexPrev->GetMedianTimePast()
4251 : block.GetBlockTime();
14aa6cc0 4252 if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
5262fde0 4253 return state.DoS(10, error("%s: contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal");
a48f2d6d 4254 }
a1d3c6fb 4255 }
8d655683 4256
c2a722d3
DH
4257 // Enforce BIP 34 rule that the coinbase starts with serialized block height.
4258 // In Zcash this has been enforced since launch, except that the genesis
4259 // block didn't include the height in the coinbase (see Zcash protocol spec
4260 // section '6.8 Bitcoin Improvement Proposals').
548bbd95 4261 if (nHeight > 0)
a48f2d6d
LD
4262 {
4263 CScript expect = CScript() << nHeight;
4264 if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
4265 !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) {
16cd9f2d 4266 return state.DoS(100, error("%s: block height mismatch in coinbase", __func__), REJECT_INVALID, "bad-cb-height");
a48f2d6d
LD
4267 }
4268 }
8d655683 4269
a48f2d6d
LD
4270 return true;
4271}
4272
531b9293 4273bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex)
0a61b0df 4274{
161f617d 4275 static uint256 zero;
4e382177 4276 const CChainParams& chainparams = Params();
e07c943c 4277 AssertLockHeld(cs_main);
531b9293 4278
de8834fb 4279 // Check for duplicate
2a4d3464 4280 uint256 hash = block.GetHash();
145d5be8 4281 BlockMap::iterator miSelf = mapBlockIndex.find(hash);
6d3df1e6 4282 CBlockIndex *pindex = NULL;
5215d24e 4283 if (miSelf != mapBlockIndex.end())
4284 {
341735eb 4285 // Block header is already known.
55c01f13 4286 if ( (pindex= miSelf->second) == 0 )
58ef04c7 4287 miSelf->second = pindex = AddToBlockIndex(block);
341735eb
PW
4288 if (ppindex)
4289 *ppindex = pindex;
6477ad07 4290 if ( pindex != 0 && pindex->nStatus & BLOCK_FAILED_MASK )
85f1853e 4291 return state.Invalid(error("%s: block is marked invalid", __func__), 0, "duplicate");
8d725ab4 4292 /*if ( pindex != 0 && hash == komodo_requestedhash )
b80fef6f 4293 {
4294 fprintf(stderr,"AddToBlockIndex A komodo_requestedhash %s\n",komodo_requestedhash.ToString().c_str());
4295 memset(&komodo_requestedhash,0,sizeof(komodo_requestedhash));
bddeaf5e 4296 komodo_requestedcount = 0;
8d725ab4 4297 }*/
55c01f13 4298
b92dfb1e 4299 //if ( pindex == 0 )
4300 // fprintf(stderr,"accepthdr %s already known but no pindex\n",hash.ToString().c_str());
dc4124de 4301 return true;
942b33a1 4302 }
531b9293 4303 if (!CheckBlockHeader(futureblockp,*ppindex!=0?(*ppindex)->nHeight:0,*ppindex, block, state,0))
44c0859f 4304 {
9840ae39 4305 if ( *futureblockp == 0 )
e8314e82 4306 {
b1af3ff1 4307 LogPrintf("AcceptBlockHeader CheckBlockHeader error\n");
9840ae39 4308 return false;
e8314e82 4309 }
44c0859f 4310 }
0a61b0df 4311 // Get prev block index
7fea4846 4312 CBlockIndex* pindexPrev = NULL;
e6c99a7a 4313 if (hash != chainparams.GetConsensus().hashGenesisBlock)
4314 {
145d5be8 4315 BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
b56585d0 4316 if (mi == mapBlockIndex.end())
beb911ec 4317 {
b1af3ff1 4318 LogPrintf("AcceptBlockHeader hashPrevBlock %s not found\n",block.hashPrevBlock.ToString().c_str());
f3071571 4319 return(false);
4320 //return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk");
beb911ec 4321 }
b56585d0 4322 pindexPrev = (*mi).second;
e6c99a7a 4323 if (pindexPrev == 0 )
f65a34b9 4324 {
b1af3ff1 4325 LogPrintf("AcceptBlockHeader hashPrevBlock %s no pindexPrev\n",block.hashPrevBlock.ToString().c_str());
e6c99a7a 4326 return(false);
f65a34b9 4327 }
e6c99a7a 4328 if ( (pindexPrev->nStatus & BLOCK_FAILED_MASK) )
5262fde0 4329 return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
942b33a1 4330 }
a48f2d6d 4331 if (!ContextualCheckBlockHeader(block, state, pindexPrev))
44c0859f 4332 {
2fea1c97 4333 //fprintf(stderr,"AcceptBlockHeader ContextualCheckBlockHeader failed\n");
b1af3ff1 4334 LogPrintf("AcceptBlockHeader ContextualCheckBlockHeader failed\n");
a48f2d6d 4335 return false;
44c0859f 4336 }
942b33a1 4337 if (pindex == NULL)
7466a330 4338 {
58ef04c7 4339 if ( (pindex= AddToBlockIndex(block)) != 0 )
f7ce3004 4340 {
58ef04c7 4341 miSelf = mapBlockIndex.find(hash);
4342 if (miSelf != mapBlockIndex.end())
4343 miSelf->second = pindex;
e8314e82 4344 //fprintf(stderr,"AcceptBlockHeader couldnt add to block index\n");
f7ce3004 4345 }
7466a330 4346 }
942b33a1
PW
4347 if (ppindex)
4348 *ppindex = pindex;
8d725ab4 4349 /*if ( pindex != 0 && hash == komodo_requestedhash )
161f617d 4350 {
4351 fprintf(stderr,"AddToBlockIndex komodo_requestedhash %s\n",komodo_requestedhash.ToString().c_str());
4352 memset(&komodo_requestedhash,0,sizeof(komodo_requestedhash));
bddeaf5e 4353 komodo_requestedcount = 0;
8d725ab4 4354 }*/
942b33a1
PW
4355 return true;
4356}
4357
531b9293 4358bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp)
942b33a1 4359{
e6973430 4360 const CChainParams& chainparams = Params();
942b33a1 4361 AssertLockHeld(cs_main);
8d655683 4362
942b33a1 4363 CBlockIndex *&pindex = *ppindex;
531b9293 4364 if (!AcceptBlockHeader(futureblockp,block, state, &pindex))
bd8997bf 4365 {
9840ae39 4366 if ( *futureblockp == 0 )
e8314e82 4367 {
857c644f 4368 LogPrintf("AcceptBlock AcceptBlockHeader error\n");
9840ae39 4369 return false;
e8314e82 4370 }
bd8997bf 4371 }
1e9dc6a8 4372 if ( pindex == 0 )
4373 {
b5711436 4374 LogPrintf("AcceptBlock null pindex error\n");
4375 return false;
1e9dc6a8 4376 }
da4020cb 4377 //fprintf(stderr,"acceptblockheader passed\n");
304892fc
SD
4378 // Try to process all requested blocks that we don't have, but only
4379 // process an unrequested block if it's new and has enough work to
93b606ae 4380 // advance our tip, and isn't too many blocks ahead.
304892fc
SD
4381 bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
4382 bool fHasMoreWork = (chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork : true);
93b606ae
SD
4383 // Blocks that are too out-of-order needlessly limit the effectiveness of
4384 // pruning, because pruning will not delete block files that contain any
4385 // blocks which are too close in height to the tip. Apply this test
4386 // regardless of whether pruning is enabled; it should generally be safe to
4387 // not process unrequested blocks.
42c2e91b 4388 bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + BLOCK_DOWNLOAD_WINDOW)); //MIN_BLOCKS_TO_KEEP));
8d655683 4389
304892fc
SD
4390 // TODO: deal better with return value and error conditions for duplicate
4391 // and unrequested blocks.
b92dfb1e 4392 //fprintf(stderr,"Accept %s flags already.%d requested.%d morework.%d farahead.%d\n",pindex->GetBlockHash().ToString().c_str(),fAlreadyHave,fRequested,fHasMoreWork,fTooFarAhead);
304892fc
SD
4393 if (fAlreadyHave) return true;
4394 if (!fRequested) { // If we didn't ask for it:
4395 if (pindex->nTx != 0) return true; // This is a previously-processed block that was pruned
4396 if (!fHasMoreWork) return true; // Don't process less-work chains
93b606ae 4397 if (fTooFarAhead) return true; // Block height is too high
341735eb 4398 }
8d655683 4399
6fb8d0c2
JG
4400 // See method docstring for why this is always disabled
4401 auto verifier = libzcash::ProofVerifier::Disabled();
531b9293 4402 if ((!CheckBlock(futureblockp,pindex->nHeight,pindex,block, state, verifier,0)) || !ContextualCheckBlock(block, state, pindex->pprev))
07359935 4403 {
9840ae39 4404 if ( *futureblockp == 0 )
4405 {
4406 if (state.IsInvalid() && !state.CorruptionPossible()) {
4407 pindex->nStatus |= BLOCK_FAILED_VALID;
4408 setDirtyBlockIndex.insert(pindex);
4409 }
b1af3ff1 4410 LogPrintf("AcceptBlock CheckBlock or ContextualCheckBlock error\n");
9840ae39 4411 return false;
e8314e82 4412 }
942b33a1 4413 }
8d655683 4414
942b33a1 4415 int nHeight = pindex->nHeight;
0a61b0df 4416 // Write block to history file
421218d3 4417 try {
2a4d3464 4418 unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
421218d3
PW
4419 CDiskBlockPos blockPos;
4420 if (dbp != NULL)
4421 blockPos = *dbp;
209377a7 4422 if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != NULL))
5262fde0 4423 return error("AcceptBlock(): FindBlockPos failed");
421218d3 4424 if (dbp == NULL)
e6973430 4425 if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
27afcd89 4426 AbortNode(state, "Failed to write block");
942b33a1 4427 if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
5262fde0 4428 return error("AcceptBlock(): ReceivedBlockTransactions failed");
27df4123 4429 } catch (const std::runtime_error& e) {
27afcd89 4430 return AbortNode(state, std::string("System error: ") + e.what());
421218d3 4431 }
8d655683 4432
f9ec3f0f 4433 if (fCheckForPruning)
4434 FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
9840ae39 4435 if ( *futureblockp == 0 )
4436 return true;
857c644f 4437 LogPrintf("AcceptBlock block from future error\n");
e8314e82 4438 return false;
0a61b0df 4439}
4440
51aa2492 4441static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams)
de237cbf
GA
4442{
4443 unsigned int nFound = 0;
51aa2492 4444 for (int i = 0; i < consensusParams.nMajorityWindow && nFound < nRequired && pstart != NULL; i++)
de237cbf
GA
4445 {
4446 if (pstart->nVersion >= minVersion)
4447 ++nFound;
4448 pstart = pstart->pprev;
4449 }
4450 return (nFound >= nRequired);
4451}
4452
c75c18fc 4453void komodo_currentheight_set(int32_t height);
c9a09183 4454
b5d0fe2e 4455CBlockIndex *komodo_ensure(CBlock *pblock,uint256 hash)
4ac854ea 4456{
58ef04c7 4457 CBlockIndex *pindex = 0;
4ac854ea 4458 BlockMap::iterator miSelf = mapBlockIndex.find(hash);
4459 if ( miSelf != mapBlockIndex.end() )
4460 {
4461 if ( (pindex= miSelf->second) == 0 ) // create pindex so first Accept block doesnt fail
4462 {
4463 miSelf->second = AddToBlockIndex(*pblock);
4464 //fprintf(stderr,"Block header %s is already known, but without pindex -> ensured %p\n",hash.ToString().c_str(),miSelf->second);
4465 }
58ef04c7 4466 /*if ( hash != Params().GetConsensus().hashGenesisBlock )
4ac854ea 4467 {
4468 miSelf = mapBlockIndex.find(pblock->hashPrevBlock);
4469 if ( miSelf != mapBlockIndex.end() )
4470 {
4471 if ( miSelf->second == 0 )
4472 {
4473 miSelf->second = InsertBlockIndex(pblock->hashPrevBlock);
4474 fprintf(stderr,"autocreate previndex %s\n",pblock->hashPrevBlock.ToString().c_str());
4475 }
4476 }
58ef04c7 4477 }*/
4ac854ea 4478 }
58ef04c7 4479 return(pindex);
4ac854ea 4480}
4481
4482CBlockIndex *oldkomodo_ensure(CBlock *pblock,uint256 hash)
b5d0fe2e 4483{
b5711436 4484 CBlockIndex *pindex=0,*previndex=0;
5d214ce7 4485 if ( (pindex= mapBlockIndex[hash]) == 0 )
d1c9d1b4 4486 {
4487 pindex = new CBlockIndex();
4488 if (!pindex)
4489 throw runtime_error("komodo_ensure: new CBlockIndex failed");
4490 BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindex)).first;
4491 pindex->phashBlock = &((*mi).first);
4492 }
b5d0fe2e 4493 BlockMap::iterator miSelf = mapBlockIndex.find(hash);
b5711436 4494 if ( miSelf == mapBlockIndex.end() )
4495 {
5d214ce7 4496 LogPrintf("komodo_ensure unexpected missing hash %s\n",hash.ToString().c_str());
4497 return(0);
b5711436 4498 }
5d214ce7 4499 if ( miSelf->second == 0 ) // create pindex so first Accept block doesnt fail
b5d0fe2e 4500 {
5d214ce7 4501 if ( pindex == 0 )
d1c9d1b4 4502 {
5d214ce7 4503 pindex = AddToBlockIndex(*pblock);
d1c9d1b4 4504 fprintf(stderr,"ensure call addtoblockindex, got %p\n",pindex);
4505 }
5d214ce7 4506 if ( pindex != 0 )
b5d0fe2e 4507 {
5d214ce7 4508 miSelf->second = pindex;
4509 LogPrintf("Block header %s is already known, but without pindex -> ensured %p\n",hash.ToString().c_str(),miSelf->second);
4510 } else LogPrintf("komodo_ensure unexpected null pindex\n");
4511 }
4512 /*if ( hash != Params().GetConsensus().hashGenesisBlock )
f8a07170 4513 {
4514 miSelf = mapBlockIndex.find(pblock->hashPrevBlock);
4515 if ( miSelf == mapBlockIndex.end() )
b5711436 4516 previndex = InsertBlockIndex(pblock->hashPrevBlock);
4517 if ( (miSelf= mapBlockIndex.find(pblock->hashPrevBlock)) != mapBlockIndex.end() )
f8a07170 4518 {
b5711436 4519 if ( miSelf->second == 0 ) // create pindex so first Accept block doesnt fail
4520 {
4521 if ( previndex == 0 )
4522 previndex = InsertBlockIndex(pblock->hashPrevBlock);
4523 if ( previndex != 0 )
4524 {
4525 miSelf->second = previndex;
4526 LogPrintf("autocreate previndex %s\n",pblock->hashPrevBlock.ToString().c_str());
4527 } else LogPrintf("komodo_ensure unexpected null previndex\n");
4528 }
4529 } else LogPrintf("komodo_ensure unexpected null miprev\n");
857c644f 4530 }
5d214ce7 4531 }*/
4532 return(pindex);
b5d0fe2e 4533}
4534
7bb789bb 4535bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
0a61b0df 4536{
0a61b0df 4537 // Preliminary checks
531b9293 4538 bool checked; uint256 hash; int32_t futureblock=0;
6fb8d0c2 4539 auto verifier = libzcash::ProofVerifier::Disabled();
bc2bcf85 4540 hash = pblock->GetHash();
194ad5b8 4541 fprintf(stderr,"ProcessBlock %d\n",(int32_t)chainActive.LastTip()->nHeight);
a5fc9157 4542 if ( chainActive.LastTip() != 0 )
4543 komodo_currentheight_set(chainActive.LastTip()->nHeight);
4544 checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
0a61b0df 4545 {
341735eb 4546 LOCK(cs_main);
bc2bcf85 4547 bool fRequested = MarkBlockAsReceived(hash);
304892fc 4548 fRequested |= fForceProcessing;
55d19b21 4549 if ( checked != 0 && komodo_checkPOW(0,pblock,height) < 0 ) //from_miner && ASSETCHAINS_STAKED == 0
13b8b2ed 4550 {
b8add6a4 4551 checked = 0;
e83bf6b3 4552 //fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0);
13b8b2ed 4553 }
9f6cb8f0 4554 if (!checked && futureblock == 0)
c7a1d234 4555 {
50c490cb 4556 if ( pfrom != 0 )
c7a1d234 4557 {
04a1f0bb 4558 Misbehaving(pfrom->GetId(), 1);
c7a1d234 4559 }
872cf91b 4560 return error("%s: CheckBlock FAILED", __func__);
5c88e3c1 4561 }
341735eb
PW
4562 // Store to disk
4563 CBlockIndex *pindex = NULL;
163fbf95 4564 if ( 1 )
17522a55 4565 {
66dd02d2 4566 // without the komodo_ensure call, it is quite possible to get a non-error but null pindex returned from AcceptBlockHeader. In a 2 node network, it will be a long time before that block is reprocessed. Even though restarting makes it rescan, it seems much better to keep the nodes in sync
b92dfb1e 4567 komodo_ensure(pblock,hash);
0f102ea7 4568 }
531b9293 4569 bool ret = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp);
341735eb
PW
4570 if (pindex && pfrom) {
4571 mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
0a61b0df 4572 }
3fcfbc8a 4573 CheckBlockIndex();
531b9293 4574 if (!ret && futureblock == 0)
5262fde0 4575 return error("%s: AcceptBlock FAILED", __func__);
bddeaf5e 4576 //else fprintf(stderr,"added block %s %p\n",pindex->GetBlockHash().ToString().c_str(),pindex->pprev);
18e72167 4577 }
8d655683 4578
531b9293 4579 if (futureblock == 0 && !ActivateBestChain(state, pblock))
5262fde0 4580 return error("%s: ActivateBestChain failed", __func__);
194ad5b8 4581 fprintf(stderr,"finished ProcessBlock %d\n",(int32_t)chainActive.LastTip()->nHeight);
61cbf1c6 4582
0a61b0df 4583 return true;
4584}
4585
df08a626
LD
4586bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot)
4587{
4588 AssertLockHeld(cs_main);
4589 assert(pindexPrev == chainActive.Tip());
8d655683 4590
df08a626
LD
4591 CCoinsViewCache viewNew(pcoinsTip);
4592 CBlockIndex indexDummy(block);
4593 indexDummy.pprev = pindexPrev;
4594 indexDummy.nHeight = pindexPrev->nHeight + 1;
6fb8d0c2
JG
4595 // JoinSplit proofs are verified in ConnectBlock
4596 auto verifier = libzcash::ProofVerifier::Disabled();
df08a626
LD
4597 // NOTE: CheckBlockHeader is called by CheckBlock
4598 if (!ContextualCheckBlockHeader(block, state, pindexPrev))
d4190a2a 4599 {
b92dfb1e 4600 //fprintf(stderr,"TestBlockValidity failure A checkPOW.%d\n",fCheckPOW);
df08a626 4601 return false;
d4190a2a 4602 }
9f6cb8f0 4603 int32_t futureblock;
4604 if (!CheckBlock(&futureblock,indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot))
d4190a2a 4605 {
b92dfb1e 4606 //fprintf(stderr,"TestBlockValidity failure B checkPOW.%d\n",fCheckPOW);
df08a626 4607 return false;
d4190a2a 4608 }
df08a626 4609 if (!ContextualCheckBlock(block, state, pindexPrev))
d4190a2a 4610 {
b92dfb1e 4611 //fprintf(stderr,"TestBlockValidity failure C checkPOW.%d\n",fCheckPOW);
df08a626 4612 return false;
d4190a2a 4613 }
455ba304 4614 if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW))
d4190a2a 4615 {
b92dfb1e 4616 //fprintf(stderr,"TestBlockValidity failure D checkPOW.%d\n",fCheckPOW);
df08a626 4617 return false;
d4190a2a 4618 }
df08a626 4619 assert(state.IsValid());
9840ae39 4620 if ( futureblock != 0 )
4621 return(false);
df08a626
LD
4622 return true;
4623}
4624
f9ec3f0f 4625/**
4626 * BLOCK PRUNING CODE
4627 */
4628
4629/* Calculate the amount of disk space the block & undo files currently use */
4630uint64_t CalculateCurrentUsage()
4631{
4632 uint64_t retval = 0;
4633 BOOST_FOREACH(const CBlockFileInfo &file, vinfoBlockFile) {
4634 retval += file.nSize + file.nUndoSize;
4635 }
4636 return retval;
4637}
4638
4639/* Prune a block file (modify associated database entries)*/
4640void PruneOneBlockFile(const int fileNumber)
4641{
4642 for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it) {
4643 CBlockIndex* pindex = it->second;
4644 if (pindex->nFile == fileNumber) {
4645 pindex->nStatus &= ~BLOCK_HAVE_DATA;
4646 pindex->nStatus &= ~BLOCK_HAVE_UNDO;
4647 pindex->nFile = 0;
4648 pindex->nDataPos = 0;
4649 pindex->nUndoPos = 0;
4650 setDirtyBlockIndex.insert(pindex);
8d655683 4651
f9ec3f0f 4652 // Prune from mapBlocksUnlinked -- any block we prune would have
4653 // to be downloaded again in order to consider its chain, at which
4654 // point it would be considered as a candidate for
4655 // mapBlocksUnlinked or setBlockIndexCandidates.
4656 std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev);
4657 while (range.first != range.second) {
4658 std::multimap<CBlockIndex *, CBlockIndex *>::iterator it = range.first;
4659 range.first++;
4660 if (it->second == pindex) {
4661 mapBlocksUnlinked.erase(it);
4662 }
4663 }
4664 }
4665 }
8d655683 4666
f9ec3f0f 4667 vinfoBlockFile[fileNumber].SetNull();
4668 setDirtyFileInfo.insert(fileNumber);
4669}
4670
4671
4672void UnlinkPrunedFiles(std::set<int>& setFilesToPrune)
4673{
4674 for (set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
4675 CDiskBlockPos pos(*it, 0);
4676 boost::filesystem::remove(GetBlockPosFilename(pos, "blk"));
4677 boost::filesystem::remove(GetBlockPosFilename(pos, "rev"));
4678 LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it);
4679 }
4680}
4681
4682/* Calculate the block/rev files that should be deleted to remain under target*/
4683void FindFilesToPrune(std::set<int>& setFilesToPrune)
4684{
4685 LOCK2(cs_main, cs_LastBlockFile);
4686 if (chainActive.Tip() == NULL || nPruneTarget == 0) {
4687 return;
4688 }
4689 if (chainActive.Tip()->nHeight <= Params().PruneAfterHeight()) {
4690 return;
4691 }
b89f3077 4692 unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP;
f9ec3f0f 4693 uint64_t nCurrentUsage = CalculateCurrentUsage();
4694 // We don't check to prune until after we've allocated new space for files
4695 // So we should leave a buffer under our target to account for another allocation
4696 // before the next pruning.
4697 uint64_t nBuffer = BLOCKFILE_CHUNK_SIZE + UNDOFILE_CHUNK_SIZE;
4698 uint64_t nBytesToPrune;
4699 int count=0;
8d655683 4700
f9ec3f0f 4701 if (nCurrentUsage + nBuffer >= nPruneTarget) {
4702 for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) {
4703 nBytesToPrune = vinfoBlockFile[fileNumber].nSize + vinfoBlockFile[fileNumber].nUndoSize;
8d655683 4704
f9ec3f0f 4705 if (vinfoBlockFile[fileNumber].nSize == 0)
4706 continue;
8d655683 4707
f9ec3f0f 4708 if (nCurrentUsage + nBuffer < nPruneTarget) // are we below our target?
4709 break;
8d655683 4710
6cb70ca4 4711 // don't prune files that could have a block within MIN_BLOCKS_TO_KEEP of the main chain's tip but keep scanning
b89f3077 4712 if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
6cb70ca4 4713 continue;
8d655683 4714
f9ec3f0f 4715 PruneOneBlockFile(fileNumber);
4716 // Queue up the files for removal
4717 setFilesToPrune.insert(fileNumber);
4718 nCurrentUsage -= nBytesToPrune;
4719 count++;
4720 }
4721 }
8d655683 4722
b89f3077 4723 LogPrint("prune", "Prune: target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n",
8d655683 4724 nPruneTarget/1024/1024, nCurrentUsage/1024/1024,
4725 ((int64_t)nPruneTarget - (int64_t)nCurrentUsage)/1024/1024,
4726 nLastBlockWeCanPrune, count);
f9ec3f0f 4727}
4728
51ed9ec9 4729bool CheckDiskSpace(uint64_t nAdditionalBytes)
0a61b0df 4730{
a3241998 4731 uint64_t nFreeBytesAvailable = boost::filesystem::space(GetDataDir()).available;
8d655683 4732
966ae00f
PK
4733 // Check for nMinDiskSpace bytes (currently 50MB)
4734 if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
b9b2e3fa 4735 return AbortNode("Disk space is low!", _("Error: Disk space is low!"));
8d655683 4736
0a61b0df 4737 return true;
4738}
4739
5382bcf8 4740FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
42613c97 4741{
cf53fd7c 4742 static int32_t didinit[64];
450cbb09 4743 if (pos.IsNull())
0a61b0df 4744 return NULL;
ec7eb0fa 4745 boost::filesystem::path path = GetBlockPosFilename(pos, prefix);
5382bcf8
PW
4746 boost::filesystem::create_directories(path.parent_path());
4747 FILE* file = fopen(path.string().c_str(), "rb+");
4748 if (!file && !fReadOnly)
4749 file = fopen(path.string().c_str(), "wb+");
450cbb09 4750 if (!file) {
7d9d134b 4751 LogPrintf("Unable to open file %s\n", path.string());
0a61b0df 4752 return NULL;
450cbb09 4753 }
1a608050 4754 if ( pos.nFile < sizeof(didinit)/sizeof(*didinit) && didinit[pos.nFile] == 0 && strcmp(prefix,(char *)"blk") == 0 )
f527fcdb 4755 {
cf53fd7c 4756 komodo_prefetch(file);
1a608050 4757 didinit[pos.nFile] = 1;
f527fcdb 4758 }
5382bcf8
PW
4759 if (pos.nPos) {
4760 if (fseek(file, pos.nPos, SEEK_SET)) {
7d9d134b 4761 LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string());
5382bcf8
PW
4762 fclose(file);
4763 return NULL;
4764 }
4765 }
0a61b0df 4766 return file;
4767}
4768
5382bcf8
PW
4769FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) {
4770 return OpenDiskFile(pos, "blk", fReadOnly);
4771}
4772
69e07747 4773FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
5382bcf8
PW
4774 return OpenDiskFile(pos, "rev", fReadOnly);
4775}
4776
ec7eb0fa
SD
4777boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix)
4778{
f7e36370 4779 return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile);
ec7eb0fa
SD
4780}
4781
2d8a4829
PW
4782CBlockIndex * InsertBlockIndex(uint256 hash)
4783{
4f152496 4784 if (hash.IsNull())
2d8a4829 4785 return NULL;
8d655683 4786
2d8a4829 4787 // Return existing
145d5be8 4788 BlockMap::iterator mi = mapBlockIndex.find(hash);
2d8a4829
PW
4789 if (mi != mapBlockIndex.end())
4790 return (*mi).second;
8d655683 4791
2d8a4829
PW
4792 // Create new
4793 CBlockIndex* pindexNew = new CBlockIndex();
4794 if (!pindexNew)
5262fde0 4795 throw runtime_error("LoadBlockIndex(): new CBlockIndex failed");
2d8a4829
PW
4796 mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
4797 pindexNew->phashBlock = &((*mi).first);
66dd02d2 4798 //fprintf(stderr,"inserted to block index %s\n",hash.ToString().c_str());
e1407365 4799
2d8a4829
PW
4800 return pindexNew;
4801}
4802
102cc989 4803//void komodo_pindex_init(CBlockIndex *pindex,int32_t height);
141950a4 4804
2d8a4829
PW
4805bool static LoadBlockIndexDB()
4806{
11982d36 4807 const CChainParams& chainparams = Params();
6a0c9826 4808 LogPrintf("%s: start loading guts\n", __func__);
2d8a4829
PW
4809 if (!pblocktree->LoadBlockIndexGuts())
4810 return false;
6a0c9826 4811 LogPrintf("%s: loaded guts\n", __func__);
b31499ec 4812 boost::this_thread::interruption_point();
8d655683 4813
1657c4bc 4814 // Calculate nChainWork
2d8a4829
PW
4815 vector<pair<int, CBlockIndex*> > vSortedByHeight;
4816 vSortedByHeight.reserve(mapBlockIndex.size());
4817 BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
4818 {
4819 CBlockIndex* pindex = item.second;
4820 vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
102cc989 4821 //komodo_pindex_init(pindex,(int32_t)pindex->nHeight);
2d8a4829 4822 }
e1a6427c 4823 //fprintf(stderr,"load blockindexDB paired %u\n",(uint32_t)time(NULL));
2d8a4829 4824 sort(vSortedByHeight.begin(), vSortedByHeight.end());
e1a6427c 4825 //fprintf(stderr,"load blockindexDB sorted %u\n",(uint32_t)time(NULL));
2d8a4829
PW
4826 BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
4827 {
4828 CBlockIndex* pindex = item.second;
092b58d1 4829 pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
f9ec3f0f 4830 // We can link the chain of blocks for which we've received transactions at some point.
4831 // Pruned nodes may have deleted the block.
4832 if (pindex->nTx > 0) {
341735eb
PW
4833 if (pindex->pprev) {
4834 if (pindex->pprev->nChainTx) {
4835 pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
ad6a36ad
JG
4836 if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
4837 pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
4838 } else {
4839 pindex->nChainSproutValue = boost::none;
4840 }
341735eb
PW
4841 } else {
4842 pindex->nChainTx = 0;
ad6a36ad 4843 pindex->nChainSproutValue = boost::none;
341735eb
PW
4844 mapBlocksUnlinked.insert(std::make_pair(pindex->pprev, pindex));
4845 }
4846 } else {
4847 pindex->nChainTx = pindex->nTx;
ad6a36ad 4848 pindex->nChainSproutValue = pindex->nSproutValue;
341735eb
PW
4849 }
4850 }
9e851450
JG
4851 // Construct in-memory chain of branch IDs.
4852 // Relies on invariant: a block that does not activate a network upgrade
4853 // will always be valid under the same consensus rules as its parent.
828940b1
JG
4854 // Genesis block has a branch ID of zero by definition, but has no
4855 // validity status because it is side-loaded into a fresh chain.
4856 // Activation blocks will have branch IDs set (read from disk).
4857 if (pindex->pprev) {
4858 if (pindex->IsValid(BLOCK_VALID_CONSENSUS) && !pindex->nCachedBranchId) {
4859 pindex->nCachedBranchId = pindex->pprev->nCachedBranchId;
4860 }
4861 } else {
be126699 4862 pindex->nCachedBranchId = SPROUT_BRANCH_ID;
9e851450 4863 }
341735eb 4864 if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == NULL))
e17bd583 4865 setBlockIndexCandidates.insert(pindex);
85eb2cef
PW
4866 if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
4867 pindexBestInvalid = pindex;
c9a09183
PW
4868 if (pindex->pprev)
4869 pindex->BuildSkip();
341735eb
PW
4870 if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == NULL || CBlockIndexWorkComparator()(pindexBestHeader, pindex)))
4871 pindexBestHeader = pindex;
102cc989 4872 //komodo_pindex_init(pindex,(int32_t)pindex->nHeight);
2d8a4829 4873 }
e1a6427c 4874 //fprintf(stderr,"load blockindexDB chained %u\n",(uint32_t)time(NULL));
d00db115 4875
2d8a4829
PW
4876 // Load block file info
4877 pblocktree->ReadLastBlockFile(nLastBlockFile);
ed6d1a2c 4878 vinfoBlockFile.resize(nLastBlockFile + 1);
7b2bb962 4879 LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile);
ed6d1a2c
PW
4880 for (int nFile = 0; nFile <= nLastBlockFile; nFile++) {
4881 pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
4882 }
7b2bb962 4883 LogPrintf("%s: last block file info: %s\n", __func__, vinfoBlockFile[nLastBlockFile].ToString());
ed6d1a2c
PW
4884 for (int nFile = nLastBlockFile + 1; true; nFile++) {
4885 CBlockFileInfo info;
4886 if (pblocktree->ReadBlockFileInfo(nFile, info)) {
4887 vinfoBlockFile.push_back(info);
4888 } else {
4889 break;
4890 }
4891 }
8d655683 4892
8c93bf4c
AH
4893 // Check presence of blk files
4894 LogPrintf("Checking all blk files are present...\n");
4895 set<int> setBlkDataFiles;
4896 BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
4897 {
4898 CBlockIndex* pindex = item.second;
4899 if (pindex->nStatus & BLOCK_HAVE_DATA) {
4900 setBlkDataFiles.insert(pindex->nFile);
4901 }
102cc989 4902 //komodo_pindex_init(pindex,(int32_t)pindex->nHeight);
8c93bf4c 4903 }
e1a6427c 4904 //fprintf(stderr,"load blockindexDB %u\n",(uint32_t)time(NULL));
8c93bf4c
AH
4905 for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++)
4906 {
4907 CDiskBlockPos pos(*it, 0);
a8738238 4908 if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
8c93bf4c
AH
4909 return false;
4910 }
4911 }
8d655683 4912
f9ec3f0f 4913 // Check whether we have ever pruned block & undo files
4914 pblocktree->ReadFlag("prunedblockfiles", fHavePruned);
4915 if (fHavePruned)
4916 LogPrintf("LoadBlockIndexDB(): Block files have previously been pruned\n");
8d655683 4917
89b7019b
PW
4918 // Check whether we need to continue reindexing
4919 bool fReindexing = false;
4920 pblocktree->ReadReindexing(fReindexing);
4921 fReindex |= fReindexing;
8d655683 4922
2d1fa42e
PW
4923 // Check whether we have a transaction index
4924 pblocktree->ReadFlag("txindex", fTxIndex);
52070c87 4925 LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled");
8b78a819
T
4926 // Check whether we have an address index
4927 pblocktree->ReadFlag("addressindex", fAddressIndex);
4928 LogPrintf("%s: address index %s\n", __func__, fAddressIndex ? "enabled" : "disabled");
4929
4930 // Check whether we have a timestamp index
4931 pblocktree->ReadFlag("timestampindex", fTimestampIndex);
4932 LogPrintf("%s: timestamp index %s\n", __func__, fTimestampIndex ? "enabled" : "disabled");
4933
4934 // Check whether we have a spent index
4935 pblocktree->ReadFlag("spentindex", fSpentIndex);
4936 LogPrintf("%s: spent index %s\n", __func__, fSpentIndex ? "enabled" : "disabled");
4937
0bc1e2c4
JG
4938 // Fill in-memory data
4939 BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
4940 {
4941 CBlockIndex* pindex = item.second;
4942 // - This relationship will always be true even if pprev has multiple
4943 // children, because hashAnchor is technically a property of pprev,
4944 // not its children.
4945 // - This will miss chain tips; we handle the best tip below, and other
4946 // tips will be handled by ConnectTip during a re-org.
4947 if (pindex->pprev) {
4948 pindex->pprev->hashAnchorEnd = pindex->hashAnchor;
4949 }
102cc989 4950 //komodo_pindex_init(pindex,(int32_t)pindex->nHeight);
0bc1e2c4 4951 }
8d655683 4952
85eb2cef 4953 // Load pointer to end of best chain
145d5be8 4954 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
84674082 4955 if (it == mapBlockIndex.end())
89b7019b 4956 return true;
84674082 4957 chainActive.SetTip(it->second);
0bc1e2c4
JG
4958 // Set hashAnchorEnd for the end of best chain
4959 it->second->hashAnchorEnd = pcoinsTip->GetBestAnchor();
8d655683 4960
cca48f69 4961 PruneBlockIndexCandidates();
3bd2c3bd
DL
4962
4963 double progress;
4964 if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
4965 progress = Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip());
4966 } else {
4967 int32_t longestchain = komodo_longestchain();
4968 // TODO: komodo_longestchain does not have the data it needs at the time LoadBlockIndexDB
4969 // runs, which makes it return 0, so we guess 50% for now
4970 progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 0.5;
4971 }
8d655683 4972
52070c87 4973 LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__,
86131275 4974 chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(),
4975 DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()),
3bd2c3bd 4976 progress);
8d655683 4977
5b3bc971 4978 EnforceNodeDeprecation(chainActive.Height(), true);
8d655683 4979
1f355b66
PW
4980 return true;
4981}
4982
06a91d96
CL
4983CVerifyDB::CVerifyDB()
4984{
4985 uiInterface.ShowProgress(_("Verifying blocks..."), 0);
4986}
4987
4988CVerifyDB::~CVerifyDB()
4989{
4990 uiInterface.ShowProgress("", 100);
4991}
4992
2e280311 4993bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
168ba993 4994{
a475285a 4995 LOCK(cs_main);
4c6d41b8 4996 if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL)
1f355b66 4997 return true;
8d655683 4998
2d8a4829 4999 // Verify blocks in the best chain
f5906533 5000 if (nCheckDepth <= 0)
2d8a4829 5001 nCheckDepth = 1000000000; // suffices until the year 19000
4c6d41b8
PW
5002 if (nCheckDepth > chainActive.Height())
5003 nCheckDepth = chainActive.Height();
1f355b66 5004 nCheckLevel = std::max(0, std::min(4, nCheckLevel));
881a85a2 5005 LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
7c70438d 5006 CCoinsViewCache coins(coinsview);
4c6d41b8 5007 CBlockIndex* pindexState = chainActive.Tip();
1f355b66
PW
5008 CBlockIndex* pindexFailure = NULL;
5009 int nGoodTransactions = 0;
ef3988ca 5010 CValidationState state;
6fb8d0c2
JG
5011 // No need to verify JoinSplits twice
5012 auto verifier = libzcash::ProofVerifier::Disabled();
d00db115 5013 //fprintf(stderr,"start VerifyDB %u\n",(uint32_t)time(NULL));
4c6d41b8 5014 for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
2d8a4829 5015 {
b31499ec 5016 boost::this_thread::interruption_point();
06a91d96 5017 uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))));
4c6d41b8 5018 if (pindex->nHeight < chainActive.Height()-nCheckDepth)
2d8a4829
PW
5019 break;
5020 CBlock block;
1f355b66 5021 // check level 0: read from disk
b8add6a4 5022 if (!ReadBlockFromDisk(block, pindex,0))
5262fde0 5023 return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
2d8a4829 5024 // check level 1: verify block validity
9f6cb8f0 5025 int32_t futureblock;
4342e69b 5026 if (nCheckLevel >= 1 && !CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, verifier,0) )
5262fde0 5027 return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
1f355b66
PW
5028 // check level 2: verify undo validity
5029 if (nCheckLevel >= 2 && pindex) {
5030 CBlockUndo undo;
5031 CDiskBlockPos pos = pindex->GetUndoPos();
5032 if (!pos.IsNull()) {
e035c6a7 5033 if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash()))
5262fde0 5034 return error("VerifyDB(): *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
1f355b66
PW
5035 }
5036 }
5037 // check level 3: check for inconsistencies during memory-only disconnect of tip blocks
fc684ad8 5038 if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
1f355b66 5039 bool fClean = true;
5c363ed6 5040 if (!DisconnectBlock(block, state, pindex, coins, &fClean))
5262fde0 5041 return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
1f355b66
PW
5042 pindexState = pindex->pprev;
5043 if (!fClean) {
5044 nGoodTransactions = 0;
5045 pindexFailure = pindex;
5046 } else
5047 nGoodTransactions += block.vtx.size();
2d8a4829 5048 }
70477a0b
TZ
5049 if (ShutdownRequested())
5050 return true;
2d8a4829 5051 }
d00db115 5052 //fprintf(stderr,"end VerifyDB %u\n",(uint32_t)time(NULL));
1f355b66 5053 if (pindexFailure)
5262fde0 5054 return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
8d655683 5055
1f355b66
PW
5056 // check level 4: try reconnecting blocks
5057 if (nCheckLevel >= 4) {
5058 CBlockIndex *pindex = pindexState;
4c6d41b8 5059 while (pindex != chainActive.Tip()) {
b31499ec 5060 boost::this_thread::interruption_point();
06a91d96 5061 uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))));
4c6d41b8 5062 pindex = chainActive.Next(pindex);
b001c871 5063 CBlock block;
b8add6a4 5064 if (!ReadBlockFromDisk(block, pindex,0))
5262fde0 5065 return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
96f9009e 5066 if (!ConnectBlock(block, state, pindex, coins,false, true))
5262fde0 5067 return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
1f355b66 5068 }
2d8a4829 5069 }
8d655683 5070
4c6d41b8 5071 LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions);
8d655683 5072
2d8a4829
PW
5073 return true;
5074}
5075
89f20450
PW
5076bool RewindBlockIndex(const CChainParams& params)
5077{
5078 LOCK(cs_main);
8d655683 5079
9e851450 5080 // RewindBlockIndex is called after LoadBlockIndex, so at this point every block
828940b1
JG
5081 // index will have nCachedBranchId set based on the values previously persisted
5082 // to disk. By definition, a set nCachedBranchId means that the block was
9e851450
JG
5083 // fully-validated under the corresponding consensus rules. Thus we can quickly
5084 // identify whether the current active chain matches our expected sequence of
5085 // consensus rule changes, with two checks:
5086 //
5087 // - BLOCK_ACTIVATES_UPGRADE is set only on blocks that activate upgrades.
828940b1 5088 // - nCachedBranchId for each block matches what we expect.
9e851450
JG
5089 auto sufficientlyValidated = [&params](const CBlockIndex* pindex) {
5090 auto consensus = params.GetConsensus();
5091 bool fFlagSet = pindex->nStatus & BLOCK_ACTIVATES_UPGRADE;
5092 bool fFlagExpected = IsActivationHeightForAnyUpgrade(pindex->nHeight, consensus);
828940b1 5093 return fFlagSet == fFlagExpected &&
8d655683 5094 pindex->nCachedBranchId &&
5095 *pindex->nCachedBranchId == CurrentEpochBranchId(pindex->nHeight, consensus);
9e851450 5096 };
8d655683 5097
89f20450
PW
5098 int nHeight = 1;
5099 while (nHeight <= chainActive.Height()) {
9e851450 5100 if (!sufficientlyValidated(chainActive[nHeight])) {
89f20450
PW
5101 break;
5102 }
5103 nHeight++;
5104 }
8d655683 5105
89f20450 5106 // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
cb580c72
JG
5107 auto rewindLength = chainActive.Height() - nHeight;
5108 if (rewindLength > 0 && rewindLength > MAX_REORG_LENGTH) {
5109 auto pindexOldTip = chainActive.Tip();
5110 auto pindexRewind = chainActive[nHeight - 1];
5111 auto msg = strprintf(_(
8d655683 5112 "A block chain rewind has been detected that would roll back %d blocks! "
5113 "This is larger than the maximum of %d blocks, and so the node is shutting down for your safety."
5114 ), rewindLength, MAX_REORG_LENGTH) + "\n\n" +
5115 _("Rewind details") + ":\n" +
5116 "- " + strprintf(_("Current tip: %s, height %d"),
5117 pindexOldTip->phashBlock->GetHex(), pindexOldTip->nHeight) + "\n" +
5118 "- " + strprintf(_("Rewinding to: %s, height %d"),
5119 pindexRewind->phashBlock->GetHex(), pindexRewind->nHeight) + "\n\n" +
5120 _("Please help, human!");
cb580c72
JG
5121 LogPrintf("*** %s\n", msg);
5122 uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
5123 StartShutdown();
5124 return false;
5125 }
8d655683 5126
89f20450
PW
5127 CValidationState state;
5128 CBlockIndex* pindex = chainActive.Tip();
5129 while (chainActive.Height() >= nHeight) {
5130 if (fPruneMode && !(chainActive.Tip()->nStatus & BLOCK_HAVE_DATA)) {
5131 // If pruning, don't try rewinding past the HAVE_DATA point;
5132 // since older blocks can't be served anyway, there's
5133 // no need to walk further, and trying to DisconnectTip()
5134 // will fail (and require a needless reindex/redownload
5135 // of the blockchain).
5136 break;
5137 }
5138 if (!DisconnectTip(state, true)) {
5139 return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight);
5140 }
5141 // Occasionally flush state to disk.
5142 if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC))
5143 return false;
5144 }
8d655683 5145
89f20450
PW
5146 // Reduce validity flag and have-data flags.
5147 // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
5148 // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
5149 for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) {
5150 CBlockIndex* pindexIter = it->second;
8d655683 5151
89f20450
PW
5152 // Note: If we encounter an insufficiently validated block that
5153 // is on chainActive, it must be because we are a pruning node, and
5154 // this block or some successor doesn't HAVE_DATA, so we were unable to
5155 // rewind all the way. Blocks remaining on chainActive at this point
5156 // must not have their validity reduced.
9e851450 5157 if (!sufficientlyValidated(pindexIter) && !chainActive.Contains(pindexIter)) {
89f20450 5158 // Reduce validity
9e851450 5159 pindexIter->nStatus =
8d655683 5160 std::min<unsigned int>(pindexIter->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) |
5161 (pindexIter->nStatus & ~BLOCK_VALID_MASK);
9e851450 5162 // Remove have-data flags
89f20450 5163 pindexIter->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
9e851450
JG
5164 // Remove branch ID
5165 pindexIter->nStatus &= ~BLOCK_ACTIVATES_UPGRADE;
828940b1 5166 pindexIter->nCachedBranchId = boost::none;
9e851450 5167 // Remove storage location
89f20450
PW
5168 pindexIter->nFile = 0;
5169 pindexIter->nDataPos = 0;
5170 pindexIter->nUndoPos = 0;
5171 // Remove various other things
5172 pindexIter->nTx = 0;
5173 pindexIter->nChainTx = 0;
9e851450
JG
5174 pindexIter->nSproutValue = boost::none;
5175 pindexIter->nChainSproutValue = boost::none;
89f20450 5176 pindexIter->nSequenceId = 0;
9e851450 5177 // Make sure it gets written
89f20450 5178 setDirtyBlockIndex.insert(pindexIter);
cef5ad03 5179 if (pindexIter == pindexBestInvalid)
5180 {
3d3f275f 5181 //fprintf(stderr,"Reset invalid block marker if it was pointing to this block\n");
cef5ad03 5182 pindexBestInvalid = NULL;
5183 }
5184
9e851450 5185 // Update indices
89f20450 5186 setBlockIndexCandidates.erase(pindexIter);
9e851450 5187 auto ret = mapBlocksUnlinked.equal_range(pindexIter->pprev);
89f20450
PW
5188 while (ret.first != ret.second) {
5189 if (ret.first->second == pindexIter) {
5190 mapBlocksUnlinked.erase(ret.first++);
5191 } else {
5192 ++ret.first;
5193 }
5194 }
5195 } else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->nChainTx) {
5196 setBlockIndexCandidates.insert(pindexIter);
5197 }
5198 }
8d655683 5199
89f20450 5200 PruneBlockIndexCandidates();
8d655683 5201
89f20450 5202 CheckBlockIndex();
8d655683 5203
89f20450
PW
5204 if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) {
5205 return false;
5206 }
8d655683 5207
89f20450
PW
5208 return true;
5209}
5210
f7f3a96b
PW
5211void UnloadBlockIndex()
5212{
51598b26 5213 LOCK(cs_main);
e17bd583 5214 setBlockIndexCandidates.clear();
4c6d41b8 5215 chainActive.SetTip(NULL);
85eb2cef 5216 pindexBestInvalid = NULL;
51598b26
PW
5217 pindexBestHeader = NULL;
5218 mempool.clear();
5219 mapOrphanTransactions.clear();
5220 mapOrphanTransactionsByPrev.clear();
5221 nSyncStarted = 0;
5222 mapBlocksUnlinked.clear();
5223 vinfoBlockFile.clear();
5224 nLastBlockFile = 0;
5225 nBlockSequenceId = 1;
5226 mapBlockSource.clear();
5227 mapBlocksInFlight.clear();
5228 nQueuedValidatedHeaders = 0;
5229 nPreferredDownload = 0;
5230 setDirtyBlockIndex.clear();
5231 setDirtyFileInfo.clear();
5232 mapNodeState.clear();
ec9b6c33 5233 recentRejects.reset(NULL);
8d655683 5234
51598b26
PW
5235 BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) {
5236 delete entry.second;
5237 }
5238 mapBlockIndex.clear();
f9ec3f0f 5239 fHavePruned = false;
f7f3a96b
PW
5240}
5241
7fea4846 5242bool LoadBlockIndex()
0a61b0df 5243{
d979e6e3 5244 // Load block index from databases
d042777b 5245 KOMODO_LOADINGBLOCKS = 1;
2d1fa42e 5246 if (!fReindex && !LoadBlockIndexDB())
d042777b 5247 {
5248 KOMODO_LOADINGBLOCKS = 0;
0a61b0df 5249 return false;
d042777b 5250 }
25f7ef8c 5251 fprintf(stderr,"finished loading blocks %s\n",ASSETCHAINS_SYMBOL);
38603761
PW
5252 return true;
5253}
2d1fa42e 5254
2d1fa42e 5255
38603761 5256bool InitBlockIndex() {
e6973430 5257 const CChainParams& chainparams = Params();
55a1db4f 5258 LOCK(cs_main);
8d655683 5259
5094a81d
WL
5260 // Initialize global variables that cannot be constructed at startup.
5261 recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
8d655683 5262
38603761 5263 // Check whether we're already initialized
4c6d41b8 5264 if (chainActive.Genesis() != NULL)
38603761 5265 return true;
8d655683 5266
38603761 5267 // Use the provided setting for -txindex in the new database
b2c00e54 5268 fTxIndex = GetBoolArg("-txindex", true);
38603761 5269 pblocktree->WriteFlag("txindex", fTxIndex);
8b78a819
T
5270 // Use the provided setting for -addressindex in the new database
5271 fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX);
5272 pblocktree->WriteFlag("addressindex", fAddressIndex);
5273
5274 // Use the provided setting for -timestampindex in the new database
5275 fTimestampIndex = GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX);
5276 pblocktree->WriteFlag("timestampindex", fTimestampIndex);
5277
5278 fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX);
5279 pblocktree->WriteFlag("spentindex", fSpentIndex);
881a85a2 5280 LogPrintf("Initializing databases...\n");
8d655683 5281
38603761
PW
5282 // Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
5283 if (!fReindex) {
38603761 5284 try {
0e4b3175
MH
5285 CBlock &block = const_cast<CBlock&>(Params().GenesisBlock());
5286 // Start new block file
38603761
PW
5287 unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
5288 CDiskBlockPos blockPos;
5289 CValidationState state;
209377a7 5290 if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime()))
5262fde0 5291 return error("LoadBlockIndex(): FindBlockPos failed");
e6973430 5292 if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
5262fde0 5293 return error("LoadBlockIndex(): writing genesis block to disk failed");
942b33a1 5294 CBlockIndex *pindex = AddToBlockIndex(block);
294925c7 5295 if ( pindex == 0 )
5296 return error("LoadBlockIndex(): couldnt add to block index");
942b33a1 5297 if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
5262fde0 5298 return error("LoadBlockIndex(): genesis block not accepted");
92bb6f2f 5299 if (!ActivateBestChain(state, &block))
5262fde0 5300 return error("LoadBlockIndex(): genesis block cannot be activated");
bf7835c2 5301 // Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
a2069500 5302 return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
27df4123 5303 } catch (const std::runtime_error& e) {
5262fde0 5304 return error("LoadBlockIndex(): failed to initialize block database: %s", e.what());
38603761 5305 }
0a61b0df 5306 }
8d655683 5307
0a61b0df 5308 return true;
5309}
5310
5311
5312
7fea4846 5313bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
1d740055 5314{
4e382177 5315 const CChainParams& chainparams = Params();
ad96e7cc
WL
5316 // Map of disk positions for blocks with unknown parent (only used for reindex)
5317 static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent;
51ed9ec9 5318 int64_t nStart = GetTimeMillis();
8d655683 5319
1d740055 5320 int nLoaded = 0;
421218d3 5321 try {
c9fb27da 5322 // This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
b8add6a4 5323 //CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
0e32bd33 5324 CBufferedFile blkdat(fileIn, 32*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
51ed9ec9 5325 uint64_t nRewind = blkdat.GetPos();
eb0b56b1 5326 while (!blkdat.eof()) {
21eb5ada 5327 boost::this_thread::interruption_point();
8d655683 5328
05d97268
PW
5329 blkdat.SetPos(nRewind);
5330 nRewind++; // start one byte further next time, in case of failure
5331 blkdat.SetLimit(); // remove former limit
7fea4846 5332 unsigned int nSize = 0;
05d97268
PW
5333 try {
5334 // locate a header
0caf2b18 5335 unsigned char buf[MESSAGE_START_SIZE];
0e4b3175 5336 blkdat.FindByte(Params().MessageStart()[0]);
05d97268
PW
5337 nRewind = blkdat.GetPos()+1;
5338 blkdat >> FLATDATA(buf);
0caf2b18 5339 if (memcmp(buf, Params().MessageStart(), MESSAGE_START_SIZE))
05d97268
PW
5340 continue;
5341 // read size
1d740055 5342 blkdat >> nSize;
05d97268
PW
5343 if (nSize < 80 || nSize > MAX_BLOCK_SIZE)
5344 continue;
27df4123 5345 } catch (const std::exception&) {
7fea4846
PW
5346 // no valid block header found; don't complain
5347 break;
5348 }
5349 try {
05d97268 5350 // read block
51ed9ec9 5351 uint64_t nBlockPos = blkdat.GetPos();
ad96e7cc
WL
5352 if (dbp)
5353 dbp->nPos = nBlockPos;
7fea4846 5354 blkdat.SetLimit(nBlockPos + nSize);
16d51941
PW
5355 blkdat.SetPos(nBlockPos);
5356 CBlock block;
5357 blkdat >> block;
ad96e7cc 5358 nRewind = blkdat.GetPos();
8d655683 5359
16d51941
PW
5360 // detect out of order blocks, and store them for later
5361 uint256 hash = block.GetHash();
4e382177 5362 if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) {
ad96e7cc 5363 LogPrint("reindex", "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
8d655683 5364 block.hashPrevBlock.ToString());
ad96e7cc 5365 if (dbp)
16d51941 5366 mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
ad96e7cc
WL
5367 continue;
5368 }
8d655683 5369
16d51941 5370 // process in case the block isn't known yet
8375e221 5371 if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
16d51941 5372 CValidationState state;
7bb789bb 5373 if (ProcessNewBlock(0,0,state, NULL, &block, true, dbp))
16d51941
PW
5374 nLoaded++;
5375 if (state.IsError())
5376 break;
4e382177 5377 } else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) {
50b43fda 5378 LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight);
16d51941 5379 }
8d655683 5380
ad96e7cc
WL
5381 // Recursively process earlier encountered successors of this block
5382 deque<uint256> queue;
5383 queue.push_back(hash);
5384 while (!queue.empty()) {
5385 uint256 head = queue.front();
5386 queue.pop_front();
5387 std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
5388 while (range.first != range.second) {
5389 std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
b8add6a4 5390 if (ReadBlockFromDisk(mapBlockIndex[hash]!=0?mapBlockIndex[hash]->nHeight:0,block, it->second,1))
ad96e7cc
WL
5391 {
5392 LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
8d655683 5393 head.ToString());
ad96e7cc 5394 CValidationState dummy;
7bb789bb 5395 if (ProcessNewBlock(0,0,dummy, NULL, &block, true, &it->second))
ad96e7cc
WL
5396 {
5397 nLoaded++;
5398 queue.push_back(block.GetHash());
5399 }
5400 }
5401 range.first++;
5402 mapBlocksUnknownParent.erase(it);
5403 }
1d740055 5404 }
27df4123 5405 } catch (const std::exception& e) {
7ff9d122 5406 LogPrintf("%s: Deserialize or I/O error - %s\n", __func__, e.what());
1d740055
PW
5407 }
5408 }
27df4123 5409 } catch (const std::runtime_error& e) {
b9b2e3fa 5410 AbortNode(std::string("System error: ") + e.what());
1d740055 5411 }
7fea4846 5412 if (nLoaded > 0)
f48742c2 5413 LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
1d740055
PW
5414 return nLoaded > 0;
5415}
0a61b0df 5416
3fcfbc8a
PW
5417void static CheckBlockIndex()
5418{
4e382177 5419 const Consensus::Params& consensusParams = Params().GetConsensus();
3fcfbc8a
PW
5420 if (!fCheckBlockIndex) {
5421 return;
5422 }
8d655683 5423
3fcfbc8a 5424 LOCK(cs_main);
8d655683 5425
0421c18f 5426 // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain,
5427 // so we have the genesis block in mapBlockIndex but no active chain. (A few of the tests when
5428 // iterating the block tree require that chainActive has been initialized.)
5429 if (chainActive.Height() < 0) {
5430 assert(mapBlockIndex.size() <= 1);
5431 return;
5432 }
8d655683 5433
3fcfbc8a
PW
5434 // Build forward-pointing map of the entire block tree.
5435 std::multimap<CBlockIndex*,CBlockIndex*> forward;
5436 for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) {
e2c2eec4 5437 if ( it->second != 0 )
5438 forward.insert(std::make_pair(it->second->pprev, it->second));
3fcfbc8a 5439 }
d916630e 5440 if ( Params().NetworkIDString() != "regtest" )
5441 assert(forward.size() == mapBlockIndex.size());
8d655683 5442
3fcfbc8a
PW
5443 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(NULL);
5444 CBlockIndex *pindex = rangeGenesis.first->second;
5445 rangeGenesis.first++;
5446 assert(rangeGenesis.first == rangeGenesis.second); // There is only one index entry with parent NULL.
8d655683 5447
3fcfbc8a
PW
5448 // Iterate over the entire block tree, using depth-first search.
5449 // Along the way, remember whether there are blocks on the path from genesis
5450 // block being explored which are the first to have certain properties.
5451 size_t nNodes = 0;
5452 int nHeight = 0;
5453 CBlockIndex* pindexFirstInvalid = NULL; // Oldest ancestor of pindex which is invalid.
5454 CBlockIndex* pindexFirstMissing = NULL; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA.
f9ec3f0f 5455 CBlockIndex* pindexFirstNeverProcessed = NULL; // Oldest ancestor of pindex for which nTx == 0.
3fcfbc8a 5456 CBlockIndex* pindexFirstNotTreeValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not).
ede379f7 5457 CBlockIndex* pindexFirstNotTransactionsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not).
3fcfbc8a
PW
5458 CBlockIndex* pindexFirstNotChainValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not).
5459 CBlockIndex* pindexFirstNotScriptsValid = NULL; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not).
5460 while (pindex != NULL) {
5461 nNodes++;
5462 if (pindexFirstInvalid == NULL && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
5463 if (pindexFirstMissing == NULL && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex;
f9ec3f0f 5464 if (pindexFirstNeverProcessed == NULL && pindex->nTx == 0) pindexFirstNeverProcessed = pindex;
3fcfbc8a 5465 if (pindex->pprev != NULL && pindexFirstNotTreeValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex;
ede379f7 5466 if (pindex->pprev != NULL && pindexFirstNotTransactionsValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) pindexFirstNotTransactionsValid = pindex;
3fcfbc8a
PW
5467 if (pindex->pprev != NULL && pindexFirstNotChainValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) pindexFirstNotChainValid = pindex;
5468 if (pindex->pprev != NULL && pindexFirstNotScriptsValid == NULL && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) pindexFirstNotScriptsValid = pindex;
8d655683 5469
3fcfbc8a
PW
5470 // Begin: actual consistency checks.
5471 if (pindex->pprev == NULL) {
5472 // Genesis block checks.
4e382177 5473 assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match.
3fcfbc8a
PW
5474 assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
5475 }
c1ecee8f 5476 if (pindex->nChainTx == 0) assert(pindex->nSequenceId == 0); // nSequenceId can't be set for blocks that aren't linked
f9ec3f0f 5477 // VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
5478 // HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
5479 if (!fHavePruned) {
5480 // If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
5481 assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
5482 assert(pindexFirstMissing == pindexFirstNeverProcessed);
5483 } else {
5484 // If we have pruned, then we can only say that HAVE_DATA implies nTx > 0
5485 if (pindex->nStatus & BLOCK_HAVE_DATA) assert(pindex->nTx > 0);
5486 }
5487 if (pindex->nStatus & BLOCK_HAVE_UNDO) assert(pindex->nStatus & BLOCK_HAVE_DATA);
5488 assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0)); // This is pruning-independent.
5489 // All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set.
5490 assert((pindexFirstNeverProcessed != NULL) == (pindex->nChainTx == 0)); // nChainTx != 0 is used to signal that all parent blocks have been processed (but may have been pruned).
ede379f7 5491 assert((pindexFirstNotTransactionsValid != NULL) == (pindex->nChainTx == 0));
3fcfbc8a
PW
5492 assert(pindex->nHeight == nHeight); // nHeight must be consistent.
5493 assert(pindex->pprev == NULL || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
5494 assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
5495 assert(pindexFirstNotTreeValid == NULL); // All mapBlockIndex entries must at least be TREE valid
5496 if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assert(pindexFirstNotTreeValid == NULL); // TREE valid implies all parents are TREE valid
5497 if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN) assert(pindexFirstNotChainValid == NULL); // CHAIN valid implies all parents are CHAIN valid
5498 if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS) assert(pindexFirstNotScriptsValid == NULL); // SCRIPTS valid implies all parents are SCRIPTS valid
5499 if (pindexFirstInvalid == NULL) {
5500 // Checks for not-invalid blocks.
5501 assert((pindex->nStatus & BLOCK_FAILED_MASK) == 0); // The failed mask cannot be set for blocks without invalid parents.
5502 }
f9ec3f0f 5503 if (!CBlockIndexWorkComparator()(pindex, chainActive.Tip()) && pindexFirstNeverProcessed == NULL) {
5504 if (pindexFirstInvalid == NULL) {
5505 // If this block sorts at least as good as the current tip and
5506 // is valid and we have all data for its parents, it must be in
5507 // setBlockIndexCandidates. chainActive.Tip() must also be there
5508 // even if some data has been pruned.
5509 if (pindexFirstMissing == NULL || pindex == chainActive.Tip()) {
5510 assert(setBlockIndexCandidates.count(pindex));
5511 }
5512 // If some parent is missing, then it could be that this block was in
5513 // setBlockIndexCandidates but had to be removed because of the missing data.
5514 // In this case it must be in mapBlocksUnlinked -- see test below.
3fcfbc8a 5515 }
f9ec3f0f 5516 } else { // If this block sorts worse than the current tip or some ancestor's block has never been seen, it cannot be in setBlockIndexCandidates.
3fcfbc8a
PW
5517 assert(setBlockIndexCandidates.count(pindex) == 0);
5518 }
5519 // Check whether this block is in mapBlocksUnlinked.
5520 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked = mapBlocksUnlinked.equal_range(pindex->pprev);
5521 bool foundInUnlinked = false;
5522 while (rangeUnlinked.first != rangeUnlinked.second) {
5523 assert(rangeUnlinked.first->first == pindex->pprev);
5524 if (rangeUnlinked.first->second == pindex) {
5525 foundInUnlinked = true;
5526 break;
5527 }
5528 rangeUnlinked.first++;
5529 }
f9ec3f0f 5530 if (pindex->pprev && (pindex->nStatus & BLOCK_HAVE_DATA) && pindexFirstNeverProcessed != NULL && pindexFirstInvalid == NULL) {
5531 // If this block has block data available, some parent was never received, and has no invalid parents, it must be in mapBlocksUnlinked.
5532 assert(foundInUnlinked);
5533 }
5534 if (!(pindex->nStatus & BLOCK_HAVE_DATA)) assert(!foundInUnlinked); // Can't be in mapBlocksUnlinked if we don't HAVE_DATA
5535 if (pindexFirstMissing == NULL) assert(!foundInUnlinked); // We aren't missing data for any parent -- cannot be in mapBlocksUnlinked.
5536 if (pindex->pprev && (pindex->nStatus & BLOCK_HAVE_DATA) && pindexFirstNeverProcessed == NULL && pindexFirstMissing != NULL) {
5537 // We HAVE_DATA for this block, have received data for all parents at some point, but we're currently missing data for some parent.
5538 assert(fHavePruned); // We must have pruned.
5539 // This block may have entered mapBlocksUnlinked if:
5540 // - it has a descendant that at some point had more work than the
5541 // tip, and
5542 // - we tried switching to that descendant but were missing
5543 // data for some intermediate block between chainActive and the
5544 // tip.
5545 // So if this block is itself better than chainActive.Tip() and it wasn't in
5546 // setBlockIndexCandidates, then it must be in mapBlocksUnlinked.
5547 if (!CBlockIndexWorkComparator()(pindex, chainActive.Tip()) && setBlockIndexCandidates.count(pindex) == 0) {
5548 if (pindexFirstInvalid == NULL) {
5549 assert(foundInUnlinked);
5550 }
3fcfbc8a 5551 }
3fcfbc8a
PW
5552 }
5553 // assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow
5554 // End: actual consistency checks.
8d655683 5555
3fcfbc8a
PW
5556 // Try descending into the first subnode.
5557 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range(pindex);
5558 if (range.first != range.second) {
5559 // A subnode was found.
5560 pindex = range.first->second;
5561 nHeight++;
5562 continue;
5563 }
5564 // This is a leaf node.
5565 // Move upwards until we reach a node of which we have not yet visited the last child.
5566 while (pindex) {
5567 // We are going to either move to a parent or a sibling of pindex.
5568 // If pindex was the first with a certain property, unset the corresponding variable.
5569 if (pindex == pindexFirstInvalid) pindexFirstInvalid = NULL;
5570 if (pindex == pindexFirstMissing) pindexFirstMissing = NULL;
f9ec3f0f 5571 if (pindex == pindexFirstNeverProcessed) pindexFirstNeverProcessed = NULL;
3fcfbc8a 5572 if (pindex == pindexFirstNotTreeValid) pindexFirstNotTreeValid = NULL;
ede379f7 5573 if (pindex == pindexFirstNotTransactionsValid) pindexFirstNotTransactionsValid = NULL;
3fcfbc8a
PW
5574 if (pindex == pindexFirstNotChainValid) pindexFirstNotChainValid = NULL;
5575 if (pindex == pindexFirstNotScriptsValid) pindexFirstNotScriptsValid = NULL;
5576 // Find our parent.
5577 CBlockIndex* pindexPar = pindex->pprev;
5578 // Find which child we just visited.
5579 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangePar = forward.equal_range(pindexPar);
5580 while (rangePar.first->second != pindex) {
5581 assert(rangePar.first != rangePar.second); // Our parent must have at least the node we're coming from as child.
5582 rangePar.first++;
5583 }
5584 // Proceed to the next one.
5585 rangePar.first++;
5586 if (rangePar.first != rangePar.second) {
5587 // Move to the sibling.
5588 pindex = rangePar.first->second;
5589 break;
5590 } else {
5591 // Move up further.
5592 pindex = pindexPar;
5593 nHeight--;
5594 continue;
5595 }
5596 }
5597 }
8d655683 5598
3fcfbc8a
PW
5599 // Check that we actually traversed the entire map.
5600 assert(nNodes == forward.size());
5601}
5602
0a61b0df 5603//////////////////////////////////////////////////////////////////////////////
5604//
5605// CAlert
5606//
5607
db954a65 5608std::string GetWarnings(const std::string& strFor)
0a61b0df 5609{
5610 int nPriority = 0;
5611 string strStatusBar;
5612 string strRPC;
8d655683 5613
62e21fb5
WL
5614 if (!CLIENT_VERSION_IS_RELEASE)
5615 strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications");
8d655683 5616
73578933 5617 if (GetBoolArg("-testsafemode", false))
5618 strStatusBar = strRPC = "testsafemode enabled";
8d655683 5619
0a61b0df 5620 // Misc warnings like out of disk space and clock is wrong
5621 if (strMiscWarning != "")
5622 {
5623 nPriority = 1000;
5624 strStatusBar = strMiscWarning;
5625 }
8d655683 5626
b8585384 5627 if (fLargeWorkForkFound)
0a61b0df 5628 {
5629 nPriority = 2000;
f65e7092
MC
5630 strStatusBar = strRPC = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
5631 }
5632 else if (fLargeWorkInvalidChainFound)
0a61b0df 5633 {
5634 nPriority = 2000;
f65e7092 5635 strStatusBar = strRPC = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
0a61b0df 5636 }
8d655683 5637
0a61b0df 5638 // Alerts
0a61b0df 5639 {
f8dcd5ca 5640 LOCK(cs_mapAlerts);
223b6f1b 5641 BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
0a61b0df 5642 {
5643 const CAlert& alert = item.second;
5644 if (alert.AppliesToMe() && alert.nPriority > nPriority)
5645 {
5646 nPriority = alert.nPriority;
5647 strStatusBar = alert.strStatusBar;
a40034f7
JG
5648 if (alert.nPriority >= ALERT_PRIORITY_SAFE_MODE) {
5649 strRPC = alert.strRPCError;
5650 }
0a61b0df 5651 }
5652 }
5653 }
8d655683 5654
0a61b0df 5655 if (strFor == "statusbar")
5656 return strStatusBar;
5657 else if (strFor == "rpc")
5658 return strRPC;
5262fde0 5659 assert(!"GetWarnings(): invalid parameter");
0a61b0df 5660 return "error";
5661}
5662
0a61b0df 5663
5664
5665
5666
5667
5668
5669
5670//////////////////////////////////////////////////////////////////////////////
5671//
5672// Messages
5673//
5674
5675
72b25b0f 5676bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
0a61b0df 5677{
5678 switch (inv.type)
5679 {
8d655683 5680 case MSG_TX:
8deb9822 5681 {
5094a81d 5682 assert(recentRejects);
ec9b6c33
PT
5683 if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip)
5684 {
5685 // If the chain tip has changed previously rejected transactions
5686 // might be now valid, e.g. due to a nLockTime'd tx becoming valid,
5687 // or a double-spend. Reset the rejects filter and give those
5688 // txs a second chance.
5689 hashRecentRejectsChainTip = chainActive.Tip()->GetBlockHash();
5690 recentRejects->reset();
5691 }
8d655683 5692
ec9b6c33 5693 return recentRejects->contains(inv.hash) ||
8d655683 5694 mempool.exists(inv.hash) ||
5695 mapOrphanTransactions.count(inv.hash) ||
5696 pcoinsTip->HaveCoins(inv.hash);
8deb9822 5697 }
8d655683 5698 case MSG_BLOCK:
5699 return mapBlockIndex.count(inv.hash);
0a61b0df 5700 }
5701 // Don't know what it is, just say we already got one
5702 return true;
5703}
5704
c7f039b6
PW
5705void static ProcessGetData(CNode* pfrom)
5706{
5707 std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
8d655683 5708
c7f039b6 5709 vector<CInv> vNotFound;
8d655683 5710
7d38af3c 5711 LOCK(cs_main);
8d655683 5712
c7f039b6
PW
5713 while (it != pfrom->vRecvGetData.end()) {
5714 // Don't bother if send buffer is too full to respond anyway
5715 if (pfrom->nSendSize >= SendBufferSize())
5716 break;
8d655683 5717
c7f039b6
PW
5718 const CInv &inv = *it;
5719 {
b31499ec 5720 boost::this_thread::interruption_point();
c7f039b6 5721 it++;
8d655683 5722
c7f039b6
PW
5723 if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
5724 {
d8b4b496 5725 bool send = false;
145d5be8 5726 BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
c7f039b6
PW
5727 if (mi != mapBlockIndex.end())
5728 {
85da07a5 5729 if (chainActive.Contains(mi->second)) {
2b45345a 5730 send = true;
85da07a5 5731 } else {
f7303f97 5732 static const int nOneMonth = 30 * 24 * 60 * 60;
85da07a5 5733 // To prevent fingerprinting attacks, only send blocks outside of the active
f7303f97
PW
5734 // chain if they are valid, and no more than a month older (both in time, and in
5735 // best equivalent proof of work) than the best header chain we know about.
85da07a5 5736 send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
8d655683 5737 (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) &&
5738 (GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, Params().GetConsensus()) < nOneMonth);
85da07a5 5739 if (!send) {
30c1db1c 5740 LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
85da07a5 5741 }
d8b4b496
AH
5742 }
5743 }
f9ec3f0f 5744 // Pruned nodes may have deleted the block, so check whether
5745 // it's available before trying to send.
5746 if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
d8b4b496
AH
5747 {
5748 // Send block from disk
c7f039b6 5749 CBlock block;
b8add6a4 5750 if (!ReadBlockFromDisk(block, (*mi).second,1))
13931733 5751 {
b34b7b31 5752 assert(!"cannot load block from disk");
13931733 5753 }
5754 else
c7f039b6 5755 {
13931733 5756 if (inv.type == MSG_BLOCK)
c2b0ec2e 5757 {
37782e4e 5758 //uint256 hash; int32_t z;
5759 //hash = block.GetHash();
5760 //for (z=31; z>=0; z--)
5761 // fprintf(stderr,"%02x",((uint8_t *)&hash)[z]);
5762 //fprintf(stderr," send block %d\n",komodo_block2height(&block));
13931733 5763 pfrom->PushMessage("block", block);
c2b0ec2e 5764 }
13931733 5765 else // MSG_FILTERED_BLOCK)
c7f039b6 5766 {
13931733 5767 LOCK(pfrom->cs_filter);
5768 if (pfrom->pfilter)
5769 {
5770 CMerkleBlock merkleBlock(block, *pfrom->pfilter);
5771 pfrom->PushMessage("merkleblock", merkleBlock);
5772 // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
5773 // This avoids hurting performance by pointlessly requiring a round-trip
5774 // Note that there is currently no way for a node to request any single transactions we didn't send here -
5775 // they must either disconnect and retry or request the full block.
5776 // Thus, the protocol spec specified allows for us to provide duplicate txn here,
5777 // however we MUST always provide at least what the remote peer needs
5778 typedef std::pair<unsigned int, uint256> PairType;
5779 BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
c7f039b6
PW
5780 if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
5781 pfrom->PushMessage("tx", block.vtx[pair.first]);
13931733 5782 }
5783 // else
c7f039b6 5784 // no response
13931733 5785 }
c7f039b6 5786 }
b05a89b2 5787 // Trigger the peer node to send a getblocks request for the next batch of inventory
c7f039b6
PW
5788 if (inv.hash == pfrom->hashContinue)
5789 {
5790 // Bypass PushInventory, this must send even if redundant,
5791 // and we want it right after the last block so they don't
5792 // wait for other stuff first.
5793 vector<CInv> vInv;
4c6d41b8 5794 vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
c7f039b6 5795 pfrom->PushMessage("inv", vInv);
4f152496 5796 pfrom->hashContinue.SetNull();
c7f039b6
PW
5797 }
5798 }
5799 }
5800 else if (inv.IsKnownType())
5801 {
5802 // Send stream from relay memory
5803 bool pushed = false;
5804 {
5805 LOCK(cs_mapRelay);
5806 map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
5807 if (mi != mapRelay.end()) {
5808 pfrom->PushMessage(inv.GetCommand(), (*mi).second);
5809 pushed = true;
5810 }
5811 }
5812 if (!pushed && inv.type == MSG_TX) {
319b1160
GA
5813 CTransaction tx;
5814 if (mempool.lookup(inv.hash, tx)) {
c7f039b6
PW
5815 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
5816 ss.reserve(1000);
5817 ss << tx;
5818 pfrom->PushMessage("tx", ss);
5819 pushed = true;
5820 }
5821 }
5822 if (!pushed) {
5823 vNotFound.push_back(inv);
5824 }
5825 }
8d655683 5826
c7f039b6 5827 // Track requests for our stuff.
26c16d9d 5828 GetMainSignals().Inventory(inv.hash);
8d655683 5829
75ef87dd
PS
5830 if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
5831 break;
c7f039b6
PW
5832 }
5833 }
8d655683 5834
c7f039b6 5835 pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it);
8d655683 5836
c7f039b6
PW
5837 if (!vNotFound.empty()) {
5838 // Let the peer know that we didn't find what it asked for, so it doesn't
5839 // have to wait around forever. Currently only SPV clients actually care
5840 // about this message: it's needed when they are recursively walking the
5841 // dependencies of relevant unconfirmed transactions. SPV clients want to
5842 // do that because they want to know about (and store and rebroadcast and
5843 // risk analyze) the dependencies of transactions relevant to them, without
5844 // having to download the entire memory pool.
5845 pfrom->PushMessage("notfound", vNotFound);
5846 }
5847}
5848
9f4da19b 5849bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
0a61b0df 5850{
e8e8904d 5851 const CChainParams& chainparams = Params();
28d4cff0 5852 LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
37782e4e 5853 //fprintf(stderr, "recv: %s peer=%d\n", SanitizeString(strCommand).c_str(), (int32_t)pfrom->GetId());
0a61b0df 5854 if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
5855 {
881a85a2 5856 LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
0a61b0df 5857 return true;
5858 }
8d655683 5859
5860
5861
5862
0a61b0df 5863 if (strCommand == "version")
5864 {
5865 // Each connection can only send one version message
5866 if (pfrom->nVersion != 0)
806704c2 5867 {
358ce266 5868 pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
b2864d2f 5869 Misbehaving(pfrom->GetId(), 1);
0a61b0df 5870 return false;
806704c2 5871 }
8d655683 5872
51ed9ec9 5873 int64_t nTime;
0a61b0df 5874 CAddress addrMe;
5875 CAddress addrFrom;
51ed9ec9 5876 uint64_t nNonce = 1;
0a61b0df 5877 vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
1ce41892 5878 if (pfrom->nVersion < MIN_PEER_PROTO_VERSION)
18c0fa97 5879 {
1ce41892 5880 // disconnect from peers older than this proto version
2e36866f 5881 LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
358ce266
GA
5882 pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
5883 strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION));
18c0fa97
PW
5884 pfrom->fDisconnect = true;
5885 return false;
5886 }
8d655683 5887
72b21929
S
5888 // When Overwinter is active, reject incoming connections from non-Overwinter nodes
5889 const Consensus::Params& params = Params().GetConsensus();
5890 if (NetworkUpgradeActive(GetHeight(), params, Consensus::UPGRADE_OVERWINTER)
5891 && pfrom->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion)
5892 {
5893 LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
5894 pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
8d655683 5895 strprintf("Version must be %d or greater",
5896 params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
72b21929
S
5897 pfrom->fDisconnect = true;
5898 return false;
5899 }
8d655683 5900
0a61b0df 5901 if (pfrom->nVersion == 10300)
5902 pfrom->nVersion = 300;
18c0fa97 5903 if (!vRecv.empty())
0a61b0df 5904 vRecv >> addrFrom >> nNonce;
a946aa8d 5905 if (!vRecv.empty()) {
216e9a44 5906 vRecv >> LIMITED_STRING(pfrom->strSubVer, 256);
a946aa8d
MH
5907 pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
5908 }
18c0fa97 5909 if (!vRecv.empty())
0a61b0df 5910 vRecv >> pfrom->nStartingHeight;
4c8fc1a5
MC
5911 if (!vRecv.empty())
5912 vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message
5913 else
5914 pfrom->fRelayTxes = true;
8d655683 5915
0a61b0df 5916 // Disconnect if we connected to ourself
5917 if (nNonce == nLocalHostNonce && nNonce > 1)
5918 {
7d9d134b 5919 LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString());
0a61b0df 5920 pfrom->fDisconnect = true;
5921 return true;
5922 }
8d655683 5923
845c86d1
GM
5924 pfrom->addrLocal = addrMe;
5925 if (pfrom->fInbound && addrMe.IsRoutable())
5926 {
5927 SeenLocal(addrMe);
5928 }
8d655683 5929
cbc920d4
GA
5930 // Be shy and don't send version until we hear
5931 if (pfrom->fInbound)
5932 pfrom->PushVersion();
8d655683 5933
0a61b0df 5934 pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
8d655683 5935
b4ee0bdd
PW
5936 // Potentially mark this peer as a preferred download peer.
5937 UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
8d655683 5938
0a61b0df 5939 // Change version
18c0fa97 5940 pfrom->PushMessage("verack");
41b052ad 5941 pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
8d655683 5942
c891967b 5943 if (!pfrom->fInbound)
5944 {
5945 // Advertise our address
53a08815 5946 if (fListen && !IsInitialBlockDownload())
c891967b 5947 {
39857190
PW
5948 CAddress addr = GetLocalAddress(&pfrom->addr);
5949 if (addr.IsRoutable())
845c86d1 5950 {
eb5f63fe 5951 LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
845c86d1
GM
5952 pfrom->PushAddress(addr);
5953 } else if (IsPeerAddrLocalGood(pfrom)) {
5954 addr.SetIP(pfrom->addrLocal);
eb5f63fe 5955 LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
39857190 5956 pfrom->PushAddress(addr);
845c86d1 5957 }
c891967b 5958 }
8d655683 5959
c891967b 5960 // Get recent addresses
478b01d9 5961 if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000)
c891967b 5962 {
5963 pfrom->PushMessage("getaddr");
5964 pfrom->fGetAddr = true;
5965 }
5fee401f
PW
5966 addrman.Good(pfrom->addr);
5967 } else {
5968 if (((CNetAddr)pfrom->addr) == (CNetAddr)addrFrom)
5969 {
5970 addrman.Add(addrFrom, addrFrom);
5971 addrman.Good(addrFrom);
5972 }
c891967b 5973 }
8d655683 5974
0a61b0df 5975 // Relay alerts
f8dcd5ca
PW
5976 {
5977 LOCK(cs_mapAlerts);
223b6f1b 5978 BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
8d655683 5979 item.second.RelayTo(pfrom);
f8dcd5ca 5980 }
8d655683 5981
0a61b0df 5982 pfrom->fSuccessfullyConnected = true;
8d655683 5983
70b9d36a
JG
5984 string remoteAddr;
5985 if (fLogIPs)
5986 remoteAddr = ", peeraddr=" + pfrom->addr.ToString();
8d655683 5987
70b9d36a
JG
5988 LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
5989 pfrom->cleanSubVer, pfrom->nVersion,
5990 pfrom->nStartingHeight, addrMe.ToString(), pfrom->id,
5991 remoteAddr);
8d655683 5992
26a6bae7
PJ
5993 int64_t nTimeOffset = nTime - GetTime();
5994 pfrom->nTimeOffset = nTimeOffset;
5995 AddTimeData(pfrom->addr, nTimeOffset);
0a61b0df 5996 }
8d655683 5997
5998
0a61b0df 5999 else if (pfrom->nVersion == 0)
6000 {
6001 // Must have a version message before anything else
b2864d2f 6002 Misbehaving(pfrom->GetId(), 1);
0a61b0df 6003 return false;
6004 }
8d655683 6005
6006
0a61b0df 6007 else if (strCommand == "verack")
6008 {
607dbfde 6009 pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
8d655683 6010
9c273790
PW
6011 // Mark this node as currently connected, so we update its timestamp later.
6012 if (pfrom->fNetworkNode) {
6013 LOCK(cs_main);
6014 State(pfrom->GetId())->fCurrentlyConnected = true;
6015 }
0a61b0df 6016 }
8d655683 6017
6018
72b21929
S
6019 // Disconnect existing peer connection when:
6020 // 1. The version message has been received
6021 // 2. Overwinter is active
6022 // 3. Peer version is pre-Overwinter
6023 else if (NetworkUpgradeActive(GetHeight(), chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER)
8d655683 6024 && (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion))
72b21929
S
6025 {
6026 LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
6027 pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
8d655683 6028 strprintf("Version must be %d or greater",
6029 chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
72b21929
S
6030 pfrom->fDisconnect = true;
6031 return false;
6032 }
8d655683 6033
6034
0a61b0df 6035 else if (strCommand == "addr")
6036 {
6037 vector<CAddress> vAddr;
6038 vRecv >> vAddr;
8d655683 6039
c891967b 6040 // Don't want addr from older versions unless seeding
8b09cd3a 6041 if (pfrom->nVersion < CADDR_TIME_VERSION && addrman.size() > 1000)
0a61b0df 6042 return true;
6043 if (vAddr.size() > 1000)
806704c2 6044 {
b2864d2f 6045 Misbehaving(pfrom->GetId(), 20);
783b182c 6046 return error("message addr size() = %u", vAddr.size());
806704c2 6047 }
8d655683 6048
0a61b0df 6049 // Store the new addresses
090e5b40 6050 vector<CAddress> vAddrOk;
51ed9ec9
BD
6051 int64_t nNow = GetAdjustedTime();
6052 int64_t nSince = nNow - 10 * 60;
223b6f1b 6053 BOOST_FOREACH(CAddress& addr, vAddr)
0a61b0df 6054 {
b31499ec 6055 boost::this_thread::interruption_point();
8d655683 6056
c891967b 6057 if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
6058 addr.nTime = nNow - 5 * 24 * 60 * 60;
0a61b0df 6059 pfrom->AddAddressKnown(addr);
090e5b40 6060 bool fReachable = IsReachable(addr);
c891967b 6061 if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
0a61b0df 6062 {
6063 // Relay to a limited number of other nodes
0a61b0df 6064 {
f8dcd5ca 6065 LOCK(cs_vNodes);
5cbf7532 6066 // Use deterministic randomness to send to the same nodes for 24 hours
d81cff32 6067 // at a time so the addrKnowns of the chosen nodes prevent repeats
0a61b0df 6068 static uint256 hashSalt;
4f152496 6069 if (hashSalt.IsNull())
f718aedd 6070 hashSalt = GetRandHash();
51ed9ec9 6071 uint64_t hashAddr = addr.GetHash();
734f85c4 6072 uint256 hashRand = ArithToUint256(UintToArith256(hashSalt) ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60)));
5cbf7532 6073 hashRand = Hash(BEGIN(hashRand), END(hashRand));
0a61b0df 6074 multimap<uint256, CNode*> mapMix;
223b6f1b 6075 BOOST_FOREACH(CNode* pnode, vNodes)
5cbf7532 6076 {
8b09cd3a 6077 if (pnode->nVersion < CADDR_TIME_VERSION)
c891967b 6078 continue;
5cbf7532 6079 unsigned int nPointer;
6080 memcpy(&nPointer, &pnode, sizeof(nPointer));
734f85c4 6081 uint256 hashKey = ArithToUint256(UintToArith256(hashRand) ^ nPointer);
5cbf7532 6082 hashKey = Hash(BEGIN(hashKey), END(hashKey));
6083 mapMix.insert(make_pair(hashKey, pnode));
6084 }
090e5b40 6085 int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
0a61b0df 6086 for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
6087 ((*mi).second)->PushAddress(addr);
6088 }
6089 }
090e5b40
PW
6090 // Do not store addresses outside our network
6091 if (fReachable)
6092 vAddrOk.push_back(addr);
0a61b0df 6093 }
090e5b40 6094 addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60);
0a61b0df 6095 if (vAddr.size() < 1000)
6096 pfrom->fGetAddr = false;
478b01d9
PW
6097 if (pfrom->fOneShot)
6098 pfrom->fDisconnect = true;
0a61b0df 6099 }
8d655683 6100
6101
0a61b0df 6102 else if (strCommand == "inv")
6103 {
6104 vector<CInv> vInv;
6105 vRecv >> vInv;
05a85b2b 6106 if (vInv.size() > MAX_INV_SZ)
806704c2 6107 {
b2864d2f 6108 Misbehaving(pfrom->GetId(), 20);
783b182c 6109 return error("message inv size() = %u", vInv.size());
806704c2 6110 }
8d655683 6111
7d38af3c 6112 LOCK(cs_main);
8d655683 6113
341735eb 6114 std::vector<CInv> vToFetch;
8d655683 6115
c376ac35 6116 for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
0a61b0df 6117 {
0aa89c08 6118 const CInv &inv = vInv[nInv];
8d655683 6119
b31499ec 6120 boost::this_thread::interruption_point();
0a61b0df 6121 pfrom->AddInventoryKnown(inv);
8d655683 6122
ae8bfd12 6123 bool fAlreadyHave = AlreadyHave(inv);
2e36866f 6124 LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
8d655683 6125
341735eb
PW
6126 if (!fAlreadyHave && !fImporting && !fReindex && inv.type != MSG_BLOCK)
6127 pfrom->AskFor(inv);
8d655683 6128
341735eb 6129 if (inv.type == MSG_BLOCK) {
aa815647 6130 UpdateBlockAvailability(pfrom->GetId(), inv.hash);
341735eb 6131 if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
7e6d23b1 6132 // First request the headers preceding the announced block. In the normal fully-synced
341735eb
PW
6133 // case where a new block is announced that succeeds the current tip (no reorganization),
6134 // there are no such headers.
6135 // Secondly, and only when we are close to being synced, we request the announced block directly,
6136 // to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
6137 // time the block arrives, the header chain leading up to it is already validated. Not
6138 // doing this will result in the received block being rejected as an orphan in case it is
6139 // not a direct successor.
6140 pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash);
c9077043 6141 CNodeState *nodestate = State(pfrom->GetId());
e8e8904d 6142 if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 &&
c9077043 6143 nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
341735eb
PW
6144 vToFetch.push_back(inv);
6145 // Mark block as in flight already, even though the actual "getdata" message only goes out
6146 // later (within the same cs_main lock, though).
82737933 6147 MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
341735eb 6148 }
4c933229 6149 LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
341735eb
PW
6150 }
6151 }
8d655683 6152
0a61b0df 6153 // Track requests for our stuff
26c16d9d 6154 GetMainSignals().Inventory(inv.hash);
8d655683 6155
540ac451
JG
6156 if (pfrom->nSendSize > (SendBufferSize() * 2)) {
6157 Misbehaving(pfrom->GetId(), 50);
6158 return error("send buffer size() = %u", pfrom->nSendSize);
6159 }
0a61b0df 6160 }
8d655683 6161
341735eb
PW
6162 if (!vToFetch.empty())
6163 pfrom->PushMessage("getdata", vToFetch);
0a61b0df 6164 }
8d655683 6165
6166
0a61b0df 6167 else if (strCommand == "getdata")
6168 {
6169 vector<CInv> vInv;
6170 vRecv >> vInv;
05a85b2b 6171 if (vInv.size() > MAX_INV_SZ)
806704c2 6172 {
b2864d2f 6173 Misbehaving(pfrom->GetId(), 20);
783b182c 6174 return error("message getdata size() = %u", vInv.size());
806704c2 6175 }
8d655683 6176
3b570559 6177 if (fDebug || (vInv.size() != 1))
2e36866f 6178 LogPrint("net", "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id);
8d655683 6179
3b570559 6180 if ((fDebug && vInv.size() > 0) || (vInv.size() == 1))
2e36866f 6181 LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id);
8d655683 6182
c7f039b6
PW
6183 pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
6184 ProcessGetData(pfrom);
0a61b0df 6185 }
8d655683 6186
6187
0a61b0df 6188 else if (strCommand == "getblocks")
6189 {
6190 CBlockLocator locator;
6191 uint256 hashStop;
6192 vRecv >> locator >> hashStop;
8d655683 6193
7d38af3c 6194 LOCK(cs_main);
8d655683 6195
f03304a9 6196 // Find the last block the caller has in the main chain
6db83db3 6197 CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator);
8d655683 6198
0a61b0df 6199 // Send the rest of the chain
6200 if (pindex)
4c6d41b8 6201 pindex = chainActive.Next(pindex);
9d6cd04b 6202 int nLimit = 500;
4f152496 6203 LogPrint("net", "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->id);
4c6d41b8 6204 for (; pindex; pindex = chainActive.Next(pindex))
0a61b0df 6205 {
6206 if (pindex->GetBlockHash() == hashStop)
6207 {
7d9d134b 6208 LogPrint("net", " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
0a61b0df 6209 break;
6210 }
6211 pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
9d6cd04b 6212 if (--nLimit <= 0)
0a61b0df 6213 {
b05a89b2
LD
6214 // When this block is requested, we'll send an inv that'll
6215 // trigger the peer to getblocks the next batch of inventory.
7d9d134b 6216 LogPrint("net", " getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
0a61b0df 6217 pfrom->hashContinue = pindex->GetBlockHash();
6218 break;
6219 }
6220 }
6221 }
8d655683 6222
6223
f03304a9 6224 else if (strCommand == "getheaders")
6225 {
6226 CBlockLocator locator;
6227 uint256 hashStop;
6228 vRecv >> locator >> hashStop;
8d655683 6229
7d38af3c 6230 LOCK(cs_main);
8d655683 6231
b4bbad18
SD
6232 if (IsInitialBlockDownload())
6233 return true;
8d655683 6234
f03304a9 6235 CBlockIndex* pindex = NULL;
6236 if (locator.IsNull())
6237 {
6238 // If locator is null, return the hashStop block
145d5be8 6239 BlockMap::iterator mi = mapBlockIndex.find(hashStop);
f03304a9 6240 if (mi == mapBlockIndex.end())
6241 return true;
6242 pindex = (*mi).second;
6243 }
6244 else
6245 {
6246 // Find the last block the caller has in the main chain
6db83db3 6247 pindex = FindForkInGlobalIndex(chainActive, locator);
f03304a9 6248 if (pindex)
4c6d41b8 6249 pindex = chainActive.Next(pindex);
f03304a9 6250 }
8d655683 6251
e754cf41 6252 // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
f03304a9 6253 vector<CBlock> vHeaders;
341735eb 6254 int nLimit = MAX_HEADERS_RESULTS;
4c933229 6255 LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->id);
f8a07170 6256 //if ( pfrom->lasthdrsreq >= chainActive.Height()-MAX_HEADERS_RESULTS || pfrom->lasthdrsreq != (int32_t)(pindex ? pindex->nHeight : -1) )// no need to ever suppress this
f03304a9 6257 {
164bbe6c 6258 pfrom->lasthdrsreq = (int32_t)(pindex ? pindex->nHeight : -1);
336a60cf 6259 for (; pindex; pindex = chainActive.Next(pindex))
6260 {
6261 vHeaders.push_back(pindex->GetBlockHeader());
6262 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
6263 break;
6264 }
6265 pfrom->PushMessage("headers", vHeaders);
8dcf7f94 6266 }
4d068367 6267 /*else if ( IS_KOMODO_NOTARY != 0 )
bd901dd7 6268 {
6269 static uint32_t counter;
6270 if ( counter++ < 3 )
6271 fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->nHeight : -1),pfrom->lasthdrsreq);
f8a07170 6272 }*/
f03304a9 6273 }
8d655683 6274
6275
0a61b0df 6276 else if (strCommand == "tx")
6277 {
6278 vector<uint256> vWorkQueue;
7a15109c 6279 vector<uint256> vEraseQueue;
0a61b0df 6280 CTransaction tx;
6281 vRecv >> tx;
8d655683 6282
805344dc 6283 CInv inv(MSG_TX, tx.GetHash());
0a61b0df 6284 pfrom->AddInventoryKnown(inv);
8d655683 6285
7d38af3c 6286 LOCK(cs_main);
8d655683 6287
0a61b0df 6288 bool fMissingInputs = false;
ef3988ca 6289 CValidationState state;
8d655683 6290
e2190f80 6291 pfrom->setAskFor.erase(inv.hash);
604ee2aa 6292 mapAlreadyAskedFor.erase(inv);
8d655683 6293
60aed954 6294 if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
0a61b0df 6295 {
a0fa20a1 6296 mempool.check(pcoinsTip);
d38da59b 6297 RelayTransaction(tx);
0a61b0df 6298 vWorkQueue.push_back(inv.hash);
8d655683 6299
5262fde0 6300 LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s: accepted %s (poolsz %u)\n",
8d655683 6301 pfrom->id, pfrom->cleanSubVer,
6302 tx.GetHash().ToString(),
6303 mempool.mapTx.size());
6304
0a61b0df 6305 // Recursively process any orphan transactions that depended on this one
c74332c6 6306 set<NodeId> setMisbehaving;
c376ac35 6307 for (unsigned int i = 0; i < vWorkQueue.size(); i++)
0a61b0df 6308 {
89d91f6a
WL
6309 map<uint256, set<uint256> >::iterator itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue[i]);
6310 if (itByPrev == mapOrphanTransactionsByPrev.end())
6311 continue;
6312 for (set<uint256>::iterator mi = itByPrev->second.begin();
6313 mi != itByPrev->second.end();
0a61b0df 6314 ++mi)
6315 {
159bc481 6316 const uint256& orphanHash = *mi;
c74332c6
GA
6317 const CTransaction& orphanTx = mapOrphanTransactions[orphanHash].tx;
6318 NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer;
7a15109c 6319 bool fMissingInputs2 = false;
159bc481
GA
6320 // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
6321 // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
6322 // anyone relaying LegitTxX banned)
8c4e4313 6323 CValidationState stateDummy;
8d655683 6324
6325
c74332c6
GA
6326 if (setMisbehaving.count(fromPeer))
6327 continue;
319b1160 6328 if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
0a61b0df 6329 {
7d9d134b 6330 LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
d38da59b 6331 RelayTransaction(orphanTx);
159bc481 6332 vWorkQueue.push_back(orphanHash);
37b4e425 6333 vEraseQueue.push_back(orphanHash);
7a15109c
GA
6334 }
6335 else if (!fMissingInputs2)
6336 {
c74332c6
GA
6337 int nDos = 0;
6338 if (stateDummy.IsInvalid(nDos) && nDos > 0)
6339 {
6340 // Punish peer that gave us an invalid orphan tx
6341 Misbehaving(fromPeer, nDos);
6342 setMisbehaving.insert(fromPeer);
6343 LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString());
6344 }
37b4e425
AM
6345 // Has inputs but not accepted to mempool
6346 // Probably non-standard or insufficient fee/priority
7d9d134b 6347 LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
37b4e425 6348 vEraseQueue.push_back(orphanHash);
5094a81d 6349 assert(recentRejects);
ec9b6c33 6350 recentRejects->insert(orphanHash);
0a61b0df 6351 }
a0fa20a1 6352 mempool.check(pcoinsTip);
0a61b0df 6353 }
6354 }
8d655683 6355
7a15109c 6356 BOOST_FOREACH(uint256 hash, vEraseQueue)
8d655683 6357 EraseOrphanTx(hash);
0a61b0df 6358 }
b7e4abd6 6359 // TODO: currently, prohibit joinsplits from entering mapOrphans
8675d94b 6360 else if (fMissingInputs && tx.vjoinsplit.size() == 0)
0a61b0df 6361 {
c74332c6 6362 AddOrphanTx(tx, pfrom->GetId());
8d655683 6363
142e6041 6364 // DoS prevention: do not allow mapOrphanTransactions to grow unbounded
aa3c697e
GA
6365 unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
6366 unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx);
142e6041 6367 if (nEvicted > 0)
881a85a2 6368 LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
ec9b6c33 6369 } else {
36f14bf2 6370 assert(recentRejects);
805344dc 6371 recentRejects->insert(tx.GetHash());
8d655683 6372
ec9b6c33
PT
6373 if (pfrom->fWhitelisted) {
6374 // Always relay transactions received from whitelisted peers, even
60aed954
PW
6375 // if they were already in the mempool or rejected from it due
6376 // to policy, allowing the node to function as a gateway for
6377 // nodes hidden behind it.
ec9b6c33 6378 //
60aed954
PW
6379 // Never relay transactions that we would assign a non-zero DoS
6380 // score for, as we expect peers to do the same with us in that
6381 // case.
6382 int nDoS = 0;
6383 if (!state.IsInvalid(nDoS) || nDoS == 0) {
6384 LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id);
6385 RelayTransaction(tx);
6386 } else {
e63d14fd 6387 LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s (code %d))\n",
8d655683 6388 tx.GetHash().ToString(), pfrom->id, state.GetRejectReason(), state.GetRejectCode());
60aed954 6389 }
ec9b6c33 6390 }
0a61b0df 6391 }
fbed9c9d 6392 int nDoS = 0;
5ea66c54 6393 if (state.IsInvalid(nDoS))
2b45345a 6394 {
805344dc 6395 LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(),
8d655683 6396 pfrom->id, pfrom->cleanSubVer,
6397 state.GetRejectReason());
358ce266 6398 pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
307f7d48 6399 state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
5ea66c54 6400 if (nDoS > 0)
b2864d2f 6401 Misbehaving(pfrom->GetId(), nDoS);
358ce266 6402 }
0a61b0df 6403 }
8d655683 6404
6405
341735eb
PW
6406 else if (strCommand == "headers" && !fImporting && !fReindex) // Ignore headers received while importing
6407 {
6408 std::vector<CBlockHeader> headers;
8d655683 6409
341735eb
PW
6410 // Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
6411 unsigned int nCount = ReadCompactSize(vRecv);
6412 if (nCount > MAX_HEADERS_RESULTS) {
6413 Misbehaving(pfrom->GetId(), 20);
6414 return error("headers message size = %u", nCount);
6415 }
6416 headers.resize(nCount);
6417 for (unsigned int n = 0; n < nCount; n++) {
6418 vRecv >> headers[n];
6419 ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
6420 }
8d655683 6421
341735eb 6422 LOCK(cs_main);
8d655683 6423
341735eb
PW
6424 if (nCount == 0) {
6425 // Nothing interesting. Stop asking this peers for more headers.
6426 return true;
6427 }
8d655683 6428
341735eb
PW
6429 CBlockIndex *pindexLast = NULL;
6430 BOOST_FOREACH(const CBlockHeader& header, headers) {
6431 CValidationState state;
6432 if (pindexLast != NULL && header.hashPrevBlock != pindexLast->GetBlockHash()) {
6433 Misbehaving(pfrom->GetId(), 20);
6434 return error("non-continuous headers sequence");
6435 }
531b9293 6436 int32_t futureblock;
531b9293 6437 if (!AcceptBlockHeader(&futureblock,header, state, &pindexLast)) {
341735eb 6438 int nDoS;
753b841f 6439 if (state.IsInvalid(nDoS) && futureblock == 0)
6477ad07 6440 {
531b9293 6441 if (nDoS > 0 && futureblock == 0)
0d2cefb0 6442 Misbehaving(pfrom->GetId(), nDoS/nDoS);
341735eb
PW
6443 return error("invalid header received");
6444 }
6445 }
6446 }
8d655683 6447
341735eb
PW
6448 if (pindexLast)
6449 UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
8d655683 6450
341735eb
PW
6451 if (nCount == MAX_HEADERS_RESULTS && pindexLast) {
6452 // Headers message had its maximum size; the peer may have more headers.
6453 // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
6454 // from there instead.
8ab425f8 6455 if ( pfrom->sendhdrsreq >= chainActive.Height()-MAX_HEADERS_RESULTS || pindexLast->nHeight != pfrom->sendhdrsreq )
6456 {
6457 pfrom->sendhdrsreq = (int32_t)pindexLast->nHeight;
6458 LogPrint("net", "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight);
6459 pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256());
6460 }
341735eb 6461 }
8d655683 6462
3fcfbc8a 6463 CheckBlockIndex();
341735eb 6464 }
8d655683 6465
7fea4846 6466 else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
0a61b0df 6467 {
f03304a9 6468 CBlock block;
6469 vRecv >> block;
8d655683 6470
f03304a9 6471 CInv inv(MSG_BLOCK, block.GetHash());
341735eb 6472 LogPrint("net", "received block %s peer=%d\n", inv.hash.ToString(), pfrom->id);
8d655683 6473
341735eb 6474 pfrom->AddInventoryKnown(inv);
8d655683 6475
ef3988ca 6476 CValidationState state;
93b606ae
SD
6477 // Process all blocks from whitelisted peers, even if not requested,
6478 // unless we're still syncing with the network.
6479 // Such an unrequested block may still be processed, subject to the
6480 // conditions in AcceptBlock().
6481 bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
7bb789bb 6482 ProcessNewBlock(0,0,state, pfrom, &block, forceProcessing, NULL);
40f5cb87
PW
6483 int nDoS;
6484 if (state.IsInvalid(nDoS)) {
6485 pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
307f7d48 6486 state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
40f5cb87
PW
6487 if (nDoS > 0) {
6488 LOCK(cs_main);
6489 Misbehaving(pfrom->GetId(), nDoS);
6490 }
6491 }
8d655683 6492
0a61b0df 6493 }
8d655683 6494
6495
dca799e1
IP
6496 // This asymmetric behavior for inbound and outbound connections was introduced
6497 // to prevent a fingerprinting attack: an attacker can send specific fake addresses
b05a89b2
LD
6498 // to users' AddrMan and later request them by sending getaddr messages.
6499 // Making nodes which are behind NAT and can only make outgoing connections ignore
6500 // the getaddr message mitigates the attack.
dca799e1 6501 else if ((strCommand == "getaddr") && (pfrom->fInbound))
0a61b0df 6502 {
a514cb29
GM
6503 // Only send one GetAddr response per connection to reduce resource waste
6504 // and discourage addr stamping of INV announcements.
6505 if (pfrom->fSentAddr) {
6506 LogPrint("net", "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id);
6507 return true;
6508 }
6509 pfrom->fSentAddr = true;
8d655683 6510
0a61b0df 6511 pfrom->vAddrToSend.clear();
5fee401f
PW
6512 vector<CAddress> vAddr = addrman.GetAddr();
6513 BOOST_FOREACH(const CAddress &addr, vAddr)
8d655683 6514 pfrom->PushAddress(addr);
0a61b0df 6515 }
8d655683 6516
6517
05a85b2b
JG
6518 else if (strCommand == "mempool")
6519 {
319b1160 6520 LOCK2(cs_main, pfrom->cs_filter);
8d655683 6521
05a85b2b
JG
6522 std::vector<uint256> vtxid;
6523 mempool.queryHashes(vtxid);
6524 vector<CInv> vInv;
c51694eb
MC
6525 BOOST_FOREACH(uint256& hash, vtxid) {
6526 CInv inv(MSG_TX, hash);
319b1160
GA
6527 CTransaction tx;
6528 bool fInMemPool = mempool.lookup(hash, tx);
6529 if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
d38da59b 6530 if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx)) ||
8d655683 6531 (!pfrom->pfilter))
c51694eb 6532 vInv.push_back(inv);
1f3d3647
GA
6533 if (vInv.size() == MAX_INV_SZ) {
6534 pfrom->PushMessage("inv", vInv);
6535 vInv.clear();
6536 }
05a85b2b
JG
6537 }
6538 if (vInv.size() > 0)
6539 pfrom->PushMessage("inv", vInv);
6540 }
8d655683 6541
6542
0a61b0df 6543 else if (strCommand == "ping")
6544 {
93e447b6
JG
6545 if (pfrom->nVersion > BIP0031_VERSION)
6546 {
51ed9ec9 6547 uint64_t nonce = 0;
93e447b6
JG
6548 vRecv >> nonce;
6549 // Echo the message back with the nonce. This allows for two useful features:
6550 //
6551 // 1) A remote node can quickly check if the connection is operational
6552 // 2) Remote nodes can measure the latency of the network thread. If this node
6553 // is overloaded it won't respond to pings quickly and the remote node can
6554 // avoid sending us more work, like chain download requests.
6555 //
6556 // The nonce stops the remote getting confused between different pings: without
6557 // it, if the remote node sends a ping once per second and this node takes 5
6558 // seconds to respond to each, the 5th ping the remote sends would appear to
6559 // return very quickly.
6560 pfrom->PushMessage("pong", nonce);
6561 }
0a61b0df 6562 }
8d655683 6563
6564
971bb3e9
JL
6565 else if (strCommand == "pong")
6566 {
9f4da19b 6567 int64_t pingUsecEnd = nTimeReceived;
51ed9ec9 6568 uint64_t nonce = 0;
971bb3e9
JL
6569 size_t nAvail = vRecv.in_avail();
6570 bool bPingFinished = false;
6571 std::string sProblem;
8d655683 6572
971bb3e9
JL
6573 if (nAvail >= sizeof(nonce)) {
6574 vRecv >> nonce;
8d655683 6575
971bb3e9
JL
6576 // Only process pong message if there is an outstanding ping (old ping without nonce should never pong)
6577 if (pfrom->nPingNonceSent != 0) {
6578 if (nonce == pfrom->nPingNonceSent) {
6579 // Matching pong received, this ping is no longer outstanding
6580 bPingFinished = true;
51ed9ec9 6581 int64_t pingUsecTime = pingUsecEnd - pfrom->nPingUsecStart;
971bb3e9
JL
6582 if (pingUsecTime > 0) {
6583 // Successful ping time measurement, replace previous
6584 pfrom->nPingUsecTime = pingUsecTime;
e279e5f9 6585 pfrom->nMinPingUsecTime = std::min(pfrom->nMinPingUsecTime, pingUsecTime);
971bb3e9
JL
6586 } else {
6587 // This should never happen
6588 sProblem = "Timing mishap";
6589 }
6590 } else {
6591 // Nonce mismatches are normal when pings are overlapping
6592 sProblem = "Nonce mismatch";
6593 if (nonce == 0) {
7e6d23b1 6594 // This is most likely a bug in another implementation somewhere; cancel this ping
971bb3e9
JL
6595 bPingFinished = true;
6596 sProblem = "Nonce zero";
6597 }
6598 }
6599 } else {
6600 sProblem = "Unsolicited pong without ping";
6601 }
6602 } else {
7e6d23b1 6603 // This is most likely a bug in another implementation somewhere; cancel this ping
971bb3e9
JL
6604 bPingFinished = true;
6605 sProblem = "Short payload";
6606 }
8d655683 6607
971bb3e9 6608 if (!(sProblem.empty())) {
2e36866f 6609 LogPrint("net", "pong peer=%d %s: %s, %x expected, %x received, %u bytes\n",
8d655683 6610 pfrom->id,
6611 pfrom->cleanSubVer,
6612 sProblem,
6613 pfrom->nPingNonceSent,
6614 nonce,
6615 nAvail);
971bb3e9
JL
6616 }
6617 if (bPingFinished) {
6618 pfrom->nPingNonceSent = 0;
6619 }
6620 }
8d655683 6621
6622
4d9c7fe6 6623 else if (fAlerts && strCommand == "alert")
0a61b0df 6624 {
6625 CAlert alert;
6626 vRecv >> alert;
8d655683 6627
d5a52d9b
GA
6628 uint256 alertHash = alert.GetHash();
6629 if (pfrom->setKnown.count(alertHash) == 0)
0a61b0df 6630 {
f14e687f 6631 if (alert.ProcessAlert(Params().AlertKey()))
f8dcd5ca 6632 {
d5a52d9b
GA
6633 // Relay
6634 pfrom->setKnown.insert(alertHash);
6635 {
6636 LOCK(cs_vNodes);
6637 BOOST_FOREACH(CNode* pnode, vNodes)
8d655683 6638 alert.RelayTo(pnode);
d5a52d9b
GA
6639 }
6640 }
6641 else {
6642 // Small DoS penalty so peers that send us lots of
6643 // duplicate/expired/invalid-signature/whatever alerts
6644 // eventually get banned.
6645 // This isn't a Misbehaving(100) (immediate ban) because the
6646 // peer might be an older or different implementation with
6647 // a different signature key, etc.
b2864d2f 6648 Misbehaving(pfrom->GetId(), 10);
f8dcd5ca 6649 }
0a61b0df 6650 }
6651 }
8d655683 6652
6653
422d1225
MC
6654 else if (strCommand == "filterload")
6655 {
6656 CBloomFilter filter;
6657 vRecv >> filter;
8d655683 6658
422d1225
MC
6659 if (!filter.IsWithinSizeConstraints())
6660 // There is no excuse for sending a too-large filter
b2864d2f 6661 Misbehaving(pfrom->GetId(), 100);
422d1225
MC
6662 else
6663 {
6664 LOCK(pfrom->cs_filter);
6665 delete pfrom->pfilter;
6666 pfrom->pfilter = new CBloomFilter(filter);
a7f533a9 6667 pfrom->pfilter->UpdateEmptyFull();
422d1225 6668 }
4c8fc1a5 6669 pfrom->fRelayTxes = true;
422d1225 6670 }
8d655683 6671
6672
422d1225
MC
6673 else if (strCommand == "filteradd")
6674 {
6675 vector<unsigned char> vData;
6676 vRecv >> vData;
8d655683 6677
422d1225
MC
6678 // Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
6679 // and thus, the maximum size any matched object can have) in a filteradd message
192cc910 6680 if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE)
422d1225 6681 {
b2864d2f 6682 Misbehaving(pfrom->GetId(), 100);
422d1225
MC
6683 } else {
6684 LOCK(pfrom->cs_filter);
6685 if (pfrom->pfilter)
6686 pfrom->pfilter->insert(vData);
6687 else
b2864d2f 6688 Misbehaving(pfrom->GetId(), 100);
422d1225
MC
6689 }
6690 }
8d655683 6691
6692
422d1225
MC
6693 else if (strCommand == "filterclear")
6694 {
6695 LOCK(pfrom->cs_filter);
6696 delete pfrom->pfilter;
37c6389c 6697 pfrom->pfilter = new CBloomFilter();
4c8fc1a5 6698 pfrom->fRelayTxes = true;
422d1225 6699 }
8d655683 6700
6701
358ce266
GA
6702 else if (strCommand == "reject")
6703 {
efad808a
PW
6704 if (fDebug) {
6705 try {
6706 string strMsg; unsigned char ccode; string strReason;
307f7d48 6707 vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH);
8d655683 6708
efad808a
PW
6709 ostringstream ss;
6710 ss << strMsg << " code " << itostr(ccode) << ": " << strReason;
8d655683 6711
efad808a
PW
6712 if (strMsg == "block" || strMsg == "tx")
6713 {
6714 uint256 hash;
6715 vRecv >> hash;
6716 ss << ": hash " << hash.ToString();
6717 }
6718 LogPrint("net", "Reject %s\n", SanitizeString(ss.str()));
27df4123 6719 } catch (const std::ios_base::failure&) {
efad808a
PW
6720 // Avoid feedback loops by preventing reject messages from triggering a new reject message.
6721 LogPrint("net", "Unparseable reject message received\n");
358ce266 6722 }
358ce266
GA
6723 }
6724 }
432bc22a 6725 else if (strCommand == "notfound") {
e496b2e3
WL
6726 // We do not care about the NOTFOUND message, but logging an Unknown Command
6727 // message would be undesirable as we transmit it ourselves.
6728 }
8d655683 6729
e496b2e3 6730 else {
0a61b0df 6731 // Ignore unknown commands for extensibility
6ecf3edf 6732 LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id);
0a61b0df 6733 }
8d655683 6734
6735
6736
0a61b0df 6737 return true;
6738}
6739
607dbfde 6740// requires LOCK(cs_vRecvMsg)
e89b9f6a
PW
6741bool ProcessMessages(CNode* pfrom)
6742{
e89b9f6a 6743 //if (fDebug)
30c1db1c 6744 // LogPrintf("%s(%u messages)\n", __func__, pfrom->vRecvMsg.size());
8d655683 6745
e89b9f6a
PW
6746 //
6747 // Message format
6748 // (4) message start
6749 // (12) command
6750 // (4) size
6751 // (4) checksum
6752 // (x) data
6753 //
967f2459 6754 bool fOk = true;
8d655683 6755
c7f039b6
PW
6756 if (!pfrom->vRecvGetData.empty())
6757 ProcessGetData(pfrom);
8d655683 6758
75ef87dd
PS
6759 // this maintains the order of responses
6760 if (!pfrom->vRecvGetData.empty()) return fOk;
8d655683 6761
967f2459 6762 std::deque<CNetMessage>::iterator it = pfrom->vRecvMsg.begin();
41b052ad 6763 while (!pfrom->fDisconnect && it != pfrom->vRecvMsg.end()) {
9d6cd04b 6764 // Don't bother if send buffer is too full to respond anyway
41b052ad 6765 if (pfrom->nSendSize >= SendBufferSize())
9d6cd04b 6766 break;
8d655683 6767
967f2459
PW
6768 // get next message
6769 CNetMessage& msg = *it;
8d655683 6770
607dbfde 6771 //if (fDebug)
30c1db1c 6772 // LogPrintf("%s(message %u msgsz, %u bytes, complete:%s)\n", __func__,
607dbfde
JG
6773 // msg.hdr.nMessageSize, msg.vRecv.size(),
6774 // msg.complete() ? "Y" : "N");
8d655683 6775
967f2459 6776 // end, if an incomplete message is found
607dbfde 6777 if (!msg.complete())
e89b9f6a 6778 break;
8d655683 6779
967f2459
PW
6780 // at this point, any failure means we can delete the current message
6781 it++;
8d655683 6782
607dbfde 6783 // Scan for message start
0e4b3175 6784 if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
28d4cff0 6785 LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id);
967f2459
PW
6786 fOk = false;
6787 break;
e89b9f6a 6788 }
8d655683 6789
e89b9f6a 6790 // Read header
607dbfde 6791 CMessageHeader& hdr = msg.hdr;
eec37136 6792 if (!hdr.IsValid(Params().MessageStart()))
e89b9f6a 6793 {
28d4cff0 6794 LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
e89b9f6a
PW
6795 continue;
6796 }
6797 string strCommand = hdr.GetCommand();
8d655683 6798
e89b9f6a
PW
6799 // Message size
6800 unsigned int nMessageSize = hdr.nMessageSize;
8d655683 6801
e89b9f6a 6802 // Checksum
607dbfde 6803 CDataStream& vRecv = msg.vRecv;
18c0fa97 6804 uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
556814ec 6805 unsigned int nChecksum = ReadLE32((unsigned char*)&hash);
18c0fa97 6806 if (nChecksum != hdr.nChecksum)
e89b9f6a 6807 {
30c1db1c 6808 LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n", __func__,
8d655683 6809 SanitizeString(strCommand), nMessageSize, nChecksum, hdr.nChecksum);
18c0fa97 6810 continue;
e89b9f6a 6811 }
8d655683 6812
e89b9f6a
PW
6813 // Process message
6814 bool fRet = false;
6815 try
6816 {
9f4da19b 6817 fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime);
b31499ec 6818 boost::this_thread::interruption_point();
e89b9f6a 6819 }
27df4123 6820 catch (const std::ios_base::failure& e)
e89b9f6a 6821 {
358ce266 6822 pfrom->PushMessage("reject", strCommand, REJECT_MALFORMED, string("error parsing message"));
e89b9f6a
PW
6823 if (strstr(e.what(), "end of data"))
6824 {
814efd6f 6825 // Allow exceptions from under-length message on vRecv
30c1db1c 6826 LogPrintf("%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
e89b9f6a
PW
6827 }
6828 else if (strstr(e.what(), "size too large"))
6829 {
814efd6f 6830 // Allow exceptions from over-long size
30c1db1c 6831 LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
e89b9f6a
PW
6832 }
6833 else
6834 {
5970a0d7 6835 //PrintExceptionContinue(&e, "ProcessMessages()");
e89b9f6a
PW
6836 }
6837 }
27df4123 6838 catch (const boost::thread_interrupted&) {
b31499ec
GA
6839 throw;
6840 }
27df4123 6841 catch (const std::exception& e) {
ea591ead 6842 PrintExceptionContinue(&e, "ProcessMessages()");
e89b9f6a 6843 } catch (...) {
ea591ead 6844 PrintExceptionContinue(NULL, "ProcessMessages()");
e89b9f6a 6845 }
8d655683 6846
e89b9f6a 6847 if (!fRet)
30c1db1c 6848 LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->id);
8d655683 6849
75ef87dd 6850 break;
e89b9f6a 6851 }
8d655683 6852
41b052ad
PW
6853 // In case the connection got shut down, its receive buffer was wiped
6854 if (!pfrom->fDisconnect)
6855 pfrom->vRecvMsg.erase(pfrom->vRecvMsg.begin(), it);
8d655683 6856
967f2459 6857 return fOk;
e89b9f6a 6858}
0a61b0df 6859
6860
0a61b0df 6861bool SendMessages(CNode* pto, bool fSendTrickle)
6862{
e8e8904d 6863 const Consensus::Params& consensusParams = Params().GetConsensus();
6055b910 6864 {
b05a89b2 6865 // Don't send anything until we get its version message
0a61b0df 6866 if (pto->nVersion == 0)
6867 return true;
8d655683 6868
971bb3e9
JL
6869 //
6870 // Message: ping
6871 //
6872 bool pingSend = false;
6873 if (pto->fPingQueued) {
6874 // RPC ping request by user
6875 pingSend = true;
6876 }
f1920e86
PW
6877 if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
6878 // Ping automatically sent as a latency probe & keepalive.
971bb3e9
JL
6879 pingSend = true;
6880 }
6881 if (pingSend) {
51ed9ec9 6882 uint64_t nonce = 0;
971bb3e9 6883 while (nonce == 0) {
001a53d7 6884 GetRandBytes((unsigned char*)&nonce, sizeof(nonce));
971bb3e9 6885 }
971bb3e9 6886 pto->fPingQueued = false;
f1920e86 6887 pto->nPingUsecStart = GetTimeMicros();
971bb3e9 6888 if (pto->nVersion > BIP0031_VERSION) {
f1920e86 6889 pto->nPingNonceSent = nonce;
c971112d 6890 pto->PushMessage("ping", nonce);
971bb3e9 6891 } else {
f1920e86
PW
6892 // Peer is too old to support ping command with nonce, pong will never arrive.
6893 pto->nPingNonceSent = 0;
93e447b6 6894 pto->PushMessage("ping");
971bb3e9 6895 }
93e447b6 6896 }
8d655683 6897
55a1db4f
WL
6898 TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
6899 if (!lockMain)
6900 return true;
8d655683 6901
0a61b0df 6902 // Address refresh broadcast
51ed9ec9 6903 static int64_t nLastRebroadcast;
5d1b8f17 6904 if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
0a61b0df 6905 {
845c86d1
GM
6906 LOCK(cs_vNodes);
6907 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 6908 {
d81cff32 6909 // Periodically clear addrKnown to allow refresh broadcasts
845c86d1 6910 if (nLastRebroadcast)
83671efe 6911 pnode->addrKnown.reset();
8d655683 6912
845c86d1
GM
6913 // Rebroadcast our address
6914 AdvertizeLocal(pnode);
0a61b0df 6915 }
845c86d1
GM
6916 if (!vNodes.empty())
6917 nLastRebroadcast = GetTime();
0a61b0df 6918 }
8d655683 6919
0a61b0df 6920 //
6921 // Message: addr
6922 //
6923 if (fSendTrickle)
6924 {
6925 vector<CAddress> vAddr;
6926 vAddr.reserve(pto->vAddrToSend.size());
223b6f1b 6927 BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
0a61b0df 6928 {
d81cff32 6929 if (!pto->addrKnown.contains(addr.GetKey()))
0a61b0df 6930 {
d81cff32 6931 pto->addrKnown.insert(addr.GetKey());
0a61b0df 6932 vAddr.push_back(addr);
6933 // receiver rejects addr messages larger than 1000
6934 if (vAddr.size() >= 1000)
6935 {
6936 pto->PushMessage("addr", vAddr);
6937 vAddr.clear();
6938 }
6939 }
6940 }
6941 pto->vAddrToSend.clear();
6942 if (!vAddr.empty())
6943 pto->PushMessage("addr", vAddr);
6944 }
8d655683 6945
75f51f2a
PW
6946 CNodeState &state = *State(pto->GetId());
6947 if (state.fShouldBan) {
dc942e6f
PW
6948 if (pto->fWhitelisted)
6949 LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
b2864d2f
PW
6950 else {
6951 pto->fDisconnect = true;
dc942e6f
PW
6952 if (pto->addr.IsLocal())
6953 LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
6954 else
c74332c6 6955 {
dc942e6f 6956 CNode::Ban(pto->addr);
c74332c6 6957 }
b2864d2f 6958 }
75f51f2a 6959 state.fShouldBan = false;
b2864d2f 6960 }
8d655683 6961
75f51f2a 6962 BOOST_FOREACH(const CBlockReject& reject, state.rejects)
8d655683 6963 pto->PushMessage("reject", (string)"block", reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
75f51f2a 6964 state.rejects.clear();
8d655683 6965
6055b910 6966 // Start block sync
341735eb
PW
6967 if (pindexBestHeader == NULL)
6968 pindexBestHeader = chainActive.Tip();
b4ee0bdd 6969 bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
e9b84960 6970 if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
341735eb 6971 // Only actively request headers from a single peer, unless we're close to today.
e9b84960 6972 if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
341735eb
PW
6973 state.fSyncStarted = true;
6974 nSyncStarted++;
e9b84960 6975 CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
4c933229 6976 LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
4f152496 6977 pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256());
341735eb 6978 }
6055b910 6979 }
8d655683 6980
6055b910
PW
6981 // Resend wallet transactions that haven't gotten in a block yet
6982 // Except during reindex, importing and IBD, when old wallet
6983 // transactions become unconfirmed and spams other nodes.
6984 if (!fReindex && !fImporting && !IsInitialBlockDownload())
6985 {
0f5954c4 6986 GetMainSignals().Broadcast(nTimeBestReceived);
6055b910 6987 }
8d655683 6988
0a61b0df 6989 //
6990 // Message: inventory
6991 //
6992 vector<CInv> vInv;
6993 vector<CInv> vInvWait;
0a61b0df 6994 {
f8dcd5ca 6995 LOCK(pto->cs_inventory);
0a61b0df 6996 vInv.reserve(pto->vInventoryToSend.size());
6997 vInvWait.reserve(pto->vInventoryToSend.size());
223b6f1b 6998 BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
0a61b0df 6999 {
7000 if (pto->setInventoryKnown.count(inv))
7001 continue;
8d655683 7002
0a61b0df 7003 // trickle out tx inv to protect privacy
7004 if (inv.type == MSG_TX && !fSendTrickle)
7005 {
7006 // 1/4 of tx invs blast to all immediately
7007 static uint256 hashSalt;
4f152496 7008 if (hashSalt.IsNull())
f718aedd 7009 hashSalt = GetRandHash();
734f85c4 7010 uint256 hashRand = ArithToUint256(UintToArith256(inv.hash) ^ UintToArith256(hashSalt));
0a61b0df 7011 hashRand = Hash(BEGIN(hashRand), END(hashRand));
734f85c4 7012 bool fTrickleWait = ((UintToArith256(hashRand) & 3) != 0);
8d655683 7013
0a61b0df 7014 if (fTrickleWait)
7015 {
7016 vInvWait.push_back(inv);
7017 continue;
7018 }
7019 }
8d655683 7020
0a61b0df 7021 // returns true if wasn't already contained in the set
7022 if (pto->setInventoryKnown.insert(inv).second)
7023 {
7024 vInv.push_back(inv);
7025 if (vInv.size() >= 1000)
7026 {
7027 pto->PushMessage("inv", vInv);
7028 vInv.clear();
7029 }
7030 }
7031 }
7032 pto->vInventoryToSend = vInvWait;
7033 }
7034 if (!vInv.empty())
7035 pto->PushMessage("inv", vInv);
8d655683 7036
341735eb 7037 // Detect whether we're stalling
f59d8f0b 7038 int64_t nNow = GetTimeMicros();
341735eb
PW
7039 if (!pto->fDisconnect && state.nStallingSince && state.nStallingSince < nNow - 1000000 * BLOCK_STALLING_TIMEOUT) {
7040 // Stalling only triggers when the block download window cannot move. During normal steady state,
7041 // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
7042 // should only happen during initial block download.
7043 LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
f59d8f0b
PW
7044 pto->fDisconnect = true;
7045 }
3ff735c9 7046 // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
91613034
PW
7047 // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
7048 // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
7e6d23b1 7049 // being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
91613034 7050 // to unreasonably increase our timeout.
8ba7f842
SD
7051 // We also compare the block download timeout originally calculated against the time at which we'd disconnect
7052 // if we assumed the block were being requested now (ignoring blocks we've requested from this peer, since we're
7053 // only looking at this peer's oldest request). This way a large queue in the past doesn't result in a
7054 // permanently large window for this block to be delivered (ie if the number of blocks in flight is decreasing
7055 // more quickly than once every 5 minutes, then we'll shorten the download window for this block).
7056 if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) {
7057 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
82737933 7058 int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams);
8ba7f842
SD
7059 if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) {
7060 LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow);
7061 queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow;
7062 }
7063 if (queuedBlock.nTimeDisconnect < nNow) {
7064 LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
7065 pto->fDisconnect = true;
7066 }
91613034 7067 }
8d655683 7068
0a61b0df 7069 //
f59d8f0b 7070 // Message: getdata (blocks)
0a61b0df 7071 //
161f617d 7072 static uint256 zero;
0a61b0df 7073 vector<CInv> vGetData;
00dcaf4b 7074 if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
341735eb
PW
7075 vector<CBlockIndex*> vToDownload;
7076 NodeId staller = -1;
7077 FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
7078 BOOST_FOREACH(CBlockIndex *pindex, vToDownload) {
7079 vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
82737933 7080 MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
1af838b3 7081 LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
8d655683 7082 pindex->nHeight, pto->id);
341735eb
PW
7083 }
7084 if (state.nBlocksInFlight == 0 && staller != -1) {
1bcee67e 7085 if (State(staller)->nStallingSince == 0) {
341735eb 7086 State(staller)->nStallingSince = nNow;
1bcee67e
B
7087 LogPrint("net", "Stall started peer=%d\n", staller);
7088 }
f59d8f0b
PW
7089 }
7090 }
8d725ab4 7091 /*CBlockIndex *pindex;
bddeaf5e 7092 if ( komodo_requestedhash != zero && komodo_requestedcount < 16 && (pindex= mapBlockIndex[komodo_requestedhash]) != 0 )
161f617d 7093 {
bddeaf5e 7094 LogPrint("net","komodo_requestedhash.%d request %s to nodeid.%d\n",komodo_requestedcount,komodo_requestedhash.ToString().c_str(),pto->GetId());
7095 fprintf(stderr,"komodo_requestedhash.%d request %s to nodeid.%d\n",komodo_requestedcount,komodo_requestedhash.ToString().c_str(),pto->GetId());
161f617d 7096 vGetData.push_back(CInv(MSG_BLOCK, komodo_requestedhash));
7097 MarkBlockAsInFlight(pto->GetId(), komodo_requestedhash, consensusParams, pindex);
bddeaf5e 7098 komodo_requestedcount++;
7099 if ( komodo_requestedcount > 16 )
7100 {
7101 memset(&komodo_requestedhash,0,sizeof(komodo_requestedhash));
7102 komodo_requestedcount = 0;
7103 }
8d725ab4 7104 }*/
161f617d 7105
f59d8f0b
PW
7106 //
7107 // Message: getdata (non-blocks)
7108 //
7109 while (!pto->fDisconnect && !pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
0a61b0df 7110 {
7111 const CInv& inv = (*pto->mapAskFor.begin()).second;
ae8bfd12 7112 if (!AlreadyHave(inv))
0a61b0df 7113 {
3b570559 7114 if (fDebug)
2e36866f 7115 LogPrint("net", "Requesting %s peer=%d\n", inv.ToString(), pto->id);
0a61b0df 7116 vGetData.push_back(inv);
7117 if (vGetData.size() >= 1000)
7118 {
7119 pto->PushMessage("getdata", vGetData);
7120 vGetData.clear();
7121 }
e2190f80
GM
7122 } else {
7123 //If we're not going to ask, don't expect a response.
7124 pto->setAskFor.erase(inv.hash);
0a61b0df 7125 }
7126 pto->mapAskFor.erase(pto->mapAskFor.begin());
7127 }
7128 if (!vGetData.empty())
7129 pto->PushMessage("getdata", vGetData);
8d655683 7130
0a61b0df 7131 }
7132 return true;
7133}
7134
8d655683 7135std::string CBlockFileInfo::ToString() const {
7136 return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst), DateTimeStrFormat("%Y-%m-%d", nTimeLast));
7137}
0a61b0df 7138
7139
7140
3427517d
PW
7141class CMainCleanup
7142{
7143public:
7144 CMainCleanup() {}
7145 ~CMainCleanup() {
7146 // block headers
145d5be8 7147 BlockMap::iterator it1 = mapBlockIndex.begin();
3427517d
PW
7148 for (; it1 != mapBlockIndex.end(); it1++)
7149 delete (*it1).second;
7150 mapBlockIndex.clear();
8d655683 7151
3427517d 7152 // orphan transactions
3427517d 7153 mapOrphanTransactions.clear();
c74332c6 7154 mapOrphanTransactionsByPrev.clear();
3427517d
PW
7155 }
7156} instance_of_cmaincleanup;
431cce98 7157
431cce98 7158extern "C" const char* getDataDir()
7159{
8d655683 7160 return GetDataDir().string().c_str();
431cce98 7161}
7162
072099d7
S
7163
7164// Set default values of new CMutableTransaction based on consensus rules at given height.
7165CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight)
7166{
7167 CMutableTransaction mtx;
8d655683 7168
072099d7
S
7169 bool isOverwintered = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_OVERWINTER);
7170 if (isOverwintered) {
7171 mtx.fOverwintered = true;
7172 mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
7173 mtx.nVersion = 3;
7174 // Expiry height is not set. Only fields required for a parser to treat as a valid Overwinter V3 tx.
8d655683 7175
072099d7
S
7176 // TODO: In future, when moving from Overwinter to Sapling, it will be useful
7177 // to set the expiry height to: min(activation_height - 1, default_expiry_height)
7178 }
7179 return mtx;
7180}
This page took 2.882523 seconds and 4 git commands to generate.