diff options
Diffstat (limited to 'src/walletcmd.cpp')
| -rw-r--r-- | src/walletcmd.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/walletcmd.cpp b/src/walletcmd.cpp index 6f8258d..265febe 100644 --- a/src/walletcmd.cpp +++ b/src/walletcmd.cpp | |||
| @@ -13,6 +13,10 @@ | |||
| 13 | #include "bip32.h" | 13 | #include "bip32.h" |
| 14 | #include "walletcmd.h" | 14 | #include "walletcmd.h" |
| 15 | 15 | ||
| 16 | #ifndef _WIN32 | ||
| 17 | #include <dirent.h> | ||
| 18 | #endif | ||
| 19 | |||
| 16 | #undef printf | 20 | #undef printf |
| 17 | 21 | ||
| 18 | // How far ahead to look for used addresses when restoring. | 22 | // How far ahead to look for used addresses when restoring. |
| @@ -658,6 +662,139 @@ static bool WriteAuditTextFile(const std::string& strPath, | |||
| 658 | return true; | 662 | return true; |
| 659 | } | 663 | } |
| 660 | 664 | ||
| 665 | static bool DirectoryHasFileWithPrefixLocal(const std::string& strDir, | ||
| 666 | const std::string& strPrefix) | ||
| 667 | { | ||
| 668 | #ifdef _WIN32 | ||
| 669 | std::string pattern = strDir + "/*"; | ||
| 670 | WIN32_FIND_DATAA findData; | ||
| 671 | HANDLE hFind = FindFirstFileA(pattern.c_str(), &findData); | ||
| 672 | if (hFind == INVALID_HANDLE_VALUE) | ||
| 673 | return false; | ||
| 674 | bool fFound = false; | ||
| 675 | do | ||
| 676 | { | ||
| 677 | if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) | ||
| 678 | { | ||
| 679 | std::string name = findData.cFileName; | ||
| 680 | if (name.compare(0, strPrefix.size(), strPrefix) == 0) | ||
| 681 | { | ||
| 682 | fFound = true; | ||
| 683 | break; | ||
| 684 | } | ||
| 685 | } | ||
| 686 | } | ||
| 687 | while (FindNextFileA(hFind, &findData)); | ||
| 688 | FindClose(hFind); | ||
| 689 | return fFound; | ||
| 690 | #else | ||
| 691 | DIR* dir = opendir(strDir.c_str()); | ||
| 692 | if (!dir) | ||
| 693 | return false; | ||
| 694 | bool fFound = false; | ||
| 695 | struct dirent* ent; | ||
| 696 | while ((ent = readdir(dir)) != NULL) | ||
| 697 | { | ||
| 698 | std::string name = ent->d_name; | ||
| 699 | if (name.compare(0, strPrefix.size(), strPrefix) == 0) | ||
| 700 | { | ||
| 701 | fFound = true; | ||
| 702 | break; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | closedir(dir); | ||
| 706 | return fFound; | ||
| 707 | #endif | ||
| 708 | } | ||
| 709 | |||
| 710 | static void AddWalletStorageFailure(std::vector<std::string>& vFailures, | ||
| 711 | const std::string& strFailure) | ||
| 712 | { | ||
| 713 | vFailures.push_back(strFailure); | ||
| 714 | } | ||
| 715 | |||
| 716 | static void BuildWalletStorageSanityFailures(const WalletStorageAuditCounts& counts, | ||
| 717 | std::vector<std::string>& vFailures) | ||
| 718 | { | ||
| 719 | bool fPlainHD = counts.nPlainHDMaster > 0 || counts.nPlainHDChainCode > 0; | ||
| 720 | bool fCryptedHD = counts.nCryptedHDMaster > 0 || counts.nCryptedHDChainCode > 0; | ||
| 721 | bool fEncryptedRecords = counts.nEncryptedKeys > 0 || | ||
| 722 | counts.nMasterKeys > 0 || | ||
| 723 | fCryptedHD; | ||
| 724 | |||
| 725 | if (counts.nMalformed > 0) | ||
| 726 | AddWalletStorageFailure(vFailures, "wallet.dat contains malformed records"); | ||
| 727 | if (counts.nUnknown > 0) | ||
| 728 | AddWalletStorageFailure(vFailures, "wallet.dat contains unknown records"); | ||
| 729 | if ((counts.nPlainHDMaster > 0) != (counts.nPlainHDChainCode > 0)) | ||
| 730 | AddWalletStorageFailure(vFailures, "plain HD seed is incomplete"); | ||
| 731 | if ((counts.nCryptedHDMaster > 0) != (counts.nCryptedHDChainCode > 0)) | ||
| 732 | AddWalletStorageFailure(vFailures, "encrypted HD seed is incomplete"); | ||
| 733 | if (fPlainHD && fCryptedHD) | ||
| 734 | AddWalletStorageFailure(vFailures, "wallet.dat contains both plain and encrypted HD seed records"); | ||
| 735 | if (counts.nDefaultKey > 1) | ||
| 736 | AddWalletStorageFailure(vFailures, "wallet.dat contains more than one default public key record"); | ||
| 737 | if (counts.nWalletMinVersion > 1) | ||
| 738 | AddWalletStorageFailure(vFailures, "wallet.dat contains more than one minimum-version record"); | ||
| 739 | |||
| 740 | if (fEncryptedRecords) | ||
| 741 | { | ||
| 742 | if (counts.nPlainKeys > 0) | ||
| 743 | AddWalletStorageFailure(vFailures, "encrypted wallet still contains plain private key records"); | ||
| 744 | if (fPlainHD) | ||
| 745 | AddWalletStorageFailure(vFailures, "encrypted wallet still contains plain HD seed records"); | ||
| 746 | if (counts.nMasterKeys == 0) | ||
| 747 | AddWalletStorageFailure(vFailures, "encrypted wallet has no encryption master key record"); | ||
| 748 | if (counts.nWalletMinVersion == 0) | ||
| 749 | AddWalletStorageFailure(vFailures, "encrypted wallet has no minimum-version record"); | ||
| 750 | if (DirectoryHasFileWithPrefixLocal(GetAppDir() + "/database", "log.")) | ||
| 751 | AddWalletStorageFailure(vFailures, "Berkeley DB log files are still present for an encrypted wallet"); | ||
| 752 | } | ||
| 753 | } | ||
| 754 | |||
| 755 | int CmdWalletStorageCheck() | ||
| 756 | { | ||
| 757 | AttachTerminal(); | ||
| 758 | |||
| 759 | WalletStorageAuditCounts counts; | ||
| 760 | std::string strError; | ||
| 761 | if (!ReadWalletStorageCounts(counts, strError)) | ||
| 762 | { | ||
| 763 | fprintf(stderr, "Cannot check wallet storage: %s\n", strError.c_str()); | ||
| 764 | return 1; | ||
| 765 | } | ||
| 766 | |||
| 767 | std::vector<std::string> vFailures; | ||
| 768 | BuildWalletStorageSanityFailures(counts, vFailures); | ||
| 769 | |||
| 770 | printf("Wallet storage sanity check\n"); | ||
| 771 | printf(" records total: %u\n", counts.nTotal); | ||
| 772 | printf(" encrypted records: %s\n", | ||
| 773 | (counts.nEncryptedKeys || counts.nMasterKeys || | ||
| 774 | counts.nCryptedHDMaster || counts.nCryptedHDChainCode) ? "yes" : "no"); | ||
| 775 | printf(" plain private keys: %u\n", counts.nPlainKeys); | ||
| 776 | printf(" encrypted private keys: %u\n", counts.nEncryptedKeys); | ||
| 777 | printf(" plain HD seed: %s\n", | ||
| 778 | HDSeedStorageState(counts.nPlainHDMaster, | ||
| 779 | counts.nPlainHDChainCode).c_str()); | ||
| 780 | printf(" encrypted HD seed: %s\n", | ||
| 781 | HDSeedStorageState(counts.nCryptedHDMaster, | ||
| 782 | counts.nCryptedHDChainCode).c_str()); | ||
| 783 | if (vFailures.empty()) | ||
| 784 | { | ||
| 785 | printf(" storage sanity: ok\n"); | ||
| 786 | fflush(stdout); | ||
| 787 | return 0; | ||
| 788 | } | ||
| 789 | |||
| 790 | printf(" storage sanity: failed\n"); | ||
| 791 | for (std::vector<std::string>::const_iterator it = vFailures.begin(); | ||
| 792 | it != vFailures.end(); ++it) | ||
| 793 | printf(" failure: %s\n", it->c_str()); | ||
| 794 | fflush(stdout); | ||
| 795 | return 2; | ||
| 796 | } | ||
| 797 | |||
| 661 | int CmdWalletStorageAudit(const std::string& strJsonOut) | 798 | int CmdWalletStorageAudit(const std::string& strJsonOut) |
| 662 | { | 799 | { |
| 663 | AttachTerminal(); | 800 | AttachTerminal(); |