Avoid opening copied wallet databases simultaneously #11476

pull ryanofsky wants to merge 1 commits into bitcoin:master from ryanofsky:pr/wid changing 2 files +41 −0
  1. ryanofsky commented at 7:50 pm on October 10, 2017: member

    Make sure wallet databases have unique fileids. If they don’t, throw an error. BDB caches do not work properly when more than one open database has the same fileid, because values written to one database may show up in reads to other databases.

    Bitcoin will never create different databases with the same fileid, but users can create them by manually copying database files.

    BDB caching bug was reported by @dooglus in https://github.com/bitcoin/bitcoin/issues/11429

  2. sipa commented at 8:26 pm on October 10, 2017: member
    Concept ACK
  3. jonasschnelli commented at 8:38 pm on October 10, 2017: contributor
    Nice clean PR! utACK ebc7c2ff3c31a3a5377e781d2239dae44e7b602e
  4. jonasschnelli added the label Wallet on Oct 10, 2017
  5. jonasschnelli added the label Needs backport on Oct 10, 2017
  6. meshcollider commented at 2:46 am on October 11, 2017: contributor
    Concept ACK
  7. in src/wallet/db.cpp:406 in ebc7c2ff3c outdated
    402@@ -402,11 +403,41 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb
    403                             0);
    404 
    405             if (ret != 0) {
    406+                error = strprintf("CDB: Error %d, can't open database %s", ret, strFilename);
    


    promag commented at 2:15 pm on October 11, 2017:
    Use same format as below: CDB: Can't open database %s (open error %d)".

    ryanofsky commented at 6:38 pm on October 11, 2017:
    Didn’t do this to avoid changing the existing error message.
  8. in src/wallet/db.cpp:419 in ebc7c2ff3c outdated
    414+                // fileid, but this error can be triggered if users manually
    415+                // copy database files.
    416+                u_int8_t fileid[DB_FILE_ID_LEN];
    417+                ret = pdb->get_mpf()->get_fileid(fileid);
    418+                if (ret != 0) {
    419+                    error = strprintf("CDB: Can't open database %s (get_fileid error %d)\n", strFilename, ret);
    


    promag commented at 2:15 pm on October 11, 2017:
    Remove newline?

    ryanofsky commented at 6:40 pm on October 11, 2017:
    Good catch, removed in e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f
  9. in src/wallet/db.cpp:432 in ebc7c2ff3c outdated
    423+                    u_int8_t item_fileid[DB_FILE_ID_LEN];
    424+                    if (item.second && item.second->get_mpf()->get_fileid(item_fileid) == 0 &&
    425+                        memcmp(fileid, item_fileid, sizeof(fileid)) == 0) {
    426+                        const char* item_filename = nullptr;
    427+                        item.second->get_dbname(&item_filename, nullptr);
    428+                        error = strprintf("CDB: Can't open database %s (duplicates fileid %s from %s)", strFilename,
    


    promag commented at 2:17 pm on October 11, 2017:
    This error overrides the previous.

    promag commented at 2:18 pm on October 11, 2017:
    Should += std::endl + instead?

    ryanofsky commented at 6:41 pm on October 11, 2017:
    Fixed override in e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f, but I’m not clear on what std::endl comment is referring to.

    promag commented at 10:08 am on October 12, 2017:
    Nevermind, but the suggestion was to accumulate the errors.
  10. in test/functional/multiwallet.py:34 in ebc7c2ff3c outdated
    29@@ -29,6 +30,10 @@ def run_test(self):
    30         os.mkdir(os.path.join(self.options.tmpdir, 'node0', 'regtest', 'w11'))
    31         self.assert_start_raises_init_error(0, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.')
    32 
    33+        # should not initialize if one wallet is a copy of another
    34+        shutil.copyfile(self.options.tmpdir + "/node0/regtest/w2", self.options.tmpdir + "/node0/regtest/w22")
    


    promag commented at 2:19 pm on October 11, 2017:
    Use os.path.join?

    ryanofsky commented at 6:43 pm on October 11, 2017:
    Done in e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f
  11. in src/wallet/db.cpp:422 in ebc7c2ff3c outdated
    407+            } else {
    408+                // Make sure database has a unique fileid. If it doesn't, throw
    409+                // an error. BDB caches do not work properly when more than one
    410+                // open database has the same fileid (values written to one
    411+                // database may show up in reads to other databases).
    412+                //
    


    promag commented at 2:19 pm on October 11, 2017:
    Nit, remove empty line.

    ryanofsky commented at 6:40 pm on October 11, 2017:
    It’s intended to be a new paragraph.
  12. in src/wallet/db.cpp:426 in ebc7c2ff3c outdated
    417+                ret = pdb->get_mpf()->get_fileid(fileid);
    418+                if (ret != 0) {
    419+                    error = strprintf("CDB: Can't open database %s (get_fileid error %d)\n", strFilename, ret);
    420+                }
    421+
    422+                for (const auto& item : env->mapDb) {
    


    promag commented at 2:21 pm on October 11, 2017:
    Only for when ret == 0?

    ryanofsky commented at 6:40 pm on October 11, 2017:
    Done in e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f
  13. in src/wallet/db.cpp:436 in ebc7c2ff3c outdated
    426+                        const char* item_filename = nullptr;
    427+                        item.second->get_dbname(&item_filename, nullptr);
    428+                        error = strprintf("CDB: Can't open database %s (duplicates fileid %s from %s)", strFilename,
    429+                            HexStr(std::begin(item_fileid), std::end(item_fileid)),
    430+                            item_filename ? item_filename : "");
    431+                    }
    


    promag commented at 2:22 pm on October 11, 2017:
    Break on first duplicate?

    ryanofsky commented at 6:41 pm on October 11, 2017:
    Done in e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f
  14. in src/wallet/db.cpp:445 in ebc7c2ff3c outdated
    436                 delete pdb;
    437                 pdb = nullptr;
    438                 --env->mapFileUseCount[strFile];
    439                 strFile = "";
    440-                throw std::runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFilename));
    441+                throw std::runtime_error(error);
    


    laanwj commented at 3:51 pm on October 11, 2017:
    I guess the reason for storing the error in a string, and not just raising the exceptions at the place the error occurs, above, is to avoid duplicating this cleanup code? It seems a bit circuitous, but I understand. An alternative would be to wrap these operations in a RAII operation.

    ryanofsky commented at 6:43 pm on October 11, 2017:
    This was one reason. The other reason was wanting the fix to be self-contained and not change existing code.
  15. ryanofsky force-pushed on Oct 11, 2017
  16. ryanofsky commented at 7:03 pm on October 11, 2017: member
    Updated ebc7c2ff3c31a3a5377e781d2239dae44e7b602e -> e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f (pr/wid.1 -> pr/wid.2)
  17. in src/wallet/db.cpp:428 in e32c2a51b7 outdated
    423+                // Bitcoin will never create different databases with the same
    424+                // fileid, but this error can be triggered if users manually
    425+                // copy database files.
    426+                for (const auto& item : env->mapDb) {
    427+                    u_int8_t item_fileid[DB_FILE_ID_LEN];
    428+                    if (item.second && item.second->get_mpf()->get_fileid(item_fileid) == 0 &&
    


    promag commented at 10:10 am on October 12, 2017:
    Maybe use the ret = ... pattern like above to make easier to read?
  18. ryanofsky force-pushed on Oct 12, 2017
  19. ryanofsky commented at 3:18 pm on October 12, 2017: member

    I had to make another change to avoid travis failures. For some reason the get_fileid call was failing with error 22 in accounting tests (strangely only when accounting tests were run in conjunction with other tests, not when running standalone). I fixed it by skipping the get_fileid check on in-memory databases, which actually makes sense anyway.

    Updated e32c2a51b757ab764ec5dbe8bf04b3fc4aa3cb5f -> 4164132f6b475d3a3b4f1492f22f515cdb98fcd8 (pr/wid.2 -> pr/wid.3)

  20. laanwj added this to the milestone 0.15.0.2 on Oct 12, 2017
  21. jnewbery commented at 9:18 pm on October 12, 2017: member

    Tested ACK 4164132f6b475d3a3b4f1492f22f515cdb98fcd8

    I think you could improve the code comment by saying that bdb guarantees file identification strings for different databases to be unique, and perhaps linking to the documentation (https://docs.oracle.com/cd/E17275_01/html/programmer_reference/program_copy.html).

  22. ryanofsky force-pushed on Oct 12, 2017
  23. ryanofsky commented at 9:36 pm on October 12, 2017: member

    Thanks, updated comment 4164132f6b475d3a3b4f1492f22f515cdb98fcd8 -> f98832222c17c25814b9a18859e72f5041dfb55d (pr/wid.3 -> pr/wid.4)

    I didn’t include the oracle link originally because I wasn’t sure if the URL would be stable, but I realize the comment doesn’t really make sense without that context, so it seems worth adding.

  24. jnewbery commented at 9:57 pm on October 12, 2017: member

    I didn’t include the oracle link originally because I wasn’t sure if the URL would be stable

    Yes, I considered that as well. I think it’s ok to add the link now. If it dies or changes, then the comment can be updated or removed. For now, it’s adding useful additional context.

    I can confirm that your new commit updates the comment. It also makes the following change:

    0-    u_int8_t fileid[DB_FILE_ID_LEN] = {0};
    1+    u_int8_t fileid[DB_FILE_ID_LEN];
    

    Was that intentional?

  25. ryanofsky commented at 10:01 pm on October 12, 2017: member

    Was that intentional?

    Yeah, I added the zero initialization when the get_fileid call was failing and I was considering making it optional, but it’s not needed now.

  26. jnewbery commented at 7:09 pm on October 13, 2017: member
    Tested ACK f98832222c17c25814b9a18859e72f5041dfb55d
  27. Avoid opening copied wallet databases simultaneously
    Make sure wallet databases have unique fileids. If they don't, throw an error.
    BDB caches do not work properly when more than one open database has the same
    fileid, because values written to one database may show up in reads to other
    databases.
    
    Bitcoin will never create different databases with the same fileid, but users
    can create them by manually copying database files.
    
    BDB caching bug was reported by Chris Moore <dooglus@gmail.com>
    https://github.com/bitcoin/bitcoin/issues/11429
    
    Fixes #11429
    478a89c1ef
  28. laanwj commented at 1:07 pm on October 19, 2017: member
    Needs rebase for #11492, otherwise seems ready to merge.
  29. ryanofsky force-pushed on Oct 19, 2017
  30. ryanofsky commented at 2:44 pm on October 19, 2017: member
    Rebased f98832222c17c25814b9a18859e72f5041dfb55d -> 478a89c1ef79a75275d1b508122c06eee9386b2d (pr/wid.4 -> pr/wid.5)
  31. laanwj commented at 4:16 pm on October 19, 2017: member
    utACK 478a89c
  32. laanwj merged this on Oct 19, 2017
  33. laanwj closed this on Oct 19, 2017

  34. laanwj referenced this in commit 99e93de6f8 on Oct 19, 2017
  35. MarcoFalke referenced this in commit dca447bb54 on Nov 1, 2017
  36. MarcoFalke removed the label Needs backport on Nov 1, 2017
  37. MarcoFalke referenced this in commit 736ea103df on Nov 1, 2017
  38. MarcoFalke referenced this in commit 9c8006dc33 on Nov 1, 2017
  39. codablock referenced this in commit 7d6c4d6f01 on Sep 26, 2019
  40. codablock referenced this in commit b155130224 on Sep 29, 2019
  41. barrystyle referenced this in commit f0babdd189 on Jan 22, 2020
  42. random-zebra referenced this in commit 2d50b6e3b9 on Jun 9, 2021
  43. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-05 19:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me