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