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