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.cpp187
1 files changed, 186 insertions, 1 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp
index 81c4439..81aa480 100644
--- a/src/selftest.cpp
+++ b/src/selftest.cpp
@@ -736,6 +736,189 @@ static int RunWalletFormatSelfTest()
736 return nFail == 0 ? 0 : 1; 736 return nFail == 0 ? 0 : 1;
737} 737}
738 738
739static bool FileContainsText(const string& strPath, const string& strNeedle);
740static bool MakeDirLocal(const string& strPath);
741static int RunBitflashChild(const string& strExe,
742 const vector<string>& vArgs,
743 const string* pStdinFile,
744 const string* pOutputFile);
745
746class CWalletStorageSanityRawDB : public CWalletDB
747{
748public:
749 CWalletStorageSanityRawDB(const char* pszMode="r+")
750 : CWalletDB(pszMode) { }
751
752 bool WriteUnknownRecord()
753 {
754 return Write(string("storage-sanity-unknown"), 1);
755 }
756
757 bool WriteMalformedKeyRecord()
758 {
759 if (!pdb)
760 return false;
761 unsigned char chKey = 0xff;
762 unsigned char chValue = 0x01;
763 Dbt datKey(&chKey, 1);
764 Dbt datValue(&chValue, 1);
765 return pdb->put(GetTxn(), &datKey, &datValue, 0) == 0;
766 }
767
768 bool MakePlainHDSeedIncomplete()
769 {
770 return Erase(string("hdchaincode"));
771 }
772
773 bool AddEncryptedMarkerToPlainWallet()
774 {
775 CWalletMasterKey kMasterKey;
776 kMasterKey.vchCryptedKey.resize(48);
777 for (size_t i = 0; i < kMasterKey.vchCryptedKey.size(); i++)
778 kMasterKey.vchCryptedKey[i] = (unsigned char)(0x80 + (i & 0x3f));
779 for (size_t i = 0; i < kMasterKey.vchSalt.size(); i++)
780 kMasterKey.vchSalt[i] = (unsigned char)(0x40 + i);
781 return WriteWalletMinVersion(WALLET_FORMAT_ENCRYPTED) &&
782 WriteMasterKey(1, kMasterKey);
783 }
784};
785
786int RunSelfTestMutateWallet(const std::string& name)
787{
788 bool fOk = false;
789 try
790 {
791 CWalletStorageSanityRawDB walletdb;
792 if (name == "unknown-record")
793 fOk = walletdb.WriteUnknownRecord();
794 else if (name == "malformed-key")
795 fOk = walletdb.WriteMalformedKeyRecord();
796 else if (name == "incomplete-plain-hd")
797 fOk = walletdb.MakePlainHDSeedIncomplete();
798 else if (name == "encrypted-marker-with-plain-keys")
799 fOk = walletdb.AddEncryptedMarkerToPlainWallet();
800 else
801 {
802 fprintf(stderr, "Unknown wallet storage mutation '%s'\n", name.c_str());
803 return 1;
804 }
805 }
806 catch (const std::exception& e)
807 {
808 fprintf(stderr, "Cannot mutate wallet storage: %s\n", e.what());
809 return 1;
810 }
811 catch (...)
812 {
813 fprintf(stderr, "Cannot mutate wallet storage: unknown exception\n");
814 return 1;
815 }
816
817 DBFlush(true);
818 return fOk ? 0 : 1;
819}
820
821static int RunWalletStorageSanitySelfTest()
822{
823 fflush(stdout);
824 printf("wallet-storage-sanity self-test\n");
825
826 std::string tmp;
827 std::string cwd;
828 if (!MakeTempDir(tmp))
829 {
830 printf(" FAIL could not create a temporary data directory\n");
831 return 1;
832 }
833 if (!GetCurrentDir(cwd))
834 {
835 printf(" FAIL could not read current directory\n");
836 RemoveTree(tmp);
837 return 1;
838 }
839
840 int nFail = 0;
841 printf(" temp root: %s\n", tmp.c_str());
842
843 try
844 {
845#ifdef _WIN32
846 string strExe = cwd + "\\bitflash.exe";
847#else
848 string strExe = cwd + "/bitflash-node";
849#endif
850
851 struct StorageScenario
852 {
853 const char* pszName;
854 const char* pszExpectedFailure;
855 };
856
857 StorageScenario scenarios[] = {
858 { "unknown-record", "wallet.dat contains unknown records" },
859 { "malformed-key", "wallet.dat contains malformed records" },
860 { "incomplete-plain-hd", "plain HD seed is incomplete" },
861 { "encrypted-marker-with-plain-keys",
862 "encrypted wallet still contains plain private key records" },
863 };
864
865 for (size_t i = 0; i < sizeof(scenarios)/sizeof(scenarios[0]); i++)
866 {
867 string strScenarioDir = tmp + "/" + scenarios[i].pszName;
868 nFail += Check(MakeDirLocal(strScenarioDir),
869 "scenario datadir can be created") ? 0 : 1;
870
871 string strCreateOut = tmp + "/" + scenarios[i].pszName + "-create.txt";
872 vector<string> vCreateArgs;
873 vCreateArgs.push_back("-datadir=" + strScenarioDir);
874 vCreateArgs.push_back("-nomanagedtor");
875 vCreateArgs.push_back("-nogui");
876 vCreateArgs.push_back("-newphrase");
877 int nCreateRet = RunBitflashChild(strExe, vCreateArgs, NULL, &strCreateOut);
878 nFail += Check(nCreateRet == 0 &&
879 FileContainsText(strCreateOut, "Write these twelve words down"),
880 "scenario phrase wallet can be created") ? 0 : 1;
881
882 string strMutateOut = tmp + "/" + scenarios[i].pszName + "-mutate.txt";
883 vector<string> vMutateArgs;
884 vMutateArgs.push_back("-datadir=" + strScenarioDir);
885 vMutateArgs.push_back("-nomanagedtor");
886 vMutateArgs.push_back("-nogui");
887 vMutateArgs.push_back("-selftestmutatewallet=" + string(scenarios[i].pszName));
888 int nMutateRet = RunBitflashChild(strExe, vMutateArgs, NULL, &strMutateOut);
889 nFail += Check(nMutateRet == 0, scenarios[i].pszName) ? 0 : 1;
890
891 string strCheckOut = tmp + "/" + scenarios[i].pszName + "-check.txt";
892 vector<string> vCheckArgs;
893 vCheckArgs.push_back("-datadir=" + strScenarioDir);
894 vCheckArgs.push_back("-nomanagedtor");
895 vCheckArgs.push_back("-nogui");
896 vCheckArgs.push_back("-walletstoragecheck");
897 int nCheckRet = RunBitflashChild(strExe, vCheckArgs, NULL, &strCheckOut);
898 nFail += Check(nCheckRet == 2 &&
899 FileContainsText(strCheckOut, "storage sanity: failed") &&
900 FileContainsText(strCheckOut, scenarios[i].pszExpectedFailure),
901 scenarios[i].pszExpectedFailure) ? 0 : 1;
902 }
903 }
904 catch (const std::exception& e)
905 {
906 printf(" FAIL exception: %s\n", e.what());
907 nFail++;
908 }
909 catch (...)
910 {
911 printf(" FAIL unknown exception\n");
912 nFail++;
913 }
914
915 RemoveTree(tmp);
916 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
917 nFail, nFail == 1 ? "" : "s");
918 fflush(stdout);
919 return nFail == 0 ? 0 : 1;
920}
921
739static void ClearWalletRuntimeForTest() 922static void ClearWalletRuntimeForTest()
740{ 923{
741 CRITICAL_BLOCK(cs_mapKeys) 924 CRITICAL_BLOCK(cs_mapKeys)
@@ -1991,6 +2174,8 @@ int RunSelfTest(const std::string& name)
1991 return RunWalletHDSelfTest(); 2174 return RunWalletHDSelfTest();
1992 if (name == "wallet-format") 2175 if (name == "wallet-format")
1993 return RunWalletFormatSelfTest(); 2176 return RunWalletFormatSelfTest();
2177 if (name == "wallet-storage-sanity")
2178 return RunWalletStorageSanitySelfTest();
1994 if (name == "wallet-crypto") 2179 if (name == "wallet-crypto")
1995 return RunWalletCryptoSelfTest(); 2180 return RunWalletCryptoSelfTest();
1996 if (name == "wallet-encrypt") 2181 if (name == "wallet-encrypt")
@@ -2011,6 +2196,6 @@ int RunSelfTest(const std::string& name)
2011 return RunManagedTorSelfTest(); 2196 return RunManagedTorSelfTest();
2012 2197
2013 printf("Unknown self-test '%s'\n", name.c_str()); 2198 printf("Unknown self-test '%s'\n", name.c_str());
2014 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-crypto, wallet-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n"); 2199 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, wallet-crypto, wallet-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n");
2015 return 1; 2200 return 1;
2016} 2201}