From ebb09ed8df5de09f6a088acb29ccef4950e5f05f Mon Sep 17 00:00:00 2001 From: Thomas Brady Date: Mon, 12 Aug 2024 16:52:56 -0700 Subject: [PATCH] soroban upgrades for simulation tests --- src/herder/Upgrades.h | 4 +- src/herder/test/HerderTests.cpp | 103 ++++++++-------- src/overlay/test/OverlayTests.cpp | 27 +++-- src/simulation/LoadGenerator.cpp | 92 +++++++++++++- src/simulation/LoadGenerator.h | 10 ++ src/simulation/test/LoadGeneratorTests.cpp | 132 ++++++++++++++------- src/test/TestUtils.cpp | 100 +++++++++++++++- src/test/TestUtils.h | 9 ++ 8 files changed, 363 insertions(+), 114 deletions(-) diff --git a/src/herder/Upgrades.h b/src/herder/Upgrades.h index b182d5b7ef..4fcfaca646 100644 --- a/src/herder/Upgrades.h +++ b/src/herder/Upgrades.h @@ -159,6 +159,8 @@ class ConfigUpgradeSetFrame static ConfigUpgradeSetFrameConstPtr makeFromKey(AbstractLedgerTxn& ltx, ConfigUpgradeSetKey const& key); + static LedgerKey getLedgerKey(ConfigUpgradeSetKey const& upgradeKey); + ConfigUpgradeSet const& toXDR() const; ConfigUpgradeSetKey const& getKey() const; @@ -182,8 +184,6 @@ class ConfigUpgradeSetFrame ConfigUpgradeSetKey const& key, uint32_t ledgerVersion); - static LedgerKey getLedgerKey(ConfigUpgradeSetKey const& upgradeKey); - bool isValidXDR(ConfigUpgradeSet const& upgradeSetXDR, ConfigUpgradeSetKey const& key) const; diff --git a/src/herder/test/HerderTests.cpp b/src/herder/test/HerderTests.cpp index b0c37e1b13..7acfb12686 100644 --- a/src/herder/test/HerderTests.cpp +++ b/src/herder/test/HerderTests.cpp @@ -3213,32 +3213,31 @@ TEST_CASE("soroban txs each parameter surge priced", "[soroban][herder]") }); simulation->startAllNodes(); auto nodes = simulation->getNodes(); - for (auto& node : nodes) - { - overrideSorobanNetworkConfigForTest(*node); - modifySorobanNetworkConfig( - *node, [&tweakSorobanConfig](SorobanNetworkConfig& cfg) { - auto mx = std::numeric_limits::max(); - // Set all Soroban resources to maximum initially; each - // section will adjust the config as desired - cfg.mLedgerMaxTxCount = mx; - cfg.mLedgerMaxInstructions = mx; - cfg.mLedgerMaxTransactionsSizeBytes = mx; - cfg.mLedgerMaxReadLedgerEntries = mx; - cfg.mLedgerMaxReadBytes = mx; - cfg.mLedgerMaxWriteLedgerEntries = mx; - cfg.mLedgerMaxWriteBytes = mx; - tweakSorobanConfig(cfg); - }); - } + upgradeSorobanNetworkConfig( + [&tweakSorobanConfig](SorobanNetworkConfig& cfg) { + auto mx = std::numeric_limits::max(); + // Set all Soroban resources to maximum initially; each + // section will adjust the config as desired + cfg.mLedgerMaxTxCount = mx; + cfg.mLedgerMaxInstructions = mx; + cfg.mLedgerMaxTransactionsSizeBytes = mx; + cfg.mLedgerMaxReadLedgerEntries = mx; + cfg.mLedgerMaxReadBytes = mx; + cfg.mLedgerMaxWriteLedgerEntries = mx; + cfg.mLedgerMaxWriteBytes = mx; + tweakSorobanConfig(cfg); + }, + simulation); auto& loadGen = nodes[0]->getLoadGenerator(); // Generate some accounts auto& loadGenDone = nodes[0]->getMetrics().NewMeter( {"loadgen", "run", "complete"}, "run"); auto currLoadGenCount = loadGenDone.count(); - loadGen.generateLoad(GeneratedLoadConfig::createAccountsLoad( - numAccounts, baseTxRate)); + auto creationConfig = GeneratedLoadConfig::createAccountsLoad( + numAccounts, baseTxRate); + creationConfig.offset = 1; + loadGen.generateLoad(creationConfig); simulation->crankUntil( [&]() { return loadGenDone.count() > currLoadGenCount; }, 10 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); @@ -3435,6 +3434,7 @@ TEST_CASE("accept soroban txs after network upgrade", "[soroban][herder]") 15); scheduledUpgrades.mProtocolVersion = static_cast(SOROBAN_PROTOCOL_VERSION); + // TODO maybe use loadgen for these upgrades for (auto const& app : nodes) { app->getHerder().setUpgrades(scheduledUpgrades); @@ -3513,22 +3513,23 @@ TEST_CASE("overlay parallel processing") uint32_t desiredTxRate = 1; uint32_t ledgerWideLimit = static_cast( desiredTxRate * Herder::EXP_LEDGER_TIMESPAN_SECONDS.count() * 2); - uint32_t const numAccounts = 100; - for (auto& node : nodes) - { - overrideSorobanNetworkConfigForTest(*node); - modifySorobanNetworkConfig(*node, [&](SorobanNetworkConfig& cfg) { + upgradeSorobanNetworkConfig( + [&](SorobanNetworkConfig& cfg) { + setSorobanNetworkConfigForTest(cfg); cfg.mLedgerMaxTxCount = ledgerWideLimit; - }); - } + }, + simulation); auto& loadGen = nodes[0]->getLoadGenerator(); // Generate some accounts auto& loadGenDone = nodes[0]->getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); auto currLoadGenCount = loadGenDone.count(); - loadGen.generateLoad( - GeneratedLoadConfig::createAccountsLoad(numAccounts, desiredTxRate)); + uint32_t const numAccounts = 100; + auto creationConfig = + GeneratedLoadConfig::createAccountsLoad(numAccounts, desiredTxRate); + creationConfig.offset = 1; + loadGen.generateLoad(creationConfig); simulation->crankUntil( [&]() { return loadGenDone.count() > currLoadGenCount; }, 10 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); @@ -3583,13 +3584,13 @@ TEST_CASE("soroban txs accepted by the network", uint32_t ledgerWideLimit = static_cast( desiredTxRate * Herder::EXP_LEDGER_TIMESPAN_SECONDS.count() * 2); uint32_t const numAccounts = 100; - for (auto& node : nodes) - { - overrideSorobanNetworkConfigForTest(*node); - modifySorobanNetworkConfig(*node, [&](SorobanNetworkConfig& cfg) { + upgradeSorobanNetworkConfig( + [&](SorobanNetworkConfig& cfg) { + setSorobanNetworkConfigForTest(cfg); cfg.mLedgerMaxTxCount = ledgerWideLimit; - }); - } + }, + simulation); + auto& loadGen = nodes[0]->getLoadGenerator(); auto& txsSucceeded = nodes[0]->getMetrics().NewCounter({"ledger", "apply", "success"}); @@ -3604,8 +3605,10 @@ TEST_CASE("soroban txs accepted by the network", auto& loadGenDone = nodes[0]->getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); auto currLoadGenCount = loadGenDone.count(); - loadGen.generateLoad( - GeneratedLoadConfig::createAccountsLoad(numAccounts, desiredTxRate)); + auto creationConfig = + GeneratedLoadConfig::createAccountsLoad(numAccounts, desiredTxRate); + creationConfig.offset = 1; + loadGen.generateLoad(creationConfig); simulation->crankUntil( [&]() { return loadGenDone.count() > currLoadGenCount; }, 10 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); @@ -3864,12 +3867,11 @@ herderExternalizesValuesWithProtocol(uint32_t version) if (protocolVersionStartsFrom(version, SOROBAN_PROTOCOL_VERSION)) { - for (auto const& node : simulation->getNodes()) - { - modifySorobanNetworkConfig(*node, [&](SorobanNetworkConfig& cfg) { + upgradeSorobanNetworkConfig( + [&](SorobanNetworkConfig& cfg) { cfg.mStateArchivalSettings.bucketListWindowSamplePeriod = 1; - }); - } + }, + simulation); } simulation->startAllNodes(); @@ -4660,20 +4662,17 @@ TEST_CASE("do not flood too many soroban transactions", simulation->addNode(mainKey, qset); simulation->addNode(otherKey, qset); - auto updateSorobanConfig = [](Application& app) { - overrideSorobanNetworkConfigForTest(app); - modifySorobanNetworkConfig(app, [](SorobanNetworkConfig& cfg) { + auto app = simulation->getNode(mainKey.getPublicKey()); + + upgradeSorobanNetworkConfig( + [](SorobanNetworkConfig& cfg) { + setSorobanNetworkConfigForTest(cfg); // Update read entries to allow flooding at most 1 tx per broadcast // interval. cfg.mLedgerMaxReadLedgerEntries = 40; cfg.mLedgerMaxReadBytes = cfg.mTxMaxReadBytes; - }); - }; - - auto app = simulation->getNode(mainKey.getPublicKey()); - - updateSorobanConfig(*app); - updateSorobanConfig(*simulation->getNode(otherKey.getPublicKey())); + }, + simulation); simulation->addPendingConnection(mainKey.getPublicKey(), otherKey.getPublicKey()); diff --git a/src/overlay/test/OverlayTests.cpp b/src/overlay/test/OverlayTests.cpp index 45da9a9460..3ec47d99ac 100644 --- a/src/overlay/test/OverlayTests.cpp +++ b/src/overlay/test/OverlayTests.cpp @@ -2141,18 +2141,17 @@ TEST_CASE("overlay flow control", "[overlay][flowcontrol]") simulation->addPendingConnection(vNode2NodeID, vNode3NodeID); simulation->addPendingConnection(vNode3NodeID, vNode1NodeID); - for (auto& node2 : simulation->getNodes()) + simulation->startAllNodes(); + if (appProtocolVersionStartsFrom(*simulation->getNodes()[0], + SOROBAN_PROTOCOL_VERSION)) { - if (appProtocolVersionStartsFrom(*node2, SOROBAN_PROTOCOL_VERSION)) - { - modifySorobanNetworkConfig( - *node2, [](SorobanNetworkConfig& cfg) { - cfg.mTxMaxSizeBytes = - MinimumSorobanNetworkConfig::TX_MAX_SIZE_BYTES; - }); - } + upgradeSorobanNetworkConfig( + [](SorobanNetworkConfig& cfg) { + cfg.mTxMaxSizeBytes = + MinimumSorobanNetworkConfig::TX_MAX_SIZE_BYTES; + }, + simulation); } - simulation->startAllNodes(); }; SECTION("enabled") @@ -2165,9 +2164,11 @@ TEST_CASE("overlay flow control", "[overlay][flowcontrol]") // Generate a bit of load to flood transactions, make sure nodes can // close ledgers properly auto& loadGen = node->getLoadGenerator(); - loadGen.generateLoad( - GeneratedLoadConfig::createAccountsLoad(/* nAccounts */ 150, - /* txRate */ 1)); + auto createAccountCfg = GeneratedLoadConfig::createAccountsLoad( + /* nAccounts */ 150, + /* txRate */ 1); + createAccountCfg.offset = 1; + loadGen.generateLoad(createAccountCfg); auto& loadGenDone = node->getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); diff --git a/src/simulation/LoadGenerator.cpp b/src/simulation/LoadGenerator.cpp index 9805934771..694fdc0002 100644 --- a/src/simulation/LoadGenerator.cpp +++ b/src/simulation/LoadGenerator.cpp @@ -3,6 +3,7 @@ // of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 #include "simulation/LoadGenerator.h" +#include "database/Database.h" #include "herder/Herder.h" #include "ledger/LedgerManager.h" #include "ledger/LedgerTxn.h" @@ -23,8 +24,6 @@ #include "util/numeric.h" #include "util/types.h" -#include "database/Database.h" - #include "xdrpp/marshal.h" #include "medida/meter.h" @@ -1565,12 +1564,50 @@ LoadGenerator::getConfigUpgradeSetFromLoadConfig( case CONFIG_SETTING_STATE_ARCHIVAL: { auto& ses = setting.stateArchivalSettings(); + if (upgradeCfg.maxEntryTTL > 0) + { + ses.maxEntryTTL = upgradeCfg.maxEntryTTL; + } + + if (upgradeCfg.minTemporaryTTL > 0) + { + ses.minTemporaryTTL = upgradeCfg.minTemporaryTTL; + } + + if (upgradeCfg.minPersistentTTL > 0) + { + ses.minPersistentTTL = upgradeCfg.minPersistentTTL; + } + + if (upgradeCfg.persistentRentRateDenominator > 0) + { + ses.persistentRentRateDenominator = + upgradeCfg.persistentRentRateDenominator; + } + + if (upgradeCfg.tempRentRateDenominator > 0) + { + ses.tempRentRateDenominator = + upgradeCfg.tempRentRateDenominator; + } + + if (upgradeCfg.maxEntriesToArchive > 0) + { + ses.maxEntriesToArchive = upgradeCfg.maxEntriesToArchive; + } + if (upgradeCfg.bucketListSizeWindowSampleSize > 0) { ses.bucketListSizeWindowSampleSize = upgradeCfg.bucketListSizeWindowSampleSize; } + if (upgradeCfg.bucketListWindowSamplePeriod > 0) + { + ses.bucketListWindowSamplePeriod = + upgradeCfg.bucketListWindowSamplePeriod; + } + if (upgradeCfg.evictionScanSize > 0) { ses.evictionScanSize = upgradeCfg.evictionScanSize; @@ -2202,6 +2239,57 @@ LoadGenerator::execute(TransactionTestFramePtr& txf, LoadGenMode mode, return addResult.code; } +void +GeneratedLoadConfig::copySorobanNetworkConfigToUpgradeConfig( + SorobanNetworkConfig const& cfg) +{ + releaseAssert(mode == LoadGenMode::SOROBAN_CREATE_UPGRADE); + auto& upgradeCfg = getMutSorobanUpgradeConfig(); + + upgradeCfg.maxContractSizeBytes = cfg.maxContractSizeBytes(); + upgradeCfg.maxContractDataKeySizeBytes = cfg.maxContractDataKeySizeBytes(); + upgradeCfg.maxContractDataEntrySizeBytes = + cfg.maxContractDataEntrySizeBytes(); + + upgradeCfg.ledgerMaxInstructions = cfg.ledgerMaxInstructions(); + upgradeCfg.txMaxInstructions = cfg.txMaxInstructions(); + upgradeCfg.txMemoryLimit = cfg.txMemoryLimit(); + + upgradeCfg.ledgerMaxReadLedgerEntries = cfg.ledgerMaxReadLedgerEntries(); + upgradeCfg.ledgerMaxReadBytes = cfg.ledgerMaxReadBytes(); + upgradeCfg.ledgerMaxWriteLedgerEntries = cfg.ledgerMaxWriteLedgerEntries(); + upgradeCfg.ledgerMaxWriteBytes = cfg.ledgerMaxWriteBytes(); + upgradeCfg.ledgerMaxTxCount = cfg.ledgerMaxTxCount(); + upgradeCfg.txMaxReadLedgerEntries = cfg.txMaxReadLedgerEntries(); + upgradeCfg.txMaxReadBytes = cfg.txMaxReadBytes(); + upgradeCfg.txMaxWriteLedgerEntries = cfg.txMaxWriteLedgerEntries(); + upgradeCfg.txMaxWriteBytes = cfg.txMaxWriteBytes(); + + upgradeCfg.txMaxContractEventsSizeBytes = + cfg.txMaxContractEventsSizeBytes(); + + upgradeCfg.ledgerMaxTransactionsSizeBytes = + cfg.ledgerMaxTransactionSizesBytes(); + upgradeCfg.txMaxSizeBytes = cfg.txMaxSizeBytes(); + + upgradeCfg.maxEntryTTL = cfg.stateArchivalSettings().maxEntryTTL; + upgradeCfg.minTemporaryTTL = cfg.stateArchivalSettings().minTemporaryTTL; + upgradeCfg.minPersistentTTL = cfg.stateArchivalSettings().minPersistentTTL; + upgradeCfg.persistentRentRateDenominator = + cfg.stateArchivalSettings().persistentRentRateDenominator; + upgradeCfg.tempRentRateDenominator = + cfg.stateArchivalSettings().tempRentRateDenominator; + upgradeCfg.maxEntriesToArchive = + cfg.stateArchivalSettings().maxEntriesToArchive; + upgradeCfg.bucketListSizeWindowSampleSize = + cfg.stateArchivalSettings().bucketListSizeWindowSampleSize; + upgradeCfg.bucketListWindowSamplePeriod = + cfg.stateArchivalSettings().bucketListWindowSamplePeriod; + upgradeCfg.evictionScanSize = cfg.stateArchivalSettings().evictionScanSize; + upgradeCfg.startingEvictionScanLevel = + cfg.stateArchivalSettings().startingEvictionScanLevel; +} + GeneratedLoadConfig GeneratedLoadConfig::createAccountsLoad(uint32_t nAccounts, uint32_t txRate) { diff --git a/src/simulation/LoadGenerator.h b/src/simulation/LoadGenerator.h index 9e441e5900..0d053765d4 100644 --- a/src/simulation/LoadGenerator.h +++ b/src/simulation/LoadGenerator.h @@ -92,7 +92,14 @@ struct GeneratedLoadConfig uint32_t txMaxSizeBytes{}; // State Archival Settings + uint32_t maxEntryTTL{}; + uint32_t minTemporaryTTL{}; + uint32_t minPersistentTTL{}; + int64_t persistentRentRateDenominator{}; + int64_t tempRentRateDenominator{}; + uint32_t maxEntriesToArchive{}; uint32_t bucketListSizeWindowSampleSize{}; + uint32_t bucketListWindowSamplePeriod{}; uint32_t evictionScanSize{}; uint32_t startingEvictionScanLevel{}; }; @@ -107,6 +114,9 @@ struct GeneratedLoadConfig double sorobanInvokeWeight = 0; }; + void + copySorobanNetworkConfigToUpgradeConfig(SorobanNetworkConfig const& cfg); + static GeneratedLoadConfig createAccountsLoad(uint32_t nAccounts, uint32_t txRate); diff --git a/src/simulation/test/LoadGeneratorTests.cpp b/src/simulation/test/LoadGeneratorTests.cpp index 03865af2f5..1ffff978c1 100644 --- a/src/simulation/test/LoadGeneratorTests.cpp +++ b/src/simulation/test/LoadGeneratorTests.cpp @@ -91,6 +91,68 @@ TEST_CASE("generate load with unique accounts", "[loadgen]") } } +TEST_CASE("modify soroban network config", "[loadgen][soroban]") +{ + Hash networkID = sha256(getTestConfig().NETWORK_PASSPHRASE); + Simulation::pointer simulation = + Topologies::pair(Simulation::OVER_LOOPBACK, networkID, [&](int i) { + auto cfg = getTestConfig(i); + return cfg; + }); + + simulation->startAllNodes(); + simulation->crankUntil( + [&]() { return simulation->haveAllExternalized(3, 1); }, + 2 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); + auto nodes = simulation->getNodes(); + auto& app = *nodes[0]; // pick a node to generate load + + // Manually override network settings for invoke load gen + const uint32_t ledgerMaxTxCount = 42; + const uint32_t bucketListSizeWindowSampleSize = 99; + auto upgradeSetKey = upgradeSorobanNetworkConfig( + [&](SorobanNetworkConfig& cfg) { + cfg.mLedgerMaxTxCount = ledgerMaxTxCount; + cfg.stateArchivalSettings().bucketListSizeWindowSampleSize = + bucketListSizeWindowSampleSize; + }, + simulation); + ConfigUpgradeSet upgrades; + { + LedgerTxn ltx(app.getLedgerTxnRoot()); + auto lk = ConfigUpgradeSetFrame::getLedgerKey(upgradeSetKey); + auto upgradeSet = ltx.load(lk); + REQUIRE(upgradeSet); + xdr::xdr_from_opaque( + upgradeSet.current().data.contractData().val.bytes(), upgrades); + REQUIRE(upgrades.updatedEntry[CONFIG_SETTING_CONTRACT_EXECUTION_LANES] + .contractExecutionLanes() + .ledgerMaxTxCount == ledgerMaxTxCount); + REQUIRE(upgrades.updatedEntry[CONFIG_SETTING_STATE_ARCHIVAL] + .stateArchivalSettings() + .bucketListSizeWindowSampleSize == + bucketListSizeWindowSampleSize); + } + + for (auto const& setting : upgrades.updatedEntry) + { + switch (setting.configSettingID()) + { + case CONFIG_SETTING_CONTRACT_EXECUTION_LANES: + REQUIRE(setting.contractExecutionLanes().ledgerMaxTxCount == + ledgerMaxTxCount); + break; + case CONFIG_SETTING_STATE_ARCHIVAL: + REQUIRE(setting.stateArchivalSettings() + .bucketListSizeWindowSampleSize == + bucketListSizeWindowSampleSize); + break; + default: + break; + } + } +} + TEST_CASE("generate soroban load", "[loadgen][soroban]") { uint32_t const numDataEntries = 5; @@ -121,6 +183,7 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") 2 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); auto nodes = simulation->getNodes(); + auto& app = *nodes[0]; // pick a node to generate load auto& loadGen = app.getLoadGenerator(); auto getSuccessfulTxCount = [&]() { @@ -134,24 +197,20 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") loadGen.generateLoad(GeneratedLoadConfig::createAccountsLoad( /* nAccounts */ nAccounts, /* txRate */ 1)); + auto& complete = + app.getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); + auto completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "complete"}, "run") - .count() == 1; - }, + [&]() { return complete.count() == completeCount + 1; }, 100 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); int64_t numTxsBefore = getSuccessfulTxCount(); // Make sure config upgrade works with initial network config settings loadGen.generateLoad(GeneratedLoadConfig::createSorobanUpgradeSetupLoad()); + completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "complete"}, "run") - .count() == 2; - }, + [&]() { return complete.count() == completeCount + 1; }, 100 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); // Check that Soroban TXs were successfully applied @@ -219,12 +278,9 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") numTxsBefore = getSuccessfulTxCount(); loadGen.generateLoad(createUpgradeLoadGenConfig); + completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "complete"}, "run") - .count() == 3; - }, + [&]() { return complete.count() == completeCount + 1; }, 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); for (auto node : nodes) @@ -339,13 +395,13 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") } } - // Manually override network settings for invoke load gen - for (auto node : nodes) - { - overrideSorobanNetworkConfigForTest(*node); - modifySorobanNetworkConfig(*node, [&](SorobanNetworkConfig& cfg) { + // Override network settings for invoke load gen + upgradeSorobanNetworkConfig( + [&](SorobanNetworkConfig& cfg) { + setSorobanNetworkConfigForTest(cfg); + // Entries should never expire - cfg.mStateArchivalSettings.maxEntryTTL = 1'000'000; + cfg.mStateArchivalSettings.maxEntryTTL = 2'000'000; cfg.mStateArchivalSettings.minPersistentTTL = 1'000'000; // Set write limits so that we can write all keys in a single TX @@ -366,22 +422,19 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") cfg.mTxMaxWriteBytes * cfg.mLedgerMaxTxCount; cfg.mLedgerMaxTransactionsSizeBytes = cfg.mTxMaxSizeBytes * cfg.mLedgerMaxTxCount; - }); - } - + }, + simulation); auto const numInstances = 10; auto const numSorobanTxs = 100; numTxsBefore = getSuccessfulTxCount(); + loadGen.generateLoad(GeneratedLoadConfig::createSorobanInvokeSetupLoad( /* nAccounts */ nAccounts, numInstances, /* txRate */ 1)); + completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "complete"}, "run") - .count() == 4; - }, + [&]() { return complete.count() == completeCount + 1; }, 100 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); // Check that Soroban TXs were successfully applied @@ -409,12 +462,9 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") invokeLoadCfg.setMinSorobanPercentSuccess(100 - maxInvokeFail); loadGen.generateLoad(invokeLoadCfg); + completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "complete"}, "run") - .count() == 5; - }, + [&]() { return complete.count() == completeCount + 1; }, 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); // Check that Soroban TXs were successfully applied @@ -511,12 +561,9 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") app.getMetrics() .NewCounter({"ledger", "apply-soroban", "failure"}) .count(); + completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "complete"}, "run") - .count() == 6; - }, + [&]() { return complete.count() == completeCount + 1; }, 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); // Check results @@ -563,12 +610,9 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") // LoadGen should fail loadGen.generateLoad(uploadFailCfg); + completeCount = complete.count(); simulation->crankUntil( - [&]() { - return app.getMetrics() - .NewMeter({"loadgen", "run", "failed"}, "run") - .count() == 1; - }, + [&]() { return complete.count() == completeCount + 1; }, 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); } } diff --git a/src/test/TestUtils.cpp b/src/test/TestUtils.cpp index 3b35dd71d5..dc6d25a949 100644 --- a/src/test/TestUtils.cpp +++ b/src/test/TestUtils.cpp @@ -3,11 +3,14 @@ // of this distribution or at http://www.apache.org/licenses/LICENSE-2.0 #include "TestUtils.h" +#include "ledger/LedgerTxn.h" #include "overlay/test/LoopbackPeer.h" +#include "simulation/LoadGenerator.h" +#include "simulation/Simulation.h" #include "test/TxTests.h" #include "test/test.h" +#include "util/StatusManager.h" #include "work/WorkScheduler.h" -#include "xdr/Stellar-ledger-entries.h" namespace stellar { @@ -194,6 +197,70 @@ genesis(int minute, int second) getTestDateTime(1, 7, 2014, 0, minute, second)); } +ConfigUpgradeSetKey +upgradeSorobanNetworkConfig(std::function modifyFn, + SimulationPtr simulation) +{ + auto nodes = simulation->getNodes(); + auto& lg = nodes[0]->getLoadGenerator(); + auto& app = *nodes[0]; + + auto& complete = + app.getMetrics().NewMeter({"loadgen", "run", "complete"}, "run"); + auto completeCount = complete.count(); + // Only create an account if there are none aleady created. + if (app.getMetrics() + .NewMeter({"loadgen", "account", "created"}, "account") + .count() == 0) + { + lg.generateLoad(GeneratedLoadConfig::createAccountsLoad(1, 1)); + simulation->crankUntil( + [&]() { return complete.count() == completeCount + 1; }, + 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); + } + + // Create upload wasm transaction + lg.generateLoad(GeneratedLoadConfig::createSorobanUpgradeSetupLoad()); + completeCount = complete.count(); + simulation->crankUntil( + [&]() { 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); + SorobanNetworkConfig cfg; + modifyFn(cfg); + createUpgradeLoadGenConfig.copySorobanNetworkConfigToUpgradeConfig(cfg); + auto upgradeSetKey = lg.getConfigUpgradeSetKey(createUpgradeLoadGenConfig); + lg.generateLoad(createUpgradeLoadGenConfig); + completeCount = complete.count(); + simulation->crankUntil( + [&]() { return complete.count() == completeCount + 1; }, + 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); + + // Arm for upgrade. + for (auto app : nodes) + { + Upgrades::UpgradeParameters scheduledUpgrades; + auto lclHeader = + app->getLedgerManager().getLastClosedLedgerHeader().header; + scheduledUpgrades.mUpgradeTime = + VirtualClock::from_time_t(lclHeader.scpValue.closeTime); + scheduledUpgrades.mConfigUpgradeSetKey = upgradeSetKey; + app->getHerder().setUpgrades(scheduledUpgrades); + } + // Wait for upgrade to be applied + simulation->crankUntil( + [&]() { + auto status = app.getStatusManager().getStatusMessage( + StatusCategory::REQUIRES_UPGRADES); + return status.empty(); + }, + 300 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false); + return upgradeSetKey; +} + void modifySorobanNetworkConfig(Application& app, std::function modifyFn) @@ -216,6 +283,37 @@ modifySorobanNetworkConfig(Application& app, } } +void +setSorobanNetworkConfigForTest(SorobanNetworkConfig& cfg) +{ + cfg.mMaxContractSizeBytes = 64 * 1024; + cfg.mMaxContractDataEntrySizeBytes = 64 * 1024; + + cfg.mTxMaxSizeBytes = 100 * 1024; + cfg.mLedgerMaxTransactionsSizeBytes = cfg.mTxMaxSizeBytes * 10; + + cfg.mTxMaxInstructions = 100'000'000; + cfg.mLedgerMaxInstructions = cfg.mTxMaxInstructions * 10; + cfg.mTxMemoryLimit = 100 * 1024 * 1024; + + cfg.mTxMaxReadLedgerEntries = 40; + cfg.mTxMaxReadBytes = 200 * 1024; + + cfg.mTxMaxWriteLedgerEntries = 20; + cfg.mTxMaxWriteBytes = 100 * 1024; + + cfg.mLedgerMaxReadLedgerEntries = cfg.mTxMaxReadLedgerEntries * 10; + cfg.mLedgerMaxReadBytes = cfg.mTxMaxReadBytes * 10; + cfg.mLedgerMaxWriteLedgerEntries = cfg.mTxMaxWriteLedgerEntries * 10; + cfg.mLedgerMaxWriteBytes = cfg.mTxMaxWriteBytes * 10; + + cfg.mStateArchivalSettings.minPersistentTTL = 20; + cfg.mStateArchivalSettings.maxEntryTTL = 6'312'000; + cfg.mLedgerMaxTxCount = 100; + + cfg.mTxMaxContractEventsSizeBytes = 10'000; +} + void overrideSorobanNetworkConfigForTest(Application& app) { diff --git a/src/test/TestUtils.h b/src/test/TestUtils.h index 22e09f3584..8b160975d3 100644 --- a/src/test/TestUtils.h +++ b/src/test/TestUtils.h @@ -16,6 +16,8 @@ namespace stellar { class LoopbackPeerConnection; +class Simulation; +using SimulationPtr = std::shared_ptr; namespace testutil { @@ -94,10 +96,17 @@ std::tm getTestDateTime(int day, int month, int year, int hour, int minute, VirtualClock::system_time_point genesis(int minute, int second); +// Assigns values to the SorobanNetworkConfig fields that are suitable for +// most of the unit tests. +void setSorobanNetworkConfigForTest(SorobanNetworkConfig& cfg); + // Override Soroban network config defaults with generous settings suitable // for most of the unit tests (unless the test is meant to exercise the // configuration limits). void overrideSorobanNetworkConfigForTest(Application& app); +ConfigUpgradeSetKey +upgradeSorobanNetworkConfig(std::function modifyFn, + SimulationPtr simulation); void modifySorobanNetworkConfig(Application& app, std::function modifyFn);