From 02b730fa5decdbc86ccef8b83412785ce55fd41a Mon Sep 17 00:00:00 2001 From: dmkozh Date: Mon, 3 Aug 2026 17:39:42 -0400 Subject: [PATCH] Parallelize Soroban pre-apply step. While the current logic intertwines reads and writes, in fact it can be cleanly separated into a read-only validation step, and a sequential commit step that simply bumps the sequence numbers and removes pre-authorized tx signers. This is possible because that while the writes change the entries that take part in validation, none of these changes are relevant during the validation. Specifically, sequence number bump is only observable by a single transaction (the one that has the respective account as a source), and the pre-authorized tx signer by definition belongs to a single transaction. There is also a subtle caveat to the latter operation: it increases the available balance of the signer owner (or its sponsor), but since at the pre-apply time the fees have already been charged, we're only checking that the account available balance is non-negative, which is an invariant that must always hold in the current protocol. The change is not protocol-gated because it's not a protocol change for the *current* protocol. It was technically a protocol change prior to p26 where we had a bug that actually did allow overcharging the fee bump source accounts and thus making their available balance to go negative. However, the bug has been fixed without the behavior ever triggering on-chain, and thus this replay-only behavior change should be non-observable. This change significantly speeds up the pre-apply step. On the local high TPL benchmarks I'm getting 30-60ms improvement locally compared to the main branch version. --- src/ledger/ImmutableLedgerView.cpp | 70 + src/ledger/ImmutableLedgerView.h | 35 + src/transactions/FeeBumpTransactionFrame.cpp | 39 +- src/transactions/FeeBumpTransactionFrame.h | 13 +- src/transactions/ParallelApplyUtils.cpp | 125 +- src/transactions/ParallelApplyUtils.h | 8 +- src/transactions/TransactionFrame.cpp | 183 +- src/transactions/TransactionFrame.h | 53 +- src/transactions/TransactionFrameBase.h | 19 +- .../test/InvokeHostFunctionTests.cpp | 448 +++- src/transactions/test/ParallelApplyTest.cpp | 304 +++ src/transactions/test/SorobanTxTestUtils.cpp | 9 +- .../test/TransactionTestFrame.cpp | 18 +- src/transactions/test/TransactionTestFrame.h | 13 +- src/util/BatchExecutor.cpp | 29 + src/util/BatchExecutor.h | 17 + .../InvokeHostFunctionTests.json | 1845 +++++++++++++++ .../InvokeHostFunctionTests.json | 2050 +++++++++++++++++ 18 files changed, 5132 insertions(+), 146 deletions(-) diff --git a/src/ledger/ImmutableLedgerView.cpp b/src/ledger/ImmutableLedgerView.cpp index 796e51c5d0..3bc3247627 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 3f6a523ea4..52b30f0321 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 9d62ddba1f..37aa9d3026 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 0d13134229..eccce70180 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 618901d499..701dfa2883 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 7e7fd8b743..62497713c1 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 6d35934553..b50f7115dd 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 f46716a8dd..f0d37a631d 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 0e45aa97ea..3d2a84dc01 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 18cfe946f2..41205b1e59 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 8c9a212cf6..c1350fe7b6 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 4615593862..7e8b3eace9 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 8a94d93d80..41c50f0d09 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 acb3228f83..77b40c81b6 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 324efc429b..9bc3885d19 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 652dfc357c..fc5c01ffe0 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 6a2f0d598a..a5f5930a52 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 6dc67843fa..5c7752e4c9 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=" ],