Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/simulation/ApplyLoad.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "simulation/ApplyLoad.h"

#include <algorithm>
#include <chrono>
#include <cmath>
#include <memory>
#include <numeric>
Expand Down Expand Up @@ -738,6 +739,18 @@ ApplyLoad::ApplyLoad(Application& app)
throw std::runtime_error(
"APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS cannot be zero");
}

// Seed the classic payment memo id from the current wall-clock time (in
// nanoseconds) so that classic payment tx hashes differ across runs. The id
// is then incremented per generated payment to stay unique within a run.
// Nanosecond resolution makes cross-run collisions practically impossible:
// two runs would have to start within (number of payments) ns of each other
// to overlap.
mNextClassicPaymentMemoId = static_cast<uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(
mApp.getClock().system_now().time_since_epoch())
.count());

setup();
}

Expand Down Expand Up @@ -1872,9 +1885,14 @@ ApplyLoad::generateClassicPayments(std::vector<TransactionFrameBasePtr>& txs,
auto it = accounts.find(accountIdx);
releaseAssert(it != accounts.end());
it->second->loadSequenceNumber();
// Attach a unique memo id so that the generated classic payment tx
// hashes are unique within a run and across runs (the id is seeded from
// wall-clock time in the constructor and incremented per payment).
Memo memo(MEMO_ID);
memo.id() = mNextClassicPaymentMemoId++;
auto [_, tx] = mTxGenerator.paymentTransaction(
mNumAccounts, 0, lm.getLastClosedLedgerNum() + 1, it->first, 1,
std::nullopt);
std::nullopt, memo);
auto res =
tx->checkValid(appConnector, ledgerView, 0, 0, 0, diagnostics);
releaseAssert(res && res->isSuccess());
Expand Down
6 changes: 6 additions & 0 deletions src/simulation/ApplyLoad.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ class ApplyLoad

// Counter for generating unique destination addresses for SAC payments
uint32_t mDestCounter = 0;

// Monotonic memo id assigned to generated classic payments to keep their
// tx hashes unique within a run and across runs. Seeded from the wall-clock
// time at construction (see constructor) so that separate runs start from
// different values.
uint64_t mNextClassicPaymentMemoId = 0;
};

#ifdef BUILD_TESTS
Expand Down
15 changes: 8 additions & 7 deletions src/simulation/TxGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ TxGenerator::createAccounts(uint64_t start, uint64_t count, uint32_t ledgerNum,
return ops;
}

TransactionFrameBasePtr
TransactionFrameBaseConstPtr
TxGenerator::createTransactionFramePtr(
TxGenerator::TestAccountPtr from, std::vector<Operation> ops,
std::optional<uint32_t> maxGeneratedFeeRate)
Expand All @@ -246,31 +246,32 @@ TxGenerator::createTransactionFramePtr(
return txf;
}

TransactionFrameBasePtr
TransactionFrameBaseConstPtr
TxGenerator::createTransactionFramePtr(
TxGenerator::TestAccountPtr from, std::vector<Operation> ops,
std::optional<uint32_t> maxGeneratedFeeRate,
std::optional<uint32_t> byteCount)
std::optional<uint32_t> byteCount, std::optional<Memo> memo)
{
if (byteCount.has_value())
{
return paddedTransactionFromOperations(
mApp, from->getSecretKey(), from->nextSequenceNumber(), ops,
generateFee(maxGeneratedFeeRate, ops.size()), *byteCount);
generateFee(maxGeneratedFeeRate, ops.size()), *byteCount, memo);
}
else
{
return transactionFromOperations(
mApp, from->getSecretKey(), from->nextSequenceNumber(), ops,
generateFee(maxGeneratedFeeRate, ops.size()));
generateFee(maxGeneratedFeeRate, ops.size()), memo);
}
}

std::pair<TxGenerator::TestAccountPtr, TransactionFrameBasePtr>
TxGenerator::paymentTransaction(uint32_t numAccounts, uint32_t offset,
uint32_t ledgerNum, uint64_t sourceAccount,
std::optional<uint32_t> byteCount,
std::optional<uint32_t> maxGeneratedFeeRate)
std::optional<uint32_t> maxGeneratedFeeRate,
std::optional<Memo> memo)
{
TxGenerator::TestAccountPtr to, from;
uint64_t amount = 1;
Expand All @@ -281,7 +282,7 @@ TxGenerator::paymentTransaction(uint32_t numAccounts, uint32_t offset,

return std::make_pair(from, createTransactionFramePtr(from, paymentOps,
maxGeneratedFeeRate,
byteCount));
byteCount, memo));
}

