mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 20:03:34 -03:00
Move FillPSBT to be a member of CWallet
This commit is contained in:
parent
a4af324d15
commit
3d70dd99f9
10 changed files with 99 additions and 122 deletions
|
@ -241,7 +241,6 @@ BITCOIN_CORE_H = \
|
|||
wallet/fees.h \
|
||||
wallet/ismine.h \
|
||||
wallet/load.h \
|
||||
wallet/psbtwallet.h \
|
||||
wallet/rpcwallet.h \
|
||||
wallet/scriptpubkeyman.h \
|
||||
wallet/wallet.h \
|
||||
|
@ -349,7 +348,6 @@ libbitcoin_wallet_a_SOURCES = \
|
|||
wallet/feebumper.cpp \
|
||||
wallet/fees.cpp \
|
||||
wallet/load.cpp \
|
||||
wallet/psbtwallet.cpp \
|
||||
wallet/rpcdump.cpp \
|
||||
wallet/rpcwallet.cpp \
|
||||
wallet/scriptpubkeyman.cpp \
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <wallet/fees.h>
|
||||
#include <wallet/ismine.h>
|
||||
#include <wallet/load.h>
|
||||
#include <wallet/psbtwallet.h>
|
||||
#include <wallet/rpcwallet.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
|
@ -361,9 +360,9 @@ public:
|
|||
bool& complete,
|
||||
int sighash_type = 1 /* SIGHASH_ALL */,
|
||||
bool sign = true,
|
||||
bool bip32derivs = false) override
|
||||
bool bip32derivs = false) const override
|
||||
{
|
||||
return FillPSBT(m_wallet.get(), psbtx, complete, sighash_type, sign, bip32derivs);
|
||||
return m_wallet->FillPSBT(psbtx, complete, sighash_type, sign, bip32derivs);
|
||||
}
|
||||
WalletBalances getBalances() override
|
||||
{
|
||||
|
|
|
@ -196,7 +196,7 @@ public:
|
|||
bool& complete,
|
||||
int sighash_type = 1 /* SIGHASH_ALL */,
|
||||
bool sign = true,
|
||||
bool bip32derivs = false) = 0;
|
||||
bool bip32derivs = false) const = 0;
|
||||
|
||||
//! Get balances.
|
||||
virtual WalletBalances getBalances() = 0;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <ui_interface.h>
|
||||
#include <wallet/coincontrol.h>
|
||||
#include <wallet/fees.h>
|
||||
#include <wallet/psbtwallet.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <QFontMetrics>
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
// Copyright (c) 2009-2019 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <wallet/psbtwallet.h>
|
||||
|
||||
TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs)
|
||||
{
|
||||
LOCK(pwallet->cs_wallet);
|
||||
// Get all of the previous transactions
|
||||
complete = true;
|
||||
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
|
||||
const CTxIn& txin = psbtx.tx->vin[i];
|
||||
PSBTInput& input = psbtx.inputs.at(i);
|
||||
|
||||
if (PSBTInputSigned(input)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
|
||||
if (!input.IsSane()) {
|
||||
return TransactionError::INVALID_PSBT;
|
||||
}
|
||||
|
||||
// If we have no utxo, grab it from the wallet.
|
||||
if (!input.non_witness_utxo && input.witness_utxo.IsNull()) {
|
||||
const uint256& txhash = txin.prevout.hash;
|
||||
const auto it = pwallet->mapWallet.find(txhash);
|
||||
if (it != pwallet->mapWallet.end()) {
|
||||
const CWalletTx& wtx = it->second;
|
||||
// We only need the non_witness_utxo, which is a superset of the witness_utxo.
|
||||
// The signing code will switch to the smaller witness_utxo if this is ok.
|
||||
input.non_witness_utxo = wtx.tx;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Sighash type
|
||||
if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
|
||||
return TransactionError::SIGHASH_MISMATCH;
|
||||
}
|
||||
|
||||
// Get the scriptPubKey to know which SigningProvider to use
|
||||
CScript script;
|
||||
if (!input.witness_utxo.IsNull()) {
|
||||
script = input.witness_utxo.scriptPubKey;
|
||||
} else if (input.non_witness_utxo) {
|
||||
if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
|
||||
return TransactionError::MISSING_INPUTS;
|
||||
}
|
||||
script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
|
||||
} else {
|
||||
// There's no UTXO so we can just skip this now
|
||||
complete = false;
|
||||
continue;
|
||||
}
|
||||
SignatureData sigdata;
|
||||
input.FillSignatureData(sigdata);
|
||||
std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(script, sigdata);
|
||||
if (!provider) {
|
||||
complete = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
complete &= SignPSBTInput(HidingSigningProvider(provider.get(), !sign, !bip32derivs), psbtx, i, sighash_type);
|
||||
}
|
||||
|
||||
// Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
|
||||
for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
|
||||
const CTxOut& out = psbtx.tx->vout.at(i);
|
||||
std::unique_ptr<SigningProvider> provider = pwallet->GetSigningProvider(out.scriptPubKey);
|
||||
if (provider) {
|
||||
UpdatePSBTOutput(HidingSigningProvider(provider.get(), true, !bip32derivs), psbtx, i);
|
||||
}
|
||||
}
|
||||
|
||||
return TransactionError::OK;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) 2009-2019 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_WALLET_PSBTWALLET_H
|
||||
#define BITCOIN_WALLET_PSBTWALLET_H
|
||||
|
||||
#include <psbt.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
/**
|
||||
* Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
|
||||
* them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
|
||||
* (i.e. has all required signatures or signature-parts, and is ready to
|
||||
* finalize.) Sets `error` and returns false if something goes wrong.
|
||||
*
|
||||
* @param[in] pwallet pointer to a wallet
|
||||
* @param[in] psbtx PartiallySignedTransaction to fill in
|
||||
* @param[out] complete indicates whether the PSBT is now complete
|
||||
* @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
|
||||
* @param[in] sign whether to sign or not
|
||||
* @param[in] bip32derivs whether to fill in bip32 derivation information if available
|
||||
* return error
|
||||
*/
|
||||
NODISCARD TransactionError FillPSBT(const CWallet* pwallet,
|
||||
PartiallySignedTransaction& psbtx,
|
||||
bool& complete,
|
||||
int sighash_type = 1 /* SIGHASH_ALL */,
|
||||
bool sign = true,
|
||||
bool bip32derivs = true);
|
||||
|
||||
#endif // BITCOIN_WALLET_PSBTWALLET_H
|
|
@ -27,7 +27,6 @@
|
|||
#include <util/vector.h>
|
||||
#include <wallet/coincontrol.h>
|
||||
#include <wallet/feebumper.h>
|
||||
#include <wallet/psbtwallet.h>
|
||||
#include <wallet/rpcwallet.h>
|
||||
#include <wallet/wallet.h>
|
||||
#include <wallet/walletdb.h>
|
||||
|
@ -3516,7 +3515,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
|
|||
} else {
|
||||
PartiallySignedTransaction psbtx(mtx);
|
||||
bool complete = false;
|
||||
const TransactionError err = FillPSBT(pwallet, psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
|
||||
const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_ALL, false /* sign */, true /* bip32derivs */);
|
||||
CHECK_NONFATAL(err == TransactionError::OK);
|
||||
CHECK_NONFATAL(!complete);
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -4133,7 +4132,7 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
|
|||
bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();
|
||||
bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
|
||||
bool complete = true;
|
||||
const TransactionError err = FillPSBT(pwallet, psbtx, complete, nHashType, sign, bip32derivs);
|
||||
const TransactionError err = pwallet->FillPSBT(psbtx, complete, nHashType, sign, bip32derivs);
|
||||
if (err != TransactionError::OK) {
|
||||
throw JSONRPCTransactionError(err);
|
||||
}
|
||||
|
@ -4256,7 +4255,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
|
|||
// Fill transaction with out data but don't sign
|
||||
bool bip32derivs = request.params[4].isNull() ? true : request.params[4].get_bool();
|
||||
bool complete = true;
|
||||
const TransactionError err = FillPSBT(pwallet, psbtx, complete, 1, false, bip32derivs);
|
||||
const TransactionError err = pwallet->FillPSBT(psbtx, complete, 1, false, bip32derivs);
|
||||
if (err != TransactionError::OK) {
|
||||
throw JSONRPCTransactionError(err);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <key_io.h>
|
||||
#include <util/bip32.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <wallet/psbtwallet.h>
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
@ -61,7 +60,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
|
|||
|
||||
// Fill transaction with our data
|
||||
bool complete = true;
|
||||
BOOST_REQUIRE_EQUAL(TransactionError::OK, FillPSBT(&m_wallet, psbtx, complete, SIGHASH_ALL, false, true));
|
||||
BOOST_REQUIRE_EQUAL(TransactionError::OK, m_wallet.FillPSBT(psbtx, complete, SIGHASH_ALL, false, true));
|
||||
|
||||
// Get the final tx
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
|
|
@ -2477,6 +2477,78 @@ bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint,
|
|||
return false;
|
||||
}
|
||||
|
||||
TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
// Get all of the previous transactions
|
||||
complete = true;
|
||||
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
|
||||
const CTxIn& txin = psbtx.tx->vin[i];
|
||||
PSBTInput& input = psbtx.inputs.at(i);
|
||||
|
||||
if (PSBTInputSigned(input)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify input looks sane. This will check that we have at most one uxto, witness or non-witness.
|
||||
if (!input.IsSane()) {
|
||||
return TransactionError::INVALID_PSBT;
|
||||
}
|
||||
|
||||
// If we have no utxo, grab it from the wallet.
|
||||
if (!input.non_witness_utxo && input.witness_utxo.IsNull()) {
|
||||
const uint256& txhash = txin.prevout.hash;
|
||||
const auto it = mapWallet.find(txhash);
|
||||
if (it != mapWallet.end()) {
|
||||
const CWalletTx& wtx = it->second;
|
||||
// We only need the non_witness_utxo, which is a superset of the witness_utxo.
|
||||
// The signing code will switch to the smaller witness_utxo if this is ok.
|
||||
input.non_witness_utxo = wtx.tx;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Sighash type
|
||||
if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) {
|
||||
return TransactionError::SIGHASH_MISMATCH;
|
||||
}
|
||||
|
||||
// Get the scriptPubKey to know which SigningProvider to use
|
||||
CScript script;
|
||||
if (!input.witness_utxo.IsNull()) {
|
||||
script = input.witness_utxo.scriptPubKey;
|
||||
} else if (input.non_witness_utxo) {
|
||||
if (txin.prevout.n >= input.non_witness_utxo->vout.size()) {
|
||||
return TransactionError::MISSING_INPUTS;
|
||||
}
|
||||
script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
|
||||
} else {
|
||||
// There's no UTXO so we can just skip this now
|
||||
complete = false;
|
||||
continue;
|
||||
}
|
||||
SignatureData sigdata;
|
||||
input.FillSignatureData(sigdata);
|
||||
std::unique_ptr<SigningProvider> provider = GetSigningProvider(script, sigdata);
|
||||
if (!provider) {
|
||||
complete = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
complete &= SignPSBTInput(HidingSigningProvider(provider.get(), !sign, !bip32derivs), psbtx, i, sighash_type);
|
||||
}
|
||||
|
||||
// Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
|
||||
for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) {
|
||||
const CTxOut& out = psbtx.tx->vout.at(i);
|
||||
std::unique_ptr<SigningProvider> provider = GetSigningProvider(out.scriptPubKey);
|
||||
if (provider) {
|
||||
UpdatePSBTOutput(HidingSigningProvider(provider.get(), true, !bip32derivs), psbtx, i);
|
||||
}
|
||||
}
|
||||
|
||||
return TransactionError::OK;
|
||||
}
|
||||
|
||||
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
|
||||
{
|
||||
std::vector<CRecipient> vecSend;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <interfaces/handler.h>
|
||||
#include <outputtype.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <psbt.h>
|
||||
#include <tinyformat.h>
|
||||
#include <ui_interface.h>
|
||||
#include <util/strencodings.h>
|
||||
|
@ -921,6 +922,25 @@ public:
|
|||
// Sign the tx given the input coins and sighash.
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const;
|
||||
|
||||
/**
|
||||
* Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
|
||||
* them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
|
||||
* (i.e. has all required signatures or signature-parts, and is ready to
|
||||
* finalize.) Sets `error` and returns false if something goes wrong.
|
||||
*
|
||||
* @param[in] psbtx PartiallySignedTransaction to fill in
|
||||
* @param[out] complete indicates whether the PSBT is now complete
|
||||
* @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
|
||||
* @param[in] sign whether to sign or not
|
||||
* @param[in] bip32derivs whether to fill in bip32 derivation information if available
|
||||
* return error
|
||||
*/
|
||||
TransactionError FillPSBT(PartiallySignedTransaction& psbtx,
|
||||
bool& complete,
|
||||
int sighash_type = 1 /* SIGHASH_ALL */,
|
||||
bool sign = true,
|
||||
bool bip32derivs = true) const;
|
||||
|
||||
/**
|
||||
* Create a new transaction paying the recipients with a set of coins
|
||||
* selected by SelectCoins(); Also create the change output, when needed
|
||||
|
|
Loading…
Reference in a new issue