diff --git a/src/ledger/ImmutableLedgerView.cpp b/src/ledger/ImmutableLedgerView.cpp index 796e51c5d..3bc324762 100644 --- a/src/ledger/ImmutableLedgerView.cpp +++ b/src/ledger/ImmutableLedgerView.cpp @@ -188,6 +188,12 @@ CheckValidLedgerViewWrapper::CheckValidLedgerViewWrapper( { } +CheckValidLedgerViewWrapper::CheckValidLedgerViewWrapper( + std::unique_ptr getter) + : mGetter(std::move(getter)) +{ +} + LedgerHeaderWrapper CheckValidLedgerViewWrapper::getLedgerHeader() const { @@ -355,6 +361,70 @@ ImmutableLedgerView::executeWithMaybeInnerSnapshot( "ImmutableLedgerView::executeWithMaybeInnerSnapshot is illegal: " "ImmutableLedgerView has no nested snapshots"); } +SorobanPreApplyLedgerView::SorobanPreApplyLedgerView( + std::shared_ptr 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( + 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 f) const +{ + throw std::runtime_error("SorobanPreApplyLedgerView::" + "executeWithMaybeInnerSnapshot is not supported"); +} // === Live BucketList wrapper methods === diff --git a/src/ledger/ImmutableLedgerView.h b/src/ledger/ImmutableLedgerView.h index 3f6a523ea..52b30f032 100644 --- a/src/ledger/ImmutableLedgerView.h +++ b/src/ledger/ImmutableLedgerView.h @@ -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 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 f) + const override; + + private: + std::shared_ptr 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) @@ -235,6 +268,8 @@ class CheckValidLedgerViewWrapper : public NonMovableOrCopyable CheckValidLedgerViewWrapper(AbstractLedgerTxn& ltx); CheckValidLedgerViewWrapper(Application& app); explicit CheckValidLedgerViewWrapper(ImmutableLedgerView const& ledgerView); + explicit CheckValidLedgerViewWrapper( + std::unique_ptr 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 diff --git a/src/transactions/FeeBumpTransactionFrame.cpp b/src/transactions/FeeBumpTransactionFrame.cpp index 9d62ddba1..37aa9d302 100644 --- a/src/transactions/FeeBumpTransactionFrame.cpp +++ b/src/transactions/FeeBumpTransactionFrame.cpp @@ -83,39 +83,52 @@ FeeBumpTransactionFrame::FeeBumpTransactionFrame( #endif void -FeeBumpTransactionFrame::preParallelApply( - AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, - MutableTransactionResultBase& txResult, +FeeBumpTransactionFrame::preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, SorobanNetworkConfig const& sorobanConfig) const { try { - LedgerTxn ltxTx(ltx); - removeOneTimeSignerKeyFromFeeSource(ltxTx); - meta.pushTxChangesBefore(ltxTx); - ltxTx.commit(); + mInnerTx->preParallelApplyReadOnlyWithOptionallyChargedFee( + /*chargeFee=*/false, app, ls, meta, txResult, sorobanConfig, + getContentsHash()); } catch (std::exception& e) { - printErrorAndAbort("Exception in preParallelApply ", e.what()); + printErrorAndAbort("Exception during read-only preParallelApply: ", + e.what()); } catch (...) { - printErrorAndAbort("Unknown exception in preParallelApply"); + printErrorAndAbort( + "Unknown exception during read-only preParallelApply"); } +} +void +FeeBumpTransactionFrame::preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const +{ try { - mInnerTx->preParallelApply(/*chargeFee=*/false, app, ltx, meta, - txResult, sorobanConfig, getContentsHash()); + { + LedgerTxn ltxTx(ltx); + removeOneTimeSignerKeyFromFeeSource(ltxTx); + meta.pushTxChangesBefore(ltxTx); + ltxTx.commit(); + } + mInnerTx->preParallelApplyWrite(app, ltx, meta, txResult); } catch (std::exception& e) { - printErrorAndAbort("Exception during preParallelApply: ", e.what()); + printErrorAndAbort("Exception during preParallelApply writes: ", + e.what()); } catch (...) { - printErrorAndAbort("Unknown exception during preParallelApply"); + printErrorAndAbort("Unknown exception during preParallelApply writes"); } } diff --git a/src/transactions/FeeBumpTransactionFrame.h b/src/transactions/FeeBumpTransactionFrame.h index 0d1313422..eccce7018 100644 --- a/src/transactions/FeeBumpTransactionFrame.h +++ b/src/transactions/FeeBumpTransactionFrame.h @@ -90,11 +90,14 @@ class FeeBumpTransactionFrame : public TransactionFrameBase ~FeeBumpTransactionFrame() override = default; - void - preParallelApply(AppConnector& app, AbstractLedgerTxn& ltx, - TransactionMetaBuilder& meta, - MutableTransactionResultBase& txResult, - SorobanNetworkConfig const& sorobanConfig) const override; + void preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, + SorobanNetworkConfig const& sorobanConfig) const override; + + void preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const override; std::optional parallelApply( AppConnector& app, ThreadParallelApplyLedgerState const& threadState, diff --git a/src/transactions/ParallelApplyUtils.cpp b/src/transactions/ParallelApplyUtils.cpp index 618901d49..701dfa288 100644 --- a/src/transactions/ParallelApplyUtils.cpp +++ b/src/transactions/ParallelApplyUtils.cpp @@ -8,14 +8,18 @@ #include "ledger/LedgerTxn.h" #include "ledger/NetworkConfig.h" #include "main/AppConnector.h" +#include "transactions/OperationFrame.h" #include "transactions/ParallelApplyStage.h" #include "transactions/TransactionFrameBase.h" +#include "transactions/TransactionUtils.h" +#include "util/BatchExecutor.h" #include "util/GlobalChecks.h" #include "xdr/Stellar-ledger-entries.h" #include "xdrpp/printer.h" #include #include #include +#include namespace { @@ -174,8 +178,21 @@ updateMaxOfRoTTLBump(UnorderedMap& roTTLBumps, } } +void +commitPreParallelApplyWrites(AppConnector& app, AbstractLedgerTxn& ltx, + std::vector const& txBundles) +{ + ZoneScoped; + for (auto const* txBundle : txBundles) + { + txBundle->getTx()->preParallelApplyWrite( + app, ltx, txBundle->getEffects().getMeta(), + txBundle->getResPayload()); + } } +} // namespace + namespace stellar { @@ -319,14 +336,13 @@ GlobalParallelApplyLedgerState::GlobalParallelApplyLedgerState( // had their sequence numbers bumped and fees charged. preParallelApply will // update sequence numbers so it needs to be called before we check // LedgerTxn. - preParallelApplyAndCollectModifiedClassicEntries(app, ltx, stages); + preApplyAndCollectModifiedClassicEntries(app, ltx, stages); } void -GlobalParallelApplyLedgerState:: - preParallelApplyAndCollectModifiedClassicEntries( - AppConnector& app, AbstractLedgerTxn& ltx, - std::vector const& stages) +GlobalParallelApplyLedgerState::preApplyAndCollectModifiedClassicEntries( + AppConnector& app, AbstractLedgerTxn& ltx, + std::vector const& stages) { auto fetchInMemoryClassicEntries = [&](xdr::xvector const& keys) { @@ -353,34 +369,99 @@ GlobalParallelApplyLedgerState:: } }; - // First call preParallelApply on all transactions, - // and then load from footprints. This order is important - // because preParallelApply modifies the fee source accounts - // and those accounts could show up in the footprint - // of a different transaction. + std::vector txBundles; for (auto const& stage : stages) { for (auto const& txBundle : stage) { - // Make sure to call preParallelApply on all txs because this will - // modify the fee source accounts sequence numbers. - txBundle.getTx()->preParallelApply( - app, ltx, txBundle.getEffects().getMeta(), - txBundle.getResPayload(), mSorobanConfig); + txBundles.emplace_back(&txBundle); } } - for (auto const& stage : stages) + // Pre-apply all the transactions before loading the footprint entries. This + // order is important because the pre-apply modifies the source accounts, + // and those accounts could show up in the footprint of a transaction + // applied by a different thread, thus breaking the invariant that + // transactions are independent of each other across threads. + // + // The pre-apply process is done in two phases: a parallel read-only phase + // where the transactions are validated, and a serial write phase where the + // writes are committed to the ledger. + // + // This phase separatation hinges on the fact that the validation outcome + // of any Soroban transaction can't be influenced by the pre-apply writes + // performed by another Soroban transaction. Specifically, pre-apply writes + // only include: + // - The source account sequence number bumps - this is fine because we + // have only a single transaction per source account per ledger + // - The removal of one-time pre-authorized tx signers - this is also fine + // because any given transaction in a ledger is unique, and increasing the + // sub-entry count of a source/sponsor account is not relevant at that + // point, as the fees have already been successfully charged. + + auto header = + std::make_shared(ltx.loadHeader().current()); + readOnlyParallelPreApply(app, txBundles, header, ltx); + commitPreParallelApplyWrites(app, ltx, txBundles); + + for (auto const& txBundle : txBundles) { - for (auto const& txBundle : stage) - { - auto const& footprint = - txBundle.getTx()->sorobanResources().footprint; + auto const& footprint = txBundle->getTx()->sorobanResources().footprint; + fetchInMemoryClassicEntries(footprint.readWrite); + fetchInMemoryClassicEntries(footprint.readOnly); + } +} - fetchInMemoryClassicEntries(footprint.readWrite); - fetchInMemoryClassicEntries(footprint.readOnly); +void +GlobalParallelApplyLedgerState::readOnlyParallelPreApply( + AppConnector& app, std::vector const& txBundles, + std::shared_ptr header, AbstractLedgerTxn& ltx) +{ + ZoneScoped; + if (txBundles.empty()) + { + return; + } + + // Run pre-apply for [begin, end) transaction indices. + auto runRange = [&](size_t begin, size_t end) { + // NB: mLCLApplyView is not thread-safe, so we need to copy it into a + // thread-local view. + CheckValidLedgerViewWrapper ledgerView( + std::make_unique(header, ltx, + mLCLApplyView)); + for (size_t i = begin; i < end; ++i) + { + auto const* txBundle = txBundles[i]; + txBundle->getTx()->preParallelApplyReadOnly( + app, ledgerView, txBundle->getEffects().getMeta(), + txBundle->getResPayload(), mSorobanConfig); } + }; + + size_t taskCount = app.getBatchExecutor().preferredTaskCount(); + if (taskCount <= 1) + { + runRange(0, txBundles.size()); + return; + } + + std::vector> tasks; + tasks.reserve(taskCount); + size_t begin = 0; + size_t baseChunk = txBundles.size() / taskCount; + size_t remainder = txBundles.size() % taskCount; + for (size_t i = 0; i < taskCount; ++i) + { + size_t end = begin + baseChunk + (i < remainder ? 1 : 0); + tasks.emplace_back([runRange, begin, end]() { + runRange(begin, end); + return 0; + }); + begin = end; } + releaseAssert(begin == txBundles.size()); + app.getBatchExecutor().executeBatch(std::move(tasks)); } void diff --git a/src/transactions/ParallelApplyUtils.h b/src/transactions/ParallelApplyUtils.h index 7e7fd8b74..62497713c 100644 --- a/src/transactions/ParallelApplyUtils.h +++ b/src/transactions/ParallelApplyUtils.h @@ -219,10 +219,16 @@ class GlobalParallelApplyLedgerState // after -- as well as written back to the ltx at the phase's end. ParallelApplyEntryMap mGlobalEntryMap; - void preParallelApplyAndCollectModifiedClassicEntries( + void preApplyAndCollectModifiedClassicEntries( AppConnector& app, AbstractLedgerTxn& ltx, std::vector const& stages); + // Runs the read-only pre-apply stage for every bundle. + void readOnlyParallelPreApply(AppConnector& app, + std::vector const& txBundles, + std::shared_ptr header, + AbstractLedgerTxn& ltx); + bool maybeMergeRoTTLBumps(LedgerKey const& key, GlobalParallelApplyEntry const& newEntry, diff --git a/src/transactions/TransactionFrame.cpp b/src/transactions/TransactionFrame.cpp index 6d3593455..b50f7115d 100644 --- a/src/transactions/TransactionFrame.cpp +++ b/src/transactions/TransactionFrame.cpp @@ -99,6 +99,26 @@ getNumDiskReadEntries(SorobanResources const& resources, return count; } + +// Returns true if the transaction result indicates that the source account +// sequence number should be updated for that transaction. +// There are only a few possible reasons for why we would *not* update the +// sequence number: +// - There is no source account at all at this point (due to another transaction +// in the same ledger deleting the source account) +// - The sequence number is bad (due to another transaction in the same ledger +// performing a sequence bump) +// In any other scenario we should update the sequence number, and its highly +// unlikely that there would be any new reasons in the future. +// Note, that this logic makes sense for the apply step only where the +// transactions are already expected to be valid w.r.t LCL (so that they can +// only be invalidated by the other transactions in the same ledger). +bool +shouldUpdateSeqNumInPreApply(MutableTransactionResultBase const& txResult) +{ + auto code = txResult.getInnermostResultCode(); + return code != txBAD_SEQ && code != txNO_ACCOUNT; +} } // namespace using namespace std; @@ -1545,11 +1565,14 @@ TransactionFrame::processSeqNum(AbstractLedgerTxn& ltx) const bool TransactionFrame::processSignatures( ValidationType cv, SignatureChecker& signatureChecker, - AbstractLedgerTxn& ltxOuter, MutableTransactionResultBase& txResult) const + CheckValidLedgerViewWrapper const& ledgerView, + MutableTransactionResultBase& txResult, + AbstractLedgerTxn* ltxForWrites) const { ZoneScoped; bool maybeValid = (cv == ValidationType::kMaybeValid); - uint32_t ledgerVersion = ltxOuter.loadHeader().current().ledgerVersion; + uint32_t ledgerVersion = + ledgerView.getLedgerHeader().current().ledgerVersion; if (protocolVersionIsBefore(ledgerVersion, ProtocolVersion::V_10)) { return maybeValid; @@ -1559,7 +1582,10 @@ TransactionFrame::processSignatures( if (protocolVersionStartsFrom(ledgerVersion, ProtocolVersion::V_13) && !maybeValid) { - removeOneTimeSignerFromAllSourceAccounts(ltxOuter); + if (ltxForWrites) + { + removeOneTimeSignerFromAllSourceAccounts(*ltxForWrites); + } return false; } // older versions of the protocol only fast fail in a subset of cases @@ -1576,12 +1602,14 @@ TransactionFrame::processSignatures( if (auto code = txResult.getInnermostResultCode(); code == txSUCCESS || code == txFAILED) { - CheckValidLedgerViewWrapper ledgerView(ltxOuter); allOpsValid = checkOperationSignatures(signatureChecker, ledgerView, &txResult); } - removeOneTimeSignerFromAllSourceAccounts(ltxOuter); + if (ltxForWrites) + { + removeOneTimeSignerFromAllSourceAccounts(*ltxForWrites); + } if (!allOpsValid) { @@ -2041,14 +2069,16 @@ maybeTriggerTestInternalError(TransactionEnvelope const& env) std::unique_ptr TransactionFrame::commonPreApply(bool chargeFee, AppConnector& app, - AbstractLedgerTxn& ltx, + CheckValidLedgerViewWrapper const& ledgerView, TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, SorobanNetworkConfig const* sorobanConfig, - Hash const& envelopeContentsHash) const + Hash const& envelopeContentsHash, + AbstractLedgerTxn* ltxForWrites) const { mCachedAccountPreProtocol8.reset(); - uint32_t ledgerVersion = ltx.loadHeader().current().ledgerVersion; + uint32_t ledgerVersion = + ledgerView.getLedgerHeader().current().ledgerVersion; std::unique_ptr signatureChecker; #ifdef BUILD_TESTS // If the txResult has a replay result (catchup in skip mode is @@ -2087,23 +2117,18 @@ TransactionFrame::commonPreApply(bool chargeFee, AppConnector& app, // Pass in nullopt, we always use the header ledgerSeq in the apply path for // validation. - LedgerTxn ltxTx(ltx); - CheckValidLedgerViewWrapper lsTx(ltxTx); auto cv = - commonValid(app, sorobanConfig, *signatureChecker, lsTx, 0, true, + commonValid(app, sorobanConfig, *signatureChecker, ledgerView, 0, true, chargeFee, 0, 0, envelopeContentsHash, sorobanResourceFee, txResult, meta.getDiagnosticEventManager(), /*validationLedgerSeq=*/std::nullopt); - if (cv >= ValidationType::kInvalidUpdateSeqNum) + if (ltxForWrites && cv >= ValidationType::kInvalidUpdateSeqNum) { - processSeqNum(ltxTx); + processSeqNum(*ltxForWrites); } - bool signaturesValid = - processSignatures(cv, *signatureChecker, ltxTx, txResult); - - meta.pushTxChangesBefore(ltxTx); - ltxTx.commit(); + bool signaturesValid = processSignatures(cv, *signatureChecker, ledgerView, + txResult, ltxForWrites); if (signaturesValid && cv == ValidationType::kMaybeValid) { @@ -2116,67 +2141,92 @@ TransactionFrame::commonPreApply(bool chargeFee, AppConnector& app, } void -TransactionFrame::preParallelApply( - AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, - MutableTransactionResultBase& resPayload, +TransactionFrame::preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, SorobanNetworkConfig const& sorobanConfig) const { - preParallelApply(true, app, ltx, meta, resPayload, sorobanConfig, - getContentsHash()); + try + { + preParallelApplyReadOnlyWithOptionallyChargedFee( + /*chargeFee=*/true, app, ls, meta, txResult, sorobanConfig, + getContentsHash()); + } + catch (std::exception& e) + { + printErrorAndAbort("Exception during read-only preParallelApply: ", + e.what()); + } + catch (...) + { + printErrorAndAbort( + "Unknown exception during read-only preParallelApply"); + } } void -TransactionFrame::preParallelApply(bool chargeFee, AppConnector& app, - AbstractLedgerTxn& ltx, - TransactionMetaBuilder& meta, - MutableTransactionResultBase& txResult, - SorobanNetworkConfig const& sorobanConfig, - Hash const& envelopeContentsHash) const +TransactionFrame::preParallelApplyReadOnlyWithOptionallyChargedFee( + bool chargeFee, AppConnector& app, + CheckValidLedgerViewWrapper const& ledgerView, TransactionMetaBuilder& meta, + MutableTransactionResultBase& txResult, + SorobanNetworkConfig const& sorobanConfig, + Hash const& envelopeContentsHash) const { ZoneScoped; - releaseAssert(threadIsMain() || - app.threadIsType(Application::ThreadType::APPLY)); - try + + releaseAssertOrThrow(isSoroban()); + + auto signatureChecker = + commonPreApply(chargeFee, app, ledgerView, meta, txResult, + &sorobanConfig, envelopeContentsHash, + /*ltxForWrites=*/nullptr); + bool ok = signatureChecker != nullptr; + if (ok) { - releaseAssertOrThrow(isSoroban()); + updateSorobanMetrics(app); - auto signatureChecker = - commonPreApply(chargeFee, app, ltx, meta, txResult, &sorobanConfig, - envelopeContentsHash); - bool ok = signatureChecker != nullptr; - if (ok) + auto& opResult = txResult.getOpResultAt(0); + ok = mOperations.front()->checkValid( + app, *signatureChecker, &sorobanConfig, ledgerView, true, opResult, + meta.getDiagnosticEventManager()); + if (!ok) { - updateSorobanMetrics(app); + txResult.setInnermostError(txFAILED); + } + } - auto& opResult = txResult.getOpResultAt(0); + // If validation fails, we check the result code in the parallel + // step to make sure we don't apply the transaction. + releaseAssertOrThrow(ok == txResult.isSuccess()); +} - // Pre parallel soroban, OperationFrame::checkValid is called - // right before OperationFrame::doApply, but we do it here - // instead to avoid making OperationFrame::checkValid thread - // safe. - ok = mOperations.front()->checkValid( - app, *signatureChecker, &sorobanConfig, ltx, true, opResult, - meta.getDiagnosticEventManager()); - if (!ok) - { - txResult.setInnermostError(txFAILED); - } +void +TransactionFrame::preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const +{ + ZoneScoped; + releaseAssert(threadIsMain() || + app.threadIsType(Application::ThreadType::APPLY)); + try + { + LedgerTxn ltxTx(ltx); + if (shouldUpdateSeqNumInPreApply(txResult)) + { + processSeqNum(ltxTx); } - - // If validation fails, we check the result code in the parallel - // step to make sure we don't apply the transaction. - releaseAssertOrThrow(ok == txResult.isSuccess()); + removeOneTimeSignerFromAllSourceAccounts(ltxTx); + meta.pushTxChangesBefore(ltxTx); + ltxTx.commit(); } catch (std::exception& e) { - printErrorAndAbort("Exception after processing fees but before " - "processing sequence number: ", + printErrorAndAbort("Exception during preParallelApply writes: ", e.what()); } catch (...) { - printErrorAndAbort("Unknown exception after processing fees but before " - "processing sequence number"); + printErrorAndAbort("Unknown exception during preParallelApply writes"); } } @@ -2497,10 +2547,17 @@ TransactionFrame::apply( ZoneScoped; try { - auto signatureChecker = - commonPreApply(chargeFee, app, ltx, meta, txResult, - sorobanConfig ? &sorobanConfig.value() : nullptr, - envelopeContentsHash); + auto signatureChecker = [&] { + LedgerTxn ltxTx(ltx); + CheckValidLedgerViewWrapper lsTx(ltxTx); + auto checker = + commonPreApply(chargeFee, app, lsTx, meta, txResult, + sorobanConfig ? &sorobanConfig.value() : nullptr, + envelopeContentsHash, <xTx); + meta.pushTxChangesBefore(ltxTx); + ltxTx.commit(); + return checker; + }(); bool ok = signatureChecker != nullptr; try { diff --git a/src/transactions/TransactionFrame.h b/src/transactions/TransactionFrame.h index f46716a8d..f0d37a631 100644 --- a/src/transactions/TransactionFrame.h +++ b/src/transactions/TransactionFrame.h @@ -147,10 +147,15 @@ class TransactionFrame : public TransactionFrameBase void processSeqNum(AbstractLedgerTxn& ltx) const; + // Processes the transaction signatures and returns `true` on success. + // If `ltxForWrites` is nullptr, this function will be read-only and the + // caller is expected to defer any writes until after the + // `processSignatures` call. bool processSignatures(ValidationType cv, SignatureChecker& signatureChecker, - AbstractLedgerTxn& ltxOuter, - MutableTransactionResultBase& txResult) const; + CheckValidLedgerViewWrapper const& ledgerView, + MutableTransactionResultBase& txResult, + AbstractLedgerTxn* ltxForWrites) const; std::optional const getTimeBounds() const; std::optional const getLedgerBounds() const; @@ -290,36 +295,46 @@ class TransactionFrame : public TransactionFrameBase processFeeSeqNum(AbstractLedgerTxn& ltx, std::optional baseFee) const override; - // preApply runs all pre-application steps that are common between + // `commonPreApply` runs all pre-application steps that are common between // parallelApply and (sequential) apply: // // - building a signature checker // - calling commonValid - // - calling processSeqNum - // - calling processSignatures + // - (if writes are allowed) calling processSeqNum + // - calling processSignatures (in RO or RW mode) // - // If all of this succeeds it returns a non-nullptr pointer to the + // If `ltxForWrites` is nullptr, then this function becomes read-only and + // the caller is expected to defer any writes until after the + // `commonPreApply` call. + // + // If all of this succeeds, it returns a non-nullptr pointer to the // signature checker, to be used elsewhere in the txn. If anything // fails it returns nullptr. It does all of its work in a sub-ltx - // so the passed ltx is unchanged on failure. + // so the passed `ltxForWrites` is unchanged on failure. std::unique_ptr - commonPreApply(bool chargeFee, AppConnector& app, AbstractLedgerTxn& ltx, + commonPreApply(bool chargeFee, AppConnector& app, + CheckValidLedgerViewWrapper const& ledgerView, TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, SorobanNetworkConfig const* sorobanConfig, - Hash const& envelopeContentsHash) const; + Hash const& envelopeContentsHash, + AbstractLedgerTxn* ltxForWrites) const; - void preParallelApply(bool chargeFee, AppConnector& app, - AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, - MutableTransactionResultBase& txResult, - SorobanNetworkConfig const& sorobanConfig, - Hash const& envelopeContentsHash) const; + void preParallelApplyReadOnlyWithOptionallyChargedFee( + bool chargeFee, AppConnector& app, + CheckValidLedgerViewWrapper const& ls, TransactionMetaBuilder& meta, + MutableTransactionResultBase& txResult, + SorobanNetworkConfig const& sorobanConfig, + Hash const& envelopeContentsHash) const; - void - preParallelApply(AppConnector& app, AbstractLedgerTxn& ltx, - TransactionMetaBuilder& meta, - MutableTransactionResultBase& txResult, - SorobanNetworkConfig const& sorobanConfig) const override; + void preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, + SorobanNetworkConfig const& sorobanConfig) const override; + + void preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const override; std::optional parallelApply( AppConnector& app, ThreadParallelApplyLedgerState const& threadState, diff --git a/src/transactions/TransactionFrameBase.h b/src/transactions/TransactionFrameBase.h index 0e45aa97e..3d2a84dc0 100644 --- a/src/transactions/TransactionFrameBase.h +++ b/src/transactions/TransactionFrameBase.h @@ -156,11 +156,20 @@ class TransactionFrameBase std::optional const& sorobanConfig, Hash const& sorobanBasePrngSeed) const = 0; - virtual void - preParallelApply(AppConnector& app, AbstractLedgerTxn& ltx, - TransactionMetaBuilder& meta, - MutableTransactionResultBase& txResult, - SorobanNetworkConfig const& sorobanConfig) const = 0; + // The read-only half of the Soroban pre-apply: validation, signature checks + // and the operation's checkValid. Performs no writes. Safe to run + // concurrently for distinct transactions, provided `ls` supports concurrent + // reads. + virtual void preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& txResult, + SorobanNetworkConfig const& sorobanConfig) const = 0; + + // The write half of the Soroban pre-apply. Has to run on the thread that + // owns `ltx`, serially across transactions, in canonical transaction order. + virtual void preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const = 0; // If the transaction fails during parallel apply, returns std::nullopt. // Otherwise returns a ParallelTxSuccessVal containing the modified entries diff --git a/src/transactions/test/InvokeHostFunctionTests.cpp b/src/transactions/test/InvokeHostFunctionTests.cpp index 18cfe946f..41205b1e5 100644 --- a/src/transactions/test/InvokeHostFunctionTests.cpp +++ b/src/transactions/test/InvokeHostFunctionTests.cpp @@ -38,6 +38,7 @@ #include "test/TxTests.h" #include "transactions/InvokeHostFunctionOpFrame.h" #include "transactions/SignatureUtils.h" +#include "transactions/SponsorshipUtils.h" #include "transactions/TransactionUtils.h" #include "transactions/test/SorobanTxTestUtils.h" #include "transactions/test/SponsorshipTestUtils.h" @@ -73,9 +74,24 @@ checkResults(TransactionResultSet& r, int expectedSuccess, int expectedFailed) } REQUIRE(successCounter == expectedSuccess); - REQUIRE(expectedFailed == expectedFailed); + REQUIRE(failedCounter == expectedFailed); }; +// closeLedger applies transactions in the transaction set's own order, so +// results have to be matched back to transactions by hash. +TransactionResult const& +resultFor(TransactionResultSet const& resultSet, + TransactionFrameBasePtr const& tx) +{ + auto it = + std::find_if(resultSet.results.begin(), resultSet.results.end(), + [&tx](TransactionResultPair const& pair) { + return pair.transactionHash == tx->getContentsHash(); + }); + REQUIRE(it != resultSet.results.end()); + return it->result; +} + uint32_t getParallelSorobanTestProtocolVersion() { @@ -7891,10 +7907,9 @@ TEST_CASE("Module cache miss on immediate execution", auto invokeFailTx = makeAddTx(contract, INVOKE_ADD_UNCACHED_COST_FAIL, C); - // Transaction 4: invocation (with inadequate instructions to - // succeed) + // Transaction 4: invocation (with adequate instructions to succeed). auto invokePassTx = - makeAddTx(contract, INVOKE_ADD_UNCACHED_COST_PASS, C); + makeAddTx(contract, INVOKE_ADD_UNCACHED_COST_PASS, D); // Run single ledger with all 4 txs. First 2 should pass, 3rd should // fail, 4th should pass. @@ -11171,3 +11186,428 @@ TEST_CASE("create and invoke external ref contract", "[tx][soroban]") REQUIRE(invocation.invoke()); REQUIRE(invocation.getReturnValue().i32() == 7); } + +TEST_CASE_VERSIONS("Soroban pre-apply removes pre-auth tx signers", + "[tx][soroban][preapply]") +{ + VirtualClock clock; + auto app = createTestApplication(clock, getTestConfig()); + + for_versions_from(20, *app, [&] { + // Number of transactions that all use the same op source with the + // respective pre-authorized transaction signers. + int const SHARED_SIGNER_COUNT = 20; + // Number of transactions with its own source account pre-authorizing + // the transaction. + int const OWN_SIGNER_COUNT = 10; + + SorobanTest test(app); + modifySorobanNetworkConfig(*app, [](SorobanNetworkConfig& cfg) { + cfg.mStateArchivalSettings.minPersistentTTL = 1000; + }); + auto& root = test.getRoot(); + + auto addPreAuthTxSigner = [&](Application& app, TestAccount& sponsor, + TestAccount& account, Hash const& txHash, + bool sponsored = false) { + SignerKey signer(SIGNER_KEY_TYPE_PRE_AUTH_TX); + signer.preAuthTx() = txHash; + auto signerOp = setOptions(setSigner(Signer{signer, 1})); + signerOp.sourceAccount.activate() = toMuxedAccount(account); + + std::vector ops; + if (sponsored) + { + ops.push_back( + beginSponsoringFutureReserves(account.getPublicKey())); + ops.push_back(signerOp); + auto endOp = endSponsoringFutureReserves(); + endOp.sourceAccount.activate() = toMuxedAccount(account); + ops.push_back(endOp); + } + else + { + ops.push_back(signerOp); + } + + auto signerTx = sponsor.tx(ops); + signerTx->addSignature(account.getSecretKey()); + + auto resultSet = closeLedger(app, {signerTx}); + REQUIRE(isSuccessResult(resultSet.results.front().result)); + + if (sponsored) + { + auto ledgerView = + app.getLedgerManager().copyImmutableLedgerView(); + auto accountEntry = + ledgerView.load(accountKey(account.getPublicKey())); + REQUIRE(getNumSponsored(accountEntry.current()) == 1); + auto sponsorEntry = + ledgerView.load(accountKey(sponsor.getPublicKey())); + REQUIRE(getNumSponsoring(sponsorEntry.current()) == 1); + } + }; + + int64_t const startingBalance = + app->getLedgerManager().getLastMinBalance(50); + + auto sponsor = test.getRoot().create("sponsor", startingBalance); + // Account holding a pre-auth signer for each of the shared-signer + // transactions below. + auto sharedSigner = + test.getRoot().create("sharedSigner", startingBalance); + auto feeBumper = test.getRoot().create("feeBumper", startingBalance); + + std::vector txSources; + for (int i = 0; i < SHARED_SIGNER_COUNT + OWN_SIGNER_COUNT; ++i) + { + txSources.push_back( + root.create(fmt::format("txSource{}", i), startingBalance)); + } + + auto& contract = + test.deployWasmContract(rust_bridge::get_test_wasm_add_i32()); + + auto spec = SorobanInvocationSpec() + .setInstructions(2'000'000) + .setReadBytes(10'000) + .setInclusionFee(1000) + .setNonRefundableResourceFee(100'000) + .setRefundableResourceFee(200'000); + + std::vector txs; + + // Create transactions to pre-authorize by the sharedSigner account. + std::vector sharedSignerTxHashes; + for (int i = 0; i < SHARED_SIGNER_COUNT; ++i) + { + auto tx = + contract + .prepareInvocation("add", {makeI32(1), makeI32(2)}, spec) + .withOpSourceAccount(sharedSigner.getPublicKey()) + .createTx(&txSources[i]); + sharedSignerTxHashes.push_back(tx->getContentsHash()); + txs.push_back(tx); + } + + // Add the pre-auth signers to the sharedSigner account. + std::vector signerOps; + int sponsoredCount = 0; + for (int i = 0; i < SHARED_SIGNER_COUNT; ++i) + { + SignerKey signer(SIGNER_KEY_TYPE_PRE_AUTH_TX); + signer.preAuthTx() = sharedSignerTxHashes[i]; + auto signerOp = setOptions(setSigner(Signer{signer, 1})); + signerOp.sourceAccount.activate() = toMuxedAccount(sharedSigner); + // Make half of the signers sponsored. + if (i % 2 == 0) + { + ++sponsoredCount; + signerOps.push_back( + beginSponsoringFutureReserves(sharedSigner.getPublicKey())); + signerOps.push_back(signerOp); + auto endOp = endSponsoringFutureReserves(); + endOp.sourceAccount.activate() = toMuxedAccount(sharedSigner); + signerOps.push_back(endOp); + } + else + { + signerOps.push_back(signerOp); + } + } + auto signerTx = sponsor.tx(signerOps); + signerTx->addSignature(sharedSigner.getSecretKey()); + REQUIRE(isSuccessResult( + closeLedger(*app, {signerTx}).results.front().result)); + { + auto ledgerView = app->getLedgerManager().copyImmutableLedgerView(); + auto entry = + ledgerView.load(accountKey(sharedSigner.getPublicKey())); + REQUIRE(entry.current().data.account().signers.size() == + SHARED_SIGNER_COUNT); + REQUIRE(getNumSponsored(entry.current()) == sponsoredCount); + auto sponsorEntry = + ledgerView.load(accountKey(sponsor.getPublicKey())); + REQUIRE(getNumSponsoring(sponsorEntry.current()) == sponsoredCount); + } + + // Create transactions and accounts that are pre-authorized at the + // tx source level. + std::vector ownSponsors; + for (int i = 0; i < OWN_SIGNER_COUNT; ++i) + { + auto& source = txSources[SHARED_SIGNER_COUNT + i]; + TransactionFrameBasePtr tx = + contract + .prepareInvocation("add", {makeI32(1), makeI32(2)}, spec) + .createTx(&source); + auto txEnvelope = tx->getEnvelope(); + // No need for the actual signatures, as we're using pre-auth tx + // signer. + txEnvelope.v1().signatures.clear(); + tx = TransactionFrameBase::makeTransactionFromWire( + app->getNetworkID(), txEnvelope); + ownSponsors.push_back( + root.create(fmt::format("ownSponsor{}", i), startingBalance)); + // Make some of the signers sponsored. + addPreAuthTxSigner(*app, ownSponsors.back(), source, + tx->getContentsHash(), + /*sponsored=*/i % 2 == 0); + // Make some of transactions fee-bumped. + if (i % 2 == 1) + { + tx = feeBump(*app, feeBumper, tx, 10000); + } + txs.push_back(tx); + } + + auto r = closeLedger(*app, txs); + REQUIRE(r.results.size() == txs.size()); + for (auto const& tx : txs) + { + REQUIRE(isSuccessResult(resultFor(r, tx))); + } + + auto ledgerView = app->getLedgerManager().copyImmutableLedgerView(); + // Every one-time signer is gone for the sharedSigner, and all the + // sponsorships are removed. + auto sharedEntry = + ledgerView.load(accountKey(sharedSigner.getPublicKey())); + REQUIRE(sharedEntry.current().data.account().signers.empty()); + REQUIRE(getNumSponsored(sharedEntry.current()) == 0); + auto sponsorEntry = ledgerView.load(accountKey(sponsor.getPublicKey())); + REQUIRE(getNumSponsoring(sponsorEntry.current()) == 0); + + // Every one-time signer is gone the tx sources, and all the + // sponsorships are removed. + for (int i = 0; i < txs.size(); ++i) + { + auto& source = txSources[i]; + auto entry = ledgerView.load(accountKey(source.getPublicKey())); + REQUIRE(entry.current().data.account().signers.empty()); + REQUIRE(getNumSponsored(entry.current()) == 0); + + if (i >= SHARED_SIGNER_COUNT) + { + auto ownSponsorEntry = ledgerView.load(accountKey( + ownSponsors[i - SHARED_SIGNER_COUNT].getPublicKey())); + REQUIRE(getNumSponsoring(ownSponsorEntry.current()) == 0); + } + } + }); +} + +TEST_CASE_VERSIONS( + "Soroban operation source created and removed in classic phase", + "[tx][soroban][preapply]") +{ + VirtualClock clock; + auto app = createTestApplication(clock, getTestConfig()); + + for_versions_from(20, *app, [&] { + // Number of transactions that create and remove accounts in the classic + // phase (and then are used as operation sources). + int const TX_COUNT_PER_ACCOUNT_CHANGE = 20; + + SorobanTest test(app); + auto makeOpSourceInvocation = [&](TestContract& contract, + TestAccount& txSource, + AccountID const& opSource, + SecretKey const& opKey) { + auto spec = SorobanInvocationSpec() + .setInstructions(1'000'000) + .setReadBytes(10'000) + .setInclusionFee(1000) + .setNonRefundableResourceFee(100'000) + .setRefundableResourceFee(200'000); + auto tx = + contract + .prepareInvocation("add", {makeI32(1), makeI32(2)}, spec) + .withOpSourceAccount(opSource) + .createTx(&txSource); + tx->addSignature(opKey); + return tx; + }; + + auto& root = test.getRoot(); + auto accountBalance = app->getLedgerManager().getLastMinBalance(2); + + auto sorobanTxCount = 3 * TX_COUNT_PER_ACCOUNT_CHANGE; + + // Setup all the accounts/keys necessary: accounts that create new + // accounts, accounts that keys of the created accounts, and accounts + // that are merged. + std::vector creators; + std::vector createdAccountKeys; + std::vector mergedAccounts; + for (int i = 0; i < TX_COUNT_PER_ACCOUNT_CHANGE; ++i) + { + creators.push_back( + root.create(fmt::format("creator{}", i), accountBalance * 100)); + mergedAccounts.push_back( + root.create(fmt::format("merged{}", i), accountBalance)); + createdAccountKeys.push_back( + getAccount(fmt::format("created{}", i))); + } + // Setup the source account for Soroban txs (nothing interesting happens + // to these). + std::vector sorobanSources; + for (int i = 0; i < sorobanTxCount; ++i) + { + sorobanSources.push_back( + root.create(fmt::format("sorobanSrc{}", i), accountBalance)); + } + + auto& contract = + test.deployWasmContract(rust_bridge::get_test_wasm_add_i32()); + + std::vector txs; + // Create classic txs: account creations and merges. + for (int i = 0; i < TX_COUNT_PER_ACCOUNT_CHANGE; ++i) + { + txs.push_back(creators[i].tx({createAccount( + createdAccountKeys[i].getPublicKey(), accountBalance)})); + txs.push_back( + mergedAccounts[i].tx({accountMerge(root.getPublicKey())})); + } + auto classicTxCount = txs.size(); + + for (int i = 0; i < TX_COUNT_PER_ACCOUNT_CHANGE; ++i) + { + // Tx that uses a created account as the operation source. + txs.push_back(makeOpSourceInvocation( + contract, sorobanSources[i], + createdAccountKeys[i].getPublicKey(), createdAccountKeys[i])); + // Tx that uses a merged account as the operation source (which + // should fail). + txs.push_back(makeOpSourceInvocation( + contract, sorobanSources[TX_COUNT_PER_ACCOUNT_CHANGE + i], + mergedAccounts[i].getPublicKey(), + mergedAccounts[i].getSecretKey())); + // 'Baseline' tx that just uses an existing account as the operation + // source (but the source account was also used in the classic + // phase). + txs.push_back(makeOpSourceInvocation( + contract, sorobanSources[2 * TX_COUNT_PER_ACCOUNT_CHANGE + i], + creators[i].getPublicKey(), creators[i].getSecretKey())); + } + + auto r = closeLedger(*app, txs); + REQUIRE(r.results.size() == txs.size()); + + for (int i = 0; i < classicTxCount; ++i) + { + INFO("classic tx " << i); + REQUIRE(isSuccessResult(resultFor(r, txs[i]))); + } + for (int i = 0; i < TX_COUNT_PER_ACCOUNT_CHANGE; ++i) + { + INFO("created account " << i); + REQUIRE(isSuccessResult(resultFor(r, txs[classicTxCount + 3 * i]))); + INFO("merged account " << i); + auto const& accountMergedRes = + resultFor(r, txs[classicTxCount + 3 * i + 1]); + REQUIRE(accountMergedRes.result.code() == txFAILED); + REQUIRE(accountMergedRes.result.results()[0].code() == + opNO_ACCOUNT); + INFO("existing account " << i); + REQUIRE( + isSuccessResult(resultFor(r, txs[classicTxCount + 3 * i + 2]))); + } + }); +} + +TEST_CASE_VERSIONS("classic phase bumps sequence of Soroban tx source account", + "[tx][soroban][preapply]") +{ + VirtualClock clock; + auto app = createTestApplication(clock, getTestConfig()); + + for_versions_from(20, *app, [&] { + int const BUMPED_ACCOUNT_COUNT = 20; + int const NORMAL_ACCOUNT_COUNT = 10; + + SorobanTest test(app); + auto& root = test.getRoot(); + auto accountBalance = app->getLedgerManager().getLastMinBalance(10); + + std::vector bumpSources; + std::vector bumpedAccounts; + for (int i = 0; i < BUMPED_ACCOUNT_COUNT; ++i) + { + bumpSources.push_back( + root.create(fmt::format("bumpsrc{}", i), accountBalance)); + bumpedAccounts.push_back( + root.create(fmt::format("bumped{}", i), accountBalance)); + } + std::vector normalAccounts; + for (int i = 0; i < NORMAL_ACCOUNT_COUNT; ++i) + { + normalAccounts.push_back( + root.create(fmt::format("normal{}", i), accountBalance)); + } + + auto& contract = + test.deployWasmContract(rust_bridge::get_test_wasm_add_i32()); + + auto makeInvocation = [&](TestAccount& source) { + auto spec = SorobanInvocationSpec() + .setInstructions(1'000'000) + .setReadBytes(10'000) + .setInclusionFee(1000) + .setNonRefundableResourceFee(100'000) + .setRefundableResourceFee(200'000); + return contract + .prepareInvocation("add", {makeI32(1), makeI32(2)}, spec) + .createTx(&source); + }; + + std::vector txs; + // Build the Soroban transactions first, so that they capture the + // pre-bump sequence numbers. + std::vector sorobanTxs; + for (int i = 0; i < BUMPED_ACCOUNT_COUNT; ++i) + { + txs.push_back(makeInvocation(bumpedAccounts[i])); + } + for (int i = 0; i < NORMAL_ACCOUNT_COUNT; ++i) + { + txs.push_back(makeInvocation(normalAccounts[i])); + } + auto sorobanTxCount = txs.size(); + + // Build the classic sequence bump transactions now, which will bump the + // sequence numbers of the bumpedAccounts via operation source accounts. + for (int i = 0; i < BUMPED_ACCOUNT_COUNT; ++i) + { + auto bumpOp = + bumpSequence(bumpedAccounts[i].getLastSequenceNumber() + 1000); + bumpOp.sourceAccount.activate() = + toMuxedAccount(bumpedAccounts[i].getPublicKey()); + auto bumpTx = bumpSources[i].tx({bumpOp}); + bumpTx->addSignature(bumpedAccounts[i].getSecretKey()); + txs.push_back(bumpTx); + } + + auto r = closeLedger(*app, txs); + REQUIRE(r.results.size() == txs.size()); + + for (size_t i = 0; i < BUMPED_ACCOUNT_COUNT; ++i) + { + INFO("classic tx " << i); + REQUIRE(isSuccessResult(resultFor(r, txs[sorobanTxCount + i]))); + } + for (int i = 0; i < BUMPED_ACCOUNT_COUNT; ++i) + { + INFO("bumped account " << i); + REQUIRE(resultFor(r, txs[i]).result.code() == txBAD_SEQ); + } + for (int i = 0; i < NORMAL_ACCOUNT_COUNT; ++i) + { + INFO("normal account " << i); + REQUIRE( + isSuccessResult(resultFor(r, txs[BUMPED_ACCOUNT_COUNT + i]))); + } + }); +} diff --git a/src/transactions/test/ParallelApplyTest.cpp b/src/transactions/test/ParallelApplyTest.cpp index 8c9a212cf..c1350fe7b 100644 --- a/src/transactions/test/ParallelApplyTest.cpp +++ b/src/transactions/test/ParallelApplyTest.cpp @@ -17,6 +17,7 @@ #include "transactions/OperationFrame.h" #include "transactions/TransactionFrameBase.h" #include "transactions/test/SorobanTxTestUtils.h" +#include "util/BatchExecutor.h" #include "util/UnorderedSet.h" using namespace stellar; @@ -1313,4 +1314,307 @@ TEST_CASE("parallel soroban application results are independent of transaction " runTestCase(testConfig); } +struct PreApplyScenarioResult +{ + TransactionResultSet mResults; + LedgerCloseMeta mMeta; + std::vector>> mEntries; +}; + +// Builds and applies a single ledger with classic phase that mutates a pool of +// accounts (creating, merging, sequence bumping and paying them) and with a +// Soroban phase then uses those same accounts as transaction sources, +// operation sources, and native SAC transfer destinations. +// +// `multiplier` defines the size of the test scenario, and `preApplyTaskCount` +// defines the number of worker threads that the pre-apply phase should use. +// +// The scenario is parametrized by the `seed` and `multiplier`, and it's +// expected that that no matter the `preApplyTaskCount`, the final ledger state +// is identical for the same seed. +PreApplyScenarioResult +runPreApplyScenario(int64_t seed, int multiplier, size_t preApplyTaskCount) +{ + // Number of accounts with the respective classic phase treatment. + int const MERGED_COUNT = multiplier; + int const BUMPED_COUNT = multiplier; + int const CREATED_COUNT = multiplier; + int const NORMAL_COUNT = 2 * multiplier; + + // Number of clusters to use during the apply phase itself - setting it to + // non-1 just to make coverage more realistic. + int const APPLY_CLUSTER_COUNT = 4; + + std::mt19937 rng(seed); + + Config cfg = getTestConfig(); + cfg.LEDGER_PROTOCOL_VERSION = Config::CURRENT_LEDGER_PROTOCOL_VERSION; + cfg.TESTING_UPGRADE_LEDGER_PROTOCOL_VERSION = + Config::CURRENT_LEDGER_PROTOCOL_VERSION; + cfg.TESTING_UPGRADE_MAX_TX_SET_SIZE = multiplier * 3; + + SorobanTest test(cfg, true, [&](SorobanNetworkConfig& sorobanCfg) { + sorobanCfg.mLedgerMaxDependentTxClusters = APPLY_CLUSTER_COUNT; + sorobanCfg.mLedgerMaxTxCount = multiplier * 5; + }); + test.getApp().getBatchExecutor().setPreferredTaskCountForTesting( + preApplyTaskCount); + + auto& root = test.getRoot(); + int64_t accountBalance = + test.getApp().getLedgerManager().getLastMinBalance(20); + + int sorobanTxCount = MERGED_COUNT + BUMPED_COUNT + NORMAL_COUNT; + + std::vector classicSources; + std::vector mergedAccounts; + std::vector bumpedAccounts; + std::vector normalAccounts; + std::vector createdKeys; + for (int i = 0; i < MERGED_COUNT + BUMPED_COUNT + CREATED_COUNT; ++i) + { + classicSources.push_back(root.create(fmt::format("classicSource{}", i), + accountBalance * 10)); + } + for (int i = 0; i < MERGED_COUNT; ++i) + { + mergedAccounts.push_back( + root.create(fmt::format("merged{}", i), accountBalance)); + } + for (int i = 0; i < BUMPED_COUNT; ++i) + { + bumpedAccounts.push_back( + root.create(fmt::format("bumped{}", i), accountBalance)); + } + for (int i = 0; i < NORMAL_COUNT; ++i) + { + normalAccounts.push_back( + root.create(fmt::format("normal{}", i), accountBalance)); + } + for (int i = 0; i < CREATED_COUNT; ++i) + { + createdKeys.push_back(getAccount(fmt::format("created{}", i))); + } + auto feeBumper = root.create("feeBumper", accountBalance * 1000); + + AssetContractTestClient sac(test, txtest::makeNativeAsset()); + + // Destinations for the Soroban transfers: the accounts that the classic + // phase modifies as classic transaction sources, plus the accounts it + // creates. Each destination is used at most once. + std::vector destinations; + for (auto const& acc : classicSources) + { + destinations.push_back(acc.getPublicKey()); + } + for (auto const& key : createdKeys) + { + destinations.push_back(key.getPublicKey()); + } + stellar::shuffle(destinations.begin(), destinations.end(), rng); + REQUIRE(destinations.size() >= static_cast(sorobanTxCount)); + + // Classic phase setup + std::vector txs; + for (int i = 0; i < MERGED_COUNT; ++i) + { + // Merge via an operation source so that the merged account itself + // stays free to source a Soroban transaction. + auto mergeOp = accountMerge(root.getPublicKey()); + mergeOp.sourceAccount.activate() = + toMuxedAccount(mergedAccounts[i].getPublicKey()); + auto tx = classicSources[i].tx({mergeOp}); + tx->addSignature(mergedAccounts[i].getSecretKey()); + txs.push_back(tx); + } + for (int i = 0; i < BUMPED_COUNT; ++i) + { + auto bumpOp = + bumpSequence(bumpedAccounts[i].getLastSequenceNumber() + 1000); + bumpOp.sourceAccount.activate() = + toMuxedAccount(bumpedAccounts[i].getPublicKey()); + auto tx = classicSources[MERGED_COUNT + i].tx({bumpOp}); + tx->addSignature(bumpedAccounts[i].getSecretKey()); + txs.push_back(tx); + } + for (int i = 0; i < CREATED_COUNT; ++i) + { + txs.push_back(classicSources[MERGED_COUNT + BUMPED_COUNT + i].tx( + {createAccount(createdKeys[i].getPublicKey(), accountBalance)})); + } + auto classicTxCount = txs.size(); + + // Soroban phase: native SAC transfers out of every account category. + std::vector sorobanSources; + for (auto& acc : mergedAccounts) + { + sorobanSources.push_back(&acc); + } + for (auto& acc : bumpedAccounts) + { + sorobanSources.push_back(&acc); + } + for (auto& acc : normalAccounts) + { + sorobanSources.push_back(&acc); + } + + // Manually validate that the footprints of the Soroban transactions + // are disjoint: these only mutate the SAC transfer source and destination, + // and thus it's sufficient to check that the source and destination + // account sets are disjoint (every source and destination is used just + // once per transaction). + { + UnorderedSet sourceIDs; + for (auto const* acc : sorobanSources) + { + sourceIDs.insert(acc->getPublicKey()); + } + for (auto const& dest : destinations) + { + REQUIRE(sourceIDs.count(dest) == 0); + } + } + + stellar::uniform_int_distribution feeBumpDist(0, 3); + stellar::uniform_int_distribution amountDist(1, 10000); + for (int i = 0; i < sorobanTxCount; ++i) + { + TransactionFrameBasePtr tx = sac.getTransferTx( + *sorobanSources[i], makeAccountAddress(destinations[i]), + amountDist(rng)); + // Fee bump some transactions that we expect to succeed. + if (i >= MERGED_COUNT + BUMPED_COUNT && feeBumpDist(rng) == 0) + { + tx = feeBump(test.getApp(), feeBumper, tx, 100'000); + } + txs.push_back(tx); + } + + // Validate every transaction manually, as we skip validation due to fixed + // Soroban apply order. + { + CheckValidLedgerViewWrapper ledgerView(test.getApp()); + auto diag = DiagnosticEventManager::createDisabled(); + for (auto const& tx : txs) + { + REQUIRE(tx->checkValid(test.getApp().getAppConnector(), ledgerView, + 0, 0, 0, diag) + ->isSuccess()); + } + } + + // A single stage with a fixed number of clusters. Note, that the indices + // are relative to the Soroban phase, not to the full transaction list. + ParallelSorobanOrder sorobanApplyOrder( + 1, std::vector>(APPLY_CLUSTER_COUNT)); + for (int i = 0; i < sorobanTxCount; ++i) + { + sorobanApplyOrder[0][i % APPLY_CLUSTER_COUNT].push_back(i); + } + + PreApplyScenarioResult res; + res.mResults = closeLedger(test.getApp(), txs, sorobanApplyOrder); + REQUIRE(res.mResults.results.size() == txs.size()); + res.mMeta = test.getLastLcm().getXDR(); + + // Make sure the scenario actually exercises what it is supposed to: the + // classic phase has to succeed, and the Soroban phase has to observe its + // effects on the accounts it removed and sequence bumped. + { + auto resultFor = [&res](TransactionFrameBasePtr const& tx) { + auto const& results = res.mResults.results; + auto it = std::find_if(results.begin(), results.end(), + [&tx](TransactionResultPair const& pair) { + return pair.transactionHash == + tx->getContentsHash(); + }); + REQUIRE(it != results.end()); + return it->result; + }; + for (int i = 0; i < classicTxCount; ++i) + { + INFO("classic tx " << i); + REQUIRE(isSuccessResult(resultFor(txs[i]))); + } + for (int i = 0; i < sorobanTxCount; ++i) + { + INFO("soroban tx " << i); + auto result = resultFor(txs[classicTxCount + i]); + auto code = result.result.code(); + if (i < MERGED_COUNT) + { + REQUIRE(code == txNO_ACCOUNT); + } + else if (i < MERGED_COUNT + BUMPED_COUNT) + { + REQUIRE(code == txBAD_SEQ); + } + else + { + REQUIRE(isSuccessResult(result)); + } + } + } + + // Snapshot every account the scenario could have touched. + std::vector observedAccounts; + auto addAccounts = [&observedAccounts](auto const& accounts) { + for (auto const& acc : accounts) + { + observedAccounts.push_back(acc.getPublicKey()); + } + }; + addAccounts(classicSources); + addAccounts(mergedAccounts); + addAccounts(bumpedAccounts); + addAccounts(normalAccounts); + addAccounts(createdKeys); + observedAccounts.push_back(feeBumper.getPublicKey()); + observedAccounts.push_back(root.getPublicKey()); + + auto ledgerView = + test.getApp().getLedgerManager().copyImmutableLedgerView(); + for (auto const& accountID : observedAccounts) + { + auto key = accountKey(accountID); + std::optional entry; + if (auto e = ledgerView.load(key)) + { + entry = e.current(); + } + res.mEntries.emplace_back(key, entry); + } + return res; +} + +TEST_CASE("Soroban pre-apply results are independent of the worker count", + "[soroban][preapply][acceptance]") +{ + int const SEED_COUNT = 5; + int const SCENARIOS[] = {1, 5, 20, 100}; + int const MAX_WORKER_COUNT = 8; + + for (int runIdx = 0; runIdx < SEED_COUNT; ++runIdx) + { + int64_t seed = Catch::rng()(); + CAPTURE(seed); + for (int scenario : SCENARIOS) + { + CAPTURE(scenario); + auto baseResult = runPreApplyScenario(seed, scenario, 1); + for (int workerCount = 2; workerCount <= MAX_WORKER_COUNT; + ++workerCount) + { + CAPTURE(workerCount); + auto runResult = + runPreApplyScenario(seed, scenario, workerCount); + REQUIRE(runResult.mResults == baseResult.mResults); + REQUIRE(runResult.mMeta == baseResult.mMeta); + REQUIRE(runResult.mEntries == baseResult.mEntries); + } + } + } +} + } // namespace diff --git a/src/transactions/test/SorobanTxTestUtils.cpp b/src/transactions/test/SorobanTxTestUtils.cpp index 461559386..7e8b3eace 100644 --- a/src/transactions/test/SorobanTxTestUtils.cpp +++ b/src/transactions/test/SorobanTxTestUtils.cpp @@ -736,17 +736,17 @@ TestContract::Invocation::deduplicateFootprint() xdr::xvector readWrite; UnorderedSet keys; - auto deduplicate = [&](auto const& fp) { + auto deduplicate = [&](auto const& fp, auto& output) { for (auto const& key : fp) { if (keys.insert(key).second) { - readWrite.push_back(key); + output.push_back(key); } } }; - deduplicate(mSpec.getResources().footprint.readWrite); - deduplicate(mSpec.getResources().footprint.readOnly); + deduplicate(mSpec.getResources().footprint.readWrite, readWrite); + deduplicate(mSpec.getResources().footprint.readOnly, readOnly); mSpec = mSpec.setReadOnlyFootprint(readOnly).setReadWriteFootprint(readWrite); } @@ -1708,6 +1708,7 @@ AssetContractTestClient::getTransferTx(TestAccount& fromAcc, mContract .prepareInvocation("transfer", {fromVal, toVal, makeI128(amount)}, spec) + .withDeduplicatedFootprint() .withAuthorizedTopCall(); if (!sourceIsRoot) { diff --git a/src/transactions/test/TransactionTestFrame.cpp b/src/transactions/test/TransactionTestFrame.cpp index 8a94d93d8..41c50f0d0 100644 --- a/src/transactions/test/TransactionTestFrame.cpp +++ b/src/transactions/test/TransactionTestFrame.cpp @@ -372,13 +372,21 @@ TransactionTestFrame::insertKeysForTxApply(UnorderedSet& keys) const } void -TransactionTestFrame::preParallelApply( - AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, - MutableTransactionResultBase& resPayload, +TransactionTestFrame::preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& resPayload, SorobanNetworkConfig const& sorobanConfig) const { - mTransactionFrame->preParallelApply(app, ltx, meta, resPayload, - sorobanConfig); + mTransactionFrame->preParallelApplyReadOnly(app, ls, meta, resPayload, + sorobanConfig); +} + +void +TransactionTestFrame::preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const +{ + mTransactionFrame->preParallelApplyWrite(app, ltx, meta, txResult); } std::optional diff --git a/src/transactions/test/TransactionTestFrame.h b/src/transactions/test/TransactionTestFrame.h index acb3228f8..77b40c81b 100644 --- a/src/transactions/test/TransactionTestFrame.h +++ b/src/transactions/test/TransactionTestFrame.h @@ -157,11 +157,14 @@ class TransactionTestFrame : public TransactionFrameBase insertKeysForFeeProcessing(UnorderedSet& keys) const override; void insertKeysForTxApply(UnorderedSet& keys) const override; - void - preParallelApply(AppConnector& app, AbstractLedgerTxn& ltx, - TransactionMetaBuilder& meta, - MutableTransactionResultBase& resPayload, - SorobanNetworkConfig const& sorobanConfig) const override; + void preParallelApplyReadOnly( + AppConnector& app, CheckValidLedgerViewWrapper const& ls, + TransactionMetaBuilder& meta, MutableTransactionResultBase& resPayload, + SorobanNetworkConfig const& sorobanConfig) const override; + + void preParallelApplyWrite( + AppConnector& app, AbstractLedgerTxn& ltx, TransactionMetaBuilder& meta, + MutableTransactionResultBase const& txResult) const override; std::optional parallelApply( AppConnector& app, ThreadParallelApplyLedgerState const& threadState, diff --git a/src/util/BatchExecutor.cpp b/src/util/BatchExecutor.cpp index 324efc429..9bc3885d1 100644 --- a/src/util/BatchExecutor.cpp +++ b/src/util/BatchExecutor.cpp @@ -210,6 +210,35 @@ BatchExecutor::pinWorker(size_t index) #endif } +size_t +BatchExecutor::preferredTaskCount() const +{ +#ifdef BUILD_TESTS + if (mPreferredTaskCountForTesting) + { + return *mPreferredTaskCountForTesting; + } +#endif + // As this is meant to be used for parallelizing CPU-heavy work, we want to + // only run the tasks on the physical cores (when physical core info is + // available). + auto concurrency = mPhysicalCoreCount > 0 + ? mPhysicalCoreCount + : std::thread::hardware_concurrency(); + // We want to leave at least one core free to not compete with the main + // thread and other background work. + return concurrency > 1 ? concurrency - 1 : 1; +} + +#ifdef BUILD_TESTS +void +BatchExecutor::setPreferredTaskCountForTesting(size_t count) +{ + releaseAssert(count > 0); + mPreferredTaskCountForTesting = count; +} +#endif + void BatchExecutor::runBatchImpl(size_t numTasks, std::function const& runTask) diff --git a/src/util/BatchExecutor.h b/src/util/BatchExecutor.h index 652dfc357..fc5c01ffe 100644 --- a/src/util/BatchExecutor.h +++ b/src/util/BatchExecutor.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,18 @@ class BatchExecutor : private NonMovableOrCopyable template std::vector executeBatch(std::vector> tasks); + // Returns the maximum number of tasks to use in `executeBatch` without + // oversubscribing physical cores. + // Use this many tasks whenever possible to maximize parallelism and avoid + // oversubscription. + size_t preferredTaskCount() const; + +#ifdef BUILD_TESTS + // Overrides the value returned by `preferredTaskCount`, so that tests can + // pin the parallelism independently of the machine they run on. + void setPreferredTaskCountForTesting(size_t count); +#endif + private: // Runs `runTask(0)..runTask(numTasks-1)` across `numTasks` pinned workers // and blocks until all complete. Rethrows the first exception captured from @@ -96,6 +109,10 @@ class BatchExecutor : private NonMovableOrCopyable // Marks that a batch is currently running, to prevent concurrent // executeBatch calls. std::atomic mBatchRunning{false}; + +#ifdef BUILD_TESTS + std::optional mPreferredTaskCountForTesting; +#endif }; template diff --git a/test-tx-meta-baseline-current/InvokeHostFunctionTests.json b/test-tx-meta-baseline-current/InvokeHostFunctionTests.json index 6a2f0d598..a5f5930a5 100644 --- a/test-tx-meta-baseline-current/InvokeHostFunctionTests.json +++ b/test-tx-meta-baseline-current/InvokeHostFunctionTests.json @@ -1339,6 +1339,1365 @@ "Soroban non-refundable resource fees are stable|protocol version 26" : [ "+cR3oq2qY0I=" ], "Soroban non-refundable resource fees are stable|protocol version 27" : [ "+cR3oq2qY0I=" ], "Soroban non-refundable resource fees are stable|protocol version 28" : [ "+cR3oq2qY0I=" ], + "Soroban operation source created and removed in classic phase|protocol version 20" : + [ + "bKDF6V5IzTo=", + "ocDSzYTKRxc=", + "x7pY9qZs+ww=", + "pl7yH4GxRFQ=", + "x0yt/kMxerA=", + "2J2lcePHCl0=", + "y+l/7b5BtHw=", + "PJoWBQjHG+8=", + "fFul/ank5Ug=", + "Y2wC5nPoMrw=", + "npK31zqyR9k=", + "2bEpfIKOW8M=", + "2fKoTmSijT0=", + "bLLYYTXiK5M=", + "zd2B7j7hYm8=", + "bQBW+8LXBpU=", + "DaCAag7HYyA=", + "Ls987ixcjsk=", + "RVwvcamX2zQ=", + "pK6dZrXn7tc=", + "KwX2ieEOIM4=", + "KssrhNmE6gQ=", + "ECMbl1rfvkI=", + "mWm3w129yYA=", + "T5TGEqorPA0=", + "C5NyNd3cL+M=", + "IN9qoUwnjl4=", + "qWHwM+Cwsnw=", + "MjVTRJBTTnE=", + "elVHZwI2XCU=", + "+9FSiKk7fXI=", + "Ci0AdmLRgx4=", + "0OSPUrD+VPE=", + "zmqEUhSPbw0=", + "1M+NpduwYMw=", + "iTxGjPm3S4c=", + "zDjM6F9PYIA=", + "BIGclaLIwGk=", + "NGduAG2a87k=", + "fpIm6VOnXec=", + "PXWzTCHXINU=", + "CF0dvEe/zEU=", + "EDPq9VN9FBs=", + "tAjCk6bSL5M=", + "ip/VIOG9QqY=", + "TbWAkcq8y0M=", + "0RXV1B5La98=", + "leaGw26oZuc=", + "VclaMVMhpFo=", + "qQtstBDf9Jc=", + "KONtDnAcOy0=", + "Wl4HOBTvK/Q=", + "+7pNvIZg3Fc=", + "TBn/l3NsyPg=", + "HLL52HhsHGg=", + "RmAB3vLLhWo=", + "N9x9vEZ2fPU=", + "qDuKIhch5f0=", + "2ORdTBzlKco=", + "QIlfJESQTCQ=", + "CrkmaOSPafE=", + "Ytgd0ScwB00=", + "MQFZ4YH3pw8=", + "OUxmL9js4DU=", + "+K4P8h5TqAg=", + "hGNfri2SzJE=", + "B9iRqTncc5U=", + "nEKmWZ75XcQ=", + "XPV5D6izRXk=", + "qlRRw8u4FPc=", + "60y/MYC7xzo=", + "2sxy6PueHq4=", + "XSlCJFxSxIQ=", + "KZcoFOZsArA=", + "y9+jCTKPB8U=", + "gZ8axkqf1gs=", + "jFtqLKJ1B8g=", + "KmD8ngIQNVE=", + "Sz8WZKdGgZ4=", + "Kk/VI45ftPA=", + "SE+6yhTVW88=", + "A/K6mCMMTEM=", + "k1CKfI5Z6Ts=", + "xN144MqXL1o=", + "J3wueY7hFUA=", + "JqRgmBk8WVk=", + "bGk7w5/T5ow=", + "3lJGKmoswBI=", + "g1/d5UgqoGE=", + "Jc0cnsXz3fo=", + "vGxWtpicBnw=", + "XobVeJMz94g=", + "TuCK/UVOHOc=", + "GwZy2YmjNdc=", + "zxgOFDpX5PM=", + "wMUL1rXGiFU=", + "aokk0zAKxqw=", + "pub5+5x7WKs=", + "0pzgjTY0KOA=", + "pSX8z9KMKy8=", + "GSx7GUS4Kpo=" + ], + "Soroban operation source created and removed in classic phase|protocol version 21" : + [ + "bKDF6V5IzTo=", + "ocDSzYTKRxc=", + "x7pY9qZs+ww=", + "pl7yH4GxRFQ=", + "x0yt/kMxerA=", + "2J2lcePHCl0=", + "y+l/7b5BtHw=", + "PJoWBQjHG+8=", + "fFul/ank5Ug=", + "Y2wC5nPoMrw=", + "npK31zqyR9k=", + "2bEpfIKOW8M=", + "2fKoTmSijT0=", + "bLLYYTXiK5M=", + "zd2B7j7hYm8=", + "bQBW+8LXBpU=", + "DaCAag7HYyA=", + "Ls987ixcjsk=", + "RVwvcamX2zQ=", + "pK6dZrXn7tc=", + "KwX2ieEOIM4=", + "KssrhNmE6gQ=", + "ECMbl1rfvkI=", + "mWm3w129yYA=", + "T5TGEqorPA0=", + "C5NyNd3cL+M=", + "IN9qoUwnjl4=", + "qWHwM+Cwsnw=", + "MjVTRJBTTnE=", + "elVHZwI2XCU=", + "+9FSiKk7fXI=", + "Ci0AdmLRgx4=", + "0OSPUrD+VPE=", + "zmqEUhSPbw0=", + "1M+NpduwYMw=", + "iTxGjPm3S4c=", + "zDjM6F9PYIA=", + "BIGclaLIwGk=", + "NGduAG2a87k=", + "fpIm6VOnXec=", + "PXWzTCHXINU=", + "CF0dvEe/zEU=", + "EDPq9VN9FBs=", + "tAjCk6bSL5M=", + "ip/VIOG9QqY=", + "TbWAkcq8y0M=", + "0RXV1B5La98=", + "leaGw26oZuc=", + "VclaMVMhpFo=", + "qQtstBDf9Jc=", + "KONtDnAcOy0=", + "Wl4HOBTvK/Q=", + "+7pNvIZg3Fc=", + "TBn/l3NsyPg=", + "HLL52HhsHGg=", + "RmAB3vLLhWo=", + "N9x9vEZ2fPU=", + "qDuKIhch5f0=", + "2ORdTBzlKco=", + "QIlfJESQTCQ=", + "CrkmaOSPafE=", + "Ytgd0ScwB00=", + "MQFZ4YH3pw8=", + "OUxmL9js4DU=", + "+K4P8h5TqAg=", + "hGNfri2SzJE=", + "B9iRqTncc5U=", + "nEKmWZ75XcQ=", + "XPV5D6izRXk=", + "qlRRw8u4FPc=", + "60y/MYC7xzo=", + "2sxy6PueHq4=", + "XSlCJFxSxIQ=", + "KZcoFOZsArA=", + "y9+jCTKPB8U=", + "gZ8axkqf1gs=", + "jFtqLKJ1B8g=", + "KmD8ngIQNVE=", + "Sz8WZKdGgZ4=", + "Kk/VI45ftPA=", + "SE+6yhTVW88=", + "A/K6mCMMTEM=", + "k1CKfI5Z6Ts=", + "xN144MqXL1o=", + "J3wueY7hFUA=", + "JqRgmBk8WVk=", + "bGk7w5/T5ow=", + "3lJGKmoswBI=", + "g1/d5UgqoGE=", + "Jc0cnsXz3fo=", + "vGxWtpicBnw=", + "XobVeJMz94g=", + "TuCK/UVOHOc=", + "GwZy2YmjNdc=", + "zxgOFDpX5PM=", + "wMUL1rXGiFU=", + "aokk0zAKxqw=", + "pub5+5x7WKs=", + "0pzgjTY0KOA=", + "pSX8z9KMKy8=", + "GSx7GUS4Kpo=" + ], + "Soroban operation source created and removed in classic phase|protocol version 22" : + [ + "bKDF6V5IzTo=", + "5ayMpvekkrI=", + "KpwqxixB1QU=", + "ninzTyfpD8c=", + "0xhX4klidW0=", + "DriP1FYyxvU=", + "syrbRtKc6Og=", + "s7cRiScIDRs=", + "ieMtr3xVwzs=", + "84z/mwe7bLw=", + "bolWl1e2MiI=", + "gSe0PUmaBeE=", + "XWGUN5oRCLQ=", + "giqBXEVckLs=", + "7tc351zel1s=", + "5q0dPSZe6xs=", + "108jh0FFUwQ=", + "YWPZ3Z0AALE=", + "NhbQs97HRHg=", + "4dsyL5+6R3c=", + "/i24ku1BXIk=", + "Dx/7Y1hH1JM=", + "2TqSGPO22xI=", + "5/Z6E0KBrqg=", + "ViUuIKaofeI=", + "leJeeGnjaUY=", + "3CphD5FSwJM=", + "+iy3NPt3ytA=", + "R/VTFpMVli4=", + "y+x7zHxNBmA=", + "4Yi2qwwZIa8=", + "/czKal/hKLc=", + "wCzZUJdypmU=", + "OUQvX9unks8=", + "blcnSidcFAA=", + "iKzCzPo0d6E=", + "wlGGD9kFHsU=", + "usj4INAIQLE=", + "KYhzuloANJg=", + "yBH0FljHOAE=", + "2pEDdVBCPUg=", + "RLQSuE0VRKQ=", + "ltRb1/FUQ9I=", + "eCwc/WSUNCw=", + "l2jIldD5lKI=", + "3GhYy8sX54Q=", + "LcaC2CLknZo=", + "RSb9KWtnQm8=", + "pmfIWlBW6iA=", + "/x4WW5L+tCQ=", + "5fkBtnXRe/0=", + "z62MBXihCyY=", + "CNZp6sFSoXM=", + "ZGfMkEu8Ulw=", + "gxsZCR7REC4=", + "FzKKFViimiQ=", + "2fjvelCaJrE=", + "D6jj6tAnifM=", + "y6I8zVgn67I=", + "fFxwT4onCuo=", + "zmTIbczXn0k=", + "MiTslt8iyzM=", + "jfpyVY+vrMU=", + "azA+s6oxbOg=", + "ZmUPbn7/xc0=", + "ZucccJTapDk=", + "ieWc2QQjYwg=", + "iFmCgHZLhRI=", + "4kpdCiyd6+U=", + "zkWAzUNq6g0=", + "KlkrtrwMZSA=", + "GSXS/naFC7o=", + "UwQSKeqWeuE=", + "FBOP79OXINA=", + "EcchsVBcwjA=", + "2C41h+WmaFc=", + "GstNub02AMU=", + "YNufYkDHgA8=", + "JpAFUvNARFM=", + "jPlMpkSbnnk=", + "lV1IdI9sdOI=", + "GftzwB+pCTQ=", + "hR5d6pVHc40=", + "qLHKxSvGU3E=", + "t721A004I+I=", + "HGtmt02Q6JU=", + "iaQzSi66wcs=", + "rbowyW4jCBs=", + "WJs4iuxCdaU=", + "CGmvdBp/5zs=", + "AMzWei96FSc=", + "G5oFpONpPZ0=", + "mnUDr5XOkiQ=", + "UBrHhLuwCS4=", + "tXDs520pIXI=", + "0gIZ9k20dos=", + "sb6iULDIZIk=", + "/9TZzHvXMJE=", + "U6/5/AUYgvg=", + "xIdb9LXLdE0=", + "LXkHFxv8xCI=" + ], + "Soroban operation source created and removed in classic phase|protocol version 23" : + [ + "+cR3oq2qY0I=", + "nz9v1PzpgfI=", + "hohUpT/ADqk=", + "bvjRdiFGfTM=", + "fj7GNFRwzCo=", + "nXkts5zEKgU=", + "ZiQQXHUPS5U=", + "TC5BKqdd+B4=", + "WXaQReLYO5k=", + "LPFg+MEaSQg=", + "Asgvsb6w7Q0=", + "wBJrQJNAkmE=", + "wrjwucM/Zow=", + "e4novqniZ+g=", + "Ibm21qxpI7s=", + "UextlVZsjnM=", + "0n7dMegdZ3A=", + "11XOGuZ3Xug=", + "WV1Ho30vGvc=", + "SnZLQYvZxfA=", + "M5BZn04JJsE=", + "uMeTcfXMq5A=", + "ziO+HFD3yYY=", + "kGjdPxb4AWs=", + "lpn9djEUn2M=", + "baWzcJ+nmdg=", + "UF9UKXHjJDc=", + "y+4FEa0UPZo=", + "uqFChe3y8rQ=", + "WZZHQawuopM=", + "76Tytga3SWQ=", + "oBXvRd8lj7E=", + "2UIvJMrAYkA=", + "Lu4HE/7VmrU=", + "jax2QwuMLvA=", + "icIkd6qRbPg=", + "KtZfjBYf/V8=", + "huqkxOC2LoA=", + "Jt3tgC+PClI=", + "+UcB9Bo0/hg=", + "zJRsdNMwMAc=", + "MLrMqsvOziE=", + "6vK4A0eFd9c=", + "/dBnJEv5mug=", + "T1D/fXHUY8k=", + "wbI5JOgzavw=", + "saayh6lFoy8=", + "1zCrRETesEE=", + "4aeZ3nDW2H8=", + "2EVgJD6hMxE=", + "0HYOxKmFbXc=", + "2GH3CCviOcs=", + "9kcvbtcyje8=", + "tPZwrweWQ8c=", + "bujRoPDgmrM=", + "1VayL7z/03M=", + "WzdN95wnWC4=", + "cOk9uPy8kSQ=", + "0yMEY5GgOiw=", + "80ul4iYlg1A=", + "Kvi1c6UeFIs=", + "M+BKIBuPOS4=", + "Edzb65HK+ao=", + "xNFD7cNA9PE=", + "+3bDFSiTswE=", + "x43oIP5QKZ0=", + "T1z4oGc8vqc=", + "mlW6FqrcYSI=", + "hQEjDayPI9E=", + "C1hgh4vaYvk=", + "rm96fjiAVTE=", + "C5N7gq8301Q=", + "v4o9l1ZMoD0=", + "gdJY9xf3I/I=", + "0FvLTFyx56c=", + "RihwpLL/n/E=", + "Oo2rLuCHGr4=", + "ldJr6nmpvUU=", + "4EErS4HHw7k=", + "oPYYvxcsZY4=", + "Jzmx0gWrqGQ=", + "siQ/3Hh+++U=", + "Q2Q6XWtaQCQ=", + "Ot03scyos0k=", + "rOcJh/4Ez/Y=", + "dKxQ91Mrvn8=", + "LBpIyth3wYk=", + "wmV5IzZY1pM=", + "qIRuVOi6tQM=", + "k2ZdBvYWWi8=", + "wNwIp33jJMI=", + "Ma1rDLoDtvA=", + "XpM0H5kfBLs=", + "xlufJjbEuYg=", + "TFeOtOGRmt8=", + "Eclf3i5w7gg=", + "5aKvPQAX7tE=", + "GLxznahSj+E=", + "4L5PdJ7n/qo=", + "i23Oql77Y6U=", + "cOJDuiZkHlg=" + ], + "Soroban operation source created and removed in classic phase|protocol version 24" : + [ + "+cR3oq2qY0I=", + "nz9v1PzpgfI=", + "hohUpT/ADqk=", + "bvjRdiFGfTM=", + "fj7GNFRwzCo=", + "nXkts5zEKgU=", + "ZiQQXHUPS5U=", + "TC5BKqdd+B4=", + "WXaQReLYO5k=", + "LPFg+MEaSQg=", + "Asgvsb6w7Q0=", + "wBJrQJNAkmE=", + "wrjwucM/Zow=", + "e4novqniZ+g=", + "Ibm21qxpI7s=", + "UextlVZsjnM=", + "0n7dMegdZ3A=", + "11XOGuZ3Xug=", + "WV1Ho30vGvc=", + "SnZLQYvZxfA=", + "M5BZn04JJsE=", + "uMeTcfXMq5A=", + "ziO+HFD3yYY=", + "kGjdPxb4AWs=", + "lpn9djEUn2M=", + "baWzcJ+nmdg=", + "UF9UKXHjJDc=", + "y+4FEa0UPZo=", + "uqFChe3y8rQ=", + "WZZHQawuopM=", + "76Tytga3SWQ=", + "oBXvRd8lj7E=", + "2UIvJMrAYkA=", + "Lu4HE/7VmrU=", + "jax2QwuMLvA=", + "icIkd6qRbPg=", + "KtZfjBYf/V8=", + "huqkxOC2LoA=", + "Jt3tgC+PClI=", + "+UcB9Bo0/hg=", + "zJRsdNMwMAc=", + "MLrMqsvOziE=", + "6vK4A0eFd9c=", + "/dBnJEv5mug=", + "T1D/fXHUY8k=", + "wbI5JOgzavw=", + "saayh6lFoy8=", + "1zCrRETesEE=", + "4aeZ3nDW2H8=", + "2EVgJD6hMxE=", + "0HYOxKmFbXc=", + "2GH3CCviOcs=", + "9kcvbtcyje8=", + "tPZwrweWQ8c=", + "bujRoPDgmrM=", + "1VayL7z/03M=", + "WzdN95wnWC4=", + "cOk9uPy8kSQ=", + "0yMEY5GgOiw=", + "80ul4iYlg1A=", + "Kvi1c6UeFIs=", + "M+BKIBuPOS4=", + "Edzb65HK+ao=", + "xNFD7cNA9PE=", + "+3bDFSiTswE=", + "x43oIP5QKZ0=", + "T1z4oGc8vqc=", + "mlW6FqrcYSI=", + "hQEjDayPI9E=", + "C1hgh4vaYvk=", + "rm96fjiAVTE=", + "C5N7gq8301Q=", + "v4o9l1ZMoD0=", + "gdJY9xf3I/I=", + "0FvLTFyx56c=", + "RihwpLL/n/E=", + "Oo2rLuCHGr4=", + "ldJr6nmpvUU=", + "4EErS4HHw7k=", + "oPYYvxcsZY4=", + "Jzmx0gWrqGQ=", + "siQ/3Hh+++U=", + "Q2Q6XWtaQCQ=", + "Ot03scyos0k=", + "rOcJh/4Ez/Y=", + "dKxQ91Mrvn8=", + "LBpIyth3wYk=", + "wmV5IzZY1pM=", + "qIRuVOi6tQM=", + "k2ZdBvYWWi8=", + "wNwIp33jJMI=", + "Ma1rDLoDtvA=", + "XpM0H5kfBLs=", + "xlufJjbEuYg=", + "TFeOtOGRmt8=", + "Eclf3i5w7gg=", + "5aKvPQAX7tE=", + "GLxznahSj+E=", + "4L5PdJ7n/qo=", + "i23Oql77Y6U=", + "cOJDuiZkHlg=" + ], + "Soroban operation source created and removed in classic phase|protocol version 25" : + [ + "+cR3oq2qY0I=", + "nz9v1PzpgfI=", + "hohUpT/ADqk=", + "bvjRdiFGfTM=", + "fj7GNFRwzCo=", + "nXkts5zEKgU=", + "ZiQQXHUPS5U=", + "TC5BKqdd+B4=", + "WXaQReLYO5k=", + "LPFg+MEaSQg=", + "Asgvsb6w7Q0=", + "wBJrQJNAkmE=", + "wrjwucM/Zow=", + "e4novqniZ+g=", + "Ibm21qxpI7s=", + "UextlVZsjnM=", + "0n7dMegdZ3A=", + "11XOGuZ3Xug=", + "WV1Ho30vGvc=", + "SnZLQYvZxfA=", + "M5BZn04JJsE=", + "uMeTcfXMq5A=", + "ziO+HFD3yYY=", + "kGjdPxb4AWs=", + "lpn9djEUn2M=", + "baWzcJ+nmdg=", + "UF9UKXHjJDc=", + "y+4FEa0UPZo=", + "uqFChe3y8rQ=", + "WZZHQawuopM=", + "76Tytga3SWQ=", + "oBXvRd8lj7E=", + "2UIvJMrAYkA=", + "Lu4HE/7VmrU=", + "jax2QwuMLvA=", + "icIkd6qRbPg=", + "KtZfjBYf/V8=", + "huqkxOC2LoA=", + "Jt3tgC+PClI=", + "+UcB9Bo0/hg=", + "zJRsdNMwMAc=", + "MLrMqsvOziE=", + "6vK4A0eFd9c=", + "/dBnJEv5mug=", + "T1D/fXHUY8k=", + "wbI5JOgzavw=", + "saayh6lFoy8=", + "1zCrRETesEE=", + "4aeZ3nDW2H8=", + "2EVgJD6hMxE=", + "0HYOxKmFbXc=", + "2GH3CCviOcs=", + "9kcvbtcyje8=", + "tPZwrweWQ8c=", + "bujRoPDgmrM=", + "1VayL7z/03M=", + "WzdN95wnWC4=", + "cOk9uPy8kSQ=", + "0yMEY5GgOiw=", + "80ul4iYlg1A=", + "Kvi1c6UeFIs=", + "M+BKIBuPOS4=", + "Edzb65HK+ao=", + "xNFD7cNA9PE=", + "+3bDFSiTswE=", + "x43oIP5QKZ0=", + "T1z4oGc8vqc=", + "mlW6FqrcYSI=", + "hQEjDayPI9E=", + "C1hgh4vaYvk=", + "rm96fjiAVTE=", + "C5N7gq8301Q=", + "v4o9l1ZMoD0=", + "gdJY9xf3I/I=", + "0FvLTFyx56c=", + "RihwpLL/n/E=", + "Oo2rLuCHGr4=", + "ldJr6nmpvUU=", + "4EErS4HHw7k=", + "oPYYvxcsZY4=", + "Jzmx0gWrqGQ=", + "siQ/3Hh+++U=", + "Q2Q6XWtaQCQ=", + "Ot03scyos0k=", + "rOcJh/4Ez/Y=", + "dKxQ91Mrvn8=", + "LBpIyth3wYk=", + "wmV5IzZY1pM=", + "qIRuVOi6tQM=", + "k2ZdBvYWWi8=", + "wNwIp33jJMI=", + "Ma1rDLoDtvA=", + "XpM0H5kfBLs=", + "xlufJjbEuYg=", + "TFeOtOGRmt8=", + "Eclf3i5w7gg=", + "5aKvPQAX7tE=", + "GLxznahSj+E=", + "4L5PdJ7n/qo=", + "i23Oql77Y6U=", + "cOJDuiZkHlg=" + ], + "Soroban operation source created and removed in classic phase|protocol version 26" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban operation source created and removed in classic phase|protocol version 27" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban operation source created and removed in classic phase|protocol version 28" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 20" : + [ + "bKDF6V5IzTo=", + "1YoRQpENTWE=", + "dYRpGqAlBDs=", + "pBZtiu3OJ7M=", + "IBgPoEf6H8s=", + "oUoLY4Gok3Q=", + "V6Ly+If+Kv8=", + "Cm3CkzL2syQ=", + "PhFE8ATy/4g=", + "FUBVEeXefug=", + "+hKh+5+Thsw=", + "BlhftaBlm9g=", + "ZS/mQlezUuE=", + "IbUGZ7407UU=", + "L1cDvhFQE80=", + "D+6b+5+H1ss=", + "j7SY2fAK6fU=", + "/r+khMp1/8Y=", + "7VBKTQNpMeI=", + "6jTXkdr5rPc=", + "6T+YCvYp8H0=", + "z0+71j6HB28=", + "Z8Ghz71bsAw=", + "U5VtQDYCcYU=", + "zvN90WCRkO0=", + "paei0bhsSsw=", + "S28j8kgREkE=", + "fvzFffOIdO4=", + "j+BP1ibsAFw=", + "7HmBrxtECbA=", + "rV7Gs+BCjiE=", + "JePxrvqNzs4=", + "p9TVAXdLwmc=", + "RxrYYjg9xds=", + "O8s2BCTv5DM=", + "+4b9MzEXa20=", + "SZI1PxuLtVE=", + "SvbVLfk38Jk=", + "5/k+BSJIhF4=", + "ybLgnPo+8nk=", + "9VpMR7mf4Po=", + "0oYz7Ehlm6A=", + "ZFeZS74f/4w=", + "u78kYC7n3/Q=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 21" : + [ + "bKDF6V5IzTo=", + "1YoRQpENTWE=", + "dYRpGqAlBDs=", + "pBZtiu3OJ7M=", + "IBgPoEf6H8s=", + "oUoLY4Gok3Q=", + "V6Ly+If+Kv8=", + "Cm3CkzL2syQ=", + "PhFE8ATy/4g=", + "FUBVEeXefug=", + "+hKh+5+Thsw=", + "BlhftaBlm9g=", + "ZS/mQlezUuE=", + "IbUGZ7407UU=", + "L1cDvhFQE80=", + "D+6b+5+H1ss=", + "j7SY2fAK6fU=", + "/r+khMp1/8Y=", + "7VBKTQNpMeI=", + "6jTXkdr5rPc=", + "6T+YCvYp8H0=", + "z0+71j6HB28=", + "Z8Ghz71bsAw=", + "U5VtQDYCcYU=", + "zvN90WCRkO0=", + "paei0bhsSsw=", + "S28j8kgREkE=", + "fvzFffOIdO4=", + "j+BP1ibsAFw=", + "7HmBrxtECbA=", + "rV7Gs+BCjiE=", + "JePxrvqNzs4=", + "p9TVAXdLwmc=", + "RxrYYjg9xds=", + "UIcS2n63svo=", + "5AKz5MKz3EY=", + "mQLIi4/Xnpo=", + "VtBxD9nW620=", + "ceOLSgirQIY=", + "rHzGA3aTfkw=", + "RmAa3HcLZTc=", + "NJfu6kEGL/4=", + "BSMhaTpJB4A=", + "HgIVMbnJQB4=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 22" : + [ + "bKDF6V5IzTo=", + "rR4bN6XbNfA=", + "JS6E860wJVs=", + "IDGsWUzKLBg=", + "nBz425qu8TA=", + "+5Dk5uxx0rE=", + "AKTpav8hbPk=", + "f46MIJNsJ7g=", + "C3nn7+10DbI=", + "uBGgXv+i2FQ=", + "MXG5KnbZNmI=", + "vAOX3fQHjXI=", + "j33yW667WIE=", + "Iy+GcIxksMk=", + "5ssn3tY2daI=", + "jPxDcic4tWY=", + "4ApAZLoEjvA=", + "9beQ0wLBIgo=", + "sDlVuzU/IZY=", + "LK7dyMvS/M4=", + "+fP84720bhs=", + "+6EZ1HEZ7rU=", + "L5nSFfKp2HI=", + "oqlN+7Cc354=", + "dBVQweMckj4=", + "kVTA3XuOok8=", + "ySbms3WjD1k=", + "mxfbAlSuU2A=", + "oIRc9owv+Ng=", + "5dfzdW9W/DU=", + "kh7qum+vOdQ=", + "0/2/o/Y5wvs=", + "jNP2r8hb+wM=", + "+pSYIj4EKGE=", + "NpRJ93HgrYI=", + "irA2wilgrnA=", + "IfCYdVEHN6A=", + "eSJ9dhI6SO8=", + "4+qhdqGn68g=", + "evhjr9oq5cY=", + "bSmOo50CUSQ=", + "IFQf8MX9jWM=", + "hORHjI6CsJs=", + "Is/kbc6knec=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 23" : + [ + "+cR3oq2qY0I=", + "2lu0XZUNpXE=", + "0YkYsN9TXcU=", + "Vudi8oDzW4I=", + "2v7LYECgY2E=", + "4eNmAHnACvY=", + "nsbN8jGC9+c=", + "3kOlGG6S6/Y=", + "BUWt8cXkE5A=", + "4A6ZHTxj8tg=", + "809kpAhSloE=", + "WJKVjCcl7yo=", + "a8oSOyFmNT0=", + "WyI59xx+zTc=", + "YOQgHndQKjA=", + "MsAl1s+BNFQ=", + "nF+LnYavpr0=", + "y9MpYmiN300=", + "nSNpeleCNfI=", + "PSTit18ljrQ=", + "3JCL3JAVKOQ=", + "LPGjbKnCvzE=", + "S8gNPX/DWB0=", + "cIXhb1wrROk=", + "fPIsm2zwFXg=", + "pnW9jsSv/og=", + "Jk4IV8yurg8=", + "dUsPMBubifg=", + "4NKto3sosLY=", + "50doy92gxJs=", + "1Rkqm63AlHw=", + "+LN3x+p008A=", + "+v4Ai/yLXQo=", + "uj+OehxLu2o=", + "XBUW/5qoKUo=", + "zFo4Vc6YmG8=", + "6k8nkchciDY=", + "SFVh7gD5zB8=", + "YsNY30clXRo=", + "aKiRBvxFWOs=", + "yegKP5/2ctg=", + "4WaR3adrld4=", + "b/u7eXDr9mc=", + "5t5NSWs4F3s=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 24" : + [ + "+cR3oq2qY0I=", + "2lu0XZUNpXE=", + "0YkYsN9TXcU=", + "Vudi8oDzW4I=", + "2v7LYECgY2E=", + "4eNmAHnACvY=", + "nsbN8jGC9+c=", + "3kOlGG6S6/Y=", + "BUWt8cXkE5A=", + "4A6ZHTxj8tg=", + "809kpAhSloE=", + "WJKVjCcl7yo=", + "a8oSOyFmNT0=", + "WyI59xx+zTc=", + "YOQgHndQKjA=", + "MsAl1s+BNFQ=", + "nF+LnYavpr0=", + "y9MpYmiN300=", + "nSNpeleCNfI=", + "PSTit18ljrQ=", + "3JCL3JAVKOQ=", + "LPGjbKnCvzE=", + "S8gNPX/DWB0=", + "cIXhb1wrROk=", + "fPIsm2zwFXg=", + "pnW9jsSv/og=", + "Jk4IV8yurg8=", + "dUsPMBubifg=", + "4NKto3sosLY=", + "50doy92gxJs=", + "1Rkqm63AlHw=", + "+LN3x+p008A=", + "+v4Ai/yLXQo=", + "uj+OehxLu2o=", + "XBUW/5qoKUo=", + "zFo4Vc6YmG8=", + "6k8nkchciDY=", + "SFVh7gD5zB8=", + "YsNY30clXRo=", + "aKiRBvxFWOs=", + "yegKP5/2ctg=", + "4WaR3adrld4=", + "b/u7eXDr9mc=", + "5t5NSWs4F3s=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 25" : + [ + "+cR3oq2qY0I=", + "2lu0XZUNpXE=", + "0YkYsN9TXcU=", + "Vudi8oDzW4I=", + "2v7LYECgY2E=", + "4eNmAHnACvY=", + "nsbN8jGC9+c=", + "3kOlGG6S6/Y=", + "BUWt8cXkE5A=", + "4A6ZHTxj8tg=", + "809kpAhSloE=", + "WJKVjCcl7yo=", + "a8oSOyFmNT0=", + "WyI59xx+zTc=", + "YOQgHndQKjA=", + "MsAl1s+BNFQ=", + "nF+LnYavpr0=", + "y9MpYmiN300=", + "nSNpeleCNfI=", + "PSTit18ljrQ=", + "3JCL3JAVKOQ=", + "LPGjbKnCvzE=", + "S8gNPX/DWB0=", + "cIXhb1wrROk=", + "fPIsm2zwFXg=", + "pnW9jsSv/og=", + "Jk4IV8yurg8=", + "dUsPMBubifg=", + "4NKto3sosLY=", + "50doy92gxJs=", + "1Rkqm63AlHw=", + "+LN3x+p008A=", + "+v4Ai/yLXQo=", + "uj+OehxLu2o=", + "XBUW/5qoKUo=", + "zFo4Vc6YmG8=", + "6k8nkchciDY=", + "SFVh7gD5zB8=", + "YsNY30clXRo=", + "aKiRBvxFWOs=", + "yegKP5/2ctg=", + "4WaR3adrld4=", + "b/u7eXDr9mc=", + "5t5NSWs4F3s=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 26" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 27" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 28" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], "Stellar asset contract transfer with CAP-67 address types" : [ "+cR3oq2qY0I=", @@ -2063,6 +3422,492 @@ "classic payment to soroban fee bump account|protocol version 26" : [ "NTGGdj1offM=", "aHlgICbAAQs=", "1S4Ni3f8c/0=", "wiDaeJY86QQ=" ], "classic payment to soroban fee bump account|protocol version 27" : [ "NTGGdj1offM=", "aHlgICbAAQs=", "1S4Ni3f8c/0=", "wiDaeJY86QQ=" ], "classic payment to soroban fee bump account|protocol version 28" : [ "NTGGdj1offM=", "aHlgICbAAQs=", "1S4Ni3f8c/0=", "wiDaeJY86QQ=" ], + "classic phase bumps sequence of Soroban tx source account|protocol version 20" : + [ + "bKDF6V5IzTo=", + "rykv5BBzl1k=", + "F6F6vr15q1A=", + "4tvlkZFFRX4=", + "HgDUNiXg80U=", + "18FzAAQdQ70=", + "IHdIHFYrMgg=", + "t89GweXHC1I=", + "apCV+hCbZl8=", + "S29r/lxDh70=", + "UDozttyLWyI=", + "QILccI+f94s=", + "4O7/p0uxawc=", + "XwTloGeBtpc=", + "umjGbr+xtOs=", + "BcAvVWg4Jmw=", + "iHA3lSwayZI=", + "MlkJ5OnVDJQ=", + "2duFeYTKLWw=", + "eOmcEBMQdlE=", + "+eyKPmg9JrE=", + "rCZG4VEVwT0=", + "SGL4HT2uYfA=", + "RjhND1kQks0=", + "SMsTDaoGh5s=", + "L0c/XCA0c6E=", + "1YZC+osAer4=", + "vkAUGnoDIWU=", + "YWbsWj8wD90=", + "E99WgsmZhpk=", + "POLMhqkKPgM=", + "ZXG+1zagaV8=", + "Tifr/sJJRZY=", + "jgRoiQihkdw=", + "lFTHEDTm6z4=", + "8PWngVNc9DA=", + "Vm4VrTdRe6M=", + "eZc8pI4CZao=", + "ByEpJiDhfdA=", + "RYE+nBNdNk4=", + "ljCgxBXavyk=", + "KZdTXZqOc9I=", + "ApLOH3i1dlk=", + "wT3WFcxv7ME=", + "9dt+A5yy5C4=", + "v142Cwj8ods=", + "UZD6laODN4k=", + "bcwT4P0WJEM=", + "CNB2siN27BQ=", + "80Aedxva4PY=", + "b6+dMGM8F6I=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 21" : + [ + "bKDF6V5IzTo=", + "rykv5BBzl1k=", + "F6F6vr15q1A=", + "4tvlkZFFRX4=", + "HgDUNiXg80U=", + "18FzAAQdQ70=", + "IHdIHFYrMgg=", + "t89GweXHC1I=", + "apCV+hCbZl8=", + "S29r/lxDh70=", + "UDozttyLWyI=", + "QILccI+f94s=", + "4O7/p0uxawc=", + "XwTloGeBtpc=", + "umjGbr+xtOs=", + "BcAvVWg4Jmw=", + "iHA3lSwayZI=", + "MlkJ5OnVDJQ=", + "2duFeYTKLWw=", + "eOmcEBMQdlE=", + "+eyKPmg9JrE=", + "rCZG4VEVwT0=", + "SGL4HT2uYfA=", + "RjhND1kQks0=", + "SMsTDaoGh5s=", + "L0c/XCA0c6E=", + "1YZC+osAer4=", + "vkAUGnoDIWU=", + "YWbsWj8wD90=", + "E99WgsmZhpk=", + "POLMhqkKPgM=", + "ZXG+1zagaV8=", + "Tifr/sJJRZY=", + "jgRoiQihkdw=", + "lFTHEDTm6z4=", + "8PWngVNc9DA=", + "Vm4VrTdRe6M=", + "eZc8pI4CZao=", + "ByEpJiDhfdA=", + "RYE+nBNdNk4=", + "ljCgxBXavyk=", + "KZdTXZqOc9I=", + "ApLOH3i1dlk=", + "wT3WFcxv7ME=", + "9dt+A5yy5C4=", + "v142Cwj8ods=", + "UZD6laODN4k=", + "bcwT4P0WJEM=", + "CNB2siN27BQ=", + "80Aedxva4PY=", + "b6+dMGM8F6I=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 22" : + [ + "bKDF6V5IzTo=", + "KauhmrCg434=", + "i2MP9cdPoQA=", + "6eUlCy7NfA8=", + "dv4BVugo9Pg=", + "GlNEXON53WM=", + "5ji87LopYYw=", + "xR65gTZpjQg=", + "ggE2L5NcQm0=", + "bYzJySm4pJw=", + "+J+y9jDJ/Os=", + "BJdhJgqrUvM=", + "Trqgj75G5qQ=", + "ROga9zur2h4=", + "W1o7OisVZ6M=", + "B2myGpMGbks=", + "PUkvsmqFwW0=", + "LgtPg7GlRuk=", + "DOdX56mpKUA=", + "CTbGbLivHyQ=", + "8gJgm7hCCDk=", + "i3ieaS2MRTQ=", + "S4k1pw8IB0o=", + "ZWY8Qtj2yvo=", + "sjKfSsXN0TY=", + "8LdOzje9Jvk=", + "rbMHcrEsWQI=", + "uAQLz05EF7c=", + "DV+jLYgMzyM=", + "sah3Y6KWgwM=", + "kTdgHIVAjbU=", + "d1nR73Vx9+w=", + "mcfXbs12gZY=", + "vicbAJ0rNlE=", + "F4rgNeQ8IRs=", + "E2Z/buvl4So=", + "VMLALQO+jFw=", + "LTR8SHIw5wQ=", + "ak0x6FJy7NE=", + "carMrGgUz0k=", + "Ae7xAPoccL0=", + "SN1v0r7HvJc=", + "Y8XHtnfJ+3I=", + "dau45GFv2C4=", + "03G7p4D2srI=", + "MaHEhKl/EG8=", + "KdQvPSPGfCM=", + "pIZUsigzx1A=", + "1ytaxBFTWaQ=", + "iIt0HAhbgR8=", + "744WeiXt6Lo=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 23" : + [ + "+cR3oq2qY0I=", + "xkbxRHKhRz4=", + "0aeGvP7QhNY=", + "qEJFG6MlRu8=", + "XsgH1c4Y8jE=", + "wncOj5kDqQk=", + "mCjhH83YP1E=", + "wo9cdhwcJxQ=", + "8mY+Hh264uc=", + "XsZ8hZZjnZc=", + "m2hJ7TZM74k=", + "dwFqcSZBTmA=", + "gIWzcqTqr6I=", + "2OqlMksDyek=", + "vTCH8GUcwxk=", + "UoLY7lwUbng=", + "brZEf0Qd6Uk=", + "HsXv1mQ86v0=", + "1CJ5MhbEknI=", + "ONTM2yLjg8c=", + "doJkTlm07Q0=", + "KPHoMvuWIlY=", + "/ti+01USiNc=", + "3cI3odnQfmk=", + "iaHUOftB+Uw=", + "OR7cDRnC/F4=", + "PRT9Xl9zkSw=", + "4DPNrmvKB2M=", + "2UTxLEm41VY=", + "FpZZf7OgA1Y=", + "jThf3ILflPk=", + "AHkcqIASpfE=", + "SHVlFzsVemA=", + "i52vHXLCMI8=", + "G/XCJvs11Qs=", + "K0jLgQjq/dM=", + "sCRVpE+JPrg=", + "/og8kIzS74Y=", + "KtLG25hvCe8=", + "y82NDXppduU=", + "NL7L5pMxgVA=", + "ARKssIQ+5d4=", + "NI9WByR7em8=", + "M87swFclhmk=", + "XgoXLGJ95dk=", + "eFL6eJUV78Q=", + "0ycIKH0BnjM=", + "QUBP3y7EVgY=", + "gtKDQKoYDvc=", + "F976AZv+d4c=", + "6ECCc6Afj/Q=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 24" : + [ + "+cR3oq2qY0I=", + "xkbxRHKhRz4=", + "0aeGvP7QhNY=", + "qEJFG6MlRu8=", + "XsgH1c4Y8jE=", + "wncOj5kDqQk=", + "mCjhH83YP1E=", + "wo9cdhwcJxQ=", + "8mY+Hh264uc=", + "XsZ8hZZjnZc=", + "m2hJ7TZM74k=", + "dwFqcSZBTmA=", + "gIWzcqTqr6I=", + "2OqlMksDyek=", + "vTCH8GUcwxk=", + "UoLY7lwUbng=", + "brZEf0Qd6Uk=", + "HsXv1mQ86v0=", + "1CJ5MhbEknI=", + "ONTM2yLjg8c=", + "doJkTlm07Q0=", + "KPHoMvuWIlY=", + "/ti+01USiNc=", + "3cI3odnQfmk=", + "iaHUOftB+Uw=", + "OR7cDRnC/F4=", + "PRT9Xl9zkSw=", + "4DPNrmvKB2M=", + "2UTxLEm41VY=", + "FpZZf7OgA1Y=", + "jThf3ILflPk=", + "AHkcqIASpfE=", + "SHVlFzsVemA=", + "i52vHXLCMI8=", + "G/XCJvs11Qs=", + "K0jLgQjq/dM=", + "sCRVpE+JPrg=", + "/og8kIzS74Y=", + "KtLG25hvCe8=", + "y82NDXppduU=", + "NL7L5pMxgVA=", + "ARKssIQ+5d4=", + "NI9WByR7em8=", + "M87swFclhmk=", + "XgoXLGJ95dk=", + "eFL6eJUV78Q=", + "0ycIKH0BnjM=", + "QUBP3y7EVgY=", + "gtKDQKoYDvc=", + "F976AZv+d4c=", + "6ECCc6Afj/Q=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 25" : + [ + "+cR3oq2qY0I=", + "xkbxRHKhRz4=", + "0aeGvP7QhNY=", + "qEJFG6MlRu8=", + "XsgH1c4Y8jE=", + "wncOj5kDqQk=", + "mCjhH83YP1E=", + "wo9cdhwcJxQ=", + "8mY+Hh264uc=", + "XsZ8hZZjnZc=", + "m2hJ7TZM74k=", + "dwFqcSZBTmA=", + "gIWzcqTqr6I=", + "2OqlMksDyek=", + "vTCH8GUcwxk=", + "UoLY7lwUbng=", + "brZEf0Qd6Uk=", + "HsXv1mQ86v0=", + "1CJ5MhbEknI=", + "ONTM2yLjg8c=", + "doJkTlm07Q0=", + "KPHoMvuWIlY=", + "/ti+01USiNc=", + "3cI3odnQfmk=", + "iaHUOftB+Uw=", + "OR7cDRnC/F4=", + "PRT9Xl9zkSw=", + "4DPNrmvKB2M=", + "2UTxLEm41VY=", + "FpZZf7OgA1Y=", + "jThf3ILflPk=", + "AHkcqIASpfE=", + "SHVlFzsVemA=", + "i52vHXLCMI8=", + "G/XCJvs11Qs=", + "K0jLgQjq/dM=", + "sCRVpE+JPrg=", + "/og8kIzS74Y=", + "KtLG25hvCe8=", + "y82NDXppduU=", + "NL7L5pMxgVA=", + "ARKssIQ+5d4=", + "NI9WByR7em8=", + "M87swFclhmk=", + "XgoXLGJ95dk=", + "eFL6eJUV78Q=", + "0ycIKH0BnjM=", + "QUBP3y7EVgY=", + "gtKDQKoYDvc=", + "F976AZv+d4c=", + "6ECCc6Afj/Q=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 26" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 27" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 28" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], "classic phase bumps sequence of soroban source account|protocol version 20" : [ "NTGGdj1offM=", "FVbub/Ss/Xg=", "9Rpfyyb4ewI=" ], "classic phase bumps sequence of soroban source account|protocol version 21" : [ "NTGGdj1offM=", "FVbub/Ss/Xg=", "9Rpfyyb4ewI=" ], "classic phase bumps sequence of soroban source account|protocol version 22" : [ "NTGGdj1offM=", "CTLGLR5LLHY=", "xXpwdFz6+Uc=" ], diff --git a/test-tx-meta-baseline-next/InvokeHostFunctionTests.json b/test-tx-meta-baseline-next/InvokeHostFunctionTests.json index 6dc67843f..5c7752e4c 100644 --- a/test-tx-meta-baseline-next/InvokeHostFunctionTests.json +++ b/test-tx-meta-baseline-next/InvokeHostFunctionTests.json @@ -1341,6 +1341,1516 @@ "Soroban non-refundable resource fees are stable|protocol version 27" : [ "+cR3oq2qY0I=" ], "Soroban non-refundable resource fees are stable|protocol version 28" : [ "+cR3oq2qY0I=" ], "Soroban non-refundable resource fees are stable|protocol version 29" : [ "+cR3oq2qY0I=" ], + "Soroban operation source created and removed in classic phase|protocol version 20" : + [ + "bKDF6V5IzTo=", + "ocDSzYTKRxc=", + "x7pY9qZs+ww=", + "pl7yH4GxRFQ=", + "x0yt/kMxerA=", + "2J2lcePHCl0=", + "y+l/7b5BtHw=", + "PJoWBQjHG+8=", + "fFul/ank5Ug=", + "Y2wC5nPoMrw=", + "npK31zqyR9k=", + "2bEpfIKOW8M=", + "2fKoTmSijT0=", + "bLLYYTXiK5M=", + "zd2B7j7hYm8=", + "bQBW+8LXBpU=", + "DaCAag7HYyA=", + "Ls987ixcjsk=", + "RVwvcamX2zQ=", + "pK6dZrXn7tc=", + "KwX2ieEOIM4=", + "KssrhNmE6gQ=", + "ECMbl1rfvkI=", + "mWm3w129yYA=", + "T5TGEqorPA0=", + "C5NyNd3cL+M=", + "IN9qoUwnjl4=", + "qWHwM+Cwsnw=", + "MjVTRJBTTnE=", + "elVHZwI2XCU=", + "+9FSiKk7fXI=", + "Ci0AdmLRgx4=", + "0OSPUrD+VPE=", + "zmqEUhSPbw0=", + "1M+NpduwYMw=", + "iTxGjPm3S4c=", + "zDjM6F9PYIA=", + "BIGclaLIwGk=", + "NGduAG2a87k=", + "fpIm6VOnXec=", + "PXWzTCHXINU=", + "CF0dvEe/zEU=", + "EDPq9VN9FBs=", + "tAjCk6bSL5M=", + "ip/VIOG9QqY=", + "TbWAkcq8y0M=", + "0RXV1B5La98=", + "leaGw26oZuc=", + "VclaMVMhpFo=", + "qQtstBDf9Jc=", + "KONtDnAcOy0=", + "Wl4HOBTvK/Q=", + "+7pNvIZg3Fc=", + "TBn/l3NsyPg=", + "HLL52HhsHGg=", + "RmAB3vLLhWo=", + "N9x9vEZ2fPU=", + "qDuKIhch5f0=", + "2ORdTBzlKco=", + "QIlfJESQTCQ=", + "CrkmaOSPafE=", + "Ytgd0ScwB00=", + "MQFZ4YH3pw8=", + "OUxmL9js4DU=", + "+K4P8h5TqAg=", + "hGNfri2SzJE=", + "B9iRqTncc5U=", + "nEKmWZ75XcQ=", + "XPV5D6izRXk=", + "qlRRw8u4FPc=", + "60y/MYC7xzo=", + "2sxy6PueHq4=", + "XSlCJFxSxIQ=", + "KZcoFOZsArA=", + "y9+jCTKPB8U=", + "gZ8axkqf1gs=", + "jFtqLKJ1B8g=", + "KmD8ngIQNVE=", + "Sz8WZKdGgZ4=", + "Kk/VI45ftPA=", + "SE+6yhTVW88=", + "A/K6mCMMTEM=", + "k1CKfI5Z6Ts=", + "xN144MqXL1o=", + "J3wueY7hFUA=", + "JqRgmBk8WVk=", + "bGk7w5/T5ow=", + "3lJGKmoswBI=", + "g1/d5UgqoGE=", + "Jc0cnsXz3fo=", + "vGxWtpicBnw=", + "XobVeJMz94g=", + "TuCK/UVOHOc=", + "GwZy2YmjNdc=", + "zxgOFDpX5PM=", + "wMUL1rXGiFU=", + "aokk0zAKxqw=", + "pub5+5x7WKs=", + "0pzgjTY0KOA=", + "pSX8z9KMKy8=", + "GSx7GUS4Kpo=" + ], + "Soroban operation source created and removed in classic phase|protocol version 21" : + [ + "bKDF6V5IzTo=", + "ocDSzYTKRxc=", + "x7pY9qZs+ww=", + "pl7yH4GxRFQ=", + "x0yt/kMxerA=", + "2J2lcePHCl0=", + "y+l/7b5BtHw=", + "PJoWBQjHG+8=", + "fFul/ank5Ug=", + "Y2wC5nPoMrw=", + "npK31zqyR9k=", + "2bEpfIKOW8M=", + "2fKoTmSijT0=", + "bLLYYTXiK5M=", + "zd2B7j7hYm8=", + "bQBW+8LXBpU=", + "DaCAag7HYyA=", + "Ls987ixcjsk=", + "RVwvcamX2zQ=", + "pK6dZrXn7tc=", + "KwX2ieEOIM4=", + "KssrhNmE6gQ=", + "ECMbl1rfvkI=", + "mWm3w129yYA=", + "T5TGEqorPA0=", + "C5NyNd3cL+M=", + "IN9qoUwnjl4=", + "qWHwM+Cwsnw=", + "MjVTRJBTTnE=", + "elVHZwI2XCU=", + "+9FSiKk7fXI=", + "Ci0AdmLRgx4=", + "0OSPUrD+VPE=", + "zmqEUhSPbw0=", + "1M+NpduwYMw=", + "iTxGjPm3S4c=", + "zDjM6F9PYIA=", + "BIGclaLIwGk=", + "NGduAG2a87k=", + "fpIm6VOnXec=", + "PXWzTCHXINU=", + "CF0dvEe/zEU=", + "EDPq9VN9FBs=", + "tAjCk6bSL5M=", + "ip/VIOG9QqY=", + "TbWAkcq8y0M=", + "0RXV1B5La98=", + "leaGw26oZuc=", + "VclaMVMhpFo=", + "qQtstBDf9Jc=", + "KONtDnAcOy0=", + "Wl4HOBTvK/Q=", + "+7pNvIZg3Fc=", + "TBn/l3NsyPg=", + "HLL52HhsHGg=", + "RmAB3vLLhWo=", + "N9x9vEZ2fPU=", + "qDuKIhch5f0=", + "2ORdTBzlKco=", + "QIlfJESQTCQ=", + "CrkmaOSPafE=", + "Ytgd0ScwB00=", + "MQFZ4YH3pw8=", + "OUxmL9js4DU=", + "+K4P8h5TqAg=", + "hGNfri2SzJE=", + "B9iRqTncc5U=", + "nEKmWZ75XcQ=", + "XPV5D6izRXk=", + "qlRRw8u4FPc=", + "60y/MYC7xzo=", + "2sxy6PueHq4=", + "XSlCJFxSxIQ=", + "KZcoFOZsArA=", + "y9+jCTKPB8U=", + "gZ8axkqf1gs=", + "jFtqLKJ1B8g=", + "KmD8ngIQNVE=", + "Sz8WZKdGgZ4=", + "Kk/VI45ftPA=", + "SE+6yhTVW88=", + "A/K6mCMMTEM=", + "k1CKfI5Z6Ts=", + "xN144MqXL1o=", + "J3wueY7hFUA=", + "JqRgmBk8WVk=", + "bGk7w5/T5ow=", + "3lJGKmoswBI=", + "g1/d5UgqoGE=", + "Jc0cnsXz3fo=", + "vGxWtpicBnw=", + "XobVeJMz94g=", + "TuCK/UVOHOc=", + "GwZy2YmjNdc=", + "zxgOFDpX5PM=", + "wMUL1rXGiFU=", + "aokk0zAKxqw=", + "pub5+5x7WKs=", + "0pzgjTY0KOA=", + "pSX8z9KMKy8=", + "GSx7GUS4Kpo=" + ], + "Soroban operation source created and removed in classic phase|protocol version 22" : + [ + "bKDF6V5IzTo=", + "5ayMpvekkrI=", + "KpwqxixB1QU=", + "ninzTyfpD8c=", + "0xhX4klidW0=", + "DriP1FYyxvU=", + "syrbRtKc6Og=", + "s7cRiScIDRs=", + "ieMtr3xVwzs=", + "84z/mwe7bLw=", + "bolWl1e2MiI=", + "gSe0PUmaBeE=", + "XWGUN5oRCLQ=", + "giqBXEVckLs=", + "7tc351zel1s=", + "5q0dPSZe6xs=", + "108jh0FFUwQ=", + "YWPZ3Z0AALE=", + "NhbQs97HRHg=", + "4dsyL5+6R3c=", + "/i24ku1BXIk=", + "Dx/7Y1hH1JM=", + "2TqSGPO22xI=", + "5/Z6E0KBrqg=", + "ViUuIKaofeI=", + "leJeeGnjaUY=", + "3CphD5FSwJM=", + "+iy3NPt3ytA=", + "R/VTFpMVli4=", + "y+x7zHxNBmA=", + "4Yi2qwwZIa8=", + "/czKal/hKLc=", + "wCzZUJdypmU=", + "OUQvX9unks8=", + "blcnSidcFAA=", + "iKzCzPo0d6E=", + "wlGGD9kFHsU=", + "usj4INAIQLE=", + "KYhzuloANJg=", + "yBH0FljHOAE=", + "2pEDdVBCPUg=", + "RLQSuE0VRKQ=", + "ltRb1/FUQ9I=", + "eCwc/WSUNCw=", + "l2jIldD5lKI=", + "3GhYy8sX54Q=", + "LcaC2CLknZo=", + "RSb9KWtnQm8=", + "pmfIWlBW6iA=", + "/x4WW5L+tCQ=", + "5fkBtnXRe/0=", + "z62MBXihCyY=", + "CNZp6sFSoXM=", + "ZGfMkEu8Ulw=", + "gxsZCR7REC4=", + "FzKKFViimiQ=", + "2fjvelCaJrE=", + "D6jj6tAnifM=", + "y6I8zVgn67I=", + "fFxwT4onCuo=", + "zmTIbczXn0k=", + "MiTslt8iyzM=", + "jfpyVY+vrMU=", + "azA+s6oxbOg=", + "ZmUPbn7/xc0=", + "ZucccJTapDk=", + "ieWc2QQjYwg=", + "iFmCgHZLhRI=", + "4kpdCiyd6+U=", + "zkWAzUNq6g0=", + "KlkrtrwMZSA=", + "GSXS/naFC7o=", + "UwQSKeqWeuE=", + "FBOP79OXINA=", + "EcchsVBcwjA=", + "2C41h+WmaFc=", + "GstNub02AMU=", + "YNufYkDHgA8=", + "JpAFUvNARFM=", + "jPlMpkSbnnk=", + "lV1IdI9sdOI=", + "GftzwB+pCTQ=", + "hR5d6pVHc40=", + "qLHKxSvGU3E=", + "t721A004I+I=", + "HGtmt02Q6JU=", + "iaQzSi66wcs=", + "rbowyW4jCBs=", + "WJs4iuxCdaU=", + "CGmvdBp/5zs=", + "AMzWei96FSc=", + "G5oFpONpPZ0=", + "mnUDr5XOkiQ=", + "UBrHhLuwCS4=", + "tXDs520pIXI=", + "0gIZ9k20dos=", + "sb6iULDIZIk=", + "/9TZzHvXMJE=", + "U6/5/AUYgvg=", + "xIdb9LXLdE0=", + "LXkHFxv8xCI=" + ], + "Soroban operation source created and removed in classic phase|protocol version 23" : + [ + "+cR3oq2qY0I=", + "nz9v1PzpgfI=", + "hohUpT/ADqk=", + "bvjRdiFGfTM=", + "fj7GNFRwzCo=", + "nXkts5zEKgU=", + "ZiQQXHUPS5U=", + "TC5BKqdd+B4=", + "WXaQReLYO5k=", + "LPFg+MEaSQg=", + "Asgvsb6w7Q0=", + "wBJrQJNAkmE=", + "wrjwucM/Zow=", + "e4novqniZ+g=", + "Ibm21qxpI7s=", + "UextlVZsjnM=", + "0n7dMegdZ3A=", + "11XOGuZ3Xug=", + "WV1Ho30vGvc=", + "SnZLQYvZxfA=", + "M5BZn04JJsE=", + "uMeTcfXMq5A=", + "ziO+HFD3yYY=", + "kGjdPxb4AWs=", + "lpn9djEUn2M=", + "baWzcJ+nmdg=", + "UF9UKXHjJDc=", + "y+4FEa0UPZo=", + "uqFChe3y8rQ=", + "WZZHQawuopM=", + "76Tytga3SWQ=", + "oBXvRd8lj7E=", + "2UIvJMrAYkA=", + "Lu4HE/7VmrU=", + "jax2QwuMLvA=", + "icIkd6qRbPg=", + "KtZfjBYf/V8=", + "huqkxOC2LoA=", + "Jt3tgC+PClI=", + "+UcB9Bo0/hg=", + "zJRsdNMwMAc=", + "MLrMqsvOziE=", + "6vK4A0eFd9c=", + "/dBnJEv5mug=", + "T1D/fXHUY8k=", + "wbI5JOgzavw=", + "saayh6lFoy8=", + "1zCrRETesEE=", + "4aeZ3nDW2H8=", + "2EVgJD6hMxE=", + "0HYOxKmFbXc=", + "2GH3CCviOcs=", + "9kcvbtcyje8=", + "tPZwrweWQ8c=", + "bujRoPDgmrM=", + "1VayL7z/03M=", + "WzdN95wnWC4=", + "cOk9uPy8kSQ=", + "0yMEY5GgOiw=", + "80ul4iYlg1A=", + "Kvi1c6UeFIs=", + "M+BKIBuPOS4=", + "Edzb65HK+ao=", + "xNFD7cNA9PE=", + "+3bDFSiTswE=", + "x43oIP5QKZ0=", + "T1z4oGc8vqc=", + "mlW6FqrcYSI=", + "hQEjDayPI9E=", + "C1hgh4vaYvk=", + "rm96fjiAVTE=", + "C5N7gq8301Q=", + "v4o9l1ZMoD0=", + "gdJY9xf3I/I=", + "0FvLTFyx56c=", + "RihwpLL/n/E=", + "Oo2rLuCHGr4=", + "ldJr6nmpvUU=", + "4EErS4HHw7k=", + "oPYYvxcsZY4=", + "Jzmx0gWrqGQ=", + "siQ/3Hh+++U=", + "Q2Q6XWtaQCQ=", + "Ot03scyos0k=", + "rOcJh/4Ez/Y=", + "dKxQ91Mrvn8=", + "LBpIyth3wYk=", + "wmV5IzZY1pM=", + "qIRuVOi6tQM=", + "k2ZdBvYWWi8=", + "wNwIp33jJMI=", + "Ma1rDLoDtvA=", + "XpM0H5kfBLs=", + "xlufJjbEuYg=", + "TFeOtOGRmt8=", + "Eclf3i5w7gg=", + "5aKvPQAX7tE=", + "GLxznahSj+E=", + "4L5PdJ7n/qo=", + "i23Oql77Y6U=", + "cOJDuiZkHlg=" + ], + "Soroban operation source created and removed in classic phase|protocol version 24" : + [ + "+cR3oq2qY0I=", + "nz9v1PzpgfI=", + "hohUpT/ADqk=", + "bvjRdiFGfTM=", + "fj7GNFRwzCo=", + "nXkts5zEKgU=", + "ZiQQXHUPS5U=", + "TC5BKqdd+B4=", + "WXaQReLYO5k=", + "LPFg+MEaSQg=", + "Asgvsb6w7Q0=", + "wBJrQJNAkmE=", + "wrjwucM/Zow=", + "e4novqniZ+g=", + "Ibm21qxpI7s=", + "UextlVZsjnM=", + "0n7dMegdZ3A=", + "11XOGuZ3Xug=", + "WV1Ho30vGvc=", + "SnZLQYvZxfA=", + "M5BZn04JJsE=", + "uMeTcfXMq5A=", + "ziO+HFD3yYY=", + "kGjdPxb4AWs=", + "lpn9djEUn2M=", + "baWzcJ+nmdg=", + "UF9UKXHjJDc=", + "y+4FEa0UPZo=", + "uqFChe3y8rQ=", + "WZZHQawuopM=", + "76Tytga3SWQ=", + "oBXvRd8lj7E=", + "2UIvJMrAYkA=", + "Lu4HE/7VmrU=", + "jax2QwuMLvA=", + "icIkd6qRbPg=", + "KtZfjBYf/V8=", + "huqkxOC2LoA=", + "Jt3tgC+PClI=", + "+UcB9Bo0/hg=", + "zJRsdNMwMAc=", + "MLrMqsvOziE=", + "6vK4A0eFd9c=", + "/dBnJEv5mug=", + "T1D/fXHUY8k=", + "wbI5JOgzavw=", + "saayh6lFoy8=", + "1zCrRETesEE=", + "4aeZ3nDW2H8=", + "2EVgJD6hMxE=", + "0HYOxKmFbXc=", + "2GH3CCviOcs=", + "9kcvbtcyje8=", + "tPZwrweWQ8c=", + "bujRoPDgmrM=", + "1VayL7z/03M=", + "WzdN95wnWC4=", + "cOk9uPy8kSQ=", + "0yMEY5GgOiw=", + "80ul4iYlg1A=", + "Kvi1c6UeFIs=", + "M+BKIBuPOS4=", + "Edzb65HK+ao=", + "xNFD7cNA9PE=", + "+3bDFSiTswE=", + "x43oIP5QKZ0=", + "T1z4oGc8vqc=", + "mlW6FqrcYSI=", + "hQEjDayPI9E=", + "C1hgh4vaYvk=", + "rm96fjiAVTE=", + "C5N7gq8301Q=", + "v4o9l1ZMoD0=", + "gdJY9xf3I/I=", + "0FvLTFyx56c=", + "RihwpLL/n/E=", + "Oo2rLuCHGr4=", + "ldJr6nmpvUU=", + "4EErS4HHw7k=", + "oPYYvxcsZY4=", + "Jzmx0gWrqGQ=", + "siQ/3Hh+++U=", + "Q2Q6XWtaQCQ=", + "Ot03scyos0k=", + "rOcJh/4Ez/Y=", + "dKxQ91Mrvn8=", + "LBpIyth3wYk=", + "wmV5IzZY1pM=", + "qIRuVOi6tQM=", + "k2ZdBvYWWi8=", + "wNwIp33jJMI=", + "Ma1rDLoDtvA=", + "XpM0H5kfBLs=", + "xlufJjbEuYg=", + "TFeOtOGRmt8=", + "Eclf3i5w7gg=", + "5aKvPQAX7tE=", + "GLxznahSj+E=", + "4L5PdJ7n/qo=", + "i23Oql77Y6U=", + "cOJDuiZkHlg=" + ], + "Soroban operation source created and removed in classic phase|protocol version 25" : + [ + "+cR3oq2qY0I=", + "nz9v1PzpgfI=", + "hohUpT/ADqk=", + "bvjRdiFGfTM=", + "fj7GNFRwzCo=", + "nXkts5zEKgU=", + "ZiQQXHUPS5U=", + "TC5BKqdd+B4=", + "WXaQReLYO5k=", + "LPFg+MEaSQg=", + "Asgvsb6w7Q0=", + "wBJrQJNAkmE=", + "wrjwucM/Zow=", + "e4novqniZ+g=", + "Ibm21qxpI7s=", + "UextlVZsjnM=", + "0n7dMegdZ3A=", + "11XOGuZ3Xug=", + "WV1Ho30vGvc=", + "SnZLQYvZxfA=", + "M5BZn04JJsE=", + "uMeTcfXMq5A=", + "ziO+HFD3yYY=", + "kGjdPxb4AWs=", + "lpn9djEUn2M=", + "baWzcJ+nmdg=", + "UF9UKXHjJDc=", + "y+4FEa0UPZo=", + "uqFChe3y8rQ=", + "WZZHQawuopM=", + "76Tytga3SWQ=", + "oBXvRd8lj7E=", + "2UIvJMrAYkA=", + "Lu4HE/7VmrU=", + "jax2QwuMLvA=", + "icIkd6qRbPg=", + "KtZfjBYf/V8=", + "huqkxOC2LoA=", + "Jt3tgC+PClI=", + "+UcB9Bo0/hg=", + "zJRsdNMwMAc=", + "MLrMqsvOziE=", + "6vK4A0eFd9c=", + "/dBnJEv5mug=", + "T1D/fXHUY8k=", + "wbI5JOgzavw=", + "saayh6lFoy8=", + "1zCrRETesEE=", + "4aeZ3nDW2H8=", + "2EVgJD6hMxE=", + "0HYOxKmFbXc=", + "2GH3CCviOcs=", + "9kcvbtcyje8=", + "tPZwrweWQ8c=", + "bujRoPDgmrM=", + "1VayL7z/03M=", + "WzdN95wnWC4=", + "cOk9uPy8kSQ=", + "0yMEY5GgOiw=", + "80ul4iYlg1A=", + "Kvi1c6UeFIs=", + "M+BKIBuPOS4=", + "Edzb65HK+ao=", + "xNFD7cNA9PE=", + "+3bDFSiTswE=", + "x43oIP5QKZ0=", + "T1z4oGc8vqc=", + "mlW6FqrcYSI=", + "hQEjDayPI9E=", + "C1hgh4vaYvk=", + "rm96fjiAVTE=", + "C5N7gq8301Q=", + "v4o9l1ZMoD0=", + "gdJY9xf3I/I=", + "0FvLTFyx56c=", + "RihwpLL/n/E=", + "Oo2rLuCHGr4=", + "ldJr6nmpvUU=", + "4EErS4HHw7k=", + "oPYYvxcsZY4=", + "Jzmx0gWrqGQ=", + "siQ/3Hh+++U=", + "Q2Q6XWtaQCQ=", + "Ot03scyos0k=", + "rOcJh/4Ez/Y=", + "dKxQ91Mrvn8=", + "LBpIyth3wYk=", + "wmV5IzZY1pM=", + "qIRuVOi6tQM=", + "k2ZdBvYWWi8=", + "wNwIp33jJMI=", + "Ma1rDLoDtvA=", + "XpM0H5kfBLs=", + "xlufJjbEuYg=", + "TFeOtOGRmt8=", + "Eclf3i5w7gg=", + "5aKvPQAX7tE=", + "GLxznahSj+E=", + "4L5PdJ7n/qo=", + "i23Oql77Y6U=", + "cOJDuiZkHlg=" + ], + "Soroban operation source created and removed in classic phase|protocol version 26" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban operation source created and removed in classic phase|protocol version 27" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban operation source created and removed in classic phase|protocol version 28" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban operation source created and removed in classic phase|protocol version 29" : + [ + "+cR3oq2qY0I=", + "crbAf4Ea6kg=", + "iqTvm0y1Iow=", + "6pO37nDn84A=", + "wRmit6MBjrQ=", + "oVpHg7RRBlk=", + "Aid/7xaOTR0=", + "bbMlrMP+qlI=", + "fdD5DjwwiOQ=", + "dLar7fQTVJQ=", + "rqoO87FasNU=", + "7aj+KvKQXwY=", + "mruvECGnEyU=", + "5/S0IcIxBNI=", + "Ze0l8W+lT7M=", + "UXimakEXASc=", + "ay1R0+swdfw=", + "VEV8xNmTE1Q=", + "ohDWJIUApRk=", + "LeIaM+VHBWo=", + "XXB+LJhuCO0=", + "Z1SOcuDsn3U=", + "1j7QdwSbjPY=", + "OSoLJeVtHOg=", + "AoGTPhaZJy4=", + "DWRtqn3dZGo=", + "tuOemI/6/Vw=", + "rpw06OPQ4YQ=", + "yq78L4dQbBA=", + "pS8F28DUKnk=", + "R7aUoGb7MyA=", + "CzSTC9mDsx0=", + "9pl1fjzk41A=", + "czFb8xk728c=", + "67+TTjrwYLE=", + "yRwsYheUXUo=", + "E8kX1Yrj71M=", + "8fn8vzThmDI=", + "WBTucsatdSY=", + "cLZ5fozibbY=", + "sVBaA3CDFfU=", + "zLz7Tfj0ef4=", + "kbGW6RV1SW4=", + "NStKgU3nvsw=", + "jyRmbaA22SU=", + "5niYf+Sj4qo=", + "IYqTe+q5124=", + "b/asdCehmbs=", + "gGW69QBxFJA=", + "sjeXqxl36Eg=", + "ga0wPKIyWeU=", + "o8iLtP9jdUY=", + "3C5DxayMoqQ=", + "oyRATLVeDdA=", + "cBSvG7Y4Lp4=", + "qeYaEXAXYc0=", + "jxNlURg20AM=", + "lwAZn9dNSjg=", + "+ijl0DL07ME=", + "RyPBfGhCxpY=", + "3M0rqTnOqhE=", + "inHVXSTA278=", + "qz9ZiOB41eY=", + "3G2x7xoeHOU=", + "IkoYpaPqPrw=", + "j0WdJcdb+BE=", + "CeAemj67nZM=", + "kVpPjbTS/jo=", + "XEF5tUmLfjU=", + "0Bz/VETaobk=", + "7l4k+XN3Xno=", + "4imVULlTzUw=", + "Aea+sYr85WQ=", + "8PaqAkHF0e0=", + "QKC5AS+jhCM=", + "pEWBhRBgCz8=", + "fMxyYZquhAA=", + "8xxIbp8nLLY=", + "AYZkATYEJOk=", + "XKrbs5lBIcw=", + "6KVpqakZPiw=", + "OeAMSZ0Gc/U=", + "MhgNQLzMD4Q=", + "NK6v8hyAKGY=", + "QuMvE+2NFIU=", + "1G81YWIYlgo=", + "bKdk2OVRSDo=", + "maokePOWsQI=", + "CdgngSmnixI=", + "IcLAQnataC4=", + "vr2lY+iMklA=", + "CYO7w60bDzE=", + "rl+0lPOoBHk=", + "qHcIz27YW90=", + "yvViF0w9JZs=", + "dNuw4Jq10aY=", + "Bk//FNsJ//8=", + "8JWNtTVb5mE=", + "v64n9RwfQRM=", + "q1W0Fxx9Nxw=", + "0u+ay1fNNYE=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 20" : + [ + "bKDF6V5IzTo=", + "1YoRQpENTWE=", + "dYRpGqAlBDs=", + "pBZtiu3OJ7M=", + "IBgPoEf6H8s=", + "oUoLY4Gok3Q=", + "V6Ly+If+Kv8=", + "Cm3CkzL2syQ=", + "PhFE8ATy/4g=", + "FUBVEeXefug=", + "+hKh+5+Thsw=", + "BlhftaBlm9g=", + "ZS/mQlezUuE=", + "IbUGZ7407UU=", + "L1cDvhFQE80=", + "D+6b+5+H1ss=", + "j7SY2fAK6fU=", + "/r+khMp1/8Y=", + "7VBKTQNpMeI=", + "6jTXkdr5rPc=", + "6T+YCvYp8H0=", + "z0+71j6HB28=", + "Z8Ghz71bsAw=", + "U5VtQDYCcYU=", + "zvN90WCRkO0=", + "paei0bhsSsw=", + "S28j8kgREkE=", + "fvzFffOIdO4=", + "j+BP1ibsAFw=", + "7HmBrxtECbA=", + "rV7Gs+BCjiE=", + "JePxrvqNzs4=", + "p9TVAXdLwmc=", + "RxrYYjg9xds=", + "O8s2BCTv5DM=", + "+4b9MzEXa20=", + "SZI1PxuLtVE=", + "SvbVLfk38Jk=", + "5/k+BSJIhF4=", + "ybLgnPo+8nk=", + "9VpMR7mf4Po=", + "0oYz7Ehlm6A=", + "ZFeZS74f/4w=", + "u78kYC7n3/Q=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 21" : + [ + "bKDF6V5IzTo=", + "1YoRQpENTWE=", + "dYRpGqAlBDs=", + "pBZtiu3OJ7M=", + "IBgPoEf6H8s=", + "oUoLY4Gok3Q=", + "V6Ly+If+Kv8=", + "Cm3CkzL2syQ=", + "PhFE8ATy/4g=", + "FUBVEeXefug=", + "+hKh+5+Thsw=", + "BlhftaBlm9g=", + "ZS/mQlezUuE=", + "IbUGZ7407UU=", + "L1cDvhFQE80=", + "D+6b+5+H1ss=", + "j7SY2fAK6fU=", + "/r+khMp1/8Y=", + "7VBKTQNpMeI=", + "6jTXkdr5rPc=", + "6T+YCvYp8H0=", + "z0+71j6HB28=", + "Z8Ghz71bsAw=", + "U5VtQDYCcYU=", + "zvN90WCRkO0=", + "paei0bhsSsw=", + "S28j8kgREkE=", + "fvzFffOIdO4=", + "j+BP1ibsAFw=", + "7HmBrxtECbA=", + "rV7Gs+BCjiE=", + "JePxrvqNzs4=", + "p9TVAXdLwmc=", + "RxrYYjg9xds=", + "UIcS2n63svo=", + "5AKz5MKz3EY=", + "mQLIi4/Xnpo=", + "VtBxD9nW620=", + "ceOLSgirQIY=", + "rHzGA3aTfkw=", + "RmAa3HcLZTc=", + "NJfu6kEGL/4=", + "BSMhaTpJB4A=", + "HgIVMbnJQB4=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 22" : + [ + "bKDF6V5IzTo=", + "rR4bN6XbNfA=", + "JS6E860wJVs=", + "IDGsWUzKLBg=", + "nBz425qu8TA=", + "+5Dk5uxx0rE=", + "AKTpav8hbPk=", + "f46MIJNsJ7g=", + "C3nn7+10DbI=", + "uBGgXv+i2FQ=", + "MXG5KnbZNmI=", + "vAOX3fQHjXI=", + "j33yW667WIE=", + "Iy+GcIxksMk=", + "5ssn3tY2daI=", + "jPxDcic4tWY=", + "4ApAZLoEjvA=", + "9beQ0wLBIgo=", + "sDlVuzU/IZY=", + "LK7dyMvS/M4=", + "+fP84720bhs=", + "+6EZ1HEZ7rU=", + "L5nSFfKp2HI=", + "oqlN+7Cc354=", + "dBVQweMckj4=", + "kVTA3XuOok8=", + "ySbms3WjD1k=", + "mxfbAlSuU2A=", + "oIRc9owv+Ng=", + "5dfzdW9W/DU=", + "kh7qum+vOdQ=", + "0/2/o/Y5wvs=", + "jNP2r8hb+wM=", + "+pSYIj4EKGE=", + "NpRJ93HgrYI=", + "irA2wilgrnA=", + "IfCYdVEHN6A=", + "eSJ9dhI6SO8=", + "4+qhdqGn68g=", + "evhjr9oq5cY=", + "bSmOo50CUSQ=", + "IFQf8MX9jWM=", + "hORHjI6CsJs=", + "Is/kbc6knec=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 23" : + [ + "+cR3oq2qY0I=", + "2lu0XZUNpXE=", + "0YkYsN9TXcU=", + "Vudi8oDzW4I=", + "2v7LYECgY2E=", + "4eNmAHnACvY=", + "nsbN8jGC9+c=", + "3kOlGG6S6/Y=", + "BUWt8cXkE5A=", + "4A6ZHTxj8tg=", + "809kpAhSloE=", + "WJKVjCcl7yo=", + "a8oSOyFmNT0=", + "WyI59xx+zTc=", + "YOQgHndQKjA=", + "MsAl1s+BNFQ=", + "nF+LnYavpr0=", + "y9MpYmiN300=", + "nSNpeleCNfI=", + "PSTit18ljrQ=", + "3JCL3JAVKOQ=", + "LPGjbKnCvzE=", + "S8gNPX/DWB0=", + "cIXhb1wrROk=", + "fPIsm2zwFXg=", + "pnW9jsSv/og=", + "Jk4IV8yurg8=", + "dUsPMBubifg=", + "4NKto3sosLY=", + "50doy92gxJs=", + "1Rkqm63AlHw=", + "+LN3x+p008A=", + "+v4Ai/yLXQo=", + "uj+OehxLu2o=", + "XBUW/5qoKUo=", + "zFo4Vc6YmG8=", + "6k8nkchciDY=", + "SFVh7gD5zB8=", + "YsNY30clXRo=", + "aKiRBvxFWOs=", + "yegKP5/2ctg=", + "4WaR3adrld4=", + "b/u7eXDr9mc=", + "5t5NSWs4F3s=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 24" : + [ + "+cR3oq2qY0I=", + "2lu0XZUNpXE=", + "0YkYsN9TXcU=", + "Vudi8oDzW4I=", + "2v7LYECgY2E=", + "4eNmAHnACvY=", + "nsbN8jGC9+c=", + "3kOlGG6S6/Y=", + "BUWt8cXkE5A=", + "4A6ZHTxj8tg=", + "809kpAhSloE=", + "WJKVjCcl7yo=", + "a8oSOyFmNT0=", + "WyI59xx+zTc=", + "YOQgHndQKjA=", + "MsAl1s+BNFQ=", + "nF+LnYavpr0=", + "y9MpYmiN300=", + "nSNpeleCNfI=", + "PSTit18ljrQ=", + "3JCL3JAVKOQ=", + "LPGjbKnCvzE=", + "S8gNPX/DWB0=", + "cIXhb1wrROk=", + "fPIsm2zwFXg=", + "pnW9jsSv/og=", + "Jk4IV8yurg8=", + "dUsPMBubifg=", + "4NKto3sosLY=", + "50doy92gxJs=", + "1Rkqm63AlHw=", + "+LN3x+p008A=", + "+v4Ai/yLXQo=", + "uj+OehxLu2o=", + "XBUW/5qoKUo=", + "zFo4Vc6YmG8=", + "6k8nkchciDY=", + "SFVh7gD5zB8=", + "YsNY30clXRo=", + "aKiRBvxFWOs=", + "yegKP5/2ctg=", + "4WaR3adrld4=", + "b/u7eXDr9mc=", + "5t5NSWs4F3s=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 25" : + [ + "+cR3oq2qY0I=", + "2lu0XZUNpXE=", + "0YkYsN9TXcU=", + "Vudi8oDzW4I=", + "2v7LYECgY2E=", + "4eNmAHnACvY=", + "nsbN8jGC9+c=", + "3kOlGG6S6/Y=", + "BUWt8cXkE5A=", + "4A6ZHTxj8tg=", + "809kpAhSloE=", + "WJKVjCcl7yo=", + "a8oSOyFmNT0=", + "WyI59xx+zTc=", + "YOQgHndQKjA=", + "MsAl1s+BNFQ=", + "nF+LnYavpr0=", + "y9MpYmiN300=", + "nSNpeleCNfI=", + "PSTit18ljrQ=", + "3JCL3JAVKOQ=", + "LPGjbKnCvzE=", + "S8gNPX/DWB0=", + "cIXhb1wrROk=", + "fPIsm2zwFXg=", + "pnW9jsSv/og=", + "Jk4IV8yurg8=", + "dUsPMBubifg=", + "4NKto3sosLY=", + "50doy92gxJs=", + "1Rkqm63AlHw=", + "+LN3x+p008A=", + "+v4Ai/yLXQo=", + "uj+OehxLu2o=", + "XBUW/5qoKUo=", + "zFo4Vc6YmG8=", + "6k8nkchciDY=", + "SFVh7gD5zB8=", + "YsNY30clXRo=", + "aKiRBvxFWOs=", + "yegKP5/2ctg=", + "4WaR3adrld4=", + "b/u7eXDr9mc=", + "5t5NSWs4F3s=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 26" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 27" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 28" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], + "Soroban pre-apply removes pre-auth tx signers|protocol version 29" : + [ + "+cR3oq2qY0I=", + "YS3CtbB4LCY=", + "yuxnivFgzdw=", + "NmWV7/t534g=", + "/Kjv95RCny8=", + "pO1qODwjXZY=", + "468KGJPAA6M=", + "zEMED1Ra2FE=", + "6KQ1GRPt6bI=", + "MLNDTE6pvY4=", + "M26lOjlaQIY=", + "mp+KNeldXrU=", + "lUxktDmMJ54=", + "z+4rbTbSb84=", + "CvbvbVNMx4k=", + "5MTOb0MPD+w=", + "MIvv9ify+gw=", + "dSs8vpDFl3c=", + "iw4hEELDw5Q=", + "hajZcnBWStU=", + "Orkjm9fvOX0=", + "YiZVW2/DJTA=", + "MHNjEmcU/yc=", + "N9FNXxDcVDs=", + "IpqtiLtCShI=", + "IWJJU/JPink=", + "hNhPmyg88jY=", + "1pct7OGGkkI=", + "l9wje+2H0Jg=", + "fkW5vRedzh4=", + "Bt4XkzF4Smc=", + "jsZPxY0xD3I=", + "fH3XJwGQAME=", + "MBYfICUqUII=", + "UB3keZnV78E=", + "yTp/L/LfDZ0=", + "fYKKnLHVgDY=", + "/k+LTrpQXdw=", + "hlZh01w9cdU=", + "CPKD3YpWfmI=", + "00Ek9r6xKCU=", + "CYn7uvpg2AM=", + "WgyGQCjDM68=", + "YJso3URJjlo=" + ], "Stellar asset contract transfer with CAP-67 address types" : [ "+cR3oq2qY0I=", @@ -2151,6 +3661,546 @@ "classic payment to soroban fee bump account|protocol version 27" : [ "NTGGdj1offM=", "aHlgICbAAQs=", "1S4Ni3f8c/0=", "wiDaeJY86QQ=" ], "classic payment to soroban fee bump account|protocol version 28" : [ "NTGGdj1offM=", "aHlgICbAAQs=", "1S4Ni3f8c/0=", "wiDaeJY86QQ=" ], "classic payment to soroban fee bump account|protocol version 29" : [ "NTGGdj1offM=", "aHlgICbAAQs=", "1S4Ni3f8c/0=", "wiDaeJY86QQ=" ], + "classic phase bumps sequence of Soroban tx source account|protocol version 20" : + [ + "bKDF6V5IzTo=", + "rykv5BBzl1k=", + "F6F6vr15q1A=", + "4tvlkZFFRX4=", + "HgDUNiXg80U=", + "18FzAAQdQ70=", + "IHdIHFYrMgg=", + "t89GweXHC1I=", + "apCV+hCbZl8=", + "S29r/lxDh70=", + "UDozttyLWyI=", + "QILccI+f94s=", + "4O7/p0uxawc=", + "XwTloGeBtpc=", + "umjGbr+xtOs=", + "BcAvVWg4Jmw=", + "iHA3lSwayZI=", + "MlkJ5OnVDJQ=", + "2duFeYTKLWw=", + "eOmcEBMQdlE=", + "+eyKPmg9JrE=", + "rCZG4VEVwT0=", + "SGL4HT2uYfA=", + "RjhND1kQks0=", + "SMsTDaoGh5s=", + "L0c/XCA0c6E=", + "1YZC+osAer4=", + "vkAUGnoDIWU=", + "YWbsWj8wD90=", + "E99WgsmZhpk=", + "POLMhqkKPgM=", + "ZXG+1zagaV8=", + "Tifr/sJJRZY=", + "jgRoiQihkdw=", + "lFTHEDTm6z4=", + "8PWngVNc9DA=", + "Vm4VrTdRe6M=", + "eZc8pI4CZao=", + "ByEpJiDhfdA=", + "RYE+nBNdNk4=", + "ljCgxBXavyk=", + "KZdTXZqOc9I=", + "ApLOH3i1dlk=", + "wT3WFcxv7ME=", + "9dt+A5yy5C4=", + "v142Cwj8ods=", + "UZD6laODN4k=", + "bcwT4P0WJEM=", + "CNB2siN27BQ=", + "80Aedxva4PY=", + "b6+dMGM8F6I=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 21" : + [ + "bKDF6V5IzTo=", + "rykv5BBzl1k=", + "F6F6vr15q1A=", + "4tvlkZFFRX4=", + "HgDUNiXg80U=", + "18FzAAQdQ70=", + "IHdIHFYrMgg=", + "t89GweXHC1I=", + "apCV+hCbZl8=", + "S29r/lxDh70=", + "UDozttyLWyI=", + "QILccI+f94s=", + "4O7/p0uxawc=", + "XwTloGeBtpc=", + "umjGbr+xtOs=", + "BcAvVWg4Jmw=", + "iHA3lSwayZI=", + "MlkJ5OnVDJQ=", + "2duFeYTKLWw=", + "eOmcEBMQdlE=", + "+eyKPmg9JrE=", + "rCZG4VEVwT0=", + "SGL4HT2uYfA=", + "RjhND1kQks0=", + "SMsTDaoGh5s=", + "L0c/XCA0c6E=", + "1YZC+osAer4=", + "vkAUGnoDIWU=", + "YWbsWj8wD90=", + "E99WgsmZhpk=", + "POLMhqkKPgM=", + "ZXG+1zagaV8=", + "Tifr/sJJRZY=", + "jgRoiQihkdw=", + "lFTHEDTm6z4=", + "8PWngVNc9DA=", + "Vm4VrTdRe6M=", + "eZc8pI4CZao=", + "ByEpJiDhfdA=", + "RYE+nBNdNk4=", + "ljCgxBXavyk=", + "KZdTXZqOc9I=", + "ApLOH3i1dlk=", + "wT3WFcxv7ME=", + "9dt+A5yy5C4=", + "v142Cwj8ods=", + "UZD6laODN4k=", + "bcwT4P0WJEM=", + "CNB2siN27BQ=", + "80Aedxva4PY=", + "b6+dMGM8F6I=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 22" : + [ + "bKDF6V5IzTo=", + "KauhmrCg434=", + "i2MP9cdPoQA=", + "6eUlCy7NfA8=", + "dv4BVugo9Pg=", + "GlNEXON53WM=", + "5ji87LopYYw=", + "xR65gTZpjQg=", + "ggE2L5NcQm0=", + "bYzJySm4pJw=", + "+J+y9jDJ/Os=", + "BJdhJgqrUvM=", + "Trqgj75G5qQ=", + "ROga9zur2h4=", + "W1o7OisVZ6M=", + "B2myGpMGbks=", + "PUkvsmqFwW0=", + "LgtPg7GlRuk=", + "DOdX56mpKUA=", + "CTbGbLivHyQ=", + "8gJgm7hCCDk=", + "i3ieaS2MRTQ=", + "S4k1pw8IB0o=", + "ZWY8Qtj2yvo=", + "sjKfSsXN0TY=", + "8LdOzje9Jvk=", + "rbMHcrEsWQI=", + "uAQLz05EF7c=", + "DV+jLYgMzyM=", + "sah3Y6KWgwM=", + "kTdgHIVAjbU=", + "d1nR73Vx9+w=", + "mcfXbs12gZY=", + "vicbAJ0rNlE=", + "F4rgNeQ8IRs=", + "E2Z/buvl4So=", + "VMLALQO+jFw=", + "LTR8SHIw5wQ=", + "ak0x6FJy7NE=", + "carMrGgUz0k=", + "Ae7xAPoccL0=", + "SN1v0r7HvJc=", + "Y8XHtnfJ+3I=", + "dau45GFv2C4=", + "03G7p4D2srI=", + "MaHEhKl/EG8=", + "KdQvPSPGfCM=", + "pIZUsigzx1A=", + "1ytaxBFTWaQ=", + "iIt0HAhbgR8=", + "744WeiXt6Lo=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 23" : + [ + "+cR3oq2qY0I=", + "xkbxRHKhRz4=", + "0aeGvP7QhNY=", + "qEJFG6MlRu8=", + "XsgH1c4Y8jE=", + "wncOj5kDqQk=", + "mCjhH83YP1E=", + "wo9cdhwcJxQ=", + "8mY+Hh264uc=", + "XsZ8hZZjnZc=", + "m2hJ7TZM74k=", + "dwFqcSZBTmA=", + "gIWzcqTqr6I=", + "2OqlMksDyek=", + "vTCH8GUcwxk=", + "UoLY7lwUbng=", + "brZEf0Qd6Uk=", + "HsXv1mQ86v0=", + "1CJ5MhbEknI=", + "ONTM2yLjg8c=", + "doJkTlm07Q0=", + "KPHoMvuWIlY=", + "/ti+01USiNc=", + "3cI3odnQfmk=", + "iaHUOftB+Uw=", + "OR7cDRnC/F4=", + "PRT9Xl9zkSw=", + "4DPNrmvKB2M=", + "2UTxLEm41VY=", + "FpZZf7OgA1Y=", + "jThf3ILflPk=", + "AHkcqIASpfE=", + "SHVlFzsVemA=", + "i52vHXLCMI8=", + "G/XCJvs11Qs=", + "K0jLgQjq/dM=", + "sCRVpE+JPrg=", + "/og8kIzS74Y=", + "KtLG25hvCe8=", + "y82NDXppduU=", + "NL7L5pMxgVA=", + "ARKssIQ+5d4=", + "NI9WByR7em8=", + "M87swFclhmk=", + "XgoXLGJ95dk=", + "eFL6eJUV78Q=", + "0ycIKH0BnjM=", + "QUBP3y7EVgY=", + "gtKDQKoYDvc=", + "F976AZv+d4c=", + "6ECCc6Afj/Q=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 24" : + [ + "+cR3oq2qY0I=", + "xkbxRHKhRz4=", + "0aeGvP7QhNY=", + "qEJFG6MlRu8=", + "XsgH1c4Y8jE=", + "wncOj5kDqQk=", + "mCjhH83YP1E=", + "wo9cdhwcJxQ=", + "8mY+Hh264uc=", + "XsZ8hZZjnZc=", + "m2hJ7TZM74k=", + "dwFqcSZBTmA=", + "gIWzcqTqr6I=", + "2OqlMksDyek=", + "vTCH8GUcwxk=", + "UoLY7lwUbng=", + "brZEf0Qd6Uk=", + "HsXv1mQ86v0=", + "1CJ5MhbEknI=", + "ONTM2yLjg8c=", + "doJkTlm07Q0=", + "KPHoMvuWIlY=", + "/ti+01USiNc=", + "3cI3odnQfmk=", + "iaHUOftB+Uw=", + "OR7cDRnC/F4=", + "PRT9Xl9zkSw=", + "4DPNrmvKB2M=", + "2UTxLEm41VY=", + "FpZZf7OgA1Y=", + "jThf3ILflPk=", + "AHkcqIASpfE=", + "SHVlFzsVemA=", + "i52vHXLCMI8=", + "G/XCJvs11Qs=", + "K0jLgQjq/dM=", + "sCRVpE+JPrg=", + "/og8kIzS74Y=", + "KtLG25hvCe8=", + "y82NDXppduU=", + "NL7L5pMxgVA=", + "ARKssIQ+5d4=", + "NI9WByR7em8=", + "M87swFclhmk=", + "XgoXLGJ95dk=", + "eFL6eJUV78Q=", + "0ycIKH0BnjM=", + "QUBP3y7EVgY=", + "gtKDQKoYDvc=", + "F976AZv+d4c=", + "6ECCc6Afj/Q=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 25" : + [ + "+cR3oq2qY0I=", + "xkbxRHKhRz4=", + "0aeGvP7QhNY=", + "qEJFG6MlRu8=", + "XsgH1c4Y8jE=", + "wncOj5kDqQk=", + "mCjhH83YP1E=", + "wo9cdhwcJxQ=", + "8mY+Hh264uc=", + "XsZ8hZZjnZc=", + "m2hJ7TZM74k=", + "dwFqcSZBTmA=", + "gIWzcqTqr6I=", + "2OqlMksDyek=", + "vTCH8GUcwxk=", + "UoLY7lwUbng=", + "brZEf0Qd6Uk=", + "HsXv1mQ86v0=", + "1CJ5MhbEknI=", + "ONTM2yLjg8c=", + "doJkTlm07Q0=", + "KPHoMvuWIlY=", + "/ti+01USiNc=", + "3cI3odnQfmk=", + "iaHUOftB+Uw=", + "OR7cDRnC/F4=", + "PRT9Xl9zkSw=", + "4DPNrmvKB2M=", + "2UTxLEm41VY=", + "FpZZf7OgA1Y=", + "jThf3ILflPk=", + "AHkcqIASpfE=", + "SHVlFzsVemA=", + "i52vHXLCMI8=", + "G/XCJvs11Qs=", + "K0jLgQjq/dM=", + "sCRVpE+JPrg=", + "/og8kIzS74Y=", + "KtLG25hvCe8=", + "y82NDXppduU=", + "NL7L5pMxgVA=", + "ARKssIQ+5d4=", + "NI9WByR7em8=", + "M87swFclhmk=", + "XgoXLGJ95dk=", + "eFL6eJUV78Q=", + "0ycIKH0BnjM=", + "QUBP3y7EVgY=", + "gtKDQKoYDvc=", + "F976AZv+d4c=", + "6ECCc6Afj/Q=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 26" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 27" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 28" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], + "classic phase bumps sequence of Soroban tx source account|protocol version 29" : + [ + "+cR3oq2qY0I=", + "9G86+JBHgeg=", + "O9xQyz4xR6g=", + "u0McD0c7NfI=", + "KLJ0pWMwK30=", + "wpwSFCn5q6g=", + "4r+bbTlvQKM=", + "hDtFvwMk1/Q=", + "LgGCds/Fc5Q=", + "7e0mbuTWiVk=", + "V4njnChVt/w=", + "dDEX/hJzsdc=", + "vp8A6fnZmGU=", + "Kye95ZZ5ASA=", + "tjYacA0ikf0=", + "5HuWsvaD6R0=", + "7vAx5m28tlg=", + "xefwYThnA/c=", + "1OAH/Yjpzhw=", + "OnxYYYZ1auA=", + "xyDBkmJ29YM=", + "gJObg3YiHKo=", + "Fasoypcxhw8=", + "Op58Pa68puU=", + "QZzhPrNXWOk=", + "uQCN2iKRws4=", + "4qXGhGs0MEY=", + "BhD8QBYtJck=", + "LMq6nGWKQQs=", + "qUCY5Yht2nE=", + "+yQ+NHtpKwc=", + "odMr5HEuZ1c=", + "YfdsmGxer0Y=", + "6nHthXP12Is=", + "cBu0hV6kpKM=", + "JxBRDvkPK+c=", + "ndLjEW0PIeY=", + "5m3OBkeUZEI=", + "JE4YlOvb+as=", + "5tlNHzS4jsY=", + "UJ8X82k1Rwc=", + "q5MMlD4ueJk=", + "wuk/cKq2M60=", + "zzCTevwh32E=", + "um3lT2lgzlk=", + "7TXOxf6SKR8=", + "WXrk89lXDpE=", + "PT44jKZRsK0=", + "N8EpdAB4Iy0=", + "Bk0zP1Njm5M=", + "RG5lu2TSBAE=" + ], "classic phase bumps sequence of soroban source account|protocol version 20" : [ "NTGGdj1offM=", "FVbub/Ss/Xg=", "9Rpfyyb4ewI=" ], "classic phase bumps sequence of soroban source account|protocol version 21" : [ "NTGGdj1offM=", "FVbub/Ss/Xg=", "9Rpfyyb4ewI=" ], "classic phase bumps sequence of soroban source account|protocol version 22" : [ "NTGGdj1offM=", "CTLGLR5LLHY=", "xXpwdFz6+Uc=" ],