Changeset View
Changeset View
Standalone View
Standalone View
src/policy/fees.cpp
Show First 20 Lines • Show All 337 Lines • ▼ Show 20 Lines | bool CBlockPolicyEstimator::removeTx(uint256 hash) { | ||||
return true; | return true; | ||||
} | } | ||||
CBlockPolicyEstimator::CBlockPolicyEstimator() | CBlockPolicyEstimator::CBlockPolicyEstimator() | ||||
: nBestSeenHeight(0), trackedTxs(0), untrackedTxs(0) { | : nBestSeenHeight(0), trackedTxs(0), untrackedTxs(0) { | ||||
static_assert(MIN_FEERATE > Amount(0), "Min feerate must be nonzero"); | static_assert(MIN_FEERATE > Amount(0), "Min feerate must be nonzero"); | ||||
CFeeRate minFeeRate(MIN_FEERATE); | CFeeRate minFeeRate(MIN_FEERATE); | ||||
std::vector<double> vfeelist; | std::vector<double> vfeelist; | ||||
for (double bucketBoundary = minFeeRate.GetFeePerK().GetSatoshis(); | for (double bucketBoundary = minFeeRate.GetFeePerK() / SATOSHI; | ||||
bucketBoundary <= double(MAX_FEERATE.GetSatoshis()); | bucketBoundary <= double(MAX_FEERATE / SATOSHI); | ||||
bucketBoundary *= FEE_SPACING) { | bucketBoundary *= FEE_SPACING) { | ||||
vfeelist.push_back(bucketBoundary); | vfeelist.push_back(bucketBoundary); | ||||
} | } | ||||
vfeelist.push_back(double(INF_FEERATE.GetSatoshis())); | vfeelist.push_back(double(INF_FEERATE / SATOSHI)); | ||||
feeStats.Initialize(vfeelist, MAX_BLOCK_CONFIRMS, DEFAULT_DECAY); | feeStats.Initialize(vfeelist, MAX_BLOCK_CONFIRMS, DEFAULT_DECAY); | ||||
} | } | ||||
void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry &entry, | void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry &entry, | ||||
bool validFeeEstimate) { | bool validFeeEstimate) { | ||||
uint32_t txHeight = entry.GetHeight(); | uint32_t txHeight = entry.GetHeight(); | ||||
uint256 txid = entry.GetTx().GetId(); | uint256 txid = entry.GetTx().GetId(); | ||||
if (mapMemPoolTxs.count(txid)) { | if (mapMemPoolTxs.count(txid)) { | ||||
Show All 20 Lines | void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry &entry, | ||||
} | } | ||||
trackedTxs++; | trackedTxs++; | ||||
// Feerates are stored and reported as BCH-per-kb: | // Feerates are stored and reported as BCH-per-kb: | ||||
CFeeRate feeRate(entry.GetFee(), entry.GetTxSize()); | CFeeRate feeRate(entry.GetFee(), entry.GetTxSize()); | ||||
mapMemPoolTxs[txid].blockHeight = txHeight; | mapMemPoolTxs[txid].blockHeight = txHeight; | ||||
mapMemPoolTxs[txid].bucketIndex = | mapMemPoolTxs[txid].bucketIndex = | ||||
feeStats.NewTx(txHeight, double(feeRate.GetFeePerK().GetSatoshis())); | feeStats.NewTx(txHeight, double(feeRate.GetFeePerK() / SATOSHI)); | ||||
} | } | ||||
bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, | bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, | ||||
const CTxMemPoolEntry *entry) { | const CTxMemPoolEntry *entry) { | ||||
if (!removeTx(entry->GetTx().GetId())) { | if (!removeTx(entry->GetTx().GetId())) { | ||||
// This transaction wasn't being tracked for fee estimation | // This transaction wasn't being tracked for fee estimation | ||||
return false; | return false; | ||||
} | } | ||||
Show All 9 Lines | if (blocksToConfirm <= 0) { | ||||
BCLog::ESTIMATEFEE, | BCLog::ESTIMATEFEE, | ||||
"Blockpolicy error Transaction had negative blocksToConfirm\n"); | "Blockpolicy error Transaction had negative blocksToConfirm\n"); | ||||
return false; | return false; | ||||
} | } | ||||
// Feerates are stored and reported as BCH-per-kb: | // Feerates are stored and reported as BCH-per-kb: | ||||
CFeeRate feeRate(entry->GetFee(), entry->GetTxSize()); | CFeeRate feeRate(entry->GetFee(), entry->GetTxSize()); | ||||
feeStats.Record(blocksToConfirm, | feeStats.Record(blocksToConfirm, double(feeRate.GetFeePerK() / SATOSHI)); | ||||
(double)feeRate.GetFeePerK().GetSatoshis()); | |||||
return true; | return true; | ||||
} | } | ||||
void CBlockPolicyEstimator::processBlock( | void CBlockPolicyEstimator::processBlock( | ||||
unsigned int nBlockHeight, std::vector<const CTxMemPoolEntry *> &entries) { | unsigned int nBlockHeight, std::vector<const CTxMemPoolEntry *> &entries) { | ||||
if (nBlockHeight <= nBestSeenHeight) { | if (nBlockHeight <= nBestSeenHeight) { | ||||
// Ignore side chains and re-orgs; assuming they are random they don't | // Ignore side chains and re-orgs; assuming they are random they don't | ||||
// affect the estimate. And if an attacker can re-org the chain at will, | // affect the estimate. And if an attacker can re-org the chain at will, | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | if (nFileVersion < 139900) { | ||||
priStats.Read(filein); | priStats.Read(filein); | ||||
} | } | ||||
} | } | ||||
FeeFilterRounder::FeeFilterRounder(const CFeeRate &minIncrementalFee) { | FeeFilterRounder::FeeFilterRounder(const CFeeRate &minIncrementalFee) { | ||||
Amount minFeeLimit = | Amount minFeeLimit = | ||||
std::max(Amount(1), minIncrementalFee.GetFeePerK() / 2); | std::max(Amount(1), minIncrementalFee.GetFeePerK() / 2); | ||||
feeset.insert(Amount(0)); | feeset.insert(Amount(0)); | ||||
for (double bucketBoundary = minFeeLimit.GetSatoshis(); | for (double bucketBoundary = minFeeLimit / SATOSHI; | ||||
bucketBoundary <= double(MAX_FEERATE.GetSatoshis()); | bucketBoundary <= double(MAX_FEERATE / SATOSHI); | ||||
bucketBoundary *= FEE_SPACING) { | bucketBoundary *= FEE_SPACING) { | ||||
feeset.insert(Amount(int64_t(bucketBoundary))); | feeset.insert(Amount(int64_t(bucketBoundary))); | ||||
} | } | ||||
} | } | ||||
Amount FeeFilterRounder::round(const Amount currentMinFee) { | Amount FeeFilterRounder::round(const Amount currentMinFee) { | ||||
auto it = feeset.lower_bound(currentMinFee); | auto it = feeset.lower_bound(currentMinFee); | ||||
if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || | if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || | ||||
it == feeset.end()) { | it == feeset.end()) { | ||||
it--; | it--; | ||||
} | } | ||||
return *it; | return *it; | ||||
} | } |