[rpc] sendrawtransaction no longer bypasses minRelayTxFee

The prioritisetransaction API can always be used if a transaction needs to be submitted that bypasses minRelayTxFee.

(cherry picked from commit bitcoin/bitcoin@ad727f4eaf)

Signed-off-by: Daira Emma Hopwood <daira@jacaranda.org>
This commit is contained in:
Alex Morcos 2017-01-20 08:39:25 -05:00 committed by Daira Emma Hopwood
parent 1a57b52109
commit a4346b2012
10 changed files with 14 additions and 58 deletions

View File

@ -25,7 +25,6 @@ class MempoolPackagesTest(BitcoinTestFramework):
def setup_network(self): def setup_network(self):
base_args = [ base_args = [
"-maxorphantx=1000", "-maxorphantx=1000",
"-relaypriority=0",
"-debug", "-debug",
"-allowdeprecated=getnewaddress", "-allowdeprecated=getnewaddress",
] ]

View File

@ -29,7 +29,6 @@ class PrioritiseTransactionTest (BitcoinTestFramework):
args = [ args = [
"-blockmaxsize=11000", "-blockmaxsize=11000",
"-maxorphantx=1000", "-maxorphantx=1000",
"-relaypriority=true",
"-printpriority=1", "-printpriority=1",
"-limitancestorcount=900", "-limitancestorcount=900",
"-allowdeprecated=getnewaddress", "-allowdeprecated=getnewaddress",

View File

@ -156,7 +156,7 @@ class EstimateFeeTest(BitcoinTestFramework):
self.nodes = [] self.nodes = []
# Use node0 to mine blocks for input splitting # Use node0 to mine blocks for input splitting
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
"-relaypriority=0", "-whitelist=127.0.0.1"])) "-whitelist=127.0.0.1"]))
print("This test is time consuming, please be patient") print("This test is time consuming, please be patient")
print("Splitting inputs to small size so we can generate low priority tx's") print("Splitting inputs to small size so we can generate low priority tx's")
@ -188,17 +188,16 @@ class EstimateFeeTest(BitcoinTestFramework):
# Now we can connect the other nodes, didn't want to connect them earlier # Now we can connect the other nodes, didn't want to connect them earlier
# so the estimates would not be affected by the splitting transactions # so the estimates would not be affected by the splitting transactions
# Node1 mines small blocks but that are bigger than the expected transaction rate, # Node1 mines small blocks but that are bigger than the expected transaction rate.
# and allows free transactions.
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes, # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
# (17k is room enough for 110 or so transactions) # (17k is room enough for 110 or so transactions)
self.nodes.append(start_node(1, self.options.tmpdir, self.nodes.append(start_node(1, self.options.tmpdir,
["-blockmaxsize=18000", "-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"])) ["-blockmaxsize=18000", "-maxorphantx=1000", "-debug=estimatefee"]))
connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[1], 0)
# Node2 is a stingy miner, that # Node2 is a stingy miner, that
# produces too small blocks (room for only 70 or so transactions) # produces too small blocks (room for only 70 or so transactions)
node2args = ["-blockmaxsize=12000", "-maxorphantx=1000", "-relaypriority=0"] node2args = ["-blockmaxsize=12000", "-maxorphantx=1000"]
self.nodes.append(start_node(2, self.options.tmpdir, node2args)) self.nodes.append(start_node(2, self.options.tmpdir, node2args))
connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 2)

View File

@ -479,8 +479,6 @@ std::string HelpMessage(HelpMessageMode mode)
{ {
strUsage += HelpMessageOpt("-clockoffset=<n>", "Applies offset of <n> seconds to the actual time. Incompatible with -mocktime (default: 0)"); strUsage += HelpMessageOpt("-clockoffset=<n>", "Applies offset of <n> seconds to the actual time. Incompatible with -mocktime (default: 0)");
strUsage += HelpMessageOpt("-mocktime=<n>", "Replace actual time with <n> seconds since epoch. Incompatible with -clockoffset (default: 0)"); strUsage += HelpMessageOpt("-mocktime=<n>", "Replace actual time with <n> seconds since epoch. Incompatible with -clockoffset (default: 0)");
strUsage += HelpMessageOpt("-limitfreerelay=<n>", strprintf("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default: %u)", DEFAULT_LIMITFREERELAY));
strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", DEFAULT_RELAYPRIORITY));
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit total size of signature and bundle caches to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE)); strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit total size of signature and bundle caches to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE));
strUsage += HelpMessageOpt("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE)); strUsage += HelpMessageOpt("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE));
} }
@ -1227,7 +1225,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (nConnectTimeout <= 0) if (nConnectTimeout <= 0)
nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
// Fee-per-kilobyte amount considered the same as "free" // Fee-per-kilobyte amount required for mempool acceptance and relay
// If you are mining, be careful setting this: // If you are mining, be careful setting this:
// if you set it to zero then // if you set it to zero then
// a transaction spammer can cheaply fill blocks using // a transaction spammer can cheaply fill blocks using

View File

