@@ -1210,15 +1210,21 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
12101210 CAmount inChainInputValue;
12111211 double dPriority = view.GetPriority (tx, chainActive.Height (), inChainInputValue);
12121212
1213+ bool fIsWithdrawLockSpender = false ;
1214+
12131215 // Keep track of transactions that spend a coinbase, which we re-scan
12141216 // during reorgs to ensure COINBASE_MATURITY is still met.
1217+ // Also track withdraw lock spends to allow them through free relay
12151218 bool fSpendsCoinbase = false ;
12161219 BOOST_FOREACH (const CTxIn &txin, tx.vin ) {
12171220 const CCoins *coins = view.AccessCoins (txin.prevout .hash );
12181221 if (coins->IsCoinBase ()) {
12191222 fSpendsCoinbase = true ;
12201223 break ;
12211224 }
1225+ if (coins->vout [txin.prevout .n ].scriptPubKey .IsWithdrawLock ()) {
1226+ fIsWithdrawLockSpender = true ;
1227+ }
12221228 }
12231229
12241230 CTxMemPoolEntry entry (ptx, nFees, nAcceptTime, dPriority, chainActive.Height (),
@@ -1237,32 +1243,12 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
12371243 CAmount mempoolRejectFee = pool.GetMinFee (GetArg (" -maxmempool" , DEFAULT_MAX_MEMPOOL_SIZE) * 1000000 ).GetFee (nSize);
12381244 if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
12391245 return state.DoS (0 , false , REJECT_INSUFFICIENTFEE, " mempool min fee not met" , false , strprintf (" %d < %d" , nFees, mempoolRejectFee));
1240- } else if (GetBoolArg (" -relaypriority" , DEFAULT_RELAYPRIORITY) && nModifiedFees < ::minRelayTxFee.GetFee (nSize) && !AllowFree (entry.GetPriority (chainActive.Height () + 1 ))) {
1241- // Require that free transactions have sufficient priority to be mined in the next block.
1242- return state.DoS (0 , false , REJECT_INSUFFICIENTFEE, " insufficient priority" );
12431246 }
12441247
1245- // Continuously rate-limit free (really, very-low-fee) transactions
1246- // This mitigates 'penny-flooding' -- sending thousands of free transactions just to
1247- // be annoying or make others' transactions take longer to confirm.
1248- if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee (nSize))
1248+ // No transactions are allowed below minRelayTxFee except from disconnected blocks and withdraw lock spends
1249+ if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee (nSize) && !fIsWithdrawLockSpender )
12491250 {
1250- static CCriticalSection csFreeLimiter;
1251- static double dFreeCount;
1252- static int64_t nLastTime;
1253- int64_t nNow = GetTime ();
1254-
1255- LOCK (csFreeLimiter);
1256-
1257- // Use an exponentially decaying ~10-minute window:
1258- dFreeCount *= pow (1.0 - 1.0 /600.0 , (double )(nNow - nLastTime));
1259- nLastTime = nNow;
1260- // -limitfreerelay unit is thousand-bytes-per-minute
1261- // At default rate it would take over a month to fill 1GB
1262- if (dFreeCount + nSize >= GetArg (" -limitfreerelay" , DEFAULT_LIMITFREERELAY) * 10 * 1000 )
1263- return state.DoS (0 , false , REJECT_INSUFFICIENTFEE, " rate limited free transaction" );
1264- LogPrint (" mempool" , " Rate limit dFreeCount: %g => %g\n " , dFreeCount, dFreeCount+nSize);
1265- dFreeCount += nSize;
1251+ return state.DoS (0 , false , REJECT_INSUFFICIENTFEE, " min relay fee not met" );
12661252 }
12671253
12681254 if (nAbsurdFee && nFees > nAbsurdFee)
@@ -1605,8 +1591,10 @@ bool GetLockedOutputs(const uint256 &genesisHash, const CAmount &nAmount, std::v
16051591
16061592 std::vector<std::pair<COutPoint, CAmount> > locksCreated;
16071593 bool locksChanged = false ;
1608- if (!pblocktree->ReadLocksCreated (genesisHash, locksCreated))
1609- return false ;
1594+ // If this fails, we should still try to grab from mempool.
1595+ if (!pblocktree->ReadLocksCreated (genesisHash, locksCreated)) {
1596+ locksCreated.clear ();
1597+ }
16101598
16111599 // For faster random esasure
16121600 std::list<std::pair<COutPoint, CAmount> > locksList;
@@ -1646,8 +1634,9 @@ bool GetLockedOutputs(const uint256 &genesisHash, const CAmount &nAmount, std::v
16461634 pblocktree->ReWriteLocksCreated (genesisHash, vChangedLocks);
16471635 }
16481636 // Found single lock large enough
1649- if (res.size ())
1637+ if (res.size ()) {
16501638 return true ;
1639+ }
16511640
16521641 CAmount nTotal = 0 ;
16531642 // Gather up smaller locked outputs for aggregation.
@@ -1660,8 +1649,9 @@ bool GetLockedOutputs(const uint256 &genesisHash, const CAmount &nAmount, std::v
16601649 continue ;
16611650 }
16621651
1663- if (mempool.mapNextTx .count (COutPoint (it->first .hash , it->first .n )))
1652+ if (mempool.mapNextTx .count (COutPoint (it->first .hash , it->first .n ))) {
16641653 continue ;
1654+ }
16651655
16661656 assert (coins.vout [it->first .n ].nValue .IsExplicit () && coins.vout [it->first .n ].nValue .GetAmount () == it->second );
16671657 res.push_back (*it);
@@ -1689,20 +1679,28 @@ bool GetLockedOutputs(const uint256 &genesisHash, const CAmount &nAmount, std::v
16891679 const CTransaction& tx = *ptx;
16901680 for (unsigned int j = 0 ; j < tx.vout .size () && nTotal < nAmount; j++) {
16911681 CTxOut txout = tx.vout [j];
1692- if (!txout.scriptPubKey .IsWithdrawLock ())
1682+ if (!txout.scriptPubKey .IsWithdrawLock ()) {
16931683 continue ;
1684+ }
16941685
16951686 uint256 withdrawGenHash = txout.scriptPubKey .GetWithdrawLockGenesisHash ();
1696- if (genesisHash != withdrawGenHash)
1687+ if (genesisHash != withdrawGenHash) {
16971688 continue ;
1698- if (mempool.mapWithdrawsSpentToTxid .count (std::make_pair (withdrawGenHash, COutPoint (tx.GetHash (), j))))
1689+ }
1690+
1691+ // Only written locks are filtered previously for invalid type
1692+ if (txout.nValue .IsCommitment () || txout.nAsset .IsCommitment () || txout.nAsset .GetAsset () != BITCOINID) {
1693+ continue ;
1694+ }
1695+
1696+ if (mempool.mapNextTx .count (COutPoint (tx.GetHash (), j))) {
16991697 continue ;
1698+ }
17001699
1701- if (txout.scriptPubKey .IsWithdrawLock () && txout.nValue .IsExplicit ()) {
1702- res.push_back (std::make_pair (COutPoint (tx.GetHash (), j), txout.nValue .GetAmount ()));
1703- nTotal += txout.nValue .GetAmount ();
1704- if (nTotal >= nAmount)
1705- return true ;
1700+ res.push_back (std::make_pair (COutPoint (tx.GetHash (), j), txout.nValue .GetAmount ()));
1701+ nTotal += txout.nValue .GetAmount ();
1702+ if (nTotal >= nAmount) {
1703+ return true ;
17061704 }
17071705 }
17081706 }
@@ -1712,8 +1710,9 @@ bool GetLockedOutputs(const uint256 &genesisHash, const CAmount &nAmount, std::v
17121710 // res list is already randomized
17131711 nTotal = 0 ;
17141712 size_t i = 0 ;
1715- for (; i < res.size () && nTotal < nAmount; i++)
1713+ for (; i < res.size () && nTotal < nAmount; i++) {
17161714 nTotal += res[i].second ;
1715+ }
17171716
17181717 res.resize (i);
17191718 return true ;
0 commit comments