void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate) { LOCK(cs_feeEstimator); unsigned int txHeight = entry.GetHeight(); uint256 hash = entry.GetTx().GetHash(); if (mapMemPoolTxs.count(hash)) { LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error mempool tx %s already being tracked\n", hash.ToString().c_str()); return; } if (txHeight != nBestSeenHeight) { // Ignore side chains and re-orgs; assuming they are random they don't // affect the estimate. We'll potentially double count transactions in 1-block reorgs. // Ignore txs if BlockPolicyEstimator is not in sync with chainActive.Tip(). // It will be synced next time a block is processed. return; } // Only want to be updating estimates when our blockchain is synced, // otherwise we'll miscalculate how many blocks its taking to get included. if (!validFeeEstimate) { untrackedTxs++; return; } trackedTxs++; // Feerates are stored and reported as BTC-per-kb: CFeeRate feeRate(entry.GetFee(), entry.GetTxSize()); mapMemPoolTxs[hash].blockHeight = txHeight; mapMemPoolTxs[hash].bucketIndex = feeStats->NewTx(txHeight, (double)feeRate.GetFeePerK()); }
bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry) { if (!removeTx(entry->GetTx().GetHash(), true)) { // This transaction wasn't being tracked for fee estimation return false; } // How many blocks did it take for miners to include this transaction? // blocksToConfirm is 1-based, so a transaction included in the earliest // possible block has confirmation count of 1 int blocksToConfirm = nBlockHeight - entry->GetHeight(); if (blocksToConfirm <= 0) { // This can't happen because we don't process transactions from a block with a height // lower than our greatest seen height LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error Transaction had negative blocksToConfirm\n"); return false; } // Feerates are stored and reported as DGB-per-kb: CFeeRate feeRate(entry->GetFee(), entry->GetTxSize()); feeStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK()); shortStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK()); longStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK()); return true; }
void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool fCurrentEstimate) { unsigned int txHeight = entry.GetHeight(); uint256 hash = entry.GetTx().GetHash(); if (mapMemPoolTxs[hash].stats != NULL) { LogPrint("estimatefee", "Blockpolicy error mempool tx %s already being tracked\n", hash.ToString().c_str()); return; } if (txHeight < nBestSeenHeight) { // Ignore side chains and re-orgs; assuming they are random they don't // affect the estimate. We'll potentially double count transactions in 1-block reorgs. return; } // Only want to be updating estimates when our blockchain is synced, // otherwise we'll miscalculate how many blocks its taking to get included. if (!fCurrentEstimate) return; if (!entry.WasClearAtEntry()) { // This transaction depends on other transactions in the mempool to // be included in a block before it will be able to be included, so // we shouldn't include it in our calculations return; } // Fees are stored and reported as XRE-per-kb: CFeeRate feeRate(entry.GetFee(), entry.GetTxSize()); // Want the priority of the tx at confirmation. However we don't know // what that will be and its too hard to continue updating it // so use starting priority as a proxy double curPri = entry.GetPriority(txHeight); mapMemPoolTxs[hash].blockHeight = txHeight; LogPrint("estimatefee", "Blockpolicy mempool tx %s ", hash.ToString().substr(0,10)); // Record this as a priority estimate if (entry.GetFee() == 0 || isPriDataPoint(feeRate, curPri)) { mapMemPoolTxs[hash].stats = &priStats; mapMemPoolTxs[hash].bucketIndex = priStats.NewTx(txHeight, curPri); } // Record this as a fee estimate else if (isFeeDataPoint(feeRate, curPri)) { mapMemPoolTxs[hash].stats = &feeStats; mapMemPoolTxs[hash].bucketIndex = feeStats.NewTx(txHeight, (double)feeRate.GetFeePerK()); } else { LogPrint("estimatefee", "not adding"); } LogPrint("estimatefee", "\n"); }
void CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry& entry) { if (!entry.WasClearAtEntry()) { // This transaction depended on other transactions in the mempool to // be included in a block before it was able to be included, so // we shouldn't include it in our calculations return; } // How many blocks did it take for miners to include this transaction? // blocksToConfirm is 1-based, so a transaction included in the earliest // possible block has confirmation count of 1 int blocksToConfirm = nBlockHeight - entry.GetHeight(); if (blocksToConfirm <= 0) { // This can't happen because we don't process transactions from a block with a height // lower than our greatest seen height LogPrint("estimatefee", "Blockpolicy error Transaction had negative blocksToConfirm\n"); return; } // Fees are stored and reported as XRE-per-kb: CFeeRate feeRate(entry.GetFee(), entry.GetTxSize()); // Want the priority of the tx at confirmation. The priority when it // entered the mempool could easily be very small and change quickly double curPri = entry.GetPriority(nBlockHeight); // Record this as a priority estimate if (entry.GetFee() == 0 || isPriDataPoint(feeRate, curPri)) { priStats.Record(blocksToConfirm, curPri); } // Record this as a fee estimate else if (isFeeDataPoint(feeRate, curPri)) { feeStats.Record(blocksToConfirm, (double)feeRate.GetFeePerK()); } }