mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-02 09:46:14 +00:00
refactor: interfaces, make 'createTransaction' less error-prone
Bundle all function's outputs inside the util::Result returned object. Reasons for the refactoring: - The 'change_pos' ref argument has been a source of bugs in the past. - The 'fee' ref argument is currently only set when the transaction creation process succeeds.
This commit is contained in:
parent
e2c3ec9bf4
commit
4c0d4f6f93
@ -40,6 +40,7 @@ namespace node {
|
||||
enum class TransactionError;
|
||||
} // namespace node
|
||||
namespace wallet {
|
||||
struct CreatedTransactionResult;
|
||||
class CCoinControl;
|
||||
class CWallet;
|
||||
enum class AddressPurpose;
|
||||
@ -142,11 +143,10 @@ public:
|
||||
virtual void listLockedCoins(std::vector<COutPoint>& outputs) = 0;
|
||||
|
||||
//! Create transaction.
|
||||
virtual util::Result<CTransactionRef> createTransaction(const std::vector<wallet::CRecipient>& recipients,
|
||||
virtual util::Result<wallet::CreatedTransactionResult> createTransaction(const std::vector<wallet::CRecipient>& recipients,
|
||||
const wallet::CCoinControl& coin_control,
|
||||
bool sign,
|
||||
int& change_pos,
|
||||
CAmount& fee) = 0;
|
||||
std::optional<unsigned int> change_pos) = 0;
|
||||
|
||||
//! Commit transaction.
|
||||
virtual void commitTransaction(CTransactionRef tx,
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <psbt.h>
|
||||
#include <util/translation.h>
|
||||
#include <wallet/coincontrol.h>
|
||||
#include <wallet/types.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <cstdint>
|
||||
@ -149,6 +150,8 @@ bool WalletModel::validateAddress(const QString& address) const
|
||||
|
||||
WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl)
|
||||
{
|
||||
transaction.getWtx() = nullptr; // reset tx output
|
||||
|
||||
CAmount total = 0;
|
||||
bool fSubtractFeeFromAmount = false;
|
||||
QList<SendCoinsRecipient> recipients = transaction.getRecipients();
|
||||
@ -199,22 +202,21 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
|
||||
}
|
||||
|
||||
try {
|
||||
CAmount nFeeRequired = 0;
|
||||
int nChangePosRet = -1;
|
||||
|
||||
auto& newTx = transaction.getWtx();
|
||||
const auto& res = m_wallet->createTransaction(vecSend, coinControl, /*sign=*/!wallet().privateKeysDisabled(), nChangePosRet, nFeeRequired);
|
||||
newTx = res ? *res : nullptr;
|
||||
transaction.setTransactionFee(nFeeRequired);
|
||||
if (fSubtractFeeFromAmount && newTx)
|
||||
transaction.reassignAmounts(nChangePosRet);
|
||||
|
||||
if (!newTx) {
|
||||
const auto& res = m_wallet->createTransaction(vecSend, coinControl, /*sign=*/!wallet().privateKeysDisabled(), /*change_pos=*/std::nullopt);
|
||||
if (!res) {
|
||||
Q_EMIT message(tr("Send Coins"), QString::fromStdString(util::ErrorString(res).translated),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
return TransactionCreationFailed;
|
||||
}
|
||||
|
||||
newTx = res->tx;
|
||||
CAmount nFeeRequired = res->fee;
|
||||
transaction.setTransactionFee(nFeeRequired);
|
||||
if (fSubtractFeeFromAmount && newTx) {
|
||||
transaction.reassignAmounts(static_cast<int>(res->change_pos.value_or(-1)));
|
||||
}
|
||||
|
||||
// Reject absurdly high fee. (This can never happen because the
|
||||
// wallet never creates transactions with fee greater than
|
||||
// m_default_max_tx_fee. This merely a belt-and-suspenders check).
|
||||
|
||||
@ -257,21 +257,13 @@ public:
|
||||
LOCK(m_wallet->cs_wallet);
|
||||
return m_wallet->ListLockedCoins(outputs);
|
||||
}
|
||||
util::Result<CTransactionRef> createTransaction(const std::vector<CRecipient>& recipients,
|
||||
util::Result<wallet::CreatedTransactionResult> createTransaction(const std::vector<CRecipient>& recipients,
|
||||
const CCoinControl& coin_control,
|
||||
bool sign,
|
||||
int& change_pos,
|
||||
CAmount& fee) override
|
||||
std::optional<unsigned int> change_pos) override
|
||||
{
|
||||
LOCK(m_wallet->cs_wallet);
|
||||
auto res = CreateTransaction(*m_wallet, recipients, change_pos == -1 ? std::nullopt : std::make_optional(change_pos),
|
||||
coin_control, sign);
|
||||
if (!res) return util::Error{util::ErrorString(res)};
|
||||
const auto& txr = *res;
|
||||
fee = txr.fee;
|
||||
change_pos = txr.change_pos ? int(*txr.change_pos) : -1;
|
||||
|
||||
return txr.tx;
|
||||
return CreateTransaction(*m_wallet, recipients, change_pos, coin_control, sign);
|
||||
}
|
||||
void commitTransaction(CTransactionRef tx,
|
||||
WalletValueMap value_map,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user