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