From aa6ab6c8ebecabb61806fef34146f7f0d895c17c Mon Sep 17 00:00:00 2001 From: Thomas Brady Date: Fri, 22 Nov 2024 22:42:25 -0800 Subject: [PATCH 1/2] WIP use root account for soroban upgrades in loadgen --- src/simulation/LoadGenerator.cpp | 49 +++++++++++++++++++++++++++----- src/simulation/LoadGenerator.h | 5 ++++ src/simulation/TxGenerator.cpp | 36 +++++++++++++++++++++-- src/simulation/TxGenerator.h | 18 ++++++++++++ src/test/TestUtils.cpp | 21 +------------- 5 files changed, 99 insertions(+), 30 deletions(-) diff --git a/src/simulation/LoadGenerator.cpp b/src/simulation/LoadGenerator.cpp index fd124f321d..1e74dc5700 100644 --- a/src/simulation/LoadGenerator.cpp +++ b/src/simulation/LoadGenerator.cpp @@ -657,7 +657,11 @@ LoadGenerator::generateLoad(GeneratedLoadConfig cfg) return; } - uint64_t sourceAccountId = getNextAvailableAccount(ledgerNum); + uint64_t sourceAccountId = 0; + if (!cfg.useRootAccountForSorobanUpgradeFlow) + { + sourceAccountId = getNextAvailableAccount(ledgerNum); + } std::function()> @@ -753,6 +757,14 @@ LoadGenerator::generateLoad(GeneratedLoadConfig cfg) auto upgradeBytes = mTxGenerator.getConfigUpgradeSetFromLoadConfig( cfg.getSorobanUpgradeConfig()); + if (cfg.useRootAccountForSorobanUpgradeFlow) + { + return mTxGenerator + .invokeSorobanCreateUpgradeTransaction( + mRoot, upgradeBytes, *mCodeKey, + *mContractInstanceKeys.begin(), + cfg.maxGeneratedFeeRate); + } return mTxGenerator.invokeSorobanCreateUpgradeTransaction( ledgerNum, sourceAccountId, upgradeBytes, *mCodeKey, *mContractInstanceKeys.begin(), @@ -1083,9 +1095,17 @@ LoadGenerator::createUploadWasmTransaction(GeneratedLoadConfig const& cfg, // instance and ContractCode LE overhead mContactOverheadBytes = wasmBytes.size() + 160; - return mTxGenerator.createUploadWasmTransaction(ledgerNum, sourceAccountId, - wasmBytes, *mCodeKey, - cfg.maxGeneratedFeeRate); + if (cfg.useRootAccountForSorobanUpgradeFlow) + { + return mTxGenerator.createUploadWasmTransaction( + mRoot, wasmBytes, *mCodeKey, cfg.maxGeneratedFeeRate); + } + else + { + return mTxGenerator.createUploadWasmTransaction( + ledgerNum, sourceAccountId, wasmBytes, *mCodeKey, + cfg.maxGeneratedFeeRate); + } } std::pair @@ -1096,9 +1116,19 @@ LoadGenerator::createInstanceTransaction(GeneratedLoadConfig const& cfg, auto salt = sha256("upgrade" + std::to_string(++mNumCreateContractTransactionCalls)); - auto txPair = mTxGenerator.createContractTransaction( - ledgerNum, sourceAccountId, *mCodeKey, mContactOverheadBytes, salt, - cfg.maxGeneratedFeeRate); + std::pair txPair; + if (cfg.useRootAccountForSorobanUpgradeFlow) + { + txPair = mTxGenerator.createContractTransaction( + mRoot, *mCodeKey, mContactOverheadBytes, salt, + cfg.maxGeneratedFeeRate); + } + else + { + txPair = mTxGenerator.createContractTransaction( + ledgerNum, sourceAccountId, *mCodeKey, mContactOverheadBytes, salt, + cfg.maxGeneratedFeeRate); + } auto const& instanceLk = txPair.second->sorobanResources().footprint.readWrite.back(); @@ -1564,6 +1594,7 @@ GeneratedLoadConfig::createSorobanUpgradeSetupLoad() cfg.nAccounts = 1; cfg.getMutSorobanConfig().nInstances = 1; cfg.txRate = 1; + cfg.useRootAccountForSorobanUpgradeFlow = true; return cfg; } @@ -1573,6 +1604,10 @@ GeneratedLoadConfig::txLoad(LoadGenMode mode, uint32_t nAccounts, uint32_t nTxs, std::optional maxFee) { GeneratedLoadConfig cfg; + if (mode == LoadGenMode::SOROBAN_CREATE_UPGRADE) + { + cfg.useRootAccountForSorobanUpgradeFlow = true; + } cfg.mode = mode; cfg.nAccounts = nAccounts; cfg.nTxs = nTxs; diff --git a/src/simulation/LoadGenerator.h b/src/simulation/LoadGenerator.h index 0fd898176a..f57def9e35 100644 --- a/src/simulation/LoadGenerator.h +++ b/src/simulation/LoadGenerator.h @@ -117,6 +117,7 @@ struct GeneratedLoadConfig Json::Value getStatus() const; LoadGenMode mode = LoadGenMode::CREATE; + bool useRootAccountForSorobanUpgradeFlow = false; uint32_t nAccounts = 0; uint32_t offset = 0; uint32_t nTxs = 0; @@ -329,6 +330,10 @@ class LoadGenerator std::pair createUploadWasmTransaction(GeneratedLoadConfig const& cfg, uint32_t ledgerNum, uint64_t sourceAccountId); + std::pair + createUploadWasmTransaction(GeneratedLoadConfig const& cfg, + uint32_t ledgerNum, + TxGenerator::TestAccountPtr sourceAccount); std::pair createInstanceTransaction(GeneratedLoadConfig const& cfg, diff --git a/src/simulation/TxGenerator.cpp b/src/simulation/TxGenerator.cpp index b5e938baa3..74fe34e99c 100644 --- a/src/simulation/TxGenerator.cpp +++ b/src/simulation/TxGenerator.cpp @@ -271,8 +271,18 @@ TxGenerator::createUploadWasmTransaction( std::optional maxGeneratedFeeRate, std::optional uploadResources) { - auto account = findAccount(accountId, ledgerNum); + return createUploadWasmTransaction(findAccount(accountId, ledgerNum), wasm, + contractCodeLedgerKey, + maxGeneratedFeeRate, uploadResources); +} +std::pair +TxGenerator::createUploadWasmTransaction( + TxGenerator::TestAccountPtr account, xdr::opaque_vec<> const& wasm, + LedgerKey const& contractCodeLedgerKey, + std::optional maxGeneratedFeeRate, + std::optional uploadResources) +{ if (!uploadResources) { uploadResources = SorobanResources{}; @@ -307,7 +317,16 @@ TxGenerator::createContractTransaction( uint64_t contractOverheadBytes, uint256 const& salt, std::optional maxGeneratedFeeRate) { - auto account = findAccount(accountId, ledgerNum); + return createContractTransaction(findAccount(accountId, ledgerNum), codeKey, + contractOverheadBytes, salt, + maxGeneratedFeeRate); +} +std::pair +TxGenerator::createContractTransaction( + TxGenerator::TestAccountPtr account, LedgerKey const& codeKey, + uint64_t contractOverheadBytes, uint256 const& salt, + std::optional maxGeneratedFeeRate) +{ SorobanResources createResources{}; createResources.instructions = 1'000'000; createResources.readBytes = contractOverheadBytes; @@ -774,7 +793,18 @@ TxGenerator::invokeSorobanCreateUpgradeTransaction( std::optional maxGeneratedFeeRate, std::optional resources) { - auto account = findAccount(accountId, ledgerNum); + return invokeSorobanCreateUpgradeTransaction( + findAccount(accountId, ledgerNum), upgradeBytes, codeKey, instanceKey, + maxGeneratedFeeRate, resources); +} + +std::pair +TxGenerator::invokeSorobanCreateUpgradeTransaction( + TxGenerator::TestAccountPtr account, SCBytes const& upgradeBytes, + LedgerKey const& codeKey, LedgerKey const& instanceKey, + std::optional maxGeneratedFeeRate, + std::optional resources) +{ auto const& contractID = instanceKey.contractData().contract; LedgerKey upgradeLK(CONTRACT_DATA); diff --git a/src/simulation/TxGenerator.h b/src/simulation/TxGenerator.h index ed21ab0dec..562904f673 100644 --- a/src/simulation/TxGenerator.h +++ b/src/simulation/TxGenerator.h @@ -99,6 +99,13 @@ class TxGenerator std::optional maxGeneratedFeeRate, std::optional resources = std::nullopt); std::pair + createUploadWasmTransaction( + TestAccountPtr account, xdr::opaque_vec<> const& wasm, + LedgerKey const& contractCodeLedgerKey, + std::optional maxGeneratedFeeRate, + std::optional resources = std::nullopt); + + std::pair createContractTransaction(uint32_t ledgerNum, uint64_t accountId, LedgerKey const& codeKey, uint64_t contractOverheadBytes, @@ -106,6 +113,11 @@ class TxGenerator std::optional maxGeneratedFeeRate); std::pair + createContractTransaction(TestAccountPtr account, LedgerKey const& codeKey, + uint64_t contractOverheadBytes, + uint256 const& salt, + std::optional maxGeneratedFeeRate); + std::pair invokeSorobanLoadTransaction(uint32_t ledgerNum, uint64_t accountId, TxGenerator::ContractInstance const& instance, uint64_t contractOverheadBytes, @@ -117,6 +129,12 @@ class TxGenerator std::optional maxGeneratedFeeRate, std::optional resources = std::nullopt); std::pair + invokeSorobanCreateUpgradeTransaction( + TestAccountPtr account, SCBytes const& upgradeBytes, + LedgerKey const& codeKey, LedgerKey const& instanceKey, + std::optional maxGeneratedFeeRate, + std::optional resources = std::nullopt); + std::pair sorobanRandomWasmTransaction(uint32_t ledgerNum, uint64_t accountId, uint32_t inclusionFee); diff --git a/src/test/TestUtils.cpp b/src/test/TestUtils.cpp index b351112bd8..985164f8e2 100644 --- a/src/test/TestUtils.cpp +++ b/src/test/TestUtils.cpp @@ -188,29 +188,11 @@ upgradeSorobanNetworkConfig(std::function modifyFn, auto& complete = app.getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); - auto completeCount = complete.count(); - // Only create an account if there are none aleady created. - uint32_t offset = 0; - if (app.getMetrics() - .NewMeter({"loadgen", "account", "created"}, "account") - .count() == 0) - { - auto createAccountsLoadConfig = - GeneratedLoadConfig::createAccountsLoad(1, 1); - offset = std::numeric_limits::max() - 1; - createAccountsLoadConfig.offset = offset; - - lg.generateLoad(createAccountsLoadConfig); - simulation->crankUntil( - [&]() { return complete.count() == completeCount + 1; }, - 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); - } // Create upload wasm transaction. auto createUploadCfg = GeneratedLoadConfig::createSorobanUpgradeSetupLoad(); - createUploadCfg.offset = offset; lg.generateLoad(createUploadCfg); - completeCount = complete.count(); + auto completeCount = complete.count(); simulation->crankUntil( [&]() { return complete.count() == completeCount + 1; }, 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); @@ -218,7 +200,6 @@ upgradeSorobanNetworkConfig(std::function modifyFn, // Create upgrade transaction. auto createUpgradeLoadGenConfig = GeneratedLoadConfig::txLoad( LoadGenMode::SOROBAN_CREATE_UPGRADE, 1, 1, 1); - createUpgradeLoadGenConfig.offset = offset; // Get current network config. auto cfg = nodes[0]->getLedgerManager().getSorobanNetworkConfig(); modifyFn(cfg); From 263942e0291bbb6db244d53122026c3f883a8719 Mon Sep 17 00:00:00 2001 From: Thomas Brady Date: Mon, 25 Nov 2024 21:28:13 -0800 Subject: [PATCH 2/2] Fix timing out 'generate soroban load' by special casing two-part upgrade sequence retries --- src/simulation/LoadGenerator.cpp | 38 ++++++++++++++++++++++++++------ src/test/TestUtils.cpp | 5 +++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/simulation/LoadGenerator.cpp b/src/simulation/LoadGenerator.cpp index 1e74dc5700..78c5a1f70e 100644 --- a/src/simulation/LoadGenerator.cpp +++ b/src/simulation/LoadGenerator.cpp @@ -783,6 +783,19 @@ LoadGenerator::generateLoad(GeneratedLoadConfig cfg) { --cfg.nTxs; } + else if (cfg.mode == LoadGenMode::SOROBAN_UPGRADE_SETUP && + cfg.useRootAccountForSorobanUpgradeFlow) + { + // If submission failed during SOROBAN_UPGRADE_SETUP, the + // contract instance key must be regenerated + // so we reset the nInstances to 1 to prevent + // subtracting past zero. + auto& sorobanCfg = cfg.getMutSorobanConfig(); + if (sorobanCfg.nInstances == 0) + { + sorobanCfg.nInstances = 1; + } + } else if (mFailed) { break; @@ -864,11 +877,9 @@ LoadGenerator::submitTx(GeneratedLoadConfig const& cfg, TransactionResultCode code; TransactionQueue::AddResultCode status; uint32_t numTries = 0; - while ((status = execute(tx, cfg.mode, code)) != TransactionQueue::AddResultCode::ADD_STATUS_PENDING) { - if (cfg.skipLowFeeTxs && (status == TransactionQueue::AddResultCode::ADD_STATUS_TRY_AGAIN_LATER || @@ -882,6 +893,24 @@ LoadGenerator::submitTx(GeneratedLoadConfig const& cfg, tx->getInclusionFee()); return false; } + // If we are using the root account to perform a soroban upgrade flow, + // retry the transaction. + if (cfg.mode == LoadGenMode::SOROBAN_UPGRADE_SETUP && + cfg.useRootAccountForSorobanUpgradeFlow) + { + if (status == TransactionQueue::AddResultCode:: + ADD_STATUS_TRY_AGAIN_LATER || + (status == TransactionQueue::AddResultCode::ADD_STATUS_ERROR && + code == txBAD_SEQ)) + { + // The next attempt will regenerate a contract instance key. + mContractInstanceKeys.clear(); + maybeHandleFailedTx(tx, from, status, code); // Update seq num + return false; + } + mFailed = true; + return false; + } if (++numTries >= TX_SUBMIT_MAX_TRIES || status != TransactionQueue::AddResultCode::ADD_STATUS_ERROR) { @@ -1594,7 +1623,6 @@ GeneratedLoadConfig::createSorobanUpgradeSetupLoad() cfg.nAccounts = 1; cfg.getMutSorobanConfig().nInstances = 1; cfg.txRate = 1; - cfg.useRootAccountForSorobanUpgradeFlow = true; return cfg; } @@ -1604,10 +1632,6 @@ GeneratedLoadConfig::txLoad(LoadGenMode mode, uint32_t nAccounts, uint32_t nTxs, std::optional maxFee) { GeneratedLoadConfig cfg; - if (mode == LoadGenMode::SOROBAN_CREATE_UPGRADE) - { - cfg.useRootAccountForSorobanUpgradeFlow = true; - } cfg.mode = mode; cfg.nAccounts = nAccounts; cfg.nTxs = nTxs; diff --git a/src/test/TestUtils.cpp b/src/test/TestUtils.cpp index 985164f8e2..61f1452a99 100644 --- a/src/test/TestUtils.cpp +++ b/src/test/TestUtils.cpp @@ -185,21 +185,22 @@ upgradeSorobanNetworkConfig(std::function modifyFn, auto nodes = simulation->getNodes(); auto& lg = nodes[0]->getLoadGenerator(); auto& app = *nodes[0]; - auto& complete = app.getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); // Create upload wasm transaction. auto createUploadCfg = GeneratedLoadConfig::createSorobanUpgradeSetupLoad(); + createUploadCfg.useRootAccountForSorobanUpgradeFlow = true; lg.generateLoad(createUploadCfg); auto completeCount = complete.count(); simulation->crankUntil( - [&]() { return complete.count() == completeCount + 1; }, + [&]() { return complete.count() >= completeCount + 1; }, 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); // Create upgrade transaction. auto createUpgradeLoadGenConfig = GeneratedLoadConfig::txLoad( LoadGenMode::SOROBAN_CREATE_UPGRADE, 1, 1, 1); + createUpgradeLoadGenConfig.useRootAccountForSorobanUpgradeFlow = true; // Get current network config. auto cfg = nodes[0]->getLedgerManager().getSorobanNetworkConfig(); modifyFn(cfg);