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