Skip to content

Commit f607f18

Browse files
committed
Change GetPriority calculation.
Compute the value of inputs that already are in the chain at time of mempool entry and only increase priority due to aging for those inputs. This effectively changes the CTxMemPoolEntry's GetPriority calculation from an upper bound to a lower bound. Coming from btc@c0353064ddf71ad103bd19f6e7c10ff8e240ac46
1 parent ac3c0f1 commit f607f18

File tree

6 files changed

+40
-17
lines changed

6 files changed

+40
-17
lines changed

src/coins.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,17 +267,19 @@ bool CCoinsViewCache::IsOutputAvailable(const uint256& txId, int index) {
267267
return coins && coins->IsAvailable(index);
268268
}
269269

270-
double CCoinsViewCache::GetPriority(const CTransaction& tx, int nHeight) const
270+
double CCoinsViewCache::GetPriority(const CTransaction& tx, int nHeight, CAmount &inChainInputValue) const
271271
{
272+
inChainInputValue = 0;
272273
if (tx.IsCoinBase() || tx.IsCoinStake())
273274
return 0.0;
274275
double dResult = 0.0;
275276
for (const CTxIn& txin : tx.vin) {
276277
const CCoins* coins = AccessCoins(txin.prevout.hash);
277278
assert(coins);
278279
if (!coins->IsAvailable(txin.prevout.n)) continue;
279-
if (coins->nHeight < nHeight) {
280+
if (coins->nHeight <= nHeight) {
280281
dResult += coins->vout[txin.prevout.n].nValue * (nHeight - coins->nHeight);
282+
inChainInputValue += coins->vout[txin.prevout.n].nValue;
281283
}
282284
}
283285
return tx.ComputePriority(dResult);

src/coins.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,12 @@ class CCoinsViewCache : public CCoinsViewBacked
457457
//! Check if the specific output is available in this view
458458
bool IsOutputAvailable(const uint256& txId, int index);
459459

460-
//! Return priority of tx at height nHeight
461-
double GetPriority(const CTransaction& tx, int nHeight) const;
460+
/**
461+
* Return priority of tx at height nHeight. Also calculate the sum of the values of the inputs
462+
* that are already in the chain. These are the inputs that will age and increase priority as
463+
* new blocks are added to the chain.
464+
*/
465+
double GetPriority(const CTransaction& tx, int nHeight, CAmount &inChainInputValue) const;
462466

463467
const CTxOut& GetOutputFor(const CTxIn& input) const;
464468

src/main.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -996,11 +996,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
996996

997997
CAmount nValueOut = tx.GetValueOut();
998998
CAmount nFees = nValueIn - nValueOut;
999+
CAmount inChainInputValue = 0;
9991000
double dPriority = 0;
10001001
if (!hasZcSpendInputs)
1001-
dPriority = view.GetPriority(tx, chainHeight);
1002+
dPriority = view.GetPriority(tx, chainHeight, inChainInputValue);
10021003

1003-
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainHeight, pool.HasNoInputsOf(tx));
1004+
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainHeight, pool.HasNoInputsOf(tx), inChainInputValue);
10041005
unsigned int nSize = entry.GetTxSize();
10051006

10061007
// Don't accept it if it can't get into a block
@@ -1011,7 +1012,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
10111012
strprintf("%d < %d", nFees, txMinFee));
10121013

10131014
// Require that free transactions have sufficient priority to be mined in the next block.
1014-
if (!hasZcSpendInputs && GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainHeight + 1))) {
1015+
if (!hasZcSpendInputs && GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainHeight + 1))) {
10151016
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
10161017
}
10171018

@@ -1222,9 +1223,10 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState& state, const CTransact
12221223

12231224
CAmount nValueOut = tx.GetValueOut();
12241225
CAmount nFees = nValueIn - nValueOut;
1225-
double dPriority = view.GetPriority(tx, chainHeight);
1226+
CAmount inChainInputValue;
1227+
double dPriority = view.GetPriority(tx, chainHeight, inChainInputValue);
12261228

