diff options
| author | Bitflash <admin@bitflash.network> | 2026-08-14 09:39:24 -0300 |
|---|---|---|
| committer | Bitflash <admin@bitflash.network> | 2026-08-14 09:39:24 -0300 |
| commit | 636644d0102689f61ec488dde62cd53e4835b8f1 (patch) | |
| tree | 1ca90f11685b47aaa6a36e3677d0a3dfed072136 /src | |
| parent | cf597ca37aec53b0dd7016399fee73e1959dc604 (diff) | |
| parent | 95bd9cbcb1d17f4bc6223e6bfe3a92bfb8c3067d (diff) | |
Merge pull request 'wallet: add read-only record scan boundary' (#40) from wallet-store-read-abstraction into main
Diffstat (limited to 'src')
| -rw-r--r-- | src/db.cpp | 39 | ||||
| -rw-r--r-- | src/db.h | 11 | ||||
| -rw-r--r-- | src/walletcmd.cpp | 63 |
3 files changed, 75 insertions, 38 deletions
| @@ -932,6 +932,45 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet) | |||
| 932 | return true; | 932 | return true; |
| 933 | } | 933 | } |
| 934 | 934 | ||
| 935 | bool ScanWalletRecords(CWalletRecordVisitor& visitor, string& strErrorRet) | ||
| 936 | { | ||
| 937 | class CWalletScanDB : public CWalletDB | ||
| 938 | { | ||
| 939 | public: | ||
| 940 | CWalletScanDB() : CWalletDB("r") { } | ||
| 941 | using CDB::GetCursor; | ||
| 942 | using CDB::ReadAtCursor; | ||
| 943 | }; | ||
| 944 | |||
| 945 | strErrorRet.clear(); | ||
| 946 | CWalletScanDB dbWallet; | ||
| 947 | Dbc* pcursor = dbWallet.GetCursor(); | ||
| 948 | if (!pcursor) | ||
| 949 | { | ||
| 950 | strErrorRet = "could not open a wallet cursor"; | ||
| 951 | return false; | ||
| 952 | } | ||
| 953 | CAutoCursor cursorGuard(pcursor); | ||
| 954 | |||
| 955 | loop | ||
| 956 | { | ||
| 957 | CDataStream ssKey(SER_DISK); | ||
| 958 | CDataStream ssValue(SER_DISK); | ||
| 959 | int ret = dbWallet.ReadAtCursor(pcursor, ssKey, ssValue); | ||
| 960 | if (ret == DB_NOTFOUND) | ||
| 961 | break; | ||
| 962 | if (ret != 0) | ||
| 963 | { | ||
| 964 | strErrorRet = strprintf("could not read wallet record: Berkeley DB error %d", ret); | ||
| 965 | return false; | ||
| 966 | } | ||
| 967 | if (!visitor.VisitWalletRecord(ssKey, ssValue, strErrorRet)) | ||
| 968 | return false; | ||
| 969 | } | ||
| 970 | |||
| 971 | return true; | ||
| 972 | } | ||
| 973 | |||
| 935 | bool LoadWallet() | 974 | bool LoadWallet() |
| 936 | { | 975 | { |
| 937 | vector<unsigned char> vchDefaultKey; | 976 | vector<unsigned char> vchDefaultKey; |
| @@ -524,6 +524,17 @@ public: | |||
| 524 | bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet); | 524 | bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet); |
| 525 | }; | 525 | }; |
| 526 | 526 | ||
| 527 | class CWalletRecordVisitor | ||
| 528 | { | ||
| 529 | public: | ||
| 530 | virtual ~CWalletRecordVisitor() { } | ||
| 531 | virtual bool VisitWalletRecord(const CDataStream& ssKey, | ||
| 532 | const CDataStream& ssValue, | ||
| 533 | string& strErrorRet) = 0; | ||
| 534 | }; | ||
| 535 | |||
| 536 | bool ScanWalletRecords(CWalletRecordVisitor& visitor, string& strErrorRet); | ||
| 537 | |||
| 527 | bool LoadWallet(); | 538 | bool LoadWallet(); |
| 528 | 539 | ||
| 529 | // Writes a wallet.dat that opens on its own, anywhere -- see the definition in | 540 | // Writes a wallet.dat that opens on its own, anywhere -- see the definition in |
diff --git a/src/walletcmd.cpp b/src/walletcmd.cpp index ce0da02..71f1ec3 100644 --- a/src/walletcmd.cpp +++ b/src/walletcmd.cpp | |||
| @@ -553,51 +553,38 @@ static void CountWalletStorageType(const std::string& strType, | |||
| 553 | static bool ReadWalletStorageCounts(WalletStorageAuditCounts& counts, | 553 | static bool ReadWalletStorageCounts(WalletStorageAuditCounts& counts, |
| 554 | std::string& strError) | 554 | std::string& strError) |
| 555 | { | 555 | { |
| 556 | class CWalletAuditDB : public CWalletDB | 556 | class CWalletStorageCountVisitor : public CWalletRecordVisitor |
| 557 | { | 557 | { |
| 558 | public: | 558 | public: |
| 559 | CWalletAuditDB() : CWalletDB("r") { } | 559 | WalletStorageAuditCounts& counts; |
| 560 | using CDB::GetCursor; | ||
| 561 | using CDB::ReadAtCursor; | ||
| 562 | }; | ||
| 563 | |||
| 564 | CWalletAuditDB walletdb; | ||
| 565 | Dbc* pcursor = walletdb.GetCursor(); | ||
| 566 | if (!pcursor) | ||
| 567 | { | ||
| 568 | strError = "cannot open wallet.dat cursor"; | ||
| 569 | return false; | ||
| 570 | } | ||
| 571 | 560 | ||
| 572 | for (;;) | 561 | explicit CWalletStorageCountVisitor(WalletStorageAuditCounts& countsIn) |
| 573 | { | 562 | : counts(countsIn) { } |
| 574 | CDataStream ssKey(SER_DISK); | ||
| 575 | CDataStream ssValue(SER_DISK); | ||
| 576 | int ret = walletdb.ReadAtCursor(pcursor, ssKey, ssValue); | ||
| 577 | if (ret == DB_NOTFOUND) | ||
| 578 | break; | ||
| 579 | if (ret != 0) | ||
| 580 | { | ||
| 581 | pcursor->close(); | ||
| 582 | strError = strprintf("Berkeley DB cursor read failed (%d)", ret); | ||
| 583 | return false; | ||
| 584 | } | ||
| 585 | 563 | ||
| 586 | counts.nTotal++; | 564 | bool VisitWalletRecord(const CDataStream& ssKeyIn, |
| 587 | try | 565 | const CDataStream& ssValue, |
| 566 | std::string& strErrorRet) | ||
| 588 | { | 567 | { |
| 589 | std::string strType; | 568 | (void)ssValue; |
| 590 | ssKey >> strType; | 569 | (void)strErrorRet; |
| 591 | CountWalletStorageType(strType, counts); | 570 | counts.nTotal++; |
| 592 | } | 571 | try |
| 593 | catch (...) | 572 | { |
| 594 | { | 573 | CDataStream ssKey = ssKeyIn; |
| 595 | counts.nMalformed++; | 574 | std::string strType; |
| 575 | ssKey >> strType; | ||
| 576 | CountWalletStorageType(strType, counts); | ||
| 577 | } | ||
| 578 | catch (...) | ||
| 579 | { | ||
| 580 | counts.nMalformed++; | ||
| 581 | } | ||
| 582 | return true; | ||
| 596 | } | 583 | } |
| 597 | } | 584 | }; |
| 598 | 585 | ||
| 599 | pcursor->close(); | 586 | CWalletStorageCountVisitor visitor(counts); |
| 600 | return true; | 587 | return ScanWalletRecords(visitor, strError); |
| 601 | } | 588 | } |
| 602 | 589 | ||
| 603 | static std::string WalletStorageAuditJson(const WalletStorageAuditCounts& counts) | 590 | static std::string WalletStorageAuditJson(const WalletStorageAuditCounts& counts) |