Skip to content

Commit

Permalink
Add helpers to extract CONTRACT_CODE entries efficiently from BL.
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Jan 15, 2025
1 parent 8539c45 commit 06adc32
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/bucket/BucketBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ BucketBase::getOfferRange() const
return getIndex().getOfferRange();
}

std::optional<std::pair<std::streamoff, std::streamoff>>
BucketBase::getContractCodeRange() const
{
return getIndex().getContractCodeRange();
}

void
BucketBase::setIndex(std::unique_ptr<BucketIndex const>&& index)
{
Expand Down
5 changes: 5 additions & 0 deletions src/bucket/BucketBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ class BucketBase : public NonMovableOrCopyable
std::optional<std::pair<std::streamoff, std::streamoff>>
getOfferRange() const;

// Returns [lowerBound, upperBound) of file offsets for all contract code
// entries in the bucket, or std::nullopt if no contract code exists
std::optional<std::pair<std::streamoff, std::streamoff>>
getContractCodeRange() const;

// Sets index, throws if index is already set
void setIndex(std::unique_ptr<BucketIndex const>&& index);

Expand Down
5 changes: 5 additions & 0 deletions src/bucket/BucketIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ class BucketIndex : public NonMovableOrCopyable
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
getOfferRange() const = 0;

// Returns lower bound and upper bound for contract code entry positions in
// the given bucket, or std::nullopt if no contract code entries exist
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
getContractCodeRange() const = 0;

// Returns page size for index. InidividualIndex returns 0 for page size
virtual std::streamoff getPageSize() const = 0;

Expand Down
14 changes: 14 additions & 0 deletions src/bucket/BucketIndexImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,20 @@ BucketIndexImpl<IndexT>::getOfferRange() const
return getOffsetBounds(lowerBound, upperBound);
}

template <class IndexT>
std::optional<std::pair<std::streamoff, std::streamoff>>
BucketIndexImpl<IndexT>::getContractCodeRange() const
{
// Get the smallest and largest possible contract code keys
LedgerKey lowerBound(CONTRACT_CODE);
lowerBound.contractCode().hash.fill(std::numeric_limits<uint8_t>::min());

LedgerKey upperBound(CONTRACT_CODE);
upperBound.contractCode().hash.fill(std::numeric_limits<uint8_t>::max());

return getOffsetBounds(lowerBound, upperBound);
}

#ifdef BUILD_TESTS
template <class IndexT>
bool
Expand Down
3 changes: 3 additions & 0 deletions src/bucket/BucketIndexImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ template <class IndexT> class BucketIndexImpl : public BucketIndex
virtual std::optional<std::pair<std::streamoff, std::streamoff>>
getOfferRange() const override;

virtual std::optional<std::pair<std::streamoff, std::streamoff>>
getContractCodeRange() const override;

virtual std::streamoff
getPageSize() const override
{
Expand Down
35 changes: 35 additions & 0 deletions src/bucket/BucketSnapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,41 @@ LiveBucketSnapshot::scanForEviction(
return Loop::INCOMPLETE;
}

// Scans contract code entries in the bucket.
Loop
LiveBucketSnapshot::scanForContractCode(
std::function<Loop(LedgerEntry const&)> callback) const
{
ZoneScoped;
if (isEmpty())
{
return Loop::INCOMPLETE;
}

auto range = mBucket->getContractCodeRange();
if (!range)
{
return Loop::INCOMPLETE;
}

auto& stream = getStream();
stream.seek(range->first);

BucketEntry be;
while (stream.pos() < range->second && stream.readOne(be))
{
if (be.type() != DEADENTRY &&
be.liveEntry().data.type() == CONTRACT_CODE)
{
if (callback(be.liveEntry()) == Loop::COMPLETE)
{
return Loop::COMPLETE;
}
}
}
return Loop::INCOMPLETE;
}

template <class BucketT>
XDRInputFileStream&
BucketSnapshotBase<BucketT>::getStream() const
Expand Down
4 changes: 4 additions & 0 deletions src/bucket/BucketSnapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ class LiveBucketSnapshot : public BucketSnapshotBase<LiveBucket>
std::list<EvictionResultEntry>& evictableKeys,
SearchableLiveBucketListSnapshot const& bl,
uint32_t ledgerVers) const;

// Scans contract code entries in the bucket.
Loop
scanForContractCode(std::function<Loop(LedgerEntry const&)> callback) const;
};

class HotArchiveBucketSnapshot : public BucketSnapshotBase<HotArchiveBucket>
Expand Down
12 changes: 12 additions & 0 deletions src/bucket/SearchableBucketList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ SearchableLiveBucketListSnapshot::scanForEviction(
return result;
}

void
SearchableLiveBucketListSnapshot::scanForContractCode(
std::function<Loop(LedgerEntry const&)> callback) const
{
ZoneScoped;
releaseAssert(mSnapshot);
auto f = [&callback](auto const& b) {
return b.scanForContractCode(callback);
};
loopAllBuckets(f, *mSnapshot);
}

template <class BucketT>
std::optional<std::vector<typename BucketT::LoadT>>
SearchableBucketListSnapshotBase<BucketT>::loadKeysInternal(
Expand Down
3 changes: 3 additions & 0 deletions src/bucket/SearchableBucketList.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class SearchableLiveBucketListSnapshot
std::shared_ptr<EvictionStatistics> stats,
StateArchivalSettings const& sas, uint32_t ledgerVers) const;

void
scanForContractCode(std::function<Loop(LedgerEntry const&)> callback) const;

friend SearchableSnapshotConstPtr
BucketSnapshotManager::copySearchableLiveBucketListSnapshot() const;
};
Expand Down
23 changes: 23 additions & 0 deletions src/main/ApplicationUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,4 +1011,27 @@ getStellarCoreMajorReleaseVersion(std::string const& vstr)
return std::nullopt;
}

int
listContracts(Config const& cfg)
{
VirtualClock clock(VirtualClock::REAL_TIME);
auto config = cfg;
config.setNoListen();
auto app = Application::create(clock, config, /* newDB */ false);

// Start app to ensure BucketManager is initialized
app->start();

auto snap = app->getBucketManager()
.getBucketSnapshotManager()
.copySearchableLiveBucketListSnapshot();
snap->scanForContractCode([](LedgerEntry const& entry) {
auto hash = sha256(entry.data.contractCode().code);
std::cout << binToHex(hash) << std::endl;
return Loop::INCOMPLETE; // Continue scanning
});

return 0;
}

}
2 changes: 2 additions & 0 deletions src/main/ApplicationUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,6 @@ void setAuthenticatedLedgerHashPair(Application::pointer app,
std::string startHash);
std::optional<uint32_t>
getStellarCoreMajorReleaseVersion(std::string const& vstr);

int listContracts(Config const& cfg);
}
15 changes: 15 additions & 0 deletions src/main/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1471,6 +1471,18 @@ runReportLastHistoryCheckpoint(CommandLineArgs const& args)
});
}

int
runListContracts(CommandLineArgs const& args)
{
CommandLine::ConfigOption configOption;

return runWithHelp(args, {configurationParser(configOption)},
[&] { return listContracts(configOption.getConfig()); });


});
}

int
run(CommandLineArgs const& args)
{
Expand Down Expand Up @@ -1945,6 +1957,9 @@ handleCommandLine(int argc, char* const* argv)
{"test", "execute test suite", runTest},
{"apply-load", "run apply time load test", runApplyLoad},
#endif
{"list-contracts",
"List sha256 hashes of all contract code entries in the bucket list",
runListContracts},
{"version", "print version information", runVersion}}};

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

0 comments on commit 06adc32

Please sign in to comment.