mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-28 04:52:36 +02:00
script: Return total sum of input amounts from SignTransaction when available
This commit is contained in:
parent
bbbf89a9de
commit
97282b0903
@ -17,6 +17,8 @@
|
||||
#include <util/translation.h>
|
||||
#include <util/vector.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
typedef std::vector<unsigned char> valtype;
|
||||
|
||||
MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction& tx, unsigned int input_idx, const CAmount& amount, int hash_type)
|
||||
@ -752,7 +754,7 @@ bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, std::map<int, bilingual_str>& input_errors)
|
||||
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum)
|
||||
{
|
||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
||||
|
||||
@ -777,20 +779,37 @@ bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
|
||||
}
|
||||
|
||||
// Sign what we can:
|
||||
if (inputs_amount_sum) *inputs_amount_sum = 0;
|
||||
for (unsigned int i = 0; i < mtx.vin.size(); ++i) {
|
||||
CTxIn& txin = mtx.vin[i];
|
||||
auto coin = coins.find(txin.prevout);
|
||||
if (coin == coins.end() || coin->second.IsSpent()) {
|
||||
if (inputs_amount_sum) {
|
||||
inputs_amount_sum->reset();
|
||||
inputs_amount_sum = nullptr;
|
||||
}
|
||||
input_errors[i] = _("Input not found or already spent");
|
||||
continue;
|
||||
}
|
||||
const CScript& prevPubKey = coin->second.out.scriptPubKey;
|
||||
const CAmount& amount = coin->second.out.nValue;
|
||||
if (inputs_amount_sum && *inputs_amount_sum) {
|
||||
if (amount > 0) {
|
||||
**inputs_amount_sum += amount;
|
||||
} else {
|
||||
inputs_amount_sum->reset();
|
||||
inputs_amount_sum = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
|
||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||
if (!fHashSingle || (i < mtx.vout.size())) {
|
||||
ProduceSignature(*keystore, MutableTransactionSignatureCreator(mtx, i, amount, &txdata, nHashType), prevPubKey, sigdata);
|
||||
if ((!sigdata.witness) && inputs_amount_sum && *inputs_amount_sum) {
|
||||
inputs_amount_sum->reset();
|
||||
inputs_amount_sum = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateInput(txin, sigdata);
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <script/standard.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
class CKey;
|
||||
class CKeyID;
|
||||
class CScript;
|
||||
@ -123,6 +125,6 @@ void UpdateInput(CTxIn& input, const SignatureData& data);
|
||||
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);
|
||||
|
||||
/** Sign the CMutableTransaction */
|
||||
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors);
|
||||
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum = nullptr);
|
||||
|
||||
#endif // BITCOIN_SCRIPT_SIGN_H
|
||||
|
@ -604,9 +604,9 @@ bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sig
|
||||
}
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
|
||||
bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum) const
|
||||
{
|
||||
return ::SignTransaction(tx, this, coins, sighash, input_errors);
|
||||
return ::SignTransaction(tx, this, coins, sighash, input_errors, inputs_amount_sum);
|
||||
}
|
||||
|
||||
SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
|
||||
@ -2429,7 +2429,7 @@ bool DescriptorScriptPubKeyMan::CanProvide(const CScript& script, SignatureData&
|
||||
return IsMine(script);
|
||||
}
|
||||
|
||||
bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
|
||||
bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum) const
|
||||
{
|
||||
std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
|
||||
for (const auto& coin_pair : coins) {
|
||||
@ -2440,7 +2440,7 @@ bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const s
|
||||
keys->Merge(std::move(*coin_keys));
|
||||
}
|
||||
|
||||
return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
|
||||
return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors, inputs_amount_sum);
|
||||
}
|
||||
|
||||
SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
|
||||
|
@ -234,7 +234,7 @@ public:
|
||||
virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
|
||||
|
||||
/** Creates new signatures and adds them to the transaction. Returns whether all inputs were signed */
|
||||
virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const { return false; }
|
||||
virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum = nullptr) const { return false; }
|
||||
/** 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. */
|
||||
@ -409,7 +409,7 @@ public:
|
||||
|
||||
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
|
||||
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum = nullptr) const override;
|
||||
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
|
||||
TransactionError FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type = SIGHASH_DEFAULT, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr, bool finalize = true) const override;
|
||||
|
||||
@ -632,7 +632,7 @@ public:
|
||||
|
||||
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
|
||||
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum = nullptr) const override;
|
||||
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
|
||||
TransactionError FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type = SIGHASH_DEFAULT, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr, bool finalize = true) const override;
|
||||
|
||||
|
@ -2126,13 +2126,13 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const
|
||||
return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
|
||||
}
|
||||
|
||||
bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
|
||||
bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum) const
|
||||
{
|
||||
// Try to sign with all ScriptPubKeyMans
|
||||
for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
|
||||
// spk_man->SignTransaction will return true if the transaction is complete,
|
||||
// so we can exit early and return true if that happens
|
||||
if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
|
||||
if (spk_man->SignTransaction(tx, coins, sighash, input_errors, inputs_amount_sum)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -586,7 +586,7 @@ public:
|
||||
/** Fetch the inputs and sign with SIGHASH_ALL. */
|
||||
bool SignTransaction(CMutableTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
/** Sign the tx given the input coins and sighash. */
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const;
|
||||
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors, std::optional<CAmount>* inputs_amount_sum = nullptr) const;
|
||||
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user