diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/init.cpp | 39 | ||||
-rw-r--r-- | src/interfaces/wallet.cpp | 255 | ||||
-rw-r--r-- | src/node/transaction.cpp | 40 | ||||
-rw-r--r-- | src/node/transaction.h | 20 | ||||
-rw-r--r-- | src/psbt.cpp | 10 | ||||
-rw-r--r-- | src/psbt.h | 7 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 9 | ||||
-rw-r--r-- | src/util/system.cpp | 18 | ||||
-rw-r--r-- | src/util/system.h | 5 | ||||
-rw-r--r-- | src/wallet/psbtwallet.cpp | 10 | ||||
-rw-r--r-- | src/wallet/psbtwallet.h | 8 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 8 | ||||
-rw-r--r-- | src/wallet/test/psbt_wallet_tests.cpp | 3 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 9 |
14 files changed, 215 insertions, 226 deletions
diff --git a/src/init.cpp b/src/init.cpp index 0013319ad5..8b831a726f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -53,6 +53,8 @@ #include <stdio.h> #ifndef WIN32 +#include <attributes.h> +#include <cerrno> #include <signal.h> #include <sys/stat.h> #endif @@ -92,6 +94,30 @@ std::unique_ptr<BanMan> g_banman; static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; +/** + * The PID file facilities. + */ +#ifndef WIN32 +static const char* BITCOIN_PID_FILENAME = "bitcoind.pid"; + +static fs::path GetPidFile() +{ + return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME))); +} + +NODISCARD static bool CreatePidFile() +{ + FILE* file = fsbridge::fopen(GetPidFile(), "w"); + if (file) { + fprintf(file, "%d\n", getpid()); + fclose(file); + return true; + } else { + return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno))); + } +} +#endif + ////////////////////////////////////////////////////////////////////////////// // // Shutdown @@ -262,9 +288,11 @@ void Shutdown(InitInterfaces& interfaces) #ifndef WIN32 try { - fs::remove(GetPidFile()); + if (!fs::remove(GetPidFile())) { + LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__); + } } catch (const fs::filesystem_error& e) { - LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what()); + LogPrintf("%s: Unable to remove PID file: %s\n", __func__, e.what()); } #endif interfaces.chain_clients.clear(); @@ -352,7 +380,7 @@ void SetupServerArgs() gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS); gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS); gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), true, OptionsCategory::OPTIONS); - gArgs.AddArg("-dbcache=<n>", strprintf("Set database cache size in MiB (%d to %d, default: %d)", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS); + gArgs.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS); gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS); gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), true, OptionsCategory::OPTIONS); gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", false, OptionsCategory::OPTIONS); @@ -1201,7 +1229,10 @@ bool AppInitMain(InitInterfaces& interfaces) const CChainParams& chainparams = Params(); // ********************************************************* Step 4a: application initialization #ifndef WIN32 - CreatePidFile(GetPidFile(), getpid()); + if (!CreatePidFile()) { + // Detailed error printed inside CreatePidFile(). + return false; + } #endif if (LogInstance().m_print_to_file) { if (gArgs.GetBoolArg("-shrinkdebugfile", LogInstance().DefaultShrinkDebugFile())) { diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 5b5430037c..0dac75834e 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -135,55 +135,55 @@ WalletTxOut MakeWalletTxOut(interfaces::Chain::Lock& locked_chain, class WalletImpl : public Wallet { public: - explicit WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_shared_wallet(wallet), m_wallet(*wallet.get()) {} + explicit WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_wallet(wallet) {} bool encryptWallet(const SecureString& wallet_passphrase) override { - return m_wallet.EncryptWallet(wallet_passphrase); + return m_wallet->EncryptWallet(wallet_passphrase); } - bool isCrypted() override { return m_wallet.IsCrypted(); } - bool lock() override { return m_wallet.Lock(); } - bool unlock(const SecureString& wallet_passphrase) override { return m_wallet.Unlock(wallet_passphrase); } - bool isLocked() override { return m_wallet.IsLocked(); } + bool isCrypted() override { return m_wallet->IsCrypted(); } + bool lock() override { return m_wallet->Lock(); } + bool unlock(const SecureString& wallet_passphrase) override { return m_wallet->Unlock(wallet_passphrase); } + bool isLocked() override { return m_wallet->IsLocked(); } bool changeWalletPassphrase(const SecureString& old_wallet_passphrase, const SecureString& new_wallet_passphrase) override { - return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase); + return m_wallet->ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase); } - void abortRescan() override { m_wallet.AbortRescan(); } - bool backupWallet(const std::string& filename) override { return m_wallet.BackupWallet(filename); } - std::string getWalletName() override { return m_wallet.GetName(); } + void abortRescan() override { m_wallet->AbortRescan(); } + bool backupWallet(const std::string& filename) override { return m_wallet->BackupWallet(filename); } + std::string getWalletName() override { return m_wallet->GetName(); } bool getKeyFromPool(bool internal, CPubKey& pub_key) override { - return m_wallet.GetKeyFromPool(pub_key, internal); + return m_wallet->GetKeyFromPool(pub_key, internal); } - bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet.GetPubKey(address, pub_key); } - bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet.GetKey(address, key); } - bool isSpendable(const CTxDestination& dest) override { return IsMine(m_wallet, dest) & ISMINE_SPENDABLE; } - bool haveWatchOnly() override { return m_wallet.HaveWatchOnly(); }; + bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet->GetPubKey(address, pub_key); } + bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet->GetKey(address, key); } + bool isSpendable(const CTxDestination& dest) override { return IsMine(*m_wallet, dest) & ISMINE_SPENDABLE; } + bool haveWatchOnly() override { return m_wallet->HaveWatchOnly(); }; bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::string& purpose) override { - return m_wallet.SetAddressBook(dest, name, purpose); + return m_wallet->SetAddressBook(dest, name, purpose); } bool delAddressBook(const CTxDestination& dest) override { - return m_wallet.DelAddressBook(dest); + return m_wallet->DelAddressBook(dest); } bool getAddress(const CTxDestination& dest, std::string* name, isminetype* is_mine, std::string* purpose) override { - LOCK(m_wallet.cs_wallet); - auto it = m_wallet.mapAddressBook.find(dest); - if (it == m_wallet.mapAddressBook.end()) { + LOCK(m_wallet->cs_wallet); + auto it = m_wallet->mapAddressBook.find(dest); + if (it == m_wallet->mapAddressBook.end()) { return false; } if (name) { *name = it->second.name; } if (is_mine) { - *is_mine = IsMine(m_wallet, dest); + *is_mine = IsMine(*m_wallet, dest); } if (purpose) { *purpose = it->second.purpose; @@ -192,52 +192,52 @@ public: } std::vector<WalletAddress> getAddresses() override { - LOCK(m_wallet.cs_wallet); + LOCK(m_wallet->cs_wallet); std::vector<WalletAddress> result; - for (const auto& item : m_wallet.mapAddressBook) { - result.emplace_back(item.first, IsMine(m_wallet, item.first), item.second.name, item.second.purpose); + for (const auto& item : m_wallet->mapAddressBook) { + result.emplace_back(item.first, IsMine(*m_wallet, item.first), item.second.name, item.second.purpose); } return result; } - void learnRelatedScripts(const CPubKey& key, OutputType type) override { m_wallet.LearnRelatedScripts(key, type); } + void learnRelatedScripts(const CPubKey& key, OutputType type) override { m_wallet->LearnRelatedScripts(key, type); } bool addDestData(const CTxDestination& dest, const std::string& key, const std::string& value) override { - LOCK(m_wallet.cs_wallet); - return m_wallet.AddDestData(dest, key, value); + LOCK(m_wallet->cs_wallet); + return m_wallet->AddDestData(dest, key, value); } bool eraseDestData(const CTxDestination& dest, const std::string& key) override { - LOCK(m_wallet.cs_wallet); - return m_wallet.EraseDestData(dest, key); + LOCK(m_wallet->cs_wallet); + return m_wallet->EraseDestData(dest, key); } std::vector<std::string> getDestValues(const std::string& prefix) override { - LOCK(m_wallet.cs_wallet); - return m_wallet.GetDestValues(prefix); + LOCK(m_wallet->cs_wallet); + return m_wallet->GetDestValues(prefix); } void lockCoin(const COutPoint& output) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.LockCoin(output); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->LockCoin(output); } void unlockCoin(const COutPoint& output) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.UnlockCoin(output); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->UnlockCoin(output); } bool isLockedCoin(const COutPoint& output) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.IsLockedCoin(output.hash, output.n); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->IsLockedCoin(output.hash, output.n); } void listLockedCoins(std::vector<COutPoint>& outputs) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.ListLockedCoins(outputs); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->ListLockedCoins(outputs); } std::unique_ptr<PendingWalletTx> createTransaction(const std::vector<CRecipient>& recipients, const CCoinControl& coin_control, @@ -246,25 +246,25 @@ public: CAmount& fee, std::string& fail_reason) override { - 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, pending->m_key, fee, change_pos, + 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, pending->m_key, fee, change_pos, fail_reason, coin_control, sign)) { return {}; } return std::move(pending); } - bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet.TransactionCanBeAbandoned(txid); } + bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); } bool abandonTransaction(const uint256& txid) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.AbandonTransaction(*locked_chain, txid); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->AbandonTransaction(*locked_chain, txid); } bool transactionCanBeBumped(const uint256& txid) override { - return feebumper::TransactionCanBeBumped(&m_wallet, txid); + return feebumper::TransactionCanBeBumped(m_wallet.get(), txid); } bool createBumpTransaction(const uint256& txid, const CCoinControl& coin_control, @@ -274,46 +274,46 @@ public: CAmount& new_fee, CMutableTransaction& mtx) override { - return feebumper::CreateTransaction(&m_wallet, txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) == + return feebumper::CreateTransaction(m_wallet.get(), txid, coin_control, total_fee, errors, old_fee, new_fee, mtx) == feebumper::Result::OK; } - bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(&m_wallet, mtx); } + bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(m_wallet.get(), mtx); } bool commitBumpTransaction(const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) override { - return feebumper::CommitTransaction(&m_wallet, txid, std::move(mtx), errors, bumped_txid) == + return feebumper::CommitTransaction(m_wallet.get(), txid, std::move(mtx), errors, bumped_txid) == feebumper::Result::OK; } CTransactionRef getTx(const uint256& txid) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - auto mi = m_wallet.mapWallet.find(txid); - if (mi != m_wallet.mapWallet.end()) { + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + auto mi = m_wallet->mapWallet.find(txid); + if (mi != m_wallet->mapWallet.end()) { return mi->second.tx; } return {}; } WalletTx getWalletTx(const uint256& txid) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - auto mi = m_wallet.mapWallet.find(txid); - if (mi != m_wallet.mapWallet.end()) { - return MakeWalletTx(*locked_chain, m_wallet, mi->second); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + auto mi = m_wallet->mapWallet.find(txid); + if (mi != m_wallet->mapWallet.end()) { + return MakeWalletTx(*locked_chain, *m_wallet, mi->second); } return {}; } std::vector<WalletTx> getWalletTxs() override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); std::vector<WalletTx> result; - result.reserve(m_wallet.mapWallet.size()); - for (const auto& entry : m_wallet.mapWallet) { - result.emplace_back(MakeWalletTx(*locked_chain, m_wallet, entry.second)); + result.reserve(m_wallet->mapWallet.size()); + for (const auto& entry : m_wallet->mapWallet) { + result.emplace_back(MakeWalletTx(*locked_chain, *m_wallet, entry.second)); } return result; } @@ -322,16 +322,16 @@ public: int& num_blocks, int64_t& block_time) override { - auto locked_chain = m_wallet.chain().lock(true /* try_lock */); + auto locked_chain = m_wallet->chain().lock(true /* try_lock */); if (!locked_chain) { return false; } - TRY_LOCK(m_wallet.cs_wallet, locked_wallet); + TRY_LOCK(m_wallet->cs_wallet, locked_wallet); if (!locked_wallet) { return false; } - auto mi = m_wallet.mapWallet.find(txid); - if (mi == m_wallet.mapWallet.end()) { + auto mi = m_wallet->mapWallet.find(txid); + if (mi == m_wallet->mapWallet.end()) { return false; } if (Optional<int> height = locked_chain->getHeight()) { @@ -350,37 +350,37 @@ public: bool& in_mempool, int& num_blocks) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - auto mi = m_wallet.mapWallet.find(txid); - if (mi != m_wallet.mapWallet.end()) { + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + auto mi = m_wallet->mapWallet.find(txid); + if (mi != m_wallet->mapWallet.end()) { num_blocks = locked_chain->getHeight().get_value_or(-1); in_mempool = mi->second.InMempool(); order_form = mi->second.vOrderForm; tx_status = MakeWalletTxStatus(*locked_chain, mi->second); - return MakeWalletTx(*locked_chain, m_wallet, mi->second); + return MakeWalletTx(*locked_chain, *m_wallet, mi->second); } return {}; } WalletBalances getBalances() override { WalletBalances result; - result.balance = m_wallet.GetBalance(); - result.unconfirmed_balance = m_wallet.GetUnconfirmedBalance(); - result.immature_balance = m_wallet.GetImmatureBalance(); - result.have_watch_only = m_wallet.HaveWatchOnly(); + result.balance = m_wallet->GetBalance(); + result.unconfirmed_balance = m_wallet->GetUnconfirmedBalance(); + result.immature_balance = m_wallet->GetImmatureBalance(); + result.have_watch_only = m_wallet->HaveWatchOnly(); if (result.have_watch_only) { - result.watch_only_balance = m_wallet.GetBalance(ISMINE_WATCH_ONLY); - result.unconfirmed_watch_only_balance = m_wallet.GetUnconfirmedWatchOnlyBalance(); - result.immature_watch_only_balance = m_wallet.GetImmatureWatchOnlyBalance(); + result.watch_only_balance = m_wallet->GetBalance(ISMINE_WATCH_ONLY); + result.unconfirmed_watch_only_balance = m_wallet->GetUnconfirmedWatchOnlyBalance(); + result.immature_watch_only_balance = m_wallet->GetImmatureWatchOnlyBalance(); } return result; } bool tryGetBalances(WalletBalances& balances, int& num_blocks) override { - auto locked_chain = m_wallet.chain().lock(true /* try_lock */); + auto locked_chain = m_wallet->chain().lock(true /* try_lock */); if (!locked_chain) return false; - TRY_LOCK(m_wallet.cs_wallet, locked_wallet); + TRY_LOCK(m_wallet->cs_wallet, locked_wallet); if (!locked_wallet) { return false; } @@ -388,68 +388,68 @@ public: num_blocks = locked_chain->getHeight().get_value_or(-1); return true; } - CAmount getBalance() override { return m_wallet.GetBalance(); } + CAmount getBalance() override { return m_wallet->GetBalance(); } CAmount getAvailableBalance(const CCoinControl& coin_control) override { - return m_wallet.GetAvailableBalance(&coin_control); + return m_wallet->GetAvailableBalance(&coin_control); } isminetype txinIsMine(const CTxIn& txin) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.IsMine(txin); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->IsMine(txin); } isminetype txoutIsMine(const CTxOut& txout) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.IsMine(txout); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->IsMine(txout); } CAmount getDebit(const CTxIn& txin, isminefilter filter) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.GetDebit(txin, filter); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->GetDebit(txin, filter); } CAmount getCredit(const CTxOut& txout, isminefilter filter) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); - return m_wallet.GetCredit(txout, filter); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); + return m_wallet->GetCredit(txout, filter); } CoinsList listCoins() override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); CoinsList result; - for (const auto& entry : m_wallet.ListCoins(*locked_chain)) { + for (const auto& entry : m_wallet->ListCoins(*locked_chain)) { auto& group = result[entry.first]; for (const auto& coin : entry.second) { group.emplace_back(COutPoint(coin.tx->GetHash(), coin.i), - MakeWalletTxOut(*locked_chain, m_wallet, *coin.tx, coin.i, coin.nDepth)); + MakeWalletTxOut(*locked_chain, *m_wallet, *coin.tx, coin.i, coin.nDepth)); } } return result; } std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) override { - auto locked_chain = m_wallet.chain().lock(); - LOCK(m_wallet.cs_wallet); + auto locked_chain = m_wallet->chain().lock(); + LOCK(m_wallet->cs_wallet); std::vector<WalletTxOut> result; result.reserve(outputs.size()); for (const auto& output : outputs) { result.emplace_back(); - auto it = m_wallet.mapWallet.find(output.hash); - if (it != m_wallet.mapWallet.end()) { + auto it = m_wallet->mapWallet.find(output.hash); + if (it != m_wallet->mapWallet.end()) { int depth = it->second.GetDepthInMainChain(*locked_chain); if (depth >= 0) { - result.back() = MakeWalletTxOut(*locked_chain, m_wallet, it->second, output.n, depth); + result.back() = MakeWalletTxOut(*locked_chain, *m_wallet, it->second, output.n, depth); } } } return result; } - CAmount getRequiredFee(unsigned int tx_bytes) override { return GetRequiredFee(m_wallet, tx_bytes); } + CAmount getRequiredFee(unsigned int tx_bytes) override { return GetRequiredFee(*m_wallet, tx_bytes); } CAmount getMinimumFee(unsigned int tx_bytes, const CCoinControl& coin_control, int* returned_target, @@ -457,55 +457,54 @@ public: { FeeCalculation fee_calc; CAmount result; - result = GetMinimumFee(m_wallet, tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc); + result = GetMinimumFee(*m_wallet, tx_bytes, coin_control, ::mempool, ::feeEstimator, &fee_calc); if (returned_target) *returned_target = fee_calc.returnedTarget; if (reason) *reason = fee_calc.reason; return result; } - unsigned int getConfirmTarget() override { return m_wallet.m_confirm_target; } - bool hdEnabled() override { return m_wallet.IsHDEnabled(); } - bool canGetAddresses() override { return m_wallet.CanGetAddresses(); } - bool IsWalletFlagSet(uint64_t flag) override { return m_wallet.IsWalletFlagSet(flag); } - OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; } - OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; } + unsigned int getConfirmTarget() override { return m_wallet->m_confirm_target; } + bool hdEnabled() override { return m_wallet->IsHDEnabled(); } + bool canGetAddresses() override { return m_wallet->CanGetAddresses(); } + bool IsWalletFlagSet(uint64_t flag) override { return m_wallet->IsWalletFlagSet(flag); } + OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; } + OutputType getDefaultChangeType() override { return m_wallet->m_default_change_type; } void remove() override { - RemoveWallet(m_shared_wallet); + RemoveWallet(m_wallet); } std::unique_ptr<Handler> handleUnload(UnloadFn fn) override { - return MakeHandler(m_wallet.NotifyUnload.connect(fn)); + return MakeHandler(m_wallet->NotifyUnload.connect(fn)); } std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override { - return MakeHandler(m_wallet.ShowProgress.connect(fn)); + return MakeHandler(m_wallet->ShowProgress.connect(fn)); } std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override { - return MakeHandler(m_wallet.NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); })); + return MakeHandler(m_wallet->NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); })); } std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override { - return MakeHandler(m_wallet.NotifyAddressBookChanged.connect( + return MakeHandler(m_wallet->NotifyAddressBookChanged.connect( [fn](CWallet*, const CTxDestination& address, const std::string& label, bool is_mine, const std::string& purpose, ChangeType status) { fn(address, label, is_mine, purpose, status); })); } std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) override { - return MakeHandler(m_wallet.NotifyTransactionChanged.connect( + return MakeHandler(m_wallet->NotifyTransactionChanged.connect( [fn](CWallet*, const uint256& txid, ChangeType status) { fn(txid, status); })); } std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) override { - return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn)); + return MakeHandler(m_wallet->NotifyWatchonlyChanged.connect(fn)); } std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override { - return MakeHandler(m_wallet.NotifyCanGetAddressesChanged.connect(fn)); + return MakeHandler(m_wallet->NotifyCanGetAddressesChanged.connect(fn)); } - std::shared_ptr<CWallet> m_shared_wallet; - CWallet& m_wallet; + std::shared_ptr<CWallet> m_wallet; }; class WalletClientImpl : public ChainClient diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index c9cdd0d1cd..7b9b4310e7 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -12,7 +12,7 @@ #include <future> -const char* TransactionErrorString(const TransactionError err) +std::string TransactionErrorString(const TransactionError err) { switch (err) { case TransactionError::OK: @@ -33,22 +33,16 @@ const char* TransactionErrorString(const TransactionError err) return "PSBTs not compatible (different transactions)"; case TransactionError::SIGHASH_MISMATCH: return "Specified sighash value does not match existing value"; - - case TransactionError::UNKNOWN_ERROR: - default: break; + // no default case, so the compiler can warn about missing cases } - return "Unknown error"; + assert(false); } -bool BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, TransactionError& error, std::string& err_string, const bool allowhighfees) +TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee) { std::promise<void> promise; hashTx = tx->GetHash(); - CAmount nMaxRawTxFee = maxTxFee; - if (allowhighfees) - nMaxRawTxFee = 0; - { // cs_main scope LOCK(cs_main); CCoinsViewCache &view = *pcoinsTip; @@ -63,19 +57,16 @@ bool BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, Transaction CValidationState state; bool fMissingInputs; if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs, - nullptr /* plTxnReplaced */, false /* bypass_limits */, nMaxRawTxFee)) { + nullptr /* plTxnReplaced */, false /* bypass_limits */, highfee)) { if (state.IsInvalid()) { err_string = FormatStateMessage(state); - error = TransactionError::MEMPOOL_REJECTED; - return false; + return TransactionError::MEMPOOL_REJECTED; } else { if (fMissingInputs) { - error = TransactionError::MISSING_INPUTS; - return false; + return TransactionError::MISSING_INPUTS; } err_string = FormatStateMessage(state); - error = TransactionError::MEMPOOL_ERROR; - return false; + return TransactionError::MEMPOOL_ERROR; } } else { // If wallet is enabled, ensure that the wallet has been made aware @@ -88,8 +79,7 @@ bool BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, Transaction }); } } else if (fHaveChain) { - error = TransactionError::ALREADY_IN_CHAIN; - return false; + return TransactionError::ALREADY_IN_CHAIN; } else { // Make sure we don't block forever if re-sending // a transaction already in mempool. @@ -100,16 +90,14 @@ bool BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, Transaction promise.get_future().wait(); - if(!g_connman) { - error = TransactionError::P2P_DISABLED; - return false; + if (!g_connman) { + return TransactionError::P2P_DISABLED; } CInv inv(MSG_TX, hashTx); - g_connman->ForEachNode([&inv](CNode* pnode) - { + g_connman->ForEachNode([&inv](CNode* pnode) { pnode->PushInventory(inv); }); - return true; - } + return TransactionError::OK; +} diff --git a/src/node/transaction.h b/src/node/transaction.h index 3b0cbba98b..3457ececa4 100644 --- a/src/node/transaction.h +++ b/src/node/transaction.h @@ -1,17 +1,16 @@ -// Copyright (c) 2017-2018 The Bitcoin Core developers +// Copyright (c) 2017-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. #ifndef BITCOIN_NODE_TRANSACTION_H #define BITCOIN_NODE_TRANSACTION_H +#include <attributes.h> #include <primitives/transaction.h> #include <uint256.h> enum class TransactionError { - OK = 0, - UNKNOWN_ERROR, - + OK, //!< No error MISSING_INPUTS, ALREADY_IN_CHAIN, P2P_DISABLED, @@ -20,24 +19,19 @@ enum class TransactionError { INVALID_PSBT, PSBT_MISMATCH, SIGHASH_MISMATCH, - - ERROR_COUNT }; -#define TRANSACTION_ERR_LAST TransactionError::ERROR_COUNT - -const char* TransactionErrorString(const TransactionError error); +std::string TransactionErrorString(const TransactionError error); /** * Broadcast a transaction * * @param[in] tx the transaction to broadcast * @param[out] &txid the txid of the transaction, if successfully broadcast - * @param[out] &error reference to UniValue to fill with error info on failure * @param[out] &err_string reference to std::string to fill with error string if available - * @param[in] allowhighfees whether to allow fees exceeding maxTxFee - * return true on success, false on error (and fills in `error`) + * @param[in] highfee Reject txs with fees higher than this (if 0, accept any fee) + * return error */ -bool BroadcastTransaction(CTransactionRef tx, uint256& txid, TransactionError& error, std::string& err_string, bool allowhighfees = false); +NODISCARD TransactionError BroadcastTransaction(CTransactionRef tx, uint256& txid, std::string& err_string, const CAmount& highfee); #endif // BITCOIN_NODE_TRANSACTION_H diff --git a/src/psbt.cpp b/src/psbt.cpp index 32fb459dec..0fb7d49d7d 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -309,21 +309,19 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti return true; } -bool CombinePSBTs(PartiallySignedTransaction& out, TransactionError& error, const std::vector<PartiallySignedTransaction>& psbtxs) +TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs) { out = psbtxs[0]; // Copy the first one // Merge for (auto it = std::next(psbtxs.begin()); it != psbtxs.end(); ++it) { if (!out.Merge(*it)) { - error = TransactionError::PSBT_MISMATCH; - return false; + return TransactionError::PSBT_MISMATCH; } } if (!out.IsSane()) { - error = TransactionError::INVALID_PSBT; - return false; + return TransactionError::INVALID_PSBT; } - return true; + return TransactionError::OK; } diff --git a/src/psbt.h b/src/psbt.h index 27b0aedd05..c889dad361 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-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. @@ -575,10 +575,9 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti * Combines PSBTs with the same underlying transaction, resulting in a single PSBT with all partial signatures from each input. * * @param[out] &out the combined PSBT, if successful - * @param[out] &error reference to TransactionError to fill with error info on failure * @param[in] psbtxs the PSBTs to combine - * @return True if we successfully combined the transactions, false if they were not compatible + * @return error (OK if we successfully combined the transactions, other error if they were not compatible) */ -bool CombinePSBTs(PartiallySignedTransaction& out, TransactionError& error, const std::vector<PartiallySignedTransaction>& psbtxs); +NODISCARD TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs); #endif // BITCOIN_PSBT_H diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 38e2dc237e..5a714a137e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1065,10 +1065,11 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request) bool allowhighfees = false; if (!request.params[1].isNull()) allowhighfees = request.params[1].get_bool(); + const CAmount highfee{allowhighfees ? 0 : ::maxTxFee}; uint256 txid; - TransactionError err; std::string err_string; - if (!BroadcastTransaction(tx, txid, err, err_string, allowhighfees)) { + const TransactionError err = BroadcastTransaction(tx, txid, err_string, highfee); + if (TransactionError::OK != err) { throw JSONRPCTransactionError(err, err_string); } @@ -1493,8 +1494,8 @@ UniValue combinepsbt(const JSONRPCRequest& request) } PartiallySignedTransaction merged_psbt; - TransactionError error; - if (!CombinePSBTs(merged_psbt, error, psbtxs)) { + const TransactionError error = CombinePSBTs(merged_psbt, psbtxs); + if (error != TransactionError::OK) { throw JSONRPCTransactionError(error); } diff --git a/src/util/system.cpp b/src/util/system.cpp index 27ed24d012..6e82de743a 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -74,7 +74,6 @@ const int64_t nStartupTime = GetTime(); const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf"; -const char * const BITCOIN_PID_FILENAME = "bitcoind.pid"; ArgsManager gArgs; @@ -965,23 +964,6 @@ std::string ArgsManager::GetChainName() const return CBaseChainParams::MAIN; } -#ifndef WIN32 -fs::path GetPidFile() -{ - return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME))); -} - -void CreatePidFile(const fs::path &path, pid_t pid) -{ - FILE* file = fsbridge::fopen(path, "w"); - if (file) - { - fprintf(file, "%d\n", pid); - fclose(file); - } -} -#endif - bool RenameOver(fs::path src, fs::path dest) { #ifdef WIN32 diff --git a/src/util/system.h b/src/util/system.h index 8867e49478..69ae11d1ed 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -40,7 +40,6 @@ int64_t GetStartupTime(); extern const char * const BITCOIN_CONF_FILENAME; -extern const char * const BITCOIN_PID_FILENAME; /** Translate a message to the native language of the user. */ const extern std::function<std::string(const char*)> G_TRANSLATION_FUN; @@ -86,10 +85,6 @@ const fs::path &GetBlocksDir(); const fs::path &GetDataDir(bool fNetSpecific = true); void ClearDatadirCache(); fs::path GetConfigFile(const std::string& confPath); -#ifndef WIN32 -fs::path GetPidFile(); -void CreatePidFile(const fs::path &path, pid_t pid); -#endif #ifdef WIN32 fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif diff --git a/src/wallet/psbtwallet.cpp b/src/wallet/psbtwallet.cpp index 761e7b7dd7..1b17b09763 100644 --- a/src/wallet/psbtwallet.cpp +++ b/src/wallet/psbtwallet.cpp @@ -4,7 +4,7 @@ #include <wallet/psbtwallet.h> -bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, TransactionError& error, bool& complete, int sighash_type, bool sign, bool bip32derivs) +TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, bool& complete, int sighash_type, bool sign, bool bip32derivs) { LOCK(pwallet->cs_wallet); // Get all of the previous transactions @@ -19,8 +19,7 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, Transac // Verify input looks sane. This will check that we have at most one uxto, witness or non-witness. if (!input.IsSane()) { - error = TransactionError::INVALID_PSBT; - return false; + return TransactionError::INVALID_PSBT; } // If we have no utxo, grab it from the wallet. @@ -37,8 +36,7 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, Transac // Get the Sighash type if (sign && input.sighash_type > 0 && input.sighash_type != sighash_type) { - error = TransactionError::SIGHASH_MISMATCH; - return false; + return TransactionError::SIGHASH_MISMATCH; } complete &= SignPSBTInput(HidingSigningProvider(pwallet, !sign, !bip32derivs), psbtx, i, sighash_type); @@ -58,5 +56,5 @@ bool FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, Transac psbt_out.FromSignatureData(sigdata); } - return true; + return TransactionError::OK; } diff --git a/src/wallet/psbtwallet.h b/src/wallet/psbtwallet.h index b679f5c6ba..a24a0967d2 100644 --- a/src/wallet/psbtwallet.h +++ b/src/wallet/psbtwallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-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. @@ -18,16 +18,14 @@ * * @param[in] pwallet pointer to a wallet * @param[in] &psbtx reference to PartiallySignedTransaction to fill in - * @param[out] &error reference to UniValue to fill with error info on failure * @param[out] &complete indicates whether the PSBT is now complete * @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify) * @param[in] sign whether to sign or not * @param[in] bip32derivs whether to fill in bip32 derivation information if available - * return true on success, false on error (and fills in `error`) + * return error */ -bool FillPSBT(const CWallet* pwallet, +NODISCARD TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& psbtx, - TransactionError& error, bool& complete, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 37fc88dfd5..97c6c38be1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4007,8 +4007,8 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request) bool sign = request.params[1].isNull() ? true : request.params[1].get_bool(); bool bip32derivs = request.params[3].isNull() ? false : request.params[3].get_bool(); bool complete = true; - TransactionError err; - if (!FillPSBT(pwallet, psbtx, err, complete, nHashType, sign, bip32derivs)) { + const TransactionError err = FillPSBT(pwallet, psbtx, complete, nHashType, sign, bip32derivs); + if (err != TransactionError::OK) { throw JSONRPCTransactionError(err); } @@ -4125,8 +4125,8 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request) // Fill transaction with out data but don't sign bool bip32derivs = request.params[4].isNull() ? false : request.params[4].get_bool(); bool complete = true; - TransactionError err; - if (!FillPSBT(pwallet, psbtx, err, complete, 1, false, bip32derivs)) { + const TransactionError err = FillPSBT(pwallet, psbtx, complete, 1, false, bip32derivs); + if (err != TransactionError::OK) { throw JSONRPCTransactionError(err); } diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp index 2a3149de46..789e86e21b 100644 --- a/src/wallet/test/psbt_wallet_tests.cpp +++ b/src/wallet/test/psbt_wallet_tests.cpp @@ -62,9 +62,8 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test) ssData >> psbtx; // Fill transaction with our data - TransactionError err; bool complete = true; - FillPSBT(&m_wallet, psbtx, err, complete, SIGHASH_ALL, false, true); + BOOST_REQUIRE_EQUAL(TransactionError::OK, FillPSBT(&m_wallet, psbtx, complete, SIGHASH_ALL, false, true)); // Get the final tx CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d174e308f0..388422bec8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -371,6 +371,8 @@ void CWallet::UpgradeKeyMetadata() return; } + std::unique_ptr<WalletBatch> batch = MakeUnique<WalletBatch>(*database); + size_t cnt = 0; for (auto& meta_pair : mapKeyMetadata) { CKeyMetadata& meta = meta_pair.second; if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && meta.hdKeypath != "s") { // If the hdKeypath is "s", that's the seed and it doesn't have a key origin @@ -392,10 +394,15 @@ void CWallet::UpgradeKeyMetadata() // Write meta to wallet CPubKey pubkey; if (GetPubKey(meta_pair.first, pubkey)) { - WriteKeyMetadata(meta, pubkey, true); + batch->WriteKeyMetadata(meta, pubkey, true); + if (++cnt % 1000 == 0) { + // avoid creating overlarge in-memory batches in case the wallet contains large amounts of keys + batch.reset(new WalletBatch(*database)); + } } } } + batch.reset(); //write before setting the flag SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA); } |