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