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); }
std::string getOutputs(std::string txid) { uint256 hash; hash.SetHex(txid); CTransaction tx; uint256 hashBlock = 0; if (!GetTransaction(hash, tx, hashBlock)) return "N/A"; std::string str = ""; for (unsigned int i = (tx.IsCoinStake() ? 1 : 0); i < tx.vout.size(); i++) { const CTxOut& txout = tx.vout[i]; CTxDestination address; if (!ExtractDestination(txout.scriptPubKey, address) ) address = CNoDestination(); double buffer = convertCoins(txout.nValue); std::string amount = boost::to_string(buffer); str.append(CBitcoinAddress(address).ToString()); str.append(": "); str.append(amount); str.append(" PIO"); str.append("\n"); } return str; }
double CCoinsViewCache::GetPriority(const CTransaction& tx, int nHeight) const { if (tx.IsCoinBase() || tx.IsCoinStake()) return 0.0; double dResult = 0.0; for (const CTxIn& txin: tx.vin) { const CCoins* coins = AccessCoins(txin.prevout.hash); assert(coins); if (!coins->IsAvailable(txin.prevout.n)) continue; if (coins->nHeight < nHeight) { dResult += coins->vout[txin.prevout.n].nValue * (nHeight - coins->nHeight); } } return tx.ComputePriority(dResult); }
double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight, CAmount &inChainInputValue) const { inChainInputValue = 0; if (tx.IsCoinBase() || tx.IsCoinStake()) return 0.0; double dResult = 0.0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { const CCoins* coins = AccessCoins(txin.prevout.hash); assert(coins); if (!coins->IsAvailable(txin.prevout.n)) continue; if (coins->nHeight <= nHeight) { dResult += (double)(coins->vout[txin.prevout.n].nValue) * (nHeight-coins->nHeight); inChainInputValue += coins->vout[txin.prevout.n].nValue; } } return tx.ComputePriority(dResult); }
// Check kernel hash target and coinstake signature bool CheckProofOfStake(const CBlock& block, const CBlockIndex* prevBlock, const COutPoint& outpointStakePointer, uint256& hashProofOfStake) { const CTransaction tx = block.vtx[1]; if (!tx.IsCoinStake()) return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString().c_str()); // Get the stake modifier auto pindexModifier = prevBlock->GetAncestor(prevBlock->nHeight - Params().KernelModifierOffset()); if (!pindexModifier) return error("CheckProofOfStake() : could not find modifier index for stake"); uint256 nStakeModifier = pindexModifier->GetBlockHash(); // Get the correct amount for the collateral CAmount nAmountCollateral = 0; if (outpointStakePointer.n == 1) nAmountCollateral = MASTERNODE_COLLATERAL; else if (outpointStakePointer.n == 2) nAmountCollateral = SYSTEMNODE_COLLATERAL; else return error("%s: Stake pointer is neither pos 1 or 2", __func__); // Reconstruct the kernel that created the stake auto pairOut = std::make_pair(outpointStakePointer.hash, outpointStakePointer.n); Kernel kernel(pairOut, nAmountCollateral, nStakeModifier, prevBlock->GetBlockTime(), block.nTime); bool fNegative; bool fOverflow; arith_uint256 bnTarget; bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); // Check range if (fNegative || bnTarget == 0 || fOverflow) return error("CheckProofOfStake() : nBits below minimum stake"); LogPrintf("%s : %s\n", __func__, kernel.ToString()); hashProofOfStake = kernel.GetStakeHash(); return kernel.IsValidProof(ArithToUint256(bnTarget)); }
extern "C" char* GetPeggyByBlock(CBlock *pblock, CBlockIndex *pindex) { cJSON *array, *arrayObj, *header, *peggybase, *peggypayments, *peggytx; header = cJSON_CreateObject(); peggybase = cJSON_CreateObject(); peggypayments = cJSON_CreateArray(); peggytx = cJSON_CreateArray(); array = cJSON_CreateArray(); arrayObj = cJSON_CreateObject(); //header jaddnum(header, "blocknum", pindex->nHeight); jaddnum(header, "blocktimestamp", pblock->nTime); jaddstr(header, "blockhash", (char*)pindex->GetBlockHash().ToString().c_str()); jadd(arrayObj, "header", header); if(pindex->nHeight >= nMinPeggyHeight){ if(!pblock->vtx[2].IsPeggyBase()) throw runtime_error( "Block Does not contain a peggybase transaction!\n" ); } else{ return "Not a peggy block\n"; } int index, vouts; //peggypayments char bits[4096]; char hex[4096]; bool fPeggy = false; uint64_t nPeggyPayments = 0; for(index=0; index<pblock->vtx.size(); index++){ fPeggy = false; const CTransaction tempTx = pblock->vtx[index]; if(tempTx.IsCoinBase() || tempTx.IsCoinStake()) continue; if(tempTx.IsPeggyBase()){ const CTxOut peggyOut = tempTx.vout[0]; const CScript priceFeed = peggyOut.scriptPubKey; char peggybits[4096]; strcpy(peggybits, (char*)HexStr(priceFeed.begin(), priceFeed.end(), false).c_str()+2); jaddstr(peggybase, "txid", (char*)tempTx.GetHash().ToString().c_str()); jaddstr(peggybase, "peggybase", peggybits); jaddnum(peggybase, "time", tempTx.nTime); jaddnum(peggybase, "txind", 2); jaddnum(peggybase, "voutind", 0); jaddstr(peggybase, "address", "peggypayments"); fPeggy = true; } for(vouts=0; vouts<tempTx.vout.size(); vouts++){ const CTxOut tempVout = tempTx.vout[vouts]; const CScript tempScriptPubKey = tempVout.scriptPubKey; CTxDestination destAddress; strcpy(hex, (char*)HexStr(tempScriptPubKey.begin(), tempScriptPubKey.end(), false).c_str()); sprintf(hex, "%s", hex); if(fPeggy && (vouts != 0)){ cJSON *peggyOut = cJSON_CreateObject(); jaddstr(peggyOut, "txid", (char*)tempTx.GetHash().ToString().c_str()); jaddnum(peggyOut, "time", tempTx.nTime); jaddnum(peggyOut, "txind", index); jaddnum(peggyOut, "amount", tempVout.nValue); jaddnum(peggyOut, "voutind", vouts); jaddstr(peggyOut, "scriptPubKey", hex); if(ExtractDestination(tempScriptPubKey, destAddress)){ jaddstr(peggyOut, "address", (char*)CBitcoinAddress(destAddress).ToString().c_str()); } else{ jaddstr(peggyOut, "address", "null"); } nPeggyPayments += (uint64_t)tempVout.nValue; jaddi(peggypayments, peggyOut); } else if(!fPeggy && (isOpReturn(hex) == 0)){ //peggy lock found cJSON *lockVout = cJSON_CreateObject(); jaddstr(lockVout, "txid", (char*)tempTx.GetHash().ToString().c_str()); jaddnum(lockVout, "time", tempTx.nTime); jaddnum(lockVout, "txind", index); jaddnum(lockVout, "voutind", vouts); jaddstr(lockVout, "scriptPubKey", hex); if(ExtractDestination(tempScriptPubKey, destAddress)){ jaddstr(lockVout, "address", (char*)CBitcoinAddress(destAddress).ToString().c_str()); } else{ jaddstr(lockVout, "address", "null"); } jaddnum(lockVout, "amount", (uint64_t)tempVout.nValue); jaddi(peggytx, lockVout); continue; //1 op_return per tx } } } jaddnum(peggybase, "amount", nPeggyPayments); jadd(arrayObj, "peggybase", peggybase); jadd(arrayObj, "peggypayments", peggypayments); jadd(arrayObj, "peggytx", peggytx); jaddi(array, arrayObj); return jprint(array,0); }
bool CzTNXTracker::UpdateStatusInternal(const std::set<uint256>& setMempool, CMintMeta& mint) { //! Check whether this mint has been spent and is considered 'pending' or 'confirmed' // If there is not a record of the block height, then look it up and assign it uint256 txidMint; bool isMintInChain = zerocoinDB->ReadCoinMint(mint.hashPubcoin, txidMint); //See if there is internal record of spending this mint (note this is memory only, would reset on restart) bool isPendingSpend = static_cast<bool>(mapPendingSpends.count(mint.hashSerial)); // See if there is a blockchain record of spending this mint uint256 txidSpend; bool isConfirmedSpend = zerocoinDB->ReadCoinSpend(mint.hashSerial, txidSpend); // Double check the mempool for pending spend if (isPendingSpend) { uint256 txidPendingSpend = mapPendingSpends.at(mint.hashSerial); if (!setMempool.count(txidPendingSpend) || isConfirmedSpend) { RemovePending(txidPendingSpend); isPendingSpend = false; LogPrintf("%s : Pending txid %s removed because not in mempool\n", __func__, txidPendingSpend.GetHex()); } } bool isUsed = isPendingSpend || isConfirmedSpend; if (!mint.nHeight || !isMintInChain || isUsed != mint.isUsed) { CTransaction tx; uint256 hashBlock; // Txid will be marked 0 if there is no knowledge of the final tx hash yet if (mint.txid == 0) { if (!isMintInChain) { LogPrintf("%s : Failed to find mint in zerocoinDB %s\n", __func__, mint.hashPubcoin.GetHex().substr(0, 6)); mint.isArchived = true; Archive(mint); return true; } mint.txid = txidMint; } if (setMempool.count(mint.txid)) return true; // Check the transaction associated with this mint if (!IsInitialBlockDownload() && !GetTransaction(mint.txid, tx, hashBlock, true)) { LogPrintf("%s : Failed to find tx for mint txid=%s\n", __func__, mint.txid.GetHex()); mint.isArchived = true; Archive(mint); return true; } // An orphan tx if hashblock is in mapBlockIndex but not in chain active if (mapBlockIndex.count(hashBlock) && !chainActive.Contains(mapBlockIndex.at(hashBlock))) { LogPrintf("%s : Found orphaned mint txid=%s\n", __func__, mint.txid.GetHex()); mint.isUsed = false; mint.nHeight = 0; if (tx.IsCoinStake()) { mint.isArchived = true; Archive(mint); } return true; } // Check that the mint has correct used status if (mint.isUsed != isUsed) { LogPrintf("%s : Set mint %s isUsed to %d\n", __func__, mint.hashPubcoin.GetHex(), isUsed); mint.isUsed = isUsed; return true; } } return false; }