mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
merge bitcoin#8365: Treat high-sigop transactions as larger rather than rejecting them (#4562)
This commit is contained in:
parent
d4910cab3b
commit
0a760bb809
@ -14,11 +14,11 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po
|
||||
int64_t nTime = 0;
|
||||
unsigned int nHeight = 1;
|
||||
bool spendsCoinbase = false;
|
||||
unsigned int sigOpCost = 4;
|
||||
unsigned int sigOps = 1;
|
||||
LockPoints lp;
|
||||
pool.addUnchecked(CTxMemPoolEntry(
|
||||
tx, nFee, nTime, nHeight,
|
||||
spendsCoinbase, sigOpCost, lp));
|
||||
spendsCoinbase, sigOps, lp));
|
||||
}
|
||||
|
||||
// Right now this is only testing eviction performance in an extremely small
|
||||
|
@ -15,7 +15,7 @@
|
||||
static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs)
|
||||
{
|
||||
LockPoints lp;
|
||||
pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOpCost */ 4, lp));
|
||||
pool.addUnchecked(CTxMemPoolEntry(tx, fee, /* time */ 0, /* height */ 1, /* spendsCoinbase */ false, /* sigOps */ 1, lp));
|
||||
}
|
||||
|
||||
static void RpcMempool(benchmark::Bench& bench)
|
||||
|
@ -698,7 +698,7 @@ void SetupServerArgs()
|
||||
gArgs.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), true, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), true, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), true, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-bytespersigop", strprintf("Minimum bytes per sigop in transactions we relay and mine (default: %u)", DEFAULT_BYTES_PER_SIGOP), false, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), false, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), false, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), false, OptionsCategory::NODE_RELAY);
|
||||
gArgs.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
|
||||
|
@ -170,5 +170,16 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
||||
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
||||
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
||||
|
||||
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOp)
|
||||
{
|
||||
return std::max(nSize, nSigOp * nBytesPerSigOp);
|
||||
}
|
||||
|
||||
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOp)
|
||||
{
|
||||
return GetVirtualTransactionSize(tx.GetTotalSize(), nSigOp);
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ static const unsigned int MAX_STANDARD_TX_SIGOPS = 4000;
|
||||
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
|
||||
/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP 125 replacement **/
|
||||
static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE = 1000;
|
||||
/** Default for -bytespersigop */
|
||||
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
|
||||
/** Min feerate for defining dust. Historically this has been based on the
|
||||
* minRelayTxFee, however changing the dust limit changes which transactions are
|
||||
* standard and should be done with care and ideally rarely. It makes sense to
|
||||
@ -81,6 +83,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
|
||||
*/
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||
|
||||
extern unsigned int nBytesPerSigOp;
|
||||
|
||||
/** Compute the virtual transaction size (taking sigops into account). */
|
||||
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOp);
|
||||
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOp = 0);
|
||||
|
||||
extern CFeeRate incrementalRelayFee;
|
||||
extern CFeeRate dustRelayFee;
|
||||
#endif // BITCOIN_POLICY_POLICY_H
|
||||
|
@ -3,6 +3,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <txmempool.h>
|
||||
#include <policy/policy.h>
|
||||
#include <util/system.h>
|
||||
|
||||
#include <test/setup_common.h>
|
||||
@ -308,7 +309,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
|
||||
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
|
||||
tx2.vout[0].nValue = 2 * COIN;
|
||||
pool.addUnchecked(entry.Fee(20000LL).FromTx(tx2));
|
||||
uint64_t tx2Size = ::GetSerializeSize(tx2, SER_NETWORK, PROTOCOL_VERSION);
|
||||
uint64_t tx2Size = GetVirtualTransactionSize(CTransaction(tx2));
|
||||
|
||||
/* lowest fee */
|
||||
CMutableTransaction tx3 = CMutableTransaction();
|
||||
@ -356,7 +357,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
|
||||
tx6.vout.resize(1);
|
||||
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
|
||||
tx6.vout[0].nValue = 20 * COIN;
|
||||
uint64_t tx6Size = ::GetSerializeSize(tx6, SER_NETWORK, PROTOCOL_VERSION);
|
||||
uint64_t tx6Size = GetVirtualTransactionSize(CTransaction(tx6));
|
||||
|
||||
pool.addUnchecked(entry.Fee(0LL).FromTx(tx6));
|
||||
BOOST_CHECK_EQUAL(pool.size(), 6U);
|
||||
@ -375,7 +376,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
|
||||
tx7.vout.resize(1);
|
||||
tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
|
||||
tx7.vout[0].nValue = 10 * COIN;
|
||||
uint64_t tx7Size = ::GetSerializeSize(tx7, SER_NETWORK, PROTOCOL_VERSION);
|
||||
uint64_t tx7Size = GetVirtualTransactionSize(CTransaction(tx7));
|
||||
|
||||
/* set the fee to just below tx2's feerate when including ancestor */
|
||||
CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1;
|
||||
@ -463,12 +464,12 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||
BOOST_CHECK(pool.exists(tx2.GetHash()));
|
||||
BOOST_CHECK(pool.exists(tx3.GetHash()));
|
||||
|
||||
pool.TrimToSize(::GetSerializeSize(CTransaction(tx1), SER_NETWORK, PROTOCOL_VERSION)); // mempool is limited to tx1's size in memory usage, so nothing fits
|
||||
pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits
|
||||
BOOST_CHECK(!pool.exists(tx1.GetHash()));
|
||||
BOOST_CHECK(!pool.exists(tx2.GetHash()));
|
||||
BOOST_CHECK(!pool.exists(tx3.GetHash()));
|
||||
|
||||
CFeeRate maxFeeRateRemoved(25000, ::GetSerializeSize(CTransaction(tx3), SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(CTransaction(tx2), SER_NETWORK, PROTOCOL_VERSION));
|
||||
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
|
||||
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
|
||||
|
||||
CMutableTransaction tx4 = CMutableTransaction();
|
||||
|
@ -135,7 +135,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
|
||||
uint256 hashFreeTx = tx.GetHash();
|
||||
mempool.addUnchecked(entry.Fee(0).FromTx(tx));
|
||||
size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||
size_t freeTxSize = GetVirtualTransactionSize(CTransaction(tx));
|
||||
|
||||
// Calculate a fee on child transaction that will put the package just
|
||||
// below the block min tx fee (assuming 1 child tx of the same size).
|
||||
|
@ -3,6 +3,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <txmempool.h>
|
||||
#include <uint256.h>
|
||||
#include <util/system.h>
|
||||
@ -43,7 +44,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
|
||||
tx.vin[0].scriptSig = garbage;
|
||||
tx.vout.resize(1);
|
||||
tx.vout[0].nValue=0LL;
|
||||
CFeeRate baseRate(basefee, ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
|
||||
CFeeRate baseRate(basefee, GetVirtualTransactionSize(CTransaction(tx)));
|
||||
|
||||
// Create a fake block
|
||||
std::vector<CTransactionRef> block;
|
||||
|
@ -135,7 +135,7 @@ struct TestMemPoolEntryHelper
|
||||
|
||||
TestMemPoolEntryHelper() :
|
||||
nFee(0), nTime(0), nHeight(1),
|
||||
spendsCoinbase(false), sigOpCount(4) { }
|
||||
spendsCoinbase(false), sigOpCount(1) { }
|
||||
|
||||
CTxMemPoolEntry FromTx(const CMutableTransaction& tx);
|
||||
CTxMemPoolEntry FromTx(const CTransactionRef& tx);
|
||||
|
@ -32,13 +32,13 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFe
|
||||
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp), m_epoch(0)
|
||||
{
|
||||
nCountWithDescendants = 1;
|
||||
nSizeWithDescendants = nTxSize;
|
||||
nSizeWithDescendants = GetTxSize();
|
||||
nModFeesWithDescendants = nFee;
|
||||
|
||||
feeDelta = 0;
|
||||
|
||||
nCountWithAncestors = 1;
|
||||
nSizeWithAncestors = nTxSize;
|
||||
nSizeWithAncestors = GetTxSize();
|
||||
nModFeesWithAncestors = nFee;
|
||||
nSigOpCountWithAncestors = sigOpCount;
|
||||
}
|
||||
@ -55,6 +55,11 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
|
||||
lockPoints = lp;
|
||||
}
|
||||
|
||||
size_t CTxMemPoolEntry::GetTxSize() const
|
||||
{
|
||||
return GetVirtualTransactionSize(nTxSize, sigOpCount);
|
||||
}
|
||||
|
||||
// Update the given tx for any in-mempool descendants.
|
||||
// Assumes that setMemPoolChildren is correct for the given tx and all
|
||||
// descendants.
|
||||
|
@ -103,7 +103,7 @@ public:
|
||||
const CTransaction& GetTx() const { return *this->tx; }
|
||||
CTransactionRef GetSharedTx() const { return this->tx; }
|
||||
const CAmount& GetFee() const { return nFee; }
|
||||
size_t GetTxSize() const { return nTxSize; }
|
||||
size_t GetTxSize() const;
|
||||
int64_t GetTime() const { return nTime; }
|
||||
unsigned int GetHeight() const { return entryHeight; }
|
||||
unsigned int GetSigOpCount() const { return sigOpCount; }
|
||||
|
@ -143,7 +143,6 @@ bool fHavePruned = false;
|
||||
bool fPruneMode = false;
|
||||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
||||
bool fRequireStandard = true;
|
||||
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
||||
bool fCheckBlockIndex = false;
|
||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||
size_t nCoinCacheUsage = 5000 * 300;
|
||||
@ -682,7 +681,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
||||
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
|
||||
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
|
||||
// merely non-standard transaction.
|
||||
if ((nSigOps > MAX_STANDARD_TX_SIGOPS) || (nBytesPerSigOp && nSigOps > nSize / nBytesPerSigOp))
|
||||
if (nSigOps > MAX_STANDARD_TX_SIGOPS)
|
||||
return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false,
|
||||
strprintf("%d", nSigOps));
|
||||
|
||||
|
@ -85,7 +85,6 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 6 * 60 * 60; // ~144 blocks behind ->
|
||||
|
||||
/** Default for -permitbaremultisig */
|
||||
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
|
||||
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
|
||||
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
|
||||
static const bool DEFAULT_TXINDEX = true;
|
||||
static const bool DEFAULT_ADDRESSINDEX = false;
|
||||
@ -146,7 +145,6 @@ extern bool fIsBareMultisigStd;
|
||||
*/
|
||||
extern bool g_parallel_script_checks;
|
||||
extern bool fRequireStandard;
|
||||
extern unsigned int nBytesPerSigOp;
|
||||
extern bool fCheckBlockIndex;
|
||||
extern bool fCheckpointsEnabled;
|
||||
extern size_t nCoinCacheUsage;
|
||||
|
Loading…
Reference in New Issue
Block a user