Skip to content

Commit 06adc32

Browse files
committed
Add helpers to extract CONTRACT_CODE entries efficiently from BL.
1 parent 8539c45 commit 06adc32

12 files changed

+127
-0
lines changed

src/bucket/BucketBase.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ BucketBase::getOfferRange() const
5151
return getIndex().getOfferRange();
5252
}
5353

54+
std::optional<std::pair<std::streamoff, std::streamoff>>
55+
BucketBase::getContractCodeRange() const
56+
{
57+
return getIndex().getContractCodeRange();
58+
}
59+
5460
void
5561
BucketBase::setIndex(std::unique_ptr<BucketIndex const>&& index)
5662
{

src/bucket/BucketBase.h

+5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ class BucketBase : public NonMovableOrCopyable
9393
std::optional<std::pair<std::streamoff, std::streamoff>>
9494
getOfferRange() const;
9595

96+
// Returns [lowerBound, upperBound) of file offsets for all contract code
97+
// entries in the bucket, or std::nullopt if no contract code exists
98+
std::optional<std::pair<std::streamoff, std::streamoff>>
99+
getContractCodeRange() const;
100+
96101
// Sets index, throws if index is already set
97102
void setIndex(std::unique_ptr<BucketIndex const>&& index);
98103

src/bucket/BucketIndex.h

+5
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ class BucketIndex : public NonMovableOrCopyable
130130
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
131131
getOfferRange() const = 0;
132132

133+
// Returns lower bound and upper bound for contract code entry positions in
134+
// the given bucket, or std::nullopt if no contract code entries exist
135+
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
136+
getContractCodeRange() const = 0;
137+
133138
// Returns page size for index. InidividualIndex returns 0 for page size
134139
virtual std::streamoff getPageSize() const = 0;
135140

src/bucket/BucketIndexImpl.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,20 @@ BucketIndexImpl<IndexT>::getOfferRange() const
598598
return getOffsetBounds(lowerBound, upperBound);
599599
}
600600

601+
template <class IndexT>
602+
std::optional<std::pair<std::streamoff, std::streamoff>>
603+
BucketIndexImpl<IndexT>::getContractCodeRange() const
604+
{
605+
// Get the smallest and largest possible contract code keys
606+
LedgerKey lowerBound(CONTRACT_CODE);
607+
lowerBound.contractCode().hash.fill(std::numeric_limits<uint8_t>::min());
608+
609+
LedgerKey upperBound(CONTRACT_CODE);
610+
upperBound.contractCode().hash.fill(std::numeric_limits<uint8_t>::max());
611+
612+
return getOffsetBounds(lowerBound, upperBound);
613+
}
614+
601615
#ifdef BUILD_TESTS
602616
template <class IndexT>
603617
bool

src/bucket/BucketIndexImpl.h

+3
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ template <class IndexT> class BucketIndexImpl : public BucketIndex
100100
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
101101
getOfferRange() const override;
102102

103+
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
104+
getContractCodeRange() const override;
105+
103106
virtual std::streamoff
104107
getPageSize() const override
105108
{

src/bucket/BucketSnapshot.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,41 @@ LiveBucketSnapshot::scanForEviction(
282282
return Loop::INCOMPLETE;
283283
}
284284

285+
// Scans contract code entries in the bucket.
286+
Loop
287+
LiveBucketSnapshot::scanForContractCode(
288+
std::function<Loop(LedgerEntry const&)> callback) const
289+
{
290+
ZoneScoped;
291+
if (isEmpty())
292+
{
293+
return Loop::INCOMPLETE;
294+
}
295+
296+
auto range = mBucket->getContractCodeRange();
297+
if (!range)
298+
{
299+
return Loop::INCOMPLETE;
300+
}
301+
302+
auto& stream = getStream();
303+
stream.seek(range->first);
304+
305+
BucketEntry be;
306+
while (stream.pos() < range->second && stream.readOne(be))
307+
{
308+
if (be.type() != DEADENTRY &&
309+
be.liveEntry().data.type() == CONTRACT_CODE)
310+
{
311+
if (callback(be.liveEntry()) == Loop::COMPLETE)
312+
{
313+
return Loop::COMPLETE;
314+
}
315+
}
316+
}
317+
return Loop::INCOMPLETE;
318+
}
319+
285320
template <class BucketT>
286321
XDRInputFileStream&
287322
BucketSnapshotBase<BucketT>::getStream() const

src/bucket/BucketSnapshot.h

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class LiveBucketSnapshot : public BucketSnapshotBase<LiveBucket>
8787
std::list<EvictionResultEntry>& evictableKeys,
8888
SearchableLiveBucketListSnapshot const& bl,
8989
uint32_t ledgerVers) const;
90+
91+
// Scans contract code entries in the bucket.
92+
Loop
93+
scanForContractCode(std::function<Loop(LedgerEntry const&)> callback) const;
9094
};
9195

