Skip to content

Commit

Permalink
wallet/rpc: add maxfeerate parameter to testmempoolaccept
Browse files Browse the repository at this point in the history
  • Loading branch information
kallewoof committed Mar 13, 2019
1 parent 6c0a6f7 commit 7abd2e6
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendrawtransaction", 1, "maxfeerate" },
{ "testmempoolaccept", 0, "rawtxs" },
{ "testmempoolaccept", 1, "allowhighfees" },
{ "testmempoolaccept", 1, "maxfeerate" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
{ "fundrawtransaction", 2, "iswitness" },
Expand Down
26 changes: 20 additions & 6 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
{"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
},
},
{"allowhighfees", RPCArg::Type::BOOL, /* default */ "false", "Allow high fees"},
{"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(maxTxFee), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"},
},
RPCResult{
"[ (array) The result of the mempool acceptance test for each raw transaction in the input array.\n"
Expand All @@ -1133,7 +1133,11 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
}.ToString());
}

RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL});
RPCTypeCheck(request.params, {
UniValue::VARR,
UniValueType(), // NUM or BOOL, checked later
});

if (request.params[0].get_array().size() != 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now");
}
Expand All @@ -1145,9 +1149,19 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
const uint256& tx_hash = tx->GetHash();

CAmount max_raw_tx_fee = ::maxTxFee;
if (!request.params[1].isNull() && request.params[1].get_bool()) {
max_raw_tx_fee = 0;
CAmount max_raw_tx_fee = maxTxFee;
// TODO: temporary migration code for old clients. Remove in v0.20
if (request.params[1].isBool()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
} else if (request.params[1].isNum()) {
size_t weight = GetTransactionWeight(*tx);
CFeeRate fr(AmountFromValue(request.params[1]));
// the +3/4 part rounds the value up, and is the same formula used when
// calculating the fee for a transaction
// (see GetVirtualTransactionSize)
max_raw_tx_fee = fr.GetFee((weight+3)/4);
} else if (!request.params[1].isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "second argument (maxfeerate) must be numeric");
}

UniValue result(UniValue::VARR);
Expand Down Expand Up @@ -2068,7 +2082,7 @@ static const CRPCCommand commands[] =
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
{ "hidden", "signrawtransaction", &signrawtransaction, {"hexstring","prevtxs","privkeys","sighashtype"} },
{ "rawtransactions", "signrawtransactionwithkey", &signrawtransactionwithkey, {"hexstring","privkeys","prevtxs","sighashtype"} },
{ "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees"} },
{ "rawtransactions", "testmempoolaccept", &testmempoolaccept, {"rawtxs","allowhighfees|maxfeerate"} },
{ "rawtransactions", "decodepsbt", &decodepsbt, {"psbt"} },
{ "rawtransactions", "combinepsbt", &combinepsbt, {"txs"} },
{ "rawtransactions", "finalizepsbt", &finalizepsbt, {"psbt", "extract"} },
Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_cltv.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def run_test(self):
# rejected from the mempool for exactly that reason.
assert_equal(
[{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Negative locktime)'}],
self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], allowhighfees=True)
self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0)
)

# Now we verify that a block with this transaction is also invalid.
Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_dersig.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def run_test(self):
# rejected from the mempool for exactly that reason.
assert_equal(
[{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Non-canonical DER signature)'}],
self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], allowhighfees=True)
self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0)
)

# Now we verify that a block with this transaction is also invalid.
Expand Down
12 changes: 9 additions & 3 deletions test/functional/rpc_rawtransaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ def run_test(self):
decrawtx = self.nodes[0].decoderawtransaction(rawtx)
assert_equal(decrawtx['version'], 0x7fffffff)

self.log.info('sendrawtransaction with maxfeerate')
self.log.info('sendrawtransaction/testmempoolaccept with maxfeerate')

txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
rawTx = self.nodes[0].getrawtransaction(txId, True)
Expand All @@ -439,9 +439,15 @@ def run_test(self):
rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx)
assert_equal(rawTxSigned['complete'], True)
# 1000 sat fee, ~200 b transaction, fee rate should land around 5 sat/b = 0.00005000 BTC/kB
# Thus, below call should fail
# Thus, testmempoolaccept should reject
testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']], 0.00001000)[0]
assert_equal(testres['allowed'], False)
assert_equal(testres['reject-reason'], '256: absurdly-high-fee')
# and sendrawtransaction should throw
assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], 0.00001000)
# And below call should succeed
# And below calls should both succeed
testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']], maxfeerate=0.00007000)[0]
assert_equal(testres['allowed'], True)
self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'], maxfeerate=0.00007000)


Expand Down

0 comments on commit 7abd2e6

Please sign in to comment.