Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions src/ledger/ImmutableLedgerView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ CheckValidLedgerViewWrapper::CheckValidLedgerViewWrapper(
{
}

CheckValidLedgerViewWrapper::CheckValidLedgerViewWrapper(
std::unique_ptr<AbstractLedgerView const> getter)
: mGetter(std::move(getter))
{
}

LedgerHeaderWrapper
CheckValidLedgerViewWrapper::getLedgerHeader() const
{
Expand Down Expand Up @@ -355,6 +361,70 @@ ImmutableLedgerView::executeWithMaybeInnerSnapshot(
"ImmutableLedgerView::executeWithMaybeInnerSnapshot is illegal: "
"ImmutableLedgerView has no nested snapshots");
}
SorobanPreApplyLedgerView::SorobanPreApplyLedgerView(
std::shared_ptr<LedgerHeader const> header, AbstractLedgerTxn& ltx,
ApplyLedgerView const& lclView)
: mHeader(std::move(header)), mLtx(ltx), mLclView(lclView)
{
}

LedgerHeaderWrapper
SorobanPreApplyLedgerView::getLedgerHeader() const
{
return LedgerHeaderWrapper(mHeader);
}

LedgerEntryWrapper
SorobanPreApplyLedgerView::getAccount(AccountID const& account) const
{
return load(accountKey(account));
}

LedgerEntryWrapper
SorobanPreApplyLedgerView::getAccount(LedgerHeaderWrapper const& header,
TransactionFrame const& tx) const
{
return getAccount(tx.getSourceID());
}

LedgerEntryWrapper
SorobanPreApplyLedgerView::getAccount(LedgerHeaderWrapper const& header,
TransactionFrame const& tx,
AccountID const& accountID) const
{
return getAccount(accountID);
}

LedgerEntryWrapper
SorobanPreApplyLedgerView::load(LedgerKey const& key) const
{
auto entryPair = mLtx.getNewestVersionBelowRoot(key);
if (entryPair.first)
{
// Modified in this ledger, so the ltx has the authoritative version.
// A null entry means it has been deleted.
if (!entryPair.second)
{
return LedgerEntryWrapper(nullptr);
}
// Alias the entry owned by the ltx instead of copying it: the aliasing
// constructor shares ownership with the InternalLedgerEntry while
// pointing at the LedgerEntry nested inside it.
return LedgerEntryWrapper(std::shared_ptr<LedgerEntry const>(
entryPair.second, &entryPair.second->ledgerEntry()));
}
// Not modified in this ledger, so the last closed ledger snapshot is
// up to date.
return LedgerEntryWrapper(mLclView.loadLiveEntry(key));
}

void
SorobanPreApplyLedgerView::executeWithMaybeInnerSnapshot(
std::function<void(CheckValidLedgerViewWrapper const& ledgerView)> f) const
{
throw std::runtime_error("SorobanPreApplyLedgerView::"
"executeWithMaybeInnerSnapshot is not supported");
}

// === Live BucketList wrapper methods ===

Expand Down
35 changes: 35 additions & 0 deletions src/ledger/ImmutableLedgerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,39 @@ class ApplyLedgerView : private ImmutableLedgerView,
using ImmutableLedgerView::scanLiveEntriesOfType;
};

// An ledger view used by the read-only phase of the Soroban pre-apply.
//
// It's a thin wrapper around the LTX representing the current ledger state,
// and the LCL view, which allows the pre-apply phase to observe the changes
// that happened in the classic phase.
//
// Lookups are first attempted in the LTX *newest version* only (which is thread
// safe as long as we don't mutate the LTX), and only then in the LCL view.
class SorobanPreApplyLedgerView : public AbstractLedgerView
{
public:
SorobanPreApplyLedgerView(std::shared_ptr<LedgerHeader const> header,
AbstractLedgerTxn& ltx,
ApplyLedgerView const& lclView);

LedgerHeaderWrapper getLedgerHeader() const override;
LedgerEntryWrapper getAccount(AccountID const& account) const override;
LedgerEntryWrapper getAccount(LedgerHeaderWrapper const& header,
TransactionFrame const& tx) const override;
LedgerEntryWrapper getAccount(LedgerHeaderWrapper const& header,
TransactionFrame const& tx,
AccountID const& accountID) const override;
LedgerEntryWrapper load(LedgerKey const& key) const override;
void executeWithMaybeInnerSnapshot(
std::function<void(CheckValidLedgerViewWrapper const&)> f)
const override;

private:
std::shared_ptr<LedgerHeader const> mHeader;
AbstractLedgerTxn& mLtx;
ApplyLedgerView mLclView;
};

