| 3162 | } |
| 3163 | |
| 3164 | bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings) |
| 3165 | { |
| 3166 | LOCK(walletInstance->cs_wallet); |
| 3167 | // allow setting the chain if it hasn't been set already but prevent changing it |
| 3168 | assert(!walletInstance->m_chain || walletInstance->m_chain == &chain); |
| 3169 | walletInstance->m_chain = &chain; |
| 3170 | |
| 3171 | // Register wallet with validationinterface. It's done before rescan to avoid |
| 3172 | // missing block connections between end of rescan and validation subscribing. |
| 3173 | // Because of wallet lock being hold, block connection notifications are going to |
| 3174 | // be pending on the validation-side until lock release. It's likely to have |
| 3175 | // block processing duplicata (if rescan block range overlaps with notification one) |
| 3176 | // but we guarantee at least than wallet state is correct after notifications delivery. |
| 3177 | // This is temporary until rescan and notifications delivery are unified under same |
| 3178 | // interface. |
| 3179 | walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance); |
| 3180 | |
| 3181 | // If rescan_required = true, rescan_height remains equal to 0 |
| 3182 | int rescan_height = 0; |
| 3183 | if (!rescan_required) |
| 3184 | { |
| 3185 | WalletBatch batch(walletInstance->GetDatabase()); |
| 3186 | CBlockLocator locator; |
| 3187 | if (batch.ReadBestBlock(locator)) { |
| 3188 | if (const std::optional<int> fork_height = chain.findLocatorFork(locator)) { |
| 3189 | rescan_height = *fork_height; |
| 3190 | } |
| 3191 | } |
| 3192 | } |
| 3193 | |
| 3194 | const std::optional<int> tip_height = chain.getHeight(); |
| 3195 | if (tip_height) { |
| 3196 | walletInstance->m_last_block_processed = chain.getBlockHash(*tip_height); |
| 3197 | walletInstance->m_last_block_processed_height = *tip_height; |
| 3198 | } else { |
| 3199 | walletInstance->m_last_block_processed.SetNull(); |
| 3200 | walletInstance->m_last_block_processed_height = -1; |
| 3201 | } |
| 3202 | |
| 3203 | if (tip_height && *tip_height != rescan_height) |
| 3204 | { |
| 3205 | if (chain.havePruned()) { |
| 3206 | int block_height = *tip_height; |
| 3207 | while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) { |
| 3208 | --block_height; |
| 3209 | } |
| 3210 | |
| 3211 | if (rescan_height != block_height) { |
| 3212 | // We can't rescan beyond non-pruned blocks, stop and throw an error. |
| 3213 | // This might happen if a user uses an old wallet within a pruned node |
| 3214 | // or if they ran -disablewallet for a longer time, then decided to re-enable |
| 3215 | // Exit early and print an error. |
| 3216 | // If a block is pruned after this check, we will load the wallet, |
| 3217 | // but fail the rescan with a generic error. |
| 3218 | error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"); |
| 3219 | return false; |
| 3220 | } |
| 3221 | } |
nothing calls this directly
no test coverage detected