// Czecoin: reset synchronized checkpoint to last hardened checkpoint bool ResetSyncCheckpoint() { LOCK(cs_hashSyncCheckpoint); const uint256& hash = mapCheckpoints.rbegin()->second; if (mapBlockIndex.count(hash) && !mapBlockIndex[hash]->IsInMainChain()) { // checkpoint block accepted but not yet in main chain printf("ResetSyncCheckpoint: SetBestChain to hardened checkpoint %s\n", hash.ToString().c_str()); CTxDB txdb; CBlock block; if (!block.ReadFromDisk(mapBlockIndex[hash])) return error("ResetSyncCheckpoint: ReadFromDisk failed for hardened checkpoint %s", hash.ToString().c_str()); if (!block.SetBestChain(txdb, mapBlockIndex[hash])) { return error("ResetSyncCheckpoint: SetBestChain failed for hardened checkpoint %s", hash.ToString().c_str()); } } else if(!mapBlockIndex.count(hash)) { // checkpoint block not yet accepted hashPendingCheckpoint = hash; checkpointMessagePending.SetNull(); printf("ResetSyncCheckpoint: pending for sync-checkpoint %s\n", hashPendingCheckpoint.ToString().c_str()); } BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints) { const uint256& hash = i.second; if (mapBlockIndex.count(hash) && mapBlockIndex[hash]->IsInMainChain()) { if (!WriteSyncCheckpoint(hash)) return error("ResetSyncCheckpoint: failed to write sync checkpoint %s", hash.ToString().c_str()); printf("ResetSyncCheckpoint: sync-checkpoint reset to %s\n", hashSyncCheckpoint.ToString().c_str()); return true; } } return false; }
Value dumpbootstrap(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) throw runtime_error( "dumpbootstrap \"destination\" \"blocks\"\n" "\nCreates a bootstrap format block dump of the blockchain in destination, which can be a directory or a path with filename, up to the given block number."); string strDest = params[0].get_str(); int nBlocks = params[1].get_int(); if (nBlocks < 0 || nBlocks > nBestHeight) throw runtime_error("Block number out of range."); boost::filesystem::path pathDest(strDest); if (boost::filesystem::is_directory(pathDest)) pathDest /= "bootstrap.dat"; try { FILE* file = fopen(pathDest.string().c_str(), "wb"); if (!file) throw JSONRPCError(RPC_MISC_ERROR, "Error: Could not open bootstrap file for writing."); CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION); if (!fileout) throw JSONRPCError(RPC_MISC_ERROR, "Error: Could not open bootstrap file for writing."); for (int nHeight = 0; nHeight <= nBlocks; nHeight++) { CBlock block; CBlockIndex* pblockindex = FindBlockByHeight(nHeight); block.ReadFromDisk(pblockindex, true); fileout << FLATDATA(Params().MessageStart()) << fileout.GetSerializeSize(block) << block; } } catch(const boost::filesystem::filesystem_error &e) { throw JSONRPCError(RPC_MISC_ERROR, "Error: Bootstrap dump failed!"); } return Value::null; }
Value getblock(const Array& params, bool fHelp, CACLUser &user) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "getblock <hash> [verbose=true]\n" "If verbose is false, returns a string that is serialized, hex-encoded data for block <hash>.\n" "If verbose is true, returns an Object with information about block <hash>." ); if(!user.check(ACL_PUBLICREAD)) { throw JSONRPCError(RPC_PERMISSION_DENIED, "Permission denied!"); } std::string strHash = params[0].get_str(); uint256 hash(strHash); bool fVerbose = true; if (params.size() > 1) fVerbose = params[1].get_bool(); if (mapBlockIndex.count(hash) == 0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); CBlock block; CBlockIndex* pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex); if (!fVerbose) { CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); ssBlock << block; std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); return strHex; } return blockToJSON(block, pblockindex); }
Value getblockbynumber(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "getblock <number> [txinfo]\n" "txinfo optional to print more detailed tx info\n" "Returns details of a block with given block-number."); int nHeight = params[0].get_int(); if (nHeight < 0 || nHeight > nBestHeight) throw runtime_error("Block number out of range."); CBlock block; CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; while (pblockindex->nHeight > nHeight) pblockindex = pblockindex->pprev; uint256 hash = *pblockindex->phashBlock; pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex, true); return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); }
bool CTxDB::LoadBlockIndex() { if (mapBlockIndex.size() > 0) { // Already loaded once in this session. It can happen during migration // from BDB. return true; } // The block index is an in-memory structure that maps hashes to on-disk // locations where the contents of the block can be found. Here, we scan it // out of the DB and into mapBlockIndex. leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); // Seek to start key. CDataStream ssStartKey(SER_DISK, CLIENT_VERSION); ssStartKey << make_pair(string("blockindex"), uint256(0)); iterator->Seek(ssStartKey.str()); // Now read each entry. while (iterator->Valid()) { // Unpack keys and values. CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.write(iterator->key().data(), iterator->key().size()); CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.write(iterator->value().data(), iterator->value().size()); string strType; ssKey >> strType; // Did we reach the end of the data to read? if (fRequestShutdown || strType != "blockindex") break; CDiskBlockIndex diskindex; ssValue >> diskindex; uint256 blockHash = diskindex.GetBlockHash(); // Construct block index object CBlockIndex* pindexNew = InsertBlockIndex(blockHash); pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); pindexNew->pnext = InsertBlockIndex(diskindex.hashNext); pindexNew->nFile = diskindex.nFile; pindexNew->nBlockPos = diskindex.nBlockPos; pindexNew->nHeight = diskindex.nHeight; pindexNew->nMint = diskindex.nMint; pindexNew->nMoneySupply = diskindex.nMoneySupply; pindexNew->nFlags = diskindex.nFlags; pindexNew->nStakeModifier = diskindex.nStakeModifier; pindexNew->prevoutStake = diskindex.prevoutStake; pindexNew->nStakeTime = diskindex.nStakeTime; pindexNew->hashProofOfStake = diskindex.hashProofOfStake; pindexNew->nVersion = diskindex.nVersion; pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; // Watch for genesis block if (pindexGenesisBlock == NULL && blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)) pindexGenesisBlock = pindexNew; if (!pindexNew->CheckIndex()) { delete iterator; return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight); } // CurrentCoin: build setStakeSeen if (pindexNew->IsProofOfStake()) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); iterator->Next(); } delete iterator; if (fRequestShutdown) return true; // Calculate nChainTrust vector<pair<int, CBlockIndex*> > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { CBlockIndex* pindex = item.second; vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); } sort(vSortedByHeight.begin(), vSortedByHeight.end()); BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust(); // CurrentCoin: calculate stake modifier checksum pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex); if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum)) return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier); } // Load hashBestChain pointer to end of best chain if (!ReadHashBestChain(hashBestChain)) { if (pindexGenesisBlock == NULL) return true; return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded"); } if (!mapBlockIndex.count(hashBestChain)) return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index"); pindexBest = mapBlockIndex[hashBestChain]; nBestHeight = pindexBest->nHeight; nBestChainTrust = pindexBest->nChainTrust; printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%s date=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(), DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); // CurrentCoin: load hashSyncCheckpoint if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint)) return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded"); printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str()); // Load bnBestInvalidTrust, OK if it doesn't exist CBigNum bnBestInvalidTrust; ReadBestInvalidTrust(bnBestInvalidTrust); nBestInvalidTrust = bnBestInvalidTrust.getuint256(); // Verify blocks in the best chain int nCheckLevel = GetArg("-checklevel", 1); int nCheckDepth = GetArg( "-checkblocks", 2500); if (nCheckDepth == 0) nCheckDepth = 1000000000; // suffices until the year 19000 if (nCheckDepth > nBestHeight) nCheckDepth = nBestHeight; printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); CBlockIndex* pindexFork = NULL; map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos; for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) { if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) break; CBlock block; if (!block.ReadFromDisk(pindex)) return error("LoadBlockIndex() : block.ReadFromDisk failed"); // check level 1: verify block validity // check level 7: verify block signature too if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6))) { printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); pindexFork = pindex->pprev; } // check level 2: verify transaction index validity if (nCheckLevel>1) { pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos); mapBlockPos[pos] = pindex; BOOST_FOREACH(const CTransaction &tx, block.vtx) { uint256 hashTx = tx.GetHash(); CTxIndex txindex; if (ReadTxIndex(hashTx, txindex)) { // check level 3: checker transaction hashes if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos) { // either an error or a duplicate transaction CTransaction txFound; if (!txFound.ReadFromDisk(txindex.pos)) { printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str()); pindexFork = pindex->pprev; } else if (txFound.GetHash() != hashTx) // not a duplicate tx { printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str()); pindexFork = pindex->pprev; } } // check level 4: check whether spent txouts were spent within the main chain unsigned int nOutput = 0; if (nCheckLevel>3) { BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent) { if (!txpos.IsNull()) { pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos); if (!mapBlockPos.count(posFind)) { printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str()); pindexFork = pindex->pprev; } // check level 6: check whether spent txouts were spent by a valid transaction that consume them if (nCheckLevel>5) { CTransaction txSpend; if (!txSpend.ReadFromDisk(txpos)) { printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } else if (!txSpend.CheckTransaction()) { printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } else { bool fFound = false; BOOST_FOREACH(const CTxIn &txin, txSpend.vin) if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput) fFound = true; if (!fFound) { printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } } } } nOutput++; } } }
// pindex must belong to the main branch, i.e. corresponding blocks must be connected // Returns a copy of the game state bool GetGameState (DatabaseSet& dbset, CBlockIndex *pindex, GameState &outState) { if (!pindex) { outState = GameState(); return true; } /* See if we have the block in the state cache. */ if (stateCache.query (*pindex->phashBlock, outState)) return true; // Get the latest saved state CGameDB gameDb("r", dbset.tx ()); if (gameDb.Read(pindex->nHeight, outState)) { if (outState.nHeight != pindex->nHeight) return error("GetGameState: wrong height"); if (outState.hashBlock != *pindex->phashBlock) return error("GetGameState: wrong hash"); return true; } if (!pindex->IsInMainChain()) return error("GetGameState called for non-main chain"); printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); printf("GetGameState: need to integrate state for height %d (current %d)\n", pindex->nHeight, nBestHeight); CBlockIndex *plast = pindex; GameState lastState; for (; plast->pprev; plast = plast->pprev) { if (stateCache.query (*plast->pprev->phashBlock, lastState)) break; if (gameDb.Read(plast->pprev->nHeight, lastState)) break; } printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); printf("GetGameState: last saved block has height %d\n", lastState.nHeight); // Integrate steps starting from the last saved state // FIXME: Might want to store intermediate steps in stateCache, too. loop { std::vector<CTransaction> vgametx; CBlock block; block.ReadFromDisk(plast); int64 nTax; if (!PerformStep (dbset.name (), lastState, &block, nTax, outState, vgametx)) return false; if (block.vgametx != vgametx) { printf("Error: GetGameState: computed vgametx is different from the stored one\n"); printf(" block %s (height = %d) vgametx:\n", block.GetHash().ToString().c_str(), plast->nHeight); BOOST_FOREACH (const CTransaction &tx, block.vgametx) { printf(" "); tx.print(); } printf(" computed vgametx (height = %d):\n", outState.nHeight); BOOST_FOREACH (const CTransaction &tx, vgametx) { printf(" "); tx.print(); } return false; }
Value rewindchain(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "rewindchain <number>\n" "Remove <number> blocks from the chain."); int nNumber = params[0].get_int(); if (nNumber < 0 || nNumber > nBestHeight) throw runtime_error("Block number out of range."); Object result; int nRemoved = 0; { LOCK2(cs_main, pwalletMain->cs_wallet); uint32_t nFileRet = 0; uint8_t buffer[512]; LogPrintf("rewindchain %d\n", nNumber); void* nFind; for (int i = 0; i < nNumber; ++i) { memset(buffer, 0, sizeof(buffer)); FILE* fp = AppendBlockFile(false, nFileRet, "r+b"); if (!fp) { LogPrintf("AppendBlockFile failed.\n"); break; }; errno = 0; if (fseek(fp, 0, SEEK_END) != 0) { LogPrintf("fseek failed: %s\n", strerror(errno)); break; }; long int fpos = ftell(fp); if (fpos == -1) { LogPrintf("ftell failed: %s\n", strerror(errno)); break; }; long int foundPos = -1; long int readSize = sizeof(buffer) / 2; while (fpos > 0) { if (fpos < (long int)sizeof(buffer) / 2) readSize = fpos; memcpy(buffer+readSize, buffer, readSize); // move last read data (incase token crosses a boundary) fpos -= readSize; if (fseek(fp, fpos, SEEK_SET) != 0) { LogPrintf("fseek failed: %s\n", strerror(errno)); break; }; errno = 0; if (fread(buffer, sizeof(uint8_t), readSize, fp) != (size_t)readSize) { if (errno != 0) LogPrintf("fread failed: %s\n", strerror(errno)); else LogPrintf("End of file.\n"); break; }; uint32_t findPos = sizeof(buffer); while (findPos > MESSAGE_START_SIZE) { if ((nFind = shellk::memrchr(buffer, Params().MessageStart()[0], findPos-MESSAGE_START_SIZE))) { if (memcmp(nFind, Params().MessageStart(), MESSAGE_START_SIZE) == 0) { foundPos = ((uint8_t*)nFind - buffer) + MESSAGE_START_SIZE; break; } else { findPos = ((uint8_t*)nFind - buffer); // -- step over matched char that wasn't pchMessageStart if (findPos > 0) // prevent findPos < 0 (unsigned) findPos--; }; } else { break; // pchMessageStart[0] not found in buffer }; }; if (foundPos > -1) break; }; LogPrintf("fpos %d, foundPos %d.\n", fpos, foundPos); if (foundPos < 0) { LogPrintf("block start not found.\n"); fclose(fp); break; }; CAutoFile blkdat(fp, SER_DISK, CLIENT_VERSION); if (fseek(blkdat, fpos+foundPos, SEEK_SET) != 0) { LogPrintf("fseek blkdat failed: %s\n", strerror(errno)); break; }; unsigned int nSize; blkdat >> nSize; LogPrintf("nSize %u .\n", nSize); if (nSize < 1 || nSize > MAX_BLOCK_SIZE) { LogPrintf("block size error %u\n", nSize); }; CBlock block; blkdat >> block; uint256 hashblock = block.GetHash(); LogPrintf("hashblock %s .\n", hashblock.ToString().c_str()); std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashblock); if (mi != mapBlockIndex.end() && (*mi).second) { LogPrintf("block is in main chain.\n"); if (!mi->second->pprev) { LogPrintf("! mi->second.pprev\n"); } else { { CBlock blockPrev; // strange way SetBestChain works, TODO: does it need the full block? if (!blockPrev.ReadFromDisk(mi->second->pprev)) { LogPrintf("blockPrev.ReadFromDisk failed %s.\n", mi->second->pprev->GetBlockHash().ToString().c_str()); break; }; CTxDB txdb; if (!blockPrev.SetBestChain(txdb, mi->second->pprev)) { LogPrintf("SetBestChain failed.\n"); }; } mi->second->pprev->pnext = NULL; }; delete mi->second; mapBlockIndex.erase(mi); }; std::map<uint256, COrphanBlock*>::iterator miOph = mapOrphanBlocks.find(hashblock); if (miOph != mapOrphanBlocks.end()) { LogPrintf("block is an orphan.\n"); mapOrphanBlocks.erase(miOph); }; CTxDB txdb; for (vector<CTransaction>::iterator it = block.vtx.begin(); it != block.vtx.end(); ++it) { LogPrintf("EraseTxIndex().\n"); txdb.EraseTxIndex(*it); }; LogPrintf("EraseBlockIndex().\n"); txdb.EraseBlockIndex(hashblock); errno = 0; if (ftruncate(fileno(fp), fpos+foundPos-MESSAGE_START_SIZE) != 0) { LogPrintf("ftruncate failed: %s\n", strerror(errno)); }; LogPrintf("hashBestChain %s, nBestHeight %d\n", hashBestChain.ToString().c_str(), nBestHeight); //fclose(fp); // ~CAutoFile() will close the file nRemoved++; }; } result.push_back(Pair("no. blocks removed", itostr(nRemoved))); result.push_back(Pair("hashBestChain", hashBestChain.ToString())); result.push_back(Pair("nBestHeight", itostr(nBestHeight))); // -- need restart, setStakeSeen etc if (nRemoved > 0) result.push_back(Pair("Please restart Taurus", "")); if (nRemoved == nNumber) result.push_back(Pair("result", "success")); else result.push_back(Pair("result", "failure")); return result; }
// pindex must belong to the main branch, i.e. corresponding blocks must be connected // Returns a copy of the game state bool GetGameState(CTxDB &txdb, CBlockIndex *pindex, GameState &outState) { if (!pindex) { outState = GameState(); return true; } if (*pindex->phashBlock == currentState.hashBlock) { outState = currentState; return true; } // Get the latest saved state CGameDB gameDb("cr", txdb); if (gameDb.Read(pindex->nHeight, outState)) { if (outState.nHeight != pindex->nHeight) return error("GetGameState: wrong height"); if (outState.hashBlock != *pindex->phashBlock) return error("GetGameState: wrong hash"); return true; } if (!pindex->IsInMainChain()) return error("GetGameState called for non-main chain"); CBlockIndex *plast = pindex; GameState lastState; for (; plast->pprev; plast = plast->pprev) { if (gameDb.Read(plast->pprev->nHeight, lastState)) break; } // When connecting genesis block, there is no nameindexfull.dat file yet std::auto_ptr<CNameDB> nameDb(pindex == pindexGenesisBlock ? NULL : new CNameDB("r", txdb)); // Integrate steps starting from the last saved state loop { std::vector<CTransaction> vgametx; CBlock block; block.ReadFromDisk(plast); int64 nTax; if (!PerformStep(nameDb.get(), lastState, &block, nTax, outState, vgametx)) return false; if (block.vgametx != vgametx) { printf("Error: GetGameState: computed vgametx is different from the stored one\n"); printf(" block %s (height = %d) vgametx:\n", block.GetHash().ToString().c_str(), plast->nHeight); BOOST_FOREACH (const CTransaction &tx, block.vgametx) { printf(" "); tx.print(); } printf(" computed vgametx (height = %d):\n", outState.nHeight); BOOST_FOREACH (const CTransaction &tx, vgametx) { printf(" "); tx.print(); } return false; }
/** Initialize Gridcoin. * @pre Parameters should be parsed and config file should be read. */ bool AppInit2(ThreadHandlerPtr threads) { // ********************************************************* Step 1: setup #ifdef _MSC_VER // Turn off Microsoft heap dump noise _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); #endif #if _MSC_VER >= 1400 // Disable confusing "helpful" text message on abort, Ctrl-C _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); #endif #ifdef WIN32 // Enable Data Execution Prevention (DEP) // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008 // A failure is non-critical and needs no further attention! #ifndef PROCESS_DEP_ENABLE // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7), // which is not correct. Can be removed, when GCCs winbase.h is fixed! #define PROCESS_DEP_ENABLE 0x00000001 #endif typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD); PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy"); if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE); #endif #ifndef WIN32 umask(077); // Clean shutdown on SIGTERM struct sigaction sa; sa.sa_handler = HandleSIGTERM; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); // Reopen debug.log on SIGHUP struct sigaction sa_hup; sa_hup.sa_handler = HandleSIGHUP; sigemptyset(&sa_hup.sa_mask); sa_hup.sa_flags = 0; sigaction(SIGHUP, &sa_hup, NULL); #endif // ********************************************************* Step 2: parameter interactions // Gridcoin - Check to see if config is empty? if (IsConfigFileEmpty()) { uiInterface.ThreadSafeMessageBox( "Configuration file empty. \n" + _("Please wait for new user wizard to start..."), "", 0); } //6-10-2014: R Halford: Updating Boost version to 1.5.5 to prevent sync issues; print the boost version to verify: //5-04-2018: J Owens: Boost now needs to be 1.65 or higher to avoid thread sleep problems with system clock resets. std::string boost_version = ""; std::ostringstream s; s << boost_version << "Using Boost " << BOOST_VERSION / 100000 << "." // major version << BOOST_VERSION / 100 % 1000 << "." // minior version << BOOST_VERSION % 100 // patch level << "\n"; LogPrintf("Boost Version: %s", s.str()); //Placeholder: Load Remote CPIDs Here nNodeLifespan = GetArg("-addrlifespan", 7); fUseFastIndex = GetBoolArg("-fastindex", false); nMinerSleep = GetArg("-minersleep", 8000); nDerivationMethodIndex = 0; fTestNet = GetBoolArg("-testnet"); if (mapArgs.count("-bind")) { // when specifying an explicit binding address, you want to listen on it // even when -connect or -proxy is specified SoftSetBoolArg("-listen", true); } if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { // when only connecting to trusted nodes, do not seed via DNS, or listen by default SoftSetBoolArg("-dnsseed", false); SoftSetBoolArg("-listen", false); } if (mapArgs.count("-proxy")) { // to protect privacy, do not listen by default if a proxy server is specified SoftSetBoolArg("-listen", false); } if (!GetBoolArg("-listen", true)) { // do not map ports or try to retrieve public IP when not listening (pointless) SoftSetBoolArg("-upnp", false); SoftSetBoolArg("-discover", false); } if (mapArgs.count("-externalip")) { // if an explicit public IP is specified, do not try to find others SoftSetBoolArg("-discover", false); } if (GetBoolArg("-salvagewallet")) { // Rewrite just private keys: rescan to find transactions SoftSetBoolArg("-rescan", true); } if (GetBoolArg("-zapwallettxes", false)) { // -zapwallettx implies a rescan SoftSetBoolArg("-rescan", true); } // Verify testnet is using the testnet directory for the config file: std::string sTestNetSpecificArg = GetArgument("testnetarg","default"); LogPrintf("Using specific arg %s",sTestNetSpecificArg); // ********************************************************* Step 3: parameter-to-internal-flags fDebug=false; if (fDebug) fDebugNet = true; else fDebugNet = GetBoolArg("-debugnet"); if (GetArg("-debug", "false")=="true") { fDebug = true; LogPrintf("Entering debug mode."); } fDebug2 = false; if (GetArg("-debug2", "false")=="true") { fDebug2 = true; LogPrintf("Entering GRC debug mode 2."); } fDebug3 = false; if (GetArg("-debug3", "false")=="true") { fDebug3 = true; LogPrintf("Entering GRC debug mode 3."); } if (GetArg("-debug4", "false")=="true") { fDebug4 = true; LogPrintf("Entering RPC time debug mode"); } fDebug10= (GetArg("-debug10","false")=="true"); #if defined(WIN32) fDaemon = false; #else if(fQtActive) fDaemon = false; else fDaemon = GetBoolArg("-daemon"); #endif if (fDaemon) fServer = true; else fServer = GetBoolArg("-server"); /* force fServer when running without GUI */ if(!fQtActive) fServer = true; fPrintToConsole = GetBoolArg("-printtoconsole"); fPrintToDebugger = GetBoolArg("-printtodebugger"); fLogTimestamps = GetBoolArg("-logtimestamps"); fLogTimestamps = true; if (mapArgs.count("-timeout")) { int nNewTimeout = GetArg("-timeout", 4000); if (nNewTimeout > 0 && nNewTimeout < 600000) nConnectTimeout = nNewTimeout; } if (mapArgs.count("-paytxfee")) { if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"])); if (nTransactionFee > 0.25 * COIN) InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); } fConfChange = GetBoolArg("-confchange", false); fEnforceCanonical = GetBoolArg("-enforcecanonical", true); if (mapArgs.count("-mininput")) { if (!ParseMoney(mapArgs["-mininput"], nMinimumInputValue)) return InitError(strprintf(_("Invalid amount for -mininput=<amount>: '%s'"), mapArgs["-mininput"])); } // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Sanity check if (!InitSanityCheck()) return InitError(_("Initialization sanity check failed. Gridcoin is shutting down.")); // Initialize internal hashing code with SSE/AVX2 optimizations. In the future we will also have ARM/NEON optimizations. std::string sha256_algo = SHA256AutoDetect(); LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo); std::string strDataDir = GetDataDir().string(); std::string strWalletFileName = GetArg("-wallet", "wallet.dat"); // strWalletFileName must be a plain filename without a directory if (strWalletFileName != boost::filesystem::basename(strWalletFileName) + boost::filesystem::extension(strWalletFileName)) return InitError(strprintf(_("Wallet %s resides outside data directory %s."), strWalletFileName, strDataDir)); // Make sure only a single Bitcoin process is using the data directory. boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. if (file) fclose(file); static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (!lock.try_lock()) return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Gridcoin is probably already running."), strDataDir)); #if !defined(WIN32) if (fDaemon) { // Daemonize pid_t pid = fork(); if (pid < 0) { fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); return false; } if (pid > 0) { CreatePidFile(GetPidFile(), pid); // Now that we are forked we can request a shutdown so the parent // exits while the child lives on. StartShutdown(); return true; } pid_t sid = setsid(); if (sid < 0) fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); } #endif ShrinkDebugFile(); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); LogPrintf("Gridcoin version %s (%s)", FormatFullVersion(), CLIENT_DATE); LogPrintf("Using OpenSSL version %s", SSLeay_version(SSLEAY_VERSION)); if (!fLogTimestamps) LogPrintf("Startup time: %s", DateTimeStrFormat("%x %H:%M:%S", GetAdjustedTime())); LogPrintf("Default data directory %s", GetDefaultDataDir().string()); LogPrintf("Used data directory %s", strDataDir); std::ostringstream strErrors; fDevbuildCripple = false; if((CLIENT_VERSION_BUILD != 0) && !fTestNet) { fDevbuildCripple = true; LogPrintf("WARNING: Running development version outside of testnet!\n" "Staking and sending transactions will be disabled."); if( (GetArg("-devbuild", "") == "override") && fDebug ) fDevbuildCripple = false; } if (fDaemon) fprintf(stdout, "Gridcoin server starting\n"); int64_t nStart; // ********************************************************* Step 5: verify database integrity uiInterface.InitMessage(_("Verifying database integrity...")); if (!bitdb.Open(GetDataDir())) { string msg = strprintf(_("Error initializing database environment %s!" " To recover, BACKUP THAT DIRECTORY, then remove" " everything from it except for wallet.dat."), strDataDir); return InitError(msg); } if (GetBoolArg("-salvagewallet")) { // Recover readable keypairs: if (!CWalletDB::Recover(bitdb, strWalletFileName, true)) return false; } if (filesystem::exists(GetDataDir() / strWalletFileName)) { CDBEnv::VerifyResult r = bitdb.Verify(strWalletFileName, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) { string msg = strprintf(_("Warning: wallet.dat corrupt, data salvaged!" " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), strDataDir); uiInterface.ThreadSafeMessageBox(msg, _("Gridcoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); } if (r == CDBEnv::RECOVER_FAIL) return InitError(_("wallet.dat corrupt, salvage failed")); } // ********************************************************* Step 6: network initialization int nSocksVersion = GetArg("-socks", 5); if (nSocksVersion != 4 && nSocksVersion != 5) return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion)); if (mapArgs.count("-onlynet")) { std::set<enum Network> nets; for (auto const& snet : mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet)); nets.insert(net); } for (int n = 0; n < NET_MAX; n++) { enum Network net = (enum Network)n; if (!nets.count(net)) SetLimited(net); } } CService addrProxy; bool fProxy = false; if (mapArgs.count("-proxy")) { addrProxy = CService(mapArgs["-proxy"], 9050); if (!addrProxy.IsValid()) return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); if (!IsLimited(NET_IPV4)) SetProxy(NET_IPV4, addrProxy, nSocksVersion); if (nSocksVersion > 4) { if (!IsLimited(NET_IPV6)) SetProxy(NET_IPV6, addrProxy, nSocksVersion); SetNameProxy(addrProxy, nSocksVersion); } fProxy = true; } // -tor can override normal proxy, -notor disables tor entirely if (!(mapArgs.count("-tor") && mapArgs["-tor"] == "0") && (fProxy || mapArgs.count("-tor"))) { CService addrOnion; if (!mapArgs.count("-tor")) addrOnion = addrProxy; else addrOnion = CService(mapArgs["-tor"], 9050); if (!addrOnion.IsValid()) return InitError(strprintf(_("Invalid -tor address: '%s'"), mapArgs["-tor"])); SetProxy(NET_TOR, addrOnion, 5); SetReachable(NET_TOR); } // see Step 2: parameter interactions for more information about these fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); fNameLookup = GetBoolArg("-dns", true); #ifdef USE_UPNP fUseUPnP = GetBoolArg("-upnp", USE_UPNP); #endif bool fBound = false; if (!fNoListen) { std::string strError; if (mapArgs.count("-bind")) { for (auto const& strBind : mapMultiArgs["-bind"]) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind)); fBound |= Bind(addrBind); } } else { struct in_addr inaddr_any; inaddr_any.s_addr = INADDR_ANY; if (!IsLimited(NET_IPV6)) fBound |= Bind(CService(in6addr_any, GetListenPort()), false); if (!IsLimited(NET_IPV4)) fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound); } if (!fBound) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); } if (mapArgs.count("-externalip")) { for (auto const& strAddr : mapMultiArgs["-externalip"]) { CService addrLocal(strAddr, GetListenPort(), fNameLookup); if (!addrLocal.IsValid()) return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr)); AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL); } } if (mapArgs.count("-reservebalance")) // ppcoin: reserve balance amount { if (!ParseMoney(mapArgs["-reservebalance"], nReserveBalance)) { InitError(_("Invalid amount for -reservebalance=<amount>")); return false; } } for (auto const& strDest : mapMultiArgs["-seednode"]) AddOneShot(strDest); // ********************************************************* Step 7: load blockchain if (!bitdb.Open(GetDataDir())) { string msg = strprintf(_("Error initializing database environment %s!" " To recover, BACKUP THAT DIRECTORY, then remove" " everything from it except for wallet.dat."), strDataDir); return InitError(msg); } if (GetBoolArg("-loadblockindextest")) { CTxDB txdb("r"); txdb.LoadBlockIndex(); PrintBlockTree(); return false; } uiInterface.InitMessage(_("Loading block index...")); LogPrintf("Loading block index..."); nStart = GetTimeMillis(); if (!LoadBlockIndex()) return InitError(_("Error loading blkindex.dat")); // as LoadBlockIndex can take several minutes, it's possible the user // requested to kill bitcoin-qt during the last operation. If so, exit. // As the program has not fully started yet, Shutdown() is possibly overkill. if (fRequestShutdown) { LogPrintf("Shutdown requested. Exiting."); return false; } LogPrintf(" block index %15" PRId64 "ms", GetTimeMillis() - nStart); if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) { PrintBlockTree(); return false; } if (mapArgs.count("-printblock")) { string strMatch = mapArgs["-printblock"]; int nFound = 0; for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) { uint256 hash = (*mi).first; if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) { CBlockIndex* pindex = (*mi).second; CBlock block; block.ReadFromDisk(pindex); block.BuildMerkleTree(); block.print(); LogPrintf(""); nFound++; } } if (nFound == 0) LogPrintf("No blocks matching %s were found", strMatch); return false; } // ********************************************************* Step 8: load wallet uiInterface.InitMessage(_("Loading wallet...")); LogPrintf("Loading wallet..."); nStart = GetTimeMillis(); bool fFirstRun = true; pwalletMain = new CWallet(strWalletFileName); DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); if (nLoadWalletRet != DB_LOAD_OK) { if (nLoadWalletRet == DB_CORRUPT) strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n"; else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) { string msg(_("Warning: error reading wallet.dat! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect.")); uiInterface.ThreadSafeMessageBox(msg, _("Gridcoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); } else if (nLoadWalletRet == DB_TOO_NEW) strErrors << _("Error loading wallet.dat: Wallet requires newer version of Gridcoin") << "\n"; else if (nLoadWalletRet == DB_NEED_REWRITE) { strErrors << _("Wallet needed to be rewritten: restart Gridcoin to complete") << "\n"; LogPrintf("%s", strErrors.str()); return InitError(strErrors.str()); } else strErrors << _("Error loading wallet.dat") << "\n"; } if (GetBoolArg("-upgradewallet", fFirstRun)) { int nMaxVersion = GetArg("-upgradewallet", 0); if (nMaxVersion == 0) // the -upgradewallet without argument case { LogPrintf("Performing wallet upgrade to %i", FEATURE_LATEST); nMaxVersion = CLIENT_VERSION; pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately } else LogPrintf("Allowing wallet upgrade up to %i", nMaxVersion); if (nMaxVersion < pwalletMain->GetVersion()) strErrors << _("Cannot downgrade wallet") << "\n"; pwalletMain->SetMaxVersion(nMaxVersion); } if (fFirstRun) { // Create new keyUser and set as default key RandAddSeedPerfmon(); CPubKey newDefaultKey; if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) { pwalletMain->SetDefaultKey(newDefaultKey); if (!pwalletMain->SetAddressBookName(pwalletMain->vchDefaultKey.GetID(), "")) strErrors << _("Cannot write default address") << "\n"; } } LogPrintf("%s", strErrors.str()); LogPrintf(" wallet %15" PRId64 "ms", GetTimeMillis() - nStart); RegisterWallet(pwalletMain); CBlockIndex *pindexRescan = pindexBest; if (GetBoolArg("-rescan")) pindexRescan = pindexGenesisBlock; else { CWalletDB walletdb(strWalletFileName); CBlockLocator locator; if (walletdb.ReadBestBlock(locator)) pindexRescan = locator.GetBlockIndex(); } if (pindexBest != pindexRescan && pindexBest && pindexRescan && pindexBest->nHeight > pindexRescan->nHeight) { uiInterface.InitMessage(_("Rescanning...")); LogPrintf("Rescanning last %i blocks (from block %i)...", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); nStart = GetTimeMillis(); pwalletMain->ScanForWalletTransactions(pindexRescan, true); LogPrintf(" rescan %15" PRId64 "ms", GetTimeMillis() - nStart); } // ********************************************************* Step 9: import blocks if (mapArgs.count("-loadblock")) { uiInterface.InitMessage(_("Importing blockchain data file.")); for (auto const& strFile : mapMultiArgs["-loadblock"]) { FILE *file = fopen(strFile.c_str(), "rb"); if (file) LoadExternalBlockFile(file); } exit(0); } filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; if (filesystem::exists(pathBootstrap)) { uiInterface.InitMessage(_("Importing bootstrap blockchain data file.")); FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); if (file) { filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LoadExternalBlockFile(file); RenameOver(pathBootstrap, pathBootstrapOld); } } // ********************************************************* Step 10: load peers uiInterface.InitMessage(_("Loading addresses...")); if (fDebug10) LogPrintf("Loading addresses..."); nStart = GetTimeMillis(); { CAddrDB adb; if (!adb.Read(addrman)) LogPrintf("Invalid or missing peers.dat; recreating"); } LogPrintf("Loaded %i addresses from peers.dat %" PRId64 "ms", addrman.size(), GetTimeMillis() - nStart); // ********************************************************* Step 11: start node uiInterface.InitMessage(_("Loading Persisted Data Cache...")); // std::string sOut = ""; if (fDebug3) LogPrintf("Loading admin Messages"); LoadAdminMessages(true,sOut); LogPrintf("Done loading Admin messages"); uiInterface.InitMessage(_("Compute Neural Network Hashes...")); ComputeNeuralNetworkSupermajorityHashes(); LoadCPIDs(); uiInterface.InitMessage(_("Finding first applicable Research Project...")); if (!CheckDiskSpace()) return false; RandAddSeedPerfmon(); //// debug print if (fDebug) { LogPrintf("mapBlockIndex.size() = %" PRIszu, mapBlockIndex.size()); LogPrintf("nBestHeight = %d", nBestHeight); LogPrintf("setKeyPool.size() = %" PRIszu, pwalletMain->setKeyPool.size()); LogPrintf("mapWallet.size() = %" PRIszu, pwalletMain->mapWallet.size()); LogPrintf("mapAddressBook.size() = %" PRIszu, pwalletMain->mapAddressBook.size()); } uiInterface.InitMessage(_("Loading Network Averages...")); if (fDebug3) LogPrintf("Loading network averages"); CBlockIndex* tallyHeight = FindTallyTrigger(pindexBest); if(tallyHeight) TallyResearchAverages(tallyHeight); if (!threads->createThread(StartNode, NULL, "Start Thread")) InitError(_("Error: could not start node")); if (fServer) StartRPCThreads(); // ********************************************************* Step 12: finished uiInterface.InitMessage(_("Done loading")); LogPrintf("Done loading"); if (!strErrors.str().empty()) return InitError(strErrors.str()); // Add wallet transactions that aren't already in a block to mapTransactions pwalletMain->ReacceptWalletTransactions(); int nMismatchSpent; int64_t nBalanceInQuestion; pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion); return true; }
// pNut: list top prime chain within pnut network Value listtopprimes(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "listtopprimes <primechain length> [primechain type]\n" "Returns the list of top prime chains in pnut network.\n" "<primechain length> is integer like 10, 11, 12 etc.\n" "[primechain type] is optional type, among 1CC, 2CC and TWN"); int nPrimeChainLength = params[0].get_int(); unsigned int nPrimeChainType = 0; if (params.size() > 1) { std::string strPrimeChainType = params[1].get_str(); if (strPrimeChainType.compare("1CC") == 0) nPrimeChainType = PRIME_CHAIN_CUNNINGHAM1; else if (strPrimeChainType.compare("2CC") == 0) nPrimeChainType = PRIME_CHAIN_CUNNINGHAM2; else if (strPrimeChainType.compare("TWN") == 0) nPrimeChainType = PRIME_CHAIN_BI_TWIN; else throw runtime_error("Prime chain type must be 1CC, 2CC or TWN."); } // Search for top prime chains unsigned int nRankingSize = 10; // ranking list size unsigned int nSortVectorSize = 64; // vector size for sort operation CBigNum bnPrimeQualify = 0; // minimum qualify value for ranking list vector<pair<CBigNum, uint256> > vSortedByOrigin; for (CBlockIndex* pindex = pindexGenesisBlock; pindex; pindex = pindex->pnext) { if (nPrimeChainLength != (int) TargetGetLength(pindex->nPrimeChainLength)) continue; // length not matching, next block if (nPrimeChainType && nPrimeChainType != pindex->nPrimeChainType) continue; // type not matching, next block CBlock block; block.ReadFromDisk(pindex); // read block CBigNum bnPrimeChainOrigin = CBigNum(block.GetHeaderHash()) * block.bnPrimeChainMultiplier; // compute prime chain origin if (bnPrimeChainOrigin > bnPrimeQualify) vSortedByOrigin.push_back(make_pair(bnPrimeChainOrigin, block.GetHash())); if (vSortedByOrigin.size() >= nSortVectorSize) { // Sort prime chain candidates sort(vSortedByOrigin.begin(), vSortedByOrigin.end()); reverse(vSortedByOrigin.begin(), vSortedByOrigin.end()); // Truncate candidate list while (vSortedByOrigin.size() > nRankingSize) vSortedByOrigin.pop_back(); // Update minimum qualify value for top prime chains bnPrimeQualify = vSortedByOrigin.back().first; } } // Final sort of prime chain candidates sort(vSortedByOrigin.begin(), vSortedByOrigin.end()); reverse(vSortedByOrigin.begin(), vSortedByOrigin.end()); // Truncate candidate list while (vSortedByOrigin.size() > nRankingSize) vSortedByOrigin.pop_back(); // Output top prime chains Array ret; BOOST_FOREACH(const PAIRTYPE(CBigNum, uint256)& item, vSortedByOrigin) { CBigNum bnPrimeChainOrigin = item.first; CBlockIndex* pindex = mapBlockIndex[item.second]; CBlock block; block.ReadFromDisk(pindex); // read block Object entry; entry.push_back(Pair("time", DateTimeStrFormat("%Y-%m-%d %H:%M:%S UTC", pindex->GetBlockTime()).c_str())); entry.push_back(Pair("epoch", (boost::int64_t) pindex->GetBlockTime())); entry.push_back(Pair("height", pindex->nHeight)); entry.push_back(Pair("ismine", pwalletMain->IsMine(block.vtx[0]))); CTxDestination address; entry.push_back(Pair("mineraddress", (block.vtx[0].vout.size() > 1)? "multiple" : ExtractDestination(block.vtx[0].vout[0].scriptPubKey, address)? CBitcoinAddress(address).ToString().c_str() : "invalid")); entry.push_back(Pair("primedigit", (int) bnPrimeChainOrigin.ToString().length())); entry.push_back(Pair("primechain", GetPrimeChainName(pindex->nPrimeChainType, pindex->nPrimeChainLength).c_str())); entry.push_back(Pair("primeorigin", bnPrimeChainOrigin.ToString().c_str())); entry.push_back(Pair("primorialform", GetPrimeOriginPrimorialForm(bnPrimeChainOrigin).c_str())); ret.push_back(entry); } return ret; }
Value scaninput(const Array& params, bool fHelp) { if (fHelp || params.size() > 4 || params.size() < 2) throw runtime_error( "scaninput <txid> <nout> [difficulty] [days]\n" "Scan specified input for suitable kernel solutions.\n" " [difficulty] - upper limit for difficulty, current difficulty by default;\n" " [days] - time window, 365 days by default.\n" ); uint256 hash; hash.SetHex(params[0].get_str()); uint32_t nOut = params[1].get_int(), nBits = GetNextTargetRequired(pindexBest, true), nDays = 365; if (params.size() > 2) { CBigNum bnTarget(nPoWBase); bnTarget *= 1000; bnTarget /= (int) (params[2].get_real() * 1000); nBits = bnTarget.GetCompact(); } if (params.size() > 3) { nDays = params[3].get_int(); } CTransaction tx; uint256 hashBlock = 0; if (GetTransaction(hash, tx, hashBlock)) { if (nOut > tx.vout.size()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Incorrect output number"); if (hashBlock == 0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to find transaction in the blockchain"); CTxDB txdb("r"); CBlock block; CTxIndex txindex; // Load transaction index item if (!txdb.ReadTxIndex(tx.GetHash(), txindex)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to read block index item"); // Read block header if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "CBlock::ReadFromDisk() failed"); uint64_t nStakeModifier = 0; if (!GetKernelStakeModifier(block.GetHash(), nStakeModifier)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No kernel stake modifier generated yet"); std::pair<uint32_t, uint32_t> interval; interval.first = GetTime(); // Only count coins meeting min age requirement if (nStakeMinAge + block.nTime > interval.first) interval.first += (nStakeMinAge + block.nTime - interval.first); interval.second = interval.first + nDays * 86400; SHA256_CTX ctx; GetKernelMidstate(nStakeModifier, block.nTime, txindex.pos.nTxPos - txindex.pos.nBlockPos, tx.nTime, nOut, ctx); std::pair<uint256, uint32_t> solution; if (ScanMidstateForward(ctx, nBits, tx.nTime, tx.vout[nOut].nValue, interval, solution)) { Object r; r.push_back(Pair("hash", solution.first.GetHex())); r.push_back(Pair("time", DateTimeStrFormat(solution.second))); return r; } } else throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); return Value::null; }
Value getstakers(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 4) throw runtime_error( "getstakers <min block> <max block> [total]" "Returns array of stakers in between min and max block, inclusive." " If [total] is provided, outputs an array of stakers with proportionate amounts. Can be used as input to sendmany for dividends."); int nHeight = params[0].get_int(); int max = params[1].get_int(); double amount = 0.0, amountEach = 0.0; int amtProvided = 0; int iCount = 0; std::string outStr(" '{"); if (max < nHeight) throw runtime_error("Max Block is less than Min Block."); if (nHeight < 20161 || nHeight > nBestHeight) throw runtime_error("Min Block number out of range. (First PoS Block: 20,161)"); if (max < 0 || max > nBestHeight) throw runtime_error("Max Block number out of range."); if(params.size() >= 3) { amount = params[2].get_real(); if( amount / (max - nHeight + 1) < 1) throw runtime_error("Amount is less than 1 BTCD per staker."); amountEach = amount/(max-nHeight+1); amtProvided = 1; } //Find Min. Block CBlock block; CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; while (pblockindex->nHeight > nHeight) pblockindex = pblockindex->pprev; CTransaction tx; CTxOut txout; uint256 txHash = 0; uint256 hash; vector<CTxDestination> addresses; int nRequired; txnouttype type; Object entry; Object result; std::ostringstream s; s << amountEach; std::string strAmount = s.str(); for(iCount = nHeight; iCount <= max; iCount++) { hash = *pblockindex->phashBlock; pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex, true); tx = block.vtx[1]; txout = tx.vout[1]; txHash = tx.GetHash(); addresses.clear(); ExtractDestinations(txout.scriptPubKey, type, addresses, nRequired); outStr += std::string("\"") + CBitcoinAddress(addresses[0]).ToString() + std::string("\""); if(amtProvided == 1) { outStr += std::string(": ") + strAmount; if( iCount != max) outStr += std::string(", "); } else if( iCount != max) outStr += std::string(", "); pblockindex = pblockindex->pnext; } outStr += std::string("}' "); char *finalString = (char*)outStr.c_str(); result.push_back(Pair("Addresses:", std::string(unstringify(finalString)))); return result; }
void ProfitExplorerPage::loadStakeChart(bool firstRun) { if(fShutdown) return; nTimeData.clear(); netStakeData.clear(); myStakeData.clear(); difficultyData.clear(); velTimeData.clear(); velAmountData.clear(); // go back this many blocks max int max = ui->spinBox->value(); int i = 0; //BOOST_REVERSE_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& b, mapBlockIndex) //{ // if(i >= max) // break; CBlockIndex* pindex = pindexBest; while(i < max && pindex != NULL) { //CBlockIndex* pindex = b.second; if(pindex->IsProofOfStake()) { nTimeData.append(pindex->nTime); netStakeData.append(pindex->nMint / COIN); // Read the block in and check if the coinstake is ours CBlock block; block.ReadFromDisk(pindex, true); if(block.IsProofOfStake()) // this should always be true here { velTimeData.append(pindex->nTime); double blockOutAmount = 0; for(int j=0; j<block.vtx.size(); j++) { blockOutAmount += block.vtx[j].GetValueOut() / COIN; } velAmountData.append(blockOutAmount); difficultyData.append(GetDifficulty(pindex)); if(pwalletMain->IsMine(block.vtx[1])) { myStakeData.append(pindex->nMint / COIN); } else { myStakeData.append(0); } } else { myStakeData.append(0); // should never happen } i = i + 1; } pindex = pindex->pprev; //++i; } if(!firstRun) { uint64_t nMinWeight = 0, nMaxWeight = 0, nWeight = 0; pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight); uint64_t nNetworkWeight = 0; if(pindexBest) nNetworkWeight = GetPoSKernelPS(); bool staking = nLastCoinStakeSearchInterval && nWeight; int nExpectedTime = staking ? (nTargetSpacing * nNetworkWeight / nWeight) : -1; ui->stakingLabel->setText(staking ? "Enabled" : "Disabled"); if(pindexBest) ui->difficultyLabel->setText(QString::number(GetDifficulty(GetLastBlockIndex(pindexBest, true)))); ui->weightLabel->setText(QString::number(nWeight)); ui->netWeightLabel->setText(QString::number(nNetworkWeight)); ui->timeToStakeLabel->setText(QString::number(nExpectedTime) + " secs"); } //qDebug() << "Stake blocks processed:"; //qDebug() << i; ui->customPlot->clearPlottables(); ui->customPlot->clearGraphs(); ui->customPlot->clearItems(); ui->customPlot->addGraph(); ui->customPlot->graph(0)->setPen(QPen(QColor(206, 206, 206))); // line color green for first graph ui->customPlot->graph(0)->setBrush(QBrush(QColor(206, 206, 206, 20))); // first graph will be filled with translucent green ui->customPlot->addGraph(); ui->customPlot->graph(1)->setPen(QPen(QColor(76, 255, 0))); // line color red for second graph ui->customPlot->graph(1)->setBrush(QBrush(QColor(76, 255, 0, 20))); if(ui->networkCheckBox->isChecked()) ui->customPlot->graph(0)->setData(nTimeData, netStakeData); ui->customPlot->graph(1)->setData(nTimeData, myStakeData); //ui->customPlot->xAxis->setRangeLower(nTimeData.first()); //ui->customPlot->xAxis->setRangeUpper(nTimeData.last()); QLinearGradient plotGradient; plotGradient.setStart(0, 0); plotGradient.setFinalStop(0, 350); plotGradient.setColorAt(0, QColor(10, 10, 10)); plotGradient.setColorAt(1, QColor(0, 0, 0)); ui->customPlot->setBackground(plotGradient); ui->customPlot->xAxis->grid()->setVisible(false); ui->customPlot->yAxis->grid()->setVisible(false); ui->customPlot->xAxis->grid()->setSubGridVisible(false); ui->customPlot->yAxis->grid()->setSubGridVisible(false); ui->customPlot->xAxis->setAutoTickStep(true); ui->customPlot->xAxis->setTickStep(3600 * 24); // 24 hr tickstep ui->customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime); ui->customPlot->xAxis->setDateTimeSpec(Qt::UTC); ui->customPlot->xAxis->setDateTimeFormat("dd. MMM hh:mm"); ui->customPlot->xAxis->setTickLabelRotation(15); ui->customPlot->xAxis->setTickLabelColor(QColor(137, 140, 146)); ui->customPlot->yAxis->setTickLabelColor(QColor(137, 140, 146)); ui->customPlot->rescaleAxes(); ui->customPlot->xAxis->setLabelColor(QColor(137, 140, 146)); ui->customPlot->yAxis->setLabelColor(QColor(137, 140, 146)); ui->customPlot->yAxis->setLabel("$XQN Minted"); ui->customPlot->xAxis->setLabel("Stake Block Generation Time"); ui->customPlot->replot(); ui->difficultyPlot->clearPlottables(); ui->difficultyPlot->clearGraphs(); ui->difficultyPlot->clearItems(); ui->difficultyPlot->addGraph(); ui->difficultyPlot->graph(0)->setPen(QPen(QColor(76, 255, 0))); // line color green for first graph ui->difficultyPlot->graph(0)->setBrush(QBrush(QColor(76, 255, 0, 20))); // first graph will be filled with translucent green ui->difficultyPlot->graph(0)->setData(nTimeData, difficultyData); ui->difficultyPlot->xAxis->setRangeLower(nTimeData.first()); ui->difficultyPlot->xAxis->setRangeUpper(nTimeData.last()); QLinearGradient diffPlotGradient; diffPlotGradient.setStart(0, 0); diffPlotGradient.setFinalStop(0, 350); diffPlotGradient.setColorAt(0, QColor(10, 10, 10)); diffPlotGradient.setColorAt(1, QColor(0, 0, 0)); ui->difficultyPlot->setBackground(diffPlotGradient); ui->difficultyPlot->xAxis->grid()->setVisible(false); ui->difficultyPlot->yAxis->grid()->setVisible(false); ui->difficultyPlot->xAxis->grid()->setSubGridVisible(false); ui->difficultyPlot->yAxis->grid()->setSubGridVisible(false); ui->difficultyPlot->xAxis->setAutoTickStep(false); ui->difficultyPlot->xAxis->setTickStep(3600 * 24); // 24 hr tickstep ui->difficultyPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime); ui->difficultyPlot->xAxis->setDateTimeSpec(Qt::UTC); ui->difficultyPlot->xAxis->setDateTimeFormat("dd. MMM hh:mm"); ui->difficultyPlot->xAxis->setTickLabelRotation(15); ui->difficultyPlot->xAxis->setTickLabelColor(QColor(137, 140, 146)); ui->difficultyPlot->yAxis->setTickLabelColor(QColor(137, 140, 146)); ui->difficultyPlot->rescaleAxes(); ui->difficultyPlot->yAxis->setTickStep(0.00005); ui->difficultyPlot->xAxis->setLabelColor(QColor(137, 140, 146)); ui->difficultyPlot->yAxis->setLabelColor(QColor(137, 140, 146)); ui->difficultyPlot->yAxis->setLabel("Difficulty"); ui->difficultyPlot->xAxis->setTickLabels(false); //ui->difficultyPlot->xAxis->setLabel("Stake Block Generation Time"); ui->difficultyPlot->replot(); ui->velocityPlot->clearPlottables(); ui->velocityPlot->clearGraphs(); ui->velocityPlot->clearItems(); ui->velocityPlot->addGraph(); ui->velocityPlot->graph(0)->setPen(QPen(QColor(76, 255, 0))); // line color green for first graph ui->velocityPlot->graph(0)->setBrush(QBrush(QColor(76, 255, 0, 20))); // first graph will be filled with translucent green ui->velocityPlot->graph(0)->setData(velTimeData, velAmountData); ui->velocityPlot->xAxis->setRangeLower(velTimeData.first()); ui->velocityPlot->xAxis->setRangeUpper(velTimeData.last()); QLinearGradient velPlotGradient; velPlotGradient.setStart(0, 0); velPlotGradient.setFinalStop(0, 150); velPlotGradient.setColorAt(0, QColor(10, 10, 10)); velPlotGradient.setColorAt(1, QColor(0, 0, 0)); ui->velocityPlot->setBackground(velPlotGradient); ui->velocityPlot->xAxis->grid()->setVisible(false); ui->velocityPlot->yAxis->grid()->setVisible(false); ui->velocityPlot->xAxis->grid()->setSubGridVisible(false); ui->velocityPlot->yAxis->grid()->setSubGridVisible(false); ui->velocityPlot->xAxis->setAutoTickStep(false); ui->velocityPlot->xAxis->setTickStep(3600 * 24); // 24 hr tickstep ui->velocityPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime); ui->velocityPlot->xAxis->setDateTimeSpec(Qt::UTC); ui->velocityPlot->xAxis->setDateTimeFormat("dd. MMM hh:mm"); ui->velocityPlot->xAxis->setTickLabelRotation(15); ui->velocityPlot->xAxis->setTickLabelColor(QColor(137, 140, 146)); ui->velocityPlot->yAxis->setTickLabelColor(QColor(137, 140, 146)); ui->velocityPlot->yAxis->setScaleType(QCPAxis::stLogarithmic); ui->velocityPlot->yAxis->setTickStep(1000); ui->velocityPlot->xAxis->setLabelColor(QColor(137, 140, 146)); ui->velocityPlot->yAxis->setLabelColor(QColor(137, 140, 146)); ui->velocityPlot->yAxis->setLabel("$XQN"); ui->velocityPlot->xAxis->setTickLabels(false); ui->velocityPlot->xAxis->setLabel("Financial Velocity"); ui->velocityPlot->rescaleAxes(); ui->velocityPlot->replot(); }
bool CTxDB::LoadBlockIndex() { if (mapBlockIndex.size() > 0) { // Already loaded once in this session. It can happen during migration // from BDB. return true; } #ifdef WIN32 const int #ifdef _DEBUG nREFRESH = 2000; // generally resfresh rates are chosen to give ~1 update/sec #else // seems to be slowing down?? nREFRESH = 12000; #endif int nMaxHeightGuess = 1, nCounter = 0, nRefresh = nREFRESH; ::int64_t n64MsStartTime = GetTimeMillis(); #endif // The block index is an in-memory structure that maps hashes to on-disk // locations where the contents of the block can be found. Here, we scan it // out of the DB and into mapBlockIndex. leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); // Seek to start key. CDataStream ssStartKey(SER_DISK, CLIENT_VERSION); ssStartKey << make_pair(string("blockindex"), uint256(0)); iterator->Seek(ssStartKey.str()); // Now read each entry. while (iterator->Valid()) { // Unpack keys and values. CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.write(iterator->key().data(), iterator->key().size()); CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.write(iterator->value().data(), iterator->value().size()); string strType; ssKey >> strType; // Did we reach the end of the data to read? if (fRequestShutdown || strType != "blockindex") break; CDiskBlockIndex diskindex; ssValue >> diskindex; uint256 blockHash = diskindex.GetBlockHash(); if ( 0 == blockHash ) { if (fPrintToConsole) (void)printf( "Error? at nHeight=%d" "\n" "", diskindex.nHeight ); continue; //? } // Construct block index object CBlockIndex * pindexNew = InsertBlockIndex(blockHash); // what if null? Can't be, since blockhash is known to be != 0 //if( NULL == pindexNew ) // ??? //{ // iterator->Next(); // continue; //} pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); pindexNew->pnext = InsertBlockIndex(diskindex.hashNext); pindexNew->nFile = diskindex.nFile; pindexNew->nBlockPos = diskindex.nBlockPos; pindexNew->nHeight = diskindex.nHeight; pindexNew->nMint = diskindex.nMint; pindexNew->nMoneySupply = diskindex.nMoneySupply; pindexNew->nFlags = diskindex.nFlags; pindexNew->nStakeModifier = diskindex.nStakeModifier; pindexNew->prevoutStake = diskindex.prevoutStake; pindexNew->nStakeTime = diskindex.nStakeTime; pindexNew->hashProofOfStake = diskindex.hashProofOfStake; pindexNew->nVersion = diskindex.nVersion; pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; // Watch for genesis block if( (0 == diskindex.nHeight) && (NULL != pindexGenesisBlock) ) { if (fPrintToConsole) (void)printf( "Error? an extra null block???" "\n" "" ); } if ( (0 == diskindex.nHeight) && // ought to be faster than a hash check!? (NULL == pindexGenesisBlock) ) { if (blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))// check anyway, but only if block 0 { pindexGenesisBlock = pindexNew; /************* #ifdef WIN32 if (fPrintToConsole) (void)printf( "Found block 0 at nCounter=%d" "\n" "", nCounter ); #endif *************/ } else { if (fPrintToConsole) (void)printf( "Error? a extra genesis block with the wrong hash???" "\n" "" ); } } // there seem to be 2 errant blocks? else { if( (NULL != pindexGenesisBlock) && (0 == diskindex.nHeight) ) { if (fPrintToConsole) (void)printf( "Error? a extra genesis null block???" "\n" "" ); } } //if (!pindexNew->CheckIndex()) // as it stands, this never fails??? So why bother????? //{ // delete iterator; // return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight); //} // NovaCoin: build setStakeSeen if (pindexNew->IsProofOfStake()) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); #ifdef WIN32 ++nCounter; // could "guess at the max nHeight & %age against the loop count // to "hone in on" the %age done. // Towards the end it ought to be pretty accurate. if( nMaxHeightGuess < pindexNew->nHeight ) { nMaxHeightGuess = pindexNew->nHeight; } if( 0 == ( nCounter % nRefresh ) ) // every nRefresh-th time through the loop { float // these #s are just to slosh the . around dEstimate = float( ( 100.0 * nCounter ) / nMaxHeightGuess ); std::string sGutsNoise = strprintf( "%7d (%3.2f%%)" "", nCounter, //pindexNew->nHeight, dEstimate > 100.0? 100.0: dEstimate ); if (fPrintToConsole) { /**************** (void)printf( "%s" " " "", sGutsNoise.c_str() ); ****************/ DoProgress( nCounter, nMaxHeightGuess, n64MsStartTime ); //(void)printf( // "\r" // ); } #ifdef QT_GUI // uiInterface.InitMessage( sGutsNoise.c_str() ); #endif } #endif iterator->Next(); } delete iterator; if (fRequestShutdown) return true; #ifdef WIN32 if (fPrintToConsole) (void)printf( "\n" ); #ifdef QT_GUI uiInterface.InitMessage(_("<b>...done.</b>")); #endif #endif // <<<<<<<<< #ifdef WIN32 if (fPrintToConsole) (void)printf( "Sorting by height...\n" ); #ifdef QT_GUI uiInterface.InitMessage( _("Sorting by height...") ); #endif nCounter = 0; #endif // Calculate bnChainTrust { LOCK(cs_main); vector< pair< int, CBlockIndex*> > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); //vSortedByHeight.resize( mapBlockIndex.size() ); int nUpdatePeriod = 10000; BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { CBlockIndex * pindex = item.second; vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); #ifdef WIN32 ++nCounter; if( 0 == (nCounter % nUpdatePeriod) ) { #ifdef QT_GUI uiInterface.InitMessage( strprintf( _("%7d"), nCounter ) ); #else if (fPrintToConsole) printf( "%7d\r", nCounter ); #endif } #endif } sort(vSortedByHeight.begin(), vSortedByHeight.end()); #ifdef WIN32 if (fPrintToConsole) (void)printf( "\ndone\nChecking stake checksums...\n" ); #ifdef _DEBUG nUpdatePeriod /= 4; // speed up update for debug mode #else nUpdatePeriod *= 5; // slow down update for release mode #endif #ifdef QT_GUI uiInterface.InitMessage( _("done") ); uiInterface.InitMessage( _("Checking stake checksums...") ); #endif nCounter = 0; #endif BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; pindex->nPosBlockCount = ( pindex->pprev ? pindex->pprev->nPosBlockCount : 0 ) + ( pindex->IsProofOfStake() ? 1 : 0 ); pindex->nBitsMA = pindex->IsProofOfStake() ? GetProofOfWorkMA(pindex->pprev) : 0; pindex->bnChainTrust = (pindex->pprev ? pindex->pprev->bnChainTrust : CBigNum(0)) + pindex->GetBlockTrust(); // NovaCoin: calculate stake modifier checksum pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex); if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum)) return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016" PRIx64, pindex->nHeight, pindex->nStakeModifier); #ifdef WIN32 ++nCounter; if( 0 == (nCounter % nUpdatePeriod) ) { #ifdef QT_GUI uiInterface.InitMessage( strprintf( _("%7d"), nCounter ) ); #else if (fPrintToConsole) printf( "%7d\r", nCounter ); #endif } #endif } } #ifdef WIN32 if (fPrintToConsole) (void)printf( "\ndone\n" "Read best chain\n" ); #ifdef QT_GUI uiInterface.InitMessage( _("...done") ); uiInterface.InitMessage( _("Read best chain") ); #endif #endif // Load hashBestChain pointer to end of best chain if (!ReadHashBestChain(hashBestChain)) { if (pindexGenesisBlock == NULL) return true; return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded"); } if (!mapBlockIndex.count(hashBestChain)) return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index"); pindexBest = mapBlockIndex[hashBestChain]; nBestHeight = pindexBest->nHeight; bnBestChainTrust = pindexBest->bnChainTrust; printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%s date=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str(), DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); // NovaCoin: load hashSyncCheckpoint if( !fTestNet ) { if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint)) return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded"); printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str() ); } // Load bnBestInvalidTrust, OK if it doesn't exist ReadBestInvalidTrust(bnBestInvalidTrust); // Verify blocks in the best chain int nCheckLevel = GetArg("-checklevel", 1); int nCheckDepth = GetArg( "-checkblocks", 750); if (nCheckDepth == 0) nCheckDepth = 1000000000; // suffices until the year 19000 if (nCheckDepth > nBestHeight) nCheckDepth = nBestHeight; #ifdef WIN32 nCounter = 0; //#ifdef _MSC_VER #ifdef _DEBUG /**************** const int nMINUTESperBLOCK = 1, // or whatever you want to do in this *coin nMINUTESperHOUR = 60, nBLOCKSperHOUR = nMINUTESperHOUR / nMINUTESperBLOCK, nHOURStoCHECK = 1, //12, // this could be a variable nBLOCKSinLASTwhateverHOURS = nBLOCKSperHOUR * nHOURStoCHECK; nCheckDepth = nBLOCKSinLASTwhateverHOURS; ****************/ #endif //#endif #ifdef QT_GUI std::string sX; uiInterface.InitMessage( strprintf( _("Verifying the last %i blocks at level %i"), nCheckDepth, nCheckLevel ).c_str() ); #endif #endif printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); CBlockIndex* pindexFork = NULL; map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos; for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) { if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) break; CBlock block; if (!block.ReadFromDisk(pindex)) return error("LoadBlockIndex() : block.ReadFromDisk failed"); // check level 1: verify block validity // check level 7: verify block signature too if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6))) { printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); pindexFork = pindex->pprev; } // check level 2: verify transaction index validity if (nCheckLevel>1) { pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos); mapBlockPos[pos] = pindex; BOOST_FOREACH(const CTransaction &tx, block.vtx) { uint256 hashTx = tx.GetHash(); CTxIndex txindex; if (ReadTxIndex(hashTx, txindex)) { // check level 3: checker transaction hashes if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos) { // either an error or a duplicate transaction CTransaction txFound; if (!txFound.ReadFromDisk(txindex.pos)) { printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str()); pindexFork = pindex->pprev; } else if (txFound.GetHash() != hashTx) // not a duplicate tx { printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str()); pindexFork = pindex->pprev; } } // check level 4: check whether spent txouts were spent within the main chain unsigned int nOutput = 0; if (nCheckLevel>3) { BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent) { if (!txpos.IsNull()) { pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos); if (!mapBlockPos.count(posFind)) { printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str()); pindexFork = pindex->pprev; } // check level 6: check whether spent txouts were spent by a valid transaction that consume them if (nCheckLevel>5) { CTransaction txSpend; if (!txSpend.ReadFromDisk(txpos)) { printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } else if (!txSpend.CheckTransaction()) { printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } else { bool fFound = false; BOOST_FOREACH(const CTxIn &txin, txSpend.vin) if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput) fFound = true; if (!fFound) { printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } } } } ++nOutput; } } }
bool CTxDB::LoadBlockIndex() { if (!LoadBlockIndexGuts()) return false; if (fRequestShutdown) return true; // Calculate bnChainTrust vector<pair<int, CBlockIndex*> > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { CBlockIndex* pindex = item.second; vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); } sort(vSortedByHeight.begin(), vSortedByHeight.end()); BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; pindex->bnChainTrust = (pindex->pprev ? pindex->pprev->bnChainTrust : 0) + pindex->GetBlockTrust(); // ppcoin: calculate stake modifier checksum pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex); if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum)) return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier); } // Load hashBestChain pointer to end of best chain if (!ReadHashBestChain(hashBestChain)) { if (pindexGenesisBlock == NULL) return true; return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded"); } if (!mapBlockIndex.count(hashBestChain)) return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index"); pindexBest = mapBlockIndex[hashBestChain]; nBestHeight = pindexBest->nHeight; bnBestChainTrust = pindexBest->bnChainTrust; printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%s date=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainTrust.ToString().c_str(), DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); // ppcoin: load hashSyncCheckpoint if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint)) return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded"); printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str()); // Load bnBestInvalidTrust, OK if it doesn't exist ReadBestInvalidTrust(bnBestInvalidTrust); // Verify blocks in the best chain int nCheckLevel = GetArg("-checklevel", 1); int nCheckDepth = GetArg( "-checkblocks", 2500); if (nCheckDepth == 0) nCheckDepth = 1000000000; // suffices until the year 19000 if (nCheckDepth > nBestHeight) nCheckDepth = nBestHeight; printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); CBlockIndex* pindexFork = NULL; map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos; for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) { if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) break; CBlock block; if (!block.ReadFromDisk(pindex)) return error("LoadBlockIndex() : block.ReadFromDisk failed"); // check level 1: verify block validity if (nCheckLevel>0 && !block.CheckBlock()) { printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str()); pindexFork = pindex->pprev; } // check level 2: verify transaction index validity if (nCheckLevel>1) { pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos); mapBlockPos[pos] = pindex; BOOST_FOREACH(const CTransaction &tx, block.vtx) { uint256 hashTx = tx.GetHash(); CTxIndex txindex; if (ReadTxIndex(hashTx, txindex)) { // check level 3: checker transaction hashes if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos) { // either an error or a duplicate transaction CTransaction txFound; if (!txFound.ReadFromDisk(txindex.pos)) { printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str()); pindexFork = pindex->pprev; } else if (txFound.GetHash() != hashTx) // not a duplicate tx { printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str()); pindexFork = pindex->pprev; } } // check level 4: check whether spent txouts were spent within the main chain unsigned int nOutput = 0; if (nCheckLevel>3) { BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent) { if (!txpos.IsNull()) { pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos); if (!mapBlockPos.count(posFind)) { printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str()); pindexFork = pindex->pprev; } // check level 6: check whether spent txouts were spent by a valid transaction that consume them if (nCheckLevel>5) { CTransaction txSpend; if (!txSpend.ReadFromDisk(txpos)) { printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } else if (!txSpend.CheckTransaction()) { printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } else { bool fFound = false; BOOST_FOREACH(const CTxIn &txin, txSpend.vin) if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput) fFound = true; if (!fFound) { printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput); pindexFork = pindex->pprev; } } } } nOutput++; } } }
Value getblockbynumber(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "getblockbynumber <number> [txinfo]\n" "txinfo optional to print more detailed tx info\n" "Returns details of a block with given block-number."); int nHeight = params[0].get_int(); if (nHeight < 0 || nHeight > nBestHeight) throw runtime_error("Block number out of range."); if (nNodeMode == NT_THIN) { if (!fThinFullIndex && pindexRear && nHeight < pindexRear->nHeight) { CDiskBlockThinIndex diskindex; uint256 hashPrev = pindexRear->GetBlockHash(); // -- find closest checkpoint Checkpoints::MapCheckpoints& checkpoints = (fTestNet ? Checkpoints::mapCheckpointsTestnet : Checkpoints::mapCheckpoints); Checkpoints::MapCheckpoints::reverse_iterator rit; for (rit = checkpoints.rbegin(); rit != checkpoints.rend(); ++rit) { if (rit->first < nHeight) break; hashPrev = rit->second; }; CTxDB txdb("r"); while (hashPrev != 0) { if (!txdb.ReadBlockThinIndex(hashPrev, diskindex)) throw runtime_error("Read header from db failed.\n"); if (diskindex.nHeight == nHeightFilteredNeeded) return diskBlockThinIndexToJSON(diskindex); hashPrev = diskindex.hashPrev; }; throw runtime_error("block not found."); }; CBlockThin block; std::map<uint256, CBlockThinIndex*>::iterator mi = mapBlockThinIndex.find(hashBestChain); if (mi != mapBlockThinIndex.end()) { CBlockThinIndex* pblockindex = mi->second; while (pblockindex->pprev && pblockindex->nHeight > nHeight) pblockindex = pblockindex->pprev; if (nHeight != pblockindex->nHeight) { throw runtime_error("block not in chain index."); } return blockHeaderToJSON(block, pblockindex); } else { throw runtime_error("hashBestChain not in chain index."); } }; CBlock block; CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; while (pblockindex->nHeight > nHeight) pblockindex = pblockindex->pprev; uint256 hash = *pblockindex->phashBlock; pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex, true); return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); }
bool CreateCoinStake( CBlock &blocknew, CKey &key, vector<const CWalletTx*> &StakeInputs, uint64_t &CoinAge, CWallet &wallet, CBlockIndex* pindexPrev ) { int64_t CoinWeight; CBigNum StakeKernelHash; CTxDB txdb("r"); int64_t StakeWeightSum = 0; double StakeValueSum = 0; int64_t StakeWeightMin=MAX_MONEY; int64_t StakeWeightMax=0; uint64_t StakeCoinAgeSum=0; double StakeDiffSum = 0; double StakeDiffMax = 0; CTransaction &txnew = blocknew.vtx[1]; // second tx is coinstake //initialize the transaction txnew.nTime = blocknew.nTime & (~STAKE_TIMESTAMP_MASK); txnew.vin.clear(); txnew.vout.clear(); // Choose coins to use set <pair <const CWalletTx*,unsigned int> > CoinsToStake; int64_t BalanceToStake = wallet.GetBalance(); int64_t nValueIn = 0; //Request all the coins here, check reserve later if ( BalanceToStake<=0 || !wallet.SelectCoinsForStaking(BalanceToStake*2, txnew.nTime, CoinsToStake, nValueIn) ) { LOCK(MinerStatus.lock); MinerStatus.ReasonNotStaking+=_("No coins; "); if (fDebug) LogPrintf("CreateCoinStake: %s",MinerStatus.ReasonNotStaking); return false; } BalanceToStake -= nReserveBalance; if(fDebug2) LogPrintf("\nCreateCoinStake: Staking nTime/16= %d Bits= %u", txnew.nTime/16,blocknew.nBits); for(const auto& pcoin : CoinsToStake) { const CTransaction &CoinTx =*pcoin.first; //transaction that produced this coin unsigned int CoinTxN =pcoin.second; //index of this coin inside it CTxIndex txindex; { LOCK2(cs_main, wallet.cs_wallet); if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex)) continue; //error? } CBlock CoinBlock; //Block which contains CoinTx { LOCK2(cs_main, wallet.cs_wallet); if (!CoinBlock.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) continue; } // only count coins meeting min age requirement if (CoinBlock.GetBlockTime() + nStakeMinAge > txnew.nTime) continue; if (CoinTx.vout[CoinTxN].nValue > BalanceToStake) continue; { int64_t nStakeValue= CoinTx.vout[CoinTxN].nValue; StakeValueSum += nStakeValue /(double)COIN; //crazy formula... // todo: clean this // todo reuse calculated value for interst CBigNum bn = CBigNum(nStakeValue) * (blocknew.nTime-CoinTx.nTime) / CENT; bn = bn * CENT / COIN / (24 * 60 * 60); StakeCoinAgeSum += bn.getuint64(); } if(blocknew.nVersion==7) { NetworkTimer(); CoinWeight = CalculateStakeWeightV3(CoinTx,CoinTxN,GlobalCPUMiningCPID); StakeKernelHash= CalculateStakeHashV3(CoinBlock,CoinTx,CoinTxN,txnew.nTime,GlobalCPUMiningCPID,mdPORNonce); } else { uint64_t StakeModifier = 0; if(!FindStakeModifierRev(StakeModifier,pindexPrev)) continue; CoinWeight = CalculateStakeWeightV8(CoinTx,CoinTxN,GlobalCPUMiningCPID); StakeKernelHash= CalculateStakeHashV8(CoinBlock,CoinTx,CoinTxN,txnew.nTime,StakeModifier,GlobalCPUMiningCPID); } CBigNum StakeTarget; StakeTarget.SetCompact(blocknew.nBits); StakeTarget*=CoinWeight; StakeWeightSum += CoinWeight; StakeWeightMin=std::min(StakeWeightMin,CoinWeight); StakeWeightMax=std::max(StakeWeightMax,CoinWeight); double StakeKernelDiff = GetBlockDifficulty(StakeKernelHash.GetCompact())*CoinWeight; StakeDiffSum += StakeKernelDiff; StakeDiffMax = std::max(StakeDiffMax,StakeKernelDiff); if (fDebug2) { int64_t RSA_WEIGHT = GetRSAWeightByBlock(GlobalCPUMiningCPID); LogPrintf( "CreateCoinStake: V%d Time %.f, Por_Nonce %.f, Bits %jd, Weight %jd\n" " RSA_WEIGHT %.f\n" " Stk %72s\n" " Trg %72s\n" " Diff %0.7f of %0.7f\n", blocknew.nVersion, (double)txnew.nTime, mdPORNonce, (intmax_t)blocknew.nBits,(intmax_t)CoinWeight, (double)RSA_WEIGHT, StakeKernelHash.GetHex().c_str(), StakeTarget.GetHex().c_str(), StakeKernelDiff, GetBlockDifficulty(blocknew.nBits) ); } if( StakeKernelHash <= StakeTarget ) { // Found a kernel LogPrintf("\nCreateCoinStake: Found Kernel;\n"); blocknew.nNonce= mdPORNonce; vector<valtype> vSolutions; txnouttype whichType; CScript scriptPubKeyOut; CScript scriptPubKeyKernel; scriptPubKeyKernel = CoinTx.vout[CoinTxN].scriptPubKey; if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) { LogPrintf("CreateCoinStake: failed to parse kernel\n"); break; } if (whichType == TX_PUBKEYHASH) // pay to address type { // convert to pay to public key type if (!wallet.GetKey(uint160(vSolutions[0]), key)) { LogPrintf("CreateCoinStake: failed to get key for kernel type=%d\n", whichType); break; // unable to find corresponding public key } scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG; } else if (whichType == TX_PUBKEY) // pay to public key type { valtype& vchPubKey = vSolutions[0]; if (!wallet.GetKey(Hash160(vchPubKey), key) || key.GetPubKey() != vchPubKey) { LogPrintf("CreateCoinStake: failed to get key for kernel type=%d\n", whichType); break; // unable to find corresponding public key } scriptPubKeyOut = scriptPubKeyKernel; } else { LogPrintf("CreateCoinStake: no support for kernel type=%d\n", whichType); break; // only support pay to public key and pay to address } txnew.vin.push_back(CTxIn(CoinTx.GetHash(), CoinTxN)); StakeInputs.push_back(pcoin.first); if (!txnew.GetCoinAge(txdb, CoinAge)) return error("CreateCoinStake: failed to calculate coin age"); int64_t nCredit = CoinTx.vout[CoinTxN].nValue; txnew.vout.push_back(CTxOut(0, CScript())); // First Must be empty txnew.vout.push_back(CTxOut(nCredit, scriptPubKeyOut)); //txnew.vout.push_back(CTxOut(0, scriptPubKeyOut)); LogPrintf("CreateCoinStake: added kernel type=%d credit=%f\n", whichType,CoinToDouble(nCredit)); LOCK(MinerStatus.lock); MinerStatus.KernelsFound++; MinerStatus.KernelDiffMax = 0; MinerStatus.KernelDiffSum = StakeDiffSum; return true; } } LOCK(MinerStatus.lock); MinerStatus.WeightSum = StakeWeightSum; MinerStatus.ValueSum = StakeValueSum; MinerStatus.WeightMin=StakeWeightMin; MinerStatus.WeightMax=StakeWeightMax; MinerStatus.CoinAgeSum=StakeCoinAgeSum; MinerStatus.KernelDiffMax = std::max(MinerStatus.KernelDiffMax,StakeDiffMax); MinerStatus.KernelDiffSum = StakeDiffSum; MinerStatus.nLastCoinStakeSearchInterval= txnew.nTime; return false; }