Apply AreSane() checks to the fees from the network.

'Sane' was already defined by this code as:
 fee.GetFeePerK() > minRelayFee.GetFeePerK() * 10000
 But sanity was only enforced for data loaded from disk.

Note that this is a pretty expansive definition of 'sane': A 10 BTC
 fee is still passes the test if its on a 100kb transaction.

This prevents a single insane fee on the network from making us reject
 our stored fee data at start.  We still may reject valid saved fee
 state if minRelayFee is changed between executions.

This also reduces the risk and limits the damage from a cascading
 failure where one party pays a bunch of insane fees which cases
 others to pay insane fees.

Rebased-From: 6484930690
Github-Pull: #5481
This commit is contained in:
Gregory Maxwell 2014-12-15 14:38:25 -08:00 committed by Wladimir J. van der Laan
parent 11855c1f99
commit 15ad0b54fa
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6

View File

@ -91,22 +91,32 @@ public:
* Used as belt-and-suspenders check when reading to detect * Used as belt-and-suspenders check when reading to detect
* file corruption * file corruption
*/ */
bool AreSane(const std::vector<CFeeRate>& vecFee, const CFeeRate& minRelayFee) static bool AreSane(const CFeeRate fee, const CFeeRate& minRelayFee)
{
BOOST_FOREACH(CFeeRate fee, vecFee)
{ {
if (fee < CFeeRate(0)) if (fee < CFeeRate(0))
return false; return false;
if (fee.GetFeePerK() > minRelayFee.GetFeePerK() * 10000) if (fee.GetFeePerK() > minRelayFee.GetFeePerK() * 10000)
return false; return false;
return true;
}
static bool AreSane(const std::vector<CFeeRate>& vecFee, const CFeeRate& minRelayFee)
{
BOOST_FOREACH(CFeeRate fee, vecFee)
{
if (!AreSane(fee, minRelayFee))
return false;
} }
return true; return true;
} }
bool AreSane(const std::vector<double> vecPriority) static bool AreSane(const double priority)
{
return priority >= 0;
}
static bool AreSane(const std::vector<double> vecPriority)
{ {
BOOST_FOREACH(double priority, vecPriority) BOOST_FOREACH(double priority, vecPriority)
{ {
if (priority < 0) if (!AreSane(priority))
return false; return false;
} }
return true; return true;
@ -167,12 +177,12 @@ private:
bool sufficientFee = (feeRate > minRelayFee); bool sufficientFee = (feeRate > minRelayFee);
bool sufficientPriority = AllowFree(dPriority); bool sufficientPriority = AllowFree(dPriority);
const char* assignedTo = "unassigned"; const char* assignedTo = "unassigned";
if (sufficientFee && !sufficientPriority) if (sufficientFee && !sufficientPriority && CBlockAverage::AreSane(feeRate, minRelayFee))
{ {
history[nBlocksTruncated].RecordFee(feeRate); history[nBlocksTruncated].RecordFee(feeRate);
assignedTo = "fee"; assignedTo = "fee";
} }
else if (sufficientPriority && !sufficientFee) else if (sufficientPriority && !sufficientFee && CBlockAverage::AreSane(dPriority))
{ {
history[nBlocksTruncated].RecordPriority(dPriority); history[nBlocksTruncated].RecordPriority(dPriority);
assignedTo = "priority"; assignedTo = "priority";