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