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