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