diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rpc/client.cpp | 1 | ||||
-rw-r--r-- | src/rpc/mempool.cpp | 16 | ||||
-rw-r--r-- | src/util/error.cpp | 2 | ||||
-rw-r--r-- | src/util/error.h | 1 |
4 files changed, 19 insertions, 1 deletions
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 5fe914f0a1..eb91a151b5 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -114,6 +114,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "signrawtransactionwithkey", 2, "prevtxs" }, { "signrawtransactionwithwallet", 1, "prevtxs" }, { "sendrawtransaction", 1, "maxfeerate" }, + { "sendrawtransaction", 2, "maxburnamount" }, { "testmempoolaccept", 0, "rawtxs" }, { "testmempoolaccept", 1, "maxfeerate" }, { "submitpackage", 0, "package" }, diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 44f7435a26..0e202a963d 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -18,6 +18,7 @@ #include <rpc/server.h> #include <rpc/server_util.h> #include <rpc/util.h> +#include <script/standard.h> #include <txmempool.h> #include <univalue.h> #include <util/moneystr.h> @@ -44,7 +45,11 @@ static RPCHelpMan sendrawtransaction() {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"}, {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())}, "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + - "/kvB.\nSet to 0 to accept any fee rate.\n"}, + "/kvB.\nSet to 0 to accept any fee rate."}, + {"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(0)}, + "Reject transactions with provably unspendable outputs (e.g. 'datacarrier' outputs that use the OP_RETURN opcode) greater than the specified value, expressed in " + CURRENCY_UNIT + ".\n" + "If burning funds through unspendable outputs is desired, increase this value.\n" + "This check is based on heuristics and does not guarantee spendability of outputs.\n"}, }, RPCResult{ RPCResult::Type::STR_HEX, "", "The transaction hash in hex" @@ -61,10 +66,19 @@ static RPCHelpMan sendrawtransaction() }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { + const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]); + CMutableTransaction mtx; if (!DecodeHexTx(mtx, request.params[0].get_str())) { throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input."); } + + for (const auto& out : mtx.vout) { + if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) { + throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED); + } + } + CTransactionRef tx(MakeTransactionRef(std::move(mtx))); const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ? diff --git a/src/util/error.cpp b/src/util/error.cpp index 193265c842..309877d067 100644 --- a/src/util/error.cpp +++ b/src/util/error.cpp @@ -33,6 +33,8 @@ bilingual_str TransactionErrorString(const TransactionError err) return Untranslated("Specified sighash value does not match value stored in PSBT"); case TransactionError::MAX_FEE_EXCEEDED: return Untranslated("Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)"); + case TransactionError::MAX_BURN_EXCEEDED: + return Untranslated("Unspendable output exceeds maximum configured by user (maxburnamount)"); case TransactionError::EXTERNAL_SIGNER_NOT_FOUND: return Untranslated("External signer not found"); case TransactionError::EXTERNAL_SIGNER_FAILED: diff --git a/src/util/error.h b/src/util/error.h index 649200c98e..a52a8f47de 100644 --- a/src/util/error.h +++ b/src/util/error.h @@ -30,6 +30,7 @@ enum class TransactionError { PSBT_MISMATCH, SIGHASH_MISMATCH, MAX_FEE_EXCEEDED, + MAX_BURN_EXCEEDED, EXTERNAL_SIGNER_NOT_FOUND, EXTERNAL_SIGNER_FAILED, INVALID_PACKAGE, |