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