diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/init.cpp | 6 | ||||
-rw-r--r-- | src/wallet/scriptpubkeyman.cpp | 4 | ||||
-rw-r--r-- | src/wallet/transaction.cpp | 25 | ||||
-rw-r--r-- | src/wallet/transaction.h | 8 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 20 | ||||
-rw-r--r-- | src/wallet/wallet.h | 7 | ||||
-rw-r--r-- | src/wallet/walletutil.h | 4 |
7 files changed, 48 insertions, 26 deletions
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 0d0a8650ac..088343458c 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -95,8 +95,6 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); argsman.AddArg("-walletcrosschain", strprintf("Allow reusing wallet files across chains (default: %u)", DEFAULT_WALLETCROSSCHAIN), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST); - - argsman.AddHiddenArgs({"-zapwallettxes"}); } bool WalletInit::ParameterInteraction() const @@ -118,10 +116,6 @@ bool WalletInit::ParameterInteraction() const LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); } - if (gArgs.IsArgSet("-zapwallettxes")) { - return InitError(Untranslated("-zapwallettxes has been removed. If you are attempting to remove a stuck transaction from your wallet, please use abandontransaction instead.")); - } - return true; } diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index bc3327cdb2..d2b2801aa8 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -2601,7 +2601,7 @@ std::unique_ptr<CKeyMetadata> DescriptorScriptPubKeyMan::GetMetadata(const CTxDe uint256 DescriptorScriptPubKeyMan::GetID() const { LOCK(cs_desc_man); - return DescriptorID(*m_wallet_descriptor.descriptor); + return m_wallet_descriptor.id; } void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache) @@ -2655,7 +2655,7 @@ bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKe bool DescriptorScriptPubKeyMan::HasWalletDescriptor(const WalletDescriptor& desc) const { LOCK(cs_desc_man); - return m_wallet_descriptor.descriptor != nullptr && desc.descriptor != nullptr && m_wallet_descriptor.descriptor->ToString() == desc.descriptor->ToString(); + return !m_wallet_descriptor.id.IsNull() && !desc.id.IsNull() && m_wallet_descriptor.id == desc.id; } void DescriptorScriptPubKeyMan::WriteDescriptor() diff --git a/src/wallet/transaction.cpp b/src/wallet/transaction.cpp index 4f78fe7520..6777257e53 100644 --- a/src/wallet/transaction.cpp +++ b/src/wallet/transaction.cpp @@ -4,6 +4,10 @@ #include <wallet/transaction.h> +#include <interfaces/chain.h> + +using interfaces::FoundBlock; + namespace wallet { bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const { @@ -25,6 +29,27 @@ int64_t CWalletTx::GetTxTime() const return n ? n : nTimeReceived; } +void CWalletTx::updateState(interfaces::Chain& chain) +{ + bool active; + auto lookup_block = [&](const uint256& hash, int& height, TxState& state) { + // If tx block (or conflicting block) was reorged out of chain + // while the wallet was shutdown, change tx status to UNCONFIRMED + // and reset block height, hash, and index. ABANDONED tx don't have + // associated blocks and don't need to be updated. The case where a + // transaction was reorged out while online and then reconfirmed + // while offline is covered by the rescan logic. + if (!chain.findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) { + state = TxStateInactive{}; + } + }; + if (auto* conf = state<TxStateConfirmed>()) { + lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, m_state); + } else if (auto* conf = state<TxStateConflicted>()) { + lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, m_state); + } +} + void CWalletTx::CopyFrom(const CWalletTx& _tx) { *this = _tx; diff --git a/src/wallet/transaction.h b/src/wallet/transaction.h index db858fa5ba..0c28628915 100644 --- a/src/wallet/transaction.h +++ b/src/wallet/transaction.h @@ -22,6 +22,10 @@ #include <variant> #include <vector> +namespace interfaces { +class Chain; +} // namespace interfaces + namespace wallet { //! State of transaction confirmed in a block. struct TxStateConfirmed { @@ -326,6 +330,10 @@ public: template<typename T> const T* state() const { return std::get_if<T>(&m_state); } template<typename T> T* state() { return std::get_if<T>(&m_state); } + //! Update transaction state when attaching to a chain, filling in heights + //! of conflicted and confirmed blocks + void updateState(interfaces::Chain& chain); + bool isAbandoned() const { return state<TxStateInactive>() && state<TxStateInactive>()->abandoned; } bool isConflicted() const { return state<TxStateConflicted>(); } bool isInactive() const { return state<TxStateInactive>(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 162d7f9ec7..ecf18fbe78 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1184,23 +1184,7 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx // If wallet doesn't have a chain (e.g when using bitcoin-wallet tool), // don't bother to update txn. if (HaveChain()) { - bool active; - auto lookup_block = [&](const uint256& hash, int& height, TxState& state) { - // If tx block (or conflicting block) was reorged out of chain - // while the wallet was shutdown, change tx status to UNCONFIRMED - // and reset block height, hash, and index. ABANDONED tx don't have - // associated blocks and don't need to be updated. The case where a - // transaction was reorged out while online and then reconfirmed - // while offline is covered by the rescan logic. - if (!chain().findBlock(hash, FoundBlock().inActiveChain(active).height(height)) || !active) { - state = TxStateInactive{}; - } - }; - if (auto* conf = wtx.state<TxStateConfirmed>()) { - lookup_block(conf->confirmed_block_hash, conf->confirmed_block_height, wtx.m_state); - } else if (auto* conf = wtx.state<TxStateConflicted>()) { - lookup_block(conf->conflicting_block_hash, conf->conflicting_block_height, wtx.m_state); - } + wtx.updateState(chain()); } if (/* insertion took place */ ins.second) { wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx)); @@ -3319,8 +3303,10 @@ int CWallet::GetTxDepthInMainChain(const CWalletTx& wtx) const { AssertLockHeld(cs_wallet); if (auto* conf = wtx.state<TxStateConfirmed>()) { + assert(conf->confirmed_block_height >= 0); return GetLastBlockHeight() - conf->confirmed_block_height + 1; } else if (auto* conf = wtx.state<TxStateConflicted>()) { + assert(conf->conflicting_block_height >= 0); return -1 * (GetLastBlockHeight() - conf->conflicting_block_height + 1); } else { return 0; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 9333493a6e..0832887159 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -503,6 +503,13 @@ public: * <0 : conflicts with a transaction this deep in the blockchain * 0 : in memory pool, waiting to be included in a block * >=1 : this many blocks deep in the main chain + * + * Preconditions: it is only valid to call this function when the wallet is + * online and the block index is loaded. So this cannot be called by + * bitcoin-wallet tool code or by wallet migration code. If this is called + * without the wallet being online, it won't be able able to determine the + * the height of the last block processed, or the heights of blocks + * referenced in transaction, and might cause assert failures. */ int GetTxDepthInMainChain(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool IsTxInMainChain(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h index c5975144c1..7ad3ffe9e4 100644 --- a/src/wallet/walletutil.h +++ b/src/wallet/walletutil.h @@ -85,6 +85,7 @@ class WalletDescriptor { public: std::shared_ptr<Descriptor> descriptor; + uint256 id; // Descriptor ID (calculated once at descriptor initialization/deserialization) uint64_t creation_time = 0; int32_t range_start = 0; // First item in range; start of range, inclusive, i.e. [range_start, range_end). This never changes. int32_t range_end = 0; // Item after the last; end of range, exclusive, i.e. [range_start, range_end). This will increment with each TopUp() @@ -99,6 +100,7 @@ public: if (!descriptor) { throw std::ios_base::failure("Invalid descriptor: " + error); } + id = DescriptorID(*descriptor); } SERIALIZE_METHODS(WalletDescriptor, obj) @@ -110,7 +112,7 @@ public: } WalletDescriptor() {} - WalletDescriptor(std::shared_ptr<Descriptor> descriptor, uint64_t creation_time, int32_t range_start, int32_t range_end, int32_t next_index) : descriptor(descriptor), creation_time(creation_time), range_start(range_start), range_end(range_end), next_index(next_index) {} + WalletDescriptor(std::shared_ptr<Descriptor> descriptor, uint64_t creation_time, int32_t range_start, int32_t range_end, int32_t next_index) : descriptor(descriptor), id(DescriptorID(*descriptor)), creation_time(creation_time), range_start(range_start), range_end(range_end), next_index(next_index) { } }; } // namespace wallet |