std::pair<TxGenerator::TestAccountPtr, TransactionFrameBaseConstPtr>
Expand Down
6 changes: 4 additions & 2 deletions src/simulation/TxGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,15 @@ class TxGenerator
TransactionFrameBaseConstPtr
createTransactionFramePtr(TestAccountPtr from, std::vector<Operation> ops,
std::optional<uint32_t> maxGeneratedFeeRate,
std::optional<uint32_t> byteCount);
std::optional<uint32_t> byteCount,
std::optional<Memo> memo = std::nullopt);
Comment thread
dmkozh marked this conversation as resolved.

std::pair<TestAccountPtr, TransactionFrameBaseConstPtr>
paymentTransaction(uint32_t numAccounts, uint32_t offset,
uint32_t ledgerNum, uint64_t sourceAccount,
std::optional<uint32_t> byteCount,
std::optional<uint32_t> maxGeneratedFeeRate);
std::optional<uint32_t> maxGeneratedFeeRate,
std::optional<Memo> memo = std::nullopt);

std::pair<TestAccountPtr, TransactionFrameBaseConstPtr>
createUploadWasmTransaction(
Expand Down
12 changes: 9 additions & 3 deletions src/test/TxTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,11 +775,17 @@ TransactionTestFramePtr
paddedTransactionFromOperationsV1(Application& app, SecretKey const& from,
SequenceNumber seq,
std::vector<Operation> const& ops,
uint32_t fee, uint32_t desiredSize)
uint32_t fee, uint32_t desiredSize,
std::optional<Memo> memo)
{
TransactionEnvelope e =
makeEnvelopeV1(app, from, seq, ops, fee, std::nullopt);

if (memo)
{
e.v1().tx.memo = *memo;
}

uint32_t baseSize = xdr::xdr_argpack_size(e);

StellarMessage baseMessage;
Expand Down Expand Up @@ -855,7 +861,7 @@ TransactionTestFramePtr
paddedTransactionFromOperations(Application& app, SecretKey const& from,
SequenceNumber seq,
std::vector<Operation> const& ops, uint32_t fee,
uint32_t desiredSize)
uint32_t desiredSize, std::optional<Memo> memo)
{
auto ledgerVersion =
app.getLedgerManager().getLastClosedLedgerHeader().header.ledgerVersion;
Expand All @@ -865,7 +871,7 @@ paddedTransactionFromOperations(Application& app, SecretKey const& from,
"paddedTransactionFromOperations() called from pre-V23 protocol");
}
return paddedTransactionFromOperationsV1(app, from, seq, ops, fee,
desiredSize);
desiredSize, memo);
}

TransactionTestFramePtr
Expand Down
12 changes: 6 additions & 6 deletions src/test/TxTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ transactionFromOperationsV0(Application& app, SecretKey const& from,
// the cost to enable the sorobanData extension (~36 bytes).
TransactionTestFramePtr paddedTransactionFromOperationsV1(
Application& app, SecretKey const& from, SequenceNumber seq,
std::vector<Operation> const& ops, uint32_t fee, uint32_t desiredSize);
std::vector<Operation> const& ops, uint32_t fee, uint32_t desiredSize,
std::optional<Memo> memo = std::nullopt);

TransactionTestFramePtr
transactionFromOperationsV1(Application& app, SecretKey const& from,
Expand All @@ -157,11 +158,10 @@ transactionFromOperationsV1(Application& app, SecretKey const& from,
// If `app` protocol version is >=23, attempts to pad to around `desiredSize`
// (see comment on `paddedTransactionFromOperationsV1`). Otherwise, throw an
// error.
TransactionTestFramePtr
paddedTransactionFromOperations(Application& app, SecretKey const& from,
SequenceNumber seq,
std::vector<Operation> const& ops,
uint32_t fee = 0, uint32_t desiredSize = 0);
TransactionTestFramePtr paddedTransactionFromOperations(
Application& app, SecretKey const& from, SequenceNumber seq,
std::vector<Operation> const& ops, uint32_t fee = 0,
uint32_t desiredSize = 0, std::optional<Memo> memo = std::nullopt);

TransactionTestFramePtr
transactionFromOperations(Application& app, SecretKey const& from,
Expand Down
Loading