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