// A helper class to create and query read-only snapshots
// Automatically decides whether to create a BucketList (recommended), or SQL
// snapshot (deprecated, but currently supported)
Expand All @@ -235,6 +268,8 @@ class CheckValidLedgerViewWrapper : public NonMovableOrCopyable
CheckValidLedgerViewWrapper(AbstractLedgerTxn& ltx);
CheckValidLedgerViewWrapper(Application& app);
explicit CheckValidLedgerViewWrapper(ImmutableLedgerView const& ledgerView);
explicit CheckValidLedgerViewWrapper(
std::unique_ptr<AbstractLedgerView const> getter);
#ifdef BUILD_TESTS
// Set by overlay-only mode call sites so commonValid skips the seqnum
// equality check: on-disk seqnums are frozen at genesis while
Expand Down
6 changes: 6 additions & 0 deletions src/ledger/InternalLedgerEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ InternalLedgerEntry::InternalLedgerEntry(LedgerEntry const& le)
ledgerEntry() = le;
}

InternalLedgerEntry::InternalLedgerEntry(LedgerEntry&& le)
: InternalLedgerEntry(InternalLedgerEntryType::LEDGER_ENTRY)
{
ledgerEntry() = std::move(le);
}

InternalLedgerEntry::InternalLedgerEntry(SponsorshipEntry const& se)
: InternalLedgerEntry(InternalLedgerEntryType::SPONSORSHIP)
{
Expand Down
1 change: 1 addition & 0 deletions src/ledger/InternalLedgerEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class InternalLedgerEntry
explicit InternalLedgerEntry(InternalLedgerEntryType t);

InternalLedgerEntry(LedgerEntry const& le);
InternalLedgerEntry(LedgerEntry&& le);
explicit InternalLedgerEntry(SponsorshipEntry const& se);
explicit InternalLedgerEntry(SponsorshipCounterEntry const& sce);
explicit InternalLedgerEntry(MaxSeqNumToApplyEntry const& msne);
Expand Down
78 changes: 78 additions & 0 deletions src/ledger/LedgerEntryScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ ScopedLedgerEntryOpt<S>::modifyInScope(
scope.scopeModifyOptionalEntry(*this, func);
}

template <StaticLedgerEntryScope S>
std::optional<LedgerEntry>
ScopedLedgerEntryOpt<S>::releaseFromScope(LedgerEntryScope<S> const& scope) &&
{
return scope.scopeReleaseOptionalEntry(std::move(*this));
}

template <StaticLedgerEntryScope S>
bool
ScopedLedgerEntryOpt<S>::operator==(ScopedLedgerEntryOpt<S> const& other) const
Expand Down Expand Up @@ -409,6 +416,20 @@ LedgerEntryScope<S>::scopeAdoptEntry(LedgerEntry const& entry) const
return ScopedLedgerEntry(mScopeID, entry);
}

template <StaticLedgerEntryScope S>
std::optional<LedgerEntry>
LedgerEntryScope<S>::scopeReleaseOptionalEntry(
ScopedLedgerEntryOpt<S>&& w) const
{
if (w.mScopeID != mScopeID)
{
throw std::runtime_error(fmt::format(
"scopeReleaseOptionalEntry: scope ID '{}' != entry scope ID '{}'",
mScopeID, w.mScopeID));
}
return std::move(w.mEntry);
}

