Skip to content

Commit

Permalink
Ensure unique preimages during loadgen upgrade setup (#4425)
Browse files Browse the repository at this point in the history
Currently, loadgen can produce duplicate preimages during
`SOROBAN_UPGRADE_SETUP` if metrics have been cleared between
`SOROBAN_UPGRADE_SETUP` calls. This scenario causes the setup to fail.
This change fixes this by using an internal counter as part of the
preimage instead of using medida metrics.

# Checklist
- [x] Reviewed the
[contributing](https://github.com/stellar/stellar-core/blob/master/CONTRIBUTING.md#submitting-changes)
document
- [x] Rebased on top of master (no merge commits)
- [x] Ran `clang-format` v8.0.0 (via `make format` or the Visual Studio
extension)
- [x] Compiles
- [x] Ran all tests
- [ ] If change impacts performance, include supporting evidence per the
[performance
document](https://github.com/stellar/stellar-core/blob/master/performance-eval/performance-eval.md)
  • Loading branch information
marta-lokhova committed Aug 8, 2024
2 parents 3c7fb22 + 70f2a87 commit f25405b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
7 changes: 2 additions & 5 deletions src/simulation/LoadGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1260,11 +1260,8 @@ LoadGenerator::createContractTransaction(uint32_t ledgerNum, uint64_t accountId,
createResources.readBytes = mContactOverheadBytes;
createResources.writeBytes = 300;

auto salt = sha256(
std::to_string(mContractInstanceKeys.size()) + "run" +
std::to_string(mApp.getMetrics()
.NewMeter({"loadgen", "run", "complete"}, "run")
.count()));
auto salt = sha256("upgrade" +
std::to_string(++mNumCreateContractTransactionCalls));
auto contractIDPreimage = makeContractIDPreimage(*account, salt);

auto tx = makeSorobanCreateContractTx(
Expand Down
4 changes: 4 additions & 0 deletions src/simulation/LoadGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ class LoadGenerator
int64_t mPreLoadgenApplySorobanSuccess = 0;
int64_t mPreLoadgenApplySorobanFailure = 0;

// Number of times `createContractTransaction` has been called. Used to
// ensure unique preimages for all `SOROBAN_UPGRADE_SETUP` runs.
uint32_t mNumCreateContractTransactionCalls = 0;

bool mFailed{false};
bool mStarted{false};
bool mInitialAccountsCreated{false};
Expand Down
45 changes: 45 additions & 0 deletions src/simulation/test/LoadGeneratorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,3 +716,48 @@ TEST_CASE("Multi-op mixed transactions are valid", "[loadgen]")
REQUIRE(dexOps > 0);
REQUIRE(dexOps + nonDexOps == 3 * 100);
}

TEST_CASE("Upgrade setup with metrics reset", "[loadgen]")
{
// Create a simulation with two nodes
Simulation::pointer sim = Topologies::pair(
Simulation::OVER_LOOPBACK, sha256(getTestConfig().NETWORK_PASSPHRASE));
sim->startAllNodes();
sim->crankUntil([&]() { return sim->haveAllExternalized(3, 1); },
2 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false);

Application::pointer app = sim->getNodes().front();
LoadGenerator& loadgen = app->getLoadGenerator();
medida::Meter& runsComplete =
app->getMetrics().NewMeter({"loadgen", "run", "complete"}, "run");
medida::Meter& runsFailed =
app->getMetrics().NewMeter({"loadgen", "run", "failed"}, "run");

// Add an account
loadgen.generateLoad(GeneratedLoadConfig::createAccountsLoad(
/* nAccounts */ 1, /* txRate */ 1));
sim->crankUntil([&]() { return runsComplete.count() == 1; },
5 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false);

// Clear metrics to reset run count
app->clearMetrics("");

// Setup a soroban limit upgrade that must succeed
GeneratedLoadConfig upgradeSetupCfg =
GeneratedLoadConfig::createSorobanUpgradeSetupLoad();
upgradeSetupCfg.setMinSorobanPercentSuccess(100);
loadgen.generateLoad(upgradeSetupCfg);
sim->crankUntil([&]() { return runsComplete.count() == 1; },
5 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false);
REQUIRE(runsFailed.count() == 0);

// Clear metrics again to reset run count
app->clearMetrics("");

// Setup again. This should succeed even though it's the same account with
// the same `runsComplete` value performing the setup
loadgen.generateLoad(upgradeSetupCfg);
sim->crankUntil([&]() { return runsComplete.count() == 1; },
5 * Herder::EXP_LEDGER_TIMESPAN_SECONDS, false);
REQUIRE(runsFailed.count() == 0);
}

0 comments on commit f25405b

Please sign in to comment.