| 922 | } |
| 923 | |
| 924 | static RPCHelpMan sendrawtransaction() |
| 925 | { |
| 926 | return RPCHelpMan{"sendrawtransaction", |
| 927 | "\nSubmit a raw transaction (serialized, hex-encoded) to local node and network.\n" |
| 928 | "\nThe transaction will be sent unconditionally to all peers, so using sendrawtransaction\n" |
| 929 | "for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n" |
| 930 | "nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n" |
| 931 | "\nA specific exception, RPC_TRANSACTION_ALREADY_IN_CHAIN, may throw if the transaction cannot be added to the mempool.\n" |
| 932 | "\nRelated RPCs: createrawtransaction, signrawtransactionwithkey\n", |
| 933 | { |
| 934 | {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"}, |
| 935 | {"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())}, |
| 936 | "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + |
| 937 | "/kvB.\nSet to 0 to accept any fee rate.\n"}, |
| 938 | }, |
| 939 | RPCResult{ |
| 940 | RPCResult::Type::STR_HEX, "", "The transaction hash in hex" |
| 941 | }, |
| 942 | RPCExamples{ |
| 943 | "\nCreate a transaction\n" |
| 944 | + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\" : \\\"mytxid\\\",\\\"vout\\\":0}]\" \"{\\\"myaddress\\\":0.01}\"") + |
| 945 | "Sign the transaction, and get back the hex\n" |
| 946 | + HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + |
| 947 | "\nSend the transaction (signed hex)\n" |
| 948 | + HelpExampleCli("sendrawtransaction", "\"signedhex\"") + |
| 949 | "\nAs a JSON-RPC call\n" |
| 950 | + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") |
| 951 | }, |
| 952 | [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue |
| 953 | { |
| 954 | RPCTypeCheck(request.params, { |
| 955 | UniValue::VSTR, |
| 956 | UniValueType(), // VNUM or VSTR, checked inside AmountFromValue() |
| 957 | }); |
| 958 | |
| 959 | CMutableTransaction mtx; |
| 960 | if (!DecodeHexTx(mtx, request.params[0].get_str())) { |
| 961 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input."); |
| 962 | } |
| 963 | CTransactionRef tx(MakeTransactionRef(std::move(mtx))); |
| 964 | |
| 965 | const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ? |
| 966 | DEFAULT_MAX_RAW_TX_FEE_RATE : |
| 967 | CFeeRate(AmountFromValue(request.params[1])); |
| 968 | |
| 969 | for (const auto& out : tx->vout) { |
| 970 | // If we have a nonce, it could be a smuggled pubkey, or it could be a |
| 971 | // proper nonce produced by blinding. In the latter case, the value |
| 972 | // will always be blinded and not explicit. In the former case, we |
| 973 | // error out because the transaction is not blinded properly. |
| 974 | if (!out.nNonce.IsNull() && out.nValue.IsExplicit()) { |
| 975 | throw JSONRPCError(RPC_TRANSACTION_ERROR, "Transaction output has nonce, but is not blinded. Did you forget to call blindrawtransaction, or rawblindrawtransaction?"); |
| 976 | } |
| 977 | } |
| 978 | |
| 979 | int64_t virtual_size = GetVirtualTransactionSize(*tx); |
| 980 | CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size); |
| 981 |
nothing calls this directly
no test coverage detected