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