aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/script/sign.cpp22
-rw-r--r--src/script/sign.h4
-rw-r--r--src/wallet/wallet.cpp29
-rw-r--r--src/wallet/wallet.h27
4 files changed, 45 insertions, 37 deletions
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index c103e3c2f0..66d942d7c5 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -417,22 +417,25 @@ public:
const DummySignatureChecker DUMMY_CHECKER;
class DummySignatureCreator final : public BaseSignatureCreator {
+private:
+ char m_r_len = 32;
+ char m_s_len = 32;
public:
- DummySignatureCreator() {}
+ DummySignatureCreator(char r_len, char s_len) : m_r_len(r_len), m_s_len(s_len) {}
const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override
{
// Create a dummy signature that is a valid DER-encoding
- vchSig.assign(71, '\000');
+ vchSig.assign(m_r_len + m_s_len + 7, '\000');
vchSig[0] = 0x30;
- vchSig[1] = 68;
+ vchSig[1] = m_r_len + m_s_len + 4;
vchSig[2] = 0x02;
- vchSig[3] = 32;
+ vchSig[3] = m_r_len;
vchSig[4] = 0x01;
- vchSig[4 + 32] = 0x02;
- vchSig[5 + 32] = 32;
- vchSig[6 + 32] = 0x01;
- vchSig[6 + 32 + 32] = SIGHASH_ALL;
+ vchSig[4 + m_r_len] = 0x02;
+ vchSig[5 + m_r_len] = m_s_len;
+ vchSig[6 + m_r_len] = 0x01;
+ vchSig[6 + m_r_len + m_s_len] = SIGHASH_ALL;
return true;
}
};
@@ -450,7 +453,8 @@ bool LookupHelper(const M& map, const K& key, V& value)
}
-const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator();
+const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
+const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
const SigningProvider& DUMMY_SIGNING_PROVIDER = SigningProvider();
bool IsSolvable(const SigningProvider& provider, const CScript& script)
diff --git a/src/script/sign.h b/src/script/sign.h
index 96ef59fbe8..a614d17a9f 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -80,8 +80,10 @@ public:
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};
-/** A signature creator that just produces 72-byte empty signatures. */
+/** A signature creator that just produces 71-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
+/** A signature creator that just produces 72-byte empty signatures. */
+extern const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR;
typedef std::pair<CPubKey, std::vector<unsigned char>> SigPair;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 173f1b786c..3a473e4de3 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1541,29 +1541,28 @@ int64_t CWalletTx::GetTxTime() const
}
// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
-bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const
+// or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
+bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig) const
{
// Fill in dummy signatures for fee calculation.
const CScript& scriptPubKey = txout.scriptPubKey;
SignatureData sigdata;
- if (!ProduceSignature(*this, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata))
- {
+ if (!ProduceSignature(*this, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
return false;
- } else {
- UpdateInput(tx_in, sigdata);
}
+ UpdateInput(tx_in, sigdata);
return true;
}
// Helper for producing a bunch of max-sized low-S low-R signatures (eg 71 bytes)
-bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const
+bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig) const
{
// Fill in dummy signatures for fee calculation.
int nIn = 0;
for (const auto& txout : txouts)
{
- if (!DummySignInput(txNew.vin[nIn], txout)) {
+ if (!DummySignInput(txNew.vin[nIn], txout, use_max_sig)) {
return false;
}
@@ -1572,7 +1571,7 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut>
return true;
}
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet)
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
{
std::vector<CTxOut> txouts;
// Look up the inputs. We should have already checked that this transaction
@@ -1586,14 +1585,14 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
assert(input.prevout.n < mi->second.tx->vout.size());
txouts.emplace_back(mi->second.tx->vout[input.prevout.n]);
}
- return CalculateMaximumSignedTxSize(tx, wallet, txouts);
+ return CalculateMaximumSignedTxSize(tx, wallet, txouts, use_max_sig);
}
// txouts needs to be in the order of tx.vin
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts)
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig)
{
CMutableTransaction txNew(tx);
- if (!wallet->DummySignTx(txNew, txouts)) {
+ if (!wallet->DummySignTx(txNew, txouts, use_max_sig)) {
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
// implies that we can sign for every input.
return -1;
@@ -1601,11 +1600,11 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
return GetVirtualTransactionSize(txNew);
}
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet)
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
{
CMutableTransaction txn;
txn.vin.push_back(CTxIn(COutPoint()));
- if (!wallet->DummySignInput(txn.vin[0], txout)) {
+ if (!wallet->DummySignInput(txn.vin[0], txout, use_max_sig)) {
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
// implies that we can sign for every input.
return -1;
@@ -2332,7 +2331,7 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
- vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx));
+ vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
@@ -2881,7 +2880,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
txNew.vin.push_back(CTxIn(coin.outpoint,CScript()));
}
- nBytes = CalculateMaximumSignedTxSize(txNew, this);
+ nBytes = CalculateMaximumSignedTxSize(txNew, this, coin_control.fAllowWatchOnly);
if (nBytes < 0) {
strFailReason = _("Signing transaction failed");
return false;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 8054cfadf0..d1c0218d9e 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -276,7 +276,7 @@ public:
};
//Get the marginal bytes of spending the specified output
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet);
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, bool use_max_sig = false);
/**
* A transaction with a bunch of additional info that only the owner cares about.
@@ -461,9 +461,9 @@ public:
CAmount GetChange() const;
// Get the marginal bytes if spending the specified output from this transaction
- int GetSpendSize(unsigned int out) const
+ int GetSpendSize(unsigned int out, bool use_max_sig = false) const
{
- return CalculateMaximumSignedInputSize(tx->vout[out], pwallet);
+ return CalculateMaximumSignedInputSize(tx->vout[out], pwallet, use_max_sig);
}
void GetAmounts(std::list<COutputEntry>& listReceived,
@@ -507,6 +507,9 @@ public:
/** Whether we know how to spend this output, ignoring the lack of keys */
bool fSolvable;
+ /** Whether to use the maximum sized, 72 byte signature when calculating the size of the input spend. This should only be set when watch-only outputs are allowed */
+ bool use_max_sig;
+
/**
* Whether this output is considered safe to spend. Unconfirmed transactions
* from outside keys and unconfirmed replacement transactions are considered
@@ -514,13 +517,13 @@ public:
*/
bool fSafe;
- COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn)
+ COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn, bool fSafeIn, bool use_max_sig_in = false)
{
- tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1;
+ tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; fSolvable = fSolvableIn; fSafe = fSafeIn; nInputBytes = -1; use_max_sig = use_max_sig_in;
// If known and signable by the given wallet, compute nInputBytes
// Failure will keep this value -1
if (fSpendable && tx) {
- nInputBytes = tx->GetSpendSize(i);
+ nInputBytes = tx->GetSpendSize(i, use_max_sig);
}
}
@@ -976,14 +979,14 @@ public:
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& entries);
bool AddAccountingEntry(const CAccountingEntry&);
bool AddAccountingEntry(const CAccountingEntry&, WalletBatch *batch);
- bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts) const
+ bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const
{
std::vector<CTxOut> v_txouts(txouts.size());
std::copy(txouts.begin(), txouts.end(), v_txouts.begin());
- return DummySignTx(txNew, v_txouts);
+ return DummySignTx(txNew, v_txouts, use_max_sig);
}
- bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const;
- bool DummySignInput(CTxIn &tx_in, const CTxOut &txout) const;
+ bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig = false) const;
+ bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig = false) const;
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
@@ -1311,6 +1314,6 @@ public:
// Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
// be IsAllFromMe).
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet);
-int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts);
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false);
+int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false);
#endif // BITCOIN_WALLET_WALLET_H