1227-
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainHeight, mempool.HasNoInputsOf(tx));
1229+
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainHeight, mempool.HasNoInputsOf(tx), inChainInputValue);
12281230
unsigned int nSize = entry.GetTxSize();
12291231

12301232
// Don't accept it if it can't get into a block
@@ -1242,7 +1244,7 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState& state, const CTransact
12421244
if (mempoolRejectFee > 0 && nFees < mempoolRejectFee) {
12431245
return state.DoS(0, error("%s : insuffiecient fee: %d < %d",
12441246
__func__, nFees, mempoolRejectFee), REJECT_INSUFFICIENTFEE, "mempool min fee not met", false);
1245-
} else if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
1247+
} else if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) {
12461248
// Require that free transactions have sufficient priority to be mined in the next block.
12471249
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
12481250
}

src/test/test_pivx.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,13 @@ TestingSetup::~TestingSetup()
6969
}
7070

7171
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
72-
return CTxMemPoolEntry(tx, nFee, nTime, dPriority, nHeight,
73-
pool ? pool->HasNoInputsOf(tx) : hadNoDependencies);
72+
CTransaction txn(tx);
73+
bool hasNoDependencies = pool ? pool->HasNoInputsOf(tx) : hadNoDependencies;
74+
// Hack to assume either its completely dependent on other mempool txs or not at all
75+
CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0;
76+
77+
return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
78+
hasNoDependencies, inChainValue);
7479
}
7580

7681
[[noreturn]] void Shutdown(void* parg)

src/txmempool.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323
CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
2424
int64_t _nTime, double _entryPriority,
25-
unsigned int _entryHeight, bool poolHasNoInputsOf) :
26-
tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), hadNoDependencies(poolHasNoInputsOf)
25+
unsigned int _entryHeight, bool poolHasNoInputsOf, CAmount _inChainInputValue) :
26+
tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue)
2727
{
2828
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
2929
nModSize = tx.CalculateModifiedSize(nTxSize);
@@ -33,6 +33,8 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
3333
nCountWithDescendants = 1;
3434
nSizeWithDescendants = nTxSize;
3535
nFeesWithDescendants = nFee;
36+
CAmount nValueIn = tx.GetValueOut()+nFee;
37+
assert(inChainInputValue <= nValueIn);
3638
}
3739

3840
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
@@ -43,9 +45,10 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
4345
double
4446
CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
4547
{
46-
CAmount nValueIn = tx.GetValueOut() + nFee;
47-
double deltaPriority = ((double)(currentHeight - entryHeight) * nValueIn) / nModSize;
48+
double deltaPriority = ((double)(currentHeight - entryHeight) * inChainInputValue) / nModSize;
4849
double dResult = entryPriority + deltaPriority;
50+
if (dResult < 0) // This should only happen if it was called with a height below entry height
51+
dResult = 0;
4952
return dResult;
5053
}
5154

src/txmempool.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class CTxMemPoolEntry
6969
double entryPriority; //! Priority when entering the mempool
7070
unsigned int entryHeight; //! Chain height when entering the mempool
7171
bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool
72+
CAmount inChainInputValue; //! Sum of all txin values that are already in blockchain
7273

7374
// Information about descendants of this transaction that are in the
7475
// mempool; if we remove this transaction we must remove all of these
@@ -80,10 +81,16 @@ class CTxMemPoolEntry
8081
CAmount nFeesWithDescendants; //! ... and total fees (all including us)
8182

8283
public:
83-
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee, int64_t _nTime, double _entryPriority, unsigned int _entryHeight, bool poolHasNoInputsOf);
84+
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
85+
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
86+
bool poolHasNoInputsOf, CAmount _inChainInputValue);
8487
CTxMemPoolEntry(const CTxMemPoolEntry& other);
8588

8689
const CTransaction& GetTx() const { return this->tx; }
90+
/**
91+
* Fast calculation of lower bound of current priority as update
92+
* from entry priority. Only inputs that were originally in-chain will age.
93+
*/
8794
double GetPriority(unsigned int currentHeight) const;
8895
const CAmount& GetFee() const { return nFee; }
8996
size_t GetTxSize() const { return nTxSize; }

0 commit comments

Comments
 (0)