@ -1938,32 +1938,11 @@ bool AcceptToMemoryPool(
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), fSpendsCoinbase, nSigOps, consensusBranchId); CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), fSpendsCoinbase, nSigOps, consensusBranchId);
unsigned int nSize = entry.GetTxSize(); unsigned int nSize = entry.GetTxSize();
// Require that free transactions have sufficient priority to be mined in the next block. // No transactions are allowed with modified fee below the minimum relay fee,
if (GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && nModifiedFees < ::minRelayTxFee.GetFeeForRelay(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) { // except from disconnected blocks. The minimum relay fee will never be more
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority"); // than DEFAULT_FEE zatoshis.
} if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFeeForRelay(nSize)) {
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met");
// Continuously rate-limit free (really, very-low-fee) transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFeeForRelay(nSize))
{
static CCriticalSection csFreeLimiter;
static double dFreeCount;
static int64_t nLastTime;
int64_t nNow = GetTime();
LOCK(csFreeLimiter);
// Use an exponentially decaying ~10-minute window:
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
nLastTime = nNow;
// -limitfreerelay unit is thousand-bytes-per-minute
// At default rate it would take over a month to fill 1GB
if (dFreeCount >= GetArg("-limitfreerelay", DEFAULT_LIMITFREERELAY) * 10 * 1000)
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "rate limited free transaction");
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize;
} }
if (fRejectAbsurdFee && nFees > maxTxFee) { if (fRejectAbsurdFee && nFees > maxTxFee) {
@ -7175,7 +7154,7 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString()); LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString());
} }
// Has inputs but not accepted to mempool // Has inputs but not accepted to mempool
// Probably non-standard or insufficient fee/priority // Probably non-standard or insufficient fee
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString()); LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
vEraseQueue.push_back(orphanHash); vEraseQueue.push_back(orphanHash);
// Add the wtxid of this transaction to our reject filter. // Add the wtxid of this transaction to our reject filter.

View File

@ -135,8 +135,6 @@ static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5;
* Limits the impact of low-fee transaction floods. */ * Limits the impact of low-fee transaction floods. */
static const unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_INTERVAL; static const unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_INTERVAL;
static const unsigned int DEFAULT_LIMITFREERELAY = 15;
static const bool DEFAULT_RELAYPRIORITY = false;
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Default for -permitbaremultisig */ /** Default for -permitbaremultisig */

View File

@ -68,7 +68,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
" \"keypoolsize\": xxxx, (numeric, optional) how many new keys are pre-generated\n" " \"keypoolsize\": xxxx, (numeric, optional) how many new keys are pre-generated\n"
" \"unlocked_until\": ttt, (numeric, optional) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked, if wallet functionality is available and the wallet is encrypted\n" " \"unlocked_until\": ttt, (numeric, optional) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked, if wallet functionality is available and the wallet is encrypted\n"
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"relayfee\": x.xxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
" \"errors\": \"...\" (string) message describing the latest or highest-priority error\n" " \"errors\": \"...\" (string) message describing the latest or highest-priority error\n"
" \"errorstimestamp\": \"...\" (string) timestamp associated with the latest or highest-priority error\n" " \"errorstimestamp\": \"...\" (string) timestamp associated with the latest or highest-priority error\n"
"}\n" "}\n"

View File

@ -516,7 +516,7 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
" }\n" " }\n"
" ,...\n" " ,...\n"
" ],\n" " ],\n"
" \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
" \"localaddresses\": [ (array) list of local addresses\n" " \"localaddresses\": [ (array) list of local addresses\n"
" {\n" " {\n"
" \"address\": \"xxxx\", (string) network address\n" " \"address\": \"xxxx\", (string) network address\n"

View File

@ -1285,7 +1285,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
// push to local node and sync with wallets // push to local node and sync with wallets
CValidationState state; CValidationState state;
bool fMissingInputs; bool fMissingInputs;
if (!AcceptToMemoryPool(chainparams, mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) { if (!AcceptToMemoryPool(chainparams, mempool, state, tx, true, &fMissingInputs, !fOverrideFees)) {
if (state.IsInvalid()) { if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else { } else {

View File

@ -28,22 +28,6 @@
class CAutoFile; class CAutoFile;
inline double AllowFreeThreshold()
{
// 144 is the number of Bitcoin blocks per day. This has not been updated for Zcash,
// as it would make it harder to get shielded transactions into blocks by lowering the
// threshold at which we switch from priority-based selection of transactions into
// blocks to fee-based selection.
return COIN * 144 / 250;
}
inline bool AllowFree(double dPriority)
{
// Large (in bytes) low-priority (new, small-coin) transactions
// need a fee.
return dPriority > AllowFreeThreshold();
}
/** Version from which we write `fee_estimates.dat` without priority information: 5.5.0-beta1 or later */ /** Version from which we write `fee_estimates.dat` without priority information: 5.5.0-beta1 or later */
static const int FEE_ESTIMATES_WITHOUT_PRIORITY_VERSION = 5050000; static const int FEE_ESTIMATES_WITHOUT_PRIORITY_VERSION = 5050000;