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