aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/coincontrol.h2
-rw-r--r--src/wallet/coinselection.cpp14
-rw-r--r--src/wallet/coinselection.h2
-rw-r--r--src/wallet/crypter.cpp2
-rw-r--r--src/wallet/crypter.h2
-rw-r--r--src/wallet/db.cpp4
-rw-r--r--src/wallet/db.h2
-rw-r--r--src/wallet/feebumper.cpp4
-rw-r--r--src/wallet/feebumper.h2
-rw-r--r--src/wallet/fees.cpp2
-rw-r--r--src/wallet/fees.h2
-rw-r--r--src/wallet/init.cpp2
-rw-r--r--src/wallet/rpcdump.cpp26
-rw-r--r--src/wallet/rpcwallet.cpp80
-rw-r--r--src/wallet/rpcwallet.h2
-rw-r--r--src/wallet/test/accounting_tests.cpp2
-rw-r--r--src/wallet/test/coinselector_tests.cpp2
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp2
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp2
-rw-r--r--src/wallet/test/wallet_test_fixture.h2
-rw-r--r--src/wallet/test/wallet_tests.cpp2
-rw-r--r--src/wallet/wallet.cpp198
-rw-r--r--src/wallet/wallet.h60
-rw-r--r--src/wallet/walletdb.cpp27
-rw-r--r--src/wallet/walletdb.h2
-rw-r--r--src/wallet/walletutil.cpp2
-rw-r--r--src/wallet/walletutil.h2
28 files changed, 239 insertions, 214 deletions
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index fbe6c43e24..48a924abfb 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 1a810e763f..3734ba66b6 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -299,12 +299,12 @@ void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size
m_from_me &= from_me;
m_value += output.effective_value;
m_depth = std::min(m_depth, depth);
- // m_ancestors is currently the max ancestor count for all coins in the group; however, this is
- // not ideal, as a wallet will consider e.g. thirty 2-ancestor coins as having two ancestors,
- // when in reality it has 60 ancestors.
- m_ancestors = std::max(m_ancestors, ancestors);
- // m_descendants is the count as seen from the top ancestor, not the descendants as seen from the
- // coin itself; thus, this value is accurate
+ // ancestors here express the number of ancestors the new coin will end up having, which is
+ // the sum, rather than the max; this will overestimate in the cases where multiple inputs
+ // have common ancestors
+ m_ancestors += ancestors;
+ // descendants is the count as seen from the top ancestor, not the descendants as seen from the
+ // coin itself; thus, this value is counted as the max, not the sum
m_descendants = std::max(m_descendants, descendants);
effective_value = m_value;
}
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 1be776e695..6d755d0969 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp
index 6ad18721fd..4fa9603011 100644
--- a/src/wallet/crypter.cpp
+++ b/src/wallet/crypter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index 52842cd978..418316c398 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 01b8eacccb..d0fe51801e 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -768,7 +768,7 @@ bool BerkeleyDatabase::Backup(const std::string& strDest)
env->mapFileUseCount.erase(strFile);
// Copy wallet file
- fs::path pathSrc = GetWalletDir() / strFile;
+ fs::path pathSrc = env->Directory() / strFile;
fs::path pathDest(strDest);
if (fs::is_directory(pathDest))
pathDest /= strFile;
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 5e61280f7a..b078edab7b 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 0eb85a6e5c..d5d4021305 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -195,7 +195,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// If the output would become dust, discard it (converting the dust to fee)
poutput->nValue -= nDelta;
if (poutput->nValue <= GetDustThreshold(*poutput, GetDiscardRate(*wallet, ::feeEstimator))) {
- LogPrint(BCLog::RPC, "Bumping fee and discarding dust output\n");
+ wallet->WalletLogPrintf("Bumping fee and discarding dust output\n");
new_fee += poutput->nValue;
mtx.vout.erase(mtx.vout.begin() + nOutput);
}
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index 7e36a9766b..a1eb5d0e0d 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 8d576a6689..d620e25f2b 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/fees.h b/src/wallet/fees.h
index b3cd064abc..6bfee456c0 100644
--- a/src/wallet/fees.h
+++ b/src/wallet/fees.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 52c7e6c70f..b9f267210e 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 3cb4050f01..7cb41da39e 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -115,7 +115,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
"1. \"privkey\" (string, required) The private key (see dumpprivkey)\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
"\nExamples:\n"
"\nDump a private key\n"
@@ -268,7 +268,7 @@ UniValue importaddress(const JSONRPCRequest& request)
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
"If you have the full public key, you should call importpubkey instead of this.\n"
"\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
@@ -448,7 +448,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
"1. \"pubkey\" (string, required) The hex-encoded public key\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
"\nExamples:\n"
"\nImport a public key with rescan\n"
@@ -553,7 +553,7 @@ UniValue importwallet(const JSONRPCRequest& request)
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
// we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
- uiInterface.ShowProgress(_("Importing..."), 0, false); // show progress dialog in GUI
+ uiInterface.ShowProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
while (file.good()) {
uiInterface.ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
std::string line;
@@ -571,7 +571,7 @@ UniValue importwallet(const JSONRPCRequest& request)
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwallet->HaveKey(keyid)) {
- LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
+ pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
continue;
}
int64_t nTime = DecodeDumpTime(vstr[1]);
@@ -589,7 +589,7 @@ UniValue importwallet(const JSONRPCRequest& request)
fLabel = true;
}
}
- LogPrintf("Importing %s...\n", EncodeDestination(keyid));
+ pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(keyid));
if (!pwallet->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
@@ -603,11 +603,11 @@ UniValue importwallet(const JSONRPCRequest& request)
CScript script = CScript(vData.begin(), vData.end());
CScriptID id(script);
if (pwallet->HaveCScript(id)) {
- LogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
+ pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
continue;
}
if(!pwallet->AddCScript(script)) {
- LogPrintf("Error importing script %s\n", vstr[0]);
+ pwallet->WalletLogPrintf("Error importing script %s\n", vstr[0]);
fGood = false;
continue;
}
@@ -706,15 +706,15 @@ UniValue dumpwallet(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(pwallet);
- boost::filesystem::path filepath = request.params[0].get_str();
- filepath = boost::filesystem::absolute(filepath);
+ fs::path filepath = request.params[0].get_str();
+ filepath = fs::absolute(filepath);
/* Prevent arbitrary files from being overwritten. There have been reports
* that users have overwritten wallet files this way:
* https://github.com/bitcoin/bitcoin/issues/9934
* It may also avoid other security issues.
*/
- if (boost::filesystem::exists(filepath)) {
+ if (fs::exists(filepath)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
}
@@ -1158,7 +1158,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
" {\n"
" \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n"
" }\n"
- "\nNote: This call can take minutes to complete if rescan is true, during that time, other rpc calls\n"
+ "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n"
"\nExamples:\n" +
HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, "
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 84fd55edef..3d873381e9 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -165,7 +165,7 @@ static UniValue getnewaddress(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ LOCK(pwallet->cs_wallet);
// Parse the label first so we don't generate a key if there's an error
std::string label;
@@ -276,7 +276,7 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
- LOCK2(cs_main, pwallet->cs_wallet);
+ LOCK(pwallet->cs_wallet);
if (!pwallet->IsLocked()) {
pwallet->TopUpKeyPool();
@@ -331,7 +331,7 @@ static UniValue setlabel(const JSONRPCRequest& request)
+ HelpExampleRpc("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
);
- LOCK2(cs_main, pwallet->cs_wallet);
+ LOCK(pwallet->cs_wallet);
CTxDestination dest = DecodeDestination(request.params[0].get_str());
if (!IsValidDestination(dest)) {
@@ -2982,8 +2982,16 @@ static UniValue settxfee(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
CAmount nAmount = AmountFromValue(request.params[0]);
+ CFeeRate tx_fee_rate(nAmount, 1000);
+ if (tx_fee_rate == 0) {
+ // automatic selection
+ } else if (tx_fee_rate < ::minRelayTxFee) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", ::minRelayTxFee.ToString()));
+ } else if (tx_fee_rate < pwallet->m_min_fee) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than wallet min fee (%s)", pwallet->m_min_fee.ToString()));
+ }
- pwallet->m_pay_tx_fee = CFeeRate(nAmount, 1000);
+ pwallet->m_pay_tx_fee = tx_fee_rate;
return true;
}
@@ -4504,10 +4512,11 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const C
// If we don't know about this input, skip it and let someone else deal with it
const uint256& txhash = txin.prevout.hash;
- const auto& it = pwallet->mapWallet.find(txhash);
+ const auto it = pwallet->mapWallet.find(txhash);
if (it != pwallet->mapWallet.end()) {
const CWalletTx& wtx = it->second;
CTxOut utxo = wtx.tx->vout[txin.prevout.n];
+ // Update both UTXOs from the wallet.
input.non_witness_utxo = wtx.tx;
input.witness_utxo = utxo;
}
@@ -4524,11 +4533,13 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const C
complete &= SignPSBTInput(PublicOnlySigningProvider(pwallet), *psbtx.tx, input, sigdata, i, sighash_type);
}
- // Drop the unnecessary UTXO
- if (sigdata.witness) {
- input.non_witness_utxo = nullptr;
- } else {
- input.witness_utxo.SetNull();
+ if (it != pwallet->mapWallet.end()) {
+ // Drop the unnecessary UTXO if we added both from the wallet.
+ if (sigdata.witness) {
+ input.non_witness_utxo = nullptr;
+ } else {
+ input.witness_utxo.SetNull();
+ }
}
// Get public key paths
@@ -4544,11 +4555,6 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, const C
const CTxOut& out = txConst->vout.at(i);
PSBTOutput& psbt_out = psbtx.outputs.at(i);
- // Dummy tx so we can use ProduceSignature to get stuff out
- CMutableTransaction dummy_tx;
- dummy_tx.vin.push_back(CTxIn());
- dummy_tx.vout.push_back(CTxOut());
-
// Fill a SignatureData with output info
SignatureData sigdata;
psbt_out.FillSignatureData(sigdata);
@@ -4630,8 +4636,8 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
UniValue result(UniValue::VOBJ);
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
- result.push_back(Pair("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size())));
- result.push_back(Pair("complete", complete));
+ result.pushKV("psbt", EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()));
+ result.pushKV("complete", complete);
return result;
}
@@ -4645,7 +4651,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 2 || request.params.size() > 6)
+ if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw std::runtime_error(
"walletcreatefundedpsbt [{\"txid\":\"id\",\"vout\":n},...] [{\"address\":amount},{\"data\":\"hex\"},...] ( locktime ) ( replaceable ) ( options bip32derivs )\n"
"\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"
@@ -4672,9 +4678,8 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
" accepted as second parameter.\n"
" ]\n"
"3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
- "4. replaceable (boolean, optional, default=false) Marks this transaction as BIP125 replaceable.\n"
" Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible.\n"
- "5. options (object, optional)\n"
+ "4. options (object, optional)\n"
" {\n"
" \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
@@ -4696,7 +4701,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
" \"ECONOMICAL\"\n"
" \"CONSERVATIVE\"\n"
" }\n"
- "6. bip32derivs (boolean, optiona, default=false) If true, includes the BIP 32 derivation paths for public keys if we know them\n"
+ "5. bip32derivs (boolean, optiona, default=false) If true, includes the BIP 32 derivation paths for public keys if we know them\n"
"\nResult:\n"
"{\n"
" \"psbt\": \"value\", (string) The resulting raw transaction (base64-encoded string)\n"
@@ -4712,15 +4717,15 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
UniValue::VARR,
UniValueType(), // ARR or OBJ, checked later
UniValue::VNUM,
- UniValue::VBOOL,
- UniValue::VOBJ
+ UniValue::VOBJ,
+ UniValue::VBOOL
}, true
);
CAmount fee;
int change_position;
- CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]);
- FundTransaction(pwallet, rawTx, fee, change_position, request.params[4]);
+ CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], request.params[3]["replaceable"]);
+ FundTransaction(pwallet, rawTx, fee, change_position, request.params[3]);
// Make a blank psbt
PartiallySignedTransaction psbtx;
@@ -4737,7 +4742,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
const CTransaction txConst(*psbtx.tx);
// Fill transaction with out data but don't sign
- bool bip32derivs = request.params[5].isNull() ? false : request.params[5].get_bool();
+ bool bip32derivs = request.params[4].isNull() ? false : request.params[5].get_bool();
FillPSBT(pwallet, psbtx, &txConst, 1, false, bip32derivs);
// Serialize the PSBT
@@ -4751,24 +4756,23 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
return result;
}
-extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
-extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
-extern UniValue importprivkey(const JSONRPCRequest& request);
-extern UniValue importaddress(const JSONRPCRequest& request);
-extern UniValue importpubkey(const JSONRPCRequest& request);
-extern UniValue dumpwallet(const JSONRPCRequest& request);
-extern UniValue importwallet(const JSONRPCRequest& request);
-extern UniValue importprunedfunds(const JSONRPCRequest& request);
-extern UniValue removeprunedfunds(const JSONRPCRequest& request);
-extern UniValue importmulti(const JSONRPCRequest& request);
-extern UniValue rescanblockchain(const JSONRPCRequest& request);
+UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
+UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
+UniValue importprivkey(const JSONRPCRequest& request);
+UniValue importaddress(const JSONRPCRequest& request);
+UniValue importpubkey(const JSONRPCRequest& request);
+UniValue dumpwallet(const JSONRPCRequest& request);
+UniValue importwallet(const JSONRPCRequest& request);
+UniValue importprunedfunds(const JSONRPCRequest& request);
+UniValue removeprunedfunds(const JSONRPCRequest& request);
+UniValue importmulti(const JSONRPCRequest& request);
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
{ "wallet", "walletprocesspsbt", &walletprocesspsbt, {"psbt","sign","sighashtype","bip32derivs"} },
- { "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","replaceable","options","bip32derivs"} },
+ { "wallet", "walletcreatefundedpsbt", &walletcreatefundedpsbt, {"inputs","outputs","locktime","options","bip32derivs"} },
{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 64556b5824..9b9a159b86 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
index cc6e491f53..79060887be 100644
--- a/src/wallet/test/accounting_tests.cpp
+++ b/src/wallet/test/accounting_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 1561760577..0776ffda9c 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index 2cc995bf04..61c3fa94a6 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index e04c0af1dd..f193d5c41d 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 The Bitcoin Core developers
+// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 6129e337ce..de59b60349 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index b328b3543b..ff8ec32b03 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017 The Bitcoin Core developers
+// Copyright (c) 2016-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index c89b8f252f..f44311b0be 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2017 The Bitcoin Core developers
+// Copyright (c) 2012-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 540a7b0fc6..d0857bcb72 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -35,6 +35,8 @@
#include <boost/algorithm/string/replace.hpp>
+static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10;
+
static CCriticalSection cs_wallets;
static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
@@ -82,7 +84,7 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
// Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet)
{
- LogPrintf("Releasing wallet %s\n", wallet->GetName());
+ wallet->WalletLogPrintf("Releasing wallet\n");
wallet->BlockUntilSyncedToCurrentChain();
wallet->Flush();
delete wallet;
@@ -102,14 +104,25 @@ std::string COutput::ToString() const
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
}
+/** A class to identify which pubkeys a script and a keystore have in common. */
class CAffectedKeysVisitor : public boost::static_visitor<void> {
private:
const CKeyStore &keystore;
std::vector<CKeyID> &vKeys;
public:
+ /**
+ * @param[in] keystoreIn The CKeyStore that is queried for the presence of a pubkey.
+ * @param[out] vKeysIn A vector to which a script's pubkey identifiers are appended if they are in the keystore.
+ */
CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
+ /**
+ * Apply the visitor to each destination in a script, recursively to the redeemscript
+ * in the case of p2sh destinations.
+ * @param[in] script The CScript from which destinations are extracted.
+ * @post Any CKeyIDs that script and keystore have in common are appended to the visitor's vKeys.
+ */
void Process(const CScript &script) {
txnouttype type;
std::vector<CTxDestination> vDest;
@@ -304,20 +317,18 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
}
}
-bool CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta)
+void CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta)
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
UpdateTimeFirstKey(meta.nCreateTime);
mapKeyMetadata[keyID] = meta;
- return true;
}
-bool CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta)
+void CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta)
{
AssertLockHeld(cs_wallet); // m_script_metadata
UpdateTimeFirstKey(meta.nCreateTime);
m_script_metadata[script_id] = meta;
- return true;
}
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
@@ -356,8 +367,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
{
std::string strAddr = EncodeDestination(CScriptID(redeemScript));
- LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
- __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
+ WalletLogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
return true;
}
@@ -447,7 +457,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
- LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
+ WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
@@ -470,11 +480,11 @@ void CWallet::ChainStateFlushed(const CBlockLocator& loc)
batch.WriteBestBlock(loc);
}
-bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
+void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
{
LOCK(cs_wallet); // nWalletVersion
if (nWalletVersion >= nVersion)
- return true;
+ return;
// when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
if (fExplicit && nVersion > nWalletMaxVersion)
@@ -492,8 +502,6 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in,
if (!batch_in)
delete batch;
}
-
- return true;
}
bool CWallet::SetMaxVersion(int nVersion)
@@ -657,7 +665,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
- LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
+ WalletLogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
@@ -703,9 +711,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// if we are using HD, replace the HD seed with a new one
if (IsHDEnabled()) {
- if (!SetHDSeed(GenerateNewSeed())) {
- return false;
- }
+ SetHDSeed(GenerateNewSeed());
}
NewKeyPool();
@@ -913,7 +919,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
bool success = true;
if (!batch.WriteTx(wtx)) {
- LogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
+ WalletLogPrintf("%s: Updating batch tx %s failed\n", __func__, wtx.GetHash().ToString());
success = false;
}
@@ -980,7 +986,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
}
//// debug print
- LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ WalletLogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
// Write to disk
if (fInsertedNew || fUpdated)
@@ -1006,7 +1012,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
return true;
}
-bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
+void CWallet::LoadToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
const auto& ins = mapWallet.emplace(hash, wtxIn);
@@ -1025,8 +1031,6 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
}
}
}
-
- return true;
}
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate)
@@ -1040,7 +1044,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
while (range.first != range.second) {
if (range.first->second != tx.GetHash()) {
- LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
+ WalletLogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
MarkConflicted(pIndex->GetBlockHash(), range.first->second);
}
range.first++;
@@ -1066,11 +1070,11 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
for (const CKeyID &keyid : vAffected) {
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
if (mi != m_pool_key_to_index.end()) {
- LogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
+ WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
MarkReserveKeysAsUsed(mi->second);
if (!TopUpKeyPool()) {
- LogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
+ WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
}
}
}
@@ -1478,7 +1482,7 @@ CPubKey CWallet::DeriveNewSeed(const CKey& key)
return seed;
}
-bool CWallet::SetHDSeed(const CPubKey& seed)
+void CWallet::SetHDSeed(const CPubKey& seed)
{
LOCK(cs_wallet);
// store the keyid (hash160) together with
@@ -1488,18 +1492,15 @@ bool CWallet::SetHDSeed(const CPubKey& seed)
newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
-
- return true;
}
-bool CWallet::SetHDChain(const CHDChain& chain, bool memonly)
+void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
{
LOCK(cs_wallet);
if (!memonly && !WalletBatch(*database).WriteHDChain(chain))
throw std::runtime_error(std::string(__func__) + ": writing chain failed");
hdChain = chain;
- return true;
}
bool CWallet::IsHDEnabled() const
@@ -1541,30 +1542,29 @@ int64_t CWalletTx::GetTxTime() const
return n ? n : nTimeReceived;
}
-// Helper for producing a max-sized low-S signature (eg 72 bytes)
-bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const
+// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
+// 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 signatures (eg 72 bytes)
-bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts) const
+// 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, 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;
}
@@ -1573,7 +1573,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
@@ -1587,14 +1587,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;
@@ -1602,11 +1602,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;
@@ -1652,8 +1652,8 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
{
- LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
- this->GetHash().ToString());
+ pwallet->WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
+ this->GetHash().ToString());
address = CNoDestination();
}
@@ -1687,7 +1687,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
{
LOCK(cs_main);
startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
- LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
+ WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
}
if (startBlock) {
@@ -1728,11 +1728,11 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
CBlockIndex* pindex = pindexStart;
CBlockIndex* ret = nullptr;
- if (pindex) LogPrintf("Rescan started from block %d...\n", pindex->nHeight);
+ if (pindex) WalletLogPrintf("Rescan started from block %d...\n", pindex->nHeight);
{
fAbortRescan = false;
- ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
+ ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
CBlockIndex* tip = nullptr;
double progress_begin;
double progress_end;
@@ -1750,11 +1750,11 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
while (pindex && !fAbortRescan && !ShutdownRequested())
{
if (pindex->nHeight % 100 == 0 && progress_end - progress_begin > 0.0) {
- ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100))));
+ ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100))));
}
if (GetTime() >= nNow + 60) {
nNow = GetTime();
- LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, progress_current);
+ WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, progress_current);
}
CBlock block;
@@ -1787,11 +1787,11 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
}
}
if (pindex && fAbortRescan) {
- LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, progress_current);
+ WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, progress_current);
} else if (pindex && ShutdownRequested()) {
- LogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current);
+ WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current);
}
- ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
+ ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI
}
return ret;
}
@@ -1834,7 +1834,7 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman)
CValidationState state;
/* GetDepthInMainChain already catches known conflicts. */
if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) {
- LogPrintf("Relaying wtx %s\n", GetHash().ToString());
+ pwallet->WalletLogPrintf("Relaying wtx %s\n", GetHash().ToString());
if (connman) {
CInv inv(MSG_TX, GetHash());
connman->ForEachNode([&inv](CNode* pnode)
@@ -2094,7 +2094,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman
// block was found:
std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60, connman);
if (!relayed.empty())
- LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
+ WalletLogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
}
/** @} */ // end of mapWallet
@@ -2331,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) {
@@ -2524,6 +2524,12 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
// form groups from remaining coins; note that preset coins will not
// automatically have their associated (same address) coins included
+ if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
+ // Cases where we have 11+ outputs all pointing to the same destination may result in
+ // privacy leaks as they will potentially be deterministically sorted. We solve that by
+ // explicitly shuffling the outputs before processing
+ std::shuffle(vCoins.begin(), vCoins.end(), FastRandomContext());
+ }
std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends);
size_t max_ancestors = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT));
@@ -2880,7 +2886,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;
@@ -3027,13 +3033,14 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
std::string errString;
- if (!mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
+ LOCK(::mempool.cs);
+ if (!::mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
strFailReason = _("Transaction has too long of a mempool chain");
return false;
}
}
- LogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
+ WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
nFeeRet, nBytes, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
feeCalc.est.pass.start, feeCalc.est.pass.end,
100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool),
@@ -3059,7 +3066,7 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
wtxNew.fTimeReceivedIsTxTime = true;
wtxNew.fFromMe = true;
- LogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
+ WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
{
// Take key pair from key pool so it won't be used again
reservekey.KeepKey();
@@ -3085,7 +3092,7 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
{
// Broadcast
if (!wtx.AcceptToMemoryPool(maxTxFee, state)) {
- LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state));
+ WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", FormatStateMessage(state));
// TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure.
} else {
wtx.RelayWalletTransaction(connman);
@@ -3293,7 +3300,7 @@ bool CWallet::NewKeyPool()
if (!TopUpKeyPool()) {
return false;
}
- LogPrintf("CWallet::NewKeyPool rewrote keypool\n");
+ WalletLogPrintf("CWallet::NewKeyPool rewrote keypool\n");
}
return true;
}
@@ -3377,7 +3384,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
m_pool_key_to_index[pubkey.GetID()] = index;
}
if (missingInternal + missingExternal > 0) {
- LogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
+ WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size());
}
}
return true;
@@ -3422,7 +3429,7 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
}
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
- LogPrintf("keypool reserve %d\n", nIndex);
+ WalletLogPrintf("keypool reserve %d\n", nIndex);
}
return true;
}
@@ -3432,7 +3439,7 @@ void CWallet::KeepKey(int64_t nIndex)
// Remove from key pool
WalletBatch batch(*database);
batch.ErasePool(nIndex);
- LogPrintf("keypool keep %d\n", nIndex);
+ WalletLogPrintf("keypool keep %d\n", nIndex);
}
void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
@@ -3449,7 +3456,7 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
}
m_pool_key_to_index[pubkey.GetID()] = nIndex;
}
- LogPrintf("keypool return %d\n", nIndex);
+ WalletLogPrintf("keypool return %d\n", nIndex);
}
bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
@@ -3711,7 +3718,7 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id)
}
LearnAllRelatedScripts(keypool.vchPubKey);
batch.ErasePool(index);
- LogPrintf("keypool index %d removed\n", index);
+ WalletLogPrintf("keypool index %d removed\n", index);
it = setKeyPool->erase(it);
}
}
@@ -3875,7 +3882,7 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
int64_t blocktime = pindex->GetBlockTime();
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
} else {
- LogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.hashBlock.ToString());
+ WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.hashBlock.ToString());
}
}
return nTimeSmart;
@@ -3897,10 +3904,9 @@ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
return WalletBatch(*database).EraseDestData(EncodeDestination(dest), key);
}
-bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
+void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
{
mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
- return true;
}
bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
@@ -3981,7 +3987,12 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
}
}
- if (!WalletBatch::VerifyEnvironment(wallet_path, error_string)) {
+ try {
+ if (!WalletBatch::VerifyEnvironment(wallet_path, error_string)) {
+ return false;
+ }
+ } catch (const fs::filesystem_error& e) {
+ error_string = strprintf("Error loading wallet %s. %s", wallet_file, e.what());
return false;
}
@@ -4056,12 +4067,12 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
int nMaxVersion = gArgs.GetArg("-upgradewallet", 0);
if (nMaxVersion == 0) // the -upgradewallet without argument case
{
- LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
+ walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
nMaxVersion = FEATURE_LATEST;
walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
}
else
- LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
InitError(_("Cannot downgrade wallet"));
@@ -4084,19 +4095,17 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
bool hd_upgrade = false;
bool split_upgrade = false;
if (walletInstance->CanSupportFeature(FEATURE_HD) && !walletInstance->IsHDEnabled()) {
- LogPrintf("Upgrading wallet to HD\n");
+ walletInstance->WalletLogPrintf("Upgrading wallet to HD\n");
walletInstance->SetMinVersion(FEATURE_HD);
// generate a new master key
CPubKey masterPubKey = walletInstance->GenerateNewSeed();
- if (!walletInstance->SetHDSeed(masterPubKey)) {
- throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
- }
+ walletInstance->SetHDSeed(masterPubKey);
hd_upgrade = true;
}
// Upgrade to HD chain split if necessary
if (walletInstance->CanSupportFeature(FEATURE_HD_SPLIT)) {
- LogPrintf("Upgrading wallet to use HD chain split\n");
+ walletInstance->WalletLogPrintf("Upgrading wallet to use HD chain split\n");
walletInstance->SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
split_upgrade = FEATURE_HD_SPLIT > prev_version;
}
@@ -4107,7 +4116,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
// Regenerate the keypool if upgraded to HD
if (hd_upgrade) {
if (!walletInstance->TopUpKeyPool()) {
- InitError(_("Unable to generate keys") += "\n");
+ InitError(_("Unable to generate keys"));
return nullptr;
}
}
@@ -4128,14 +4137,12 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
} else {
// generate a new seed
CPubKey seed = walletInstance->GenerateNewSeed();
- if (!walletInstance->SetHDSeed(seed)) {
- throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed");
- }
+ walletInstance->SetHDSeed(seed);
}
// Top up the keypool
if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !walletInstance->TopUpKeyPool()) {
- InitError(_("Unable to generate initial keys") += "\n");
+ InitError(_("Unable to generate initial keys"));
return nullptr;
}
@@ -4231,7 +4238,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
walletInstance->m_spend_zero_conf_change = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
walletInstance->m_signal_rbf = gArgs.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
- LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
+ walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
@@ -4267,7 +4274,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
uiInterface.InitMessage(_("Rescanning..."));
- LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
+ walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
// No need to read and scan block if block was created before
// our wallet birthday (as adjusted for block time variability)
@@ -4284,7 +4291,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true);
}
- LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
+ walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nStart);
walletInstance->ChainStateFlushed(chainActive.GetLocator());
walletInstance->database->IncrementUpdateCounter();
@@ -4323,9 +4330,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
{
LOCK(walletInstance->cs_wallet);
- LogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
- LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
- LogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
+ walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
+ walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
+ walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size());
}
return walletInstance;
@@ -4392,7 +4399,9 @@ int CMerkleTx::GetBlocksToMaturity() const
{
if (!IsCoinBase())
return 0;
- return std::max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
+ int chain_depth = GetDepthInMainChain();
+ assert(chain_depth >= 0); // coinbase tx should not be conflicted
+ return std::max(0, (COINBASE_MATURITY+1) - chain_depth);
}
bool CMerkleTx::IsImmatureCoinBase() const
@@ -4442,7 +4451,10 @@ std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outpu
size_t ancestors, descendants;
mempool.GetTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
- if (gmap.count(dst) == 10) {
+ // Limit output groups to no more than 10 entries, to protect
+ // against inadvertently creating a too-large transaction
+ // when using -avoidpartialspends
+ if (gmap[dst].m_outputs.size() >= OUTPUT_GROUP_MAX_ENTRIES) {
groups.push_back(gmap[dst]);
gmap.erase(dst);
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 8253dc1eba..c085c004b7 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -102,7 +102,7 @@ constexpr OutputType DEFAULT_CHANGE_TYPE{OutputType::CHANGE_AUTO};
enum WalletFlags : uint64_t {
// wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown
- // unkown wallet flags in the lower section <= (1 << 31) will be tolerated
+ // unknown wallet flags in the lower section <= (1 << 31) will be tolerated
// will enforce the rule that the wallet can't contain any private keys (only watch-only/pubkeys)
WALLET_FLAG_DISABLE_PRIVATE_KEYS = (1ULL << 32),
@@ -283,7 +283,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.
@@ -468,9 +468,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,
@@ -514,6 +514,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
@@ -521,13 +524,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);
}
}
@@ -892,8 +895,8 @@ public:
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
//! Load metadata (used by LoadWallet)
- bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -910,7 +913,7 @@ public:
//! Erases a destination data tuple in the store and on disk
bool EraseDestData(const CTxDestination &dest, const std::string &key);
//! Adds a destination data tuple to the store, without saving it to disk
- bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
+ void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
//! Look up a destination data tuple in the store, return true if found false otherwise
bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;
//! Get all destination values matching a prefix.
@@ -943,7 +946,7 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
- bool LoadToWallet(const CWalletTx& wtxIn);
+ void LoadToWallet(const CWalletTx& wtxIn);
void TransactionAddedToMempool(const CTransactionRef& tx) override;
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
@@ -983,14 +986,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};
@@ -1082,7 +1085,7 @@ public:
}
//! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
- bool SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false);
+ void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false);
//! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
bool SetMaxVersion(int nVersion);
@@ -1153,7 +1156,7 @@ public:
bool BackupWallet(const std::string& strDest);
/* Set the HD chain model (chain child index counters) */
- bool SetHDChain(const CHDChain& chain, bool memonly);
+ void SetHDChain(const CHDChain& chain, bool memonly);
const CHDChain& GetHDChain() const { return hdChain; }
/* Returns true if HD is enabled */
@@ -1169,7 +1172,7 @@ public:
Sets the seed's version based on the current wallet version (so the
caller must ensure the current wallet version is correct before calling
this function). */
- bool SetHDSeed(const CPubKey& key);
+ void SetHDSeed(const CPubKey& key);
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
@@ -1202,6 +1205,19 @@ public:
/** overwrite all flags by the given uint64_t
returns false if unknown, non-tolerable flags are present */
bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly);
+
+ /** Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet has no name */
+ const std::string GetDisplayName() const {
+ std::string wallet_name = GetName().length() == 0 ? "default wallet" : GetName();
+ return strprintf("[%s]", wallet_name);
+ };
+
+ /** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
+ template<typename... Params>
+ void WalletLogPrintf(std::string fmt, Params... parameters) const {
+ LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
+ };
+
};
/** A key allocated from the key pool. */
@@ -1302,9 +1318,9 @@ public:
};
// Calculate the size of the transaction assuming all signatures are max size
-// Use DummySignatureCreator, which inserts 72 byte signatures everywhere.
+// 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
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 67fcaa725b..1b787be198 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -495,21 +495,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> strAddress;
ssKey >> strKey;
ssValue >> strValue;
- if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue))
- {
- strErr = "Error reading wallet database: LoadDestData failed";
- return false;
- }
+ pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue);
}
else if (strType == "hdchain")
{
CHDChain chain;
ssValue >> chain;
- if (!pwallet->SetHDChain(chain, true))
- {
- strErr = "Error reading wallet database: SetHDChain failed";
- return false;
- }
+ pwallet->SetHDChain(chain, true);
} else if (strType == "flags") {
uint64_t flags;
ssValue >> flags;
@@ -517,7 +509,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error reading wallet database: Unknown non-tolerable wallet flags found";
return false;
}
- } else if (strType != "bestblock" && strType != "bestblock_nomerkle") {
+ } else if (strType != "bestblock" && strType != "bestblock_nomerkle" &&
+ strType != "minversion") {
wss.m_unknown_records++;
}
} catch (...)
@@ -553,7 +546,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
Dbc* pcursor = m_batch.GetCursor();
if (!pcursor)
{
- LogPrintf("Error getting wallet database cursor\n");
+ pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
return DBErrors::CORRUPT;
}
@@ -567,7 +560,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
break;
else if (ret != 0)
{
- LogPrintf("Error reading next record from wallet database\n");
+ pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT;
}
@@ -591,7 +584,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
}
}
if (!strErr.empty())
- LogPrintf("%s\n", strErr);
+ pwallet->WalletLogPrintf("%s\n", strErr);
}
pcursor->close();
}
@@ -610,9 +603,9 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (result != DBErrors::LOAD_OK)
return result;
- LogPrintf("nFileVersion = %d\n", wss.nFileVersion);
+ pwallet->WalletLogPrintf("nFileVersion = %d\n", wss.nFileVersion);
- LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
+ pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys, wss.m_unknown_records);
// nTimeFirstKey is only reliable if all keys have metadata
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 674d1c2201..0e6cb1bba4 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index 7c97b668ae..34c76ec4c4 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index f12acacd00..7c42954616 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Bitcoin Core developers
+// Copyright (c) 2017-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.