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