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