aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--configure.ac2
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/chainparams.cpp9
-rw-r--r--src/chainparams.h5
-rw-r--r--src/chainparamsbase.h1
-rw-r--r--src/interfaces/wallet.cpp47
-rw-r--r--src/interfaces/wallet.h24
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/walletmodel.cpp4
-rw-r--r--src/qt/walletmodeltransaction.cpp6
-rw-r--r--src/qt/walletmodeltransaction.h5
-rw-r--r--src/wallet/db.cpp2
-rw-r--r--src/wallet/db.h11
-rw-r--r--src/wallet/rpcdump.cpp106
-rw-r--r--src/wallet/rpcwallet.cpp9
-rw-r--r--src/wallet/wallet.cpp37
-rw-r--r--src/wallet/wallet.h5
-rw-r--r--src/wallet/walletdb.cpp32
-rw-r--r--src/wallet/walletdb.h4
-rwxr-xr-xtest/functional/feature_block.py8
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_bumpfee.py1
-rwxr-xr-xtest/functional/wallet_bumpfee_totalfee_deprecation.py54
24 files changed, 190 insertions, 188 deletions
diff --git a/.gitignore b/.gitignore
index 5cef80f92f..cec1fb3dec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,6 +86,7 @@ src/qt/bitcoin-qt.includes
# Compilation and Qt preprocessor part
*.qm
Makefile
+!depends/Makefile
bitcoin-qt
Bitcoin-Qt.app
background.tiff*
diff --git a/configure.ac b/configure.ac
index 08a850cfa2..220c82748e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -323,6 +323,7 @@ if test "x$enable_werror" = "xyes"; then
AC_MSG_ERROR("enable-werror set but -Werror is not usable")
fi
AX_CHECK_COMPILE_FLAG([-Werror=vla],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=vla"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Werror=switch],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=switch"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Werror=thread-safety-analysis],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=thread-safety-analysis"],,[[$CXXFLAG_WERROR]])
fi
@@ -331,6 +332,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wformat],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wvla],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wswitch],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wswitch"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wformat-security],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wrange-loop-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"],,[[$CXXFLAG_WERROR]])
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index ba021a5163..8e31f6e32b 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -143,7 +143,7 @@ static bool AppInit(int argc, char* argv[])
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
- tfm::format(std::cout, PACKAGE_NAME "daemon starting\n");
+ tfm::format(std::cout, PACKAGE_NAME " daemon starting\n");
// Daemonize
if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index f937e2754b..c24234aeb7 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -167,9 +167,6 @@ public:
/* nTxCount */ 383732546,
/* dTxRate */ 3.685496590998308
};
-
- /* disable fallback fee on mainnet */
- m_fallback_fee_enabled = false;
}
};
@@ -262,9 +259,6 @@ public:
/* nTxCount */ 19438708,
/* dTxRate */ 0.626
};
-
- /* enable fallback fee on testnet */
- m_fallback_fee_enabled = true;
}
};
@@ -346,9 +340,6 @@ public:
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};
bech32_hrp = "bcrt";
-
- /* enable fallback fee on regtest */
- m_fallback_fee_enabled = true;
}
/**
diff --git a/src/chainparams.h b/src/chainparams.h
index b3fcd77cea..8f1d27e03c 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -66,7 +66,7 @@ public:
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
/** Policy: Filter transactions that do not match well-defined patterns */
bool RequireStandard() const { return fRequireStandard; }
- /** If this is a test chain */
+ /** If this chain is exclusively used for testing */
bool IsTestChain() const { return m_is_test_chain; }
uint64_t PruneAfterHeight() const { return nPruneAfterHeight; }
/** Minimum free space (in GB) needed for data directory */
@@ -77,8 +77,6 @@ public:
bool MineBlocksOnDemand() const { return consensus.fPowNoRetargeting; }
/** Return the BIP70 network string (main, test or regtest) */
std::string NetworkIDString() const { return strNetworkID; }
- /** Return true if the fallback fee is by default enabled for this network */
- bool IsFallbackFeeEnabled() const { return m_fallback_fee_enabled; }
/** Return the list of hostnames to look up for DNS seeds */
const std::vector<std::string>& DNSSeeds() const { return vSeeds; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
@@ -106,7 +104,6 @@ protected:
bool m_is_test_chain;
CCheckpointData checkpointData;
ChainTxData chainTxData;
- bool m_fallback_fee_enabled;
};
/**
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 355df043d3..f34646f7ac 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -7,7 +7,6 @@
#include <memory>
#include <string>
-#include <vector>
/**
* CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind)
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index deb1618ceb..077dc1ab4d 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -33,31 +33,6 @@
namespace interfaces {
namespace {
-class PendingWalletTxImpl : public PendingWalletTx
-{
-public:
- explicit PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet) {}
-
- const CTransaction& get() override { return *m_tx; }
-
- bool commit(WalletValueMap value_map,
- WalletOrderForm order_form,
- std::string& reject_reason) override
- {
- auto locked_chain = m_wallet.chain().lock();
- LOCK(m_wallet.cs_wallet);
- CValidationState state;
- if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), state)) {
- reject_reason = state.GetRejectReason();
- return false;
- }
- return true;
- }
-
- CTransactionRef m_tx;
- CWallet& m_wallet;
-};
-
//! Construct wallet tx struct.
WalletTx MakeWalletTx(interfaces::Chain::Lock& locked_chain, CWallet& wallet, const CWalletTx& wtx)
{
@@ -227,7 +202,7 @@ public:
LOCK(m_wallet->cs_wallet);
return m_wallet->ListLockedCoins(outputs);
}
- std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
+ CTransactionRef createTransaction(const std::vector<CRecipient>& recipients,
const CCoinControl& coin_control,
bool sign,
int& change_pos,
@@ -236,12 +211,26 @@ public:
{
auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);
- auto pending = MakeUnique<PendingWalletTxImpl>(*m_wallet);
- if (!m_wallet->CreateTransaction(*locked_chain, recipients, pending->m_tx, fee, change_pos,
+ CTransactionRef tx;
+ if (!m_wallet->CreateTransaction(*locked_chain, recipients, tx, fee, change_pos,
fail_reason, coin_control, sign)) {
return {};
}
- return std::move(pending);
+ return tx;
+ }
+ bool commitTransaction(CTransactionRef tx,
+ WalletValueMap value_map,
+ WalletOrderForm order_form,
+ std::string& reject_reason) override
+ {
+ auto locked_chain = m_wallet->chain().lock();
+ LOCK(m_wallet->cs_wallet);
+ CValidationState state;
+ if (!m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form), state)) {
+ reject_reason = state.GetRejectReason();
+ return false;
+ }
+ return true;
}
bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); }
bool abandonTransaction(const uint256& txid) override
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index db47dbafaf..89e056b18b 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -34,7 +34,6 @@ struct CRecipient;
namespace interfaces {
class Handler;
-class PendingWalletTx;
struct WalletAddress;
struct WalletBalances;
struct WalletTx;
@@ -134,13 +133,19 @@ public:
virtual void listLockedCoins(std::vector<COutPoint>& outputs) = 0;
//! Create transaction.
- virtual std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients,
+ virtual CTransactionRef createTransaction(const std::vector<CRecipient>& recipients,
const CCoinControl& coin_control,
bool sign,
int& change_pos,
CAmount& fee,
std::string& fail_reason) = 0;
+ //! Commit transaction.
+ virtual bool commitTransaction(CTransactionRef tx,
+ WalletValueMap value_map,
+ WalletOrderForm order_form,
+ std::string& reject_reason) = 0;
+
//! Return whether transaction can be abandoned.
virtual bool transactionCanBeAbandoned(const uint256& txid) = 0;
@@ -288,21 +293,6 @@ public:
virtual std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0;
};
-//! Tracking object returned by CreateTransaction and passed to CommitTransaction.
-class PendingWalletTx
-{
-public:
- virtual ~PendingWalletTx() {}
-
- //! Get transaction data.
- virtual const CTransaction& get() = 0;
-
- //! Send pending transaction and commit to wallet.
- virtual bool commit(WalletValueMap value_map,
- WalletOrderForm order_form,
- std::string& reject_reason) = 0;
-};
-
//! Information about one wallet address.
struct WalletAddress
{
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index cb9efe9319..193fba78b1 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -392,7 +392,7 @@ void SendCoinsDialog::on_sendButton_clicked()
accept();
CoinControlDialog::coinControl()->UnSelectAll();
coinControlUpdateLabels();
- Q_EMIT coinsSent(currentTransaction.getWtx()->get().GetHash());
+ Q_EMIT coinsSent(currentTransaction.getWtx()->GetHash());
}
fNewRecipientAllowed = true;
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 57406179f7..49a13330ec 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -261,11 +261,11 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
auto& newTx = transaction.getWtx();
std::string rejectReason;
- if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), rejectReason))
+ if (!wallet().commitTransaction(newTx, {} /* mapValue */, std::move(vOrderForm), rejectReason))
return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason));
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- ssTx << newTx->get();
+ ssTx << *newTx;
transaction_array.append(&(ssTx[0]), ssTx.size());
}
diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp
index 8c0dc276b0..d00ccf70d9 100644
--- a/src/qt/walletmodeltransaction.cpp
+++ b/src/qt/walletmodeltransaction.cpp
@@ -21,14 +21,14 @@ QList<SendCoinsRecipient> WalletModelTransaction::getRecipients() const
return recipients;
}
-std::unique_ptr<interfaces::PendingWalletTx>& WalletModelTransaction::getWtx()
+CTransactionRef& WalletModelTransaction::getWtx()
{
return wtx;
}
unsigned int WalletModelTransaction::getTransactionSize()
{
- return wtx ? GetVirtualTransactionSize(wtx->get()) : 0;
+ return wtx ? GetVirtualTransactionSize(*wtx) : 0;
}
CAmount WalletModelTransaction::getTransactionFee() const
@@ -43,7 +43,7 @@ void WalletModelTransaction::setTransactionFee(const CAmount& newFee)
void WalletModelTransaction::reassignAmounts(int nChangePosRet)
{
- const CTransaction* walletTransaction = &wtx->get();
+ const CTransaction* walletTransaction = wtx.get();
int i = 0;
for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it)
{
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
index 289aee847b..a41d8f2457 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -16,7 +16,6 @@ class SendCoinsRecipient;
namespace interfaces {
class Node;
-class PendingWalletTx;
}
/** Data model for a walletmodel transaction. */
@@ -27,7 +26,7 @@ public:
QList<SendCoinsRecipient> getRecipients() const;
- std::unique_ptr<interfaces::PendingWalletTx>& getWtx();
+ CTransactionRef& getWtx();
unsigned int getTransactionSize();
void setTransactionFee(const CAmount& newFee);
@@ -39,7 +38,7 @@ public:
private:
QList<SendCoinsRecipient> recipients;
- std::unique_ptr<interfaces::PendingWalletTx> wtx;
+ CTransactionRef wtx;
CAmount fee;
};
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 852b194386..26aeb754ad 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -585,7 +585,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
if (fCreate && !Exists(std::string("version"))) {
bool fTmp = fReadOnly;
fReadOnly = false;
- WriteVersion(CLIENT_VERSION);
+ Write(std::string("version"), CLIENT_VERSION);
fReadOnly = fTmp;
}
}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index b3856fbaf9..94f41eaf16 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -399,17 +399,6 @@ public:
return (ret == 0);
}
- bool ReadVersion(int& nVersion)
- {
- nVersion = 0;
- return Read(std::string("version"), nVersion);
- }
-
- bool WriteVersion(int nVersion)
- {
- return Write(std::string("version"), nVersion);
- }
-
bool static Rewrite(BerkeleyDatabase& database, const char* pszSkip = nullptr);
};
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 04e9bb40c5..a905cc0c55 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -185,19 +185,15 @@ UniValue importprivkey(const JSONRPCRequest& request)
}
}
- // Don't throw error in case a key is already there
- if (pwallet->HaveKey(vchAddress)) {
- return NullUniValue;
+ // Use timestamp of 1 to scan the whole chain
+ if (!pwallet->ImportPrivKeys({{vchAddress, key}}, 1)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
- // whenever a key is imported, we need to scan the whole chain
- pwallet->UpdateTimeFirstKey(1);
- pwallet->mapKeyMetadata[vchAddress].nCreateTime = 1;
-
- if (!pwallet->AddKeyPubKey(key, pubkey)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
+ // Add the wpkh script for this key if possible
+ if (pubkey.IsCompressed()) {
+ pwallet->ImportScripts({GetScriptForDestination(WitnessV0KeyHash(vchAddress))}, 0 /* timestamp */);
}
- pwallet->LearnAllRelatedScripts(pubkey);
}
}
if (fRescan) {
@@ -235,42 +231,6 @@ UniValue abortrescan(const JSONRPCRequest& request)
return true;
}
-static void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
-static void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
-{
- if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
- throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
- }
-
- pwallet->MarkDirty();
-
- if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, 0 /* nCreateTime */)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
- }
-
- if (isRedeemScript) {
- const CScriptID id(script);
- if (!pwallet->HaveCScript(id) && !pwallet->AddCScript(script)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
- }
- ImportAddress(pwallet, ScriptHash(id), strLabel);
- } else {
- CTxDestination destination;
- if (ExtractDestination(script, destination)) {
- pwallet->SetAddressBook(destination, strLabel, "receive");
- }
- }
-}
-
-static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
-{
- CScript script = GetScriptForDestination(dest);
- ImportScript(pwallet, script, strLabel, false);
- // add to address book or update label
- if (IsValidDestination(dest))
- pwallet->SetAddressBook(dest, strLabel, "receive");
-}
-
UniValue importaddress(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -341,10 +301,22 @@ UniValue importaddress(const JSONRPCRequest& request)
if (fP2SH) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
}
- ImportAddress(pwallet, dest, strLabel);
+
+ pwallet->MarkDirty();
+
+ pwallet->ImportScriptPubKeys(strLabel, {GetScriptForDestination(dest)}, false /* have_solving_data */, true /* apply_label */, 1 /* timestamp */);
} else if (IsHex(request.params[0].get_str())) {
std::vector<unsigned char> data(ParseHex(request.params[0].get_str()));
- ImportScript(pwallet, CScript(data.begin(), data.end()), strLabel, fP2SH);
+ CScript redeem_script(data.begin(), data.end());
+
+ std::set<CScript> scripts = {redeem_script};
+ pwallet->ImportScripts(scripts, 0 /* timestamp */);
+
+ if (fP2SH) {
+ scripts.insert(GetScriptForDestination(ScriptHash(CScriptID(redeem_script))));
+ }
+
+ pwallet->ImportScriptPubKeys(strLabel, scripts, false /* have_solving_data */, true /* apply_label */, 1 /* timestamp */);
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
}
@@ -529,11 +501,16 @@ UniValue importpubkey(const JSONRPCRequest& request)
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
+ std::set<CScript> script_pub_keys;
for (const auto& dest : GetAllDestinationsForKey(pubKey)) {
- ImportAddress(pwallet, dest, strLabel);
+ script_pub_keys.insert(GetScriptForDestination(dest));
}
- ImportScript(pwallet, GetScriptForRawPubKey(pubKey), strLabel, false);
- pwallet->LearnAllRelatedScripts(pubKey);
+
+ pwallet->MarkDirty();
+
+ pwallet->ImportScriptPubKeys(strLabel, script_pub_keys, true /* have_solving_data */, true /* apply_label */, 1 /* timestamp */);
+
+ pwallet->ImportPubKeys({pubKey.GetID()}, {{pubKey.GetID(), pubKey}} , {} /* key_origins */, false /* add_keypool */, false /* internal */, 1 /* timestamp */);
}
if (fRescan)
{
@@ -664,18 +641,18 @@ UniValue importwallet(const JSONRPCRequest& request)
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
- if (pwallet->HaveKey(keyid)) {
- pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(PKHash(keyid)));
- continue;
- }
+
pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(PKHash(keyid)));
- if (!pwallet->AddKeyPubKey(key, pubkey)) {
+
+ if (!pwallet->ImportPrivKeys({{keyid, key}}, time)) {
+ pwallet->WalletLogPrintf("Error importing key for %s\n", EncodeDestination(PKHash(keyid)));
fGood = false;
continue;
}
- pwallet->mapKeyMetadata[keyid].nCreateTime = time;
+
if (has_label)
pwallet->SetAddressBook(PKHash(keyid), label, "receive");
+
nTimeBegin = std::min(nTimeBegin, time);
progress++;
}
@@ -683,24 +660,19 @@ UniValue importwallet(const JSONRPCRequest& request)
pwallet->chain().showProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false);
const CScript& script = script_pair.first;
int64_t time = script_pair.second;
- CScriptID id(script);
- if (pwallet->HaveCScript(id)) {
- pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", HexStr(script));
- continue;
- }
- if(!pwallet->AddCScript(script)) {
+
+ if (!pwallet->ImportScripts({script}, time)) {
pwallet->WalletLogPrintf("Error importing script %s\n", HexStr(script));
fGood = false;
continue;
}
if (time > 0) {
- pwallet->m_script_metadata[id].nCreateTime = time;
nTimeBegin = std::min(nTimeBegin, time);
}
+
progress++;
}
pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
- pwallet->UpdateTimeFirstKey(nTimeBegin);
}
pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
RescanWallet(*pwallet, reserver, nTimeBegin, false /* update */);
@@ -1255,7 +1227,7 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
// All good, time to import
pwallet->MarkDirty();
- if (!pwallet->ImportScripts(import_data.import_scripts)) {
+ if (!pwallet->ImportScripts(import_data.import_scripts, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding script to wallet");
}
if (!pwallet->ImportPrivKeys(privkey_map, timestamp)) {
@@ -1264,7 +1236,7 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
if (!pwallet->ImportPubKeys(ordered_pubkeys, pubkey_map, import_data.key_origins, add_keypool, internal, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- if (!pwallet->ImportScriptPubKeys(label, script_pub_keys, have_solving_data, internal, timestamp)) {
+ if (!pwallet->ImportScriptPubKeys(label, script_pub_keys, have_solving_data, !internal, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index ab732dc0d8..7af009f430 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -3263,12 +3263,12 @@ static UniValue bumpfee(const JSONRPCRequest& request)
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
"An opt-in RBF transaction with the given txid must be in the wallet.\n"
"The command will pay the additional fee by reducing change outputs or adding inputs when necessary. It may add a new change output if one does not already exist.\n"
- "If `totalFee` is given, adding inputs is not supported, so there must be a single change output that is big enough or it will fail.\n"
+ "If `totalFee` (DEPRECATED) is given, adding inputs is not supported, so there must be a single change output that is big enough or it will fail.\n"
"All inputs in the original transaction will be included in the replacement transaction.\n"
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
"By default, the new fee will be calculated automatically using estimatesmartfee.\n"
"The user can specify a confirmation target for estimatesmartfee.\n"
- "Alternatively, the user can specify totalFee, or use RPC settxfee to set a higher fee rate.\n"
+ "Alternatively, the user can specify totalFee (DEPRECATED), or use RPC settxfee to set a higher fee rate.\n"
"At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
"returned by getnetworkinfo) to enter the node's mempool.\n",
{
@@ -3276,7 +3276,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
{
{"confTarget", RPCArg::Type::NUM, /* default */ "fallback to wallet's default", "Confirmation target (in blocks)"},
- {"totalFee", RPCArg::Type::NUM, /* default */ "fallback to 'confTarget'", "Total fee (NOT feerate) to pay, in satoshis.\n"
+ {"totalFee", RPCArg::Type::NUM, /* default */ "fallback to 'confTarget'", "Total fee (NOT feerate) to pay, in satoshis. (DEPRECATED)\n"
" In rare cases, the actual fee paid might be slightly higher than the specified\n"
" totalFee if the tx change output has to be removed because it is too close to\n"
" the dust threshold."},
@@ -3331,6 +3331,9 @@ static UniValue bumpfee(const JSONRPCRequest& request)
} else if (options.exists("confTarget")) { // TODO: alias this to conf_target
coin_control.m_confirm_target = ParseConfirmTarget(options["confTarget"], pwallet->chain().estimateMaxBlocks());
} else if (options.exists("totalFee")) {
+ if (!pwallet->chain().rpcEnableDeprecated("totalFee")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "totalFee argument has been deprecated and will be removed in 0.20. Please use -deprecatedrpc=totalFee to continue using this argument until removal.");
+ }
totalFee = options["totalFee"].get_int64();
if (totalFee <= 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid totalFee %s (must be greater than 0)", FormatMoney(totalFee)));
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 4d2faa8d6c..b9eb0d3eed 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1777,14 +1777,27 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut>
return true;
}
-bool CWallet::ImportScripts(const std::set<CScript> scripts)
+bool CWallet::ImportScripts(const std::set<CScript> scripts, int64_t timestamp)
{
WalletBatch batch(*database);
for (const auto& entry : scripts) {
- if (!HaveCScript(CScriptID(entry)) && !AddCScriptWithDB(batch, entry)) {
+ CScriptID id(entry);
+ if (HaveCScript(id)) {
+ WalletLogPrintf("Already have script %s, skipping\n", HexStr(entry));
+ continue;
+ }
+ if (!AddCScriptWithDB(batch, entry)) {
return false;
}
+
+ if (timestamp > 0) {
+ m_script_metadata[CScriptID(entry)].nCreateTime = timestamp;
+ }
+ }
+ if (timestamp > 0) {
+ UpdateTimeFirstKey(timestamp);
}
+
return true;
}
@@ -1796,9 +1809,14 @@ bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const in
CPubKey pubkey = key.GetPubKey();
const CKeyID& id = entry.first;
assert(key.VerifyPubKey(pubkey));
+ // Skip if we already have the key
+ if (HaveKey(id)) {
+ WalletLogPrintf("Already have key with pubkey %s, skipping\n", HexStr(pubkey));
+ continue;
+ }
mapKeyMetadata[id].nCreateTime = timestamp;
// If the private key is not present in the wallet, insert it.
- if (!HaveKey(id) && !AddKeyPubKeyWithDB(batch, key, pubkey)) {
+ if (!AddKeyPubKeyWithDB(batch, key, pubkey)) {
return false;
}
UpdateTimeFirstKey(timestamp);
@@ -1819,7 +1837,12 @@ bool CWallet::ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const st
}
const CPubKey& pubkey = entry->second;
CPubKey temp;
- if (!GetPubKey(id, temp) && !AddWatchOnlyWithDB(batch, GetScriptForRawPubKey(pubkey), timestamp)) {
+ if (GetPubKey(id, temp)) {
+ // Already have pubkey, skipping
+ WalletLogPrintf("Already have pubkey %s, skipping\n", HexStr(temp));
+ continue;
+ }
+ if (!AddWatchOnlyWithDB(batch, GetScriptForRawPubKey(pubkey), timestamp)) {
return false;
}
mapKeyMetadata[id].nCreateTime = timestamp;
@@ -1833,7 +1856,7 @@ bool CWallet::ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const st
return true;
}
-bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool internal, const int64_t timestamp)
+bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp)
{
WalletBatch batch(*database);
for (const CScript& script : script_pub_keys) {
@@ -1844,7 +1867,7 @@ bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScri
}
CTxDestination dest;
ExtractDestination(script, dest);
- if (!internal && IsValidDestination(dest)) {
+ if (apply_label && IsValidDestination(dest)) {
SetAddressBookWithDB(batch, dest, label, "receive");
}
}
@@ -4386,7 +4409,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
walletInstance->m_min_fee = CFeeRate(n);
}
- walletInstance->m_allow_fallback_fee = Params().IsFallbackFeeEnabled();
+ walletInstance->m_allow_fallback_fee = Params().IsTestChain();
if (gArgs.IsArgSet("-fallbackfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 6a7097bf44..8ed27c3cc8 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -12,7 +12,6 @@
#include <outputtype.h>
#include <policy/feerate.h>
#include <script/sign.h>
-#include <streams.h>
#include <tinyformat.h>
#include <ui_interface.h>
#include <util/strencodings.h>
@@ -1150,10 +1149,10 @@ public:
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;
- bool ImportScripts(const std::set<CScript> scripts) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index ece97e2a75..43dd28b675 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -165,7 +165,6 @@ public:
unsigned int m_unknown_records{0};
bool fIsEncrypted{false};
bool fAnyUnordered{false};
- int nFileVersion{0};
std::vector<uint256> vWalletUpgrade;
CWalletScanState() {
@@ -376,12 +375,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
pwallet->LoadKeyPool(nIndex, keypool);
}
- else if (strType == "version")
- {
- ssValue >> wss.nFileVersion;
- if (wss.nFileVersion == 10300)
- wss.nFileVersion = 300;
- }
else if (strType == "cscript")
{
uint160 hash;
@@ -419,7 +412,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
return false;
}
} else if (strType != "bestblock" && strType != "bestblock_nomerkle" &&
- strType != "minversion" && strType != "acentry") {
+ strType != "minversion" && strType != "acentry" && strType != "version") {
wss.m_unknown_records++;
}
} catch (const std::exception& e) {
@@ -519,7 +512,12 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (result != DBErrors::LOAD_OK)
return result;
- pwallet->WalletLogPrintf("nFileVersion = %d\n", wss.nFileVersion);
+ // Last client version to open this wallet, was previously the file version number
+ int last_client = CLIENT_VERSION;
+ m_batch.Read(std::string("version"), last_client);
+
+ int wallet_version = pwallet->GetVersion();
+ pwallet->WalletLogPrintf("Wallet File Version = %d\n", wallet_version > 0 ? wallet_version : last_client);
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);
@@ -532,11 +530,11 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
WriteTx(pwallet->mapWallet.at(hash));
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
- if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
+ if (wss.fIsEncrypted && (last_client == 40000 || last_client == 50000))
return DBErrors::NEED_REWRITE;
- if (wss.nFileVersion < CLIENT_VERSION) // Update
- WriteVersion(CLIENT_VERSION);
+ if (last_client < CLIENT_VERSION) // Update
+ m_batch.Write(std::string("version"), CLIENT_VERSION);
if (wss.fAnyUnordered)
result = pwallet->ReorderTransactions();
@@ -779,13 +777,3 @@ bool WalletBatch::TxnAbort()
{
return m_batch.TxnAbort();
}
-
-bool WalletBatch::ReadVersion(int& nVersion)
-{
- return m_batch.ReadVersion(nVersion);
-}
-
-bool WalletBatch::WriteVersion(int nVersion)
-{
- return m_batch.WriteVersion(nVersion);
-}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index d4a3bba97a..90692317ea 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -249,10 +249,6 @@ public:
bool TxnCommit();
//! Abort current transaction
bool TxnAbort();
- //! Read wallet version
- bool ReadVersion(int& nVersion);
- //! Write wallet version
- bool WriteVersion(int nVersion);
private:
BerkeleyBatch m_batch;
WalletDatabase& m_database;
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index b5eac88ba7..fdb608d457 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -486,6 +486,14 @@ class FullBlockTest(BitcoinTestFramework):
tx_last = tx_new
b39_outputs += 1
+ # The accounting in the loop above can be off, because it misses the
+ # compact size encoding of the number of transactions in the block.
+ # Make sure we didn't accidentally make too big a block. Note that the
+ # size of the block has non-determinism due to the ECDSA signature in
+ # the first transaction.
+ while (len(b39.serialize()) >= MAX_BLOCK_BASE_SIZE):
+ del b39.vtx[-1]
+
b39 = self.update_block(39, [])
self.send_blocks([b39], True)
self.save_spendable_output()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 0db8382733..7ad2b78d4e 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -175,6 +175,7 @@ BASE_SCRIPTS = [
'rpc_bind.py --nonloopback',
'mining_basic.py',
'wallet_bumpfee.py',
+ 'wallet_bumpfee_totalfee_deprecation.py',
'rpc_named_arguments.py',
'wallet_listsinceblock.py',
'p2p_leak.py',
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 030eb50791..bfc01e3f5e 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -37,6 +37,7 @@ class BumpFeeTest(BitcoinTestFramework):
self.extra_args = [[
"-walletrbf={}".format(i),
"-mintxfee=0.00002",
+ "-deprecatedrpc=totalFee",
] for i in range(self.num_nodes)]
def skip_test_if_missing_module(self):
diff --git a/test/functional/wallet_bumpfee_totalfee_deprecation.py b/test/functional/wallet_bumpfee_totalfee_deprecation.py
new file mode 100755
index 0000000000..b8e097c32e
--- /dev/null
+++ b/test/functional/wallet_bumpfee_totalfee_deprecation.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test deprecation of passing `totalFee` to the bumpfee RPC."""
+from decimal import Decimal
+
+from test_framework.messages import BIP125_SEQUENCE_NUMBER
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_raises_rpc_error
+
+class BumpFeeWithTotalFeeArgumentDeprecationTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.extra_args = [[
+ "-walletrbf={}".format(i),
+ "-mintxfee=0.00002",
+ ] for i in range(self.num_nodes)]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def run_test(self):
+ peer_node, rbf_node = self.nodes
+ peer_node.generate(110)
+ self.sync_all()
+ peer_node.sendtoaddress(rbf_node.getnewaddress(), 0.001)
+ self.sync_all()
+ peer_node.generate(1)
+ self.sync_all()
+ rbfid = spend_one_input(rbf_node, peer_node.getnewaddress())
+
+ self.log.info("Testing bumpfee with totalFee argument raises RPC error with deprecation message")
+ assert_raises_rpc_error(
+ -8,
+ "totalFee argument has been deprecated and will be removed in 0.20. " +
+ "Please use -deprecatedrpc=totalFee to continue using this argument until removal.",
+ rbf_node.bumpfee, rbfid, {"totalFee": 2000})
+
+ self.log.info("Testing bumpfee without totalFee argument does not raise")
+ rbf_node.bumpfee(rbfid)
+
+def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
+ tx_input = dict(sequence=BIP125_SEQUENCE_NUMBER,
+ **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
+ destinations = {dest_address: Decimal("0.00050000")}
+ destinations[node.getrawchangeaddress()] = change_size
+ rawtx = node.createrawtransaction([tx_input], destinations)
+ signedtx = node.signrawtransactionwithwallet(rawtx)
+ txid = node.sendrawtransaction(signedtx["hex"])
+ return txid
+
+if __name__ == "__main__":
+ BumpFeeWithTotalFeeArgumentDeprecationTest().main()