template <StaticLedgerEntryScope S>
ScopedLedgerEntryOpt<S>
LedgerEntryScope<S>::scopeAdoptEntryOpt(
Expand All @@ -417,6 +438,14 @@ LedgerEntryScope<S>::scopeAdoptEntryOpt(
return ScopedLedgerEntryOpt(mScopeID, entry);
}

template <StaticLedgerEntryScope S>
ScopedLedgerEntryOpt<S>
LedgerEntryScope<S>::scopeAdoptEntryOpt(
std::optional<LedgerEntry>&& entry) const
{
return ScopedLedgerEntryOpt(mScopeID, std::move(entry));
}

template <StaticLedgerEntryScope S>
template <StaticLedgerEntryScope OtherScope>
ScopedLedgerEntry<S>
Expand Down Expand Up @@ -456,6 +485,41 @@ LedgerEntryScope<S>::scopeAdoptEntryOptFromImpl(
return ScopedLedgerEntryOpt<S>{mScopeID, entry.mEntry};
}

template <StaticLedgerEntryScope S>
template <StaticLedgerEntryScope OtherScope>
ScopedLedgerEntry<S>
LedgerEntryScope<S>::scopeAdoptEntryFromImpl(
ScopedLedgerEntry<OtherScope>&& entry,
LedgerEntryScope<OtherScope> const& scope) const
{
if (scope.mActive)
{
throw std::runtime_error(fmt::format(
"scopeAdoptEntryFrom: adopting entry with scope ID {} from "
"still-active scope ID '{}'",
entry.mScopeID, scope.mScopeID));
}
return EntryT{mScopeID, std::move(entry.mEntry)};
}

template <StaticLedgerEntryScope S>
template <StaticLedgerEntryScope OtherScope>
ScopedLedgerEntryOpt<S>
LedgerEntryScope<S>::scopeAdoptEntryOptFromImpl(
ScopedLedgerEntryOpt<OtherScope>&& entry,
LedgerEntryScope<OtherScope> const& scope) const
{
if (scope.mActive)
{
throw std::runtime_error(
fmt::format("scopeAdoptEntryOptFrom: adopting entry with "
"scope ID {} from "
"still-active scope ID '{}'",
entry.mScopeID, scope.mScopeID));
}
return ScopedLedgerEntryOpt<S>{mScopeID, std::move(entry.mEntry)};
}

/////////////////////////////////
// DeactivateScopeGuard
/////////////////////////////////
Expand Down Expand Up @@ -495,6 +559,20 @@ FOREACH_STATIC_LEDGER_ENTRY_SCOPE(INSTANTIATE_SCOPE_CLASSES)
scopeAdoptEntryOptFromImpl<StaticLedgerEntryScope::SOURCE_SCOPE>( \
ScopedLedgerEntryOpt<StaticLedgerEntryScope::SOURCE_SCOPE> const&, \
LedgerEntryScope<StaticLedgerEntryScope::SOURCE_SCOPE> const&) \
const; \
\
template ScopedLedgerEntry<StaticLedgerEntryScope::DEST_SCOPE> \
LedgerEntryScope<StaticLedgerEntryScope::DEST_SCOPE>:: \
scopeAdoptEntryFromImpl<StaticLedgerEntryScope::SOURCE_SCOPE>( \
ScopedLedgerEntry<StaticLedgerEntryScope::SOURCE_SCOPE>&&, \
LedgerEntryScope<StaticLedgerEntryScope::SOURCE_SCOPE> const&) \
const; \
\
template ScopedLedgerEntryOpt<StaticLedgerEntryScope::DEST_SCOPE> \
LedgerEntryScope<StaticLedgerEntryScope::DEST_SCOPE>:: \
scopeAdoptEntryOptFromImpl<StaticLedgerEntryScope::SOURCE_SCOPE>( \
ScopedLedgerEntryOpt<StaticLedgerEntryScope::SOURCE_SCOPE>&&, \
LedgerEntryScope<StaticLedgerEntryScope::SOURCE_SCOPE> const&) \
const;

FOR_EACH_VALID_SCOPE_ADOPTION(INSTANTIATE_ADOPT_METHODS)
Expand Down
42 changes: 42 additions & 0 deletions src/ledger/LedgerEntryScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ template <StaticLedgerEntryScope S> class ScopedLedgerEntryOpt
readInScope(LedgerEntryScope<S> const& scope) const;
void modifyInScope(LedgerEntryScope<S> const& scope,
std::function<void(std::optional<LedgerEntry>&)> func);
// Moves the payload out of the wrapper, leaving it in a moved-from state.
std::optional<LedgerEntry>
releaseFromScope(LedgerEntryScope<S> const& scope) &&;

bool operator==(ScopedLedgerEntryOpt const& other) const;
bool operator<(ScopedLedgerEntryOpt const& other) const;
Expand Down Expand Up @@ -382,11 +385,14 @@ template <StaticLedgerEntryScope S> class LedgerEntryScope
void scopeModifyOptionalEntry(
OptionalEntryT& w,
std::function<void(std::optional<LedgerEntry>&)> func) const;
std::optional<LedgerEntry>
scopeReleaseOptionalEntry(OptionalEntryT&& w) const;

EntryT scopeAdoptEntry(LedgerEntry&& entry) const;
EntryT scopeAdoptEntry(LedgerEntry const& entry) const;
OptionalEntryT
scopeAdoptEntryOpt(std::optional<LedgerEntry> const& entry) const;
OptionalEntryT scopeAdoptEntryOpt(std::optional<LedgerEntry>&& entry) const;

template <StaticLedgerEntryScope OtherScope>
EntryT
Expand Down Expand Up @@ -414,6 +420,32 @@ template <StaticLedgerEntryScope S> class LedgerEntryScope
return scopeAdoptEntryOptFromImpl(entry, scope);
}

