double BlockBrowser::getTxFees(std::string txid) { uint256 hash; hash.SetHex(txid); CTransaction tx; uint256 hashBlock = 0; CTxDB txdb("r"); if (!GetTransaction(hash, tx, hashBlock)) return convertCoins(MIN_TX_FEE); MapPrevTx mapInputs; map<uint256, CTxIndex> mapUnused; bool fInvalid; if (!tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid)) return convertCoins(MIN_TX_FEE); qint64 nTxFees = tx.GetValueIn(mapInputs)-tx.GetValueOut(); if(tx.IsCoinStake() || tx.IsCoinBase()) { ui->feesLabel->setText(QString("Reward:")); nTxFees *= -1; } else ui->feesLabel->setText(QString("Fees:")); return convertCoins(nTxFees); }
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPool *pool) { // Hack to assume either its completely dependent on other mempool txs or not at all CAmount inChainValue = pool && pool->HasNoInputsOf(txn) ? txn.GetValueOut() : 0; return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, dPriority, nHeight, inChainValue, spendsCoinbase, sigOpCost, lp); }
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CTransaction &txn, CTxMemPool *pool) { bool hasNoDependencies = pool ? pool->HasNoInputsOf(txn) : hadNoDependencies; // Hack to assume either its completely dependent on other mempool txs or not at all CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0; return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight, hasNoDependencies, inChainValue, spendsCoinbase, sigOpCost, lp); }
static void AddTx(const CTransaction& tx, const CAmount& nFee, CTxMemPool& pool) { int64_t nTime = 0; double dPriority = 10.0; unsigned int nHeight = 1; bool spendsCoinbase = false; unsigned int sigOpCost = 4; LockPoints lp; pool.addUnchecked(tx.GetHash(), CTxMemPoolEntry( MakeTransactionRef(tx), nFee, nTime, dPriority, nHeight, tx.GetValueOut(), spendsCoinbase, sigOpCost, lp)); }
static std::string TxToRow(const CTransaction& tx, const CScript& Highlight = CScript(), const std::string& Prepend = std::string(), int64_t* pSum = NULL) { std::string InAmounts, InAddresses, OutAmounts, OutAddresses; int64_t Delta = 0; for (unsigned int j = 0; j < tx.vin.size(); j++) { if (tx.IsCoinBase()) { InAmounts += ValueToString(tx.GetValueOut()); InAddresses += "coinbase"; } else { CTxOut PrevOut = getPrevOut(tx.vin[j].prevout); InAmounts += ValueToString(PrevOut.nValue); InAddresses += ScriptToString(PrevOut.scriptPubKey, false, PrevOut.scriptPubKey == Highlight).c_str(); if (PrevOut.scriptPubKey == Highlight) Delta -= PrevOut.nValue; } if (j + 1 != tx.vin.size()) { InAmounts += "<br/>"; InAddresses += "<br/>"; } } for (unsigned int j = 0; j < tx.vout.size(); j++) { CTxOut Out = tx.vout[j]; OutAmounts += ValueToString(Out.nValue); OutAddresses += ScriptToString(Out.scriptPubKey, false, Out.scriptPubKey == Highlight); if (Out.scriptPubKey == Highlight) Delta += Out.nValue; if (j + 1 != tx.vout.size()) { OutAmounts += "<br/>"; OutAddresses += "<br/>"; } } std::string List[8] = { Prepend, makeHRef(tx.GetHash().GetHex()), InAddresses, InAmounts, OutAddresses, OutAmounts, "", ""}; int n = sizeof(List) / sizeof(std::string) - 2; if (!Highlight.empty()) { List[n++] = std::string("<font color=\"") + ((Delta > 0) ? "green" : "red") + "\">" + ValueToString(Delta, true) + "</font>"; *pSum += Delta; List[n++] = ValueToString(*pSum); return makeHTMLTableRow(List, n); } return makeHTMLTableRow(List + 1, n - 1); }
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee) { // are the actual inputs available? if (!inputs.HaveInputs(tx)) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-missingorspent", false, strprintf("%s: inputs missing/spent", __func__)); } CAmount nValueIn = 0; for (unsigned int i = 0; i < tx.vin.size(); ++i) { const COutPoint &prevout = tx.vin[i].prevout; const Coin& coin = inputs.AccessCoin(prevout); assert(!coin.IsSpent()); // If prev is coinbase, check that it's matured if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) { return state.Invalid(false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase", strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight)); } // Check for negative or overflow input values nValueIn += coin.out.nValue; if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange"); } } const CAmount value_out = tx.GetValueOut(); if (nValueIn < value_out) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false, strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out))); } // Tally transaction fees const CAmount txfee_aux = nValueIn - value_out; if (!MoneyRange(txfee_aux)) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange"); } txfee = txfee_aux; return true; }
void StatsExplorer::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; int64_t diffMax = 0; // int64_t hashMax = 0; double velMax = 0; BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { if(i >= max) break; CBlockIndex* pindex = item.second; nTimeData.append(pindex->nTime); netStakeData.append(0); velTimeData.append(pindex->nTime); // if(pindex->IsProofOfStake()) if (true) { // netStakeData.append(pindex->nMint / COIN); netStakeData.append(0); // Read the block in and check if the coinstake is ours CBlock block; ReadBlockFromDisk(block, pindex, Params().GetConsensus()); // if(block.IsProofOfStake()) // this should always be true here if(true) // this should always be true here { velTimeData.append(pindex->nTime); double blockOutAmount = 0; for(uint j=0; j<block.vtx.size(); j++) { // FIXME: check dereferencing CTransaction vtx = *block.vtx[j]; blockOutAmount += vtx.GetValueOut() / COIN; } velMax = std::max<double>(velMax, blockOutAmount); velAmountData.append(blockOutAmount); int64_t d = GetDifficulty(pindex); diffMax = std::max<int64_t>(diffMax, d); difficultyData.append(d); // if(IsMine(block.vtx[1])) if(false) { // myStakeData.append(pindex->nMint / COIN); myStakeData.append(0); } else { myStakeData.append(0); } } else { myStakeData.append(0); // should never happen } } ++i; } if(!firstRun) { uint64_t nMinWeight = 0, nMaxWeight = 0; // uint64_t nWeight = 0; // nWeight = nMinWeight * nMaxWeight; // pwalletMain->GetStakeWeight(*pwalletMain, nMinWeight, nMaxWeight, nWeight); // uint64_t nNetworkWeight = 0; // if(pindexBest) // nNetworkWeight = GetPoSKernelPS(); // bool staking = nLastCoinStakeSearchInterval && nWeight; // bool staking = false; // int nExpectedTime = staking ? (nTargetSpacing * nNetworkWeight / nWeight) : -1; /* ui->stakingLabel->setText(staking ? "Enabled" : "Disabled"); bool pindexBest = true; if(pindexBest) ui->difficultyLabel->setText(QString::number(GetDifficulty(mapBlockIndex[chainActive.Tip()->GetBlockHash()]))); ui->weightLabel->setText(QString::number(nWeight)); ui->netWeightLabel->setText(QString::number(nNetworkWeight)); ui->timeToStakeLabel->setText(QString::number(nExpectedTime) + " secs"); */ } QLinearGradient plotGradient; plotGradient.setStart(0, 0); plotGradient.setFinalStop(0, 350); plotGradient.setColorAt(0, QColor(10, 10, 10)); plotGradient.setColorAt(1, QColor(0, 0, 0)); QLinearGradient diffPlotGradient; diffPlotGradient.setStart(0, 0); diffPlotGradient.setFinalStop(0, 350); diffPlotGradient.setColorAt(0, QColor(10, 10, 10)); diffPlotGradient.setColorAt(1, QColor(0, 0, 0)); 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->difficultyPlot->clearPlottables(); ui->difficultyPlot->clearGraphs(); ui->difficultyPlot->clearItems(); ui->difficultyPlot->addGraph(); ui->difficultyPlot->graph(0)->setPen(QPen(QColor(43, 239, 209))); // line color orange for first graph ui->difficultyPlot->graph(0)->setBrush(QBrush(QColor(43, 239, 209, 20))); // first orange will be filled with translucent green ui->difficultyPlot->graph(0)->setData(nTimeData, difficultyData); ui->difficultyPlot->setBackground(diffPlotGradient); // ui->difficultyPlot->xAxis->setRangeLower(nTimeData.first()); // ui->difficultyPlot->xAxis->setRangeUpper(nTimeData.last()); ui->difficultyPlot->yAxis->setRangeLower(0); ui->difficultyPlot->yAxis->setRangeUpper(diffMax+(diffMax/10)); 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"); ui->difficultyPlot->xAxis->setTickLabelRotation(33); ui->difficultyPlot->xAxis->setTickLabelColor(QColor(43, 239, 209, 95)); ui->difficultyPlot->yAxis->setTickLabelColor(QColor(43, 239, 209, 95)); ui->difficultyPlot->rescaleAxes(); ui->difficultyPlot->yAxis->setTickStep(0.00005); ui->difficultyPlot->xAxis->setLabelColor(QColor(43, 239, 209, 95)); ui->difficultyPlot->yAxis->setLabelColor(QColor(43, 239, 209, 95)); ui->difficultyPlot->yAxis->setLabel("Difficulty"); ui->difficultyPlot->xAxis->setTickLabels(true); //ui->difficultyPlot->xAxis->setLabel("Time"); ui->difficultyPlot->replot(); /* ui->customPlot->clearPlottables(); ui->customPlot->clearGraphs(); ui->customPlot->clearItems(); ui->customPlot->addGraph(); ui->customPlot->graph(0)->setPen(QPen(QColor(43, 239, 209))); // line color cream for first graph ui->customPlot->graph(0)->setBrush(QBrush(QColor(0, 255, 139, 20))); // first graph will be filled with translucent cream ui->customPlot->addGraph(); ui->customPlot->graph(1)->setPen(QPen(QColor(43, 239, 209))); // line color orange for second graph ui->customPlot->graph(1)->setBrush(QBrush(QColor(0, 255, 139, 20))); if(ui->networkCheckBox->isChecked()) ui->customPlot->graph(0)->setData(nTimeData, netStakeData); ui->customPlot->graph(1)->setData(nTimeData, myStakeData); ui->customPlot->setBackground(plotGradient); ui->customPlot->xAxis->setRangeLower(nTimeData.first()); ui->customPlot->xAxis->setRangeUpper(nTimeData.last()); 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(false); 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(33); ui->customPlot->xAxis->setTickLabelColor(QColor(43, 239, 209, 95)); ui->customPlot->yAxis->setTickLabelColor(QColor(43, 239, 209, 95)); ui->customPlot->rescaleAxes(); ui->customPlot->xAxis->setLabelColor(QColor(43, 239, 209, 95)); ui->customPlot->yAxis->setLabelColor(QColor(43, 239, 209, 95)); ui->customPlot->yAxis->setLabel("VCN Minted"); ui->customPlot->xAxis->setLabel("Stake Block Generation Time"); ui->customPlot->replot(); */ ui->velocityPlot->clearPlottables(); ui->velocityPlot->clearGraphs(); ui->velocityPlot->clearItems(); ui->velocityPlot->addGraph(); ui->velocityPlot->graph(0)->setPen(QPen(QColor(43, 239, 209))); // line color orange for first graph ui->velocityPlot->graph(0)->setBrush(QBrush(QColor(43, 239, 209, 20))); // first graph will be filled with translucent orange ui->velocityPlot->graph(0)->setData(velTimeData, velAmountData); ui->velocityPlot->setBackground(velPlotGradient); // ui->velocityPlot->xAxis->setRangeLower(velTimeData.first()); // ui->velocityPlot->xAxis->setRangeUpper(velTimeData.last()); ui->velocityPlot->yAxis->setRangeLower(0); ui->velocityPlot->yAxis->setRangeUpper(velMax+(velMax/10)); 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"); ui->velocityPlot->xAxis->setTickLabelRotation(33); ui->velocityPlot->xAxis->setTickLabelColor(QColor(43, 239, 209, 95)); ui->velocityPlot->yAxis->setTickLabelColor(QColor(43, 239, 209, 95)); ui->velocityPlot->yAxis->setScaleType(QCPAxis::stLogarithmic); ui->velocityPlot->yAxis->setTickStep(1000); ui->velocityPlot->xAxis->setLabelColor(QColor(43, 239, 209, 95)); ui->velocityPlot->yAxis->setLabelColor(QColor(43, 239, 209, 95)); ui->velocityPlot->yAxis->setLabel("VCN"); ui->velocityPlot->xAxis->setTickLabels(true); //ui->velocityPlot->xAxis->setLabel("Financial Velocity"); ui->velocityPlot->rescaleAxes(); ui->velocityPlot->replot(); }
bool CheckZerocoinSpendNoDB(const CTransaction tx, string& strError) { //max needed non-mint outputs should be 2 - one for redemption address and a possible 2nd for change if (tx.vout.size() > 2){ int outs = 0; for (const CTxOut out : tx.vout) { if (out.IsZerocoinMint()) continue; outs++; } if (outs > 2) { strError = "CheckZerocoinSpend(): over two non-mint outputs in a zerocoinspend transaction"; return false; } } //compute the txout hash that is used for the zerocoinspend signatures CMutableTransaction txTemp; for (const CTxOut out : tx.vout) { txTemp.vout.push_back(out); } // uint256 hashTxOut = txTemp.GetHash(); bool fValidated = false; set<CBigNum> serials; list<CoinSpend> vSpends; CAmount nTotalRedeemed = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { //only check txin that is a zcspend if (!txin.scriptSig.IsZerocoinSpend()) continue; CoinSpend newSpend = TxInToZerocoinSpend(txin); vSpends.push_back(newSpend); //check that the denomination is valid if (newSpend.getDenomination() == ZQ_ERROR) { strError = "Zerocoinspend does not have the correct denomination"; return false; } //check that denomination is what it claims to be in nSequence if (newSpend.getDenomination() != txin.nSequence) { strError = "Zerocoinspend nSequence denomination does not match CoinSpend"; } //make sure the txout has not changed // if (newSpend.getTxOutHash() != hashTxOut) { // strError = "Zerocoinspend does not use the same txout that was used in the SoK"; // return false; // } //see if we have record of the accumulator used in the spend tx CBigNum bnAccumulatorValue = 0; if (!GetAccumulatorValueFromChecksum(newSpend.getAccumulatorChecksum(), true, bnAccumulatorValue)) { strError = "Zerocoinspend could not find accumulator associated with checksum"; return false; } Accumulator accumulator(Params().Zerocoin_Params(), newSpend.getDenomination(), bnAccumulatorValue); //Check that the coin is on the accumulator if (!newSpend.Verify(accumulator)) { strError = "CheckZerocoinSpend(): zerocoin spend did not verify"; return false; } if (serials.count(newSpend.getCoinSerialNumber())) { strError = "Zerocoinspend serial is used twice in the same tx"; return false; } serials.insert(newSpend.getCoinSerialNumber()); //cannot check this without database // if(!IsZerocoinSpendUnknown(newSpend, tx.GetHash(), state)) // return state.DoS(100, error("Zerocoinspend is already known")); //make sure that there is no over redemption of coins nTotalRedeemed += ZerocoinDenominationToAmount(newSpend.getDenomination()); fValidated = true; } if (nTotalRedeemed < tx.GetValueOut()) { strError = "Transaction spend more than was redeemed in zerocoins"; return false; } return fValidated; }
std::string TxToString(uint256 BlockHash, const CTransaction& tx) { CAmount Input = 0; CAmount Output = tx.GetValueOut(); std::string InputsContentCells[] = {_("#"), _("Taken from"), _("Address"), _("Amount")}; std::string InputsContent = makeHTMLTableRow(InputsContentCells, sizeof(InputsContentCells) / sizeof(std::string)); std::string OutputsContentCells[] = {_("#"), _("Redeemed in"), _("Address"), _("Amount")}; std::string OutputsContent = makeHTMLTableRow(OutputsContentCells, sizeof(OutputsContentCells) / sizeof(std::string)); if (tx.IsCoinBase()) { std::string InputsContentCells[] = { "0", "coinbase", "-", ValueToString(Output)}; InputsContent += makeHTMLTableRow(InputsContentCells, sizeof(InputsContentCells) / sizeof(std::string)); } else for (unsigned int i = 0; i < tx.vin.size(); i++) { COutPoint Out = tx.vin[i].prevout; CTxOut PrevOut = getPrevOut(tx.vin[i].prevout); if (PrevOut.nValue < 0) Input = -Params().MaxMoneyOut(); else Input += PrevOut.nValue; std::string InputsContentCells[] = { itostr(i), "<span>" + makeHRef(Out.hash.GetHex()) + ":" + itostr(Out.n) + "</span>", ScriptToString(PrevOut.scriptPubKey, true), ValueToString(PrevOut.nValue)}; InputsContent += makeHTMLTableRow(InputsContentCells, sizeof(InputsContentCells) / sizeof(std::string)); } uint256 TxHash = tx.GetHash(); for (unsigned int i = 0; i < tx.vout.size(); i++) { const CTxOut& Out = tx.vout[i]; uint256 HashNext = uint256S("0"); unsigned int nNext = 0; bool fAddrIndex = false; getNextIn(COutPoint(TxHash, i), HashNext, nNext); std::string OutputsContentCells[] = { itostr(i), (HashNext == uint256S("0")) ? (fAddrIndex ? _("no") : _("unknown")) : "<span>" + makeHRef(HashNext.GetHex()) + ":" + itostr(nNext) + "</span>", ScriptToString(Out.scriptPubKey, true), ValueToString(Out.nValue)}; OutputsContent += makeHTMLTableRow(OutputsContentCells, sizeof(OutputsContentCells) / sizeof(std::string)); } InputsContent = table + InputsContent + "</table>"; OutputsContent = table + OutputsContent + "</table>"; std::string Hash = TxHash.GetHex(); std::string Labels[] = { _("In Block"), "", _("Size"), itostr(GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)), _("Input"), tx.IsCoinBase() ? "-" : ValueToString(Input), _("Output"), ValueToString(Output), _("Fees"), tx.IsCoinBase() ? "-" : ValueToString(Input - Output), _("Timestamp"), "", _("Hash"), "<pre>" + Hash + "</pre>", }; // std::map<uint256, CBlockIndex*>::iterator iter = mapBlockIndex.find(BlockHash); BlockMap::iterator iter = mapBlockIndex.find(BlockHash); if (iter != mapBlockIndex.end()) { CBlockIndex* pIndex = iter->second; Labels[0 * 2 + 1] = makeHRef(itostr(pIndex->nHeight)); Labels[5 * 2 + 1] = TimeToString(pIndex->nTime); } std::string Content; Content += "<h2>" + _("Transaction") + " <span>" + Hash + "</span></h2>"; Content += makeHTMLTable(Labels, sizeof(Labels) / (2 * sizeof(std::string)), 2); Content += "</br>"; Content += "<h3>" + _("Inputs") + "</h3>"; Content += InputsContent; Content += "</br>"; Content += "<h3>" + _("Outputs") + "</h3>"; Content += OutputsContent; return Content; }
bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) { // TODO : LOCK(cs); // No reason for a lock here now since this method only accesses data // internal to *this and since CSuperblock's are accessed only through // shared pointers there's no way our object can get deleted while this // code is running. if (!IsValidBlockHeight(nBlockHeight)) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, incorrect block height\n"); return false; } std::string strPayeesPossible = ""; // CONFIGURE SUPERBLOCK OUTPUTS int nOutputs = txNew.vout.size(); int nPayments = CountPayments(); int nMinerAndMasternodePayments = nOutputs - nPayments; LogPrint("gobject", "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n", nOutputs, nPayments, GetGovernanceObject()->GetDataAsHexString()); // We require an exact match (including order) between the expected // superblock payments and the payments actually in the block. if (nMinerAndMasternodePayments < 0) { // This means the block cannot have all the superblock payments // so it is not valid. // TODO: could that be that we just hit coinbase size limit? LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, too few superblock payments\n"); return false; } // payments should not exceed limit CAmount nPaymentsTotalAmount = GetPaymentsTotalAmount(); CAmount nPaymentsLimit = GetPaymentsLimit(nBlockHeight); if (nPaymentsTotalAmount > nPaymentsLimit) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, payments limit exceeded: payments %lld, limit %lld\n", nPaymentsTotalAmount, nPaymentsLimit); return false; } // miner and masternodes should not get more than they would usually get CAmount nBlockValue = txNew.GetValueOut(); if (nBlockValue > blockReward + nPaymentsTotalAmount) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, block value limit exceeded: block %lld, limit %lld\n", nBlockValue, blockReward + nPaymentsTotalAmount); return false; } int nVoutIndex = 0; for (int i = 0; i < nPayments; i++) { CGovernancePayment payment; if (!GetPayment(i, payment)) { // This shouldn't happen so log a warning LogPrintf("CSuperblock::IsValid -- WARNING: Failed to find payment: %d of %d total payments\n", i, nPayments); continue; } bool fPaymentMatch = false; for (int j = nVoutIndex; j < nOutputs; j++) { // Find superblock payment fPaymentMatch = ((payment.script == txNew.vout[j].scriptPubKey) && (payment.nAmount == txNew.vout[j].nValue)); if (fPaymentMatch) { nVoutIndex = j; break; } } if (!fPaymentMatch) { // Superblock payment not found! CTxDestination address1; ExtractDestination(payment.script, address1); CBitcoinAddress address2(address1); LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid: %d payment %d to %s not found\n", i, payment.nAmount, address2.ToString()); return false; } } return true; }