9296
class HotArchiveBucketSnapshot : public BucketSnapshotBase<HotArchiveBucket>

src/bucket/SearchableBucketList.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ SearchableLiveBucketListSnapshot::scanForEviction(
6262
return result;
6363
}
6464

65+
void
66+
SearchableLiveBucketListSnapshot::scanForContractCode(
67+
std::function<Loop(LedgerEntry const&)> callback) const
68+
{
69+
ZoneScoped;
70+
releaseAssert(mSnapshot);
71+
auto f = [&callback](auto const& b) {
72+
return b.scanForContractCode(callback);
73+
};
74+
loopAllBuckets(f, *mSnapshot);
75+
}
76+
6577
template <class BucketT>
6678
std::optional<std::vector<typename BucketT::LoadT>>
6779
SearchableBucketListSnapshotBase<BucketT>::loadKeysInternal(

src/bucket/SearchableBucketList.h

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class SearchableLiveBucketListSnapshot
3535
std::shared_ptr<EvictionStatistics> stats,
3636
StateArchivalSettings const& sas, uint32_t ledgerVers) const;
3737

38+
void
39+
scanForContractCode(std::function<Loop(LedgerEntry const&)> callback) const;
40+
3841
friend SearchableSnapshotConstPtr
3942
BucketSnapshotManager::copySearchableLiveBucketListSnapshot() const;
4043
};

src/main/ApplicationUtils.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -1011,4 +1011,27 @@ getStellarCoreMajorReleaseVersion(std::string const& vstr)
10111011
return std::nullopt;
10121012
}
10131013

1014+
int
1015+
listContracts(Config const& cfg)
1016+
{
1017+
VirtualClock clock(VirtualClock::REAL_TIME);
1018+
auto config = cfg;
1019+
config.setNoListen();
1020+
auto app = Application::create(clock, config, /* newDB */ false);
1021+
1022+
// Start app to ensure BucketManager is initialized
1023+
app->start();
1024+
1025+
auto snap = app->getBucketManager()
1026+
.getBucketSnapshotManager()
1027+
.copySearchableLiveBucketListSnapshot();
1028+
snap->scanForContractCode([](LedgerEntry const& entry) {
1029+
auto hash = sha256(entry.data.contractCode().code);
1030+
std::cout << binToHex(hash) << std::endl;
1031+
return Loop::INCOMPLETE; // Continue scanning
1032+
});
1033+
1034+
return 0;
1035+
}
1036+
10141037
}

src/main/ApplicationUtils.h

+2
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,6 @@ void setAuthenticatedLedgerHashPair(Application::pointer app,
6464
std::string startHash);
6565
std::optional<uint32_t>
6666
getStellarCoreMajorReleaseVersion(std::string const& vstr);
67+
68+
int listContracts(Config const& cfg);
6769
}

src/main/CommandLine.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,18 @@ runReportLastHistoryCheckpoint(CommandLineArgs const& args)
14711471
});
14721472
}
14731473

1474+
int
1475+
runListContracts(CommandLineArgs const& args)
1476+
{
1477+
CommandLine::ConfigOption configOption;
1478+
1479+
return runWithHelp(args, {configurationParser(configOption)},
1480+
[&] { return listContracts(configOption.getConfig()); });
1481+
1482+
1483+
});
1484+
}
1485+
14741486
int
14751487
run(CommandLineArgs const& args)
14761488
{
@@ -1945,6 +1957,9 @@ handleCommandLine(int argc, char* const* argv)
19451957
{"test", "execute test suite", runTest},
19461958
{"apply-load", "run apply time load test", runApplyLoad},
19471959
#endif
1960+
{"list-contracts",
1961+
"List sha256 hashes of all contract code entries in the bucket list",
1962+
runListContracts},
19481963
{"version", "print version information", runVersion}}};
19491964

19501965
auto adjustedCommandLine = commandLine.adjustCommandLine({argc, argv});

0 commit comments

Comments
 (0)