Skip to content

Commit

Permalink
FillPSBT: report number of inputs signed (or would sign)
Browse files Browse the repository at this point in the history
In FillPSBT, optionally report the number of inputs we successfully
signed, as an out parameter. If "sign" is false, instead report the
number of inputs for which GetSigningProvider does not return nullptr.
(This is a potentially overbroad estimate of inputs we could sign.)
  • Loading branch information
gwillen committed Jun 19, 2020
1 parent 9e7b23b commit 5dd0c03
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 13 deletions.
5 changes: 3 additions & 2 deletions src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,10 @@ class WalletImpl : public Wallet
bool sign,
bool bip32derivs,
PartiallySignedTransaction& psbtx,
bool& complete) override
bool& complete,
size_t* n_signed) override
{
return m_wallet->FillPSBT(psbtx, complete, sighash_type, sign, bip32derivs);
return m_wallet->FillPSBT(psbtx, complete, sighash_type, sign, bip32derivs, n_signed);
}
WalletBalances getBalances() override
{
Expand Down
3 changes: 2 additions & 1 deletion src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ class Wallet
bool sign,
bool bip32derivs,
PartiallySignedTransaction& psbtx,
bool& complete) = 0;
bool& complete,
size_t* n_signed) = 0;

//! Get balances.
virtual WalletBalances getBalances() = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/qt/sendcoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ void SendCoinsDialog::on_sendButton_clicked()
CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
const TransactionError err = model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, psbtx, complete);
const TransactionError err = model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, psbtx, complete, nullptr);
assert(!complete);
assert(err == TransactionError::OK);
// Serialize the PSBT
Expand Down
2 changes: 1 addition & 1 deletion src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash)
if (create_psbt) {
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
const TransactionError err = wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, psbtx, complete);
const TransactionError err = wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, psbtx, complete, nullptr);
if (err != TransactionError::OK || complete) {
QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't draft transaction."));
return false;
Expand Down
26 changes: 24 additions & 2 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,11 @@ SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, con
return SigningResult::SIGNING_FAILED;
}

TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs) const
TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
{
if (n_signed) {
*n_signed = 0;
}
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
const CTxIn& txin = psbtx.tx->vin[i];
PSBTInput& input = psbtx.inputs.at(i);
Expand Down Expand Up @@ -617,6 +620,14 @@ TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psb
SignatureData sigdata;
input.FillSignatureData(sigdata);
SignPSBTInput(HidingSigningProvider(this, !sign, !bip32derivs), psbtx, i, sighash_type);

bool signed_one = PSBTInputSigned(input);
if (n_signed && (signed_one || !sign)) {
// If sign is false, we assume that we _could_ sign if we get here. This
// will never have false negatives; it is hard to tell under what i
// circumstances it could have false positives.
(*n_signed)++;
}
}

// Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
Expand Down Expand Up @@ -2064,8 +2075,11 @@ SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message,
return SigningResult::OK;
}

TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs) const
TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
{
if (n_signed) {
*n_signed = 0;
}
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
const CTxIn& txin = psbtx.tx->vin[i];
PSBTInput& input = psbtx.inputs.at(i);
Expand Down Expand Up @@ -2117,6 +2131,14 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction&
}

SignPSBTInput(HidingSigningProvider(keys.get(), !sign, !bip32derivs), psbtx, i, sighash_type);

bool signed_one = PSBTInputSigned(input);
if (n_signed && (signed_one || !sign)) {
// If sign is false, we assume that we _could_ sign if we get here. This
// will never have false negatives; it is hard to tell under what i
// circumstances it could have false positives.
(*n_signed)++;
}
}

// Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change
Expand Down
6 changes: 3 additions & 3 deletions src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class ScriptPubKeyMan
/** Sign a message with the given script */
virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
/** Adds script and derivation path information to a PSBT, and optionally signs it. */
virtual TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const { return TransactionError::INVALID_PSBT; }
virtual TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const { return TransactionError::INVALID_PSBT; }

virtual uint256 GetID() const { return uint256(); }

Expand Down Expand Up @@ -393,7 +393,7 @@ class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProv

bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const override;
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const override;

uint256 GetID() const override;

Expand Down Expand Up @@ -596,7 +596,7 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan

bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false) const override;
TransactionError FillPSBT(PartiallySignedTransaction& psbt, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const override;

uint256 GetID() const override;

Expand Down
12 changes: 10 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2471,8 +2471,11 @@ 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
TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs, size_t * n_signed) const
{
if (n_signed) {
*n_signed = 0;
}
LOCK(cs_wallet);
// Get all of the previous transactions
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
Expand Down Expand Up @@ -2503,10 +2506,15 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp

// Fill in information from ScriptPubKeyMans
for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs);
int n_signed_this_spkm = 0;
TransactionError res = spk_man->FillPSBT(psbtx, sighash_type, sign, bip32derivs, &n_signed_this_spkm);
if (res != TransactionError::OK) {
return res;
}

if (n_signed) {
(*n_signed) += n_signed_this_spkm;
}
}

// Complete if every input is now signed
Expand Down
3 changes: 2 additions & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,8 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
bool& complete,
int sighash_type = 1 /* SIGHASH_ALL */,
bool sign = true,
bool bip32derivs = true) const;
bool bip32derivs = true,
size_t* n_signed = nullptr) const;

/**
* Create a new transaction paying the recipients with a set of coins
Expand Down

0 comments on commit 5dd0c03

Please sign in to comment.