// get information of sync-checkpoint Value getcheckpoint(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getcheckpoint\n" "Show info of synchronized checkpoint.\n"); Object result; CBlockIndex* pindexCheckpoint; result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); if (Checkpoints::checkpointMessage.vchSig.size() != 0) { Object msgdata; CUnsignedSyncCheckpoint checkpoint; CDataStream sMsg(Checkpoints::checkpointMessage.vchMsg, SER_NETWORK, PROTOCOL_VERSION); sMsg >> checkpoint; Object parsed; // message version and data (block hash) parsed.push_back(Pair("version", checkpoint.nVersion)); parsed.push_back(Pair("hash", checkpoint.hashCheckpoint.GetHex().c_str())); msgdata.push_back(Pair("parsed", parsed)); Object raw; // raw checkpoint message data raw.push_back(Pair("data", HexStr(Checkpoints::checkpointMessage.vchMsg).c_str())); raw.push_back(Pair("signature", HexStr(Checkpoints::checkpointMessage.vchSig).c_str())); msgdata.push_back(Pair("raw", raw)); result.push_back(Pair("data", msgdata)); }
Value sendcheckpoint(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( "sendcheckpoint <blockhash>\n" "Send a synchronized checkpoint.\n"); if (!mapArgs.count("-checkpointkey") || CSyncCheckpoint::strMasterPrivKey.empty()) throw runtime_error("Not a checkpointmaster node, first set checkpointkey in configuration and restart client. "); std::string strHash = params[0].get_str(); uint256 hash(strHash); if (!SendSyncCheckpoint(hash)) throw runtime_error("Failed to send checkpoint, check log. "); Object result; CBlockIndex* pindexCheckpoint; result.push_back(Pair("synccheckpoint", hashSyncCheckpoint.ToString().c_str())); if (mapBlockIndex.count(hashSyncCheckpoint)) { pindexCheckpoint = mapBlockIndex[hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", (boost::int64_t) pindexCheckpoint->GetBlockTime())); } result.push_back(Pair("subscribemode", IsSyncCheckpointEnforced()? "enforce" : "advisory")); if (mapArgs.count("-checkpointkey")) result.push_back(Pair("checkpointmaster", true)); return result; }
// Return average network hashes per second based on the last 'lookup' blocks, // or from the last difficulty change if 'lookup' is nonpositive. // If 'height' is nonnegative, compute the estimate at the time when a given block was found. Value GetNetworkHashPS(int lookup, int height) { CBlockIndex *pb = pindexBest; if (height >= 0 && height < nBestHeight) pb = FindBlockByHeight(height); if (pb == NULL || !pb->nHeight) return 0; // If lookup is -1, then use blocks since last difficulty change. if (lookup <= 0) lookup = pb->nHeight % 2016 + 1; // If lookup is larger than chain, then set it to chain length. if (lookup > pb->nHeight) lookup = pb->nHeight; double sum = 0.0; for (int i = 0; i < lookup; i++) { sum += (pb->GetBlockTime() - pb->pprev->GetBlockTime()) / GetDifficulty(pb); pb = pb->pprev; } return (boost::int64_t)(pow(2.0, 32) / (sum / lookup)); }
/* * 获取最近 N个块状态信息: getpolopointsstate param * * */ Value getpolopointsstate(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( "getpolopointsstate \"num\"\n" "\nget state data about the recently blocks.\n" "\nArguments:\n" "1.num (numeric,required, > 0) The number of the recently blocks.\n" "\nResult:\n" "{\n" " \"blocktime\": n, (numeric)get the time of each block\n" " \"difficulty\": n, (numeric)get the difficulty of each block\n" " \"transactions\": n, (numeric)get the transactions of each block\n" " \"fuel\": n, (numeric)get fuel of each block\n" " \"blockminer\": n, (numeric)get the miner of each block\n" "}\n" "\nExamples:\n" + HelpExampleCli("getpolopointsstate", "\"5\"") + HelpExampleRpc("getpolopointsstate", "\"5\"") ); int i = 0,nHeight = 0; if (int_type == params[0].type()) { nHeight = params[0].get_int(); if(nHeight < 1) throw runtime_error("Block number out of range."); if(nHeight > chainActive.Height()) { //防止超过最大高度 nHeight = chainActive.Height(); } } CBlockIndex * pBlockIndex = chainActive.Tip(); CBlock block; Array blocktime; Array difficulty; Array transactions; Array fuel; Array blockminer; for (i = 0; (i < nHeight) && (pBlockIndex != NULL); i++) { blocktime.push_back(pBlockIndex->GetBlockTime()); difficulty.push_back(GetDifficulty(pBlockIndex)); transactions.push_back((int)pBlockIndex->nTx); fuel.push_back(pBlockIndex->nFuel); block.SetNull(); if(ReadBlockFromDisk(block, pBlockIndex)) { string miner(boost::get<CRegID>(dynamic_pointer_cast<CRewardTransaction>(block.vptx[0])->account).ToString()); blockminer.push_back(move(miner)); } pBlockIndex = pBlockIndex->pprev; } Object obj; obj.push_back(Pair("blocktime", blocktime)); obj.push_back(Pair("difficulty", difficulty)); obj.push_back(Pair("transactions", transactions)); obj.push_back(Pair("fuel", fuel)); obj.push_back(Pair("blockminer",blockminer)); return obj; }
// apexcoin: get information of sync-checkpoint Value getcheckpoint(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getcheckpoint\n" "Show info of synchronized checkpoint.\n"); Object result; CBlockIndex* pindexCheckpoint; result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); // Check that the block satisfies synchronized checkpoint if (CheckpointsMode == Checkpoints::STRICT) result.push_back(Pair("policy", "strict")); if (CheckpointsMode == Checkpoints::ADVISORY) result.push_back(Pair("policy", "advisory")); if (CheckpointsMode == Checkpoints::PERMISSIVE) result.push_back(Pair("policy", "permissive")); if (mapArgs.count("-checkpointkey")) result.push_back(Pair("checkpointmaster", true)); return result; }
double GetPoWKHashPM() { int nPoWInterval = 72; int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30; CBlockIndex* pindex = pindexGenesisBlock; CBlockIndex* pindexPrevWork = pindexGenesisBlock; while (pindex) { int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime(); nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1); nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin); pindexPrevWork = pindex; pindex = pindex->pnext; } return (GetDifficulty() * 1024 * 4294.967296 / nTargetSpacingWork) * 60; // 60= sec to min, 1024= standard scrypt work to scrypt^2 }
double GetPoWMHashPS() { if (GetBoolArg("-testnet")){ if (pindexBest->nHeight >= P1_End_TestNet && pindexBest->nHeight < P2_Start_TestNet){ return 0; } else if (pindexBest->nHeight > P2_End_TestNet){ return 0; } }else { if (pindexBest->nHeight >= P1_End && pindexBest->nHeight < P2_Start){ return 0; } else if (pindexBest->nHeight > P2_End){ return 0; } } int nPoWInterval = 72; int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30; CBlockIndex* pindex = pindexGenesisBlock; CBlockIndex* pindexPrevWork = pindexGenesisBlock; while (pindex) { if (pindex->IsProofOfWork()) { int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime(); nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1); nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin); pindexPrevWork = pindex; } pindex = pindex->pnext; } return GetDifficulty() * 4294.967296 / nTargetSpacingWork; }
double GetPoWMHashPS() { int nPoWInterval = 72; int64 nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30; CBlockIndex* pindex = pindexGenesisBlock; CBlockIndex* pindexPrevWork = pindexGenesisBlock; while (pindex) { if (pindex->IsProofOfWork()) { int64 nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime(); nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1); nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin); pindexPrevWork = pindex; } pindex = pindex->pnext; } return GetDifficulty() * 4294.967296 / nTargetSpacingWork; }
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) { // Call into TxToUniv() in bitcoin-common to decode the transaction hex. // // Blockchain contextual information (confirmations and blocktime) is not // available to code in bitcoin-common, so we query them here and push the // data into the returned UniValue. TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags()); if (!hashBlock.IsNull()) { entry.push_back(Pair("blockhash", hashBlock.GetHex())); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); entry.push_back(Pair("time", pindex->GetBlockTime())); entry.push_back(Pair("blocktime", pindex->GetBlockTime())); } else entry.push_back(Pair("confirmations", 0)); } } }
// ppcoin: get information of sync-checkpoint Value getcheckpoint(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getcheckpoint\n" "Show info of synchronized checkpoint.\n"); Object result; CBlockIndex* pindexCheckpoint; result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str())); pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); if (mapArgs.count("-checkpointkey")) result.push_back(Pair("checkpointmaster", true)); return result; }
// Litecoin: Return average network hashes per second based on last number of blocks. Value GetNetworkHashPS(int lookup) { if (pindexBest == NULL) return 0; // If lookup is -1, then use blocks since last difficulty change. if (lookup <= 0) lookup = pindexBest->nHeight % 2016 + 1; // If lookup is larger than chain, then set it to chain length. if (lookup > pindexBest->nHeight) lookup = pindexBest->nHeight; CBlockIndex* pindexPrev = pindexBest; for (int i = 0; i < lookup; i++) pindexPrev = pindexPrev->pprev; double timeDiff = pindexBest->GetBlockTime() - pindexPrev->GetBlockTime(); double timePerBlock = timeDiff / lookup; return (boost::int64_t)(((double)GetDifficulty() * pow(2.0, 32)) / timePerBlock); }
Value peggypayments(const Array& params, bool fHelp) { if (fHelp || params.size() < 1) throw runtime_error( "peggypayments <block height>\n" "Shows all redeems for a certain block: \n" "(-1 for latest block)\n" ); int64_t nHeight, nBlockTime; nHeight = params[0].get_int64(); if(nHeight != -1){ if(nHeight < nMinPeggyHeight || nHeight > pindexBest->nHeight) throw runtime_error( "peggypayments <block height> <block time>\n" "the block height you entered is not a peggy block, or the height is out of range\n" ); CBlockIndex *pindex = FindBlockByHeight(nHeight); nHeight = pindex->nHeight; nBlockTime = pindex->GetBlockTime(); } else{ nHeight = pindexBest->nHeight; nBlockTime = pindexBest->GetBlockTime(); } CWallet wallet; char *paymentScript = peggypayments(nHeight, nBlockTime); //char *priceFeedHash = peggybase(nHeight, nBlockTime); std::string retVal = std::string(paymentScript); free(paymentScript); return std::string(paymentScript); }
uint64_t GetNetworkHashPS( int lookup ) { if( !pindexBest ) return 0; if( lookup < 0 ) lookup = 0; // If lookup is larger than chain, then set it to chain length. if( lookup > pindexBest->nHeight ) lookup = pindexBest->nHeight; CBlockIndex *pindexPrev = pindexBest; for( int i = 0; i < lookup; ++i ) pindexPrev = pindexPrev->pprev; double timeDiff = pindexBest->GetBlockTime() - pindexPrev->GetBlockTime(); double timePerBlock = timeDiff / lookup; return (uint64_t)(((double)GetDifficulty() * pow(2.0, 32)) / timePerBlock); }
// RPC commands related to sync checkpoints // get information of sync-checkpoint (first introduced in ppcoin) Value getcheckpoint(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getcheckpoint\n" "Show info of synchronized checkpoint.\n"); Object result; CBlockIndex* pindexCheckpoint; result.push_back(Pair("synccheckpoint", hashSyncCheckpoint.ToString().c_str())); if (mapBlockIndex.count(hashSyncCheckpoint)) { pindexCheckpoint = mapBlockIndex[hashSyncCheckpoint]; result.push_back(Pair("height", pindexCheckpoint->nHeight)); result.push_back(Pair("timestamp", (boost::int64_t) pindexCheckpoint->GetBlockTime())); } result.push_back(Pair("subscribemode", IsSyncCheckpointEnforced()? "enforce" : "advisory")); if (mapArgs.count("-checkpointkey")) result.push_back(Pair("checkpointmaster", true)); return result; }
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) { entry.push_back(Pair("txid", tx.GetHash().GetHex())); entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex())); entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); entry.push_back(Pair("vsize", (int)::GetVirtualTransactionSize(tx))); entry.push_back(Pair("version", tx.nVersion)); entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); UniValue vin(UniValue::VARR); for (unsigned int i = 0; i < tx.vin.size(); i++) { const CTxIn& txin = tx.vin[i]; UniValue in(UniValue::VOBJ); if (tx.IsCoinBase()) in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); else { in.push_back(Pair("txid", txin.prevout.hash.GetHex())); in.push_back(Pair("vout", (int64_t)txin.prevout.n)); UniValue o(UniValue::VOBJ); o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true))); o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); in.push_back(Pair("scriptSig", o)); } if (!tx.wit.IsNull()) { if (!tx.wit.vtxinwit[i].IsNull()) { UniValue txinwitness(UniValue::VARR); for (unsigned int j = 0; j < tx.wit.vtxinwit[i].scriptWitness.stack.size(); j++) { std::vector<unsigned char> item = tx.wit.vtxinwit[i].scriptWitness.stack[j]; txinwitness.push_back(HexStr(item.begin(), item.end())); } in.push_back(Pair("txinwitness", txinwitness)); } } in.push_back(Pair("sequence", (int64_t)txin.nSequence)); vin.push_back(in); } entry.push_back(Pair("vin", vin)); UniValue vout(UniValue::VARR); for (unsigned int i = 0; i < tx.vout.size(); i++) { const CTxOut& txout = tx.vout[i]; UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); out.push_back(Pair("n", (int64_t)i)); UniValue o(UniValue::VOBJ); ScriptPubKeyToJSON(txout.scriptPubKey, o, true); out.push_back(Pair("scriptPubKey", o)); vout.push_back(out); } entry.push_back(Pair("vout", vout)); if (!hashBlock.IsNull()) { entry.push_back(Pair("blockhash", hashBlock.GetHex())); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); entry.push_back(Pair("time", pindex->GetBlockTime())); entry.push_back(Pair("blocktime", pindex->GetBlockTime())); } else entry.push_back(Pair("confirmations", 0)); } } }
bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) { // we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey) // so nothing to do here for us if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubkey2 == activeMasternode.pubKeyMasternode) return true; // search existing Masternode list CMasternode* pmn = mnodeman.Find(vin); if(pmn != NULL) { // nothing to do here if we already know about this masternode and it's enabled if(pmn->IsEnabled()) return true; // if it's not enabled, remove old MN first and continue else mnodeman.Remove(pmn->vin); } CValidationState state; CMutableTransaction tx = CMutableTransaction(); CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); { TRY_LOCK(cs_main, lockMain); if(!lockMain) { // not mnb fault, let it to be checked again later mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); masternodeSync.mapSeenSyncMNB.erase(GetHash()); return false; } if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)) { //set nDos state.IsInvalid(nDoS); return false; } } LogPrint("masternode", "mnb - Accepted Masternode entry\n"); if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ LogPrintf("mnb - Input must have at least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); // maybe we miss few blocks, let this mnb to be checked again later mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); masternodeSync.mapSeenSyncMNB.erase(GetHash()); return false; } // verify that sig time is legit in past // should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS uint256 hashBlock = 0; CTransaction tx2; GetTransaction(vin.prevout.hash, tx2, hashBlock, true); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS if(pConfIndex->GetBlockTime() > sigTime) { LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n", sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()); return false; } } LogPrintf("mnb - Got NEW Masternode entry - %s - %s - %s - %lli \n", GetHash().ToString(), addr.ToString(), vin.ToString(), sigTime); CMasternode mn(*this); mnodeman.Add(mn); // if it matches our Masternode privkey, then we've been remotely activated if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ activeMasternode.EnableHotColdMasterNode(vin, addr); } bool isLocal = addr.IsRFC1918() || addr.IsLocal(); if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; if(!isLocal) Relay(); return true; }
Value getmininginfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getmininginfo\n" "Returns an object containing mining-related information."); double dStakeKernelsTriedAvg = 0; int nPoWInterval = 72, nPoSInterval = 72, nStakesHandled = 0, nStakesTime = 0; int64 nTargetSpacingWorkMin = 2, nTargetSpacingWork = 2; CBlockIndex* pindex = pindexGenesisBlock; CBlockIndex* pindexPrevWork = pindexGenesisBlock; CBlockIndex* pindexPrevStake = NULL; while (pindex) { if (pindex->IsProofOfWork()) { int64 nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime(); nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1); nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin); pindexPrevWork = pindex; } pindex = pindex->pnext; } pindex = pindexBest; while (pindex && nStakesHandled < nPoSInterval) { if (pindex->IsProofOfStake()) { dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296; nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0; pindexPrevStake = pindex; nStakesHandled++; } pindex = pindex->pprev; } double dNetworkMhps = GetDifficulty() * 4294.967296 / nTargetSpacingWork; double dNetworkWeight = dStakeKernelsTriedAvg / nStakesTime; Object obj; obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize)); obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx)); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); //obj.push_back(Pair("blockvalue", (uint64_t)GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits))); //obj.push_back(Pair("powmhashps", dNetworkMhps)); obj.push_back(Pair("netstakeweight", dNetworkWeight)); obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("belowweight", (uint64_t)pwalletMain->GetStakeWeight(*pwalletMain, STAKE_BELOWMIN))); obj.push_back(Pair("stakeweight", (uint64_t)pwalletMain->GetStakeWeight(*pwalletMain, STAKE_NORMAL))); obj.push_back(Pair("minweight", (uint64_t)pwalletMain->GetStakeWeight(*pwalletMain, STAKE_MINWEIGHT))); obj.push_back(Pair("maxweight", (uint64_t)pwalletMain->GetStakeWeight(*pwalletMain, STAKE_MAXWEIGHT))); obj.push_back(Pair("StakeReadytunes", ((uint64_t)pwalletMain->GetStakeWeight(*pwalletMain, STAKE_NORMAL))/730)); //obj.push_back(Pair("stakeinterest", (uint64_t)GetProofOfStakeReward(0, GetLastBlockIndex(pindexBest, true)->nBits, GetLastBlockIndex(pindexBest, true)->nTime, true))); obj.push_back(Pair("testnet", fTestNet)); return obj; }
bool CBlock::AcceptBlock() { AssertLockHeld(cs_main); if (nVersion > CURRENT_VERSION) return DoS(100, error("AcceptBlock() : reject unknown block version %d", nVersion)); // Check for duplicate uint256 hash = GetHash(); if (mapBlockIndex.count(hash)) return error("AcceptBlock() : block already in mapBlockIndex"); // Get prev block index map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock); if (mi == mapBlockIndex.end()) return DoS(10, error("AcceptBlock() : prev block not found")); CBlockIndex* pindexPrev = (*mi).second; int nHeight = pindexPrev->nHeight+1; if (IsProofOfStake() && nHeight < Params().FirstPOSBlock()) return DoS(100, error("AcceptBlock() : reject proof-of-stake at height <= %d", nHeight)); // Check coinbase timestamp if (GetBlockTime() > FutureDrift((int64_t)vtx[0].nTime, IsProofOfStake())) return DoS(50, error("AcceptBlock() : coinbase timestamp is too early")); // Check coinstake timestamp if (IsProofOfStake() && !CheckCoinStakeTimestamp(nHeight, GetBlockTime(), (int64_t)vtx[1].nTime)) return DoS(50, error("AcceptBlock() : coinstake timestamp violation nTimeBlock=%d nTimeTx=%u", GetBlockTime(), vtx[1].nTime)); // Check proof-of-work or proof-of-stake if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake())) return DoS(100, error("AcceptBlock() : incorrect %s", IsProofOfWork() ? "proof-of-work" : "proof-of-stake")); // Check timestamp against prev LogPrintf("GetBlockTime(): %d, <=? pindexPrev->GetPastTimeLimit(): %d\nFutureDrift(GetBlockTime()): %d, <?pindexPrev->GetBlockTime(): %d\n",GetBlockTime(),pindexPrev->GetPastTimeLimit(),FutureDrift(GetBlockTime()),pindexPrev->GetBlockTime()); if (GetBlockTime() <= pindexPrev->GetPastTimeLimit() || FutureDrift(GetBlockTime(), IsProofOfStake()) < pindexPrev->GetBlockTime()) return error("AcceptBlock() : block's timestamp is too early"); // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, vtx) if (!IsFinalTx(tx, nHeight, GetBlockTime())) return DoS(10, error("AcceptBlock() : contains a non-final transaction")); // Check that the block chain matches the known block chain up to a checkpoint if (!Checkpoints::CheckHardened(nHeight, hash)) return DoS(100, error("AcceptBlock() : rejected by hardened checkpoint lock-in at %d", nHeight)); uint256 hashProof; // Verify hash target and signature of coinstake tx if (IsProofOfStake()) { uint256 targetProofOfStake; if (!CheckProofOfStake(pindexPrev, vtx[1], nBits, hashProof, targetProofOfStake)) { return error("AcceptBlock() : check proof-of-stake failed for block %s", hash.ToString()); } } // PoW is checked in CheckBlock() if (IsProofOfWork()) { hashProof = GetPoWHash(); } // Check that the block satisfies synchronized checkpoint if (!Checkpoints::CheckSync(nHeight)) return error("AcceptBlock() : rejected by synchronized checkpoint"); // Enforce rule that the coinbase starts with serialized block height CScript expect = CScript() << nHeight; if (vtx[0].vin[0].scriptSig.size() < expect.size() || !std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin())) return DoS(100, error("AcceptBlock() : block height mismatch in coinbase")); // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) return error("AcceptBlock() : out of disk space"); unsigned int nFile = -1; unsigned int nBlockPos = 0; if (!WriteToDisk(nFile, nBlockPos)) return error("AcceptBlock() : WriteToDisk failed"); if (!AddToBlockIndex(nFile, nBlockPos, hashProof)) return error("AcceptBlock() : AddToBlockIndex failed"); // Relay inventory, but don't relay old inventory during initial block download int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); if (hashBestChain == hash) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) pnode->PushInventory(CInv(MSG_BLOCK, hash)); }
//Catch the counter up with the chain void CzPIVWallet::SyncWithChain(bool fGenerateMintPool) { uint32_t nLastCountUsed = 0; bool found = true; CWalletDB walletdb(strWalletFile); set<uint256> setAddedTx; while (found) { found = false; if (fGenerateMintPool) GenerateMintPool(); LogPrintf("%s: Mintpool size=%d\n", __func__, mintPool.size()); std::set<uint256> setChecked; list<pair<uint256,uint32_t> > listMints = mintPool.List(); for (pair<uint256, uint32_t> pMint : listMints) { LOCK(cs_main); if (setChecked.count(pMint.first)) return; setChecked.insert(pMint.first); if (ShutdownRequested()) return; if (pwalletMain->zpivTracker->HasPubcoinHash(pMint.first)) { mintPool.Remove(pMint.first); continue; } uint256 txHash; CZerocoinMint mint; if (zerocoinDB->ReadCoinMint(pMint.first, txHash)) { //this mint has already occurred on the chain, increment counter's state to reflect this LogPrintf("%s : Found wallet coin mint=%s count=%d tx=%s\n", __func__, pMint.first.GetHex(), pMint.second, txHash.GetHex()); found = true; uint256 hashBlock; CTransaction tx; if (!GetTransaction(txHash, tx, hashBlock, true)) { LogPrintf("%s : failed to get transaction for mint %s!\n", __func__, pMint.first.GetHex()); found = false; nLastCountUsed = std::max(pMint.second, nLastCountUsed); continue; } //Find the denomination CoinDenomination denomination = CoinDenomination::ZQ_ERROR; bool fFoundMint = false; CBigNum bnValue = 0; for (const CTxOut& out : tx.vout) { if (!out.scriptPubKey.IsZerocoinMint()) continue; PublicCoin pubcoin(Params().Zerocoin_Params(false)); CValidationState state; if (!TxOutToPublicCoin(out, pubcoin, state)) { LogPrintf("%s : failed to get mint from txout for %s!\n", __func__, pMint.first.GetHex()); continue; } // See if this is the mint that we are looking for uint256 hashPubcoin = GetPubCoinHash(pubcoin.getValue()); if (pMint.first == hashPubcoin) { denomination = pubcoin.getDenomination(); bnValue = pubcoin.getValue(); fFoundMint = true; break; } } if (!fFoundMint || denomination == ZQ_ERROR) { LogPrintf("%s : failed to get mint %s from tx %s!\n", __func__, pMint.first.GetHex(), tx.GetHash().GetHex()); found = false; break; } CBlockIndex* pindex = nullptr; if (mapBlockIndex.count(hashBlock)) pindex = mapBlockIndex.at(hashBlock); if (!setAddedTx.count(txHash)) { CBlock block; CWalletTx wtx(pwalletMain, tx); if (pindex && ReadBlockFromDisk(block, pindex)) wtx.SetMerkleBranch(block); //Fill out wtx so that a transaction record can be created wtx.nTimeReceived = pindex->GetBlockTime(); pwalletMain->AddToWallet(wtx); setAddedTx.insert(txHash); } SetMintSeen(bnValue, pindex->nHeight, txHash, denomination); nLastCountUsed = std::max(pMint.second, nLastCountUsed); nCountLastUsed = std::max(nLastCountUsed, nCountLastUsed); LogPrint("zero", "%s: updated count to %d\n", __func__, nCountLastUsed); } } } }
// Stake Modifier (hash modifier of proof-of-stake): // The purpose of stake modifier is to prevent a txout (coin) owner from // computing future proof-of-stake generated by this txout at the time // of transaction confirmation. To meet kernel protocol, the txout // must hash with a future stake modifier to generate the proof. // Stake modifier consists of bits each of which is contributed from a // selected block of a given block group in the past. // The selection of a block is based on a hash of the block's proof-hash and // the previous stake modifier. // Stake modifier is recomputed at a fixed time interval instead of every // block. This is to make it difficult for an attacker to gain control of // additional bits in the stake modifier, even after generating a chain of // blocks. bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModifier, bool& fGeneratedStakeModifier) { nStakeModifier = 0; fGeneratedStakeModifier = false; if (!pindexPrev) { fGeneratedStakeModifier = true; return true; // genesis block's modifier is 0 } // First find current stake modifier and its generation block time // if it's not old enough, return the same stake modifier if(modifierLast == NULL) { if (pindexPrev->GetBlockTime() < 1392281929 + nModifierInterval) return true; } else { //printf("modifierLast = %i \n", modifierLast->nHeight); if (fDebug) printf("ComputeNextStakeModifier: prev modifier=0x%016"PRI64x" time=%s\n", nStakeModifier, DateTimeStrFormat(modifierLast->GetBlockTime()).c_str()); if (pindexPrev->GetBlockTime() < modifierLast->GetBlockTime() + nModifierInterval) return true; } modifierLast = const_cast<CBlockIndex*>(pindexPrev); // Sort candidate blocks by timestamp vector<pair<int64, uint256> > vSortedByTimestamp; vSortedByTimestamp.reserve(64 * nModifierInterval / nStakeTargetSpacing); int64 nSelectionInterval = GetStakeModifierSelectionInterval(); int64 nSelectionIntervalStart = (pindexPrev->GetBlockTime() / nModifierInterval) * nModifierInterval - nSelectionInterval; const CBlockIndex* pindex = pindexPrev; while (pindex && pindex->GetBlockTime() >= nSelectionIntervalStart) { vSortedByTimestamp.push_back(make_pair(pindex->GetBlockTime(), pindex->GetBlockHash())); pindex = pindex->pprev; } int nHeightFirstCandidate = pindex ? (pindex->nHeight + 1) : 0; reverse(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); sort(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); // Select 64 blocks from candidate blocks to generate stake modifier uint64 nStakeModifierNew = 0; int64 nSelectionIntervalStop = nSelectionIntervalStart; map<uint256, const CBlockIndex*> mapSelectedBlocks; for (int nRound=0; nRound<min(6, (int)vSortedByTimestamp.size()); nRound++) { // add an interval section to the current selection round nSelectionIntervalStop += GetStakeModifierSelectionIntervalSection(nRound); // write the entropy bit of the selected block pair<int64, uint256> ts = vSortedByTimestamp[nRound]; uint256 hash = ts.second; std::map<uint256,CBlockIndex*>::iterator it; it = mapBlockIndex.find(hash); if(it != mapBlockIndex.end()) { CBlockIndex* cBlock = it->second; nStakeModifierNew |= (((uint64) cBlock->GetBlockTime()) >> nRound); // add the selected block from candidates to selected list mapSelectedBlocks.insert(make_pair(cBlock->GetBlockHash(), cBlock)); //if (fDebug) //printf("ComputeNextStakeModifier: selected round %d stop=%s height=%d bit=%d\n",nRound, DateTimeStrFormat(nSelectionIntervalStop).c_str(), pindex->nHeight, pindex->GetStakeEntropyBit()); } }
// 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; }
BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { LOCK(cs_main); // Cap last block file size, and mine new block in a new block file. CBlockIndex* oldTip = chainActive.Tip(); GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CBlockIndex* newTip = chainActive.Tip(); // Verify ScanForWalletTransactions picks up transactions in both the old // and new block files. { CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); } // Prune the older block file. PruneOneBlockFile(oldTip->GetBlockPos().nFile); UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); // Verify ScanForWalletTransactions only picks transactions in the new block // file. { CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); } // Verify importmulti RPC returns failure for a key whose creation time is // before the missing block, and success for a key whose creation time is // after. { CWallet wallet; CWallet *backup = ::pwalletMain; ::pwalletMain = &wallet; UniValue keys; keys.setArray(); UniValue key; key.setObject(); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey()))); key.pushKV("timestamp", 0); key.pushKV("internal", UniValue(true)); keys.push_back(key); key.clear(); key.setObject(); CKey futureKey; futureKey.MakeNewKey(true); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey()))); key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW); key.pushKV("internal", UniValue(true)); keys.push_back(key); JSONRPCRequest request; request.params.setArray(); request.params.push_back(keys); UniValue response = importmulti(request); BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}},{\"success\":true}]", newTip->GetBlockTimeMax())); ::pwalletMain = backup; } // Verify ScanForWalletTransactions does not return null when the scan is // elided due to the nTimeFirstKey optimization. { CWallet wallet; { LOCK(wallet.cs_wallet); wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1); } BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip)); } }