From df499178a3d557507955fe9881e62cdd83599c63 Mon Sep 17 00:00:00 2001 From: Siddharth Suresh Date: Fri, 28 Jun 2024 14:45:53 -0700 Subject: [PATCH] Check invariants --- src/ledger/LedgerManagerImpl.cpp | 28 +++++++++++++++++++++++++ src/transactions/TransactionFrame.cpp | 28 ++++++++++++++++++++----- src/transactions/TransactionFrameBase.h | 2 ++ 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/ledger/LedgerManagerImpl.cpp b/src/ledger/LedgerManagerImpl.cpp index 9d1e362b88..561c60c064 100644 --- a/src/ledger/LedgerManagerImpl.cpp +++ b/src/ledger/LedgerManagerImpl.cpp @@ -17,6 +17,8 @@ #include "herder/TxSetFrame.h" #include "herder/Upgrades.h" #include "history/HistoryManager.h" +#include "invariant/InvariantDoesNotHold.h" +#include "invariant/InvariantManager.h" #include "ledger/FlushAndRotateMetaDebugWork.h" #include "ledger/LedgerHeaderUtils.h" #include "ledger/LedgerRange.h" @@ -1607,6 +1609,7 @@ LedgerManagerImpl::applyCluster(ClusterEntryMap& entryMap, Config const& config, txFAILED); } txBundle.mOpMetrics = res.mOpMetrics; + txBundle.mDelta = res.mDelta; } } @@ -1746,6 +1749,31 @@ LedgerManagerImpl::applySorobanStage(Application& app, AbstractLedgerTxn& ltx, { for (auto const& txBundle : cluster) { + // First check the invariants + if (txBundle.resPayload->isSuccess()) + { + try + { + // Soroban transactions don't have access to the ledger + // header, so they can't modify it. Pass in the current + // header as both current and previous. + txBundle.mDelta->header.current = + ltxInner.loadHeader().current(); + txBundle.mDelta->header.previous = + ltxInner.loadHeader().current(); + app.getInvariantManager().checkOnOperationApply( + txBundle.tx->getRawOperations().at(0), + txBundle.resPayload->getOpResultAt(0), + *txBundle.mDelta); + } + catch (InvariantDoesNotHold& e) + { + printErrorAndAbort( + "Invariant failure while applying operations: ", + e.what()); + } + } + txBundle.tx->processPostApply(mApp, ltxInner, txBundle.meta, txBundle.resPayload); diff --git a/src/transactions/TransactionFrame.cpp b/src/transactions/TransactionFrame.cpp index feb7fb3ac8..9e3acd1218 100644 --- a/src/transactions/TransactionFrame.cpp +++ b/src/transactions/TransactionFrame.cpp @@ -1563,6 +1563,8 @@ TransactionFrame::parallelApply( if (!fastFail && res.mSuccess) { + res.mDelta = std::make_shared(); + auto& delta = *res.mDelta; // Build OperationMeta LedgerEntryChanges changes; for (auto const& newUpdates : res.mModifiedEntryMap) @@ -1605,6 +1607,27 @@ TransactionFrame::parallelApply( changes.emplace_back(LEDGER_ENTRY_CREATED); changes.back().created() = *le; } + + LedgerTxnDelta::EntryDelta entryDelta; + if (prevLe) + { + entryDelta.previous = + std::make_shared(*prevLe); + } + if (le) + { + auto deltaLe = *le; + // This is for the invariants check in LedgerManager + deltaLe.lastModifiedLedgerSeq = ledgerSeq; + + entryDelta.current = + std::make_shared(deltaLe); + } + + delta.entry[lk] = entryDelta; + // Note that we don't set delta.header here because Soroban + // transactions don't modify the header. The header will be set + // right before we cal into the invariants. } xdr::xvector operationMetas; @@ -1634,11 +1657,6 @@ TransactionFrame::parallelApply( return res; } - /* catch (InvariantDoesNotHold& e) - { - printErrorAndAbort("Invariant failure while applying operations: ", - e.what()); - } */ catch (std::bad_alloc& e) { printErrorAndAbort("Exception while applying operations: ", e.what()); diff --git a/src/transactions/TransactionFrameBase.h b/src/transactions/TransactionFrameBase.h index 59fca54920..8ad6f51de6 100644 --- a/src/transactions/TransactionFrameBase.h +++ b/src/transactions/TransactionFrameBase.h @@ -53,6 +53,7 @@ struct ParallelOpReturnVal bool mSuccess{false}; ModifiedEntryMap mModifiedEntryMap; std::shared_ptr mOpMetrics; + std::shared_ptr mDelta; }; // temporary. Remove this @@ -70,6 +71,7 @@ class TxBundle // TODO: Stop using mutable mutable TransactionMetaFrame meta; mutable std::shared_ptr mOpMetrics; + mutable std::shared_ptr mDelta; }; typedef std::vector Cluster;