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