mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-04 18:22:57 +02:00
rpc: Support version 3 transaction creation
Adds v3 support to the following RPCs: - createrawtransaction - createpsbt - send - sendall - walletcreatefundedpsbt Co-authored-by: chungeun-choi <cucuridas@gmail.com> Co-authored-by: dongwook-chan <dongwook.chan@gmail.com> Co-authored-by: sean-k1 <uhs2000@naver.com> Co-authored-by: ishaanam <ishaana.misra@gmail.com>
This commit is contained in:
@@ -21,6 +21,8 @@ namespace wallet {
|
||||
const int DEFAULT_MIN_DEPTH = 0;
|
||||
const int DEFAULT_MAX_DEPTH = 9999999;
|
||||
|
||||
const int DEFAULT_WALLET_TX_VERSION = CTransaction::CURRENT_VERSION;
|
||||
|
||||
//! Default for -avoidpartialspends
|
||||
static constexpr bool DEFAULT_AVOIDPARTIALSPENDS = false;
|
||||
|
||||
@@ -110,7 +112,7 @@ public:
|
||||
//! SigningProvider that has pubkeys and scripts to do spend size estimation for external inputs
|
||||
FlatSigningProvider m_external_provider;
|
||||
//! Version
|
||||
uint32_t m_version = CTransaction::CURRENT_VERSION;
|
||||
uint32_t m_version = DEFAULT_WALLET_TX_VERSION;
|
||||
//! Locktime
|
||||
std::optional<uint32_t> m_locktime;
|
||||
//! Caps weight of resulting tx
|
||||
|
||||
@@ -1276,6 +1276,7 @@ RPCHelpMan send()
|
||||
},
|
||||
FundTxDoc()),
|
||||
RPCArgOptions{.oneline_description="options"}},
|
||||
{"version", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_WALLET_TX_VERSION}, "Transaction version"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
@@ -1315,8 +1316,9 @@ RPCHelpMan send()
|
||||
ParseOutputs(outputs),
|
||||
InterpretSubtractFeeFromOutputInstructions(options["subtract_fee_from_outputs"], outputs.getKeys())
|
||||
);
|
||||
CMutableTransaction rawTx = ConstructTransaction(options["inputs"], request.params[0], options["locktime"], rbf);
|
||||
CCoinControl coin_control;
|
||||
coin_control.m_version = self.Arg<uint32_t>("version");
|
||||
CMutableTransaction rawTx = ConstructTransaction(options["inputs"], request.params[0], options["locktime"], rbf, coin_control.m_version);
|
||||
// Automatically select coins, unless at least one is manually selected. Can
|
||||
// be overridden by options.add_inputs.
|
||||
coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;
|
||||
@@ -1383,6 +1385,7 @@ RPCHelpMan sendall()
|
||||
{"send_max", RPCArg::Type::BOOL, RPCArg::Default{false}, "When true, only use UTXOs that can pay for their own fees to maximize the output amount. When 'false' (default), no UTXO is left behind. send_max is incompatible with providing specific inputs."},
|
||||
{"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "Require inputs with at least this many confirmations."},
|
||||
{"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Require inputs with at most this many confirmations."},
|
||||
{"version", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_WALLET_TX_VERSION}, "Transaction version"},
|
||||
},
|
||||
FundTxDoc()
|
||||
),
|
||||
@@ -1463,6 +1466,10 @@ RPCHelpMan sendall()
|
||||
}
|
||||
}
|
||||
|
||||
if (options.exists("version")) {
|
||||
coin_control.m_version = options["version"].getInt<int>();
|
||||
}
|
||||
|
||||
if (coin_control.m_version == TRUC_VERSION) {
|
||||
coin_control.m_max_tx_weight = TRUC_MAX_WEIGHT;
|
||||
} else {
|
||||
@@ -1483,7 +1490,7 @@ RPCHelpMan sendall()
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
|
||||
}
|
||||
|
||||
CMutableTransaction rawTx{ConstructTransaction(options["inputs"], recipient_key_value_pairs, options["locktime"], rbf)};
|
||||
CMutableTransaction rawTx{ConstructTransaction(options["inputs"], recipient_key_value_pairs, options["locktime"], rbf, coin_control.m_version)};
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
CAmount total_input_value(0);
|
||||
@@ -1501,6 +1508,13 @@ RPCHelpMan sendall()
|
||||
if (!tx || input.prevout.n >= tx->tx->vout.size() || !(pwallet->IsMine(tx->tx->vout[input.prevout.n]) & ISMINE_SPENDABLE)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));
|
||||
}
|
||||
if (pwallet->GetTxDepthInMainChain(*tx) == 0) {
|
||||
if (tx->tx->version == TRUC_VERSION && coin_control.m_version != TRUC_VERSION) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Can't spend unconfirmed version 3 pre-selected input with a version %d tx", coin_control.m_version));
|
||||
} else if (coin_control.m_version == TRUC_VERSION && tx->tx->version != TRUC_VERSION) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Can't spend unconfirmed version %d pre-selected input with a version 3 tx", tx->tx->version));
|
||||
}
|
||||
}
|
||||
total_input_value += tx->tx->vout[input.prevout.n].nValue;
|
||||
}
|
||||
} else {
|
||||
@@ -1749,6 +1763,7 @@ RPCHelpMan walletcreatefundedpsbt()
|
||||
FundTxDoc()),
|
||||
RPCArgOptions{.oneline_description="options"}},
|
||||
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
|
||||
{"version", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_WALLET_TX_VERSION}, "Transaction version"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
@@ -1776,16 +1791,18 @@ RPCHelpMan walletcreatefundedpsbt()
|
||||
|
||||
UniValue options{request.params[3].isNull() ? UniValue::VOBJ : request.params[3]};
|
||||
|
||||
CCoinControl coin_control;
|
||||
coin_control.m_version = self.Arg<uint32_t>("version");
|
||||
|
||||
const UniValue &replaceable_arg = options["replaceable"];
|
||||
const bool rbf{replaceable_arg.isNull() ? wallet.m_signal_rbf : replaceable_arg.get_bool()};
|
||||
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf);
|
||||
CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf, coin_control.m_version);
|
||||
UniValue outputs(UniValue::VOBJ);
|
||||
outputs = NormalizeOutputs(request.params[1]);
|
||||
std::vector<CRecipient> recipients = CreateRecipients(
|
||||
ParseOutputs(outputs),
|
||||
InterpretSubtractFeeFromOutputInstructions(options["subtractFeeFromOutputs"], outputs.getKeys())
|
||||
);
|
||||
CCoinControl coin_control;
|
||||
// Automatically select coins, unless at least one is manually selected. Can
|
||||
// be overridden by options.add_inputs.
|
||||
coin_control.m_allow_other_inputs = rawTx.vin.size() == 0;
|
||||
|
||||
Reference in New Issue
Block a user