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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
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));
}
Example #5
0
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);
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #9
0
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") + "&nbsp;<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;
}
Example #10
0
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;
}