diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main_gui.cpp | 29 | ||||
| -rw-r--r-- | src/selftest.cpp | 26 |
2 files changed, 50 insertions, 5 deletions
diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 2743429..25cde1c 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp | |||
| @@ -196,6 +196,9 @@ static void PrintUsage() | |||
| 196 | printf(" /walletsqlite=FILE (stage-load a SQLite wallet export, then exit)\n"); | 196 | printf(" /walletsqlite=FILE (stage-load a SQLite wallet export, then exit)\n"); |
| 197 | printf(" /walletbackend=sqlite (opt-in: run the node on <datadir>/wallet.sqlite\n"); | 197 | printf(" /walletbackend=sqlite (opt-in: run the node on <datadir>/wallet.sqlite\n"); |
| 198 | printf(" instead of wallet.dat; export one first)\n"); | 198 | printf(" instead of wallet.dat; export one first)\n"); |
| 199 | printf(" /createwallet (headless only: permit creating a new wallet in a\n"); | ||
| 200 | printf(" datadir that has none -- otherwise refused, since\n"); | ||
| 201 | printf(" a missing wallet is usually a mount/backup fault)\n"); | ||
| 199 | printf(" /rescan (walk the chain for coins this wallet owns\n"); | 202 | printf(" /rescan (walk the chain for coins this wallet owns\n"); |
| 200 | printf(" but never recorded, then exit)\n"); | 203 | printf(" but never recorded, then exit)\n"); |
| 201 | printf("\n"); | 204 | printf("\n"); |
| @@ -835,6 +838,32 @@ int main(int argc, char* argv[]) | |||
| 835 | else { fUseSQLite = true; fCreateSQLite = true; } | 838 | else { fUseSQLite = true; fCreateSQLite = true; } |
| 836 | } | 839 | } |
| 837 | 840 | ||
| 841 | // A headless node whose datadir holds no wallet of either kind is | ||
| 842 | // far more often an operations fault -- datadir not mounted, or | ||
| 843 | // wallet.dat caught mid-rename by a backup -- than a first run. | ||
| 844 | // Creating one here is not the harmless default it looks like: | ||
| 845 | // success also writes the backend marker, and from then on | ||
| 846 | // restoring the real wallet.dat no longer takes effect, because the | ||
| 847 | // marker keeps the node on the empty wallet it just made. Under | ||
| 848 | // 1.2.19 the same fault created a wallet.dat that a restore | ||
| 849 | // overwrote, so operators could recover by putting the file back. | ||
| 850 | // Refuse instead, and name the flag that makes it deliberate. | ||
| 851 | if (fCreateSQLite && fHeadlessStartup && | ||
| 852 | !arg(argc, argv, "/createwallet") && !arg(argc, argv, "-createwallet")) | ||
| 853 | { | ||
| 854 | AttachTerminal(); | ||
| 855 | fprintf(stderr, | ||
| 856 | "No wallet found in %s\n" | ||
| 857 | "Refusing to create one. On a headless node an absent wallet is\n" | ||
| 858 | "usually a mount or backup fault, and creating one would record a\n" | ||
| 859 | "backend marker that makes restoring the real wallet a no-op.\n" | ||
| 860 | "Pass -createwallet to start a new one deliberately, or\n" | ||
| 861 | "-walletbackend=bdb to run on a Berkeley DB wallet.dat.\n", | ||
| 862 | GetAppDir().c_str()); | ||
| 863 | fflush(stderr); | ||
| 864 | return 1; | ||
| 865 | } | ||
| 866 | |||
| 838 | if (fUseSQLite) | 867 | if (fUseSQLite) |
| 839 | { | 868 | { |
| 840 | AttachTerminal(); | 869 | AttachTerminal(); |
diff --git a/src/selftest.cpp b/src/selftest.cpp index 2ada8f3..c62d70f 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -2580,7 +2580,11 @@ static int RunWalletBackendDefaultSelfTest() | |||
| 2580 | 2580 | ||
| 2581 | try | 2581 | try |
| 2582 | { | 2582 | { |
| 2583 | // 1. Fresh datadir, no flag -> new wallet.sqlite, marker "sqlite", no wallet.dat. | 2583 | // 1. Fresh datadir, no flag -> this fork refuses, where upstream creates. |
| 2584 | // An empty datadir on a headless node is far more often a mount or | ||
| 2585 | // backup fault than a first run, and creating a wallet also pins the | ||
| 2586 | // backend marker, after which restoring the real wallet is a no-op. | ||
| 2587 | // Nothing may be left behind: no wallet of either kind, no marker. | ||
| 2584 | string d1 = tmp + "/fresh"; | 2588 | string d1 = tmp + "/fresh"; |
| 2585 | nFail += Check(MakeDirLocal(d1), "fresh scenario dir can be created") ? 0 : 1; | 2589 | nFail += Check(MakeDirLocal(d1), "fresh scenario dir can be created") ? 0 : 1; |
| 2586 | vector<string> a1; | 2590 | vector<string> a1; |
| @@ -2588,19 +2592,31 @@ static int RunWalletBackendDefaultSelfTest() | |||
| 2588 | a1.push_back("-nomanagedtor"); | 2592 | a1.push_back("-nomanagedtor"); |
| 2589 | a1.push_back("-nogui"); | 2593 | a1.push_back("-nogui"); |
| 2590 | a1.push_back("-newaddress"); | 2594 | a1.push_back("-newaddress"); |
| 2591 | int r1 = RunBitflashChild(strExe, a1); | 2595 | int r0 = RunBitflashChild(strExe, a1); |
| 2596 | nFail += Check(r0 != 0 && | ||
| 2597 | !FileExists((d1 + "/wallet.sqlite").c_str()) && | ||
| 2598 | !FileExists((d1 + "/wallet.dat").c_str()) && | ||
| 2599 | !FileExists((d1 + "/wallet-backend").c_str()), | ||
| 2600 | "a flagless headless start refuses to create a wallet") ? 0 : 1; | ||
| 2601 | |||
| 2602 | // 1a. -createwallet says it was meant: new wallet.sqlite, marker | ||
| 2603 | // "sqlite", no wallet.dat. | ||
| 2604 | vector<string> a1c = a1; | ||
| 2605 | a1c.push_back("-createwallet"); | ||
| 2606 | int r1 = RunBitflashChild(strExe, a1c); | ||
| 2592 | nFail += Check(r1 == 0 && | 2607 | nFail += Check(r1 == 0 && |
| 2593 | FileExists((d1 + "/wallet.sqlite").c_str()) && | 2608 | FileExists((d1 + "/wallet.sqlite").c_str()) && |
| 2594 | !FileExists((d1 + "/wallet.dat").c_str()) && | 2609 | !FileExists((d1 + "/wallet.dat").c_str()) && |
| 2595 | FileContainsText(d1 + "/wallet-backend", "sqlite"), | 2610 | FileContainsText(d1 + "/wallet-backend", "sqlite"), |
| 2596 | "a fresh install starts on SQLite (new default) and records the marker") ? 0 : 1; | 2611 | "-createwallet starts a fresh install on SQLite and records the marker") ? 0 : 1; |
| 2597 | 2612 | ||
| 2598 | // 1b. Second run reuses it, still SQLite, still no wallet.dat. | 2613 | // 1b. Second run reuses it without the flag -- the refusal only guards |
| 2614 | // creation, so an existing wallet still starts flagless. | ||
| 2599 | int r1b = RunBitflashChild(strExe, a1); | 2615 | int r1b = RunBitflashChild(strExe, a1); |
| 2600 | nFail += Check(r1b == 0 && | 2616 | nFail += Check(r1b == 0 && |
| 2601 | FileExists((d1 + "/wallet.sqlite").c_str()) && | 2617 | FileExists((d1 + "/wallet.sqlite").c_str()) && |
| 2602 | !FileExists((d1 + "/wallet.dat").c_str()), | 2618 | !FileExists((d1 + "/wallet.dat").c_str()), |
| 2603 | "the recorded SQLite choice survives a restart") ? 0 : 1; | 2619 | "the recorded SQLite choice survives a flagless restart") ? 0 : 1; |
| 2604 | 2620 | ||
| 2605 | // 2. Existing wallet.dat, no flag -> stays on Berkeley DB. | 2621 | // 2. Existing wallet.dat, no flag -> stays on Berkeley DB. |
| 2606 | string d2 = tmp + "/existing-bdb"; | 2622 | string d2 = tmp + "/existing-bdb"; |