|
26 | 26 |
|
27 | 27 | namespace stellar
|
28 | 28 | {
|
29 |
| - |
| 29 | +namespace |
| 30 | +{ |
| 31 | +void |
| 32 | +enforceBucketListPreLoadInvariants(LedgerKey const& key, uint32_t ledgerVersion) |
| 33 | +{ |
| 34 | + if (key.type() == TRUSTLINE) |
| 35 | + { |
| 36 | + validateTrustLineKey(ledgerVersion, key); |
| 37 | + } |
| 38 | + // Note: There are additional invariants that are enforced when |
| 39 | + // loading offers by account and asset. This type of query is only |
| 40 | + // performed on the SQL backend, so we do not enforce those invariants here. |
| 41 | + // See LedgerTxnOfferSQL.cpp::loadOffersByAccountAndAsset. |
| 42 | +} |
| 43 | +void |
| 44 | +enforceBucketListPostLoadInvariants( |
| 45 | + LedgerKey const& key, std::shared_ptr<LedgerEntry const> const& entry) |
| 46 | +{ |
| 47 | + if (!entry) |
| 48 | + { |
| 49 | + return; |
| 50 | + } |
| 51 | + releaseAssert(key.type() == entry->data.type()); |
| 52 | + if (key.type() == ACCOUNT) |
| 53 | + { |
| 54 | + // LedgerTxnRoot::loadAccount SQL enforces |
| 55 | + // invariants post-load. |
| 56 | + // It decodes the result of the query and ensures |
| 57 | + // the account signers are sorted in ascending order. |
| 58 | + releaseAssert( |
| 59 | + std::adjacent_find(entry->data.account().signers.begin(), |
| 60 | + entry->data.account().signers.end(), |
| 61 | + [](Signer const& lhs, Signer const& rhs) { |
| 62 | + return !(lhs.key < rhs.key); |
| 63 | + }) == entry->data.account().signers.end()); |
| 64 | + } |
| 65 | +}; |
| 66 | +} |
30 | 67 | LedgerEntryPtr
|
31 | 68 | LedgerEntryPtr::Init(std::shared_ptr<InternalLedgerEntry> const& lePtr)
|
32 | 69 | {
|
@@ -2985,10 +3022,16 @@ LedgerTxnRoot::Impl::prefetch(UnorderedSet<LedgerKey> const& keys)
|
2985 | 3022 | for (auto const& key : keys)
|
2986 | 3023 | {
|
2987 | 3024 | insertIfNotLoaded(keysToSearch, key);
|
| 3025 | + enforceBucketListPreLoadInvariants(key, mHeader->ledgerVersion); |
2988 | 3026 | }
|
2989 | 3027 |
|
2990 | 3028 | auto blLoad = mApp.getBucketManager().loadKeys(keysToSearch);
|
2991 |
| - cacheResult(populateLoadedEntries(keysToSearch, blLoad)); |
| 3029 | + auto loadedEntries = populateLoadedEntries(keysToSearch, blLoad); |
| 3030 | + for (auto const& entry : loadedEntries) |
| 3031 | + { |
| 3032 | + enforceBucketListPostLoadInvariants(entry.first, entry.second); |
| 3033 | + } |
| 3034 | + cacheResult(loadedEntries); |
2992 | 3035 | }
|
2993 | 3036 | else
|
2994 | 3037 | {
|
@@ -3620,11 +3663,14 @@ LedgerTxnRoot::Impl::getNewestVersion(InternalLedgerKey const& gkey) const
|
3620 | 3663 | }
|
3621 | 3664 |
|
3622 | 3665 | std::shared_ptr<LedgerEntry const> entry;
|
| 3666 | + |
3623 | 3667 | try
|
3624 | 3668 | {
|
3625 | 3669 | if (mApp.getConfig().isUsingBucketListDB() && key.type() != OFFER)
|
3626 | 3670 | {
|
| 3671 | + enforceBucketListPreLoadInvariants(key, mHeader->ledgerVersion); |
3627 | 3672 | entry = mApp.getBucketManager().getLedgerEntry(key);
|
| 3673 | + enforceBucketListPostLoadInvariants(key, entry); |
3628 | 3674 | }
|
3629 | 3675 | else
|
3630 | 3676 | {
|
|
0 commit comments