Value setbestblockbyheight(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "setbestblockbyheight <height>\n" "Sets the tip of the chain th block at <height>."); int nHeight = params[0].get_int(); if (nHeight < 0 || nHeight > nBestHeight) throw runtime_error("Block height out of range."); if (nNodeMode == NT_THIN) { throw runtime_error("Must be in full mode."); }; CBlock block; CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; while (pblockindex->nHeight > nHeight) pblockindex = pblockindex->pprev; uint256 hash = *pblockindex->phashBlock; pblockindex = mapBlockIndex[hash]; block.ReadFromDisk(pblockindex, true); Object result; CTxDB txdb; { LOCK(cs_main); if (!block.SetBestChain(txdb, pblockindex)) result.push_back(Pair("result", "failure")); else result.push_back(Pair("result", "success")); }; return result; }
bool AcceptPendingSyncCheckpoint() { LOCK(cs_hashSyncCheckpoint); if (hashPendingCheckpoint != 0 && mapBlockIndex.count(hashPendingCheckpoint)) { if (!ValidateSyncCheckpoint(hashPendingCheckpoint)) { hashPendingCheckpoint = 0; checkpointMessagePending.SetNull(); return false; } CTxDB txdb; CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint]; if (!pindexCheckpoint->IsInMainChain()) { CBlock block; if (!block.ReadFromDisk(pindexCheckpoint)) return error("AcceptPendingSyncCheckpoint: ReadFromDisk failed for sync checkpoint %s", hashPendingCheckpoint.ToString()); if (!block.SetBestChain(txdb, pindexCheckpoint)) { hashInvalidCheckpoint = hashPendingCheckpoint; return error("AcceptPendingSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashPendingCheckpoint.ToString()); } } if (!WriteSyncCheckpoint(hashPendingCheckpoint)) return error("AcceptPendingSyncCheckpoint(): failed to write sync checkpoint %s", hashPendingCheckpoint.ToString()); hashPendingCheckpoint = 0; checkpointMessage = checkpointMessagePending; checkpointMessagePending.SetNull(); LogPrintf("AcceptPendingSyncCheckpoint : sync-checkpoint at %s\n", hashSyncCheckpoint.ToString()); // relay the checkpoint if (!checkpointMessage.IsNull()) { BOOST_FOREACH(CNode* pnode, vNodes) checkpointMessage.RelayTo(pnode); } return true; } return false; }
// ppcoin: 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 LogPrintf("ResetSyncCheckpoint: SetBestChain to hardened checkpoint %s\n", hash.ToString()); CTxDB txdb; CBlock block; if (!block.ReadFromDisk(mapBlockIndex[hash])) return error("ResetSyncCheckpoint: ReadFromDisk failed for hardened checkpoint %s", hash.ToString()); if (!block.SetBestChain(txdb, mapBlockIndex[hash])) { return error("ResetSyncCheckpoint: SetBestChain failed for hardened checkpoint %s", hash.ToString()); } } else if(!mapBlockIndex.count(hash)) { // checkpoint block not yet accepted hashPendingCheckpoint = hash; checkpointMessagePending.SetNull(); LogPrintf("ResetSyncCheckpoint: pending for sync-checkpoint %s\n", hashPendingCheckpoint.ToString()); } 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()); LogPrintf("ResetSyncCheckpoint: sync-checkpoint reset to %s\n", hashSyncCheckpoint.ToString()); return true; } } if (!WriteSyncCheckpoint(Params().HashGenesisBlock())) return error("ResetSyncCheckpoint: failed to write sync checkpoint genesis block"); LogPrintf("ResetSyncCheckpoint: sync-checkpoint reset to genesis block\n"); return true; }
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; }