Skip to content

Unreliable file systems may lead to wallet file corruption during wallet creation #5082

@SomberNight

Description

@SomberNight

@ecdsa has been recently looking into #4891, and in more general, ways a user could end up with a corrupted wallet file, where the addresses in the file do not correspond to the xpub.

A potential explanation that might cause this is if os.path.exist "randomly" fails. This is not completely unrealistic if your wallet files are saved on a USB flash drive or a network drive (or similar). Or perhaps on shitty file systems.


os.path.exists is called multiple times during wallet creation. The idea is that a user can end up with a corrupted wallet if he ends up partially overwriting an existing file.

When creating a new wallet, the path would be set to the path of an existing wallet, as due to os.path.exists failing, the wizard would think there is no file there yet. However in the wallet storage constructor, os.path.exists would suddenly work and the existing file would get opened. The wizard would then start modifying the existing file, thinking it's a new one. The wizard would put a new seed and xpub there. Then, the task that creates the addresses for the xpub (create_addresses) would be a no-op, as it would find that there are already "enough" addresses generated in the file (corresponding to the old wallet!).

When the wizard finished, the wallet would then get opened as normally. The wallet file would contain the new seed, new xpub, but old addresses.

Note that while this still can happen on Electrum 3.3.x, it would immediately get recognised, and the user would get several warnings due to the sanity checks added in #4828.


See issues:
#4949 (TARS)
#4891
#5066
#4790
#4462
https://bitcoin.stackexchange.com/questions/78813/same-seed-from-electrum-but-generate-different-bitcoin-addresses


Patch on top of 3.1.3 to trigger the corruption.

diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
index 8ccc0c21b..5f8af70d5 100644
--- a/gui/qt/installwizard.py
+++ b/gui/qt/installwizard.py
@@ -193,7 +193,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                 self.storage = None
                 self.next_button.setEnabled(False)
             if self.storage:
-                if not self.storage.file_exists():
+                if True:  #not self.storage.file_exists():
                     msg =_("This file does not exist.") + '\n' \
                           + _("Press 'Next' to create this wallet, or choose another file.")
                     pw = False
@@ -293,7 +293,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
             self.wallet = Wallet(self.storage)
             return self.wallet
 
-        action = self.storage.get_action()
+        action = 'new'  # self.storage.get_action()
         if action and action != 'new':
             self.hide()
             msg = _("The file '{}' contains an incompletely created wallet.\n"

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions