Merge #12356: Fix 'mempool min fee not met' debug output
bb00c95
Consistently use FormatStateMessage in RPC error output (Ben Woosley)8b8a1c4
Add test for 'mempool min fee not met' rpc error (Ben Woosley)c04e0f6
Fix 'mempool min fee not met' debug output (Ben Woosley) Pull request description: Output the value that is tested, rather than the unmodified fee value. Prompted by looking into: #11955 Tree-SHA512: fc0bad47d4af375d208f657a6ccbad6ef7f4e2989ae2ce1171226c22fa92847494a2c55cca687bd5a1548663ed3313569bcc31c00d53c0c193a1b865dd8a7657
This commit is contained in:
commit
fd65937ec6
10 changed files with 25 additions and 16 deletions
|
@ -1434,7 +1434,7 @@ UniValue preciousblock(const JSONRPCRequest& request)
|
||||||
PreciousBlock(state, Params(), pblockindex);
|
PreciousBlock(state, Params(), pblockindex);
|
||||||
|
|
||||||
if (!state.IsValid()) {
|
if (!state.IsValid()) {
|
||||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
@ -1472,7 +1472,7 @@ UniValue invalidateblock(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.IsValid()) {
|
if (!state.IsValid()) {
|
||||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
@ -1509,7 +1509,7 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
|
||||||
ActivateBestChain(state, Params());
|
ActivateBestChain(state, Params());
|
||||||
|
|
||||||
if (!state.IsValid()) {
|
if (!state.IsValid()) {
|
||||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
@ -1563,7 +1563,7 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
|
||||||
pindex = chainActive.Tip();
|
pindex = chainActive.Tip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pindex != nullptr);
|
assert(pindex != nullptr);
|
||||||
|
|
||||||
if (request.params[0].isNull()) {
|
if (request.params[0].isNull()) {
|
||||||
|
|
|
@ -264,11 +264,11 @@ static UniValue BIP22ValidationResult(const CValidationState& state)
|
||||||
if (state.IsValid())
|
if (state.IsValid())
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
|
||||||
std::string strRejectReason = state.GetRejectReason();
|
|
||||||
if (state.IsError())
|
if (state.IsError())
|
||||||
throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
|
throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
|
||||||
if (state.IsInvalid())
|
if (state.IsInvalid())
|
||||||
{
|
{
|
||||||
|
std::string strRejectReason = state.GetRejectReason();
|
||||||
if (strRejectReason.empty())
|
if (strRejectReason.empty())
|
||||||
return "rejected";
|
return "rejected";
|
||||||
return strRejectReason;
|
return strRejectReason;
|
||||||
|
|
|
@ -981,12 +981,12 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
|
||||||
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
|
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
|
||||||
nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
|
nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) {
|
||||||
if (state.IsInvalid()) {
|
if (state.IsInvalid()) {
|
||||||
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
|
throw JSONRPCError(RPC_TRANSACTION_REJECTED, FormatStateMessage(state));
|
||||||
} else {
|
} else {
|
||||||
if (fMissingInputs) {
|
if (fMissingInputs) {
|
||||||
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
|
throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
|
||||||
}
|
}
|
||||||
throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
|
throw JSONRPCError(RPC_TRANSACTION_ERROR, FormatStateMessage(state));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If wallet is enabled, ensure that the wallet has been made aware
|
// If wallet is enabled, ensure that the wallet has been made aware
|
||||||
|
|
|
@ -712,7 +712,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
||||||
|
|
||||||
CAmount mempoolRejectFee = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
|
CAmount mempoolRejectFee = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
|
||||||
if (!bypass_limits && mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
|
if (!bypass_limits && mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
|
||||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nModifiedFees, mempoolRejectFee));
|
||||||
}
|
}
|
||||||
|
|
||||||
// No transactions are allowed below minRelayTxFee except from disconnected blocks
|
// No transactions are allowed below minRelayTxFee except from disconnected blocks
|
||||||
|
|
|
@ -274,7 +274,7 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (!wallet->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) {
|
if (!wallet->CommitTransaction(wtxBumped, reservekey, g_connman.get(), state)) {
|
||||||
// NOTE: CommitTransaction never returns false, so this should never happen.
|
// NOTE: CommitTransaction never returns false, so this should never happen.
|
||||||
errors.push_back(strprintf("The transaction was rejected: %s", state.GetRejectReason()));
|
errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state)));
|
||||||
return Result::WALLET_ERROR;
|
return Result::WALLET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,4 +297,3 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace feebumper
|
} // namespace feebumper
|
||||||
|
|
||||||
|
|
|
@ -435,7 +435,7 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA
|
||||||
}
|
}
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
|
if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) {
|
||||||
strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason());
|
strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state));
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1155,7 @@ UniValue sendmany(const JSONRPCRequest& request)
|
||||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
|
if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) {
|
||||||
strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason());
|
strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state));
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
|
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3092,7 +3092,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
|
||||||
{
|
{
|
||||||
// Broadcast
|
// Broadcast
|
||||||
if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
|
if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
|
||||||
LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", state.GetRejectReason());
|
LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state));
|
||||||
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
|
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
|
||||||
} else {
|
} else {
|
||||||
wtx.RelayWalletTransaction(connman);
|
wtx.RelayWalletTransaction(connman);
|
||||||
|
|
|
@ -21,7 +21,7 @@ from test_framework.script import CScript
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import time
|
import time
|
||||||
|
|
||||||
NULLDUMMY_ERROR = "64: non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
|
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero) (code 64)"
|
||||||
|
|
||||||
def trueDummy(tx):
|
def trueDummy(tx):
|
||||||
scriptSig = CScript(tx.vin[0].scriptSig)
|
scriptSig = CScript(tx.vin[0].scriptSig)
|
||||||
|
|
|
@ -50,5 +50,15 @@ class MempoolLimitTest(BitcoinTestFramework):
|
||||||
assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000'))
|
assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000'))
|
||||||
assert_greater_than(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000'))
|
assert_greater_than(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000'))
|
||||||
|
|
||||||
|
self.log.info('Create a mempool tx that will not pass mempoolminfee')
|
||||||
|
us0 = utxos.pop()
|
||||||
|
inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
|
||||||
|
outputs = {self.nodes[0].getnewaddress() : 0.0001}
|
||||||
|
tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||||
|
# specifically fund this tx with a fee < mempoolminfee, >= than minrelaytxfee
|
||||||
|
txF = self.nodes[0].fundrawtransaction(tx, {'feeRate': relayfee})
|
||||||
|
txFS = self.nodes[0].signrawtransaction(txF['hex'])
|
||||||
|
assert_raises_rpc_error(-26, "mempool min fee not met, 166 < 411 (code 66)", self.nodes[0].sendrawtransaction, txFS['hex'])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
MempoolLimitTest().main()
|
MempoolLimitTest().main()
|
||||||
|
|
|
@ -120,7 +120,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
|
||||||
tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"]
|
tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"]
|
||||||
|
|
||||||
# This will raise an exception due to min relay fee not being met
|
# This will raise an exception due to min relay fee not being met
|
||||||
assert_raises_rpc_error(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx_hex)
|
assert_raises_rpc_error(-26, "min relay fee not met (code 66)", self.nodes[0].sendrawtransaction, tx_hex)
|
||||||
assert(tx_id not in self.nodes[0].getrawmempool())
|
assert(tx_id not in self.nodes[0].getrawmempool())
|
||||||
|
|
||||||
# This is a less than 1000-byte transaction, so just set the fee
|
# This is a less than 1000-byte transaction, so just set the fee
|
||||||
|
|
Loading…
Add table
Reference in a new issue