Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 2,751 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < tx.vin.size(); i++) { | ||||
DataFromTransaction(tx, i, coin->second.GetTxOut()); | DataFromTransaction(tx, i, coin->second.GetTxOut()); | ||||
if (sigdata.complete) { | if (sigdata.complete) { | ||||
continue; | continue; | ||||
} | } | ||||
// Input needs to be signed, find the right ScriptPubKeyMan | // Input needs to be signed, find the right ScriptPubKeyMan | ||||
std::set<ScriptPubKeyMan *> spk_mans = | std::set<ScriptPubKeyMan *> spk_mans = | ||||
GetScriptPubKeyMans(coin->second.GetTxOut().scriptPubKey, sigdata); | GetScriptPubKeyMans(coin->second.GetTxOut().scriptPubKey, sigdata); | ||||
if (spk_mans.size() == 0) { | if (spk_mans.size() == 0) { | ||||
input_errors[i] = "Unable to sign input, missing keys"; | input_errors[i] = "Unable to sign input, missing keys"; | ||||
continue; | continue; | ||||
} | } | ||||
for (auto &spk_man : spk_mans) { | for (auto &spk_man : spk_mans) { | ||||
// If we've already been signed by this spk_man, skip it | // If we've already been signed by this spk_man, skip it | ||||
if (visited_spk_mans.count(spk_man->GetID()) > 0) { | if (visited_spk_mans.count(spk_man->GetID()) > 0) { | ||||
continue; | continue; | ||||
} | } | ||||
// Sign the tx. | // Sign the tx. | ||||
// spk_man->SignTransaction will return true if the transaction is | // spk_man->SignTransaction will return true if the transaction is | ||||
// complete, so we can exit early and return true if that happens. | // 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)) { | ||||
return true; | return true; | ||||
} | } | ||||
// Add this spk_man to visited_spk_mans so we can skip it later | // Add this spk_man to visited_spk_mans so we can skip it later | ||||
visited_spk_mans.insert(spk_man->GetID()); | visited_spk_mans.insert(spk_man->GetID()); | ||||
} | } | ||||
} | } | ||||
// When there are no available providers for the remaining inputs, use the | |||||
// legacy provider so we can get proper error messages. | |||||
auto legacy_spk_man = GetLegacyScriptPubKeyMan(); | |||||
if (legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) { | |||||
return true; | |||||
} | |||||
return false; | return false; | ||||
} | } | ||||
bool CWallet::FundTransaction(CMutableTransaction &tx, Amount &nFeeRet, | bool CWallet::FundTransaction(CMutableTransaction &tx, Amount &nFeeRet, | ||||
int &nChangePosInOut, bilingual_str &error, | int &nChangePosInOut, bilingual_str &error, | ||||
bool lockUnspents, | bool lockUnspents, | ||||
const std::set<int> &setSubtractFeeFromOutputs, | const std::set<int> &setSubtractFeeFromOutputs, | ||||
CCoinControl coinControl) { | CCoinControl coinControl) { | ||||
▲ Show 20 Lines • Show All 448 Lines • ▼ Show 20 Lines | CMutableTransaction txNew; | ||||
// Note how the sequence number is set to non-maxint so that | // Note how the sequence number is set to non-maxint so that | ||||
// the nLockTime set above actually works. | // the nLockTime set above actually works. | ||||
for (const auto &coin : selected_coins) { | for (const auto &coin : selected_coins) { | ||||
txNew.vin.push_back( | txNew.vin.push_back( | ||||
CTxIn(coin.outpoint, CScript(), | CTxIn(coin.outpoint, CScript(), | ||||
std::numeric_limits<uint32_t>::max() - 1)); | std::numeric_limits<uint32_t>::max() - 1)); | ||||
} | } | ||||
if (sign) { | if (sign && !SignTransaction(txNew)) { | ||||
SigHashType sigHashType = SigHashType().withForkId(); | |||||
int nIn = 0; | |||||
for (const auto &coin : selected_coins) { | |||||
const CScript &scriptPubKey = coin.txout.scriptPubKey; | |||||
SignatureData sigdata; | |||||
std::unique_ptr<SigningProvider> provider = | |||||
GetSigningProvider(scriptPubKey); | |||||
if (!provider || | |||||
!ProduceSignature( | |||||
*provider, | |||||
MutableTransactionSignatureCreator( | |||||
&txNew, nIn, coin.txout.nValue, sigHashType), | |||||
scriptPubKey, sigdata)) { | |||||
error = _("Signing transaction failed"); | error = _("Signing transaction failed"); | ||||
return false; | return false; | ||||
} | } | ||||
UpdateInput(txNew.vin.at(nIn), sigdata); | |||||
nIn++; | |||||
} | |||||
} | |||||
// Return the constructed transaction data. | // Return the constructed transaction data. | ||||
tx = MakeTransactionRef(std::move(txNew)); | tx = MakeTransactionRef(std::move(txNew)); | ||||
// Limit size. | // Limit size. | ||||
if (tx->GetTotalSize() > MAX_STANDARD_TX_SIZE) { | if (tx->GetTotalSize() > MAX_STANDARD_TX_SIZE) { | ||||
error = _("Transaction too large"); | error = _("Transaction too large"); | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,532 Lines • Show Last 20 Lines |