template <StaticLedgerEntryScope OtherScope>
EntryT
scopeAdoptEntryFrom(ScopedLedgerEntry<OtherScope>&& entry,
LedgerEntryScope<OtherScope> const& scope) const
{
static_assert(
IsValidScopeAdoption<S, OtherScope>::value,
"Invalid scope adoption: this transition is not allowed. "
"Check FOR_EACH_VALID_SCOPE_ADOPTION in LedgerEntryScope.h "
"for the list of valid transitions.");
return scopeAdoptEntryFromImpl(std::move(entry), scope);
}

template <StaticLedgerEntryScope OtherScope>
OptionalEntryT
scopeAdoptEntryOptFrom(ScopedLedgerEntryOpt<OtherScope>&& entry,
LedgerEntryScope<OtherScope> const& scope) const
{
static_assert(
IsValidScopeAdoption<S, OtherScope>::value,
"Invalid scope adoption: this transition is not allowed. "
"Check FOR_EACH_VALID_SCOPE_ADOPTION in LedgerEntryScope.h "
"for the list of valid transitions.");
return scopeAdoptEntryOptFromImpl(std::move(entry), scope);
}

private:
template <StaticLedgerEntryScope OtherScope>
EntryT
Expand All @@ -424,6 +456,16 @@ template <StaticLedgerEntryScope S> class LedgerEntryScope
OptionalEntryT
scopeAdoptEntryOptFromImpl(ScopedLedgerEntryOpt<OtherScope> const& entry,
LedgerEntryScope<OtherScope> const& scope) const;

template <StaticLedgerEntryScope OtherScope>
EntryT
scopeAdoptEntryFromImpl(ScopedLedgerEntry<OtherScope>&& entry,
LedgerEntryScope<OtherScope> const& scope) const;

template <StaticLedgerEntryScope OtherScope>
OptionalEntryT
scopeAdoptEntryOptFromImpl(ScopedLedgerEntryOpt<OtherScope>&& entry,
LedgerEntryScope<OtherScope> const& scope) const;
};

template <StaticLedgerEntryScope S> class DeactivateScopeGuard
Expand Down
5 changes: 3 additions & 2 deletions src/ledger/LedgerManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2601,7 +2601,8 @@ LedgerManagerImpl::applyThread(

if (res)
{
threadState->commitChangesFromSuccessfulTx(*res, txBundle);
threadState->commitChangesFromSuccessfulTx(std::move(*res),
txBundle);
}
else
{
Expand Down Expand Up @@ -2724,7 +2725,7 @@ LedgerManagerImpl::applySorobanStage(
txBundle.getResPayload().getRefundableFeeTracker());
}

globalParState.commitChangesFromThreads(app, threadStates, stage);
globalParState.commitChangesFromThreads(app, threadStates);
}

void
Expand Down
Loading
Loading