upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/selftest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/selftest.cpp')
-rw-r--r--src/selftest.cpp241
1 files changed, 240 insertions, 1 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp
index 90a30d2..a9c73fe 100644
--- a/src/selftest.cpp
+++ b/src/selftest.cpp
@@ -911,6 +911,7 @@ static int RunWalletStorageSanitySelfTest()
911 vCreateArgs.push_back("-datadir=" + strScenarioDir); 911 vCreateArgs.push_back("-datadir=" + strScenarioDir);
912 vCreateArgs.push_back("-nomanagedtor"); 912 vCreateArgs.push_back("-nomanagedtor");
913 vCreateArgs.push_back("-nogui"); 913 vCreateArgs.push_back("-nogui");
914 vCreateArgs.push_back("-walletbackend=bdb"); // this suite is about wallet.dat
914 vCreateArgs.push_back("-newphrase"); 915 vCreateArgs.push_back("-newphrase");
915 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut); 916 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut);
916 nFail += Check(nCreateRet == 0 && 917 nFail += Check(nCreateRet == 0 &&
@@ -1474,6 +1475,7 @@ static int RunWalletSQLiteMigrationSelfTest()
1474 vCreateArgs.push_back("-datadir=" + strWalletDir); 1475 vCreateArgs.push_back("-datadir=" + strWalletDir);
1475 vCreateArgs.push_back("-nomanagedtor"); 1476 vCreateArgs.push_back("-nomanagedtor");
1476 vCreateArgs.push_back("-nogui"); 1477 vCreateArgs.push_back("-nogui");
1478 vCreateArgs.push_back("-walletbackend=bdb"); // migrate FROM a Berkeley DB wallet.dat
1477 vCreateArgs.push_back("-newphrase"); 1479 vCreateArgs.push_back("-newphrase");
1478 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut); 1480 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut);
1479 nFail += Check(nCreateRet == 0 && 1481 nFail += Check(nCreateRet == 0 &&
@@ -2534,6 +2536,238 @@ static int RunWalletSQLiteEncryptSelfTest()
2534 return nFail == 0 ? 0 : 1; 2536 return nFail == 0 ? 0 : 1;
2535} 2537}
2536 2538
2539// Backend resolution when no -walletbackend flag is given: a fresh install
2540// starts on SQLite (the new default), an existing wallet.dat stays on Berkeley
2541// DB, the persistent marker overrides the default, and an explicit flag
2542// overrides everything. Each scenario runs a real child process.
2543static int RunWalletBackendDefaultSelfTest()
2544{
2545 fflush(stdout);
2546 printf("wallet-backend-default self-test\n");
2547
2548 std::string tmp, cwd;
2549 if (!MakeTempDir(tmp))
2550 {
2551 printf(" FAIL could not create a temporary data directory\n");
2552 return 1;
2553 }
2554 if (!GetCurrentDir(cwd) || !SetCurrentDir(tmp))
2555 {
2556 printf(" FAIL could not move into the temporary data directory\n");
2557 RemoveTree(tmp);
2558 return 1;
2559 }
2560
2561 int nFail = 0;
2562 strSetDataDir = tmp;
2563 printf(" temp datadir: %s\n", tmp.c_str());
2564
2565#ifdef _WIN32
2566 string strExe = cwd + "\\bitflash.exe";
2567#else
2568 string strExe = cwd + "/bitflash-node";
2569#endif
2570
2571 try
2572 {
2573 // 1. Fresh datadir, no flag -> new wallet.sqlite, marker "sqlite", no wallet.dat.
2574 string d1 = tmp + "/fresh";
2575 nFail += Check(MakeDirLocal(d1), "fresh scenario dir can be created") ? 0 : 1;
2576 vector<string> a1;
2577 a1.push_back("-datadir=" + d1);
2578 a1.push_back("-nomanagedtor");
2579 a1.push_back("-nogui");
2580 a1.push_back("-newaddress");
2581 int r1 = RunBitflashChild(strExe, a1);
2582 nFail += Check(r1 == 0 &&
2583 FileExists((d1 + "/wallet.sqlite").c_str()) &&
2584 !FileExists((d1 + "/wallet.dat").c_str()) &&
2585 FileContainsText(d1 + "/wallet-backend", "sqlite"),
2586 "a fresh install starts on SQLite (new default) and records the marker") ? 0 : 1;
2587
2588 // 1b. Second run reuses it, still SQLite, still no wallet.dat.
2589 int r1b = RunBitflashChild(strExe, a1);
2590 nFail += Check(r1b == 0 &&
2591 FileExists((d1 + "/wallet.sqlite").c_str()) &&
2592 !FileExists((d1 + "/wallet.dat").c_str()),
2593 "the recorded SQLite choice survives a restart") ? 0 : 1;
2594
2595 // 2. Existing wallet.dat, no flag -> stays on Berkeley DB.
2596 string d2 = tmp + "/existing-bdb";
2597 nFail += Check(MakeDirLocal(d2), "existing-bdb scenario dir can be created") ? 0 : 1;
2598 vector<string> a2c;
2599 a2c.push_back("-datadir=" + d2);
2600 a2c.push_back("-nomanagedtor");
2601 a2c.push_back("-nogui");
2602 a2c.push_back("-walletbackend=bdb");
2603 a2c.push_back("-newphrase");
2604 RunBitflashChild(strExe, a2c);
2605 vector<string> a2;
2606 a2.push_back("-datadir=" + d2);
2607 a2.push_back("-nomanagedtor");
2608 a2.push_back("-nogui");
2609 a2.push_back("-newaddress");
2610 int r2 = RunBitflashChild(strExe, a2);
2611 nFail += Check(r2 == 0 &&
2612 FileExists((d2 + "/wallet.dat").c_str()) &&
2613 !FileExists((d2 + "/wallet.sqlite").c_str()),
2614 "an existing wallet.dat keeps a flagless start on Berkeley DB") ? 0 : 1;
2615
2616 // 3. Marker "bdb" forces Berkeley DB even on a fresh datadir.
2617 string d3 = tmp + "/marker-bdb";
2618 nFail += Check(MakeDirLocal(d3), "marker-bdb scenario dir can be created") ? 0 : 1;
2619 nFail += Check(WriteTextFile(d3 + "/wallet-backend", "bdb\n"),
2620 "a bdb marker can be written") ? 0 : 1;
2621 vector<string> a3;
2622 a3.push_back("-datadir=" + d3);
2623 a3.push_back("-nomanagedtor");
2624 a3.push_back("-nogui");
2625 a3.push_back("-newaddress");
2626 int r3 = RunBitflashChild(strExe, a3);
2627 nFail += Check(r3 == 0 &&
2628 FileExists((d3 + "/wallet.dat").c_str()) &&
2629 !FileExists((d3 + "/wallet.sqlite").c_str()),
2630 "a bdb marker forces Berkeley DB on a fresh datadir") ? 0 : 1;
2631
2632 // 4. Explicit -walletbackend=bdb on a fresh datadir -> wallet.dat.
2633 string d4 = tmp + "/explicit-bdb";
2634 nFail += Check(MakeDirLocal(d4), "explicit-bdb scenario dir can be created") ? 0 : 1;
2635 vector<string> a4;
2636 a4.push_back("-datadir=" + d4);
2637 a4.push_back("-nomanagedtor");
2638 a4.push_back("-nogui");
2639 a4.push_back("-walletbackend=bdb");
2640 a4.push_back("-newaddress");
2641 int r4 = RunBitflashChild(strExe, a4);
2642 nFail += Check(r4 == 0 &&
2643 FileExists((d4 + "/wallet.dat").c_str()) &&
2644 !FileExists((d4 + "/wallet.sqlite").c_str()),
2645 "an explicit -walletbackend=bdb creates wallet.dat on a fresh datadir") ? 0 : 1;
2646 }
2647 catch (const std::exception& e)
2648 {
2649 printf(" FAIL exception: %s\n", e.what());
2650 nFail++;
2651 }
2652 catch (...)
2653 {
2654 printf(" FAIL unknown exception\n");
2655 nFail++;
2656 }
2657
2658 DBFlush(true);
2659 SetCurrentDir(cwd);
2660 RemoveTree(tmp);
2661 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
2662 nFail, nFail == 1 ? "" : "s");
2663 fflush(stdout);
2664 return nFail == 0 ? 0 : 1;
2665}
2666
2667// The wizard's conversion action, headless: build a Berkeley DB wallet, run
2668// DoConvertWalletToSQLite() (what the GUI button calls), and prove it produced a
2669// usable wallet.sqlite + backend marker while leaving wallet.dat untouched, then
2670// that a flagless restart opens the converted SQLite wallet.
2671static int RunWalletConvertSelfTest()
2672{
2673 fflush(stdout);
2674 printf("wallet-convert self-test\n");
2675
2676 std::string tmp, cwd;
2677 if (!MakeTempDir(tmp))
2678 {
2679 printf(" FAIL could not create a temporary data directory\n");
2680 return 1;
2681 }
2682 if (!GetCurrentDir(cwd) || !SetCurrentDir(tmp))
2683 {
2684 printf(" FAIL could not move into the temporary data directory\n");
2685 RemoveTree(tmp);
2686 return 1;
2687 }
2688
2689 int nFail = 0;
2690 strSetDataDir = tmp;
2691 printf(" temp datadir: %s\n", tmp.c_str());
2692
2693#ifdef _WIN32
2694 string strExe = cwd + "\\bitflash.exe";
2695#else
2696 string strExe = cwd + "/bitflash-node";
2697#endif
2698
2699 try
2700 {
2701 if (!LoadWallet())
2702 throw std::runtime_error("LoadWallet failed");
2703
2704 string strError;
2705 nFail += Check(SetHDSeedFromMnemonic(
2706 "abandon abandon abandon abandon abandon abandon abandon "
2707 "abandon abandon abandon abandon about", strError),
2708 "a phrase can be installed before conversion") ? 0 : 1;
2709 TopUpKeyPool();
2710
2711 vector<unsigned char> vchDefaultPubKey = keyUser.GetPubKey();
2712 CPrivKey vchDefaultPrivKey;
2713 nFail += Check(GetWalletPrivKey(vchDefaultPubKey, vchDefaultPrivKey, strError),
2714 "the default private key is readable before conversion") ? 0 : 1;
2715 vector<unsigned char> vchDefaultPrivBytes(vchDefaultPrivKey.begin(),
2716 vchDefaultPrivKey.end());
2717
2718 // The conversion action the GUI button invokes.
2719 int nCopied = 0;
2720 string strConvertError;
2721 bool fConverted = DoConvertWalletToSQLite(nCopied, strConvertError);
2722 nFail += Check(fConverted && nCopied > 0,
2723 "DoConvertWalletToSQLite exports the wallet") ? 0 : 1;
2724 nFail += Check(FileExists((tmp + "/wallet.sqlite").c_str()) &&
2725 FileContainsText(tmp + "/wallet-backend", "sqlite"),
2726 "conversion writes wallet.sqlite and records the sqlite marker") ? 0 : 1;
2727 nFail += Check(FileContainsBytes(tmp + "/wallet.dat", vchDefaultPrivBytes),
2728 "wallet.dat is left untouched by the conversion") ? 0 : 1;
2729
2730 // Idempotence guard: a second conversion refuses rather than overwrite.
2731 int nCopied2 = 0;
2732 string strSecondError;
2733 nFail += Check(!DoConvertWalletToSQLite(nCopied2, strSecondError),
2734 "a second conversion refuses to overwrite wallet.sqlite") ? 0 : 1;
2735
2736 DBFlush(true);
2737
2738 // A flagless restart now opens the converted SQLite wallet (the marker
2739 // routes it) and finds the same recovery phrase.
2740 string strAudit = tmp + "/converted-recovery-audit.txt";
2741 vector<string> vAuditArgs;
2742 vAuditArgs.push_back("-datadir=" + tmp);
2743 vAuditArgs.push_back("-nomanagedtor");
2744 vAuditArgs.push_back("-nogui");
2745 vAuditArgs.push_back("-recoveryaudit");
2746 int nAuditRet = RunBitflashChild(strExe, vAuditArgs, NULL, &strAudit);
2747 nFail += Check(nAuditRet == 0 &&
2748 FileContainsText(strAudit, "recovery phrase: present"),
2749 "a flagless restart opens the converted SQLite wallet") ? 0 : 1;
2750 }
2751 catch (const std::exception& e)
2752 {
2753 printf(" FAIL exception: %s\n", e.what());
2754 nFail++;
2755 }
2756 catch (...)
2757 {
2758 printf(" FAIL unknown exception\n");
2759 nFail++;
2760 }
2761
2762 DBFlush(true);
2763 SetCurrentDir(cwd);
2764 RemoveTree(tmp);
2765 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
2766 nFail, nFail == 1 ? "" : "s");
2767 fflush(stdout);
2768 return nFail == 0 ? 0 : 1;
2769}
2770
2537static int RunWalletPortabilitySelfTest() 2771static int RunWalletPortabilitySelfTest()
2538{ 2772{
2539 fflush(stdout); 2773 fflush(stdout);
@@ -2576,6 +2810,7 @@ static int RunWalletPortabilitySelfTest()
2576 vCreateArgs.push_back("-datadir=" + strOriginal); 2810 vCreateArgs.push_back("-datadir=" + strOriginal);
2577 vCreateArgs.push_back("-nomanagedtor"); 2811 vCreateArgs.push_back("-nomanagedtor");
2578 vCreateArgs.push_back("-nogui"); 2812 vCreateArgs.push_back("-nogui");
2813 vCreateArgs.push_back("-walletbackend=bdb"); // this suite is about wallet.dat portability
2579 vCreateArgs.push_back("-newphrase"); 2814 vCreateArgs.push_back("-newphrase");
2580 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut); 2815 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut);
2581 nFail += Check(nCreateRet == 0 && 2816 nFail += Check(nCreateRet == 0 &&
@@ -3265,6 +3500,10 @@ int RunSelfTest(const std::string& name)
3265 return RunWalletEncryptSelfTest(); 3500 return RunWalletEncryptSelfTest();
3266 if (name == "wallet-sqlite-encrypt") 3501 if (name == "wallet-sqlite-encrypt")
3267 return RunWalletSQLiteEncryptSelfTest(); 3502 return RunWalletSQLiteEncryptSelfTest();
3503 if (name == "wallet-backend-default")
3504 return RunWalletBackendDefaultSelfTest();
3505 if (name == "wallet-convert")
3506 return RunWalletConvertSelfTest();
3268 if (name == "wallet-portability") 3507 if (name == "wallet-portability")
3269 return RunWalletPortabilitySelfTest(); 3508 return RunWalletPortabilitySelfTest();
3270 if (name == "net-message") 3509 if (name == "net-message")
@@ -3281,6 +3520,6 @@ int RunSelfTest(const std::string& name)
3281 return RunManagedTorSelfTest(); 3520 return RunManagedTorSelfTest();
3282 3521
3283 printf("Unknown self-test '%s'\n", name.c_str()); 3522 printf("Unknown self-test '%s'\n", name.c_str());
3284 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-sqlite-migration, wallet-crypto, wallet-encrypt, wallet-sqlite-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n"); 3523 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-sqlite-migration, wallet-crypto, wallet-encrypt, wallet-sqlite-encrypt, wallet-backend-default, wallet-convert, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n");
3285 return 1; 3524 return 1;
3286} 3525}