diff options
| author | Bitflash <admin@bitflash.network> | 2026-08-14 17:57:44 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-14 17:57:44 -0300 |
| commit | c56af18e421dff78446399a630b5fa949fc487b3 (patch) | |
| tree | 4a055fb61ea1c6fde9edc65c8ec7356baa8c9c07 /src/walletcmd.cpp | |
| parent | 307d1a79d4f9bdecd3f834f9ab4987f46d16d177 (diff) | |
| parent | 3e778dd6cc9045862e99503b5b9af80ec682826f (diff) | |
Merge pull request 'wallet: check SQLite exports against loader types' (#54) from wallet-sqlite-loadcheck into main
Diffstat (limited to 'src/walletcmd.cpp')
| -rw-r--r-- | src/walletcmd.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/walletcmd.cpp b/src/walletcmd.cpp index 9e4a981..4dda8dd 100644 --- a/src/walletcmd.cpp +++ b/src/walletcmd.cpp | |||
| @@ -903,6 +903,171 @@ public: | |||
| 903 | } | 903 | } |
| 904 | }; | 904 | }; |
| 905 | 905 | ||
| 906 | class CWalletSQLiteLoadCheckVisitor : public CWalletRecordVisitor | ||
| 907 | { | ||
| 908 | public: | ||
| 909 | int nRecords; | ||
| 910 | int nUnknown; | ||
| 911 | string strFailure; | ||
| 912 | |||
| 913 | CWalletSQLiteLoadCheckVisitor() : nRecords(0), nUnknown(0) { } | ||
| 914 | |||
| 915 | bool Fail(const string& strMessage, string& strErrorRet) | ||
| 916 | { | ||
| 917 | strFailure = strMessage; | ||
| 918 | strErrorRet = strMessage; | ||
| 919 | return false; | ||
| 920 | } | ||
| 921 | |||
| 922 | bool VisitWalletRecord(const CDataStream& ssKeyIn, | ||
| 923 | const CDataStream& ssValueIn, | ||
| 924 | string& strErrorRet) | ||
| 925 | { | ||
| 926 | nRecords++; | ||
| 927 | try | ||
| 928 | { | ||
| 929 | CDataStream ssKey = ssKeyIn; | ||
| 930 | CDataStream ssValue = ssValueIn; | ||
| 931 | string strType; | ||
| 932 | ssKey >> strType; | ||
| 933 | if (ssKey.fail()) | ||
| 934 | return Fail("malformed wallet record key", strErrorRet); | ||
| 935 | |||
| 936 | if (strType == "name") | ||
| 937 | { | ||
| 938 | string strAddress; | ||
| 939 | string strName; | ||
| 940 | ssKey >> strAddress; | ||
| 941 | ssValue >> strName; | ||
| 942 | } | ||
| 943 | else if (strType == "tx") | ||
| 944 | { | ||
| 945 | uint256 hash; | ||
| 946 | CWalletTx wtx; | ||
| 947 | ssKey >> hash; | ||
| 948 | ssValue >> wtx; | ||
| 949 | } | ||
| 950 | else if (strType == "key") | ||
| 951 | { | ||
| 952 | vector<unsigned char> vchPubKey; | ||
| 953 | CPrivKey vchPrivKey; | ||
| 954 | ssKey >> vchPubKey; | ||
| 955 | ssValue >> vchPrivKey; | ||
| 956 | } | ||
| 957 | else if (strType == "mkey") | ||
| 958 | { | ||
| 959 | unsigned int nID = 0; | ||
| 960 | CWalletMasterKey kMasterKey; | ||
| 961 | ssKey >> nID; | ||
| 962 | ssValue >> kMasterKey; | ||
| 963 | } | ||
| 964 | else if (strType == "ckey") | ||
| 965 | { | ||
| 966 | vector<unsigned char> vchPubKey; | ||
| 967 | vector<unsigned char> vchCryptedSecret; | ||
| 968 | ssKey >> vchPubKey; | ||
| 969 | ssValue >> vchCryptedSecret; | ||
| 970 | } | ||
| 971 | else if (strType == "defaultkey" || | ||
| 972 | strType == "hdmaster" || | ||
| 973 | strType == "hdchaincode" || | ||
| 974 | strType == "cryptedhdmaster" || | ||
| 975 | strType == "cryptedhdchaincode") | ||
| 976 | { | ||
| 977 | vector<unsigned char> vch; | ||
| 978 | ssValue >> vch; | ||
| 979 | } | ||
| 980 | else if (strType == "hdnext" || | ||
| 981 | strType == "hdreceivenext" || | ||
| 982 | strType == "hdchangenext" || | ||
| 983 | strType == "hdcointype") | ||
| 984 | { | ||
| 985 | unsigned int nValue = 0; | ||
| 986 | ssValue >> nValue; | ||
| 987 | } | ||
| 988 | else if (strType == "hdschema") | ||
| 989 | { | ||
| 990 | int nSchema = 0; | ||
| 991 | ssValue >> nSchema; | ||
| 992 | if (!ssValue.fail() && | ||
| 993 | nSchema != HD_SCHEMA_NONE && | ||
| 994 | nSchema != HD_SCHEMA_LEGACY && | ||
| 995 | nSchema != HD_SCHEMA_BIP44) | ||
| 996 | return Fail("unsupported deterministic wallet schema", | ||
| 997 | strErrorRet); | ||
| 998 | } | ||
| 999 | else if (strType == "walletminversion") | ||
| 1000 | { | ||
| 1001 | int nMinVersion = 0; | ||
| 1002 | ssValue >> nMinVersion; | ||
| 1003 | if (!ssValue.fail() && nMinVersion > WALLET_FORMAT_SUPPORTED) | ||
| 1004 | return Fail("unsupported future wallet format", strErrorRet); | ||
| 1005 | } | ||
| 1006 | else if (strType == "pool") | ||
| 1007 | { | ||
| 1008 | int64 nIndex = 0; | ||
| 1009 | vector<unsigned char> vchPubKey; | ||
| 1010 | ssKey >> nIndex; | ||
| 1011 | ssValue >> vchPubKey; | ||
| 1012 | } | ||
| 1013 | else if (strType == "setting") | ||
| 1014 | { | ||
| 1015 | string strKey; | ||
| 1016 | ssKey >> strKey; | ||
| 1017 | if (strKey == "nTransactionFee") | ||
| 1018 | { | ||
| 1019 | int64 nValue = 0; | ||
| 1020 | ssValue >> nValue; | ||
| 1021 | } | ||
| 1022 | else if (strKey == "addrIncoming") | ||
| 1023 | { | ||
| 1024 | CAddress addr; | ||
| 1025 | ssValue >> addr; | ||
| 1026 | } | ||
| 1027 | else if (strKey == "nMineMode") | ||
| 1028 | { | ||
| 1029 | int nValue = 0; | ||
| 1030 | ssValue >> nValue; | ||
| 1031 | } | ||
| 1032 | else if (strKey == "fGenerateBitcoins") | ||
| 1033 | { | ||
| 1034 | int fValue = 0; | ||
| 1035 | ssValue >> fValue; | ||
| 1036 | } | ||
| 1037 | else if (strKey == "strParticipantPool") | ||
| 1038 | { | ||
| 1039 | string strValue; | ||
| 1040 | ssValue >> strValue; | ||
| 1041 | } | ||
| 1042 | } | ||
| 1043 | else if (strType == "version") | ||
| 1044 | { | ||
| 1045 | int nVersion = 0; | ||
| 1046 | ssValue >> nVersion; | ||
| 1047 | } | ||
| 1048 | else | ||
| 1049 | { | ||
| 1050 | nUnknown++; | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | if (ssKey.fail()) | ||
| 1054 | return Fail("malformed wallet record key", strErrorRet); | ||
| 1055 | if (ssValue.fail()) | ||
| 1056 | return Fail("malformed wallet record value", strErrorRet); | ||
| 1057 | } | ||
| 1058 | catch (const std::exception& e) | ||
| 1059 | { | ||
| 1060 | return Fail(strprintf("wallet record parse exception: %s", e.what()), | ||
| 1061 | strErrorRet); | ||
| 1062 | } | ||
| 1063 | catch (...) | ||
| 1064 | { | ||
| 1065 | return Fail("wallet record parse exception", strErrorRet); | ||
| 1066 | } | ||
| 1067 | return true; | ||
| 1068 | } | ||
| 1069 | }; | ||
| 1070 | |||
| 906 | } // namespace | 1071 | } // namespace |
| 907 | 1072 | ||
| 908 | int CmdWalletSQLiteExport(const std::string& strDest) | 1073 | int CmdWalletSQLiteExport(const std::string& strDest) |
| @@ -1152,6 +1317,50 @@ int CmdWalletSQLiteRestore(const std::string& strPath) | |||
| 1152 | return 0; | 1317 | return 0; |
| 1153 | } | 1318 | } |
| 1154 | 1319 | ||
| 1320 | int CmdWalletSQLiteLoadCheck(const std::string& strPath) | ||
| 1321 | { | ||
| 1322 | AttachTerminal(); | ||
| 1323 | |||
| 1324 | if (strPath.empty()) | ||
| 1325 | { | ||
| 1326 | fprintf(stderr, "Missing SQLite wallet export path.\n"); | ||
| 1327 | return 1; | ||
| 1328 | } | ||
| 1329 | if (!FileExists(strPath.c_str())) | ||
| 1330 | { | ||
| 1331 | fprintf(stderr, "SQLite wallet export does not exist: %s\n", | ||
| 1332 | strPath.c_str()); | ||
| 1333 | return 1; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | string strError; | ||
| 1337 | CWalletDBSQLite sqlite; | ||
| 1338 | if (!sqlite.Open(strPath, strError)) | ||
| 1339 | { | ||
| 1340 | fprintf(stderr, "Cannot open SQLite wallet export: %s\n", strError.c_str()); | ||
| 1341 | return 1; | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | CWalletSQLiteLoadCheckVisitor visitor; | ||
| 1345 | if (!sqlite.ScanRecords(visitor, strError)) | ||
| 1346 | { | ||
| 1347 | printf("SQLite wallet load check\n"); | ||
| 1348 | printf(" records checked: %d\n", visitor.nRecords); | ||
| 1349 | printf(" unknown records: %d\n", visitor.nUnknown); | ||
| 1350 | printf(" load check: failed\n"); | ||
| 1351 | printf(" failure: %s\n", strError.c_str()); | ||
| 1352 | fflush(stdout); | ||
| 1353 | return 2; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | printf("SQLite wallet load check\n"); | ||
| 1357 | printf(" records checked: %d\n", visitor.nRecords); | ||
| 1358 | printf(" unknown records: %d\n", visitor.nUnknown); | ||
| 1359 | printf(" load check: ok\n"); | ||
| 1360 | fflush(stdout); | ||
| 1361 | return 0; | ||
| 1362 | } | ||
| 1363 | |||
| 1155 | int CmdEncryptWallet(const std::string& strPassphrase) | 1364 | int CmdEncryptWallet(const std::string& strPassphrase) |
| 1156 | { | 1365 | { |
| 1157 | AttachTerminal(); | 1366 | AttachTerminal(); |