diff options
Diffstat (limited to 'src/selftest.cpp')
| -rw-r--r-- | src/selftest.cpp | 504 |
1 files changed, 503 insertions, 1 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp index aee2951..ff0289b 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | #ifdef _WIN32 | 34 | #ifdef _WIN32 |
| 35 | #include <direct.h> | 35 | #include <direct.h> |
| 36 | #include <fcntl.h> | ||
| 37 | #include <io.h> | ||
| 36 | #else | 38 | #else |
| 37 | #include <dirent.h> | 39 | #include <dirent.h> |
| 38 | #include <sys/stat.h> | 40 | #include <sys/stat.h> |
| @@ -601,6 +603,500 @@ static int RunWalletHDSelfTest() | |||
| 601 | return nFail == 0 ? 0 : 1; | 603 | return nFail == 0 ? 0 : 1; |
| 602 | } | 604 | } |
| 603 | 605 | ||
| 606 | static int RunWalletFormatSelfTest() | ||
| 607 | { | ||
| 608 | fflush(stdout); | ||
| 609 | printf("wallet-format self-test\n"); | ||
| 610 | |||
| 611 | std::string tmp; | ||
| 612 | std::string cwd; | ||
| 613 | if (!MakeTempDir(tmp)) | ||
| 614 | { | ||
| 615 | printf(" FAIL could not create a temporary data directory\n"); | ||
| 616 | return 1; | ||
| 617 | } | ||
| 618 | if (!GetCurrentDir(cwd) || !SetCurrentDir(tmp)) | ||
| 619 | { | ||
| 620 | printf(" FAIL could not move into the temporary data directory\n"); | ||
| 621 | RemoveTree(tmp); | ||
| 622 | return 1; | ||
| 623 | } | ||
| 624 | |||
| 625 | int nFail = 0; | ||
| 626 | strSetDataDir = tmp; | ||
| 627 | printf(" temp datadir: %s\n", tmp.c_str()); | ||
| 628 | |||
| 629 | try | ||
| 630 | { | ||
| 631 | class CWalletDBRaw : public CWalletDB | ||
| 632 | { | ||
| 633 | public: | ||
| 634 | CWalletDBRaw(const char* pszMode="r+") : CWalletDB(pszMode) { } | ||
| 635 | bool WriteStringRecord(const string& strType, int nValue) | ||
| 636 | { | ||
| 637 | return Write(strType, nValue); | ||
| 638 | } | ||
| 639 | bool EraseStringRecord(const string& strType) | ||
| 640 | { | ||
| 641 | return Erase(strType); | ||
| 642 | } | ||
| 643 | }; | ||
| 644 | |||
| 645 | if (!LoadWallet()) | ||
| 646 | throw std::runtime_error("LoadWallet failed"); | ||
| 647 | |||
| 648 | { | ||
| 649 | CWalletDB walletdb; | ||
| 650 | nFail += Check(walletdb.WriteWalletMinVersion(WALLET_FORMAT_SUPPORTED), | ||
| 651 | "the current wallet format marker can be written") ? 0 : 1; | ||
| 652 | } | ||
| 653 | |||
| 654 | std::vector<unsigned char> vchDefaultKey; | ||
| 655 | nFail += Check(CWalletDB("r").LoadWallet(vchDefaultKey), | ||
| 656 | "the current wallet format marker loads") ? 0 : 1; | ||
| 657 | |||
| 658 | { | ||
| 659 | CWalletDBRaw walletdb; | ||
| 660 | nFail += Check(walletdb.WriteStringRecord("mkey", 1), | ||
| 661 | "a malformed encrypted master-key record can be written") ? 0 : 1; | ||
| 662 | } | ||
| 663 | |||
| 664 | vchDefaultKey.clear(); | ||
| 665 | nFail += Check(!CWalletDB("r").LoadWallet(vchDefaultKey), | ||
| 666 | "a malformed encrypted master-key record is refused") ? 0 : 1; | ||
| 667 | |||
| 668 | { | ||
| 669 | CWalletDBRaw walletdb; | ||
| 670 | nFail += Check(walletdb.EraseStringRecord("mkey"), | ||
| 671 | "the malformed encrypted master-key record can be removed") ? 0 : 1; | ||
| 672 | } | ||
| 673 | |||
| 674 | { | ||
| 675 | CWalletDB walletdb; | ||
| 676 | nFail += Check(walletdb.WriteWalletMinVersion(WALLET_FORMAT_SUPPORTED + 1), | ||
| 677 | "a future wallet format marker can be written") ? 0 : 1; | ||
| 678 | } | ||
| 679 | |||
| 680 | vchDefaultKey.clear(); | ||
| 681 | nFail += Check(!CWalletDB("r").LoadWallet(vchDefaultKey), | ||
| 682 | "a future wallet format marker is refused") ? 0 : 1; | ||
| 683 | } | ||
| 684 | catch (const std::exception& e) | ||
| 685 | { | ||
| 686 | printf(" FAIL exception: %s\n", e.what()); | ||
| 687 | nFail++; | ||
| 688 | } | ||
| 689 | catch (...) | ||
| 690 | { | ||
| 691 | printf(" FAIL unknown exception\n"); | ||
| 692 | nFail++; | ||
| 693 | } | ||
| 694 | |||
| 695 | DBFlush(true); | ||
| 696 | SetCurrentDir(cwd); | ||
| 697 | RemoveTree(tmp); | ||
| 698 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | ||
| 699 | nFail, nFail == 1 ? "" : "s"); | ||
| 700 | fflush(stdout); | ||
| 701 | return nFail == 0 ? 0 : 1; | ||
| 702 | } | ||
| 703 | |||
| 704 | static void ClearWalletRuntimeForTest() | ||
| 705 | { | ||
| 706 | CRITICAL_BLOCK(cs_mapKeys) | ||
| 707 | { | ||
| 708 | mapKeys.clear(); | ||
| 709 | mapCryptedKeys.clear(); | ||
| 710 | mapPubKeys.clear(); | ||
| 711 | mapMasterKeys.clear(); | ||
| 712 | vWalletMasterKey.clear(); | ||
| 713 | vchCryptedHDMaster.clear(); | ||
| 714 | vchCryptedHDChainCode.clear(); | ||
| 715 | fWalletEncrypted = false; | ||
| 716 | fWalletLocked = true; | ||
| 717 | } | ||
| 718 | CRITICAL_BLOCK(cs_keyPool) | ||
| 719 | mapKeyPool.clear(); | ||
| 720 | vchHDMaster.clear(); | ||
| 721 | vchHDChainCode.clear(); | ||
| 722 | nHDNext = 0; | ||
| 723 | } | ||
| 724 | |||
| 725 | static int RunWalletCryptoSelfTest() | ||
| 726 | { | ||
| 727 | fflush(stdout); | ||
| 728 | printf("wallet-crypto self-test\n"); | ||
| 729 | |||
| 730 | std::string tmp; | ||
| 731 | std::string cwd; | ||
| 732 | if (!MakeTempDir(tmp)) | ||
| 733 | { | ||
| 734 | printf(" FAIL could not create a temporary data directory\n"); | ||
| 735 | return 1; | ||
| 736 | } | ||
| 737 | if (!GetCurrentDir(cwd) || !SetCurrentDir(tmp)) | ||
| 738 | { | ||
| 739 | printf(" FAIL could not move into the temporary data directory\n"); | ||
| 740 | RemoveTree(tmp); | ||
| 741 | return 1; | ||
| 742 | } | ||
| 743 | |||
| 744 | int nFail = 0; | ||
| 745 | strSetDataDir = tmp; | ||
| 746 | printf(" temp datadir: %s\n", tmp.c_str()); | ||
| 747 | |||
| 748 | try | ||
| 749 | { | ||
| 750 | const string strPassphrase = "btf-test-passphrase"; | ||
| 751 | const string strWrongPassphrase = "btf-test-passphraser"; | ||
| 752 | |||
| 753 | CKey key; | ||
| 754 | key.MakeNewKey(); | ||
| 755 | vector<unsigned char> vchPubKey = key.GetPubKey(); | ||
| 756 | CPrivKey vchPrivKey = key.GetPrivKey(); | ||
| 757 | |||
| 758 | CKeyingMaterial vchMasterKey; | ||
| 759 | for (int i = 0; i < 32; i++) | ||
| 760 | vchMasterKey.push_back((unsigned char)(i + 1)); | ||
| 761 | |||
| 762 | CWalletMasterKey kMasterKey; | ||
| 763 | kMasterKey.vchSalt.clear(); | ||
| 764 | for (int i = 0; i < 8; i++) | ||
| 765 | kMasterKey.vchSalt.push_back((unsigned char)(0xa0 + i)); | ||
| 766 | kMasterKey.nDeriveIterations = 2500; | ||
| 767 | |||
| 768 | CKeyingMaterial vchPassKey; | ||
| 769 | vector<unsigned char> vchPassIV; | ||
| 770 | nFail += Check(DeriveWalletPassphraseKey(strPassphrase, kMasterKey.vchSalt, | ||
| 771 | kMasterKey.nDeriveIterations, | ||
| 772 | vchPassKey, vchPassIV), | ||
| 773 | "a passphrase key can be derived") ? 0 : 1; | ||
| 774 | nFail += Check(EncryptSecret(vchPassKey, | ||
| 775 | vector<unsigned char>(vchMasterKey.begin(), vchMasterKey.end()), | ||
| 776 | vchPassIV, kMasterKey.vchCryptedKey), | ||
| 777 | "the wallet master key can be encrypted") ? 0 : 1; | ||
| 778 | |||
| 779 | vector<unsigned char> vchCryptedKey; | ||
| 780 | nFail += Check(EncryptSecret(vchMasterKey, | ||
| 781 | vector<unsigned char>(vchPrivKey.begin(), vchPrivKey.end()), | ||
| 782 | WalletKeyIV(vchPubKey), vchCryptedKey), | ||
| 783 | "a private key can be encrypted under the wallet master key") ? 0 : 1; | ||
| 784 | |||
| 785 | { | ||
| 786 | CWalletDB walletdb("cr"); | ||
| 787 | nFail += Check(walletdb.WriteWalletMinVersion(WALLET_FORMAT_ENCRYPTED), | ||
| 788 | "an encrypted wallet format marker can be written") ? 0 : 1; | ||
| 789 | nFail += Check(walletdb.WriteMasterKey(0, kMasterKey), | ||
| 790 | "the encrypted master key can be written") ? 0 : 1; | ||
| 791 | nFail += Check(walletdb.WriteCryptedKey(vchPubKey, vchCryptedKey), | ||
| 792 | "the encrypted private key can be written") ? 0 : 1; | ||
| 793 | nFail += Check(walletdb.WriteDefaultKey(vchPubKey), | ||
| 794 | "the encrypted wallet default key can be written") ? 0 : 1; | ||
| 795 | } | ||
| 796 | |||
| 797 | ClearWalletRuntimeForTest(); | ||
| 798 | |||
| 799 | vector<unsigned char> vchDefaultKey; | ||
| 800 | nFail += Check(CWalletDB("r").LoadWallet(vchDefaultKey), | ||
| 801 | "an encrypted wallet can be loaded") ? 0 : 1; | ||
| 802 | nFail += Check(vchDefaultKey == vchPubKey, | ||
| 803 | "the encrypted wallet default public key loads") ? 0 : 1; | ||
| 804 | nFail += Check(IsWalletEncrypted() && IsWalletLocked(), | ||
| 805 | "an encrypted wallet loads locked") ? 0 : 1; | ||
| 806 | nFail += Check(WalletCanSpendKey(vchPubKey), | ||
| 807 | "an encrypted key is recognized as wallet-owned while locked") ? 0 : 1; | ||
| 808 | |||
| 809 | CPrivKey vchDecrypted; | ||
| 810 | string strError; | ||
| 811 | nFail += Check(!GetWalletPrivKey(vchPubKey, vchDecrypted, strError), | ||
| 812 | "a locked encrypted key cannot be read") ? 0 : 1; | ||
| 813 | nFail += Check(!UnlockWallet(strWrongPassphrase, strError), | ||
| 814 | "the wrong-passphrase does not unlock") ? 0 : 1; | ||
| 815 | nFail += Check(UnlockWallet(strPassphrase, strError), | ||
| 816 | "the right passphrase unlocks") ? 0 : 1; | ||
| 817 | nFail += Check(!IsWalletLocked(), | ||
| 818 | "the wallet reports unlocked") ? 0 : 1; | ||
| 819 | nFail += Check(GetWalletPrivKey(vchPubKey, vchDecrypted, strError) && | ||
| 820 | vchDecrypted == vchPrivKey, | ||
| 821 | "an unlocked encrypted key decrypts to the original private key") ? 0 : 1; | ||
| 822 | LockWallet(); | ||
| 823 | nFail += Check(IsWalletLocked(), | ||
| 824 | "locking clears the unlocked state") ? 0 : 1; | ||
| 825 | } | ||
| 826 | catch (const std::exception& e) | ||
| 827 | { | ||
| 828 | printf(" FAIL exception: %s\n", e.what()); | ||
| 829 | nFail++; | ||
| 830 | } | ||
| 831 | catch (...) | ||
| 832 | { | ||
| 833 | printf(" FAIL unknown exception\n"); | ||
| 834 | nFail++; | ||
| 835 | } | ||
| 836 | |||
| 837 | DBFlush(true); | ||
| 838 | SetCurrentDir(cwd); | ||
| 839 | RemoveTree(tmp); | ||
| 840 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | ||
| 841 | nFail, nFail == 1 ? "" : "s"); | ||
| 842 | fflush(stdout); | ||
| 843 | return nFail == 0 ? 0 : 1; | ||
| 844 | } | ||
| 845 | |||
| 846 | static bool FileContainsBytes(const string& strPath, const vector<unsigned char>& vchNeedle) | ||
| 847 | { | ||
| 848 | if (vchNeedle.empty()) | ||
| 849 | return false; | ||
| 850 | FILE* pf = fopen(strPath.c_str(), "rb"); | ||
| 851 | if (!pf) | ||
| 852 | return false; | ||
| 853 | |||
| 854 | vector<unsigned char> vchHaystack; | ||
| 855 | unsigned char buf[4096]; | ||
| 856 | size_t n = 0; | ||
| 857 | while ((n = fread(buf, 1, sizeof(buf), pf)) > 0) | ||
| 858 | vchHaystack.insert(vchHaystack.end(), buf, buf + n); | ||
| 859 | fclose(pf); | ||
| 860 | |||
| 861 | if (vchHaystack.size() < vchNeedle.size()) | ||
| 862 | return false; | ||
| 863 | return search(vchHaystack.begin(), vchHaystack.end(), | ||
| 864 | vchNeedle.begin(), vchNeedle.end()) != vchHaystack.end(); | ||
| 865 | } | ||
| 866 | |||
| 867 | static bool FileContainsText(const string& strPath, const string& strNeedle) | ||
| 868 | { | ||
| 869 | FILE* pf = fopen(strPath.c_str(), "rb"); | ||
| 870 | if (!pf) | ||
| 871 | return false; | ||
| 872 | |||
| 873 | string strHaystack; | ||
| 874 | char buf[4096]; | ||
| 875 | size_t n = 0; | ||
| 876 | while ((n = fread(buf, 1, sizeof(buf), pf)) > 0) | ||
| 877 | strHaystack.append(buf, buf + n); | ||
| 878 | fclose(pf); | ||
| 879 | |||
| 880 | return strHaystack.find(strNeedle) != string::npos; | ||
| 881 | } | ||
| 882 | |||
| 883 | static bool WriteTextFile(const string& strPath, const string& strText) | ||
| 884 | { | ||
| 885 | FILE* pf = fopen(strPath.c_str(), "wb"); | ||
| 886 | if (!pf) | ||
| 887 | return false; | ||
| 888 | bool fOk = fwrite(strText.data(), 1, strText.size(), pf) == strText.size(); | ||
| 889 | if (fclose(pf) != 0) | ||
| 890 | fOk = false; | ||
| 891 | return fOk; | ||
| 892 | } | ||
| 893 | |||
| 894 | static string QuoteCommandArg(const string& str) | ||
| 895 | { | ||
| 896 | string out = "\""; | ||
| 897 | for (size_t i = 0; i < str.size(); i++) | ||
| 898 | { | ||
| 899 | if (str[i] == '"') | ||
| 900 | out += "\\\""; | ||
| 901 | else | ||
| 902 | out += str[i]; | ||
| 903 | } | ||
| 904 | out += "\""; | ||
| 905 | return out; | ||
| 906 | } | ||
| 907 | |||
| 908 | static int RunBitflashChild(const string& strExe, | ||
| 909 | const vector<string>& vArgs, | ||
| 910 | const string* pStdinFile = NULL) | ||
| 911 | { | ||
| 912 | #ifdef _WIN32 | ||
| 913 | vector<char*> argv; | ||
| 914 | argv.push_back((char*)strExe.c_str()); | ||
| 915 | for (size_t i = 0; i < vArgs.size(); i++) | ||
| 916 | argv.push_back((char*)vArgs[i].c_str()); | ||
| 917 | argv.push_back(NULL); | ||
| 918 | |||
| 919 | int nOldOut = _dup(1); | ||
| 920 | int nOldErr = _dup(2); | ||
| 921 | int nOldIn = _dup(0); | ||
| 922 | int nNull = _open("NUL", _O_WRONLY); | ||
| 923 | int nIn = -1; | ||
| 924 | if (nNull >= 0) | ||
| 925 | { | ||
| 926 | _dup2(nNull, 1); | ||
| 927 | _dup2(nNull, 2); | ||
| 928 | } | ||
| 929 | if (pStdinFile) | ||
| 930 | { | ||
| 931 | nIn = _open(pStdinFile->c_str(), _O_RDONLY); | ||
| 932 | if (nIn >= 0) | ||
| 933 | _dup2(nIn, 0); | ||
| 934 | } | ||
| 935 | int nRet = _spawnv(_P_WAIT, strExe.c_str(), &argv[0]); | ||
| 936 | if (nIn >= 0) | ||
| 937 | _close(nIn); | ||
| 938 | if (nNull >= 0) | ||
| 939 | _close(nNull); | ||
| 940 | if (nOldIn >= 0) | ||
| 941 | { | ||
| 942 | _dup2(nOldIn, 0); | ||
| 943 | _close(nOldIn); | ||
| 944 | } | ||
| 945 | if (nOldOut >= 0) | ||
| 946 | { | ||
| 947 | _dup2(nOldOut, 1); | ||
| 948 | _close(nOldOut); | ||
| 949 | } | ||
| 950 | if (nOldErr >= 0) | ||
| 951 | { | ||
| 952 | _dup2(nOldErr, 2); | ||
| 953 | _close(nOldErr); | ||
| 954 | } | ||
| 955 | return nRet; | ||
| 956 | #else | ||
| 957 | string strCmd = QuoteCommandArg(strExe); | ||
| 958 | for (size_t i = 0; i < vArgs.size(); i++) | ||
| 959 | strCmd += " " + QuoteCommandArg(vArgs[i]); | ||
| 960 | if (pStdinFile) | ||
| 961 | strCmd += " < " + QuoteCommandArg(*pStdinFile); | ||
| 962 | strCmd += " > /dev/null 2>&1"; | ||
| 963 | return system(strCmd.c_str()); | ||
| 964 | #endif | ||
| 965 | } | ||
| 966 | |||
| 967 | static int RunWalletEncryptSelfTest() | ||
| 968 | { | ||
| 969 | fflush(stdout); | ||
| 970 | printf("wallet-encrypt self-test\n"); | ||
| 971 | |||
| 972 | std::string tmp; | ||
| 973 | std::string cwd; | ||
| 974 | if (!MakeTempDir(tmp)) | ||
| 975 | { | ||
| 976 | printf(" FAIL could not create a temporary data directory\n"); | ||
| 977 | return 1; | ||
| 978 | } | ||
| 979 | if (!GetCurrentDir(cwd) || !SetCurrentDir(tmp)) | ||
| 980 | { | ||
| 981 | printf(" FAIL could not move into the temporary data directory\n"); | ||
| 982 | RemoveTree(tmp); | ||
| 983 | return 1; | ||
| 984 | } | ||
| 985 | |||
| 986 | int nFail = 0; | ||
| 987 | bool fWalletEnvClosed = false; | ||
| 988 | strSetDataDir = tmp; | ||
| 989 | printf(" temp datadir: %s\n", tmp.c_str()); | ||
| 990 | |||
| 991 | try | ||
| 992 | { | ||
| 993 | if (!LoadWallet()) | ||
| 994 | throw std::runtime_error("LoadWallet failed"); | ||
| 995 | |||
| 996 | string strError; | ||
| 997 | const string strMnemonic = | ||
| 998 | "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; | ||
| 999 | nFail += Check(SetHDSeedFromMnemonic(strMnemonic, strError), | ||
| 1000 | "a phrase can be installed before encryption") ? 0 : 1; | ||
| 1001 | TopUpKeyPool(); | ||
| 1002 | |||
| 1003 | vector<unsigned char> vchDefaultPubKey = keyUser.GetPubKey(); | ||
| 1004 | CPrivKey vchDefaultPrivKey; | ||
| 1005 | nFail += Check(GetWalletPrivKey(vchDefaultPubKey, vchDefaultPrivKey, strError), | ||
| 1006 | "the default private key is readable before encryption") ? 0 : 1; | ||
| 1007 | vector<unsigned char> vchDefaultPrivBytes(vchDefaultPrivKey.begin(), vchDefaultPrivKey.end()); | ||
| 1008 | vector<unsigned char> vchPlainHDMaster = vchHDMaster; | ||
| 1009 | vector<unsigned char> vchPlainHDChainCode = vchHDChainCode; | ||
| 1010 | |||
| 1011 | string strBackup; | ||
| 1012 | nFail += Check(EncryptWallet("btf-test-passphrase", strBackup, strError), | ||
| 1013 | "wallet.dat can be rewritten encrypted") ? 0 : 1; | ||
| 1014 | fWalletEnvClosed = true; | ||
| 1015 | nFail += Check(FileExists(strBackup.c_str()), | ||
| 1016 | "the original wallet is preserved as an explicit backup") ? 0 : 1; | ||
| 1017 | |||
| 1018 | string strWalletPath = GetAppDir() + "/wallet.dat"; | ||
| 1019 | nFail += Check(!FileContainsBytes(strWalletPath, vchDefaultPrivBytes), | ||
| 1020 | "the active wallet no longer contains the default private key bytes") ? 0 : 1; | ||
| 1021 | nFail += Check(!FileContainsBytes(strWalletPath, vchPlainHDMaster), | ||
| 1022 | "the active wallet no longer contains the HD master key bytes") ? 0 : 1; | ||
| 1023 | nFail += Check(!FileContainsBytes(strWalletPath, vchPlainHDChainCode), | ||
| 1024 | "the active wallet no longer contains the HD chain-code bytes") ? 0 : 1; | ||
| 1025 | |||
| 1026 | #ifdef _WIN32 | ||
| 1027 | string strExe = cwd + "\\bitflash.exe"; | ||
| 1028 | #else | ||
| 1029 | string strExe = cwd + "/bitflash-node"; | ||
| 1030 | #endif | ||
| 1031 | string strWrongDump = tmp + "/wrong-pass-dump.txt"; | ||
| 1032 | string strRightDump = tmp + "/right-pass-dump.txt"; | ||
| 1033 | string strLiteralDump = tmp + "/literal-pass-dump.txt"; | ||
| 1034 | string strStdinDump = tmp + "/stdin-pass-dump.txt"; | ||
| 1035 | string strWrongPassFile = tmp + "/wrong-pass.txt"; | ||
| 1036 | string strRightPassFile = tmp + "/right-pass.txt"; | ||
| 1037 | nFail += Check(WriteTextFile(strWrongPassFile, "wrong-passphrase\n") && | ||
| 1038 | WriteTextFile(strRightPassFile, "btf-test-passphrase\n"), | ||
| 1039 | "passphrase files can be written for restarted commands") ? 0 : 1; | ||
| 1040 | |||
| 1041 | vector<string> vWrongArgs; | ||
| 1042 | vWrongArgs.push_back("-datadir=" + tmp); | ||
| 1043 | vWrongArgs.push_back("-walletpassphrase=@" + strWrongPassFile); | ||
| 1044 | vWrongArgs.push_back("-dumpwallet=" + strWrongDump); | ||
| 1045 | vWrongArgs.push_back("-nogui"); | ||
| 1046 | int nWrongRet = RunBitflashChild(strExe, vWrongArgs); | ||
| 1047 | nFail += Check(nWrongRet != 0 && !FileExists(strWrongDump.c_str()), | ||
| 1048 | "a restarted wallet rejects the wrong-passphrase") ? 0 : 1; | ||
| 1049 | |||
| 1050 | vector<string> vLiteralArgs; | ||
| 1051 | vLiteralArgs.push_back("-datadir=" + tmp); | ||
| 1052 | vLiteralArgs.push_back("-walletpassphrase=btf-test-passphrase"); | ||
| 1053 | vLiteralArgs.push_back("-dumpwallet=" + strLiteralDump); | ||
| 1054 | vLiteralArgs.push_back("-nogui"); | ||
| 1055 | int nLiteralRet = RunBitflashChild(strExe, vLiteralArgs); | ||
| 1056 | nFail += Check(nLiteralRet != 0 && !FileExists(strLiteralDump.c_str()), | ||
| 1057 | "literal passphrases on the command line are refused") ? 0 : 1; | ||
| 1058 | |||
| 1059 | vector<string> vRightArgs; | ||
| 1060 | vRightArgs.push_back("-datadir=" + tmp); | ||
| 1061 | vRightArgs.push_back("-walletpassphrase=@" + strRightPassFile); | ||
| 1062 | vRightArgs.push_back("-dumpwallet=" + strRightDump); | ||
| 1063 | vRightArgs.push_back("-nogui"); | ||
| 1064 | int nRightRet = RunBitflashChild(strExe, vRightArgs); | ||
| 1065 | nFail += Check(nRightRet == 0 && FileExists(strRightDump.c_str()), | ||
| 1066 | "a restarted wallet unlocks with the right passphrase") ? 0 : 1; | ||
| 1067 | nFail += Check(FileContainsText(strRightDump, HexStrLocal(vchDefaultPrivBytes)), | ||
| 1068 | "the restarted wallet can decrypt and dump the original key") ? 0 : 1; | ||
| 1069 | |||
| 1070 | vector<string> vStdinArgs; | ||
| 1071 | vStdinArgs.push_back("-datadir=" + tmp); | ||
| 1072 | vStdinArgs.push_back("-walletpassphrase"); | ||
| 1073 | vStdinArgs.push_back("-dumpwallet=" + strStdinDump); | ||
| 1074 | vStdinArgs.push_back("-nogui"); | ||
| 1075 | int nStdinRet = RunBitflashChild(strExe, vStdinArgs, &strRightPassFile); | ||
| 1076 | nFail += Check(nStdinRet == 0 && FileExists(strStdinDump.c_str()), | ||
| 1077 | "a restarted wallet can read the passphrase from stdin") ? 0 : 1; | ||
| 1078 | } | ||
| 1079 | catch (const std::exception& e) | ||
| 1080 | { | ||
| 1081 | printf(" FAIL exception: %s\n", e.what()); | ||
| 1082 | nFail++; | ||
| 1083 | } | ||
| 1084 | catch (...) | ||
| 1085 | { | ||
| 1086 | printf(" FAIL unknown exception\n"); | ||
| 1087 | nFail++; | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | if (!fWalletEnvClosed) | ||
| 1091 | DBFlush(true); | ||
| 1092 | SetCurrentDir(cwd); | ||
| 1093 | RemoveTree(tmp); | ||
| 1094 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | ||
| 1095 | nFail, nFail == 1 ? "" : "s"); | ||
| 1096 | fflush(stdout); | ||
| 1097 | return nFail == 0 ? 0 : 1; | ||
| 1098 | } | ||
| 1099 | |||
| 604 | static int RunNetMessageSelfTest() | 1100 | static int RunNetMessageSelfTest() |
| 605 | { | 1101 | { |
| 606 | fflush(stdout); | 1102 | fflush(stdout); |
| @@ -728,12 +1224,18 @@ int RunSelfTest(const std::string& name) | |||
| 728 | return RunWalletKeyPoolSelfTest(); | 1224 | return RunWalletKeyPoolSelfTest(); |
| 729 | if (name == "wallet-hd") | 1225 | if (name == "wallet-hd") |
| 730 | return RunWalletHDSelfTest(); | 1226 | return RunWalletHDSelfTest(); |
| 1227 | if (name == "wallet-format") | ||
| 1228 | return RunWalletFormatSelfTest(); | ||
| 1229 | if (name == "wallet-crypto") | ||
| 1230 | return RunWalletCryptoSelfTest(); | ||
| 1231 | if (name == "wallet-encrypt") | ||
| 1232 | return RunWalletEncryptSelfTest(); | ||
| 731 | if (name == "net-message") | 1233 | if (name == "net-message") |
| 732 | return RunNetMessageSelfTest(); | 1234 | return RunNetMessageSelfTest(); |
| 733 | if (name == "consensus-limits") | 1235 | if (name == "consensus-limits") |
| 734 | return RunConsensusLimitsSelfTest(); | 1236 | return RunConsensusLimitsSelfTest(); |
| 735 | 1237 | ||
| 736 | printf("Unknown self-test '%s'\n", name.c_str()); | 1238 | printf("Unknown self-test '%s'\n", name.c_str()); |
| 737 | printf("Known self-tests: wallet-keypool, wallet-hd, net-message, consensus-limits\n"); | 1239 | printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-crypto, wallet-encrypt, net-message, consensus-limits\n"); |
| 738 | return 1; | 1240 | return 1; |
| 739 | } | 1241 | } |